Zdůvodnění
Dne 2026-09-10 byl spustitelný soubor sestavený z dřívější revize tohoto crate namířen na aktuální strom přes MAJORDOMUS_BIN. Ohlásil zastaralé artefakty na stromě, který byl ve skutečnosti aktuální, a vytiskl nápravu run: majordomus generate. Její spuštění odstranilo kolem šestnácti tisíc řádků v deseti dokumentech — většinu z changelogu — přičemž každý přepsalo podle modelu, který strom už nedrží. Skončilo s nulou a neřeklo, že je něco špatně. Chytilo se to jen proto, že jeden pracovník před commitem přečetl git diff --stat; jinak by to přistálo vypadající jako běžná regenerace.
Mlčení způsobily dvě věci a obě stojí za pojmenování, protože ani jedna není neobvyklá.
Řetězec verze není build. Strážce, který existoval, porovnával verzi samotného executable s verzí, kterou deklaruje manifest crate. Oba říkaly totéž číslo, protože číslo se mění při vydání release, ne když se pohne deklarace. Dva executable se mohou shodnout na své verzi a neshodnout se na každé schopnosti, kterou promítají, a právě druhá neshoda přepisuje dokumenty.
Verdikt obvinil špatnou stranu. „Tento artefakt je zastaralý“ je výrok o stromu. Když je zastaralou stranou nástroj, je ta věta nepravdivá, a to v nejdražším možném směru: říká čtenáři, že náprava je regenerovat, a regenerace je akt, který ničí. Kontrola, která se může mýlit v tom, která ze dvou věcí je zastaralá, musí říct, kterou rozhodla, aby jí čtenář mohl nevěřit.
Zvyk, který to způsobil, nezmizí a neměl by: pracovník, který si půjčí sestavený spustitelný soubor místo deseti minut jeho přestavby, má pravdu, a několik relací denně to dělá. Musí se změnit to, že půjčení nevhodného je hlasité.
Požadované chování
Executable, který má generovat nebo kontrolovat odvozené artefakty tohoto repozitáře, nejprve zjistí, že byl sestaven ze stejných deklarací, jaké strom nese. Když to nedokáže, odmítne: nic nezapíše, uvede, čím je a co strom očekává, uvede nápravu a skončí nenulovým kódem.
Tři použití zůstávají funkční a mechanismus, který rozbije kterékoli z nich, je špatný mechanismus:
- odvození sestavující vlastní spustitelný soubor, což je běžná cesta;
- vydaný spustitelný soubor generující uvnitř repozitáře, který není tento, k čemuž vydaný spustitelný soubor slouží;
- správně odpovídající předsestavený spustitelný soubor pojmenovaný pomocí
MAJORDOMUS_BIN, čímž se relace vyhne zbytečnému přebuildu.
Pracovník, který si půjčí spustitelný soubor, před spuštěním odvození zjistí, že odpovídá, a před commitem přečte odvozený diff: regenerace, která odstraní tisíce řádků z dokumentu, který nikdo neupravoval, je odmítnutí, které se nestalo.
Chování při selhání
Odmítnutí je vlastní spustitelnému souboru, takže platí všude, kde se spustitelný soubor dosáhne — odvození, kontrola, git hook i člověk u terminálu — a ne v jednom volajícím, kterého může jiný volající obejít.
Oba verdikty jsou samostatné exit kódy a to oddělení je smyslem. Zastaralý artefakt je 10, kód nesplněného kontraktu, a jeho náprava je regenerace. Cizí generace je 15, kód odmítnutí, a její náprava je přestavba nebo pojmenování jiného spustitelného souboru. Jejich zploštění učinilo toto destruktivním: čtenář, kterému se řekne, že strom je zastaralý, udělá jedinou věc, která se nesmí stát, když je zastaralou stranou nástroj. Každý volající rozlišení přenáší, místo aby je zhroutil na selhání, a každý jmenuje spustitelný soubor, který dostal, protože půjčený spustitelný soubor byl dříve v logu neviditelný.
Porovnává se vlastnost kódu, který je modelem, ve třech otázkách kladených postupně: deklarovaná verze, která je vyražena do každé hlavičky původu, a proto při změně přerazí všechno; otisk vlastních zdrojů crate, který odpovídá na běžný případ, kdy odvození sestavilo spustitelný soubor ze stromu, který odvozuje; a když se ty liší, registr, který spustitelný soubor promítá, proti registru, který zaznamenává strom — což udržuje správně odpovídající předsestavený spustitelný soubor v provozu bez přestavby. Do tohoto porovnání nesmí vstoupit nic odvozeného z vlastního obsahu repozitáře: dokument nového druhu je změna repozitáře, ne spustitelný soubor, který se stal cizím.
Jedno omezení je neodmyslitelné a je uvedeno místo skrývání: spustitelný soubor sestavený dříve, než ochrana existovala, nemůže odmítnout sám sebe. Ochrana chrání stromy, proti nimž běží, ne workera, který si ponechal starý binární soubor.
Ověření
test/cases/33_stale_executable.sh namíří záměrně nesouhlasný spustitelný soubor na strom a ověří, že odvození odmítne, že skončí kódem odmítnutí, nikoli kódem nesplněného kontraktu, a že se pod odvozenými stromy nic nezměnilo — ani vytvořený výstupní adresář. Stejný případ pustí odpovídající spustitelný soubor proti jeho vlastnímu stromu a ověří, že pokračuje, takže se záruka nedá splnit odmítáním všeho. Každé ze tří použití výše má vlastní aserci, protože záruku, která rozbila případ vydané binárky, by objevil až ten, kdo nástroj přebírá.