Zdůvodnění
Tři programy zde odpovídají člověku a každý povrch, který chce ukázat, co nabízejí, je v pokušení vést seznam. Pokušení je pokaždé rozumné: recept just na příkaz má čtyři řádky a čte se dobře; doplňovací skript se jmény příkazů funguje okamžitě; dokumentační stránka s tabulkou příkazů se snadno píše.
Každý z těchto seznamů je správný v den, kdy je napsán. Co se děje potom, není hypotéza — tento repozitář má důkaz. Schopnost deklarovala, že je dostupná jako majordomus scope classify; příkazový řádek takový příkaz neměl a nikdy nemá. Nikdo si nevšiml, protože nic obě deklarace nespojovalo. Generovaná reference ukazovala příkaz, který nešlo spustit.
Obecný tvar je ten, který pojmenovává DYNAMICITY.md: fakt zapsaný na dvou místech, z nichž se jedno mění. Název příkazu, jeho jednořádkový popis, argumenty a hodnoty, které přijímají, jsou fakta, která implementující program už zná, a každá jejich kopie tiše chátrá — recept, který přežije příkaz, jejž zapisuje, doplňování, které nabízí odstraněný přepínač, stránka, která dokumentuje příkaz, jenž nikdy neexistoval.
Cena alternativy je malá a jednosměrná. Graf skládá tři deklarace, které už existují a už jsou autoritou: strom clap, dodaný registr příkazů, se kterým se shellový nástroj sesouhlasuje, a vlastní strukturovaný výpis spouštěče workflow. Nic se u něj neregistruje. Přidání příkazu do kteréhokoli z nich ho dá na každý povrch, který politika vystavení připouští, a odebrání ho sundá.
Požadované chování
Příkaz je deklarován na jednom místě: v programu, který jej implementuje.
- příkazy spustitelného souboru v Rustu jsou deklarace clap v
apps/majordomus-cli/src/cli.rs; - příkazy shellového nástroje jsou
share/commands.yaml, srovnané s jeho dispečerskou tabulkou; - workflow je recept v
justfilenebo.just/*.just.
Sémantika, kterou deklarace nenese, se anotuje jednou, hned vedle ní. Co běh příkazu mění, zda drží terminál, co vyžaduje a odkud se berou hodnoty argumentu, žije v apps/majordomus-cli/src/command_graph/semantics.rs, vedle příkazové řádky, kterou popisuje. Výchozí je to, čím je většina příkazů, takže se zapisuje jen odchylka, a anotace jmenující příkaz, který už neexistuje, shodí build.
Každý jiný povrch odvozuje. Konkrétně žádný z nich nesmí nést název, popis ani argumenty příkazu:
- soubor workflow nesmí deklarovat recept, jehož tělem je volání kteréhokoli z obou programů — to je ručně psaný most a generovaný ho už nese, s popisem, který dává jeho vlastní deklarace. Napsat příkaz není totéž co ho použít: recept, který z příkazu přečte hodnotu a pak udělá práci, kterou nedělá žádný příkaz žádného z programů —
just opense zeptáserve statusna adresu a otevře na ní prohlížeč — skládá, a neopakuje, a žádný uzel grafu se na něj neprojektuje; - adaptér shell completion nesmí obsahovat příkaz, flag, identifikátor ani množinu hodnot;
- seznam nástrojů MCP, tabulka tras HTTP, dokument OpenAPI, paleta Cockpitu a index dokumentace nesmějí být ručně udržovány pro příkaz, který graf nese;
- alias kompatibility pro starší název receptu je deklarován jednou, vedle příkazového řádku, a vykreslen do generovaného mostu — nikdy se neudržuje v souboru workflow.
Projekce se odvozují, ne deklarují. Který povrch příkaz nese, vyplývá z toho, co jeho spuštění mění a jak se chová vůči terminálu, a rozhoduje o tom jedna funkce (command_graph/policy.rs). Žádný příkaz nenastavuje povrch a každý povrch, který příkaz zadržuje, nese důvod.
Generované projekce se nesledují. Most workflow je čistá funkce stromu, v němž sídlí; žije pod .ai/local/cache/, zapisuje se atomicky a obnovuje se, když se změnila deklarace za ním. Vstup do repozitáře nesmí zašpinit pracovní strom.
Chování při selhání
Kontrola command-graph (scripts/ci/command-graph) selže, exit 10, když:
- graf nese chybu — duplicitní identitu, název receptu, který by převzaly dva příkazy, schopnost, která si nárokuje příkazovou řádku, již executable nedeklaruje, anotaci nebo alias jmenující příkaz, který už neexistuje, nebo tajný argument se zdrojem hodnoty, který by ho vyjmenoval;
- soubor workflow deklaruje recept, jehož tělo je voláním jednoho ze dvou programů — řádek těla, který po úvodních mezerách a
@a-, které runner dovoluje, začíná launcherem — s výjimkou bootstrap receptu, který vytváří most. Program jmenovaný uvnitř substituce příkazu, pipeline nebo přiřazení je hodnota, kterou recept spotřeboval, ne jméno, které zopakoval, a není nález.
test/cases/102_completion_shell.sh načte vygenerovaný adaptér do skutečného zsh a přečte, co nabízí, protože doplňování, které v souboru vypadá správně a vůbec nic nedělá, je běžné selhání tohoto druhu práce.
test/cases/101_command_graph.sh je behaviorální polovina: dokazuje, že graf se sestaví v jednorázovém repozitáři, že most, který zapisuje, předává argumenty a neinterpoluje je, že druhá materializace nezapíše nic, že přidání příkazu do deklarace dosáhne projekce workflow i dokončování bez další úpravy a že kontrola může selhat — ručně napsaný most vložený do kopie je odmítnut toutéž kontrolou.
Samotné odvození se za běhu nevynucuje. Projekce odvozením jsou: za běhu není co kontrolovat, protože neexistuje druhá kopie, která by mohla být odlišná.
Ověření
scripts/ci/command-graph # the gate
bash test/run.sh 101_command_graph # the behavioural case
majordomus commands graph --check # the graph alone; exit 10 on an error
majordomus commands explain <id> # where one command is projected, and why
apps/majordomus-cli/src/command_graph/ nese jednotkovou polovinu: že žádný adaptér nepojmenuje příkaz, že mutace nikdy nedosáhne strojového povrchu, že workflow se nikdy nepropojí zpět do workflow a že otisk grafu nad jedním stromem je stabilní.