Každý příkaz, který tento repozitář nabízí, od kteréhokoli programu, který jej nabízí, složený jednou a promítnutý všude. Tento dokument je smlouva: čím příkaz je, odkud pocházejí skutečnosti o něm, která plocha jej nese a proč, a co je třeba udělat pro přidání nového.
Krátká verze poslední otázky je: definujte to jednou, v programu, který to implementuje. Nic jiného.
Problém, který řeší
Člověku se v tomto repozitáři zodpovídají tři programy:
| Program | Co to je | Kde jsou deklarovány jeho příkazy |
|---|---|---|
| spustitelný soubor v Rustu | apps/majordomus-cli — rozhraní jen pro čtení, generování, introspekce, servery | strom clap v apps/majordomus-cli/src/cli.rs |
| nástroj shell | bin/majordomus — životní cyklus úlohy | share/commands.yaml, sjednoceno s dispečerskou tabulkou nástroje |
| spouštěč workflow | just — co repozitář deklaruje k spuštění člověkem | justfile a .just/*.just |
Před grafem si každý povrch, který chtěl tyto příkazy ukázat, vedl vlastní seznam. justfile nesl recept na příkaz s popisem zkopírovaným z nápovědy příkazu. Web parsoval nápovědu. Dokončování shellu, kdyby je někdo napsal, by nesl čtvrtou kopii. Každý z těch seznamů byl v den, kdy byl napsán, správný.
Graf nahrazuje seznamy jednou kompozicí a sadou projekcí.
flowchart TD
subgraph contributors["contributors"]
clap["clap tree<br/><small>the executable</small>"]
yaml["share/commands.yaml<br/><small>the shell tool</small>"]
dump["just --dump<br/><small>the workflows</small>"]
end
registry["capability registry<br/>capabilities.list"]
commandGraph["CommandGraph<br/>commands.graph"]
fingerprint["fingerprint"]
contributors --> commandGraph
registry --> commandGraph
commandGraph --- fingerprint
commandGraph --> bridge["workflow bridge<br/>majordomus commands bridge"]
commandGraph --> completion["completion<br/>majordomus completion query"]
commandGraph --> api["MCP · HTTP"]
commandGraph --> cockpit["Cockpit"]
commandGraph --> docs["docs"]
Odkazováno z tohoto diagramu (2)
Nic se v grafu neregistruje. Každý uzel je přečten z deklarace, která už existovala a je už autoritou pro to, co uvádí.
Identita
Identita příkazu je <program>.<path joined by dots>:
executable.worktree.status majordomus worktree status
tool.check majordomus check (the shell tool)
workflow.site-build just site-build
Program je součástí identity, protože tyto tři jsou skutečně různé programy, z nichž dva sdílejí jméno na cestě. Identita není nikdy zobrazovaný řetězec: přežije přeformulované shrnutí, přejmenovanou skupinu i přesunutý recept, a právě podle ní klíčuje každá projekce a právě ji rozlišuje commands explain.
Co příkaz nese
| Fakt | Odkud pochází |
|---|---|
| cesta, argumenty, výchozí hodnoty, množiny hodnot, nápověda | deklarace — clap, registr příkazů, výpis runneru |
| účinek: co spuštění mění | schopnost za tím, nebo command_graph/semantics.rs vedle deklarace |
| interaktivita: terminál, dlouhotrvající | totéž |
| požadavky: repozitář, vrstva, úloha, toolchain | totéž |
| odkud pocházejí hodnoty argumentu | vyvozeno nejdřív z deklarace; anotováno jen pro identifikátor, který zná zdejší registr |
| aliasy | vlastní alias clap a aliasy workflow vedle příkazové řádky |
| schopnost, schémata, nástroj MCP, HTTP routa | registr schopností, připojený přes expozici cli příkazu |
| každá projekce | odvozeno command_graph/policy.rs — nikdy deklarováno |
Efekty
read-only reads and answers; changes nothing anywhere
local mutation writes what no commit carries: process memory, .ai/local/, a build directory
repository mutation writes tracked files: generated artifacts, the worktree, git
network mutation reaches the network with an effect on the far side
destructive removes something a person would have to reconstruct
Pořadí je pořadí rostoucího dopadu a politika expozice ho čte.
Který povrch co nese
| efekt / interaktivita | příkazová řádka | most workflow | MCP · HTTP | Cockpit |
|---|---|---|---|---|
| jen pro čtení, neinteraktivní | ano | ano | ano, se schopností za sebou | ano |
| lokální mutace | ano | ano | ano, se schopností za sebou | ano |
| mutace repozitáře / sítě | ano | ano | ne | ne |
| destruktivní | ano | ano, nejprve se zeptá | ne | ne |
| interaktivní | ano | ano | ne | ne |
| dlouhotrvající | ano | ano | ne | ne |
Nic nenastavuje povrch na příkaz. majordomus commands explain <id> vypíše důvod, proč povrch příkaz zadržuje, a důvod je zapsán jednou, v politice.
Most workflow
just je ergonomická přední brána, ne místo, kde se deklarují příkazy. Každý recept mostu je jeden řádek, který spouští kanonický program s argumenty volajícího:
# Where this call is — branch, worktree, canonical or not, uncommitted work — and how many errors the whole topology carries; exit 10 when this worktree is out of place
[group('worktree')]
worktree-status *args:
@"{{majordomus_executable}}" worktree status "$@"
Stojí za to jmenovat tři vlastnosti.
Nemůže to být cyklus. Recept spouští program, nikdy jiný recept, a recept, který napsal sám most, se nikdy nečte zpět jako deklarace — manifest vedle mostu zaznamenává přesně, která jména napsal.
Argumenty se předávají, neinterpolují. Kořenový justfile nastavuje positional-arguments a každé tělo předává "$@". Cesta s mezerou, řetězec v uvozovkách, $(…), zpětný apostrof a úvodní pomlčka přijdou každé jako jediný argument, jak byly zadány. Interpolace {{args}} by je vložila do příkazu shellu a žádné escapování v generátoru to nezajistí.
Není sledován. Žije pod .ai/local/cache/command-graph/, které neobsahuje žádný commit, protože je čistou funkcí stromu, v němž sedí. Vstup do repozitáře ho obnoví, když se změnila některá z deklarací za ním, a když žádná, provede několik volání stat.
Jména
Název receptu je cesta příkazu spojená -: majordomus worktree status se stane just worktree-status. Dvě pravidla řeší kolize, které tento algoritmus může vytvořit.
- Deklarovaný workflow vlastní své jméno. Můstek, který by si jej vzal, je zadržen s chybou pojmenovávající oba.
just benchjsou mikrobenchmarky criterion, deklarované v.just/test.just, a ponechávají si toto jméno. - Dva programy, jedno odvozené jméno: oba jsou kvalifikované.
majordomus benchexistuje v obou programech, takže ani jeden si nenechábench: jsouexecutable-benchatool-bencha graf to říká.
Starší názvy
Každý název receptu, který předcházel mostu, stále funguje. Jsou deklarovány jednou v WORKFLOW_ALIASES vedle příkazové řádky a vykresleny do mostu pod skupinou compatibility s důvodem, proč každý existuje. Alias, který jmenuje příkaz, jenž graf už nenese, shodí build, místo aby ukazoval do prázdna.
Dokončení
Existuje jeden engine doplňování a shellové adaptéry nevědí nic.
flowchart LR shell["zsh / bash"] -->|"words, cursor"| adapter["generic adapter"] adapter --> query["majordomus completion query"] --> engine["CompletionEngine"] engine --- sources["CommandGraph + value sources"]
Adaptér přečte doplňovaná slova, najde kurzor, zeptá se spustitelného souboru a vypíše, co přijde zpět. Nenese žádný příkaz, žádný příznak ani identifikátor — test to tvrdí přesně — takže příkaz přidaný zítra doplňuje adaptér načtený před rokem.
just <TAB> a majordomus <TAB> jsou stejný dotaz s jiným povrchem: název receptu se přeloží zpět na kanonický příkaz a na to, co následuje, odpovídají stejná metadata argumentů. Druhá implementace doplňování, která by se s ní rozcházela, neexistuje.
Nainstalujte jednou pro všechny repozitáře:
majordomus completion install --shell zsh # or --shell bash, --shell fish
To zapíše integraci do startovacího souboru shellu mezi značky # >>> MAJORDOMUS >>>. Nic mimo ně se nečte ani nepřepisuje, opakované spuštění nic nezmění a --remove ji odstraní a nechá soubor, jak byl; --dry-run řekne, co by se změnilo, a nic nezapíše. První zápis ponechá vedle originálu .majordomus.bak.
Je to samostatný příkaz a nic jiného ho nevolá. majordomus init inicializuje vrstvu .ai/ repozitáře a zápis do domovského adresáře člověka jako vedlejší efekt by byl druhým, nevyžádaným činem. Instalace integrace shellu je rozhodnutí, a proto je to příkaz.
Řádek, který zapíše, je ten, který byste napsali ručně:
eval "$(majordomus completion init --shell zsh)"
majordomus, nikoli cesta do adresáře buildu: integrace je obecná a přežije každý jednotlivý checkout. Uvnitř repozitáře .envrc exportuje MAJORDOMUS_COMPLETION_BIN a adaptér se ptá tohoto spustitelného souboru — tak doplňování v tomto repozitáři funguje, kde je jméno majordomus na cestě shellový nástroj a nemá vlastní completion query.
Co neudělá
- Žádná síť. Hodnota, kterou lze zjistit jen vzdáleně, se nenabízí.
- Žádné tajemství. Argument klasifikovaný jako tajemství se nikdy nevyčísluje, nikdy neukládá do cache a nikdy neloguje. Graf se odmítne sestavit, pokud má zdroj hodnot, který by ho vyčíslil.
- Žádná závislost na serveru. Běžící server nic nemění; nic zde žádný nespouští.
- Žádný index. Dokončování nikdy nestaví index repozitáře — index trvá sekundy a odpovídá na otázku o
.ai/, což není otázka, jaké příkazy existují.
Odkud hodnoty pocházejí
Nejdřív odvození: argument s výčtem hodnot nese své vlastní hodnoty, zástupný symbol PATH je cesta, zástupný symbol BRANCH je větev. Jen identifikátor, jehož množina žije zde v registru, je anotován v VALUE_BINDINGS vedle příkazového řádku. Autor příkazu, který argumentu dá typovanou hodnotu, už řekl vše, co doplňování potřebuje.
Vstup do repozitáře
# .envrc
PATH_add bin
watch_file .ai/local/state/mcp/server.json
eval "$(bin/majordomus-env enter --shell direnv)"
Jedno volání, a je to celé vstupování: přiřazení na stdout pro eval, banner na stderr, obnovený most workflow, když se změnila deklarace za ním, a zajištěný sdílený server tohoto repozitáře, když tento checkout nic neobsluhuje. Které z toho stojí za to dělat a kdy lze které přeskočit, je práce nástroje — pravidlo zastaralosti nebo kontrola živosti implementovaná ve vstupním bodě shellu by byla druhou implementací, která běží při každém cd a nic ji netestuje. Pravidla project.envrc-is-an-adapter a project.entry-converges to drží uzavřené a ADR 0043 je rozhodnutí.
Vstup do repozitáře nikdy nic nestaví, nikdy nesahá do vzdálené sítě a nikdy nečeká, až server, který spustil, odpoví: vstup se vrátí a watch_file nad leasem přinese publikovanou adresu, když ji server publikuje. Checkout, který spustitelný soubor ještě nesestavil, vypíše jeden řádek jmenující recept, který jej sestaví, a skončí s 0 — a nezajistí žádný runtime, protože server spuštěný ze zastaralého kódu odpovídá stromem, který už neexistuje.
Přidání příkazu
Do spustitelného souboru v Rustu
- Přidejte větev clap v
apps/majordomus-cli/src/cli.rsa její implementaci podsrc/commands/. - Přidejte jeho příklad do
EXAMPLESvedle deklarace — testy samotného crate jej spustí. - Pokud je to cokoli jiného než jen pro čtení a neinteraktivní, přidejte jednu položku do
SEMANTICSvsrc/command_graph/semantics.rs.
Pak: příkazová řádka, --help, most workflow, shellové doplňování obou povrchů, majordomus commands, /api/v1/commands, nástroje MCP, které graf servírují, Cockpit a generovaná reference — všechno to nese. Žádný jiný soubor se needituje.
Nástroji shellu
Přidejte záznam do share/commands.yaml a větev do dispečerské tabulky v bin/majordomus. Doktrína command_surface_complete obojí sesouhlasí; graf čte registr.
Jako workflow
Napište recept do .just/<context>.just. Runner jej hlásí, graf jej čte a most se jej nedotýká.
Stránky
Stránka příkazu není nový strom stránek. Příkazy každého programu už mají zde referenci, generovanou ze stejných deklarací, které čte graf, a jediné rozhodnutí grafu je, na kterou z nich příkaz odkazuje:
| program | route |
|---|---|
| spustitelný soubor v Rustu | /docs/cli/<path>/ — jedna stránka na příkaz, z klap stromu |
| nástroj shell | /commands/<id>/ — jedna stránka na příkaz, z share/commands.yaml |
| workflow | /docs/commands/ — tato stránka; recept nemá vlastní referenci |
Samotný graf záměrně není commitnutý artefakt. Nese workflow, která hlásí runner, a ta závisí na tom, co je nainstalováno na stroji, který jej sestavil; commitnout jej by znamenalo commitnout stav stroje a nazvat to projekcí. Servíruje se místo toho — přes HTTP, přes MCP a z příkazové řádky — a Cockpit jej vykresluje na /cockpit/commands.
Čtení grafu
majordomus commands # every command, one line each
majordomus commands list --effect read-only # only what changes nothing
majordomus commands show executable.serve # one command, and every surface that carries it
majordomus commands explain executable.serve # and why each surface does or does not
majordomus commands graph --format json # the whole document, fingerprinted
majordomus commands bridge # materialise the workflow bridge
majordomus commands bridge --check # exit 10 when it is stale
Stejný graf nad ostatními povrchy:
GET /api/v1/commands the index, filtered
GET /api/v1/command?id=… one command in full
GET /api/v1/commands/graph the whole document with its diagnostics
majordomus_commands the MCP tool over the first of thoseDiagnostika
Sestavení sbírá nálezy a projekce odmítne zapisovat, dokud je kterýkoli z nich chyba. Kódy jsou stabilní, takže na ně může kontrola párovat.
| kód | co to znamená |
|---|---|
duplicate-command-id | dva příkazy nárokují jednu identitu |
duplicate-workflow-projection | jedno jméno receptu by zapisovaly dva příkazy |
duplicate-mcp-projection | jedno jméno nástroje MCP si nárokují dva příkazy |
workflow-name-collision | deklarovaný workflow vlastní jméno, které můstek chtěl |
workflow-name-qualified | příkazy dvou programů odvodily jedno jméno; obě byla kvalifikována |
capability-names-no-command | schopnost si nárokuje příkazovou řádku, která neexistuje |
semantics-names-no-command | anotace jmenuje příkaz, který už neexistuje |
alias-names-no-command | alias kompatibility ukazuje na nic |
execution-cycle | příkaz promítnutý jako recept se provádí přes runner |
secret-is-suggestible | tajný argument má zdroj hodnot, který by ji vyjmenoval |
Při prvním běhu spojení našlo skutečný případ: schopnost deklarovala, že je dosažitelná jako majordomus scope classify, a příkazová řádka takový příkaz neměla. To je zdokumentovaný příkaz, který neexistoval, a nic jiného v repozitáři by si toho nevšimlo.
Cache
.ai/local/cache/command-graph/ drží most, manifest toho, co bylo zapsáno, a samotný graf. Všechny tři se zapisují atomicky — vykreslí se vedle cíle a poté přejmenují — takže dva shelly vstupující do repozitáře současně nemohou přečíst napůl zapsaný soubor a žádný nepotřebuje zámek.
Dva klíče pro dvě otázky:
- razítko nad velikostí a časem změny deklarací a spustitelného souboru odpovídá na „změnilo se něco?“ několika voláními
statna horké cestě; - otisk nad sémantickým obsahem samotného grafu odpovídá na otázku „je to tentýž graf?“ a podle něj se klíčuje generovaný soubor, cache klienta i kontrola integrity.
V žádném z nich není nic závislého na čase, takže dva buildy téhož stromu se shodují.
Bootstrap
Čerstvý klon nemá žádný most ani program.
flowchart TD clone["clone"] --> entry["direnv, or just"] entry --> absent["the executable is absent:<br>one line naming just build, exit 0"] absent --> build["just build"] build --> bridge["just bridge<br>(or the next cd)"] bridge --> recipes["every command of both programs, as a recipe"]
Kořenový justfile importuje most volitelně, takže klon bez něj má stále justfile: just build a just bridge jsou dva recepty, které most poskytnout nemůže, protože jsou tím, co jej vytváří.
Co to dokazuje
scripts/ci/command-graph | kontrola: graf se sestaví bez chyby a žádný soubor workflow nenese ručně psaný most |
test/cases/100_environment.sh | vstupní bod shellu je adaptér a kontrola může selhat |
test/cases/101_command_graph.sh | graf, most, doplňování, tajné sentinely, vždy jeden repozitář |
test/cases/102_completion_shell.sh | vygenerovaný adaptér, načtený do skutečného zsh, nabízející skutečné kandidáty |
apps/majordomus-cli/benches/commands.rs | cena skládání, promítání a dokončování, měřená, nikoli tvrzená |
apps/majordomus-cli/src/command_graph/ | unit polovina: žádný adaptér nejmenuje příkaz, žádná mutace nedosáhne strojového povrchu, žádný workflow se nepřemostí zpět do workflow, otisk je stabilní |
Měřeno na tomto stroji, macOS arm64. Dvě stupnice, protože odpovídají na různé otázky.
V procesu, release build (cargo bench --bench commands) — kolik engine stojí:
compose the graph, command line only 1.16 ms
compose it with the capability join 1.18 ms
compose it with the shell tool's registry 1.76 ms
render the whole workflow bridge 71 µs
answer one completion 114 ns – 4.4 µs
Od začátku do konce, debug sestavení — na co člověk čeká:
majordomus --help 8.5 ms
completion query (any shape) 14-16 ms
commands bridge, nothing changed 8.8 ms
commands graph, in full 128 ms (two `just` subprocesses)
repository entry, warm 113 ms
the bridge's overhead over a direct call 33 ms
Rozdíl mezi nimi je smyslem. Dokončení odpoví za mikrosekundy a dorazí za čtrnáct milisekund, takže prakticky všechno z toho je start procesu a hledání repozitáře — a proto rychlé načtení nestaví žádný index a nic nespouští, a proto by zchytračení enginu nekoupilo vůbec nic.
Související
CAPABILITIES.md— registr schopností, ke kterému se graf připojujeENVIRONMENT.md— typovaný snímek, který záznam repozitáře vykreslujeDYNAMICITY.md— pravidlo vlastnictví, jehož je toto instancíCLI.md— vlastní specifikace příkazu shellového nástroje