18. Provozní okamžiky jsou objekty vrstvy, ne stránky webu
Kontext
Sekce /why/ uváděla deset provozních režimů selhání, na které nástroj odpovídá. Každý byl ručně psanou stránkou pod site/content-src/why/ s TOML front matterem pojmenovávajícím příkazy, odpovědnosti a tvrzení, na kterých stál, a blokem awk, sed a jq uvnitř generátoru webu, který tento front matter parsoval do site/data/generated/why.json pro šablony.
Bylo to lepší než próza — odkazy se kontrolovaly a stránka jmenující neexistující tvrzení shodila build. Stále to byl špatný tvar, ze čtyř důvodů.
Parser byl druhým čtením formátu dokumentu, který repozitář už umí číst. Spustitelný soubor indexuje a validuje všechny ostatní deklarativní objekty vrstvy proti JSON Schema; těchto deset parsovala funkce shellu, která rozuměla podmnožině TOML a o schématech nevěděla nic.
Katalog byl mimo web neviditelný. majordomus neuměl vypsat moment, HTTP API žádný neservírovalo, MCP žádný nevystavovalo a žádný graf nevěděl, že existují — ačkoli momenty jsou nejpřímějším výrokem repozitáře o tom, k čemu nástroj slouží.
Taxonomie byla implicitní. Neexistovala publika ani provozní oblasti, takže čtenář se nemohl zeptat „jak to vypadá pro mě“ ani „kolik z mého problému je koordinace“ a sekce na ni nemohla odpovědět, aniž by někdo napsal druhý seznam.
A ten tvar se neškáloval. Jedenáctá položka by stála stránku, položku v parseru generátoru, změnu šablony a zpětný odkaz někde jinde — takže desátá byla místem, kde se to zastavilo.
Rozhodnutí
Provozní okamžik je deklarativní objekt vrstvy, objevený a validovaný mechanismem, který používá každý jiný druh, a každá jeho projekce je odvozena.
Tři druhy, deklarované jako data. moment, audience a area se připojují k share/kinds.yaml se svými JSON Schemas vedle ostatních a tři třídy zdrojů v sources.yaml repozitáře je objevují pod .ai/repo/why/. Nebyl k tomu potřeba žádný Rust: objevování, parsování front matter, validace schématu, identita, index a zdroj MCP majordomus://moment/<id> vše plyne z těchto deklarací.
Jeden doménový model. apps/majordomus-cli/src/why.rs promítá validovaná metadata do typovaných záznamů, rozřeší každý odkaz, odvodí každý vztah, který nikdo nenapsal, a odpovídá na dotazy. Sestaví se jednou při skládání kontextu schopností a je sdílen; nic jej nepřestavuje při každém požadavku.
Šest schopností, promítnutých všude. why.list, why.moment, why.audiences, why.areas, why.diagnose a why.validate jsou deklarovány jednou pomocí capability!, takže příkazová řádka, trasy HTTP, operace OpenAPI s jejich schématy a příklady a nástroje a zdroje MCP jsou odvozeninami jedné deklarace, podle ADR 0002.
Web je čtenář. majordomus generate site zapisuje site/data/registry/why.json a why-graph.json ze stejných schopností; generátor webu zapisuje jednu stránku na záznam z této datové sady a každé tělo bere ze souboru, který záznam pojmenovává. site/content-src/why/ je pryč.
Autorské a odvozené se drží odděleně. Schémata odvozený klíč odmítají: ve zdrojovém souboru není žádné route, žádné url, žádný počet ani zpětný odkaz. Publikum nevypisuje své okamžiky a okamžik nenese okamžiky, které ho pojmenovávají.
Zamítnuté alternativy
Ponechat stránky a přidat metadata do jejich front matter. Web by zůstal jediným čtenářem, parser by rostl a momenty by zůstaly neviditelné pro všechny ostatní povrchy. Katalog by také zůstal uvnitř site/, což je projekční vrstva.
Nový subsystém pro katalog — vlastní loader, vlastní validátor, vlastní registr. To je to, co úloha zdánlivě potřebovala a na co už repozitář měl obecnou odpověď. Každý z těch kusů existuje jako datově řízený mechanismus; paralelní by byl druhým způsobem, jak deklarovat druh.
Z diagnózy udělat operaci POST se vstupem typu seznam. POST v tomto repozitáři znamená schopnost s účinkem na proces (druh Command z ADR 0002). Diagnóza čte a nic nemění, takže je to Query vázané na GET a její výběr je parametr oddělený čárkami — jedno schéma, které se váže stejně v query stringu, přes MCP i v příkazové řádce.
Znovu použít druh taxonomy pro oblasti. Jeho identity žijí v jednom plochém jmenném prostoru s kategoriemi případů užití a dva katalogy by tiše kolidovaly na sdíleném id, což index řeší vyloučením obou. Samostatný druh stojí jedno schéma a kolidovat nemůže.
Důsledky
Přidání provozního momentu je přidání jednoho souboru. Pak se objeví v příkazové řádce, HTTP API, dokumentu OpenAPI, MCP, odvozeném grafu, indexu webu, stránkách své cílové skupiny a oblasti, každém filtru, vyhledávání a dotazníku, aniž by se cokoli jiného upravovalo — což test/cases/98_why_catalogue.sh dokazuje tím, že to provede a pak vrátí.
Katalog je strojově čitelná mapa od symptomu čtenáře k mechanismu: signál → okamžik → oblast a publikum → schopnost, příkaz, tvrzení, pravidlo a případ užití. Diagnóza je průchod touto mapou s počítáním, ne model, a každé doporučení nese okamžiky, které ho vytvořily.
Dvě reference po cestě získaly typované cíle: share/commands.yaml se stal objektem indexu, takže commands momentu se vyřeší proti registru příkazů, a odpovědnosti momentu přestaly být ručně psané — každé tvrzení už deklaruje odpovědnost, do které patří, takže vztah se odvozuje přes tvrzení.
Cenou je jedna další trojice druhů k udržování v souladu a dataset webu, který nyní zapisuje spustitelný soubor místo generátoru webu, což ho staví do první fáze grafu odvození. Jeho payload závisí na vlastních zdrojích katalogu a na ničem jiném, takže oba průchody generate v scripts/derive vytvoří stejné bajty.