Zdůvodnění
Spuštění Majordomus špiní strom. majordomus update přepíše CLAUDE.md a AGENTS.md, majordomus generate přepíše share/allow/ a share/schemas/, scripts/derive přepíše docs/generated/ a site/data/generated/ a každý příkaz připojí řádek do účetní knihy. Každý záznam, který tento nástroj zapsal, vzal svůj changed_files rovnou z git status --porcelain, takže každý tvrdil, že to vše je práce epizody.
Změřeno v repozitáři Majordomus, kde bylo toto pravidlo napsáno. Záznam v .ai/repo/sessions/20260910T103933Z--s-20260909152316-024f--master--38f056b--… nese 122 změněných souborů. Patří mezi ně celé site/data/generated/, jedenáct stránek pod site/content/sessions/, dvanáct souborů pod docs/generated/ — a tři sourozenecké záznamy téže epizody plus site/content/sessions/s-20260909152316-024f.md, což je projekce webu právě této epizody. Záznam jmenuje sám sebe jako svůj vlastní pracovní produkt.
Není to kosmetika. Záznam je zpráva, kterou má pozdější čtenář o tom, co úsek práce obsahoval, a web ji publikuje. Seznam, v němž signálem jsou tři skutečné soubory a šumem sto devatenáct, je seznam, který nikdo nečte, takže záznam je archiv, a ne paměť — přesně to, čemu má majordomus.session-records zabránit.
Požadované chování
lib/changed.sh klasifikuje pracovní strom a používá ho každý zapisovač záznamů. Nenese žádný vlastní seznam odvozených cest. Pět věcí už říká, co je odvozené, každá udržovaná, protože ji potřebuje něco jiného, a klasifikátor čte všech pět:
.ai/repo/scope.yaml,out.generated.pathsaout.generated.names— vlastní deklarace nástroje, dodávaná v kostře, takže to funguje v každém repozitáři, který Majordomus dohlíží, a ne jen ve vlastním;.ai/repo/scope.yaml,out.paths— množina, která se nikdy nečte a kde je deklarován.ai/local/. Pracovní produkt, který nesmí nikdo číst, není pracovním produktem;.ai/repo/policy.yaml,projections[].target— CLAUDE.md, AGENTS.md,.bb/AGENTS.md;.gitattributes, každá cesta označenámerge=derived— vlastní seznam repozitáře toho, co jeho generátor zapisuje, udržovaný, protože ho potřebuje merge driver (v repozitáři Majordomus pokrytý jehotest/cases/57_derived_merge_driver.sh);- samotná úložiště záznamů, podle resolverů, které je jmenují. Ta se neodvozují — uzavřený záznam relace je sledovaný objekt, který spustitelný soubor indexuje — ale zapisuje je nástroj, ne worker.
Repozitář, který nedeklaruje žádnou z nich, nic neztrácí: klasifikátor pak nevylučuje nic a seznam je takový, jaký byl dřív. Změní výsledek přidání cesty do kterékoli z těchto deklarací, což je smysl věci — šestý seznam uvnitř klasifikátoru by bylo šesté místo, na které se zapomene.
Chování při selhání
Poradní, a záměrně. Každý záznam zapsaný před lib/changed.sh nese neklasifikovaný seznam a záznam je podle kontraktu neměnný: přepsat třináct commitnutých záznamů relací, aby kontrola zezelenala, by znamenalo vymýšlet historii, což je přesně to, co práce, se kterou toto pravidlo přišlo, odmítá. doctor hlásí, kolik záznamů nese odvozené cesty, který jich nese nejvíc a který je nejnovější — právě to poslední číslo čtenáři říká, zda klasifikátor funguje, protože záznam zapsaný po jeho nasazení, který přesto jmenuje odvozené cesty, je regrese, nikoli dědictví.
Blokující polovinou je behaviorální případ. test/cases/136_changed_files_classifier.sh shodí build, pokud checkpoint, předávka nebo uzavřená relace zapsaná dnes pojmenovává cestu, kterou některá z deklarací pokrývá.
Ověření
mj_validate_record_changed_files v lib/changed.sh, dispatchováno z doctor, posuzuje záznamy, které existují. test/cases/136_changed_files_classifier.sh posuzuje zapisovatele: nastaví postupně každou deklaraci, zapíše jeden záznam každého druhu a ověří obě poloviny — že práce je pojmenována a že výfuk není. Jeho poslední sekce odstraní deklaraci a dokáže, že cesta se vrátí, což ukazuje, že vyloučení pocházelo z deklarace, a ne z konstanty v klasifikátoru.