Co to znamená
Data webu jsou projekcí stromu, z něhož byla vygenerována. Commit, který posune jeden z kanonických vstupů generátoru a neprovede regeneraci, nechá projekci popisovat strom, který už neexistuje — a publikační cesta, která přesně to odmítá, pak odmítne vše, co po ní následuje. Kontrola přesouvá toto odmítnutí na okamžik vzniku commitu, do checkoutu toho, kdo ho způsobil.
Princip
scripts/generate-site-data zapíše hash svých kanonických vstupů do site/data/generated/source.json jako source_hash. scripts/pages current zahashuje stejný seznam znovu — seznam pochází z generátoru samotného, s --inputs, takže neexistuje druhý seznam, který by zastaral — a porovná. Stojí to asi pětinu sekundy, protože se nic negeneruje: ptá se jen, zda je generování nutné. .githooks/pre-commit to spouští po doctor a zastaralý strom skončí s kódem 10, oběma hashi a příkazem, který ho opraví.
Kontrola je deklarována v seznamu enforcement politiky jako derived-current, zapojená přes git-hook:pre-commit, takže doctor drží zapojení tak, jako drží doctor-on-commit a finish-on-push: hook musí existovat, být spustitelný, vyvolat kontrolu a nepolykat její exit kód. Pravidlo je tak vynucováno dvakrát — kontrola odmítne zastaralý commit a doktrína odmítne repozitář, který kontrolu odpojí.
Deklarovat to místo zakompilování je záměrné. Které soubory jsou kanonické vstupy a kde se zaznamenává jejich hash, jsou fakta o tomto repozitáři, ne o každé instalaci nástroje; validátor v lib/ by dodaný spustitelný soubor naučil rozvržení jednoho repozitáře. Seznam vynucování už existuje, aby říkal „tento repozitář se tím řídí, zapojeno zde“, a doctor už takové položky dokazuje. Chybělo jen to, že jeho verifikátor předpokládal, že program je majordomus; nyní program čte z položky, takže si repozitář může deklarovat vlastní kontroly.
Jak to vidět
scripts/pages current # pages: site/data/generated is current for this tree (input hash …)
printf '\n' >> docs/DOCTRINE.md # move a canonical input
scripts/pages current # exit 10: is stale — it carries …, this tree hashes to …
git commit -am "…" # refused by .githooks/pre-commit
majordomus doctor # OK wiring derived-current — wired via .githooks/pre-commitCo nepokrývá
Odpovídá na jedinou otázku — jsou commitnutá data webu pro tento strom aktuální — a odpovídá z hashe. Neříká, který artefakt je zastaralý ani co se v něm změnilo; to dělá scripts/derive-check spuštěním obou generátorů a diffem a CI i workflow Pages jej stále spouštějí. Otisk je levná kontrola, kterou lze pustit při každém commitu; vyčerpávající běží tam, kde jsou minuty k dispozici.
Nyní pokrývá obě poloviny. scripts/generate-site-data vlastní site/data/generated, na což odpovídá hash vstupů výše; majordomus generate vlastní site/data/registry/registry.json a docs/generated/artifacts.*, které zaznamenávají každý zdrojový soubor, jejž index drží — a zdrojový soubor není vstupem webu, takže se hash při jeho změně nehne. Kontrola klade druhou otázku pomocí majordomus generate --check, vlastní definice zastarání generátoru, ne porovnání napsaného v kontrole, a hlásí obojí. Repozitář bez sestaveného spustitelného souboru se dozví, že polovina registru nebyla zkontrolována, místo aby potichu prošla.
Rebase jím neprochází a toto je mezera, která nejspíš kousne. Rebase větve, která se dotýká zdrojového souboru měřeného registrem, nechá strom zastaralý, protože ovladač merge=derived převede odvozené soubory na naše a git pak zahodí vlastní regenerační commit větve jako „patch contents already upstream“ — což platí o jeho obsahu, když trunk vygeneroval stejné bajty, ale neplatí o stromu po rebase. Rebase ohlásí úspěch a generate --check je hned poté červený. Během rebase hook nic nespouští, takže po něm znovu spusť scripts/derive a výsledek commitni.
Ruční kontrola vyžaduje spustitelný soubor samotné větve. generate --check spuštěné s binárkou sestavenou z jiného worktree hlásí artefakty jako zastaralé, které nejsou, protože generátor vytvářející porovnání pochází z jiného stromu, a odpověď se čte přesně jako skutečný nález.
Je to lokální kontrola, takže zavazuje každého, kdo má nainstalovaný hook (git config core.hooksPath .githooks). Merge provedený přes forge jí neprochází; záchytnou sítí tam zůstávají job CI site a workflow Pages.
Proč existuje
Dne 2026-09-06 publikační cesta odmítla master třikrát za hodinu. Každé odmítnutí způsobil merge, který pohnul kanonickými vstupy bez regenerace, a každé objevil další člověk, který přistával a musel pustit generování, které nezpůsobil a nemohl zkrátit — dvakrát ho při běhu předběhlo jiné přistání. Kontrola nikdy nebyla potíž; pages current už existovalo a trvá pětinu sekundy. Chybělo to, kdy běží. Kontrola, která promluví až po mergi, účtuje špatnému člověku, a pravidlo, jehož vlastní text říká, že o něm rozhoduje recenzent, je pravidlo, o kterém nerozhoduje nic.