Každý repozitář, ve kterém jsem pracoval, obsahuje věty, které nemohou selhat.
„CLI a HTTP API vystavují stejné operace.“ „Veškerá konfigurace se validuje při startu.“ „Přispěvatelé musí napsat test ke každé opravě chyby.“ Nejsou to lži, když se píší. Později se jimi stanou, tiše, zatímco všichni, kdo si toho mohli všimnout, mají plné ruce práce. Nic se nerozbije, když README přestane platit, protože README není s ničím propojeno. Je to próza stojící vedle programu a próza nemá návratový kód.
Posledních několik měsíců jsem stavěl nástroj, jehož celý předpoklad je, že tohle lze opravit — ne psaním lepší dokumentace, ale tím, že se z dokumentace stane druh objektu, který může sestavení odmítnout. Tento článek je o mechanismu, o tom, co dnes dokládá, a o konkrétním místě, kde přestává cokoli dokládat, což je část, která mě zajímá nejvíc.
Co je Majordomus
Majordomus je řídicí dozorová vrstva pro repozitář, na kterém společně pracují lidé a kódovací agenti. Konkrétně jsou to dva programy. Shellový nástroj majordomus spouští životní cyklus úlohy: informuje relaci o tom, co repozitář ví, zaznamenává rozhodnutí a předávky, kontroluje práci proti deklarovanému rozsahu úlohy a odmítne finish, jehož závazky nejsou splněny. Spustitelný soubor v Rustu indexuje vrstvu .ai/ repozitáře — pravidla, rozhodnutí, milníky, úkoly, případy užití, tvrzení, záznamy relací — do typovaného grafu objektů a servíruje tento graf přes příkazovou řádku, HTTP API, dokument OpenAPI, server MCP a webový cockpit.
To, co řídí, jsou vlastní výroky repozitáře o sobě samém. Ne kód — kód už má překladače a testy. Vrstva nad kódem: co tento projekt slibuje, která pravidla změnu zavazují, která rozhodnutí jsou uzavřená, čeho se relace nesmí dotknout a co cokoli z toho dokazuje.
Tato vrstva existuje v každém projektu. Obvykle je rozptýlena mezi soubor CONTRIBUTING, šest stránek v Notionu, diagram architektury, který přestal odpovídat skutečnosti před dvěma refaktoringy, a paměť toho, kdo tam je nejdéle. Když se připojí kódovací agent, dostane takový zlomek, jaký se vejde do promptu, a zbytek znovu objevuje — špatně a znovu i zítra.
Proč „více kontextu“ není řešení
Samozřejmá reakce na agenta, který nezná vaše konvence, je říct mu je. Dejte je do souboru, který agent vždy čte. Funguje to asi týden.
Selhává ze strukturálního důvodu, ne kapacitního. Konvence zapsaná v souboru, který nic nevynucuje, má právě dva stavy — dodržena a porušena — a soubor vám neřekne, který z nich nastal. Soubor proto roste. Přispěvatelé přidávají pravidlo, které se porušilo minulý týden. Soubor s instrukcemi pro agenta se stává hřbitovem minulých incidentů, každý řádek je jizva a žádný není ověřitelný. Skutečné chování repozitáře se mezitím od něj vzdaluje a nikdo to nezjistí, protože zjištění by vyžadovalo, aby někdo přečetl celý soubor a proti němu auditoval celý repozitář, což je přesně ta práce, na kterou nikdo nemá čas.
Pravidlo, o kterém žádný příkaz nerozhodne, je pravidlo, v které jen doufáte.
Otázkou návrhu tedy není „jak dát agentovi víc kontextu“, ale „která z těchto tvrzení lze učinit rozhodnutelnými a co dělat s těmi, která ne“.
Tvar systému
Architektura z té otázky vyplývá. Jedna kanonická deklarace, mnoho odvozených povrchů a kontrola všude, kde by odvození mohlo tiše zastarat.
flowchart TD A[canonical state<br/>.ai/ rules, decisions, issues, claims, use cases] --> B[typed discovery<br/>one index, one object graph] B --> C[capability registry<br/>declared in Rust] C --> D[HTTP API + OpenAPI] C --> E[MCP tools and resources] C --> F[Cockpit] C --> G[generated documentation] C --> H[command line] B --> I[validators and gates] I --> J[a refusal, with the command that reproduces it]
The registry is the part that pays for itself. Every operation is declared once, in Rust, with its identity, its effect and its exposure. As this page is built, that registry holds 3161 capabilities: 196 of them are exposed as MCP tools, 3010 as MCP resources, 201 as HTTP operations. Every one of those surfaces is rendered from the same rows, so an operation cannot exist in the API and be missing from the OpenAPI document, and a tool cannot appear over MCP that the registry does not know about. There is a gate that regenerates everything and fails if the result differs from what is committed.
Chci být přesný v tom, co toto nepokrývá, protože poctivá verze je užitečnější než uhlazená. Příkazová řádka není čistá projekce. Příkazová řádka spustitelného souboru má 209 spustitelných příkazů a ne za každým z nich stojí schopnost — kolik jich je, říká sám nástroj ve stejné zprávě na řádku commands no capability claims. Tyto příkazy jsou druhá deklarace, kontrolovaná proti první, ne z ní odvozená. Uzavření této mezery je probíhající práce a dokud se neuzavře, „jedna deklarace, každý povrch“ platí pro API, povrch MCP a dokumentaci a pro CLI je to aspirace.
Tvrzení jako objekty
Mechanismus, který vám skutečně chci ukázat, je užší a podle mě přenositelnější.
Každá věta o schopnostech na veřejném webu projektu pochází z jednoho souboru, docs/CLAIMS.yaml. Tvrzení je tam typovaný objekt: id, jedna věta v přítomném čase, kanonický soubor, který definuje chování, soubor, který ho implementuje, test, který ho dokládá, a stav. Stavy jsou deklarovány jako data ve stejném souboru — guaranteed, advisory, planned, rejected — s jejich významy, takže generátor nemůže vymyslet pátý.
Zaručeno znamená: implementováno a test chování to dokazuje.
Pravidlo, které z toho dělá víc než tabulku, je, že vztah musí platit v obou směrech a rozhoduje o něm gate. scripts/ci/claim-proof-check přečte každé zaručené tvrzení, otevře testovací soubor, který tvrzení uvádí, a vyžaduje, aby tento test ve své hlavičce uváděl tvrzení zpět. Tvrzení odkazující na test, který o něm nikdy neslyšel, je nález. Poté vyžaduje, aby byl pojmenovaný test spustitelný — shell případ pod test/cases/ nebo test crate pod apps/majordomus-cli/tests/ — protože tvrzení, jehož důkazem je soubor Markdown, není dokázáno, je popsáno.
Když jsem to psal, ta kontrola hlásila:
$ scripts/ci/claim-proof-check --strict
guaranteed claims: 0 of 161 name a test that does not name the claim back
runnable tests: every guaranteed claim names a shell case or a crate test
blocking rules: not measured here — scripts/ci/rule-proof-check is the one reader
claim-proof-check: every guaranteed claim names a test that names it back
Matice drží 232 zaručených tvrzení v době sestavení této stránky a kontrola běží přísně nad každým z nich: základ výjimek vedle ní obsahuje komentáře a žádné vyňaté tvrzení. Na seznamu výjimek není nic.
Stejný tvar platí o úroveň výš, pro pravidla. Pravidlo v tomto repozitáři je verzovaný dokument Markdown se strojově čitelným blokem, který deklaruje, jak se vynucuje. Objektový graf repozitáře indexuje 189 dokumentů pravidel; pravidla, která definují, se řeší v deterministickém pořadí a každé blokující nese validátor — scripts/ci/rule-proof-check je čtečka, která o něm rozhoduje. Samotný standardní balíček, část, kterou zdědí každý přijímající repozitář, deklaruje 50 pravidel, z nichž 43 je blokujících. Několik pravidel deklaruje, že je vynucuje lidský čtenář — a to je typovaný stav s povinným důvodem, ne absence. Ten rozdíl záleží: „kontrolujeme to ručně, protože automatická kontrola by musela hádat“ je obhajitelný inženýrský postoj. „O tomhle nikdo nikdy nerozhodl“ v témže přestrojení není.
Místo, kde se zastaví
Zde je část, kterou by propagační článek vynechal.
Vše výše dokazuje, že důkaz existuje. Nic z toho nedokazuje, že důkaz běžel.
Repozitář má ledger důkazů — .ai/repo/evidence/ledger.json — navržený tak, aby spojoval tvrzení se zaznamenanými provedeními, takže tvrzení může nést stav jako dokázáno, zastaralé nebo selhává, místo pouhého „má test“. Subsystém je implementován. Ledger nyní drží 14 provedení, každé zaznamenané na vývojářově stroji — "origin": "local" — protože nic jiného zatím žádné nezaznamenává.
Zeptejte se nástroje na stav důkazů všech 250 tvrzení a při sestavení této stránky odpoví: 217 nespuštěno, 21 zastaralých, 12 bez testu, 0 prokázáno. Když jsem to psal, zpráva o pravidlech říkala totéž ve svém vlastním slovníku: recorded: 0, passing: 0.
Příčina je všední a konkrétní: žádný workflow CI nevolá majordomus evidence record. Sada běží při každém pushi — každý shell případ pod test/cases/ i každá testovací funkce v Rustu v cratu — a výsledky zapisuje do logu, který GitHub smaže při dalším opakování. Neexistuje žádný publikovaný strojově čitelný report testů; https://majordomus.dev/reports/tests.json vrací 404.
Přesné shrnutí současného stavu tedy je: tento repozitář umí dokázat, že každé zaručené tvrzení má test, který je jmenuje zpět, a zatím neumí dokázat, že kterýkoli z těch testů nedávno prošel. První polovina je skutečný, vynucovaný invariant bez výjimek. Druhá polovina je drát, který není připojen. Obojí je dnes pravda a čtenář si zaslouží vědět, co je co.
Mohl jsem tento článek odložit, dokud nebude účetní kniha naplněna, a napsat čistší příběh. Myslím, že mezera je poučnější artefakt. Je to přesně ten druh napůl postaveného mechanismu, který se, ponechán nepopsaný, stane příští rok větou, která nemůže selhat.
Jeden skutečný workflow: pravidlo, které mě odmítlo
Nejlepší důkaz, který mohu podat, že tato vrstva governance je spustitelná, a ne dekorativní, je, že mě odmítla, když jsem tohle psal.
Tento článek má protějšek napsaný česky. Tento jsem nepřekládal; napsal jsem druhý článek ze stejné evidenční báze, pro jiné publikum. Abych ho mohl publikovat, musel jsem do repozitáře dát soubor obsahující českou prózu.
Repozitář má pravidlo project.english-only, jehož výrok zněl: „Kód, komentáře, commity, dokumenty a záznamy správy se píší anglicky, bez výjimek.“ Je to blokující pravidlo a na rozdíl od většiny takových výroků ve většině repozitářů je k něčemu zapojeno. scripts/ci/english-only-check skenuje každý sledovaný autorský soubor — každý .md, .rs, .sh, .yaml, .html, plus každý soubor bez přípony se shebangem — na písmena, která se vyskytují v češtině, slovenštině či polštině a nikdy v angličtině, a na celá nelatinská písma, porovnávaná jako bajtové sekvence UTF-8, takže výsledek nezávisí na locale stroje. Strom obsahu webu je v rozsahu. V tomto stromu není žádná dluhová základní linie, takže jediný zásah kontrolu selže.
Kontrola má seznam povolených se dvěma druhy položek, name pro vlastní jména a fixture pro soubory, které používají cizí řetězec jako testovací data. Obojí je deklarováno s důvodem. A obojí říká v hlavičce kontroly samotné: ani jedno nevyjímá větu.
Český článek tedy nešlo přidat. Ne „bylo by to špatná praxe“ — nešlo: kontrola by zčervenala a přidání řádky fixture k jejímu umlčení by bylo zneužití výjimky, jejíž dokumentace přesně to výslovně zakazuje.
Místo toho jsem udělal workflow, které repozitář předepisuje pro změnu toho, co vynucuje. Zaznamenal jsem rozhodnutí — ADR — uvádějící rozlišení, které původní pravidlo nikdy dělat nemuselo, protože když vzniklo, každý artefakt v repozitáři byl pracovní artefakt. Publikovaný článek adresovaný čtenáři v jeho jazyce je jiná kategorie než komentář, zpráva commitu nebo záznam governance. Povýšil jsem pravidlo na verzi 2 s tímto rozlišením zapsaným do jeho znění, přidal třetí druh allow-listu, translation, který vyžaduje cestu pod stromem publikovaného obsahu, deklarovaný jazyk a důvod a který deklaraci křížově kontroluje proti jazyku, který stránka sama deklaruje ve front matter, takže výjimka nemůže být jednostranná. Pak jsem napsal behaviorální případ, který dokazuje, že pozměněná kontrola stále odmítá českou prózu v běžném zdrojovém souboru a přijímá ji jen tam, kde to nový druh dovoluje.
Zajímavý je tvar, ne konkrétní pravidlo. Změna toho, co repozitář vynucuje, stála záznam rozhodnutí, zvýšení verze, změnu kontroly a test. Nic z toho nebylo ceremoniální: bez kteréhokoli z nich by změna nepřistála, protože kontrola, která čte pravidla, by zjistila, že deklarované vynucování pravidla už neodpovídá jeho implementaci.
To myslím vykonatelnou správou. Ne že dokument říká, že pravidla záleží — že je nemůže obejít ani autor.
Co je skutečně ověřeno
| Výrok | Stav | Jak to můžete ověřit |
|---|---|---|
| Každé zaručené tvrzení jmenuje spustitelný test, který jmenuje je zpět | Ověřeno, vynuceno | scripts/ci/claim-proof-check --strict, exit 0, prázdná základní hodnota |
| Jeden registr vykresluje HTTP API, OpenAPI, MCP i dokumentaci | Ověřeno, změřeno | majordomus capabilities projections: 3161 rows, 201 HTTP, 196 MCP tools, 3010 MCP resources |
| CLI je odvozeno z tohoto registru | Zatím neplatí | majordomus capabilities projections počítá, které z 209 spustitelných příkazů si nenárokuje žádná schopnost |
| Každé blokující pravidlo nese validátor | Ověřeno | scripts/ci/rule-proof-check, exit 0 |
| Tvrzení nesou zaznamenaný stav důkazu | Implementováno, nekrmeno z CI | ledger drží 14 provedení, všechna lokální; 0 z 250 tvrzení dokázáno |
| Publikovaný web je generován z repozitáře | Ověřeno, nasazeno | build.json jmenuje verzi, commit a generátor |
| Mesh: servery se navzájem objevují napříč stroji | Experimentální, vypnuto | enabled: false ve výchozím nastavení; status hlásí neaktivní |
Co jsem se naučil
Tři věci, v sestupném pořadí jistoty.
Kontrola mění to, čím dokument je. Před claim-proof-check byl soubor tvrzení marketingovým inventářem, který náhodou měl sloupec s testem. Po ní znamená přidání věty na web napsání testu a poctivá cesta nejmenšího odporu se stává snížením stavu tvrzení místo jeho přehánění. Soubor se nezměnil. Změnil se důsledek psaní do něj.
Většina governance dluhu je jednostranná. Opakující se vada, kterou ve své práci stále nacházím, je kontrola, která ověřuje vztah jen z jednoho konce: tvrzení, které jmenuje test, aniž by cokoli vyžadovalo, aby test jmenoval tvrzení; dokument, který deklaruje kontrakt, a žádný validátor nečte druhou stranu. Jednostranné kontroly působí jako vynucování a nejsou, protože polovina, kterou nečtou, je přesně ta, která hnije.
Rozdíl mezi „deklarováno“ a „zaznamenáno“ je místo, kde žije poctivost. Je snadné postavit systém, který ví, co slibuje. Je mnohem těžší postavit takový, který ví, kdy to naposledy zkontroloval. První mám, druhé zatím ne, a přesné pojmenování té hranice — ve výstupu samotného nástroje, na veřejném webu i v tomto článku — má větší cenu než její tiché uzavření, kdybych ji uzavřel.
Důkazy
Tento článek vznikl v září 2026, u commitu d8c97273f0, který přidal tuto stránku. Počty v něm nejsou psány ručně: každý se při každém sestavení tohoto webu čte z dat, která repozitář generuje, a příkazy níže měří totéž na checkoutu. Repozitář je veřejný.
- Počty schopností, projekce, příkazy bez podpory:
majordomus capabilities projections --format json - Počty tvrzení a stavy důkazů:
majordomus evidence show --format json - Uzavření tvrzení:
scripts/ci/claim-proof-check --strict; baseline.ai/repo/claim-proof-baseline.txt - Počty pravidel a režimy vynucování:
majordomus rules report --format json;scripts/ci/rule-proof-check - Testy:
ls test/cases/*.sh | wc -lpočítá shellové případy;grep -r '#\[test\]' apps/majordomus-cli | wc -ltestovací funkce Rustu - Kontroly: deklarované v
.ai/repo/ci/gates.yaml, ty, které běží při každé změně, označenéalways: true - Nasazení:
build.jsonna publikovaném webu jmenuje zdrojovou verzi, commit a generátor - Pravidlo, které tento článek musel změnit:
.ai/repo/rules/project/english-only.v4.md, a rozhodnutí, které je změnilo
Samotná tvrzení se publikují po jedné stránce na tvrzení a každá jmenuje svůj test. Je-li věta na tom webu nepravdivá, existuje konkrétní soubor k otevření a konkrétní příkaz, který měl selhat.