Co to znamená
Úkoly a milníky na GitHubu jsou projekcí plánu na trunku. Pull request, který upraví záznam plánu, uzavře ho nebo přesune k jinému milníku, mění to, co by GitHub měl říkat, a GitHub to nemůže říct dřív, než se pull request sloučí. Kontrola, která obojí porovnává, to pull requestu nepočítá k tíži. Záznamy, které pull request změnil, hlásí jako PENDING a odmítá jen drift, který pull request nezpůsobil.
Po merge jsou tytéž záznamy PENDING na hlavní větvi po deklarované okno, což je čas, který má přistání na aplikaci projekce. Po uplynutí okna se hlavní větev odmítne a odmítnutí jmenuje příkaz, který spustit.
Princip
scripts/ci/github-check spustí scripts/github-sync --check a čte jeho řádky driftu. Čtyři stavy jsou to, co apply zapisuje: behind, state, milestone a closed, které adaptér hlásí vedle state, když je uzavřenou stranou GitHub. Pro těchto čtyři se kontrola ptá, které záznamy se od referenčního commitu změnily.
| run | referenční commit | slova na řádku PENDING |
|---|---|---|
pull request nebo strom zadaný pomocí MJ_GH_BASE=<ref> | společný základ se základní větví | promítnuto po merge |
| strom, který výchozí větev neobsahuje | merge base s výchozí větví remote | promítnuto po merge |
| výchozí branch | nejmladší first-parent commit starší než okno | přistání se aplikuje |
Záznam se změnil, když se jeho soubor liší od reference nebo když se liší jeho vykreslení. Druhá polovina je důležitá, protože stav je odvozený: uzavření jednoho úkolu pohne tělem každého úkolu, který na něj čekal, a může uzavřít jeho milník, aniž by se dotklo jejich souborů. Kontrola vykreslí plán v referenci a v headu pomocí scripts/github-sync --plan a porovná hash těla a řádek stavu každého záznamu. Reference se vykresluje vlastním adaptérem, pokud ho nese, takže změna rendereru se počítá i jako změna headu.
Okno je apply.window v .ai/repo/ci/github.yaml, v sekundách. Kontrola ho čte ze stromu, který se testuje, a nenese kopii. Stáří přistání je datum committera jeho first-parent commitu na trunku, takže commit napsaný minulý týden a mergovaný před minutou přistál před minutou.
Řádky PENDING se počítají odděleně od nálezů. Poslední řádek zní github-check: 0 finding(s), 2 pending a stavový kód se řídí pouze nálezy.
Jak to vidět
scripts/ci/github-check # this tree, judged as CI would judge it
MJ_GH_BASE=origin/master scripts/ci/github-check # as a head that merges into origin/master
scripts/github-sync --plan # offline: the rendering the gate compares
bash test/run.sh 1038_a_head_is_judged_against_what_it_changesCo nepokrývá
Kontrola nic neaplikuje. Po přistání se projekce aplikuje pomocí .github/workflows/github.yml, které startuje každý push do masteru (Pull-request integration, project.the-projection-is-applied-at-landing), a kontrola jen omezuje, jak pozdě to smí být. Když ten běh selže, záložním řešením je scripts/github-sync --apply člověka z masteru.
Pending mohou být jen čtyři stavy, které zapisuje apply. Ručně upravená oblast (edited, conflict) a vzdálený úkol hlásící neznámý záznam (unmanaged) se odmítají při každém běhu, ať záznam změnil kdokoli.
Pull request se neomlouvá za drift, který po sobě zanechal trunk. Je-li přistání stále uvnitř svého okna a neaplikované, jiný pull request, který ty záznamy nezměnil, je kvůli nim odmítnut, dokud je někdo neaplikuje.
Nový záznam je missing, ne behind, a missing je ratchetován proti .ai/repo/ci/github-drift-baseline.txt a nikdy není pending (sousední tvrzení).
Co nelze změřit, se nepředpokládá. Bez báze, která se vyřeší, bez merge base, při mělkém klonu nebo bez deklarovaného okna kontrola vypíše řádek NOTE s uvedením, která z těchto situací nastala, a odmítne vše, co odmítala před vznikem tohoto tvrzení.
Proč existuje
Dne 2026-10-10 změnil pull request #855 jeden řádek úkolu I1900 a selhal s DRIFT behind issue I1900 (#753) body is behind the canonical record. Pull request #820 uzavřel osm záznamů a selhal s 8 record(s) state. Ani jeden nemohl zezelenat na vlastní hlavě: jediný způsob, jak změnu aplikovat, bylo ji sloučit, a kontrola odmítla sloučení proto, že změna nebyla aplikována. Východiskem bylo záznam needitovat, což znamenalo, že plán nešlo opravit pull requestem. Kdyby některá ze změn přesto přistála, vlastní běh kmene by byl červený, dokud ji někdo neaplikuje ručně, a release tag na tento běh čeká.
Důkazy
test/cases/1038_a_head_is_judged_against_what_it_changes.sh provozuje kontrolu nad fixture repozitářem se základem, hlavou a dvěma přistáními, proti skriptovanému gh, který obsluhuje remote a selže při každém volání, které není čtením. Prokazuje, že záznam změněný hlavou je pending a běh končí 0, že záznam, který nezměnila, je vedle něj odmítnut, že záznam, jehož vykreslení se pohnulo s nedotčeným souborem, je pending, že přistání uvnitř okna je na trunku pending a totéž přistání staré dvě hodiny je odmítnuto s pojmenovanou nápravou, že okno je to deklarované a že základ nebo okno, které nelze přečíst, odmítne. Případ jmenuje mutaci, která rozbije každé tvrzení.
Pravidlo je project.github-projection-gated@1.