Přeskočit na obsah

Tato stránka byla automaticky přeložena z angličtiny, jediného jazyka, ve kterém se tento web píše. Číst originál.

Graf příkazů

graf příkazů: tři deklarace, které skládá, stabilní identity, model efektů a z něj odvozená politika vystavení, generovaný most workflow a jeho aliasy kompatibility, jediný dokončovací engine, na který se ptá každý povrch, vstup do repozitáře a co stojí přidání příkazu (nic)

Vykresleno z docs/COMMANDS.md — stejného Markdownu, který zobrazuje GitHub.

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:

ProgramCo to jeKde jsou deklarovány jeho příkazy
spustitelný soubor v Rustuapps/majordomus-cli — rozhraní jen pro čtení, generování, introspekce, serverystrom clap v apps/majordomus-cli/src/cli.rs
nástroj shellbin/majordomus — životní cyklus úlohyshare/commands.yaml, sjednoceno s dispečerskou tabulkou nástroje
spouštěč workflowjust — co repozitář deklaruje k spuštění člověkemjustfile 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"]

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

FaktOdkud pochází
cesta, argumenty, výchozí hodnoty, množiny hodnot, nápovědadeklarace — 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, toolchaintotéž
odkud pocházejí hodnoty argumentuvyvozeno nejdřív z deklarace; anotováno jen pro identifikátor, který zná zdejší registr
aliasyvlastní alias clap a aliasy workflow vedle příkazové řádky
schopnost, schémata, nástroj MCP, HTTP routaregistr schopností, připojený přes expozici cli příkazu
každá projekceodvozeno 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 / interaktivitapříkazová řádkamost workflowMCP · HTTPCockpit
jen pro čtení, neinteraktivníanoanoano, se schopností za sebouano
lokální mutaceanoanoano, se schopností za sebouano
mutace repozitáře / sítěanoanonene
destruktivníanoano, nejprve se zeptánene
interaktivníanoanonene
dlouhotrvajícíanoanonene

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 bench jsou mikrobenchmarky criterion, deklarované v .just/test.just, a ponechávají si toto jméno.
  • Dva programy, jedno odvozené jméno: oba jsou kvalifikované. majordomus bench existuje v obou programech, takže ani jeden si nenechá bench: jsou executable-bench a tool-bench a 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

  1. Přidejte větev clap v apps/majordomus-cli/src/cli.rs a její implementaci pod src/commands/.
  2. Přidejte jeho příklad do EXAMPLES vedle deklarace — testy samotného crate jej spustí.
  3. Pokud je to cokoli jiného než jen pro čtení a neinteraktivní, přidejte jednu položku do SEMANTICS v src/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:

programroute
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 those

Diagnostika

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ódco to znamená
duplicate-command-iddva příkazy nárokují jednu identitu
duplicate-workflow-projectionjedno jméno receptu by zapisovaly dva příkazy
duplicate-mcp-projectionjedno jméno nástroje MCP si nárokují dva příkazy
workflow-name-collisiondeklarovaný workflow vlastní jméno, které můstek chtěl
workflow-name-qualifiedpříkazy dvou programů odvodily jedno jméno; obě byla kvalifikována
capability-names-no-commandschopnost si nárokuje příkazovou řádku, která neexistuje
semantics-names-no-commandanotace jmenuje příkaz, který už neexistuje
alias-names-no-commandalias kompatibility ukazuje na nic
execution-cyclepříkaz promítnutý jako recept se provádí přes runner
secret-is-suggestibletajný 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 stat na 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-graphkontrola: graf se sestaví bez chyby a žádný soubor workflow nenese ručně psaný most
test/cases/100_environment.shvstupní bod shellu je adaptér a kontrola může selhat
test/cases/101_command_graph.shgraf, most, doplňování, tajné sentinely, vždy jeden repozitář
test/cases/102_completion_shell.shvygenerovaný adaptér, načtený do skutečného zsh, nabízející skutečné kandidáty
apps/majordomus-cli/benches/commands.rscena 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.

  • CAPABILITIES.md — registr schopností, ke kterému se graf připojuje
  • ENVIRONMENT.md — typovaný snímek, který záznam repozitáře vykresluje
  • DYNAMICITY.md — pravidlo vlastnictví, jehož je toto instancí
  • CLI.md — vlastní specifikace příkazu shellového nástroje

Prohledává názvy a popisy všech stránek, které tento web publikuje.