Zdůvodnění
2026-10-10 se vlastník zeptal jedné relace stejné otázky sedmkrát: je vše z této relace hotovo, lze ji ukončit, je vše mergnuto, nebyl přidán žádný dluh, je méně pull requestů než na začátku, co větve a worktrees, je vše integrováno a nasazeno.
Sedmkrát relace odpověděla z toho, co si pamatovala, že udělala. Každá odpověď byla pravdivá o stopě relace samotné — neotevřela žádný pull request, její jediná větev a jediný worktree byly pryč — a každá neříkala nic pravdivého o repozitáři, na který se ptalo. Osmá odpověď byla změřena: 52 otevřených pull requestů oproti 49 na začátku relace, 42 z nich v konfliktu s trunkem; 117 worktree tam, kde předchozí relace zanechala 96; 225 lokálních větví, 59 z nich už zasažených trunkem a 13 s commity, které žádný remote neměl; deset stashů, které nikdo neauditoval; release bez tagu. Nic z toho nebylo v žádné ze sedmi odpovědí a nemohlo být: paměť workera drží, co worker udělal, ne co v téže hodině udělaly tři jiné relace.
Repozitář už věděl, že tvrzení o dokončení musí být odečet, ne věta. Invariant hotovosti kladl úloze devatenáct otázek a každou odpověď bral z podsystému, který fakt držel, a project.never-reported-is-not-green už říkal, že verdikt, který nedorazil, není úspěch. Co invariant nekladl, byla ta část závěrečné otázky, která se týká repozitáře v čase: zda zaznamenaný dluh narostl, zda to, co vzniklo, stále leží, zda se backlog prodloužil. To se nechávalo zodpovědět v próze a próza je místo, kde se na to odpovídalo špatně.
Existuje druhý důvod, proč je pracovník špatným zdrojem, a netýká se poctivosti. Pracovník, kterého se zeptáte „je to hotové?“, je jediná strana, která má důvod zaokrouhlovat nahoru, a to ve chvíli, kdy nejvíc chce, aby konverzace skončila. Měření takovou chvíli nemá.
Požadované chování
Závěrečná otázka se zodpovídá spuštěním měření. majordomus check jmenuje každou otázku invariantu hotovo, která není zodpovězena, jako id=status; gates.completion nese každou otázku s jejím stavem, důkazy, které přečetl, a zdrojem, který odpověděl. Ten dokument je odpověď. Pracovník jej ohlásí — otázky, které prošly, ty dlužné, odmítnuté i neznámé — a připojí, co ví navíc, nikdy ne místo něj.
Tři otázky nesou část, která se týká repozitáře, každá čtená ze záznamu, který drží fakt, a měřená od místa, kde úloha začala:
no-new-debt— položky každé baseline dluhu (.ai/repo/*-baseline.txt) v commitu, na kterém úloha začala, proti pracovnímu stromu. Přidaná položka je dluh, který změna vytvořila a pak si ho sama povolila; odmítne se, ať je commitnutá, či ne. Baseline, která se objeví poprvé, zaznamenává dluh, který tu už byl; je pojmenována a není růstem.nothing-accumulated— lokální větve a propojené worktrees, které podle reflogů gitu vznikly od startu úlohy a stále existují. Dokud nějaká zůstává, je otázka dlužna a větev samotné úlohy je mezi nimi, dokud práce nepřistane a není uklizena.backlog-not-grown— pull requesty, o kterých zaznamenané pozorování forge říká, že byly otevřeny od začátku úlohy a stále jsou otevřené.
Odečty patří repozitáři, ne pracovníkovi. Git nezaznamenává, kdo vytvořil větev, takže větev, kterou od začátku úlohy vytvořila jiná relace, se počítá. To je otázka, kterou si člověk klade na konci — vyrostlo to, zatímco jsme pracovali — a „není moje“ je poznámka, kterou pracovník může po sečtení doplnit spolu s důkazem.
Čtení, které se neprovedlo, je unknown. Žádný záznam úlohy znamená, že není od čeho měřit; forge nepozorovaný od zahájení úlohy nemůže říct, co ty hodiny přinesly; commit, který v repozitáři není, nelze porovnat. Každé z toho říká, které to je. Žádné z toho není průchod a pracovník z něj nevyrobí ano tím, že jej vysvětlí.
Součet, který nebyl zaznamenán, se nerekonstruuje. To, co bylo od začátku odebráno, nezanechává záznam, takže údaje jmenují to, co bylo přidáno a zůstává, a uvádějí součty nyní. Netvrdí rozdíl dvou součtů, a worker také ne.
Čtení je tak jemné jako jeho záznam a neříká víc. Dluh se počítá v položkách: jedna odebraná a jiná přidaná položka se nevidí, jen růst. Větev nebo worktree se datuje prvním řádkem, který reflog ještě drží: kde git starší záznamy expiroval, vypadá mladší, než je, a může být označena za vytvořenou po zahájení úlohy, přestože nebyla. Obě meze se naklánějí k otázce položené znovu, nikdy k propuštění.
Chování při selhání
gates.completion odpovídá; majordomus check hlásí každou otázku, která není ani pass, ani exempt, na jednom řádku done s jejím stavem. Nic se nemaže, žádná větev se neodstraňuje a žádný baseline se nepřepisuje za někoho: nález je otázka a její důkazy a náprava je příkaz, který otázka nese.
Worker, který odpoví na závěrečnou otázku bez čtení, na ni neodpověděl. Nápravou je čtení, ne lépe formulovaná věta.
Ověření
apps/majordomus-cli/src/gates/closing.rs— tři čtení, každé samostatnéResult, s unit testy nad skutečným repozitářem: záznam započítaný na začátku a nyní, první řádek reflogu, pozorování starší než úloha odmítnuté místo čtení jako prázdné.apps/majordomus-cli/src/gates/done.rs— otázky a jediné místo, kde se čtení stává odpovědí; jeho testy drží, že nepřečtené čtení jeunknown, že růst v jedné baseline se neplatí úbytkem v jiné a že bez čehokoli za sebou neprojde žádná otázka.test/cases/1037_the_closing_question_is_measured.sh— behaviorální případ v jednorázovém repozitáři: záznam přidaný k základní hodnotě je odmítnut, necommitnutý i commitnutý, a jeho odebrání odpoví; branch a worktree vytvořené od zahájení úlohy jsou dlužné a pojmenované, dokud nezmizí obojí; checkout, který forge nikdy nepozoroval, jeunknown; amajordomus checkjmenuje každý podle jeho id a stavu.test/cases/131_completion_gates.sh— invariant jako celek: každá otázka nese zdroj a své důkazy.