2. Kanonický registr schopností, s MCP, HTTP, OpenAPI, Swagger UI, CLI a referencí jako projekcemi
Rozšiřuje ADR 1.
Kontext
ADR 1 přidalo spustitelný soubor v Rustu s jedním příkazem, mcp, a ručně psanou tabulku čtyř nástrojů a výpis zdrojů v kódu MCP. Operátor požádal o tytéž schopnosti přes HTTP s dokumentem OpenAPI a Swagger UI, o introspekci z příkazové řádky a o generovanou referenční dokumentaci s jednou tvrdou invariantou: schopnost se definuje jednou a každé rozhraní se z této definice odvozuje, aby se žádná dvě rozhraní nemohla mlčky rozejít. Doktrína samotného repozitáře říká totéž o generovaných souborech (project.derived-files-regenerated) a o číslech v próze.
Rozhodnutí
- Jeden model.
Capabilityje typovaný deskriptor: kanonické id, druh (queryneboresource), název, popis, kanonická schémata vstupu a výstupu, původ, vystavení (nástroj a/nebo zdroj MCP, metoda a cesta HTTP, cesta CLI — každé výslovné, žádné odvozené), stabilita, štítky. Dotaz nese jednu typovanou obslužnou funkci; zdroj se čte. - Dva zdroje, jeden registr. Vestavěné spustitelné soubory se skládají výslovně v
capability/builtin.rspřesmacro_rules!, který jen vyplní deskriptor a obalí typovanou funkci; žádné procedurální makro, žádný linkerový registr, žádné generování kódu. Každý objekt indexu se stává schopností typu zdroj. Obojí se potkává vCapabilityRegistry, sestaveném na jednom místě (app.rs), které odmítá duplicitní id, duplicitní jména a URI MCP, duplicitní HTTP trasy, duplicitní cesty CLI, špatně utvořené expozice a spustitelnou expozici na plánované nebo nepodporované schopnosti, a jmenuje každou stranu. - Schémata z typů, za běhu z dat. Vstupní a výstupní schémata spustitelných souborů pocházejí z typů Rustu (
schemars); kontrakt metadat každého deklarativního druhu je JSON Schema (draft 2020-12) čtené za běhu zshare/schemas/a validované validátorem JSON Schema;share/kinds.yamlříká, jak se každý druh čte. Repozitář přidává druhy a schémata pod.ai/repo/knowledge/; distribuovaný druh předefinovat nemůže. - Projekce. MCP (
mcp/surface.rs), HTTP routy s vazbou GET dotazu a POST těla (http/router.rs), OpenAPI 3.1 soperationId= kanonické id a rozšířenímix-majordomus-*(http/openapi.rs), shell Swagger UI, který načítá/openapi.jsona nic nevkládá (http/swagger.rs), příkazycapabilitiesdispatchované přes CLI expozici registru,docs/generated/openapi.jsonadocs/generated/capabilities.mdz jednoho generátoru ashare/allow/*.txtshell nástroje odvozené ze schémat.majordomus generate --checkporovná každou commitnutou projekci s registrem a skončí s kódem 10, když je některá zastaralá. - HTTP je loopback a jen pro čtení.
servese váže na 127.0.0.1, pokud není řečeno jinak, nemá autentizaci, protože nevystavuje nic, co už není na disku pro téhož uživatele, a žije tak dlouho jako jeho stdin, je-li to roura.
Invarianty
- Kanonická id jsou jedinečná napříč oběma zdroji.
- Žádná projekce nenese položku, kterou registr nedrží, a žádné nechybí položka, kterou registr pro ni deklaruje (
tests/projections.rs). - Každé schéma, které projekce ukazuje, pochází z kanonického schématu deskriptoru.
- Generovaný výstup je deterministický: seřazené mapy, žádná časová razítka, žádné absolutní cesty.
- Commitnuté projekce jsou reprodukovatelné a jejich zastaralost se detekuje.
- Projekce nemůže předefinovat sémantiku schopnosti: MCP a HTTP volají tentýž handler (
tests/http_serve.rs, parita napříč protokoly). - Plánovaná schopnost může být uvedena, ale nikdy není spustitelná přes žádnou projekci.
Zamítnuté alternativy
- OpenAPI jako zdroj pravdy. Nedokáže vyjádřit zdroje MCP, cesty CLI ani deklarativní vrstvu a udělalo by z formátu dokumentace vlastníka chování.
- MCP jako zdroj pravdy. Stejná námitka z druhé strany; a MCP nemá pojem routy.
- Ručně udržované paralelní tabulky pro nástroje, routy a dokumentaci: drift, který operátor označil za problém.
- OpenAPI řízené anotacemi (atributy ve stylu
utoipana handlerech) duplikující cestu, popis a id operace vedle deskriptoru; a druhý HTTP stack (axums asynchronním runtime) pro šest loopback tras, kde stačí synchronní smyčkatiny_http. - Registr pouze za běhu bez commitnuté projekce: revidovatelné diffy rozhraní by neexistovaly.
- Procedurální makra nebo registrace v čase linkování (
inventory,linkme): skladba by přestala být čitelná v jednom souboru. - Povolené seznamy regulárních výrazů jako kontrakt pro deklarativní druhy: netypované, nestandardní a repozitář je nemůže rozšířit, aniž by kód naučil nový seznam.
Důsledky
Registr, gramatika id, schéma URI, názvy nástrojů, cesty tras, diagnostické kódy a dva soubory schémat se stávají povrchy kompatibility. Vrstvu nyní čtou dva spustitelné soubory a seznamy povolených položek shell nástroje se generují ze schémat, takže schémata jsou kontrakt a seznamy projekce; shell nástroj se nemění. Seznam „Intentionally Absent“ repozitáře dál odmítá démony a registry pracovníků; tento registr indexuje vlastní povrch nástroje a nic jiného.
Strategie testování
Nejdřív black-box: zkompilovaný binární soubor se spouští pro CLI, MCP přes roury, HTTP přes loopback socket a generate --check; invarianty registru a šíření změny v jednom deskriptoru do každé projekce jsou knihovní testy nad fixture registry; test/cases/76_capabilities_projections.sh přečte jednu schopnost zpět přes každé rozhraní z repozitáře, který zapsal init shell nástroje. CI spouští cargo fmt --check, clippy -D warnings, cargo test s doctesty, cargo doc s varováními jako chybami, generate --check, capabilities validate a práh pokrytí řádků.