Jak Rust exekutor pod apps/majordomus-cli/ zpřístupňuje to, co zpřístupňuje: jedna kanonická deklarace na schopnost, moduly, které schopnosti skládají, kořen, který skládá moduly, registr z nich sestavený, jeden exekutor, který volá každý transport, a projekce (MCP, HTTP, OpenAPI, Swagger UI, příkazová řádka, cíle měření, chování cache, generovaná reference a manifesty), které jsou odvozeny z registru a samy nedefinují nic. Chování tak, jak je implementováno a testováno; kde se tento dokument a exekutor rozcházejí, dokument se mýlí a mění se ve stejném commitu. Rozhodnutí jsou ADR 2 (registr a projekce), ADR 4 (moduly, exekutor, měření výkonu jako důkaz) a ADR 5 (jeden plán projekce, pojmenovaní vlastníci, web jako pohled na registr); pravidla jsou project.interfaces-are-projections, project.rust-canonical-declaration, project.rust-benchmark-coverage a project.rust-hot-path.
flowchart TD
decl["ONE CANONICAL DECLARATION<br>capability! { id, kind?, title, description, input, output,<br>stability, exposure, tags, cache?, benchmark?, handler }"]
modc["MODULE COMPOSITION<br>module! { id, title, description, stability, capabilities: [...] }"]
rootc["ROOT COMPOSITION<br>compose_modules![repository, objects, capabilities,<br>graph, health, peers, perf]"]
registry["CAPABILITY REGISTRY<br>+ every declarative object of the layer,<br>validated, frozen, fingerprinted"]
proj["DERIVED PROJECTIONS<br>MCP · HTTP · OpenAPI → Swagger UI · CLI · the Cockpit<br>· the execution plane and its live channel<br>· benchmark targets and coverage · cache policy · perf counters<br>· docs/generated/* · the website's /registry/ pages"]
decl --> modc --> rootc --> registry --> proj
Přispěvatel přidávající jednu schopnost upraví jeden blok capability! (s jeho typovaným vstupem a výstupem a případy měření výkonu pro vstup) a spustí majordomus generate. Nic dalšího.
Přispěvatel přidávající příkaz má o jednu věc víc k řečení, a jen jednu: zda je projekcí schopnosti (CliExposure na deklaraci té schopnosti), nebo patří jen příkazové řádce, kdy cli::LOCAL v src/cli/local.rs nese důvod a majordomus quality report ho kontroluje. Neexistuje druhý seznam: capabilities projections odpovídá na příkazy, které si žádná schopnost nenárokuje, a z nich na ty, které nenesou žádný důvod, a scripts/ci/projection-check odmítne druhou sadu. Příkaz, který neříká ani jedno, je selhání kontroly, a ne operace tiše chybějící v API — pravidlo je project.operation-transport-parity a pracovní reference je QUALITY.md.
Co je kanonické, co je odvozené a co není autoritativní
CANONICAL DERIVED (projections) NOT AUTHORITATIVE
capability! blocks, one per module file MCP tools and resources examples in prose
apps/majordomus-cli/src/capability/ HTTP routes screenshots
builtin/<module>.rs, composed by OpenAPI document the committed snapshots
module! and compose_modules! Swagger UI configuration under docs/generated/
declarative objects of the layer capabilities list/describe (caches of the registry)
.ai/** as sources.yaml maps them the Cockpit's pages, a latency number in prose
how each kind is read and validated navigation, search, palette, (evidence lives under
share/kinds.yaml, share/schemas/*.json runner form and graphs .ai/local/benchmarks/ and
.ai/repo/knowledge/kinds.yaml, schemas/ benchmark targets, coverage .ai/repo/benchmarks/rust/)
the regression policy cache behaviour (executor) the Cockpit's own markup
.ai/repo/benchmarks/rust/policy.yaml perf counters (a projection, never a
the graph derivations docs/generated/* place a fact is stated)
graph::DERIVATIONS, from the registry share/allow/*.txt (shell tool)
and the index the website's /registry/ pagesflowchart TD B[typed executable descriptors<br/>capability/builtin.rs] --> R[CapabilityRegistry] D[declarative objects<br/>.ai/** via sources.yaml] --> I[index] --> R K[share/kinds.yaml + share/schemas<br/>+ repository additions] --> I R --> M[MCP tools and resources] R --> H[HTTP routes] R --> O[OpenAPI document] --> S[Swagger UI] R --> C[capabilities list / describe] R --> K2[the Cockpit<br/>pages, navigation, runner, graphs] R --> G[docs/generated] --> W[the website's /registry/ pages] K --> A[share/allow/*.txt]
Změna jednoho deskriptoru, jednoho deklarativního souboru, jednoho druhu nebo jednoho schématu se dostane do každé projekce při příštím startu nebo příštím majordomus generate; nic se neupravuje dvakrát.
Cockpit (COCKPIT.md, ADR 12) je projekce, kterou čte člověk. Je na tomto seznamu místo vedle něj: jeho stránky jsou rozvrženy z toho, co schopnost odpověděla přes stejný executor, který volá každý jiný transport, jeho navigační katalogy jsou moduly registru a druhy indexu, formulář jeho runneru se generuje ze vstupního schématu a jeho příklady jsou vlastní případy měření schopnosti. Nic v něm nejmenuje schopnost, druh, trasu ani graf.
Model
Schopnost je deskriptor s:
| pole | význam |
|---|---|
id | kanonická identita: jmenný prostor, tečka, neprůhledná lokální část (repository.info, rule.majordomus.scope-integrity@1, document.docs/CLI.md); jedinečná napříč oběma zdroji |
kind | query: spustitelné, jen pro čtení, jeden typovaný handler; command: spustitelné, jeden typovaný handler, něco mění — paměť tohoto procesu (peer, který se ohlašuje) nebo, když to říká jeho deklarace .writes_repository(), vlastní soubory repozitáře — vázané na POST a ohlašované klientům MCP jako nikoli jen pro čtení; resource: deklarativní obsah, čtený tak, jak je. Zda příkaz zapisuje repozitář, není jeho druh, ale jeho efekt, a jak dlouho volání trvá, také není druh |
execution | co znamená spustit ji jako provedení: účinek (read, process_state, repository_mutation) a zda se dvě smějí překrývat, klasifikovaný podle druhu, se zápisem do repozitáře přidaným .writes_repository(); co smí volající předpokládat před voláním (hints: read-only, destructive, idempotent, open-world), klasifikované podle účinku a vykreslené v MCP jako anotace nástroje; a zda požádat o zastavení něčeho dosáhne, což může říct jen její handler a co deklaruje .cancellable() na deklaraci (EXECUTIONS.md) |
title, description | slova, která ukazuje každá projekce |
input, output | kanonická schémata JSON; u dotazu odvozená z jeho Rustových typů; u zdroje pohled na objekt |
provenance | builtin s modulem, nebo declarative s cestou relativní k repozitáři, adresářem, třídou zdroje, sekcí a, u člena souboru-kolekce, klíčovou cestou člena |
exposure | explicitně, pro každou projekci: mcp (jméno nástroje a/nebo URI zdroje), http (metoda a cesta pod /api/v1/), cli (slova za majordomus); chybějící znamená nevystaveno tam a nic žádnou nedovozuje |
skill | volitelné: krátké jméno, kterým osoba schopnost vyvolá z promptu agenta (alias), a jediné řetězcové pole vstupu, které vyplní napsaný text (argument), deklarované pomocí .skill(alias, argument); registr odmítne nesprávně utvořený, rezervovaný nebo obsazený alias a argument, který vstup nemůže přijmout samotný; soubor, který čte produkt agenta, se z toho generuje (EDITORS.md) |
stability | implemented, behaviorally_verified, experimental, planned, unsupported; plánovaná nebo nepodporovaná schopnost může být vypsána a nikdy není spustitelná přes žádnou projekci |
Gramatika id: jmenný prostor odpovídá [a-z][a-z0-9_-]*; lokální část je neprázdná, bez mezer a řídicích znaků, jakýkoli jiný Unicode je dovolen; id se porovnávají jako řetězce, s rozlišením velikosti písmen. Deklarativní id jsou <kind>.<identity>, kde identitou je to, co vyprodukovalo pravidlo identity druhu: id@version pro pravidlo, name pro prompt, cesta relativní k repozitáři pro druh bez polí identity.
Registr
Sestavuje se na jednom místě na proces, z vestavěných executables skládaných explicitně v capability/builtin.rs a ze všech objektů indexu. Odmítne se sestavit, se jmény všech stran, při duplicitním id (Rust s Rustem, Rust s deklarativním), duplicitním názvu nástroje MCP nebo URI zdroje, duplicitní trase HTTP, duplicitní cestě CLI, malformované expozici (trasa mimo /api/v1/, název nástroje mimo [a-z0-9_]+), dotazu nebo příkazu bez handleru, zdroji, který jej má, příkazu s expozicí zdroje MCP nebo metodou HTTP jinou než POST, dotazu vystaveném jako zdroj MCP, jehož vstup cokoli vyžaduje (čtení nic nedodává), a spustitelné expozici u plánované nebo nepodporované schopnosti. Chyby se sbírají, nezastaví se u první. majordomus capabilities validate spouští přesně toto a končí exit 10 se seznamem.
Moduly a kompozice
Schopnost žije v Rustovém modulu svého jmenného prostoru pod apps/majordomus-cli/src/capability/builtin/: repository.rs, objects.rs, capabilities.rs, peers.rs, perf.rs. Každý soubor deklaruje své typované vstupy a výstupy, implementuje BenchmarkCases pro každý typ vstupu, píše jeden handler na schopnost a končí module():
pub fn module() -> ModuleDescriptor {
module! {
id: "objects", title: "Objects", description: "...", stability: Stability::BehaviorallyVerified,
capabilities: [
capability! { id: "objects.list", ... handler: objects_list },
capability! { id: "objects.search", ..., cache: CachePolicy::Process { max_entries: 64, ttl_seconds: None }, handler: objects_search },
],
}
}
builtin/mod.rs skládá aplikaci a ten řádek je jediná kořenová kompozice:
pub fn modules() -> Vec<ModuleDescriptor> {
compose_modules![repository, objects, capabilities, peers, perf]
}
Makra jsou macro_rules!, která sestavují prosté hodnoty; app.rs je explicitně předá builderu registru. Neexistuje žádné procedurální makro, žádný globální registr plněný za zády volajícího, žádný inventář v době linkování a žádný build skript čtoucí src/. Registr neoznačuje nic, co nedostal: module! vtiskne své id na každou schopnost a schopnost, jejíž jmenný prostor id není její modul (ModuleMismatch), dvakrát složený modul, neplatné id modulu, politika cache, která nic neuchovává, cachovaný příkaz nebo politika měření, která odporuje druhu, odmítne build s uvedením id a provenience. Programy složené bez deskriptoru (testy, měření) dostanou modul odvozený ze svého jmenného prostoru; deklarativní objekty dostanou svůj druh. Souhrn registru počítá moduly, požadované a prominuté cíle měření a cachované programy a capabilities validate je vypíše.
Executor a cache
Každé volání prochází jednou cestou, ať je vyvolá cokoli: Context::execute → CapabilityExecutor::execute → handler. Relace stdio, /mcp, trasy HTTP, příkazy capabilities a runnery měření výkonu vlastní jen konverzi protokolu a nic jiného, takže instrumentace a cache platí pro každý transport najednou. Exekutor počítá provedení, vyvolání handlerů, zásahy cache, minutí a vyřazení v celoprocesovém perf::COUNTERS, vedle čítačů práce, která se děje jednou (skeny repozitáře, sestavení indexu, sestavení registru, generování schémat, sestavení projekce MCP, sestavení OpenAPI, sestavení HTTP routeru), a časování fází na monotónních hodinách; perf.counters je zodpovídá přes každý transport, čímž strukturální testy dokazují, že stovky požadavků nic nepřestaví.
Cache je politika na deskriptoru: CachePolicy::Process { max_entries, ttl_seconds }. Klíčem je kanonické id, vstup v kanonické podobě (klíče objektů seřazené na každé úrovni, takže pořadí klíčů klienta nikdy nehraje roli) a otisk registru, sha-256 z otisku indexu (cesta a obsah každého objektu) a z každého deskriptoru, takže dva stavy repozitáře nikdy nesdílejí položku. Chyby se nikdy necachují; příkaz se nikdy necachuje a registr odmítne deskriptor, který o to žádá; hranice vyřazuje nejstarší položku první; nic se netrvá. Dvě schopnosti ji deklarují, protože tak řeklo měření (objects.search a capabilities.list); každý jiný handler odpovídá z neměnného indexu v mikrosekundách a cache tam by byla druhá kopie ničeho. Generické testy procházejí každou cachovanou schopnost s každým případem a s generovanými vstupy: necachované, studené a teplé se shodují, zásah nespustí žádný handler.
Měření výkonu: každá operace, generovaný jmenovatel
Projekce měření výkonu odvozuje své cíle z registru proti repozitáři: každý spustitelný soubor s požadovanou politikou, přímo i na každém transportu, který jeho vystavení deklaruje, jednou pro každý případ, který jeho vstupní typ poskytuje; plus vlastní operace transportů, deklarované jednou jako systémové cíle (studený proces majordomus mcp, initialize, ping, tools/list, resources/list, resources/read; GET /, /openapi.json, /swagger). Pokrytí je covered / required s jmenovatelem počítaným, nikdy psaným: požadovaná schopnost, jejíž vstupní typ pro tento repozitář nevytvořil žádný případ, chybí a capabilities validate, bench coverage --check a CI na ní selžou; prominutí je typovaný důvod na deskriptoru, hlášený a nikdy nepočítaný.
majordomus bench coverage [--format json] [--check] # covered / required, per transport and in total
majordomus bench [id] [--transport direct|mcp|http|system] [--profile quick|full|ci] [--format json] [--no-write]
majordomus bench --check # against this platform's baseline, under the policy
majordomus bench baseline update [--profile full] [--allow-dirty]
Runnery měří cíl přímo přes executor (studeně, s vyčištěnou cache před každým vzorkem, a teple, pro schopnost s cache; volání handlerů se počítají), přes skutečný loopback socket obsluhovaný stejným procesem se vstupem navázaným tak, jak jej váže trasa (query string pro GET, JSON tělo pro POST), a přes skutečný podřízený proces majordomus mcp --standalone na stdio (jeden proces, mnoho vzorků; pro cíl process-cold nový proces na každý vzorek). Statistiky: samples, min, p50, p90, p95, p99, max, mean, stddev. Běh je dokument majordomus/benchmark-result/v1 s commitem, stavem dirty, profilem buildu, platformou a otiskem registru, zapsaný pod .ai/local/benchmarks/; přijatá baseline je jeden sledovaný soubor na platformu pod .ai/repo/benchmarks/rust/baseline.<os>-<arch>-<build>.json, povýšený jen příkazem bench baseline update (dirty strom odmítne bez --allow-dirty); politika regresí je .ai/repo/benchmarks/rust/policy.yaml (relativní prahy na metriku, absolutní spodní mez, pod kterou je rozdíl šum, na metriku počet vzorků, pod nímž nekontroluje, takže rychlý běh selže jen podle mediánu a plný běh podle každého percentilu, a povolení pro jednotlivé cíle, kterým dominuje zátěž stroje, například spawn process-cold). bench --check hlásí každý řádek, pojmenuje nové cíle a zastaralé záznamy baseline (přejmenovaná schopnost se nikdy tiše nespáruje) a upozorní, když se otisk registru změnil. Baseline se porovnává jen na vlastní platformě a běh selhává jen na hostiteli, který ji zaznamenal: dokument s výsledkem nese hostitele (řetězec značky CPU a počet logických jader) a běh na jiném hostiteli, například na hostovaném runneru CI čtoucím baseline zaznamenanou na vývojářově stroji, vypíše každý řádek s „reporting only“ a skončí kódem 0. Runner CI bez commitnuté baseline nic neporovnává a řekne to.
Druhy a schémata, čtené za běhu
Které soubory jsou deklarativní objekty a jakého druhu, určuje repozitář: .ai/repo/knowledge/sources.yaml mapuje pathspecy na druhy. To, jak se druh čte, jsou také data, v adresáři share distribuce nástroje (--share, MAJORDOMUS_SHARE, vlastní share/ repozitáře nebo ten vedle spustitelného souboru):
share/kinds.yaml— pro každý druh: formát (markdown,yaml,text), zda je vyžadován front matter, jakému JSON Schema musí metadata vyhovět, která pole nesou identitu, titulek a popis, pole verze s jejími podporovanými hodnotami a u kolekčního souboru seznam, který drží členy.declared:pojmenovává druhy, které si soubor Markdown smí deklarovat sám přes svůj front matter (dnescontext).share/schemas/<name>.schema.json— jedno JSON Schema (draft 2020-12) na kontrakt; při každém čtení se validuje validátorem JSON Schema. Klíč, který schéma nedovoluje, je diagnostikaunknown_key; jakékoli jiné porušené omezení jeschema_violations názvem cesty a omezení.
Repozitář rozšiřuje obojí pod svou sekcí knowledge: .ai/repo/knowledge/kinds.yaml přidává druhy, .ai/repo/knowledge/schemas/<name>.schema.json přidává schémata. Přidávání je jediná operace: druh nebo schéma, které distribuce už deklaruje, je chyba pojmenovávající oba soubory. Allow-listy shellového nástroje pod share/allow/ se generují ze schémat, která nesou x-majordomus-allow (majordomus generate allow); nikdy se nepíší ručně.
Projekce
| projekce | odvozeno z | kde |
|---|---|---|
| nástroje MCP | schopnosti s expozicí mcp.tool; inputSchema a outputSchema jsou kanonická schémata; _meta.majordomus.id nese id; readOnlyHint následuje druh | majordomus mcp na stdio a /mcp na sdíleném serveru |
| zdroje MCP | schopnosti s expozicí mcp.resource; dotaz s ní se čte jako JSON | majordomus mcp na stdio a /mcp na sdíleném serveru |
| HTTP routy | schopnosti s expozicí http; GET naváže každou vlastnost nejvyšší úrovně vstupu jako parametr dotazu přetypovaný podle typu ve schématu, POST naváže tělo JSON (vazba příkazu); chyby se mapují na 400 invalid_input, 403 forbidden (volající mimo loopback žádající o schopnost, která něco mění, ADR 0126), 404 not_found, 422 refused, 500 internal, 405 pro jinou metodu na známé cestě | sdílený server majordomus mcp startuje a majordomus serve |
| OpenAPI 3.1 | stejné trasy; operationId je id; tagy jsou moduly s jejich popisy; každý příklad je jedním z případů měření výkonu schopnosti, jmenovitě, vyhodnoceným proti indexu repozitáře; odpovědi jsou stavy, které router pro daný druh vrací (422 jen pro příkaz), a default pro to, co přidává transport; query parametr nikdy není nullable; x-majordomus-id, -kind, -stability, -provenance, -benchmark, -cache, -mcp, -cli nesou zbytek; info, licence, kontakt a externalDocs z about.rs a manifestu crate; schémata vyzvednutá do seřazených components; základní dialekt OAS 3.1 | GET /openapi.json, docs/generated/openapi.json a /docs/api/ a /openapi.json webu |
| Swagger UI | stránka shellu, která načítá /openapi.json; nevkládá žádnou specifikaci; její assety pocházejí z připnutého swagger-ui-dist na unpkg, jediné části, která není offline | GET /swagger (/docs je dokumentace) |
| příkazová řádka | capabilities list, describe a projections se dispečují přes expozici cli registru; schema a validate jsou pohledy na registr, ne schopnosti | majordomus capabilities … |
| uzavřenost projekce | expozice cli registru proti deklaraci clap, oběma směry: každé tvrzení zodpovězené spustitelným příkazem a příkazy, které žádná schopnost netvrdí | capabilities projections: majordomus_projections, GET /api/v1/capabilities/projections; řádek projection v capabilities validate |
| reference | index modulů a vestavěných schopností, jedna stránka na spustitelný modul se všemi schopnostmi v plném znění; deklarativní zdroje popsané pravidlem, vypsané živě; příkazová řádka tak, jak ji deklaruje clap | docs/generated/capabilities.md, docs/generated/modules/<id>.md, docs/generated/cli.md, docs/generated/cli.{json,yaml} (majordomus/cli/v1) |
| cíle měření výkonu | každý požadovaný spustitelný soubor na každý vystavený transport a případ, plus systémové cíle; součty pokrytí | majordomus bench, docs/generated/benchmarks.md a docs/generated/benchmarks.{json,yaml} (majordomus/benchmark-matrix/v1) — jeden výpočet, tři kódování |
| manifest registru | vestavěný registr jako data: moduly, deskriptory se schématy a souborem, ve kterém byl každý složen, deklarativní druhy, systémové cíle; hranice, kterou generátor webu čte pro své routy | docs/generated/registry.{json,yaml} (majordomus/capability-registry/v1) |
| manifest artefaktů | samotný plán generování: každý artefakt s dokumentem, který promítá, jeho kódováním, schématem, které jeho obsah splňuje, jeho zdrojem, velikostí a hashem | docs/generated/artifacts.{json,yaml,md} (majordomus/generated-artifacts/v1); zpětně čtou artifacts.list — majordomus_artifacts, GET /api/v1/artifacts, majordomus://artifacts, /cockpit/artifacts a /registry/artifacts/ webu |
| executions | každou spustitelnou schopnost lze spustit jako provedení, sledovat po živém kanálu a přečíst zpět; politika deskriptoru execution rozhoduje, co smí klient nabídnout, a nic se neregistruje podruhé | majordomus run, executions.*, GET /events, /cockpit/executions (EXECUTIONS.md) |
| čítače výkonu | čítače exekutoru a startovních fází | perf.counters: majordomus_perf, GET /api/v1/perf |
| seznamy povolených | schémata | share/allow/*.txt, každý pod bannerem původu #, který každý čtenář přeskakuje |
| datová sada webu | registr (otisk, počty, každý vestavěný deskriptor celý s jeho zdrojovým souborem, každý modul s jeho id), index (otisk, každý objekt bez obsahu), druhy, deklarované projekce poskytovatelů, příkazová řádka, nástroje a zdroje MCP, routy HTTP, cíle měření výkonu, pokrytí, politika a přijaté základní hodnoty; žádné vlastní časové značky, žádné absolutní cesty, žádný stav gitu | site/data/registry/registry.json (majordomus-site-registry/v2) — majordomus generate site; vykresleno pod /registry/ (přehled, spustitelný soubor, moduly, schopnosti, cli, mcp, měření výkonu) |
| bootstrapy poskytovatelů | projections[] politiky, profily a šablony poskytovatelů (.ai/repo/providers/, jinak share/providers/); razítko nese hash politiky a hash obsahu; bajtově shodné s update shellového nástroje | AGENTS.md, CLAUDE.md, GEMINI.md, … — majordomus generate providers |
Co každá projekce říká o sobě, pochází z about.rs: OpenAPI info, instrukce MCP initialize a index HTTP (GET /) se otevírají stejným shrnutím a nesou stejné odstavce, takže žádné rozhraní nepopisuje povrch vlastními slovy. Infrastrukturní trasy /, /openapi.json, /swagger a /mcp patří samotné projekci HTTP a nejsou schopnostmi; /mcp je MCP přes HTTP (polovina požadavků transportu Streamable HTTP, s relacemi Mcp-Session-Id) a existuje jen na sdíleném serveru. Repozitář obsluhuje jeden sdílený server: první majordomus mcp nebo serve jej naváže, každý další majordomus mcp k němu přemostí svůj stdio a peeři se vidí navzájem přes peers.list; životní cyklus je v MCP.md.
Pořadí je také projekce
Kolekce má jedno pořadí a každá plocha vykreslí posloupnost, kterou dostala. Pořadí je apps/majordomus-cli/src/order.rs: úplné uspořádání podle čtyř částí, od nejdůležitější — sémantická skupina (žádná řadí poslední), explicitní pořadí u kolekcí, jejichž doména jej deklaruje (weight u okamžiku, publika, oblasti, funkce), popisek porovnávaný přirozeně (řady číslic podle hodnoty, takže item-2 předchází item-10; ASCII bez ohledu na velikost písmen, takže Alpha a alpha zůstanou vedle sebe) a kanonická identita.
Identita je to, co činí pořadí úplným, a ne jen úhledným. Dvě položky se stejným popiskem si nesmějí vyměnit místa, protože byla přidána nesouvisející položka, byl použit jiný iterátor nebo jiný stroj vyčíslil jinak.
Chcete-li se připojit, implementujte order::Ordered na typu — vedle typu, ne vedle rendereru — a zavolejte order::canonical(). Nic dalšího se neupravuje: každá projekce, která kolekci ukazuje, ukáže novou posloupnost.
Chcete-li ho ověřit, spusťte scripts/ci/order-check. Tři jeho kontroly jsou absolutní — žádný komparátor ignorující velikost písmen mimo order.rs, žádný třídicí klíč volající render(), žádné .localeCompare( pod scripts/, share/ nebo site/ — a jedna je rohatka nad dluhem, který pravidlo předchází, držená jako dva počty v .ai/repo/order-baseline.txt: třídicí místa v crate mimo order.rs a shellová volání sort nepřipnutá přes LC_ALL=C. Obě hodnoty smějí klesat a nesmějí růst; commit, který přejde na kanonické pořadí, sníží základní hodnotu pomocí scripts/ci/order-check --update.
Seskupování je první částí pořadí a také se odvozuje. Oblast modulu schopnosti jsou oblasti funkcí, které jej pojmenovávají v modules:, rozřešené weight samotného katalogu — nejnižší první, shody podle id. Žádný modul oblast nedeklaruje a žádný soubor neuvádí dvojice; boční panel Cockpitu se ptá modelu produktu. Dvě funkce, které pojmenovávají jeden modul a nesdílejí žádnou oblast, se neshodují v tom, k čemu modul slouží: rozřešení zůstává deterministické a neshoda se hlásí jako contested_area příkazem majordomus product validate, aby se vyřešila v souboru funkce, a ne rozhodnutím remízy. ADR 0026 zaznamenává, proč se rodič odvozuje, a nedeklaruje.
Chcete-li diagnostikovat neočekávané pořadí, čtěte klíč, ne výstup. Kolekce řazená jinak než order.rs má vlastní názor; kolekce, jejíž klíč končí před identitou, má shody a shoda je místo, kde pořadí vypadá jako souběh, i když žádný není. Pravidlo je project.canonical-order; rozhodnutí zaznamenává ADR 0025.
Jediná projekce, která se může rozejít
Každá projekce v tabulce výše se staví procházením registru. Nástroj MCP, trasa HTTP, operace OpenAPI, cíl měření výkonu a stránka reference nemohou existovat bez deskriptoru a deskriptor je nemůže nevytvořit: není co porovnávat, protože existuje jen jedna deklarace.
Příkazová řádka je jiná. Je deklarována podruhé, v clap, v apps/majordomus-cli/src/cli.rs, protože clap vlastní parsování, --help, výchozí hodnoty a množiny hodnot, a odvodit to z registru by znamenalo reimplementovat parser argumentů, jen aby se dvakrát nepsala cesta. CliExposure proto není projekce — je to tvrzení o deklaraci, která žije jinde, a dvě deklarace se mohou rozejít.
Ano. repository.scope_classify deklaroval cli: ["scope", "classify"], aby modul příkazu mohl najít své id přes by_cli. Takový podpříkaz neexistuje: majordomus scope classify parsuje classify jako cestu k posouzení a odpoví out undeclared classify [absent]. Tvrzení opakoval capabilities describe, docs/generated/cli.md i datová sada registru webu a nic si toho nevšimlo, protože jediný test projekce CLI se ptal registru, zda souhlasí sám se sebou.
capability/closure.rs porovnává obě deklarace:
- tvrzení, na které příkazová řádka neodpovídá je selhání —
CLOSURE_CLI_ABSENTpro cestu, kterou clap nezná,CLOSURE_CLI_NOT_RUNNABLEpro cestu, která jen seskupuje jiné příkazy. Nález jmenuje schopnost, tvrzení, soubor, který ho deklaruje, soubor, který deklaruje příkazovou řádku, a příkaz, který ho ukáže znovu. - spustitelný příkaz, který nenárokuje žádná schopnost, není selhání.
serveamcpspouštějí procesy,generatezapisuje soubory a slovesa worktree volají službu přímo; žádné z nich není schopnost a některé nikdy nebudou. Seznam se hlásí jako míra toho, kolik příkazové řádky je stále psáno ručně, a ne odvozeno.
Je to čistá funkce registru a stromu clap — žádný repozitář, žádné prostředí, žádná síť — takže běží v unit testu, v tests/projections.rs a jako řádek projection v capabilities validate, který CI spouští přes scripts/rust-check --integration.
majordomus capabilities projections odpovídá na tutéž matici přes příkazovou řádku, HTTP i MCP, s --unmet pro samotná selhání.
Životní cyklus a politika selhání
discover the repository -> locate the share directory -> load kinds and schemas
-> discover files through sources.yaml -> read and validate each into an object or a diagnostic
-> build the registry (refuse on any invariant) -> construct the projection asked for -> serve or generate
Manifest, sources.yaml, soubory druhů a schémata jsou chyby, když je nelze přečíst: bez nich nelze nic objevit. Každý jiný soubor, který se nemůže stát objektem, se vyloučí s diagnostikou jmenující jeho cestu a stabilní kód, index hlásí degraded a projekce stále obsluhují; --strict degradovaný index odmítne. Porušení invariantu registru je chyba: z registru, který se nesestaví, se neobsluhuje žádná projekce.
Rozšíření
Přidání objektu známého druhu
Zapište soubor tam, kde se dívá třída sources.yaml repozitáře pro daný druh, s front matter nebo YAML, které jeho schéma dovoluje; sledujte jej (nebo spusťte s --discovery filesystem); restartujte. Je to schopnost typu zdroj, zdroj MCP, člen objects.list, čitelný přes objects.get přes MCP i HTTP (jedno rozřešení URI, sdílené se čtením zdroje MCP, které také odpovídá na majordomus://repository jako na report repository.info), a vypsaný pomocí capabilities list. Žádný Rust, žádná registrace, žádná upravená projekce. apps/majordomus-cli/tests/external_extension.rs mezi restarty přidává, odebírá a láme objekty a čte je zpět přes každé rozhraní.
Přidání druhu se schématem z repozitáře
.ai/repo/knowledge/kinds.yaml schema: majordomus-kinds/v1 + one kinds: entry
.ai/repo/knowledge/schemas/note.schema.json its JSON Schema
.ai/repo/knowledge/sources.yaml a class mapping a pathspec to the kind
Potom objekty. Stejný test to dokazuje pro druh pojmenovaný note. Druh, který potřebuje nový formát nebo pravidlo identity, je změna v Rustu v index.rs; data popisují objekty, nedefinují, jak se formát čte.
Přidání spustitelné schopnosti
V souboru jeho modulu pod apps/majordomus-cli/src/capability/builtin/:
- definujte typovaný vstup a výstup (
serde+schemars::JsonSchema; komentáře dokumentace jsou popisy, které čte každý klient) a implementujteBenchmarkCasespro vstup (jeden či více reprezentativních vstupů; případ se smí podívat do indexu, aby jmenoval existující objekt), - napište jednu funkci
fn(&Context, Input) -> Result<Output, CapabilityError>; kontext nese index, registr, nástěnku peerů, executor a, přes relaci MCP, volajícího peera, - přidejte jeden blok
capability! { id, title, description, input, output, stability, exposure, tags, handler }docapabilities: [...]modulu, skind: CapabilityKind::Commandza id, když mění paměť tohoto procesu, scache: CachePolicy::Process { .. }, když to říká měření, a s.cancellable()za blokem, když handler pohlédne nactx.progress.cancelled()a skončí, - spusťte
majordomus generateamajordomus capabilities validate(nebojust generateajust validate); commitněte regenerované soubory poddocs/generated/, - přidejte behaviorální test sémantiky handleru.
To je celý workflow. MCP, HTTP, OpenAPI, Swagger UI, příkazy capabilities, cíle měření výkonu na každém vystaveném transportu (s případy z kroku 1), chování cache, perf.counters, reference, matice měření výkonu a manifest registru z bloku vyplynou; generické sady (tests/projections.rs, tests/bench.rs, tests/executor.rs, tests/properties.rs, tests/hot_path.rs) schopnost objeví přes registr a otestují ji bez úprav. Schopnost, jejíž vstupní typ nemá BenchmarkCases, se nepřeloží; ta, jejíž případy jsou pro repozitář prázdné, selže v pokrytí.
Přidání modulu
Jeden modul Rustu pod builtin/ s jeho module() sestaveným pomocí module! a jedno jméno přidané do compose_modules! v builtin/mod.rs. Jeho stránka reference, jeho řádky v matici a jeho položka v manifestu se generují.
Generované projekce a synchronizace
majordomus generate [all|openapi|docs|benchmarks|registry|allow|providers|site|manifest] zapíše každý artefakt vybraných cílů; majordomus generate --check je odvodí znovu, porovná bajt po bajtu, nic nezapíše a skončí s 10 se jmény každého zastaralého souboru. CI spouští kontrolu. Generátor webu spotřebovává registry.json, openapi.json a artifacts.json a nic jiného z crate; scripts/derive spouští oba generátory v pořadí závislostí a scripts/derive-check skládá obě kontroly (docs/GITHUB_PAGES_ARCHITECTURE.md). Commitnuté soubory jsou cache: přezkoumatelné, nikdy neupravované. Co je generováno, zde není vypsáno — docs/generated/artifacts.md je ten seznam a je generovaný.
Odvození odmítne program jiné generace. Každý artefakt je projekcí modelu zkompilovaného do programu, který ho zapisuje, takže binárka sestavená z jiné revize crate přepíše všechny z modelu, který strom nemá — tiše, protože nic v bajtech neříká, který program je vytvořil. Řetězec verze ty dva nerozliší: dne 2026-09-10 binárka, která se jmenovala stejnou verzí a byla předána přes MAJORDOMUS_BIN, ohlásila jedenáct artefaktů jako zastaralých na čistém origin/master a jejich přepsání odstranilo 16 625 řádků s exit 0. Proto se generate u repozitáře, který tento crate deklaruje, ptá postupně na tři věci a pokračuje podle první zodpovězené: verze se musí shodovat, protože je vtištěna do každé hlavičky provenience; generace — digest, který generation::crate_generation počítá nad apps/majordomus-cli/{Cargo.toml,Cargo.lock,build.rs,src}, zkompilovaný přes build.rs — se smí rovnat generaci stromu, což znamená, že tento program byl sestaven z těchto zdrojů; nebo model, který promítá, se smí rovnat vestavěné polovině registru, který strom commitnul v docs/generated/registry.json — deklarativní druhy tam jsou obsahem repozitáře, ne modelem programu — což drží správně odpovídající předsestavenou MAJORDOMUS_BIN funkční bez přestavby. Jinak odmítne s REFUSED (15) a nic nezapíše. Repozitáře, který tento crate nedeklaruje, se neptá vůbec nic: vydaná binárka generující cizí repozitář je přesně to, k čemu vydaná binárka slouží. Verdikt záměrně není CONTRACT_UNMET (10): to hlásí skutečně zastaralý artefakt a jeho náprava — spustit generátor — je přesně to, co strom zničí, když je zastaralá binárka. scripts/derive a scripts/derive-check ty dvě rozlišení propagují.
Každý artefakt je typovaný. Deklaruje dokument, který promítá, kódování, v němž je zapsán (json, yaml, markdown, text, shodné s jeho příponou), schéma, které jeho obsah splňuje, má-li dokument smlouvu, a zdroj, z něhož byl odvozen. Pravidlem je project.generated-artifacts-are-typed@1; generate a generate --check plán ověří dříve, než se zapíše nebo porovná jediný bajt, a odmítnou napůl otypovaný strom.
Strukturovaný dokument se zapisuje v každém kódování, v němž se commituje, z jedné hodnoty. generate::Document drží hodnotu; JSON a YAML jsou dvě vykreslení téže hodnoty, nikdy dva výpočty, a dokument, jehož publikum zahrnuje čtenáře, má též vykreslení v Markdownu téže hodnoty. Proto matice měření v benchmarks.md nemůže být v rozporu s benchmarks.json.
Každý artefakt nese svůj původ ve formě, kterou jeho kódování dovoluje: schema, generated a generator jako členy v JSON; x-majordomus-generated a x-majordomus-generator tam, kde vlastní specifikace dokumentu pevně určuje názvy jeho členů (dokument OpenAPI); komentářový banner # v YAML a v řádkově orientovaném textu; komentář HTML v Markdownu. Bootstrap poskytovatele nese místo toho razítko majordomus update politiky, z níž byl vykreslen. Žádný nenese časové razítko, absolutní cestu ani otisk, který by se pohnul s úpravou dokumentu.
Dokument, který pojmenovává schéma, má publikovanou smlouvu. Žijí pod share/schemas/generated/, jeden soubor na dokument, připnuté k němu členem const jeho schema — objevování schémat druhů nerekuruje, takže nic tam se nikdy nečte jako schéma druhu objektu. generate validuje každý dokument proti jeho smlouvě.
Celou sadu indexuje docs/generated/artifacts.{json,yaml,md}, sám generovaný: každý artefakt s kódováním, smlouvou, zdrojem, velikostí a hashem. Jeho vlastní tři kódování hash nenesou — dokument, který by hashoval sám sebe, by neměl pevný bod — a --check je místo toho porovná bajt po bajtu. artifacts.list ten manifest načte zpět a sjednotí s pracovním stromem, což je to, co ukazují nástroj MCP, trasa HTTP, stránka Artifacts v Cockpitu i /registry/artifacts/ webu.
Když něco selže
| zpráva | význam | náprava |
|---|---|---|
capability 'x' is defined twice: <a> and <b> | dva zdroje si nárokují jedno id | přejmenujte jeden, nebo smažte duplikát |
MCP tool 'n' is claimed by 'a' and 'b', HTTP route GET /p is claimed by …, CLI path … is claimed by … | dvě schopnosti se promítají na jedno jméno | změnit jednu expozici |
invalid HTTP exposure: path '/x' is not under /api/v1/ | trasa mimo verzovaný prefix | přesuňte to pod předponu |
declares the execution policy …; its kind makes it … | deskriptor nese politiku, která není ani politikou svého druhu, ani politikou svého druhu se zrušením | nechte deklaraci klasifikovat se samu, nebo přidejte .cancellable() |
… is planned and cannot be exposed as executable through MCP tool | plánovaná schopnost deklaruje spustitelnou expozici | odstranit vystavení, dokud není implementováno |
unknown_key … not in schema 'rule': owner | deklarativní soubor nese klíč, který jeho schéma nepovoluje | odstraňte klíč, nebo rozšiřte schéma v schemas/ repozitáře pro druh repozitáře |
schema_violation … class: "fatal" is not one of … | hodnota porušuje omezení | opravte hodnotu |
kind 'x' is declared by both share/kinds.yaml and .ai/repo/knowledge/kinds.yaml | repozitář předefinuje distribuovaný druh | přejmenovat druh repozitáře |
generated artifact(s) stale: docs/generated/openapi.json (differs) | commitnutá projekce už neodpovídá registru | spusťte majordomus generate a commitněte |
this executable is not of this tree's generation | spustitelný soubor byl sestaven z jiné revize crate a promítá jiný model | přebuildujte, nebo spusťte scripts/derive s nenastaveným MAJORDOMUS_BIN — ne majordomus generate, což přepisuje artefakty ze špatného modelu |
capability 'x.y' (builtin …) is composed in module 'z' but its namespace is 'x' | blok capability! je v seznamu nesprávného modulu | přesuňte jej do modulu, který jmenuje jeho id, nebo id přejmenujte |
module 'x' is composed twice | dva module! sdílejí id, nebo id vestavěného modulu je deklarativní druh | jednu přejmenovat |
invalid cache policy: a process cache with max_entries 0 keeps nothing, … a command changes state and is never cached | politika cache deskriptoru odporuje sama sobě nebo druhu | opravit politiku na deskriptoru |
FAIL benchmarks N of M requirement(s) missing | vstupní typ vystaveného spustitelného souboru nevytvořil pro tento repozitář žádný případ | přimět BenchmarkCases, aby vrátil případ (nebo prominout typovaným důvodem, který se hlásí) |
bench --check: regression(s) found | metrika vzrostla nad .ai/repo/benchmarks/rust/policy.yaml oproti základní hodnotě této platformy | najděte příčinu pomocí majordomus bench <id> a časování fází, nebo záměrně zaznamenejte nový základní stav |
STALE <key> (in the baseline, not measured …) | základní hodnota zná cíl, který tento běh neměřil: přejmenovaný, odstraněný nebo odfiltrovaný | bench baseline update po přejmenování nebo odstranění |
no share directory holds kinds.yaml; tried … | distribuce nebyla nalezena | předejte --share nebo nastavte MAJORDOMUS_SHARE |
Stabilita
| status | |
|---|---|
| invarianty registru, oba zdroje, deterministické sestavení | behaviorálně ověřeno (tests/registry.rs) |
| každá deklarovaná projekce přítomna, žádná sirotčí, jedno id všude; změna jednoho deskriptoru se dostane do MCP, OpenAPI i reference | behaviorálně ověřeno (tests/projections.rs) |
| HTTP přes skutečný socket, OpenAPI, shell Swaggeru, typované chyby, MCP a HTTP odpovídající na tentýž handler shodně, deklarativní objekt dosahující HTTP a introspekce bez zásahu | behaviorálně ověřeno (tests/http_serve.rs) |
| každá routa přehraná přes socket vlastními případy měření výkonu schopnosti a dokument ukazující tyto případy jako příklady, moduly jako tagy, stavy druhu jako odpovědi, politiky jako rozšíření, jednu prózu s MCP a indexem | behaviorálně ověřeno (tests/http_serve.rs, test/cases/92_openapi_reference.sh); časování benches/routes.rs |
reference API webu vykreslená z commitnutého dokumentu, surový dokument servírovaný na /openapi.json, externalDocs ukazující na stránku | kontrolováno příkazy scripts/generate-site-data --check a scripts/site-check (test/cases/92_openapi_reference.sh) |
jeden sdílený server na repozitář: lease, most, relace /mcp, peery a jejich oznámení, záložní port, odkládání serve, --standalone, převzetí po zabití, opětovné připojení, zamítnutí, když přebírající nemůže obsluhovat | behaviorálně ověřeno (tests/mcp_shared.rs, tests/shared_units.rs, test/cases/90_mcp_shared_server.sh) |
| druh a schéma definované repozitářem se servírují bez změny kódu; přidat, odebrat, rozbít | behaviorálně ověřeno (tests/external_extension.rs) |
generování, bajtově shodné opětovné generování, --check u chybějících a pozměněných souborů | behaviorálně ověřeno (tests/generate_check.rs) |
| moduly skládají schopnosti, kořen skládá moduly, invarianty modulů | ověřeno chováním (tests/registry.rs, test/cases/91_canonical_architecture.sh) |
| jeden executor; cache vypnutá, studená a teplá se shodují; zásah nespustí žádný handler; chyby a příkazy se nikdy nekešují; mez; otisk | ověřeno chováním (tests/executor.rs, tests/properties.rs) |
| žádný požadavek po startu nepřestavuje kanonický stav (čítače přes stovky skutečných požadavků) | ověřeno chováním (tests/hot_path.rs, test/cases/91_canonical_architecture.sh) |
| každá operace je cílem měření výkonu, generovaný jmenovatel, expozice a propagace politiky, skutečné runnery, kontrola proti baseline | behaviorálně ověřeno (tests/bench.rs, tests/bench_units.rs, test/cases/91_canonical_architecture.sh) |
| generovaná reference na modul, matice měření výkonu, manifest registru, deterministické a sladěné | behaviorálně ověřeno (tests/projections.rs) |
celá cesta přes vlastní init shell nástroje | behaviorálně ověřeno (test/cases/76_capabilities_projections.sh) |
gramatika id, URI, názvy nástrojů, cesty tras, diagnostické kódy, kinds.yaml, soubory schémat | implementováno; kompatibilní plochy před verzí 1.0, změny zdokumentovány, nikdy tiše |
Aktiva Swagger UI offline nebo na webu, příklady odpovědí, /openapi.yaml, parametry cesty, hot reload, mutace repozitáře přes jakékoli rozhraní, stream iniciovaný serverem na /mcp | neimplementováno; smlouvou je znovuobjevení po restartu a sdílený server drží index, který sestavil při startu, dokud neodejde jeho poslední klient |