Situace
Zpráva commitu je jediný záznam o tom, proč byla změna provedena, který přežije větev, pull request i osobu. Tento repozitář uvedl, jak má jedna vypadat, a pak to nerozhodoval: verze 1 project.conventional-commits končila „Žádný příkaz toto pravidlo nerozhoduje; rozhoduje revizor.“ Měření pořízené v den, kdy byla tato věta nahrazena, říká, co to stálo — z 1161 commitů, které nejsou merge, 48 předmětů přesahuje šířku, kterou tento projekt deklaruje pro řádek čehokoli, a 38 nese slovo typu, které neobsahuje žádný slovník. Nikdo si nevšiml, protože se nikdo nedíval.
Druhá polovina problému není vynucování, ale psaní. Někdo — člověk na konci odpoledne nebo agent na konci mandátu — má pracovní strom s padesáti změněnými soubory a musí rozhodnout, kolik commitů to je, jaký rozsah každý nese a které slovo typu je poctivé. Obvyklou odpovědí je tabulka vzorů cest mapujících adresář na rozsah. Tabulka je správná v den, kdy vznikla; pak se přidá adresář, subsystém se rozdělí a tabulka jmenuje rozsah, který historie přestala používat před měsíci, aniž si toho něco všimne, protože tabulka nemá jak se mýlit.
Třetí polovina žila úplně mimo repozitář: postup psaní commitu — odvodit scope z cesty, propojit práci, nevymýšlet číslo úkolu, oprava potřebuje test — seděl v próze, kterou každý AI klient četl a prováděl ručně, jeden soubor na klienta. Workflow, jehož sémantika žije v promptu, je neverzované, nevynutitelné, netestovatelné a pravdivé právě pro jeden nástroj.
Co spouštíte
Čtyři schopnosti, deklarované jednou v apps/majordomus-cli/src/capability/builtin/commit.rs a promítnuté do příkazového řádku, seznamu nástrojů MCP a tras HTTP, aniž by byly kdekoli registrovány dvakrát. Všechny čtyři jsou příkazy Rust spustitelného souboru, takže launcherem je bin/majordomus-cli, který jej sestaví, když je třeba:
majordomus commit scopes(commit.scopes,majordomus_commit_scopes,GET /api/v1/commit/scopes): slovník, naučený z nejvýše 1500 commitů zgit loga počítaný vůči prefixům adresářů, se kterými je každý scope spojen, do hloubky čtyř segmentů. Při čtení v tomto repozitáři na8998e11fdodpovídálearned from 1161 commit(s), at most 1500a pakderives 211 commity nadsite, site/data, site/data/registry,sitese 134,cise 60,planse 44. Ten seznam nikdo neudržuje: subsystém commitnutý dnes v něm je dnes a ten, kterého se rok nikdo nedotkl, sám klesá.majordomus commit plan(commit.plan,majordomus_commit_plan,GET /api/v1/commit/plan): pracovní strom rozdělený do commitů, které podporuje vlastní členění historie, pod otiskem repozitáře, worktree, HEAD a hashe přes každou změnu s její fází a stavem. Každá skupina nese své zdůvodnění — kolik předchozích commitů tyto cesty tak zařazuje, nebo že několik rozsahů má stejný nárok, nebo že sada změn obsahující generované soubory je jeden commit, protože jen poslední z několika by mohl nést aktuální odvozená data (project.derived-files-regenerated). Předmět je záměrně ponechán jako<subject>: co změna udělala, je jediné, co žádný důkaz ve stromu nemůže říct, a plánovač, který by o tom napsal sebejistou větu, by do historie psal fikci.majordomus commit validate [FILE] [--paths a,b] [--rev REV](commit.validate,majordomus_commit_validate,GET /api/v1/commit/validate): verdikt o jedné zprávě, načtené ze souboru, ze stdin nebo z již vytvořeného commitu. Kód 0, když je nejhorším nálezem varování, kód 10, když je jím chyba.feat(commit): the header is parsed onceprojde swarning commit.unknown_scope, protožecommitje rozsah, který tato historie ještě nepoužila, a inference nesmí odmítnout první commit subsystému, který nikdy neviděla.update stuff.selže serror commit.not_conventionala dostane seznam jedenácti slov typu.--rev HEADna merge commitu odpovíexempt git_authored: git composed this subject, not a person.majordomus commit history [RANGE](commit.history,majordomus_commit_history,GET /api/v1/commit/history): každý commit v rozsahu posouzen jedním průchodem, exit 10, pokud některý nese chybu.HEAD~5..HEADzde odpovídáHEAD~5..HEAD range 11 commit(s): 6 exempt, 0 failinga končí 0; celá historie odpovídáHEAD range <n> commit(s): <e> exempt, 54 failinga končí 10. Tři počty se hýbou s historií; ten, který ne, je 54, což je zaznamenaná baseline. To je to, na co se ptáscripts/ci/commit-policy, a proto kontrola může říctcommit-policy: history 54 failing, baseline 54— dluh je zaznamenán v.ai/repo/commit-policy-baseline.txt, kontrola selže, když roste, a ohlásí, když klesá, a commity, které větev přidá, podléhají politice bez výjimky a bez jakékoli baseline.
Jeden příkaz shellového nástroje nese polovinu, kterou živý scénář dosáhne, a to je to, co scénář spouští. doctor by byl zřejmý druhý — sladí commit-policy-on-message s tím, co .githooks/commit-msg skutečně volá, a vypíše OK wiring commit-policy-on-message — wired via .githooks/commit-msg — ale záměrně tu není. Krok doctor ověřuje, že je zdravý celý repozitář, což je daleko víc, než o čem tento případ užití je: nález kdekoli jinde ve vrstvě by shodil scénář o zprávách commitů a čtenář by se z něj o zprávách commitů nic nedozvěděl. Stojí také 30–58 sekund proti runneru scénářů, který běží při každém sestavení webu. Zapojení dokazuje majordomus doctor, kam patří, a test/cases/274_commit_policy.sh, které pohání skutečný hook.
Příkaz, který scénář spouští:
doctor: hookcommit-msgje deklarován podenforcement:v.ai/repo/policy.yamljakocommit-policy-on-message, takže zapojení se sladí, ne předpokládá — cesta se musí rozlišit, být spustitelná a být volána tak, aby se její návratový kód nepolkl.doctrine list: vynucovaná podmnožina sady pravidel, o které rozhoduje shellový validátor. Pravidlo commitů v ní záměrně není.
Scénář
mode: live
given:
- 'the layer installed and the hooks wired; the executable built, because the hook and the gate both call it'
steps:
- id: no-shell-validator-decides-it
run: ['doctrine', 'list']
note: 'the doctrine registry is what a lib/ validator decides; project.conventional-commits is absent from it because the judge is the executable, asked by a hook and by a CI gate'
expect:
exit: 0
stdout_contains: ['^majordomus.enforcement-wiring +blocking']
stdout_not_contains: ['^project\.conventional-commits']
then:
- 'a rule of this project is enforced by a gate and a hook that call the executable, never by a validator added to the shell tool'
- 'the grammar is one parser: the changelog and the judge read the same CommitHeader::parse and disagree only about what to do with a header nobody spelled conventionally'
- 'the three levels in the policy - off, warning, error - are decisions a repository can read back; off is a value, not an absence'
- 'test/cases/274_commit_policy.sh drives the four commands over real repositories, real worktrees and the real hook; scripts/ci/commit-policy reads the whole history against the baseline, and a branch of its own commits outright'Výsledek
Zpráva, kterou člověk píše, se posuzuje v jediném okamžiku, kdy existují zpráva i soubory, a proto se lze fix_requires_test ptát u commit-msg a nikde jinde: oprava bez testu mezi soubory stojí za povšimnutí, dokud je jeho přidání levné. Kontrola čtoucí historii nezná cesty, a proto tento nález nedělá vůbec — úsudek, jehož důkazy chybí, se nečiní, místo aby se hádal.
Vytvoření commitu tu záměrně není. git commit je mutace repozitáře a politika vystavení zastavuje každý strojový povrch u lokální mutace, takže agent se smí ptát, čím by commit byl a zda zpráva prochází, a commituje člověk. Tento tvar činí plánovač i soudce čistými funkcemi stromu a zprávy: pracují offline, nemohou napůl uspět a každou odpověď lze přepočítat a ověřit.
Otisk na plánu je jeho multi-agentní polovina. Několik workerů sdílí zdejší checkout a další sdílejí repozitář, takže plán spočítaný na jednom HEAD a vykonaný na jiném commituje soubory, které někdo jiný stagoval, pod zprávou o práci, která už není tím, co se změnilo. Otisk nic nezamyká a tomuto race nezabrání; odmítá být tím, kdo v něm tiše prohraje, a říká, která polovina se pohnula — že se pohnul HEAD, nebo že plán patří jinému worktree.
subject_max_chars: 100 je změřeno, ne zvoleno. Konvence gitu je 72; přes 1161 ne-merge commitů, z nichž se tento slovník učí, je medián předmětu 73 znaků a 95. percentil 98. Limit, který porušuje polovina historie, není limit — je to šum, který učí lidi kontrolu ignorovat.
Nedělá to, že by posuzoval, zda je předmět dobrá věta, zda je změna atomická ani zda stálo za to práci dělat. To rozhoduje revizor a validátor, který předstíral, že to umí, je validátor, kterému nikdo nevěří.