Zdůvodnění
Plán odvozuje stav úkolu z jeho záznamu: started_at, verified_at, completed_at a položek důkazů. plan.transition a majordomus plan start|verify|done jsou střežená hranice — READY před startem, started před done, žádná otevřená závislost, úplné důkazy — a každý připojí do ledgeru událost plan_start, plan_verify nebo plan_done. Do tohoto pravidla nic nevázalo razítko na událost. Worker, který do YAML napsal completed_at a položku důkazů, dostal úkol DONE bez přechodu, bez ochrany a bez události, plan validate skončil s 0 a každý povrch — množina připravených, plán rozvoje, projekce GitHub, web — ho hlásil jako dokončený.
Kniha záznamů nemůže být důkazem, který kontrola čte: .ai/local/state/ledger.jsonl je lokální pro checkout a nikdy se nesleduje, takže klon, druhý worktree i CI začínají bez ní. Důkaz musí cestovat se záznamem. ADR 0097 tuto volbu zaznamenává: přechod zapíše pečeť — sha256 události, úkolu a razítka — do záznamu v tomtéž zápisu jako razítko a oba enginy odmítnou razítko, jehož pečeť chybí nebo nesouhlasí.
Požadované chování
- Razítko zapisuje jen přechod, který zapíše razítko, jeho pečeť (
started_event,verified_event,completed_event) aupdated_ata pak připojí událost. Shellový engine a engine v Rustu zapisují stejné bajty. - Razítko bez odpovídající pečeti nemá žádný vliv na odvozený stav a hlásí se jako
stamp_without_event, FAIL pojmenovávající úkol, razítko a chybějící událost.majordomus plan validatena něj skončí kódem 10 ascripts/ci/core-check, který běží v každém plánu CI, spouštíplan validate. donese odmítne, pokud úkol není ACTIVE nebo VERIFY: úkol READY, BLOCKED, CANCELLED nebo DONE nelze přechodem dokončit také.unsealed_stampsv záznamu úkolu jmenuje razítka tohoto záznamu zapsaná dříve, než pečetě existovaly (<field> <stamp>). Smí se zmenšovat a nikdy se do něj nepřidává. Položka omlouvá jen přesné razítko, které jmenuje, a jen takové, které je starší nežSEALED_FROM; razítko zapsané v tomto okamžiku nebo po něm potřebuje svou pečeť, ať seznam říká cokoli.
Chování při selhání
plan validate vypíše jedno FAIL pro každé nedoložené razítko a skončí s 10; odvozený stav razítko ignoruje, takže padělané DONE se čte jako cokoli říkají jeho doložená razítka. Nápravou je přechod: majordomus plan start <id> na úkolu, který padělané started_at nechalo READY, přepíše razítko s jeho pečetí. Padělané completed_at se odstraní, ručně se nepečetí.
Omezení
Pečeť je otisk veřejných hodnot, ne podpis. Mění „razítko, které nikdo nepřevedl“ z neviditelného na pojmenované selhání a falšování se stává záměrným aktem — výpočtem otisku — který je v diffu vidět jako řádek pečeti, který nezapsal žádný přechod. Nedokazuje, a bez klíče nemůže, že ji spočítal nástroj.
Ověření
bash test/run.sh 581_no_plan_stamp_without_its_event
bash test/run.sh 582_the_done_guard_holds_in_both_engines
majordomus plan validate