11. Každý adresář ve vrstvě nese smlouvu
Kontext
Vrstva už řeší kontext podle rozsahu: README.md pod .ai/, který nese schema: context/v1, je kontrakt adresáře, efektivní kontext pro cestu je řetězec kontraktů od kořene dolů a majordomus context validate odmítne strom, jehož kontrakty jsou poškozené, duplicitní, cyklické nebo nepřípustně nahrazené. Nikdy se neptala, zda adresář kontrakt vůbec má. README.md přítomný bez kontraktu je chyba; adresář bez README.md je mlčení a mlčení je to, do čeho strom sklouzává. Když bylo toto rozhodnutí přijato, devět adresářů pod .ai/ neslo kontrakt a osmnáct ne, včetně částí, kam je pracovník posílán denně (rules/project, project/issues, knowledge/curated, benchmarks/).
Mezera není kosmetická. Pravidlo tohoto repozitáře říká, že kontext žije v nejužším rozsahu, kde zůstává správný (project.context-locality), a resolver je postaven přesně na jeho skládání. Adresář bez kontraktu se nemůže účastnit: do řetězu nic nepřispívá, nepojmenovává žádný formát souborů, které drží, a worker, který tam přistane, přečte své předky a zbytek hádá. Povinnost adresář zdokumentovat byla zvyk a zvyk není invariant.
Stejná otázka dorazila zvenčí jako návrh obecného governance enginu: závažnosti pravidel (enforced/advisory/optional), pořadí vyhodnocování (before, after, priority), slovníky spouštěčů a použitelnosti, deklarace druhů artefaktů, které může adresář obsahovat, na adresář a algebra slučování na úrovni polí nad zděděným front matter. I na tento návrh se odpovídá zde, protože většina z něj už existuje pod jinými jmény a zbytek nepřináší nic, co by tento repozitář mohl spotřebovat.
Rozhodnutí
Pokrytí se stává třídou validace. Každý adresář spravovaného stromu nese kontextový dokument a majordomus context validate hlásí missing-contract u každého, který ho nemá, s uvedením adresáře a kontraktu, který ho tomuto závazku podřídil. Spravovaný strom je ten, který resolver už čte: adresář manifestu, bez local/, bez vendorovaného balíčku pravidel, jehož integrita je věcí manifestu, ne čtenáře.
Které adresáře jsou vyňaty, deklarují samy kontrakty, ne seznam v kořeni. Kontrakt může nést children.require_contract a hodnota, která platí pro adresář, je hodnota od nejbližšího nadřazeného kontraktu, který ji deklaruje; kde ji nedeklaruje nic, výchozí je true. Pole se skládá jen zužováním: potomek může zvýšit false na true pro svůj podstrom a nesmí snížit výslovně deklarované true na false. Toto odmítnutí je vlastní třída validace, illegal-override, kterou strom už používá pro potomka, který nahrazuje dokument final. Jedno pole, jedna zdokumentovaná algebra, jeden konzument — místo generického hlubokého merge, jehož výsledek nikdo nedokáže předvídat.
Zamítnuto, s důvody.
Závažnost jako třetí osa. Pravidlo zde deklaruje class: blocking nebo class: advisory a zda o něm nástroj může rozhodnout, je už vidět podle přítomnosti bloku x-majordomus: pravidlo s validátorem vynucuje příkaz, pravidlo bez něj vynucuje reviewer. optional nemá konzumenta — nic v tomto nástroji neaktivuje pravidlo na úlohu nebo profil — a pole, které nic nečte, je překlep, který tiše nedělá nic (project.unknown-keys-are-errors).
Řazení jako before, after a priority. Pravidla se zde řeší jako graf závislostí a aplikují jako množina; nic je nevyhodnocuje po sobě, takže pořadí vyhodnocení je číslo bez významu, který by šlo hájit. depends_on už dává deterministické pořadí pro vykreslení a rovnost se rozhoduje identitou, ne ručně laděným celým číslem.
Slovníky triggers a applies_to. Použitelnost je zde otázka cest a cesty jsou to, co nástroj dokáže zkontrolovat. Pravidlo, které tvrdí, že se vztahuje na „plánování“ a „refaktorování“, nemůže být vyvráceno ničím, co nástroj pozoruje, a nevyvratitelná deklarace je dekorace (project.no-claim-without-test).
content.kinds pro každý adresář. Manifest už mapuje sekci na její adresář a druh, který v něm žije; opakovat mapování v každém kontraktu je druhý registr, který se může s prvním rozcházet (project.derived-once).
Zamítnuté alternativy
Seznam spravovaných adresářů v manifestu nebo politice. Centrální a špatné ze stejného důvodu, z jakého je špatný kořenový soubor pro kontext: umisťuje fakt o adresáři tam, kam se čtenář adresáře nikdy nedívá, a zastará při prvním přejmenování. Smlouva, která podstrom řídí, je poctivým místem pro výjimku a pohybuje se se stromem.
Vyžadovat kontrakt pro každý adresář bez jediné výjimky. Zní to dobře, dokud instance druhu nejsou adresáře místo souborů: dovednost je SKILL.md plus její příklady a kontrakt v skills/<name>/examples/ by dokumentoval formát druhu jednou na instanci, což je duplicita, které kontrakt sekce brání. Výjimka není kličkou; jmenuje, kde instance druhu začínají.
Zjišťování výjimek heuristikou — adresář, který neobsahuje žádný Markdown, adresář, jehož název odpovídá vzoru. Tiché, nevysvětlitelné a na každém stromě jiné. Nástroj jinde odmítá hádat a tady s tím nezačne.
Důsledky
Adresář přidaný pod .ai/ nyní selže ve validaci, dokud neřekne, k čemu slouží, což je závazek, který toto rozhodnutí vytváří; context validate běží v pre-commit hooku přes doctor, takže selhání přijde dřív než větev. Osmnáct adresářů dostává v rámci této změny smlouvy a každý je místem, kde pracovník přistane s menším hádáním.
Schéma kontraktu získá jeden klíč, children.require_contract, s pravidlem skládání, které jen zužuje. To je první algebra na úrovni pole ve vrstvě; každý jiný klíč je skalární a lokální. Cenou je její zdokumentování (docs/CONTEXT.md, docs/SCHEMAS.md) a prokázání mutací v případu chování, obojí tato změna nese.
Co zůstává mimo nástroj, zůstává mimo: zda je próza kontraktu dobrá, je úsudek recenzenta, a nástroj kontroluje jen to, že kontrakt existuje, parsuje se a potomek ho neoslabuje. Vrstvené tvrzení je to poctivé — přítomnost kontraktu je mechanická, jeho užitečnost není.