Majordomus lze snadno špatně pochopit jako nástroj příkazové řádky, HTTP API, server MCP, dashboard a složku pravidel v Markdownu, které se náhodou dodávají společně. Tento dokument vysvětluje, proč je toto čtení chybné a kde je přesto správné. Sleduje fakt od souboru, kde je zapsán, přes index a typovaný registr, které jej drží, přes kontroly, které rozhodují, zda je pravdivý, až ke každému rozhraní, které jej ukazuje — a pojmenovává každé místo, kde repozitář tomuto tvaru zatím nedostává.
Každé tvrzení zde bylo ověřeno proti kódu v commitu, který tento soubor naposledy změnil, a po jednom tvrzení auditováno druhou relací. Kde se kód a návrhový záznam rozcházejí, vítězí kód a rozpor je uveden pod Architecture debt. Čísla se do tohoto dokumentu nepíší: každé je uvedeno jako příkaz, který je měří, protože číslo zkopírované do prózy je zastaralé den po napsání (project.no-counts-in-prose).
Teze
Majordomus by měl fakt jednou objevit a zmodelovat a pak z této kanonické reprezentace odvodit každé relevantní rozhraní.
Ta věta není preferencí opětovného použití kódu. Je to mechanismus proti driftu. Repozitář, na kterém současně pracuje několik lidí a několik AI pracovníků, hromadí popisy sebe sama: seznam příkazů v README, další v textu nápovědy, třetí ve schématu API, čtvrtý v dashboardu, pátý v seznamu nástrojů agenta. Každý je správný v den, kdy vznikl, a každý udržuje ten, kdo si na něj vzpomene. Víc pracovníků a víc rozhraní kopie násobí a agentní vývoj způsobuje, že se kopie rozcházejí rychleji.
Majordomus jde opačným směrem: jeden model, mnoho projekcí. Projekce smí fakt vykreslit jinak, filtrovat ho nebo spojit s jinými. Nesmí o něm mít druhý názor.
Architektura na jednom obrázku
flowchart TD
d1_A["Authored canonical state: rules, ADRs, policy, claims, milestones, issues, capability declarations"]
d1_G["Git and the filesystem"]
d1_R["Runtime: server leases, MCP sessions, mesh datagrams"]
d1_A --> d1_D["Discovery: kinds.yaml + sources.yaml + the capability composition"]
d1_G --> d1_D
d1_D --> d1_I["Object index: typed objects with canonical identity"]
d1_D --> d1_CR["Capability registry: one descriptor per operation"]
d1_I --> d1_CR
d1_CR --> d1_X["One executor: Context::execute"]
d1_R --> d1_O["Observed state: peers, standing, mesh nodes"]
d1_X --> d1_V["Derived state: rule proof, claim evidence, plan status, waves, environment"]
d1_O --> d1_V
d1_V --> d1_P{"Projections"}
d1_P --> d1_CLI["Command line: clap tree checked against the registry"]
d1_P --> d1_MCP["MCP: tools and resources"]
d1_P --> d1_HTTP["HTTP under /api/v1"]
d1_HTTP --> d1_OA["OpenAPI 3.1"]
d1_OA --> d1_SW["Swagger UI"]
d1_P --> d1_CK["Cockpit: server-rendered pages"]
d1_P --> d1_GEN["docs/generated and site data"]
d1_GEN --> d1_SITE["majordomus.dev"]
d1_GEN --> d1_CHK["generate --check, derive-check, projection tests"]
Čtěte od shora. Lidé a pracovníci píší malou sadu kanonických souborů. Objevování je nachází přes deklarace místo ručně vedených seznamů, index dává každému typovanou identitu a registr schopností drží každou operaci, kterou spustitelný soubor umí. Každý povrch se ptá stejného executoru. Odvozený stav — zda je pravidlo prokázáno, jaký je stav úkolu, jaké je prostředí checkoutu — se počítá z kanonických a pozorovaných vstupů; kde se drží kopie (commitnuté projekce, cache prostředí), kontroluje se proti těmto vstupům nebo se z nich znovu staví a nikdy se nepovažuje za zdroj. Generované soubory dole jsou commitnuté a kontrolované, takže rozpor mezi modelem a jeho projekcemi shodí build, místo aby se dostal ke čtenáři.
Dva programy sdílejí jedno jméno
Před modelem jeden fakt, který tvaruje vše níže. Existují dva executables a oba odpovídají na majordomus:
| Program | Spouštěč | Napsáno v | Vlastní |
|---|---|---|---|
| nástroj shell | bin/majordomus s lib/*.sh | POSIX shell a awk | životní cyklus úlohy (start, check, finish), handover, context, zachycení relace, doctor, dispatch doktrín, engine plánu |
| spustitelný soubor v Rustu | bin/majordomus-cli | Rust, apps/majordomus-cli/ | registr schopností, serve, mcp, HTTP, OpenAPI, Swagger UI, Cockpit, generate, peeři, mesh, prostředí, worktrees, důkaz pravidla, důkazy, release |
Shellový nástroj odmítne příkaz, který nezná, a když ho docs/generated/cli.yaml — generovaný popis stromu příkazů v Rustu — vypisuje, jmenuje launcher, který spustit místo něj; nepředává ho dál. Obojí konverguje na straně Rustu (ADR 0047 a ADR 0052 popisují přechod relací; obě jsou stále navržené) a některé domény už mají čtečku v Rustu držené na bajtové shodě se zapisovatelem v shellu — plán je nejjasnější případ. Zde popsaná architektura plně platí o spustitelném souboru v Rustu a částečně o shellovém nástroji; rozdíl je zaznamenán tam, kde záleží.
Šest druhů stavu
Každou hodnotu, kterou Majordomus ukazuje, lze zařadit do jednoho z těchto druhů. Druh rozhoduje, kdo ji smí zapsat a zda může někdy přepsat něco jiného.
| Druh | Příklady v tomto repozitáři | Kdo to vytváří | Kdo to mění | Autorita | Smí přepsat kanonický stav | Zneplatněno |
|---|---|---|---|---|---|---|
| Autorsky kanonické | pravidla pod .ai/repo/rules/, ADR pod .ai/repo/adrs/, .ai/repo/policy.yaml, docs/CLAIMS.yaml, milníky a úkoly pod .ai/repo/project/, deklarace capability!, share/design/tokens.yaml | člověk nebo worker, v commitu | totéž, v posouzeném commitu | nejvyšší: je to zdroj | nelze použít | nový commit |
| Objeveno | index objektů, složení modulů, výpis worktree gitu, sada sledovaných souborů | spustitelný soubor, čtoucí autoritativní struktury | nikdo: čte se znovu | přesně jako u jeho zdroje | nikdy | změna zdroje |
| Odvozeno | stav důkazu pravidla, stav důkazů tvrzení, stav a vlny úkolů, snímek prostředí, minimální verze release, vše pod docs/generated/ | deterministická funkce kanonických a objevených vstupů | nikdo ručně; generátor to přepisuje | žádné vlastní: je to pohled | nikdy; generate --check odmítne ruční úpravu | jakákoli změna vstupu |
| Pozorováno | připojení peeři, postavení serveru (ready, outdated, stale), přítomnost uzlu meshe, odpovídající port služby, špinavý pracovní strom | sonda v určitém okamžiku | další sonda | pravda jen v okamžiku své časové značky | nikdy | čas: TTL, odpojení, další sonda |
| Odvozeno | skóre relevance intent při kompilaci vývojového kontextu | heuristika | heuristika | poradní, řazeno pod každou deklarovanou relaci | nikdy | změna vstupů |
| Lokální kontinuita | předávky, kontrolní body, aktivní úloha, otevřená epizoda, účetní kniha v .ai/local/ | shellový nástroj jménem pracovníka | převážně jen přidávání, pouze přes příkazy | důkaz toho, co pracovník udělal, ne toho, co platí nyní | nikdy; zastaralá předávka se ukazuje jako historie | stáří a vzdálenost v gitu |
Většinu váhy nesou dvě rozlišení.
Objevování není odvozování. Objevování znamená, že informace už někde autoritativně existuje a Majordomus ji najde: soubor pravidla odpovídající pathspecu, modul pojmenovaný v kompozici, worktree uvedený gitem. Odvozování znamená, že Majordomus navrhne pravděpodobný výklad. Jediné odvozování v kompilátoru kontextu je relevance podle klíčových slov a je omezeno pod přímou deklaraci — drží to test an_inference_is_never_as_confident_as_a_declaration — ne však pod každý vztah dosažený slabými nebo vícekrokovými hranami (viz Kontext pro relaci).
Pozorované není kanonické. To, že je peer online, není deklarace, kterou někdo učinil; je to současná realita a vyprší. Nic z nástěnky peerů ani z registru meshe se neukládá, jako by to byl fakt o repozitáři.
Zjišťování
Majordomus raději hledá fakta o repozitáři ve strukturách, které je už vlastní, než aby držel paralelní registry. Zdroje, které skutečně čte:
| Zdroj | Co se objevuje | Kde |
|---|---|---|
share/kinds.yaml | druhy dokumentů, které distribuce definuje: formát, identita schématu, pole identity, pole titulku | načteno indexem |
kinds.yaml vedle sources.yaml | druhy, které repozitář přidává, pokud nějaké má (nesmí předefinovat druhy distribuce) | stejné |
.ai/repo/knowledge/sources.yaml | které pathspecy gitu drží objekty kterého druhu | stejné |
.ai/manifest.yaml | který adresář .ai/ drží kterou sekci a které jsou nesledované | shellový nástroj a spustitelný soubor |
| git | sledované soubory, worktrees, větve, HEAD, společný adresář gitu | apps/majordomus-cli/src/worktree/, lib/common.sh |
| složení schopností | každá spustitelná operace | apps/majordomus-cli/src/capability/builtin/mod.rs |
| strom clap | příkazová řádka tak, jak je napsána | apps/majordomus-cli/src/cli.rs |
share/commands.yaml a výpis receptů just | příkazy nástroje shellu a recepty workflow | graf příkazů |
.ai/repo/ci/gates.yaml | kontroly, třídy cest a co každá kontrola spouští | scripts/ci-plan, důkaz pravidla |
soubory lease pod .ai/local/state/mcp/ | který checkout má živý server a na jaké URL | apps/majordomus-cli/src/lease.rs |
| UDP multicast, broadcast, rendezvous (ve výchozím stavu vypnuto) | další uzly Majordomus | apps/majordomus-cli/src/mesh/ |
index docs/README.md | které dokumenty jsou zveřejněny a v jakém pořadí | scripts/generate-site-data |
Objevování je explicitní tam, kde mohlo být magické. Neexistuje žádný soupis při linkování ani build skript skenující zdrojové soubory: ADR 0004 obojí odmítá, takže složení modulů je obyčejný výraz v Rustu, který si čtenář může otevřít. Ta volba má cenu — přidání modulu znamená úpravu tohoto složení — zaznamenanou pod Architektonický dluh.
Index se v procesu sestaví jednou z těchto deklarací (apps/majordomus-cli/src/index.rs). Co drží v tomto checkoutu, uvidíte:
$ bin/majordomus-cli serve ensure
$ curl -s 'http://127.0.0.1:8741/api/v1/objects?kind=rule' | jq .
$ curl -s http://127.0.0.1:8741/api/v1/repository | jq .
Sdílený server checkoutu naslouchá na výchozím portu, pokud není obsazený, a bin/majordomus-cli serve status vypíše URL, kterou skutečně drží.
Identita
Zobrazované jméno je pro čtenáře. Kanonická identita je pro každou relaci. Majordomus nikdy nespojuje dvě věci podle jejich titulků.
| Entita | Kanonická identita | Příklad |
|---|---|---|
| schopnost | tečkované id, s jmenným prostorem podle jeho modulu | rules.show |
| indexovaný objekt | majordomus://<kind>/<identity> | majordomus://rule/majordomus.scope-integrity@1 |
| indexovaný objekt jako schopnost | <kind>.<identity> | rule.majordomus.scope-integrity@1 |
| pravidlo | id plus version, nikdy název souboru | project.derived-once ve verzi 1 |
| tvrzení | jeho id v docs/CLAIMS.yaml | scope-enforcement |
| test v knize důkazů | jeho runner a název, se zdrojovou cestou vedle | suite:04_start_check (zdroj test/cases/04_start_check.sh) |
| peer na nástěnce | pozice, p1, p2, přiřazená znovu při opětovném připojení; checkout, který nese, je trvalá polovina | p7 ve worktree prismatic-majordomus-wt/feature/x |
| uzel meshe | digest jeho veřejného klíče Ed25519 | uchováno v ~/.local/state/majordomus/node.json |
| worktree | odvozeno z názvu větve: <repository>-wt/<branch> | prismatic-majordomus-wt/docs/how-majordomus-is-derived |
Identita je to, co činí řetězec pravidlo, validátor, test, provedení, důkaz strojově spojitelným. Pravidlo jmenuje své testy cestou; engine důkazů váže tyto cesty ke kontrolám podle toho, co kontroly spouštějí; kniha důkazů zaznamenává provedení podle identity testu a commitu. Žádný krok neshoduje text.
Schémata
Existují dva řetězce schémat, jeden pro každý druh věci, a žádný se nepíše dvakrát.
Spustitelné operace. Vstup a výstup schopnosti jsou běžné typy Rustu, které odvozují schemars::JsonSchema. CanonicalSchema::of::<T> převede typ na jednu hodnotu JSON Schema 2020-12 (apps/majordomus-cli/src/capability/schema.rs) a ta se vykresluje čtyřmi způsoby: inline pro MCP (for_mcp), jako komponenty OpenAPI (for_openapi), jako formulář runneru Cockpitu a do docs/generated/registry.json. Parametry dotazu HTTP se převádějí přes totéž schéma. Žádné schéma schopnosti není ručně udržovaný dokument — není tu rozhraní TypeScript ani samostatná definice Swagger — přestože jeden typ Rustu, design::Ordered<T> (seřazená mapa), implementuje JsonSchema ručně, ne derivací.
flowchart LR d2_T["Rust type with derive JsonSchema"] --> d2_S["CanonicalSchema"] d2_S --> d2_M["MCP inputSchema and outputSchema"] d2_S --> d2_O["OpenAPI components"] d2_S --> d2_F["Cockpit runner form"] d2_S --> d2_J["docs/generated/registry.json"] d2_S --> d2_Q["HTTP query coercion"]
Dokumenty repozitáře. Každý druh deklarovaný v share/kinds.yaml jmenuje identitu schématu tvaru <vendor>.<name>/v<n>. Schémata žijí pod share/schemas/majordomus/<kind>/. Většina druhů v Markdownu — pravidla, ADR, dovednosti, prompty, kontextové dokumenty a další (ls share/schemas/majordomus/*/*.proto) — se píše jako zprávy protobuf a jejich JSON Schema se z nich odvozuje; ostatní druhy se píší přímo jako JSON Schema. Hlavička pravidla je například uzavřená zpráva v share/schemas/majordomus/rule/rule.v1.proto, a proto se neznámý klíč front-matteru v pravidle odmítne, místo aby se tiše ponechal.
Generované artefakty mají také schémata, pod share/schemas/generated/. Před zápisem generate zkontroluje každý artefakt na banner původu a každý strukturovaný dokument, který deklaruje kontrakt, proti jeho schématu.
Schopnost: jedna deklarace
Každá operace Rust programu se deklaruje jednou, makrem capability! (apps/majordomus-cli/src/capability/handler.rs). Toto je skutečná deklarace operace, která vysvětluje důkaz jednoho pravidla, z apps/majordomus-cli/src/capability/builtin/rules.rs (popis zkrácen):
capability! {
id: "rules.show",
title: "What proves this rule",
description: "One rule with its full proof: ...",
input: RuleInput,
output: RuleDetail,
stability: Stability::BehaviorallyVerified,
exposure: Exposure {
mcp: mcp("majordomus_rule"),
http: get("/api/v1/rules/rule"),
cli: Some(CliExposure { path: vec!["rules".into(), "show".into()] }),
},
tags: ["rules", "governance", "verification", "evidence"],
cache: CachePolicy::Disabled,
handler: show,
},
Co deklarace uvádí a co makro doplní samo:
| Deklarováno autorem | Klasifikováno nebo označeno, nikdy deklarováno |
|---|---|
id, title, description | module, opatřeno razítkem module! při skládání modulu |
kind (ve výchozím stavu Query, nebo Command, Resource) | provenance, z module_path!() |
typy input a output | availability, visibility, execution, klasifikováno podle druhu a expozice |
stability | případy měření převzaté z implementace BenchmarkCases vstupního typu |
exposure pro MCP, HTTP a příkazovou řádku | zda zapisuje do repozitáře: výslovný souhlas přes .writes_repository(), připnuto unit testem the_capabilities_that_write_the_repository_are_these v capability/builtin/mod.rs na množinu, kterou uvádí |
tags, cache, benchmark, handler |
Dvě vlastnosti vynucuje překladač, nikoli revize: vstupní typ, který neimplementuje BenchmarkCases, se nepřeloží — zda se operace poté měří, určuje její deklarovaná BenchmarkPolicy (vyžadovaná, nebo prominutá s typovaným důvodem), kterou ukazuje report pokrytí; a handler, jehož signatura neodpovídá deklarovaným typům, se nepřeloží.
Registr
Moduly skládají schopnosti pomocí module!; compose_modules! skládá moduly; aplikace sestaví registr pomocí CapabilityRegistry::builder().with_modules(builtin::modules()).with_index(&index). Druhé volání je místo, kde se objevování setkává s rovinou schopností: každý indexovaný objekt se stane schopností Resource (apps/majordomus-cli/src/capability/declarative.rs), čitelnou přes MCP jako majordomus://<kind>/<identity>, takže nový soubor s pravidlem si agent přečte bez jediného řádku v Rustu.
build() validuje celou množinu a sbírá každou chybu místo zastavení u první (apps/majordomus-cli/src/capability/registry.rs): gramatiku id, jmenný prostor shodný s modulem, duplicitní nástroj MCP, duplicitní trasu HTTP, duplicitní cestu příkazu, chybně utvořené vystavení HTTP, neplatnou politiku cache. Registr, který by vystavil dvě operace na jedné trase, nelze sestavit.
Exekutor je jeden. Context::execute (apps/majordomus-cli/src/capability/executor.rs) je jediný volající dispatche registru. Příkazová řádka, HTTP, MCP i Cockpit jdou přes něj, což činí „stejnou operaci na každém povrchu“ vlastností kódu, ne slibem.
Prohlédnout registr tohoto checkoutu:
$ jq '.capabilities | length' docs/generated/registry.json
$ jq -r '.capabilities[] | [.id, .kind, .stability] | @tsv' docs/generated/registry.json
$ bin/majordomus-cli capabilities describe rules.show
$ bin/majordomus-cli capabilities validateProjekce
HTTP
Neexistuje tabulka tras. Router se ptá registru: Router::capability v apps/majordomus-cli/src/http/router.rs volá registry.by_http(method, path), odpoví 405, když sedí jiná metoda, a 404, když nesedí nic, naváže query parametry GET přes vstupní schéma nebo vezme JSON tělo POST a volá Context::execute. Každá HTTP expozice je vynucena pod /api/v1/ přes HttpExposure::PREFIX. Chyby se mapují na 400, 404, 422 a 500 na jednom místě.
Nekapacitní mounty — obsluhovaná domovská stránka, /openapi.json, /swagger, /cockpit, /mcp, proud událostí, /docs/, /rustdoc — jsou deklarovány jednou v zjišťování webových povrchů (apps/majordomus-cli/src/web/; docs/generated/web.json je vypíše), které popisuje docs/WEB.md. Nová operace nepotřebuje vůbec žádný kód HTTP: rules.show nemá v routeru žádný handler, jen generický dispatch.
Ručně se píše obchodní logika za handlerem — apps/majordomus-cli/src/rules/ pro důkaz pravidla — nikdy metadata trasy.
OpenAPI
apps/majordomus-cli/src/http/openapi.rs projde registr a vytvoří dokument OpenAPI 3.1. operationId je id schopnosti, schémata jsou kanonická schémata jako komponenty, příklady jsou případy měření výkonu a rozšíření x-majordomus-* nesou druh a identitu. Je poskytován živě na /openapi.json ze stejného registru, který obsluhuje požadavky, a commitnut jako docs/generated/openapi.json, aby byla změna kontraktu vidět při review. Jedna odpověď zatím není odvozena věrně: dokument připojuje odpověď 422 refused jen k příkazům, ačkoli některé dotazy mohou také odmítnout a router jim přesto odpovídá 422.
OpenAPI je odvozeno z týchž smluv, které obsluhují skutečné požadavky API. Není to druhá dokumentace, kterou je třeba držet v souladu.
Swagger UI
Swagger UI na /swagger je pouze vykreslovač /openapi.json a nic víc (apps/majordomus-cli/src/http/swagger.rs). Není zdrojem pravdy, nedrží žádné definice a nemůže s API nesouhlasit, protože nemá nic vlastního, s čím by nesouhlasil. Jeho assety pro prohlížeč jsou připnuty na jednu verzi a načítají se z CDN — jediná část lokálního povrchu, která nefunguje offline, a modul to říká.
MCP
MCP je projekce téhož registru pro agenty (apps/majordomus-cli/src/mcp/surface.rs):
- Nástroje jsou každá schopnost, jejíž expozice jmenuje nástroj.
inputSchemaaoutputSchemapocházejí z kanonického schématu; nápověda read-only pochází z druhu. Nápovědy destructive a idempotent zatím nepocházejí z deklarovaného účinku: jsou jednou zapsány vmcp/protocol.rspro každý nástroj (viz Architektonický dluh). - Zdroje jsou každá schopnost, jejíž expozice jmenuje zdroj, plus každý indexovaný objekt jako
majordomus://<kind>/<identity>, čtené stejným řešením objektů, jaké používá HTTP endpoint objektů. - Volání nástroje se vyřeší pomocí
registry.by_mcp_toola spustíContext::execute. - Instrukce, které klient čte na
initialize, jmenují nástroje, jež zapisují do repozitáře, změřené z deklarovaného účinku každé schopnosti, a OpenAPI publikuje stejný účinek jakox-majordomus-effect;every_surface_names_what_writes_the_repository_and_nothing_elsevapps/majordomus-cli/tests/shared_units.rsdrží obojí na registru. - Prompty se neinzerují a šablony zdrojů jsou prázdné — záměrně, ne opomenutím.
Žádný nástroj MCP není psán ručně. majordomus_announce, který vypadá jako zvláštní koordinační nástroj, je běžná schopnost peers.announce. Jediné ručně kódované chování je v mostu MCP (apps/majordomus-cli/src/mcp/bridge.rs), který tento nástroj rozpozná, aby mohl po opětovném připojení přehrát oznámení klienta na nový server.
Příkazová řádka: kontrolovaná druhá deklarace
Tady je model k sobě upřímný. Příkazová řádka není generována z registru. Strom clap v apps/majordomus-cli/src/cli.rs je psán ručně, odesílán ručně psaným matchem a vykreslován textovými funkcemi v každém modulu příkazu. Zdroj to říká: apps/majordomus-cli/src/capability/closure.rs uvádí, že příkazová řádka „je deklarována podruhé, v clap“.
To, co brání tomu, aby se ta druhá deklarace rozešla, je, že se kontroluje v obou směrech:
- Od deklarace k přítomnosti. Schopnost, jejíž
CliExposurepojmenovává cestu, která ve stromu clap neexistuje nebo existuje, ale nelze ji spustit, selže vclosure.rsa v testu projekce. - Přítomné k deklarovanému. Každý příkaz clap, který nevykresluje schopnost, musí figurovat v
cli::LOCAL(apps/majordomus-cli/src/cli/local.rs) s typovaným důvodem — vykresluje schopnost, zapisuje repozitář, je alias, je lokální pro relaci, nebo spravuje proces.quality::paritykontroluje seznam proti stromu oběma směry ascripts/ci/projection-checkselže u příkazu bez důvodu. - Stejný executor. Příkaz, který vykresluje schopnost, volá
ctx.execute(id, input); jeho vlastní kód je jen prezentace (report_text,show_textvapps/majordomus-cli/src/commands/rules.rs) a--format jsonvypíše hodnotu schopnosti beze změny.
V praxi se cesta příkazu píše třikrát: ve strukturách clap, v CliExposure schopnosti a jako doslovná slova, která modul příkazu předá registry.by_cli, aby našel svou schopnost. Výše uvedené kontroly drží tyto tři v souladu; neudělají z nich jedno. Ne každý spustitelný příkaz je projekcí schopnosti — mnoho z nich jsou položky LOCAL, které vykreslují sdílenou doménovou logiku, zapisují do repozitáře, aliasují jiný příkaz nebo spravují proces. Rozdělení změřte, nevěřte zde napsanému číslu:
$ jq '[.. | objects | select(.executable? == true)] | length' docs/generated/cli.json
$ jq '[.capabilities[] | select(.exposure.cli)] | length' docs/generated/registry.json
Vedle ručně vykreslených příkazů existuje generický a je odvozený. majordomus-cli run <capability-id> [--input JSON] (apps/majordomus-cli/src/commands/executions.rs) provede jakoukoli registrovanou schopnost tímtéž executorem a vypíše její hodnotu — protějšek runneru Cockpitu v příkazové řádce. Každá schopnost je tedy dosažitelná z příkazové řádky; vyhrazený příkaz s vlastními slovy a lidským rendererem existuje jen tam, kde pro něj byl napsán příkaz clap. Indexované objekty se čtou stejně, přes entity kinds a entity show (schopnosti entity.kinds a entity.show, také přes HTTP a MCP), nebo přes run objects.list.
$ bin/majordomus-cli run plan.status --format json
$ bin/majordomus-cli run peers.list --format json
$ bin/majordomus-cli entity show <uri>
Text nápovědy je z clap. Doplňování shellu z clap není: majordomus completion odpovídá z grafu příkazů, který skládá strom clap, share/commands.yaml pro nástroj shellu a výpis receptů just (ADR 0027, docs/COMMANDS.md). Reference příkazů na webu, /docs/cli/, se generuje z docs/generated/cli.json, které se samo generuje ze stromu clap — takže reference nemůže uvést příkaz, který program nemá.
flowchart TD d3_CAP["capability! declaration with CliExposure"] --> d3_CL["closure check: path exists and runs"] d3_CLAP["clap tree in cli.rs"] --> d3_CL d3_CLAP --> d3_LOC["cli::LOCAL reasons for non-capability commands"] d3_LOC --> d3_PAR["quality::parity both directions"] d3_CLAP --> d3_CJ["docs/generated/cli.json"] d3_CJ --> d3_REF["/docs/cli/ reference pages"] d3_CLAP --> d3_CG["command graph"] d3_SC["share/commands.yaml"] --> d3_CG d3_JU["just recipes"] --> d3_CG d3_CG --> d3_COMP["completion"]
Cockpit
Cockpit není další aplikace, databáze ani doménový model. ADR 0012 jej nazývá projekcí registru pro člověka a kód to na úrovni dat dodržuje: data, která ukazuje každá stránka, procházejí přes Context::execute (ask() v apps/majordomus-cli/src/cockpit/pages.rs) a nedělá žádné vlastní objevování. Stránka mesh vykresluje mesh.status a mesh.nodes a nedrží žádný seznam uzlů (project.mesh-is-observation-not-authority); pohled peers vykresluje peers.list.
Je to server-rendered Rust bez šablonovacího enginu: typovaný strom HTML (apps/majordomus-cli/src/cockpit/html.rs), komponenty v view.rs a prohlížečové knihovny vendorované jako progresivní vylepšení. Jeho barvy, písmo a stavová slova jsou projekcemi share/design/tokens.yaml (ADR 0036), generovanými do stylopisu, který stránky používají.
Co se odvozuje a co se píše:
| Část | Jak existuje |
|---|---|
průzkumník a spouštěč schopností na /cockpit/capabilities/<id> | generické: jedna stránka pro každou schopnost; formulář runneru, generovaný ze vstupního schématu s příklady z případů měření výkonu, pro každou schopnost vystavenou přes HTTP, jejíž stabilita spuštění dovoluje; rules.show nemá žádný kód stránky |
prohlížeč objektů na /cockpit/objects?kind=<kind> a /cockpit/object?uri=<uri> | obecné: každý indexovaný druh, včetně pravidel, ADR a tvrzení |
| navigační katalogy | odvozeno z modulů registru, druhů indexu a odvození grafů, seskupeno podle oblastí produktového modelu a kanonicky seřazeno |
| oblasti nejvyšší úrovně a jejich trasy | ručně psáno: match v apps/majordomus-cli/src/cockpit/mod.rs a seznam oblastí v nav.rs |
| specializované stránky (release, design, mesh, worktrees, kontinuita) | ručně psané pohledy nad typovanými odpověďmi schopností |
Proto neexistuje trasa /cockpit/rules/<id>. Pravidlo se prohlíží na svém URI objektu a jeho důkaz spuštěním rules.show v runneru. Každá kanonická entita je prohlédnutelná; ne každý druh má vlastní stránku.
Dokumentace a web
Ke čtenáři se dostanou tři vygenerované vrstvy a každá vzniká z kanonického zdroje pojmenovaným generátorem a kontroluje se na drift:
| Výstup | Zdroj | Generátor | Kontrola driftu |
|---|---|---|---|
docs/generated/ — registr, OpenAPI, reference příkazů, reference schopností, měření výkonu, changelog, design, manifest artefaktů, graf | registr, index, designové tokeny, záznamy release a historie gitu | majordomus generate | majordomus generate --check, bajt po bajtu |
projekce site/data/generated/ a site/content/ — stránky dokumentace, záruky, doktríny, příkazy, stránky registru, stav plánu | docs/*.md, docs/CLAIMS.yaml, pravidla, share/commands.yaml, .ai/repo/project/, generovaný registr | scripts/generate-site-data | scripts/generate-site-data --check |
site/public/ | vše výše | Zola přes scripts/site-build | scripts/site-check, poté ověření publikace |
scripts/derive spustí celý graf popořadě (generování, data webu, generování znovu, protože dokumenty jsou indexované objekty, pak .gitattributes) a scripts/derive-check jmenuje každý zastaralý soubor. Manifest artefaktů docs/generated/artifacts.md vypisuje každý soubor, který majordomus generate zapisuje, s jeho schématem, pokud ho má, a zdrojem, a sám je generován; výstupy generátoru webu v něm nejsou.
Tento dokument je příklad. Píše se jednou, zde. scripts/generate-site-data ho najde přes jeho řádek v docs/README.md — každý Markdown nebo YAML soubor nejvyšší úrovně v docs/ musí mít řádek v jedné z tabulek indexu, jinak generování selže — zapíše site/content/docs/how-it-works.md s generovaným front matter (titul z prvního nadpisu, popis z řádku indexu, pořadí z pozice řádku), přepíše jeho relativní odkazy na routes webu a převede jeho bloky mermaid na vykreslené diagramy. Stránka dokumentace je commitnuta a drží se zdroje stejnou --check.
Porovnané povrchy
| Povrch | Konzument | Účel | Odvozeno z | Psáno ručně | Formát |
|---|---|---|---|---|---|
| HTTP | software | programová operace | registr (trasy, vazba, dispečink) | pouze business logika | JSON pod /api/v1 |
| OpenAPI | integrátoři, generátory | kontrakt | registr a kanonická schémata | nic | OpenAPI 3.1 JSON |
| Swagger UI | člověk zkoumající API | interaktivní smlouva | /openapi.json | nic | HTML |
| MCP | AI pracovníci | nástroje a zdroje | registr a index objektů | přehrání oznámení po opětovném připojení | JSON-RPC |
| Příkazová řádka | lidé a skripty | interaktivní operace | kontrolováno proti registru; vykresluje hodnoty schopností | strom clap, textové renderery, cli::LOCAL | text terminálu nebo --format json |
| Cockpit | lidé | viditelnost a běžící operace | odpovědi schopností; katalogy z registru a indexu | seznam oblastí, routes, specializované pohledy | HTML |
| Generované dokumenty a web | čtenáři | reference a vysvětlení | registr, index, docs/ | vysvětlující próza | Markdown, JSON, HTML |
Jsou to rozhraní nad toutéž skutečností, ne její nezávislé implementace. Rozdíly jsou prezentace a místa, kde je prezentace stále psána ručně, jsou místa, která kontroly sledují.
Generátor a renderer
Generátor rozhoduje, co existuje: které entity, jejich vztahy, jejich pořadí, jejich metadata. Renderer rozhoduje jen o tom, jak to vypadá. Důkaz pravidla ukazuje toto rozdělení:
flowchart TD d4_RF["rule files"] --> d4_IDX["object index"] d4_GY[".ai/repo/ci/gates.yaml"] --> d4_ENG["rules engine: apps/majordomus-cli/src/rules"] d4_IDX --> d4_ENG d4_LED[".ai/repo/evidence/ledger.json"] --> d4_ENG d4_ENG --> d4_RD["RuleDetail value"] d4_RD --> d4_T1["text renderer: rules show"] d4_RD --> d4_T2["JSON: rules show --format json and GET /api/v1/rules/rule"] d4_RD --> d4_T3["MCP tool majordomus_rule"] d4_RD --> d4_T4["Cockpit runner"]
Žádný renderer nepočítá, zda je pravidlo dokázáno. Frontend není autoritou nad sémantikou repozitáře: Cockpit neodvozuje vztahy pravidel, připravenost úkolů ani stav vynucování, protože engine, který každé z nich vlastní, už odpovídá.
Routy, navigace a pořadí
Které trasy a nabídky jsou odvozeny a které jsou deklarovány záměrně:
| Povrch | Trasy | Navigace | Jak se udržuje pravdivé |
|---|---|---|---|
| HTTP | jedna na expozici schopnosti, nalezená registry.by_http v době požadavku; nic neregistruje trasu | GET /api/v1/ vypíše každou vystavenou schopnost | registr odmítne duplicitní trasu |
| OpenAPI | jedna cesta na HTTP expozici | tagy z jmenného prostoru schopností | test projekce porovnává každou expozici s její operací |
| MCP | jeden nástroj nebo zdroj na expozici plus jeden zdroj na indexovaný objekt | tools/list, resources/list | test projekce; jedinečnost v registru |
| Cockpit | obecné stránky pro každou schopnost a každý objekt; trasy oblastí jsou ručně psaný seznam a shodují se | seznam oblastí psaný ručně; katalogy uvnitř každé oblasti odvozené z registru, indexu a modelu produktu | testy v cockpit/mod.rs drží seznam oblastí, statické trasy a dispatcher v rovnosti |
| web | jedna stránka na odvozený objekt, který projekce publikuje — funkce, tvrzení (jako záruky), doktríny, pravidla, ADR, příkazy, schopnosti, případy užití | site/data/nav.toml, deklarováno jednou záměrně: navbar je redakční, sitemap ne | scripts/ci/nav-check a site-check: každý href se vyřeší, žádný href se neopakuje, každá publikovaná sekce je dosažitelná |
| servírovaná domovská stránka | připojení runtimu, z webové topologie | z vyřešené topologie | web::discover a seznam vyhrazených cest |
Pořadí je smlouva, ne náhoda. Generované seznamy se řadí podle klíče crate::order — skupina, pak pořadí, pak štítek, pak kanonická identita (ADR 0025) — takže projekce uvádí tytéž entity ve stejném pořadí při každém běhu a na každém povrchu; shellové generátory řadí pomocí LC_ALL=C. scripts/ci/order-check odmítne ručně napsané řazení podle locale a zpřísňuje zbývající ad hoc místa řazení a testy determinismu generují dvakrát a porovnávají bajty.
Jak se předchází odchylkám
Generování samo drift nezabrání; generátor, který nikdo znovu nespouští, je zastaralá kopie se skriptem vedle. Zabrání mu to, že se každá projekce kontroluje proti svému zdroji.
| Invariant | Mechanismus | Kde běží |
|---|---|---|
| každá deklarovaná projekce existuje a žádná projekce nemá chybějící deklaraci | every_declared_projection_exists_and_no_projection_is_an_orphan v apps/majordomus-cli/tests/projections.rs: každý nástroj MCP má id, schéma a popis schopnosti; každé vystavení přes HTTP má operaci OpenAPI se stejným id; každá cesta příkazu existuje a běží; žádný osiřelý nástroj, zdroj ani operace; každé $ref se vyřeší | sada testů crate v CI |
| změna kanonického typu dosáhne každé projekce | a_change_to_the_canonical_type_or_description_reaches_every_projection: výměna vstupního typu změní vlastnosti MCP, parametry OpenAPI i referenci dohromady; odstranění vystavení HTTP odstraní cestu a ponechá nástroj | stejné |
| generovaný výstup je deterministický a nenese cestu stroje | generated_artifacts_are_byte_identical_twice_and_carry_no_absolute_path a test trasování artefaktů | stejné |
| commitnuté generované soubory se rovnají čerstvé generaci | majordomus generate --check, scripts/generate-site-data --check, scripts/derive-check | scripts/rust-check a job site v CI; scripts/pages current v háčku pre-commit |
| povrchy schopností se shodují od začátku do konce na skutečné binárce | test/cases/76_capabilities_projections.sh: capabilities validate, jedna schopnost porovnaná napříč svými metadaty MCP, operací OpenAPI a generovanou referencí, počty porovnané oběma směry, generate --check selhávající po zásahu, nový druh dokumentu přidaný jen daty | shellová sada |
| každý příkaz má důvod existovat i mimo registr | scripts/ci/projection-check, quality::parity | CI |
| graf příkazů je jediný zdroj doplňování a referencí | scripts/ci/command-graph, test/cases/101_command_graph.sh | CI |
| generovaný soubor se needituje ručně | hlavička „GENERATED FILE — DO NOT EDIT DIRECTLY“ plus bytové porovnání; project.derived-files-regenerated | pre-commit a CI |
Determinismus je požadavek, ne hezká vlastnost: projekce, která řadí své položky při dvou během různě, dělá z každé regenerace diff a z každé kontroly driftu šum. Generované výstupy se řadí podle kanonické identity v rámci sémantických skupin (crate::order ve spustitelném souboru; řazení v C-locale v shellových generátorech) a testy determinismu generují dvakrát a porovnávají bajty.
Jedna schopnost přes každý povrch
rules.show, od deklarace po důkazy. Poslední sloupec je smysl: téměř nic po deklaraci se nepíše na schopnost zvlášť.
| Krok | Soubor nebo URL | Psaný ručně, nebo odvozený |
|---|---|---|
| deklarace | apps/majordomus-cli/src/capability/builtin/rules.rs | ručně psané |
| vstupní typ a jeho případy měření | RuleInput ve stejném souboru | ručně psané |
| doménová logika | apps/majordomus-cli/src/rules/ | ručně psané |
| kompozice | modul rules v builtin::modules() | autorské, dva existující řádky: pub mod a položka compose_modules! |
| validace registru | CapabilityRegistry::build | automaticky |
| HTTP routa | GET /api/v1/rules/rule?rule=<id> přes generický router | automaticky |
Operace OpenAPI rules.show | /openapi.json, docs/generated/openapi.json | vygenerováno |
| Vstup do Swagger UI | /swagger | vykresleno |
Nástroj MCP majordomus_rule | mcp/surface.rs, obecné | automaticky |
| runner Cockpitu | /cockpit/capabilities/rules.show, formulář ze schématu | automaticky |
příkaz majordomus-cli rules show <id> | varianta clap v cli.rs, dispatch a textový renderer v commands/rules.rs, spustitelný příklad v cli.rs | psáno ručně, pak kontrolováno uzávěrem a paritou |
| referenční dokumentace | docs/generated/capabilities.md, docs/generated/modules/rules.md, docs/generated/cli.md | vygenerováno |
| web | /registry/capabilities/rules-show/, /docs/cli/rules/show/ | vygenerováno |
| benchmarks | přímé transporty, MCP a HTTP z měřicích případů | vygenerováno |
| tests | test projekce pro každý modul, tests/projections.rs, test příkladů CLI, apps/majordomus-cli/tests/rules.rs | napsáno jednou, kde možno generické |
Co se stane, když se přidá schopnost
Poctivý vývojářský postup na výchozí větvi dnes:
- Doménové chování napište do vlastního modulu pod
apps/majordomus-cli/src/. - Deklarujte schopnost pomocí
capability!v modulu podapps/majordomus-cli/src/capability/builtin/, se vstupními a výstupními typy odvozujícímiJsonSchemaa vstupem implementujícímBenchmarkCases. Pokud je modul nový, přidejte jej do seznamupub moda dobuiltin::modules()— jediný ruční krok skládání. - HTTP, OpenAPI, Swagger UI, MCP a spouštěč Cockpitu se objeví bez dalšího kódu, pro každé vystavení, které deklarace jmenuje; spouštěč potřebuje vystavení přes HTTP a
run <id>k němu z příkazové řádky dojde tak či onak. - Je-li schopnost vystavena na příkazové řádce, přidejte variantu clap, dispečujte ji přes
ctx.execute, napište textový renderer a přidejte spustitelný příklad. Closure a parity selhávajícapabilities validate, projekční test aprojection-check, dokud se deklarace a strom neshodují; samotný build uspěje. - Spusťte
just derive(scripts/derive: generate, data webu, znovu generate, pak.gitattributes), což přepíše registr, OpenAPI, reference, inventář měření a data webu; samotnémajordomus generatedata webu nepřepíše. Commitněte je se změnou. Pre-commit hook odmítne commit, jehož data webu jsou zastaralá, a — je-li spustitelný soubor sestaven — takový, jehož projekce registru jsou zastaralé. - Testy. Generické testy projekcí pokrývají novou schopnost automaticky. Vlastní pin test modulu vypisuje jeho schopnosti a jejich vystavení, takže přidání jedné do existujícího modulu znamená rozšířit tu tabulku; poté přidejte behaviorální případ pro to, co dělá.
- Tvrzení a důkazy. Je-li schopnost veřejnou zárukou, přidejte do
docs/CLAIMS.yamltvrzení s jeho testem a detailní stránku poddocs/claims/; běh testu zaznamenejte pomocímajordomus-cli evidence record. - Verze. Veřejná plocha se změnila, takže
majordomus-cli release analyzenyní dluží bump;release bumpjej zapíše (viz Publikace a verze).
Nic se neregistruje zvlášť v HTTP, OpenAPI, Swaggeru, MCP, Cockpitu ani referenci. Příkazová řádka je zbývající druhá deklarace a je kontrolovaná. Cíl nulové registrace — nová kanonická entita, která dosáhne každého relevantního povrchu bez kroku na povrch — je splněn pro každý povrch kromě příkazové řádky a skládání modulů.
Správa: čím je každý druh dokumentu
Taxonomie tak, jak ji implementují schémata a loadery:
| Druh | Co to je | Autorsky v | Schéma |
|---|---|---|---|
| pravidlo | verzovaný invariant s tvrzením, třídou (blokující nebo poradní), závislostmi a volitelně deklarací, jak se vynucuje | .ai/repo/rules/project/ a vendorovaný standard pod .ai/repo/rules/vendor/majordomus/rules/ | majordomus.rule/v1 |
| doktrína | ne samostatný druh: pravidlo, jehož blok vynucování jmenuje validátor, který spouští příkaz | odvozeno z pravidel pomocí lib/doctrine.sh | schéma pravidla |
| policy | konfigurovatelné chování repozitáře: platné profily, povinné sekce předávky, prahy čerstvosti, zapojení vynucování | .ai/repo/policy.yaml | majordomus.policy/v1 |
| ADR | architektonické rozhodnutí s jeho kontextem, alternativami a důsledky; proposed, dokud je osoba nepřijme | .ai/repo/adrs/ | majordomus.adr/v1 |
| claim | veřejné prohlášení o tom, co nástroj zaručuje, se zdrojem, implementací, testem a stavem | docs/CLAIMS.yaml, podrobnosti v docs/claims/ | majordomus.claim/v1 |
| profil | pojmenovaná sada přepínačů politiky pro druh práce | .ai/repo/profiles/ | majordomus.profile/v1 |
| dovednost | zabalený postup pro workera | .ai/repo/skills/ | majordomus.skill/v1 |
Doktrína je část, která se nejčastěji chápe špatně. Doktrína není dokument principů, na který pravidla ukazují; je to pravidlo, které nástroj sám vynucuje pojmenovaným validátorem. Registr doktrín se odvozuje, nikdy nepíše: je to každé pravidlo účinné sady, jehož blok vynucování jmenuje validátor (docs/DOCTRINE.md). Principy, kterým doktrína slouží, jsou samy pravidly — vendorovaná pravidla označená principle (soubory principle-NN-*.v1.md, například majordomus.one-worker-one-scope) — spojená obyčejným depends_on. Neexistuje typované pole doktrína-pravidlo; viz Dluh architektury.
Doktríny pocházejí z balíčku. Standardní pravidla žijí v share/standard/majordomus/ s manifestem nesoucím sha256 každého souboru a do repozitáře se vendorují bajt po bajtu. majordomus doctor porovnává vendorované soubory s manifestem.
Tvar pravidla
Úryvek skutečné hlavičky .ai/repo/rules/project/rule-is-a-doctrine.v1.md (jeho description vynecháno, výrok zkrácen):
id: project.rule-is-a-doctrine
version: 1
kind: rule
title: A new enforced rule is a doctrine, not an inline check
statement: A rule the tool enforces declares an x-majordomus block ...
status: active
class: blocking
depends_on: []
tags: [doctrine]
x-majordomus:
tests: [test/cases/18_doctrine_wiring.sh, test/cases/125_rule_proof.sh]
Tělo musí nést nadpisy, které rule.v1.proto vyžaduje: Rationale, Required behaviour, Failure behaviour, Verification. Blok x-majordomus nemá pole mode. Režim vynucování se odvozuje z toho, co blok jmenuje (ADR 0048):
| Názvy bloků | Režim | Význam |
|---|---|---|
a validator | odesláno | příkaz spouští mj_validate_<name> sám: check, finish, doctor, watch — podle toho, co uvádí jeho enforced_by |
tests a žádný validátor | řízeno kontrolou | CI kontrola spouští testy, které ho dokazují |
jen reviewed_because | zrevidováno | vynucuje ho člověk a pravidlo říká, proč to žádný stroj nedokáže |
| nic | deklarativní | uvedený princip; povoleno jen pro vendorovaná pravidla označená principle — jakékoli jiné pravidlo, které nic nejmenuje, selže rule-proof-check |
Shellový nakladač pravidel (lib/rules.sh) odmítne napůl deklarovaný blok; Rustový engine důkazů ho čte jako deklarativní a nahlásí ho.
Životní cyklus pravidla
flowchart TD d5_AU["authored: a .vN.md file"] --> d5_PA["parsed against rule.v1"] d5_PA --> d5_IX["indexed: majordomus://rule/id@version"] d5_IX --> d5_MO["mode derived from x-majordomus"] d5_MO --> d5_GB["gates bound: tests matched to what gates.yaml runs"] d5_GB --> d5_EX["executed: a gate or a command runs"] d5_EX --> d5_RC["recorded: evidence ledger row with commit and digest"] d5_RC --> d5_ST["state derived against the current tree"] d5_ST --> d5_SF["surfaces: rules report, rules show, MCP, Cockpit, site"]
Existence pravidla neznamená, že se vynucuje
Toto je ústřední myšlenka správy a implementace ji typuje. Pravidlo může stát na kterémkoli z těchto stupňů a každý stupeň je samostatný fakt:
| Příčka | Co to zakládá |
|---|---|
| deklarováno | soubor existuje |
| zpracováno a platné | loader a schéma pravidla to přijímají |
| registrováno | index to drží na jeho URI |
| důkaz pojmenován | jeho blok x-majordomus jmenuje validátor nebo testy |
| důkaz se vyřeší | každá jmenovaná cesta existuje ve stromu — jinak visící, což vždy selže |
| zapojeno | validátor je vyvolán příkazem (kontroluje doctor kontrola zapojení doktríny), nebo kontrola v .ai/repo/ci/gates.yaml spouští pojmenovaný test |
| provedeno | běh proběhl |
| zaznamenáno | ledger důkazů drží ten běh, s jeho commitem, stavem pracovního stromu a digestem |
| aktuální | vstupy zaznamenaného běhu se ve stromu, na který se ptáme, nezměnily |
Rust engine pravidel (apps/majordomus-cli/src/rules/mod.rs) to redukuje na jeden stav z RuleState, nejsilnější první: proven, inputs_unchanged, stale, gated, failing, not_run, reviewed, unrunnable, dangling, unproven. Visící cesta činí pravidlo dangling — převažuje nad vším; jinak selhávající test činí pravidlo failing; jinak je jeho stav nejslabší z testů, které mohou nést důkaz. Za prošlé se počítají jen první tři. Nález se vznáší pro visící důkaz nebo pro blokující pravidlo, které je nedokázané, selhává nebo nejde spustit; not_run, gated a reviewed záměrně nálezy nejsou, protože popisují absenci záznamu, ne vadu.
scripts/ci/rule-proof-check je kontrola: visící (dangling) důkaz selhává a pravidlo jakékoli třídy, které nejmenuje žádný validátor, žádný test a žádné reviewed_because, selhává — třída není výjimka. Jediná výjimka je vendorované pravidlo označené principle. Drží ho ratchet, jehož základní stav, .ai/repo/rule-proof-baseline.txt, je prázdný.
Abyste viděli, kde repozitář stojí — ne abyste věřili slovu tohoto dokumentu:
$ bin/majordomus-cli rules report
$ bin/majordomus-cli rules show majordomus.scope-integrity
$ curl -s http://127.0.0.1:8741/api/v1/rules | jq .summary
V době psaní ten report říká, že každé blokující pravidlo buď jmenuje důkaz, který se vyřeší a je navázán na kontrolu, nebo deklaruje reviewed_because a vynucuje ho člověk (rules report --class blocking uvádí které), a že v ledgeru je zaznamenáno málo běhů, takže většina pravidel stojí na not_run místo proven. To je správné čtení důkazů: kontroly běží v CI při každé změně a CI zaznamenává své běhy do artefaktu na běh (scripts/ci/evidence-collect), ale nic je zatím nepřenáší do sledovaného ledgeru (ADR 0080, navrženo). „Satisfied“ v reportu znamená žádný nález — nic nevisí a žádné blokující pravidlo není nedokázané, selhávající ani nespustitelné; zahrnuje reviewovaná pravidla a poradní pravidla, která žádný důkaz nejmenují. Neznamená, že zaznamenaný běh prošel. Zelený odznak kdekoli v Majordomu musí být projekcí zaznamenaného provedení; kde žádné zaznamenáno není, povrchy říkají not run, gated nebo reviewed — nikdy proven.
Mapa správy
flowchart LR g_P["principle: a vendored advisory rule tagged principle"] -->|depends_on| g_R["rule: id@version, class, statement"] g_R -->|x-majordomus names a validator| g_V["validator: mj_validate_* in lib/"] g_R -->|x-majordomus names tests| g_T["tests: test/cases, crate tests, gate scripts"] g_R -->|names only reviewed_because| g_H["a person's review"] g_V --> g_D["dispatched by check, finish, doctor, watch"] g_T --> g_G["bound to gates in .ai/repo/ci/gates.yaml"] g_D --> g_X["execution"] g_G --> g_X g_X -->|evidence record| g_L["ledger: outcome, commit, tree, digest"] g_L --> g_S["proof state, judged against the presented tree"] g_S --> g_U["rules report, rules show, MCP, Cockpit runner, site"]
Doktrína je horní cesta — pravidlo, jehož blok jmenuje validátor, který příkaz spouští. Pravidlo s kontrolou je prostřední cesta. Pravidlo s review je dolní a žádný povrch ho nenazývá vynucovaným strojem.
Důkazy
Důkazem je zaznamenané provedení, nikoli cesta k testu, která náhodou existuje (docs/EVIDENCE.md).
flowchart LR d6_TR["test run"] --> d6_REC["majordomus-cli evidence record"] d6_REC --> d6_LED[".ai/repo/evidence/ledger.json: latest run per test"] d6_LED --> d6_JOIN["join: claim or rule to its tests"] d6_TREE["git: diff from the recorded commit"] --> d6_JOIN d6_JOIN --> d6_STATE["proof state"] d6_STATE --> d6_OUT["evidence report, rules show, Cockpit, site guarantees"]
Kniha je commitnutá a drží poslední provedení každého testu: runner, výsledek, sekundy, commit, stav pracovního stromu, digest, původ (local, CI nebo release) a příkaz. Stav důkazu tvrzení se odvozuje na požádání:
| Stav | Význam |
|---|---|
proven | zaznamenaný běh prošel, mezi jeho commitem a dotazovaným stromem se nezměnilo nic než ledger a oba stromy byly čisté |
inputs_unchanged | vlastní zdroj, implementace a test tvrzení se nezměnily, ale změnilo se něco jiného nebo byl jeden ze dvou stromů špinavý |
stale | jeden z těch vstupů se změnil, předložená revize neobsahuje commit běhu, tvrzení nedeklaruje žádné vstupy, nebo git nemohl odpovědět |
failing | zaznamenaný běh selhal |
not_run | žádný běh není zaznamenán |
unrunnable | pojmenovaný test je druhu, který žádný runner nemůže provést |
no_test | tvrzení nejmenuje žádný test |
Rozhodnutí žije v jedné funkci, freshness() v apps/majordomus-cli/src/evidence/freshness.rs, takže žádný povrch nemůže posoudit běh jinak. Čerstvost proto není časové razítko, ale vztah ke stromu: test, který prošel u jednoho commitu, je u tohoto commitu proven, u pozdějšího commitu, který se jeho vstupů nedotkl, inputs_unchanged a u toho, který se jich dotkl, stale. proven a inputs_unchanged se nikdy nesloučí do jednoho stavu, protože druhé je závěr o relevanci a první ne.
Schopnosti důkazů jsou deklarovány jednou v apps/majordomus-cli/src/capability/builtin/evidence.rs a vypisuje je jq -r '.capabilities[] | select(.id | startswith("evidence.")) | .id' docs/generated/registry.json: report, jedno tvrzení, jeden test, záznam a razítko. evidence.record je jediný zapisovatel a je jen z příkazové řádky, stejně jako evidence.stamp, který čte cestu, již jeho volající jmenuje.
Jedna doktrína vystopovaná: integrita rozsahu
majordomus.scope-integrity je doktrína: převzaté pravidlo, jehož blok jmenuje validátor.
| Odkaz | Kde |
|---|---|
| ručně psané | share/standard/majordomus/rules/scope-integrity.v1.md, vendorováno do .ai/repo/rules/vendor/majordomus/rules/scope-integrity.v1.md, sha256 v obou manifestech |
| princip | depends_on: majordomus.one-worker-one-scope@1 |
| blok vynucování | validator: scope, enforced_by: [check, finish, watch], exit_code: 10, claims: [scope-enforcement, scoped-task], tests: [test/cases/04_start_check.sh] |
| validátor | mj_validate_scope v lib/check.sh: selže u souborů změněných od začátku úlohy, které leží mimo rozsah úlohy |
| dispatch | mj_doctrine_dispatch v check, finish a watch; finish --check běží z hooku pre-push |
| zapojení ověřeno | mj_validate_doctrine_wiring v lib/doctor.sh, mutačně testováno pomocí test/cases/18_doctrine_wiring.sh |
| test | test/cases/04_start_check.sh, spouštěno kontrolami shell-suite a macos |
| claim | scope-enforcement v docs/CLAIMS.yaml, podrobnosti na docs/claims/scope-enforcement.md |
| index a MCP | majordomus://rule/majordomus.scope-integrity@1; nástroj majordomus_rule |
| HTTP | GET /api/v1/rules/rule?rule=majordomus.scope-integrity |
| Cockpit | /cockpit/object?uri=majordomus%3A%2F%2Frule%2Fmajordomus.scope-integrity%401 |
| web | /doctrines/scope-integrity/, z site/data/generated/doctrines.json; /guarantees/scope-enforcement/ |
| evidence | cokoli ledger drží pro test/cases/04_start_check.sh, čtené pomocí rules show |
Jedno pravidlo vystopováno: odvozené soubory se přegenerují
project.derived-files-regenerated je kontrolované pravidlo projektu: žádný validátor, testy pojmenovány.
| Odkaz | Kde |
|---|---|
| ručně psané | .ai/repo/rules/project/derived-files-regenerated.v1.md |
| důkaz | tests: jmenující test/cases/56_derived_current_gate.sh, test/cases/51_derived_artifacts_committed.sh, test/cases/95_executable_reference.sh a scripts/derive-check |
| bod vynucování | hook pre-commit spouští scripts/pages current; .ai/repo/policy.yaml deklaruje toto zapojení jako derived-current a doctor selže, pokud ho hook přestane spouštět |
| kontroly | shell-suite spouští pojmenované případy a macos na požádání; scripts/derive-check engine důkazů klasifikuje jako nespustitelné a ignoruje, protože ostatní se vyřeší |
| povrchy | rules show project.derived-files-regenerated, stránka objektu v Cockpitu, jeho vlastní stránka /rules/project-derived-files-regenerated-1/ a sekce pravidel v /features/declare-once/ |
| evidence | čteno pomocí rules show; důkaz je pojmenován a kontrolován |
Postup: přidání nového pravidla
Předpokládejme, že správce přidá: každá veřejná schopnost má alespoň jedno spustitelné ověření. Co se dnes děje v každém kroku na výchozí větvi:
- Ručně psané. Soubor jménem
every-capability-is-verified.v1.mdpod.ai/repo/rules/project/, s hlavičkou pravidla a požadovanými nadpisy těla. Ručně: soubor, jeho vztahy a jeho blok vynucování jsou ručně psané části. - Schéma. Loader pravidel validuje hlavičku proti
rule.v1; neznámý klíč nebo napůl deklarovaný blok vynucování se odmítne. Automatické. - Discovery. Třída zdrojů
rulev.ai/repo/knowledge/sources.yamluž adresáři odpovídá, takže index držímajordomus://rule/project.every-capability-is-verified@1. Automaticky. - Vztahy.
depends_onjmenuje princip, kterému slouží, pomocíid@version; DAG validujedoctor. Psáno, pak kontrolováno. - Vynucování. Režim volí autor podle toho, co blok jmenuje. Velká část tohoto pravidla je už pravdivá z konstrukce — vstup bez benchmarkových případů se nepřeloží a testy projekcí spouštějí každou expozici — takže seznam
tests:jmenujícíapps/majordomus-cli/tests/projections.rsa nový případ z něj udělá kontrolovaný. Autorsky. - Navázání na kontrolu. Engine důkazů naváže tyto testy na kontroly v
.ai/repo/ci/gates.yaml, které je spouštějí. Automaticky; cesta, která neexistuje, visí a shodírule-proof-check. - Příkazová řádka.
majordomus-cli rules reportarules showho zahrnují. Automatické. - HTTP.
GET /api/v1/rules/rule?rule=project.every-capability-is-verified. Automaticky. - MCP. Zdroj na svém URI a nástroj
majordomus_rule. Automaticky. - Cockpit. Jeho stránka objektu a zpráva o pravidlech v runneru. Automaticky.
- Web. Pravidlo dostane svou generovanou stránku na
/rules/project-every-capability-is-verified-1/; doktrína dostane také stránku/doctrines/a funkce, která ji jmenuje, ji uvádí. Automaticky. - Provedení. CI spustí kontroly při příští změně, která se dotkne jejich třídy cest. Automaticky.
- Důkazy. Běh se dostane do knihy jen přes
evidence record. Dnes ručně. - Aktuální stav na každém povrchu. Odvozeno na požádání z knihy a stromu. Automaticky.
- Regrese. Kontrola selže u budoucí změny, která poruší invariant;
rule-proof-checkselže u budoucí úpravy, která odstraní jmenovaný test. Automaticky.
Relace, úlohy a kontinuita
Práce přežije relaci, která ji dělá, díky trvalým záznamům, ne přepisům (docs/CONTINUITY.md). Záznamy zapisuje nástroj shellu:
| Záznam | Kde | Trvalé | Psaný ručně, nebo odvozený |
|---|---|---|---|
| aktivní úloha | .ai/local/state/current.yaml | lokální | úloha, rozsah, profil psané ručně; blok computed from git odvozený |
| otevřená epizoda | .ai/local/state/sessions-open/ | lokální, do uzavření | odvozeno z událostí hooků poskytovatele |
| uzavřená relace | .ai/repo/sessions/, když manifest pojmenovává tento oddíl | commitnuto | odvozeno z knihy při uzavření |
| kontrolní bod | .ai/local/state/checkpoints/ | lokální | odvozeno pomocí checkpoint --derive, nebo napsáno ručně |
| handover | .ai/local/state/handovers/ | lokální | tělo napsáno; front matter odvozen |
| kniha záznamů | .ai/local/state/ledger.jsonl | lokální, připojuje se a rotuje podle ledger.retention_max_lines politiky | odvozeno: jedna účtenka na událost |
Hooky poskytovatele (pro Claude Code v .claude/hooks/) volají majordomus capture session při startu, compactu a ukončení. Start otevře nebo zachová epizodu, zajistí, že server checkoutu běží, a vypíše briefing; ukončení odvodí checkpoint a předávku a uzavře vlastní relaci poskytovatele. .ai/local/ je ignorováno gitem: kontinuita je lokální pro stroj a commitují se pouze záznamy uzavřených relací. V repozitáři se zapnutou kooperací mesh se předávky navíc replikují do propojených runtime přes žurnál (apps/majordomus-cli/src/mesh/handover.rs).
Životní cyklus úlohy je start s povinným rozsahem, check, které rozesílá doktríny na ni vázané, a finish s výsledkem a, pokud to profil vyžaduje, ověřovacím příkazem, jehož exit kód se zaznamená. Dokončení, které selže v doktríně, je odmítnuto s exitem 10 a seznamem nesplněného.
Kontext pro relaci
Kontext se kompiluje na několika místech a každé je deterministické. Kromě tří níže lib/session_context.sh skládá pracovní kontext otevřené epizody při každém čtení.
majordomus context (lib/context.sh) sestavuje seřazené sekce — git, peery, úlohu, profil, kontextové dokumenty, otevřené otázky, kandidáty znalostí, rozhodnutí, uvažování, checkpoint, předávku, integraci, relevantní soubory, historii, prompt — řízené přepínači profilu a vtěsnané do řádkového rozpočtu politiky. Sekce se zahazují od nejméně spolehlivé — historie, integrace, soubory, dokumenty, znalosti, uvažování, rozhodnutí, pak těla checkpointu a předávky, která před zahozením zkrátí na řádek s ukazatelem, pak peery — a git, úloha, profil a otevřené otázky se nezahazují nikdy. Každé zahození je uvedeno pod EXCLUDED; pokud je výstup stále nad rozpočtem, příkaz skončí exitem 10 místo tichého zkrácení.
majordomus context resolve <path> (lib/context_docs.sh) skládá kontextové dokumenty, které platí pro cestu: každý Markdown soubor context/v1 pod .ai/, jehož rozsah ji pokrývá — přesný adresář, obsahující podstrom nebo explicitní seznam cest — seřazené podle hloubky, pak deklarovaného pořadí, pak cesty, s odstraněnými nahrazenými dokumenty a otiskem nad řetězcem. Každý dokument přidává k svým předkům; nejbližší je nenahrazuje.
devcontext.compile je kompilátor v Rustu pro seřazenou pracovní množinu úlohy (apps/majordomus-cli/src/devcontext/). Prochází složený graf objektů od úlohy po typovaných hranách s pevnými dopřednými a zpětnými vahami, řadí podle úrovně autority — úloha, governance, zdroj, rozhodnutí, znalost, historie — poté podle relevance, poté podle URI a utrácí tokenový rozpočet metodou first fit, přičemž pojmenuje každou přeskočenou položku a její cenu. Jeho jediné odvozování je záměr: slova úlohy porovnaná s titulkem, popisem, identitou a tagy objektu, omezená pod přímým semínkem a pod většinou jednotlivých deklarovaných hran (devcontext/select.rs); stále může předstihnout deklarovaný vztah dosažený slabou nebo vícekrokovou hranou a úroveň autority se řadí před relevancí. Příkaz shellu context jej zatím nepoužívá.
Kontext se generuje, protože musí být znovu sestavitelný. Kontext, který existuje jen uvnitř dřívějšího promptu, se ztratí spolu s ním; kontext zkompilovaný ze stavu repozitáře může příští pracovník zkompilovat znovu a vysvětlit ho položku po položce.
Předávka
majordomus handover bere tělo na stdin se sekcemi, které politika vyžaduje — Objective, Current State, Next Action — nebo ho odvodí pomocí --derive. Tělo je autorské; front matter je odvozený: repozitář, worktree, větev, head, stav pracovního stromu, změněné soubory, časová razítka. Tělo, které nese identitní pole, je odmítnuto, takže worker nemůže tvrdit head, na kterém není.
handover --resolve najde nejrelevantnější záznam: nejprve stejný worktree a větev, pak stejnou větev, nikdy v celém repozitáři. Označí vztah k aktuálnímu HEAD jako exact, advanced, diverged nebo jiný kontext a vypíše verdikt čerstvosti podle prahů z politiky, přičemž zastaralý záznam označí jako historii. Briefing relace používá stejný verdikt a necituje další akci zastaralé předávky, protože pokyn, který platil před několika dny, je kontext, ne rozkaz.
Plánování
Milníky jsou specifikace výsledků; úkoly jsou prováděcí kontrakty (docs/PLANNING.md). Obojí je autorské YAML pod .ai/repo/project/. Úkol deklaruje závislosti, rozsah, akceptační kritéria, validaci, požadované důkazy a časová razítka svých přechodů. Nemá pole status. Status se odvozuje:
flowchart TD d7_I["issues: depends_on, timestamps, evidence_required, evidence covers"] --> d7_S["status per issue"] d7_S --> d7_W["waves: Kahn layering of the dependency DAG"] d7_W --> d7_C["scope_conflict warnings: same wave, shared paths"] d7_M["milestones: required issues, milestone dependencies"] --> d7_MS["milestone status"] d7_S --> d7_MS d7_MS --> d7_N["active milestone and next issue"] d7_N --> d7_P["docs/PLAN_STATUS.md, plan capabilities, Cockpit, site"]
Úkol je hotov, když není zrušen, má čas dokončení a každý vyžadovaný token důkazů je pokryt; jinak je prvním z verify, active, blocked nebo ready, který jeho časová razítka a závislosti dovolují. Stav před jeho blokátory se hlásí jako předčasné provedení. Úkoly na cyklu nebo za ním nedostanou žádnou vlnu a hlásí se. Milník blokovaný svou závislostí blokuje své úkoly.
Motorem je lib/project.awk; apps/majordomus-cli/src/plan.rs je druhý čtenář držený na bajtové shodě pomocí test/cases/99_plan_capabilities.sh. Jediná zapisující schopnost, plan.transition, přesune úkol, jen když to odvozený plán dovolí, a odmítne jej označit za hotový, když by simulovaný plán po přesunu hotový neodvodil. Neexistuje žádný zastaralý druhý stav k údržbě: stav je funkcí záznamů.
Nástěnka peerů, překryv a mesh
Tři věci se snadno pletou: kdo jiný právě teď v tomto repozitáři pracuje, zda jeho práce koliduje s mou a které instance Majordomu existují v síti.
Nástěnka: co dělají peeři
Sdílený server každého checkoutu drží v paměti nástěnku peerů (apps/majordomus-cli/src/peers.rs). Klient MCP, který se připojí, se stane peerem s id pozice, jménem klienta, transportem, časem připojení a poslední aktivitou. Pomocí majordomus_announce uvede záměr a rozsah, volitelně pod názvem claimu, a nové oznámení pod stejným názvem tento claim nahradí. Nástěnka se neperzistuje: odešlý peer, který něco oznámil, je uchován jako nepřipojený, až do RETAINED odešlých slotů (apps/majordomus-cli/src/peers.rs), a ten, který nikdy nic neoznámil, zmizí.
majordomus_peers sbírá nástěnku v rámci repozitáře (ADR 0044): čte nástěnku tohoto checkoutu z paměti a ptá se serveru každého sesterského worktree přes HTTP, jedním skokem, a každého peera označí checkoutem, z něhož pochází. complete: false znamená, že nástěnku nešlo přečíst, a boards říká které a proč — krátká nástěnka není důkazem, že tam nikdo není.
Překryv: odvozeno, doporučující
Překryv se odvozuje z tvrzení, nikdy se nedeklaruje. Dva rozsahy se potkají, když jsou stejné nebo když jeden obsahuje druhý na hranici cesty. Počítá se na třech místech:
| Kde | Porovnává | Výsledek |
|---|---|---|
peers.announce a peers.list | ohlášené rozsahy na nástěnce | seznam překryvů; informativní |
majordomus start a check --overlap (lib/start.sh) | aktivní rozsahy úloh jiných worktrees | nálezy INFO; vždy exit 0 |
majordomus context | nároky na nástěnce vůči rozsahu aktivní úlohy | řádek OVERLAP: „claim není zámek“ |
Žádné z nich nic neodmítá. Překryv v době oznámení porovnává jen vlastní nástěnku oznamujícího checkoutu; porovnání napříč repozitářem se dělá při sběru nástěnky, pomocí peers.list a briefingu context. Na jednom stroji odmítá doktrína rozsahu: soubory, které úloha změnila mimo svůj rozsah, neprojdou check a dokončeným finish, a finish --check běží z pre-push hooku. scripts/collision-check porovnává nesloučené lokální a vzdálené větve na cesty, které obě přidávají s různým obsahem, a kontrola collision-check takovou kolizi u pull requestu odmítne (exit 11), pokud není označena jako přijatá. Napříč stroji je claim převzatý přes mesh.claim ve výchozím stavu exkluzivní a je odmítnut s claim_conflict, když narazí na živý exkluzivní claim jiné relace — mezi claimy ten, který je víc než povědomí (viz Mesh: kdo existuje).
flowchart LR d8_A["worker A: task scope, announced claim"] --> d8_B["board in A's server"] d8_C["worker B in another worktree"] --> d8_D["board in B's server"] d8_B --> d8_G["peers.list gathers every checkout's board"] d8_D --> d8_G d8_G --> d8_O["overlap: scopes equal or nested"] d8_O --> d8_V["CLI context, MCP peers, Cockpit"] d8_T["task scope in current.yaml"] --> d8_SC["scope doctrine at check, finish, pre-push"]
Odkazováno z tohoto diagramu (1)
Mesh: kdo existuje
Mesh odpovídá na jinou otázku: které uzly Majordomus existují a lze je zastihnout (docs/MESH.md, apps/majordomus-cli/src/mesh/). Uzel má identitu Ed25519 vedenou na uživatele; instance je jeden běh procesu. Poskytovatelé objevování posílají jednu podepsanou, omezenou obálku přes UDP multicast, UDP broadcast nebo HTTP rendezvous endpoint a deklarace může jmenovat statické seedy spolupráce. Registr drží uzly podle identity s presence TTL a retenčním oknem; důvěra je deny-unknown; uzly označuje a rozhoduje, které se smějí propojit a replikovat žurnál, a nedává žádná práva provádění.
| Pole | Druh stavu |
|---|---|
| identita uzlu (digest veřejného klíče) | trvalé, na uživatele |
| instance, adresa, naposledy viděno | pozorováno; vyprší |
| štítek důvěry | autorská politika aplikovaná na pozorování |
Repozitář bez deklarace meshe, nebo s deklarací enabled: false, neotevře žádný objevovací socket a kostra, ze které nový repozitář začíná, žádný nedodává. Vlastní deklarace tohoto repozitáře, .ai/repo/mesh/majordomus.yaml, je zapnutá: multicast na lokálním segmentu, rendezvous huby na soukromé síti vlastníka a tailnetu a důvěryhodné klíče, které vypisuje (docs/MESH.md, „Mesh tohoto repozitáře“). Neexistuje poskytovatel Tailscale ani mDNS; ADR 0050 je uvádí jako budoucí poskytovatele a rendezvous koncový bod dosažitelný přes tailnet je podporovaný způsob, jak spojit stroje. Tok dat je stejný jako u každého jiného povrchu: schopnosti mesh.status a mesh.nodes, obsluhované přes HTTP a MCP a vykreslené na /cockpit/mesh.
Nástěnka se promítá do meshe. Nástěnka stále sbírá checkouty jednoho stroje přes soubory zápůjček a to zůstává pohledem místním ke stroji. Nad objevováním kooperace propojuje runtimy jednoho repozitáře — jeden server na checkout, na tomto stroji nebo jiném — přes ověřená spojení (ADR 0067): při každém tepu se relace nástěnky runtime stávají relacemi meshe a jejich oznámení poradními nároky, v jednom podepsaném žurnálu, který každý propojený runtime replikuje a sloučí stejně. Takže nástěnka peerů a nároky se replikují napříč runtimy; spojení potřebuje povolený mesh a důvěryhodný klíč. Žurnál je podepsaná posloupnost na proud s hodinami Lamport (apps/majordomus-cli/src/mesh/journal.rs) nesoucí události relací, nároků, předávek a review a jeho stav je čisté sloučení (mesh::state::fold): oznámení nástěnky se stane poradním nárokem meshe, zatímco nárok převzatý přes mesh.claim je výhradní a při konfliktu se odmítne. Při rozdělení sítě mohou nárokovat obě strany; sloučení vybere nejnižší hodiny Lamport, pak proud, pak posloupnost a poraženého označí conflicted — nároky nejsou linearizovatelné a docs/MESH.md to říká. Registr uzlů a tabulka spojení žijí v paměti a umírají s procesem; soubor identity a žurnál přetrvávají a znovu načtený žurnál obnoví události, ale ne čerstvost. Stabilita modulu je experimentální. Mesh agenty neorchestruje.
Mapa mesh
flowchart TD m_M["machine"] --> m_N["node: Ed25519 identity per user and machine"] m_N --> m_R["runtime: one per checkout's shared server"] m_R --> m_B["board: attached MCP peers and their announcements, in memory"] m_R --> m_S["mesh sessions in the signed journal"] m_B -->|every heartbeat| m_AC["advisory mesh claims"] m_S --> m_EC["exclusive claims via mesh.claim"] m_AC --> m_SC["scopes"] m_EC --> m_SC m_SC --> m_O["overlap: equal or nested paths, reported"] m_EC -->|meets a live exclusive claim| m_CC["claim_conflict: refused"]
Odkazováno z tohoto diagramu (1)
Přítomnost, spojení a nástěnka se pozorují a vyprší; identita a žurnál trvají; překryv se odvozuje z tvrzení a hlásí se; odmítne se jedině výhradní mesh tvrzení.
Prostředí repozitáře
RepositoryEnvironment (apps/majordomus-cli/src/environment/mod.rs) je jeden typovaný snímek toho, čím checkout je: projekt, repozitář, správa verzí, toolchainy, vrstva, workflow, projekce poskytovatelů, lokální služby a diagnostika, se záznamem původu u každé hodnoty (docs/ENVIRONMENT.md). Rozřeší se rychle z cache pod .ai/local/ nebo plně z indexu.
Model je architektura; banner je jeden jeho renderer. Stejná hodnota se vykresluje jako banner shellu přes direnv (environment/render.rs), jako text a JSON majordomus-cli env, jako GET /api/v1/environment, jako zdroj MCP majordomus://environment a vysvětluje ji environment.explain. Lokální služba se pozoruje jediným omezeným TCP spojením, které dokazuje, že port odpovídá, a nic víc.
Publikace a verze
Od merge k veřejné stránce
flowchart TD d9_M["merge to master"] --> d9_B["scripts/pages build: refuse stale source hash, render without regenerating"] d9_B --> d9_K["scripts/pages check: site-check and the never-published check"] d9_K --> d9_P["scripts/site-deploy pushes site/public to gh-pages"] d9_P --> d9_V["scripts/pages verify --commit SHA: poll majordomus.dev/build.json"] d9_V --> d9_G["pages-live gate: served commit is on master, nothing owed past the window"]
Publikační cesta (.github/workflows/pages.yml, modelovaná v .ai/repo/ci/pages.yaml) nic nepřegenerovává: commitnuté projekce jsou už zkontrolovány, takže publikace je vykresluje. Tři fakty se drží zvlášť, protože selhávají zvlášť: build uspěl, nasazení bylo pushnuto a veřejný web servíruje nový commit. Jen poslední se ověřuje proti veřejnému endpointu — build.json na majordomus.dev nese commit, ze kterého byl postaven. V jobu nasazení je toto ověření (scripts/pages verify --commit … --smoke) poradní: krok může selhat, aniž by selhal job, a job hlásí „pushed“ a „serving“ jako samostatné fakty. Rozhoduje kontrola pages-live, spouštěná při finish, která ověřuje, že servírovaný commit je na masteru a že žádná publikace není dlužna déle než okno nasazení (share/standard/majordomus/rules/publication-currency.v1.md).
Verze se píše jednou
Verze se píše na jednom místě, v [package] version manifestu crate, a zapisuje ji jeden příkaz, majordomus-cli release bump (apps/majordomus-cli/src/release/version.rs), který také udržuje v souladu vlastní položku lockfilu a čte obojí zpět. Shellový nástroj žádnou verzi neuvádí: čte share/version.txt, generovanou projekci manifestu, která se dodává vedle něj (ADR 0085), a release::version::diagnose odmítne verzi napsanou ručně kdekoli, kde žijí soubory nástroje — kontrola version-authored-once. Minimální zvýšení se měří, ne volí: release analyze porovnává veřejný povrch schopností — id, expozice a schémata, s kompatibilitou vstupu a výstupu posuzovanou v opačných směrech — s posledním release (ADR 0051). Conventional commity jsou důkaz, ne autorita. Stejná analýza je GET /api/v1/release/analysis, nástroj MCP a /cockpit/release. Po zvýšení just derive přepíše share/version.txt, každé razítko generátoru, changelog, docs/INSTALL.md a data verze webu.
Tag spustí workflow releasu: sestaví matici platforem z docs/generated/distribution-matrix.json, publikuje, zapíše záznam releasu pod .ai/repo/releases/ ze skutečných otisků artefaktů, otevře s ním pull request a po dosažení záznamu na výchozí větvi otestuje veřejný instalátor smoke testem.
Co doctor kontroluje
majordomus doctor je jen pro čtení a dispečuje každou doktrínu, která je na něj navázána (lib/doctor.sh). Mezi nimi: vendorovaný balík pravidel proti hashům manifestu; řetěz zapojení doktríny od validátoru přes dispečink a propagaci selhání po test, tvrzení a CI; instrukční soubory poskytovatelů proti jejich generačním razítkům (bez razítka nebo ručně upravené selže); zapojení každého vynucovacího záznamu v politice, včetně odvozovací kontroly v pre-commitu; integrita schémat, rozložení, rozpočty, retence, DAG pravidel, ADR, dovednosti a prompty. Rustové health.report přidává porovnání commitnutého registru s vykreslením v procesu.
Doctor odhaluje, neopravuje. Regenerace je majordomus generate a just derive; oprava ručně upravené projekce poskytovatele je majordomus update --diff <target> a poté --force — prosté update odmítne přepsat ruční úpravu. Generátor se neopravuje sám jen proto, že existuje: regenerace běží bez dozoru pouze ve workflow verzí a releasů, které otevírají pull requesty, a nic neopravuje na místě.
Kruhový dogfooding
Majordomus je supervizován Majordomem. Pravidla, která zakazují ručně vedené registry, jsou pravidla ve vlastním .ai/ tohoto repozitáře; důkazní engine, který říká, zda jsou vynucována, čte kontroly tohoto repozitáře; generátory, které píšou referenci, jsou kontrolovány kontrolami, které tato pravidla jmenují; ledger důkazů může zaznamenat běhy testů, které dokazují determinismus generátorů (dnes jich žádný nedrží: jq -r '.executions[].test' .ai/repo/evidence/ledger.json); a Cockpit vykresluje tento důkaz ze stejného registru, který dokazuje. Když se generátor rozbije, kontrola, kterou jmenuje pravidlo o generátorech, selže v CI a samo pravidlo se čte failing až poté, co je ten běh zaznamenán. Smyčka je silná jen jako její nejslabší zaznamenaný článek — dnes zaznamenávání provádění — a proto je ten článek níže jmenován.
Co se negeneruje
Majordomus generuje mechanické projekce. Negeneruje lidský úsudek, aby ho pak potichu nazval kanonickou pravdou.
| Píší lidé, nikdy se negeneruje | Odvozeno strojem z toho |
|---|---|
| záměr: proč milník existuje, co znamená hotovo | stav, vlny, připravenost |
| rozhodnutí a jeho kompromisy v ADR | záznam ADR v indexu, odkazy z pravidel a souborů |
| přijetí rozhodnutí | nic: extrahované ADR se nesmí nazývat přijatým |
| znění pravidla a proč existuje | její režim, kontroly, stav důkazů, povrchy |
| tvrzení o tom, co nástroj zaručuje | jeho stav důkazů |
| vysvětlující próza, včetně tohoto dokumentu | jeho stránka na webu, odkazy, pořadí a popis |
| cíl a další akce předávky | jeho repozitář, větev, hlava a změněné soubory |
Pokud člověk zaznamená OAuth musí používat PKCE, stroj smí odvodit pravidla, kterých se to dotýká, kontext, který to má nést, odkazy z dokumentace a zda je implementace testována. Nesmí rozhodnutí přepsat proto, že heuristika usoudila, že je nepravděpodobné. Odvození v kompilátoru kontextu je zastropováno pod přímou deklarací právě z toho důvodu.
Matice generování
| Entita | Napsáno | Objeveno | Odvozeno | CLI | HTTP | MCP | Cockpit | Web |
|---|---|---|---|---|---|---|---|---|
| schopnost | capability! | skládání modulů | dostupnost, viditelnost, provádění, měření výkonu | každý přes run <id>; vyhrazený příkaz tam, kde ho vykresluje příkaz clap | ano, když je vystaveno | nástroj nebo zdroj, pokud je vystaven | explorer a runner | stránky /registry/ |
| command | strom clap, share/commands.yaml | recepty just | graf příkazů, completion | ano | přes svou schopnost | přes svou schopnost | /cockpit/commands | /docs/cli/, /commands/ |
| objekt dokumentu | jakýkoli indexovaný soubor | sources.yaml | URI, druh | entity kinds, entity show; shell search; run objects.list | /api/v1/objects, /api/v1/entity* | zdroj | stránka objektu | jen druhy s projekcí |
| pravidlo | soubor pravidla | index | režim, kontroly, stav důkazu | rules report, rules show | /api/v1/rules | majordomus_rules, majordomus_rule | stránka objektu, runner | /rules/<id>-<version>/ pro každé platné pravidlo; /doctrines/ pro doktríny |
| doktrína | pravidlo s validátorem | loader doktrín | registr doktrín | shell doctrine | přes pravidla | přes pravidla | přes pravidla | /doctrines/ |
| claim | docs/CLAIMS.yaml, docs/claims/ | index | stav důkazu | evidence claim | koncové body důkazů | nástroje důkazů | stránka objektu, runner | /guarantees/ |
| ADR | soubor ADR | index | žádné | entity show | objekty | zdroj | stránka objektu | /adrs/adr-NNNN/, jedna generovaná stránka na rozhodnutí |
| úkol, milník | YAML | index | status, waves, next | shell plan; plánovací schopnosti v Rustu pouze přes run plan.<op> | /api/v1/plan/*, POST /api/v1/plan/transition | majordomus_plan* | pouze runner, žádná stránka plánu | /plan/, plán rozvoje, graf závislostí |
| peer (pozorováno: připojení a ohlášení) | oznámení | Připojení MCP | překryvy | run peers.list; sekce shellu context; oznámení vyžaduje relaci MCP | /api/v1/peers; POST /api/v1/peers/announce existuje, ale bez relace MCP odmítá | majordomus_peers, majordomus_announce | /cockpit/peers | žádné |
| uzel meshe (pozorováno: přítomnost), claim meshe | deklarace meshe; mesh.claim | poskytovatelé, odkazy | přítomnost, štítek důvěry, sloučený stav žurnálu | majordomus-cli mesh | /api/v1/mesh/* | majordomus_mesh* | /cockpit/mesh | žádné |
| prostředí | politika, manifest | git, toolchainy, služby | snapshot s provenancí | env | /api/v1/environment | majordomus://environment | ne na přehledu | žádné |
| design token | share/design/tokens.yaml | žádné | stylesheety, logo, designová data | žádné | report designu | designové nástroje | /cockpit/design, veškeré stylování | veškeré stylování |
| verze | [package] version manifestu crate, zapsané pomocí release bump | poslední záznam o release | minimální bump | release analyze | /api/v1/release/analysis | nástroj pro release | /cockpit/release | changelog, instalace |
Architektonický dluh
Kde repozitář ještě není modelem, který tento dokument popisuje, měřeno na výchozí větvi. Ne všechny povrchy tyto mezery samy zveřejňují; jsou zde vypsány, aby je čtenář nemusel hledat.
Deklarováno dvakrát nebo registrováno ručně
- Příkazový řádek je druhá deklarace v clap, kontrolovaná uzavřením a paritou, ale negenerovaná; cesta příkazu se také opakuje jako slova, která jeho modul předává
by_cli, a pomocná funkce, která to dělá, je zkopírována do několika modulů příkazů. Textové renderery a spustitelné příklady se píší ručně. - Přidání modulu schopností upraví seznam
pub moda jediné volánícompose_modules!. - Oblasti Cockpitu, statické trasy a dispatcher jsou psány ručně a testy je drží shodné, nejsou odvozeny; komentář modulu v
cockpit/nav.rspojmenovává méně oblastí, než servíruje. - Seznam cílů příkazové řádky
majordomus generateje druhý výčet vedle vlastního výčtu generátoru a chybí mu jeden z jeho cílů, který proto běží jen podall. - Nástroj shellu drží vlastní dispatch tabulku vedle
share/commands.yamlarules,skills,evidence,knowledgeabenchexistují v obou programech s různými významy. - Dva seznamy povolených,
share/allow/commands.txtashare/allow/events.txt, jsou psané ručně; žádný generátor je zatím neodvozuje. - Můstek MCP má pro nástroj announce zvláštní případ při přehrání po opětovném připojení.
docs/HARDCODING_LEDGER.yamluvádí místa, kde je fakt zapsán dvakrát a která byla založena, s příkazem, který každé reprodukuje; několik otevřených položek zůstává a několik duplikací pojmenovaných v této sekci tam zatím není. Tabulka povrchů vdocs/WEB.mdje jednou z nich svým duchem: psaná ručně a nekontrolovaná žádným testem.
Odvozeno, ale ne věrně
- Anotace MCP nástrojů: nápovědy destructive a idempotent jsou stejné pro každý nástroj, včetně těch, které zapisují do repozitáře; jen nápověda read-only se řídí deklarací.
- OpenAPI připojuje odpověď 422
refusedpouze k příkazům, ačkoli některé dotazy odmítají. - Diagram pipeline na stránce architektury webu je pevná posloupnost zapsaná v generátoru a vynechává vlastní generační fáze spustitelného souboru.
- Vztah doktríny k principu je obyčejné
depends_on; žádné typované pole neexistuje. Odkazy pravidlo-tvrzení existují jen u vendorovaných doktrín; tvrzení na pravidla nezpět neodkazují. - Členové souboru kolekce (tvrzení, příkazy, taxonomie případů užití) se indexují bez kontroly schématem na člena, jíž prochází každý jiný objekt.
Není zpřístupněno všude
- Žádné stránky Cockpitu podle druhu pro pravidla, doktríny, ADR nebo tvrzení — obsluhuje je generická stránka objektu. Žádná stránka plánu v Cockpitu a přehled ukazuje preflight, ale ne snapshot prostředí.
- Nástěnka peerů nemá vlastní příkaz — čte ji
run peers.list— a pro oznamování je potřeba relace MCP. - Příkazy životního cyklu v shellu (
start,check,finish,handover,context) nejsou schopnosti, takže nemají projekci HTTP ani MCP;continuity.stateje jejich čtecí model. - Hooky relace jsou adaptovány jen pro Claude Code; ostatní poskytovatelé své deklarují a jsou neadaptovaní (
share/providers.yaml,lib/capture.sh). - Prostředky Swagger UI pocházejí z CDN.
Bez důkazů
- Běhy se do registru zapisují jen pomocí
evidence record; CI spouští každou kontrolu, ale své běhy zpět nezapisuje, takže většina pravidel a tvrzení se čte jakonot_runmístoprovena web publikuje deklarované a podporované počty vedle sebe, aby to řekl. - Deklarativní pravidla nejmenují žádný důkaz a stojí na
unproven; jsou poradní, takže nejsou zjištěními. Revidovaná pravidla vynucuje člověk a nepočítají se jako strojově vynucená.
Nevynucováno, jak je zdokumentováno
project.derived-files-regeneratedříká, žescripts/derive-checkběží v CI a ve workflow Pages; běží jen ve workflow zvýšení verze a release, zatímco kontrola pull requestu spouští své poloviny odděleně. Polovina pre-commit porovnává hash vstupu a porovnání registru přeskočí, není-li sestaven spustitelný soubor.- Sonda obsluhy nasazení je uvnitř jobu nasazení jen poradní; jakmile uvidí commit, publikovaná dokumentace a rustdoc se ověří a job selže, stejně jako při chybě sestavení GitHub Pages, a kontrola
pages-livepři dokončení posoudí, zda je publikace aktuální. project.no-counts-in-proseje mechanizováno pro vždy načítaný kontext poskytovatele (doctor) a pás důkazů na domovské stránce (homepage-check); u dokumentů se vynucuje revizí.evidence.recordzapisuje commitnutý ledger, ale deklaruje efektprocess_state, takže seznam zapisovatelů do repozitáře odvozený z efektů (instrukce MCP,x-majordomus-effect) ho vynechává.
Nesestaveno, nebo sestaveno částečně
- Poskytovatelé discovery Tailscale a mDNS; NAT traversal a spoje širokého dosahu. Spolupráce mezi stroji existuje přes rendezvous endpointy a důvěryhodné klíče, je experimentální a její provoz na více strojích se opírá o zaznamenaný ruční běh (
docs/MESH.md). - Rustová strana životního cyklu relace je čtecí model; přechod je navržen.
- Záznam záměru je částečně adoptován (ADR 0070):
.ai/repo/project/intents/drží záznamy, které čtouintent validateaintent preflight; úloha se k nim váže přistarta je z nich briefována (ADR 0111) a žádná politika dokončení je nespotřebovává. - Verzi lze deklarovat dříve, než je vydána: verze crate a nejnovější záznam o release jsou samostatné skutečnosti; navigační lišta uvádí release a changelog zobrazuje nevydanou verzi nad ním.
- Mnohá ADR, která kód už dodržuje, zůstávají
proposed, protože přijetí je aktem člověka.
Audit tvrzení
Každé silné tvrzení v tomto dokumentu s tím, jak ho ověřit.
| Výrok | Kontrola |
|---|---|
| HTTP, OpenAPI, MCP a runner Cockpitu nepotřebují žádný kód na schopnost | čtěte Router::capability v apps/majordomus-cli/src/http/router.rs a mcp/surface.rs; grep -rn '"rules.show"' apps/majordomus-cli/src najde jen deklaraci a testy |
| OpenAPI se odvozuje z registru, který obsluhuje požadavky | apps/majordomus-cli/src/http/openapi.rs; bin/majordomus-cli generate --check |
| každá projekce má deklaraci a naopak | cargo test --test projections v apps/majordomus-cli |
| příkazová řádka je kontrolovaná druhá deklarace | apps/majordomus-cli/src/capability/closure.rs, apps/majordomus-cli/src/cli/local.rs, scripts/ci/projection-check |
| doktrína je pravidlo s validátorem | lib/doctrine.sh; bin/majordomus doctrine list |
| režim vynucování se odvozuje, nedeklaruje | ADR 0048; rule.v1.proto nemá pole mode |
| selhávající test činí pravidlo selhávajícím; jinak je jeho stav nejslabší z testů, které mohou nést důkaz | apps/majordomus-cli/src/rules/mod.rs, apps/majordomus-cli/src/evidence/freshness.rs; bin/majordomus-cli rules report |
| stav úkolu se odvozuje bez uloženého stavu | YAML úkolu nemá klíč status; lib/project.awk; bin/majordomus plan status |
| překryv je jen poradní | lib/check.sh vrací 0 po --overlap; peers.rs dokumentuje informativní překryvy |
| mesh je ve výchozím stavu vypnutý a nemá poskytovatele Tailscale | ls share/skeleton/ai/repo nemá mesh/; ls apps/majordomus-cli/src/mesh |
| tento repozitář provozuje vlastní mesh a důvěřuje klíčům, které jeho deklarace vypisuje | .ai/repo/mesh/majordomus.yaml; test/cases/491_the_mesh_is_on_here.sh |
| nástěnka je jen v paměti | komentář modulu apps/majordomus-cli/src/peers.rs |
| publikace se ověřuje proti veřejnému endpointu | scripts/pages verify; curl -s https://majordomus.dev/build.json |
| verze se píše na jednom místě a promítá se pro shellový nástroj | apps/majordomus-cli/src/release/version.rs; share/version.txt; scripts/ci/release-check; kontrola version-authored-once |
Pětadvacet otázek, zodpovězeno
Otázky, na které by měl technický čtenář po přečtení tohoto dokumentu umět odpovědět, každá s místem, které odpovídá.
| Otázka | Odpověď |
|---|---|
| Odkud se bere příkaz? | Varianta clap v apps/majordomus-cli/src/cli.rs (Rust) nebo případ v bin/majordomus s jeho řádkem v share/commands.yaml (shell); a pro každou schopnost generický majordomus-cli run <id>. Příkazová řádka |
| Registruje se ručně, nebo se odvozuje? | Vyhrazený příkaz ručně, jako kontrolovaná druhá deklarace — uzavřenost a parita selžou na stromu, který s registrem nesouhlasí; run <id> je odvozeno. Stejná sekce |
| Odkud pochází trasa HTTP? | HttpExposure schopnosti; router se ptá registru při každém požadavku. HTTP |
| Jak se OpenAPI vytváří? | Projito z registru přes http/openapi.rs, schémata z Rustových typů. OpenAPI |
| Jak souvisí Swagger UI s API? | Vykresluje /openapi.json a nedrží nic vlastního. Swagger UI |
| Jak získá stejnou schopnost AI pracovník? | Jako nástroj nebo zdroj MCP, který jeho expozice jmenuje, přes téhož executora. MCP |
| Jak to člověk uvidí v Cockpitu? | Generická stránka schopnosti a runner, formulář ze vstupního schématu. Cockpit |
| Jak se dělá navigace Cockpitu? | Oblasti a trasy se píší; katalogy v nich se odvozují. Trasy, navigace a pořadí |
| Odkud pocházejí stránky pravidel a doktrín? | Index a registr doktríny přes scripts/generate-site-data: /rules/, /doctrines/, /adrs/; stránka objektu v Cockpitu. Dokumentace a web |
| Jak souvisí doktrína s pravidly? | Doktrína je pravidlo, jehož blok jmenuje validátor; principy jsou pravidla, na nichž závisí. Správa |
| Jak souvisí pravidlo se svým validátorem? | Jmenuje ho její blok x-majordomus a režim se odvozuje z toho, co je jmenováno. Správa, pod „Tvar pravidla“ |
| Jak se validátor vztahuje k důkazům? | Běh se zaznamenává do knihy s commitem a digestem a posuzuje se proti stromu. Důkazy |
| Jak poznáte, že je pravidlo vynucováno? | Jeho příčka na žebříku důkazů a jeho stav v rules report. Existence pravidla neznamená, že se vynucuje |
| Jak se detekuje drift mezi projekcemi? | Bajtové porovnání commitnutého a znovu vygenerovaného výstupu a testy projekcí oběma směry. Jak se předchází driftu |
| Jak funguje objevování? | Druhy a zdrojové třídy jsou deklarace; sledované soubory gitu se vůči nim porovnávají. Objevování |
| Jak fungují typované registry? | Index objektů pro dokumenty, registr schopností pro operace, validované celé. Registr |
| Co je kanonické, odvozené, pozorované, vyvozené? | Šest druhů stavu |
| Jak vzniká kontext relace? | Seřazené oddíly vměstnané do rozpočtu, každé zahození pojmenováno. Kontext pro relaci |
| Jak se dělá předávka? | Psané tělo s odvozeným front matterem, vyřešené podle worktree a větve. Předávka |
| Jak se odvozují vlny provádění? | Kahnovo vrstvení grafu závislostí úkolů. Plánování |
| Jak funguje objevování peerů a meshe? | Nástěnka přes připojení MCP a soubory lease; uzly přes podepsané datagramy a rendezvous. Nástěnka peerů, překryv a mesh |
| Jak se data meshe dostávají na povrchy? | Přes schopnosti mesh.* a peers.* přes HTTP, MCP, Cockpit a run, jako všechno ostatní. Mesh: kdo existuje |
| Jak se odvozuje kolize rozsahů? | Rozsahy porovnané jako shodné nebo vnořené cesty; hlásí se a odmítají jen pro výlučný claim mesh. Překryv |
| Jak se nová schopnost dostane na povrchy? | Co se stane, když se přidá schopnost |
| Kde jsou výjimky? | Architektonický dluh |
Proč na tom záleží
flowchart LR d10_W["more workers"] --> d10_D["more descriptions of the repository"] d10_S["more interfaces"] --> d10_D d10_MD["more metadata"] --> d10_D d10_D --> d10_X["more drift, faster"] d10_ONE["one model"] --> d10_P1["command line"] d10_ONE --> d10_P2["MCP"] d10_ONE --> d10_P3["HTTP and OpenAPI"] d10_ONE --> d10_P4["Cockpit"] d10_ONE --> d10_P5["docs and site"]
Majordomus není sbírka příkazů, dashboardů a integrací agentů. Je to model nativní pro repozitář, z něhož se tyto povrchy odvozují.
Příkazová řádka, HTTP API, MCP, OpenAPI, Swagger UI, Cockpit a dokumentace mají být projekcemi jedné typované reality repozitáře — a tam, kde je některé z nich stále psáno ručně, ho k té realitě drží kontrola a tento dokument jej jmenuje.
Pravidla a doktríny nejsou cenné proto, že jsou napsané. Cennými se stanou, když je jejich vztah k validátorům, kontrolám, provedením a důkazům strojově zkoumatelný — a když povrchy říkají not run místo zeleného odznaku, dokud není zaznamenán běh.
Nástěnka peerů a mesh nejsou orchestrace agentů. Činí workery, jejich přítomnost a jejich claimy dostatečně viditelnými, aby o nich mohli uvažovat lidé a koordinační mechanismy.
Generování a odvozování jsou způsob, jímž se Majordomus snaží zabránit tomu, aby repozitář pomalu nashromáždil sedm neslučitelných popisů sebe sama.