From c720992a13d61bb27a0a24d45346e1104e15564a Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 24 Aug 2026 07:59:30 +0100 Subject: [PATCH] refactor: migrate repository documentation from Markdown to AsciiDoc --- CHANGELOG.adoc | 198 +++++++++ CHANGELOG.md | 86 ---- CODE_OF_CONDUCT.adoc | 28 ++ CODE_OF_CONDUCT.md | 18 - CONTRIBUTING.adoc | 147 +++++++ CONTRIBUTING.md | 62 --- DEBT.adoc | 377 ++++++++++++++++++ DEBT.md | 155 ------- GOVERNANCE.adoc | 60 +++ GOVERNANCE.md | 60 --- SECURITY.adoc | 66 +++ SECURITY.md | 34 -- audits/cartridge-schema-2026-06-01.adoc | 8 + audits/cartridge-schema-2026-06-01.md | 7 - audits/panic-attack-scan-2026-06-01.adoc | 190 +++++++++ audits/panic-attack-scan-2026-06-01.md | 157 -------- ...{ABI-FFI-README.md => ABI-FFI-README.adoc} | 240 ++++++----- .../_source-archive/README.adoc | 254 ++++++++++++ .../_source-archive/README.md | 235 ----------- .../git-lsp/_source-archive/README.adoc | 118 ++++++ .../git-lsp/_source-archive/README.md | 105 ----- .../proof-lsp/_source-archive/README.adoc | 178 +++++++++ .../proof-lsp/_source-archive/README.md | 148 ------- .../domains/gaming/npc-mcp/INSTALL.adoc | 47 +++ cartridges/domains/gaming/npc-mcp/INSTALL.md | 43 -- cartridges/domains/gaming/npc-mcp/README.adoc | 52 +++ cartridges/domains/gaming/npc-mcp/README.md | 48 --- .../knowledge/librarian-mcp/INSTALL.adoc | 74 ++++ .../knowledge/librarian-mcp/INSTALL.md | 68 ---- .../knowledge/librarian-mcp/README.adoc | 88 ++++ .../domains/knowledge/librarian-mcp/README.md | 82 ---- .../observe-lsp/_source-archive/README.adoc | 115 ++++++ .../observe-lsp/_source-archive/README.md | 100 ----- .../web/ssg-lsp/_source-archive/README.adoc | 34 ++ .../web/ssg-lsp/_source-archive/README.md | 32 -- ...ho-types-integration-audit-2026-06-01.adoc | 376 +++++++++++++++++ ...echo-types-integration-audit-2026-06-01.md | 320 --------------- schemas/SCHEMA-MIRROR.adoc | 50 +++ schemas/SCHEMA-MIRROR.md | 31 -- tools/auth-method-batch-fix/README.adoc | 38 ++ tools/auth-method-batch-fix/README.md | 38 -- tools/cartridge-minter/README.adoc | 123 ++++++ tools/cartridge-minter/README.md | 100 ----- tools/category-batch-fix/README.adoc | 30 ++ tools/category-batch-fix/README.md | 30 -- tools/missing-fields-batch-fix/README.adoc | 51 +++ tools/missing-fields-batch-fix/README.md | 44 -- tools/validate-cartridges/README.adoc | 34 ++ tools/validate-cartridges/README.md | 34 -- 49 files changed, 2868 insertions(+), 2145 deletions(-) create mode 100644 CHANGELOG.adoc delete mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.adoc delete mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.adoc delete mode 100644 CONTRIBUTING.md create mode 100644 DEBT.adoc delete mode 100644 DEBT.md create mode 100644 GOVERNANCE.adoc delete mode 100644 GOVERNANCE.md create mode 100644 SECURITY.adoc delete mode 100644 SECURITY.md create mode 100644 audits/cartridge-schema-2026-06-01.adoc delete mode 100644 audits/cartridge-schema-2026-06-01.md create mode 100644 audits/panic-attack-scan-2026-06-01.adoc delete mode 100644 audits/panic-attack-scan-2026-06-01.md rename cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/{ABI-FFI-README.md => ABI-FFI-README.adoc} (74%) create mode 100644 cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/README.adoc delete mode 100644 cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/README.md create mode 100644 cartridges/domains/development/git-lsp/_source-archive/README.adoc delete mode 100644 cartridges/domains/development/git-lsp/_source-archive/README.md create mode 100644 cartridges/domains/formal-verification/proof-lsp/_source-archive/README.adoc delete mode 100644 cartridges/domains/formal-verification/proof-lsp/_source-archive/README.md create mode 100644 cartridges/domains/gaming/npc-mcp/INSTALL.adoc delete mode 100644 cartridges/domains/gaming/npc-mcp/INSTALL.md create mode 100644 cartridges/domains/gaming/npc-mcp/README.adoc delete mode 100644 cartridges/domains/gaming/npc-mcp/README.md create mode 100644 cartridges/domains/knowledge/librarian-mcp/INSTALL.adoc delete mode 100644 cartridges/domains/knowledge/librarian-mcp/INSTALL.md create mode 100644 cartridges/domains/knowledge/librarian-mcp/README.adoc delete mode 100644 cartridges/domains/knowledge/librarian-mcp/README.md create mode 100644 cartridges/domains/observability/observe-lsp/_source-archive/README.adoc delete mode 100644 cartridges/domains/observability/observe-lsp/_source-archive/README.md create mode 100644 cartridges/domains/web/ssg-lsp/_source-archive/README.adoc delete mode 100644 cartridges/domains/web/ssg-lsp/_source-archive/README.md create mode 100644 docs/echo-types-integration-audit-2026-06-01.adoc delete mode 100644 docs/echo-types-integration-audit-2026-06-01.md create mode 100644 schemas/SCHEMA-MIRROR.adoc delete mode 100644 schemas/SCHEMA-MIRROR.md create mode 100644 tools/auth-method-batch-fix/README.adoc delete mode 100644 tools/auth-method-batch-fix/README.md create mode 100644 tools/cartridge-minter/README.adoc delete mode 100644 tools/cartridge-minter/README.md create mode 100644 tools/category-batch-fix/README.adoc delete mode 100644 tools/category-batch-fix/README.md create mode 100644 tools/missing-fields-batch-fix/README.adoc delete mode 100644 tools/missing-fields-batch-fix/README.md create mode 100644 tools/validate-cartridges/README.adoc delete mode 100644 tools/validate-cartridges/README.md diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc new file mode 100644 index 00000000..64ff7298 --- /dev/null +++ b/CHANGELOG.adoc @@ -0,0 +1,198 @@ +== Changelog + +All notable changes to `+boj-server-cartridges+` are recorded here. +Format follows https://keepachangelog.com/en/1.1.0/[Keep a Changelog]; +the project adheres to https://semver.org/spec/v2.0.0.html[Semantic +Versioning]. + +____ +*No release has ever been tagged.* There are no git tags in this +repository and no GitHub releases. The `+[0.1.0]+` heading below marks +the 2026-06-01 milestone, not a published artefact — treat it as a dated +section, not a version you can fetch. +____ + +=== https://github.com/hyperpolymath/boj-server-cartridges/commits/main[Unreleased] + +Everything landed on `+main+` since the 2026-06-01 milestone — 71 +commits, none of which were recorded here. + +==== Added + +* *This repository became the sole source of BoJ cartridges.* +`+boj-server+` retired its own bundled `+cartridges/+` tree in +https://github.com/hyperpolymath/boj-server/pull/300[boj-server#300] +(merged 2026-08-04). There is no second copy: what lands here is what +every host fetches. +* *Foundry* — a high-assurance cartridge-making subsystem under +link:tools/foundry/[`+tools/foundry/+`], gated by +link:.github/workflows/foundry.yml[`+.github/workflows/foundry.yml+`], +with a machine-checked Idris2 design proof at +link:tools/foundry/proof/Foundry.idr[`+tools/foundry/proof/Foundry.idr+`]. +Landed across `+002ac93+` (factory + textkit-mcp, A1 closure), +`+29e1734+` (the checked design proof), `+0b54a8a+` (Provision stage — +capability partition + enforcement), `+1fb2349+` (per-kind obligation +bundles, #44) and `+caeb14e+` (the missing Configure stage; the wizard +now fails closed, #102). +* *Proofs Gate* — `+368143a+` (#40) added Idris2 to CI here for the +first time and reconciled *23 cartridge ABI proofs across 21 cartridges* +that had silently stopped type-checking in this repo while their +`+boj-server+` twins still passed. Nothing had run `+idris2+` in this +repository before. +* *Foundry Wave-1 "`Golden Dozen`"* (`+be17f66+`) — the first 12 +cartridges marked `+"available": true+`. They remain the only 12. +* New cartridges: *bug-filing-mcp* (`+373dce6+`, wrapping the +feedback-o-tron engine; `+5a8be0c+` v0.2 interactive loop tools + full +cartridge layout; `+d0d89f6+` unified adapter) and *cicd-squabbler-mcp* +(`+77a2edb+`, with review follow-ups in `+6767196+`). +* *Presence site* for +https://cartridges.boj-server.net/[cartridges.boj-server.net] — +`+1bab028+` added link:site/[`+site/+`] plus a Cloudflare Pages deploy +action; `+b1c09f2+` (#93) added docs deployment via Ddraig SSG. +* SonarCloud scan workflow, config and badge (`+bf92407+`, #64); OpenSSF +Best Practices badge (`+5734305+`). +* link:docs/cartridge-authoring.adoc[`+docs/cartridge-authoring.adoc+`], +link:docs/known-issues/adapters.adoc[`+docs/known-issues/adapters.adoc+`] +and +link:docs/decisions/ADR-0006-cartridge-invoke-abi.adoc[`+docs/decisions/ADR-0006-cartridge-invoke-abi.adoc+`] +— the layer contract and ABI were previously documented only inside a +tool config file, and 458 in-tree files cited an ADR-0006 that did not +exist here. +* link:tools/build-catalog/[`+tools/build-catalog/+`] — generates +`+site/catalog.json+` from the manifests. It had been hand-maintained +and had drifted; there was no generator at all. +* `+just mint+`, `+just validate+`, `+just catalog+`, +`+just catalog-check+`. The minter script already existed but had no +recipe. + +==== Changed + +* *`+README.md+` → `+README.adoc+`* (`+e75661f+`, #69) per the estate +`+.adoc+`-default policy. This broke the two `+README.md+` links in +`+CONTRIBUTING.md+`, now repaired. +* *`+GOVERNANCE.adoc+` removed, `+GOVERNANCE.md+` kept* (`+c2da9ed+`). +Note this inverts the repo’s own `+.adoc+`-default policy, under which +`+GOVERNANCE+` is not an exempt filename — see the open conflict noted +below. +* Licence normalised to the canonical MPL-2.0 + CC-BY-SA-4.0 pair +(`+4f1d042+`, #60). +* Retired local issue/discussion templates in favour of the org +`+.github+` canon (`+2ec1bff+`). +* Secret scanning standardised on TruffleHog (`+f20955a+`), then +re-pinned onto the real gitleaks gate with the retired inline job +dropped (`+5013853+` #99, `+10d92c0+` #101). +* Substantial CI remediation: path-filtered required gates made to +always report (`+d9c7898+`), 7 startup-failing workflows repaired and +the schema mirror re-pinned (`+de20566+`, #70), reusable-call job +permissions granted (`+65e91da+`, #71), the governance gate closed on +SPDX/permissions/SHA pins (`+b04274c+`, #103), and estate-wide +foundational remediation (`+18afa91+`, #105). +* `+SCHEMA-MIRROR.md+` pin values reconciled with `+PINNED-SHA+` +(`+08bb723+`, #73). + +==== Fixed + +* *CWE-704* — unchecked `+@ptrCast+` removed from every cartridge shim +(`+47f1ac3+`, #89, 115 files) and from the bug-filing-mcp adapter +dispatch call (`+cb4c0cc+`, #91). The shims now use +`+std.mem.sliceTo(ptr, 0)+` instead of re-typing a raw pointer. +* `+linear-mcp+` implemented against the real Linear GraphQL API +(`+5b4cad8+`, #83). The cartridge itself was not new — it shipped in the +original 125. +* `+007-mcp+`: `+BindAddress.proof+` renamed to `+.witness+` +(`+594d08f+`, #34, closes #33). +* Six hard-coded `+139+`s in `+site/index.html+` and three cartridges +missing from `+site/catalog.json+`; the catalogue also claimed all 139 +entries were `+available: true+` when only 12 manifests say so. +* Counts across `+README.adoc+`, `+CONTRIBUTING.md+` and +`+schemas/SCHEMA-MIRROR.md+` that no longer matched the tree. + +==== Known issues + +* *The `+adapter/+` tree does not build and no CI job compiles it.* +`+zig-test.yml+` globs `+cartridges/**/ffi/**+` only, so none of the 99 +`+adapter/build.zig+` files is gated. The canonical template’s adapter +calls `+ffi.gossamer_init()+`, a symbol defined nowhere in the +repository, and `+just mint+` copies the defect into every new +cartridge. This predates the Zig 0.16 work. See +link:docs/known-issues/adapters.adoc[`+docs/known-issues/adapters.adoc+`]. +* *Shim drift is unenforced.* Nothing in CI compares a cartridge’s +`+cartridge_shim.zig+` against the canonical copy. 115 of the 116 +in-tree shims are byte-identical; `+npc-mcp+`’s differs in comments +only. +* `+GOVERNANCE.md+` versus the repo’s `+.adoc+`-default policy, and +`+.machine_readable/contractiles/Mustfile.a2ml+` still requiring a +`+GOVERNANCE.adoc+` that `+c2da9ed+` deleted. + +==== Not in this section + +The *Zig 0.16.0 migration* +(https://github.com/hyperpolymath/boj-server-cartridges/pull/109[#109]) +is *open, not merged*, and is therefore deliberately absent above. +`+.tool-versions+` on `+main+` still pins `+zig 0.15.1+`, and `+main+` +carries 116 shims, not the 118 that PR describes. Move those entries up +when it lands. + +=== [0.1.0] — 2026-06-01 + +==== Added + +* Initial population from `+boj-server/cartridges/+` (snapshot +2026-05-26): 125 cartridges migrated into the taxonomied layout under +link:cartridges/[`+cartridges/+`] per +link:docs/decisions/ADR-001-taxonomy.adoc[`+docs/decisions/ADR-001-taxonomy.adoc+`]. +* Schema-validation foundation: SHA-pinned mirror of +https://github.com/hyperpolymath/standards/blob/main/cartridges/cartridge-v1.json[`+hyperpolymath/standards/cartridges/cartridge-v1.json+`] +under link:schemas/cartridge-v1.json[`+schemas/cartridge-v1.json+`] (pin +in link:schemas/PINNED-SHA[`+schemas/PINNED-SHA+`], mirror discipline in +link:schemas/SCHEMA-MIRROR.md[`+schemas/SCHEMA-MIRROR.md+`]). +* Zero-dependency Deno validator at +link:tools/validate-cartridges/[`+tools/validate-cartridges/+`] with +three tasks: `+audit+`, `+audit-verbose+`, `+strict+`. +* Strict-mode CI gate +(link:.github/workflows/cartridge-schema.yml[`+.github/workflows/cartridge-schema.yml+`]) +live since 2026-06-01: any manifest that fails schema validation blocks +the PR. +* Wave additions bundled into the v0.1 baseline: vector-DB cartridge +wave (boj-server#100) and multi-modal cartridge wave (boj-server#101). +* Wiki bootstrapped with Home + Cartridge-Schema-Validation + +Refresh-Discipline pages. (Verified 2026-08-07: true — commit +`+c5647a8+` in +https://github.com/hyperpolymath/boj-server-cartridges/wiki[the wiki +repository] adds exactly those three pages. The wiki is a separate git +repository, which is why it is not in this tree.) +* Documented downstream consumer relationship (the on-demand fetch +contract) at `+boj-server#183+`. + +==== Changed + +* Drift-remediation campaigns closed in the run-up to the strict gate +flip: #18 (`+category+` field backfill), #19 (`+auth.method+` enum +mismatches), #20 (canonical-only / missing top-level fields / +name-pattern renames). Post-remediation baseline: 139 / 139 manifests +passing — see +link:audits/cartridge-schema-2026-06-01.md[`+audits/cartridge-schema-2026-06-01.md+`]. +* Per-cartridge `+cartridge_shim.zig+` is now the de facto FFI shim +layout (#29 / #31): 97 `+build.zig+` files rewritten to resolve +`+b.path("cartridge_shim.zig")+` against the local directory (the +`+adapter/build.zig+` case uses `+"../ffi/cartridge_shim.zig"+`). The +canonical shim source remains +link:cartridges/templates/gossamer-mcp/ffi/cartridge_shim.zig[`+cartridges/templates/gossamer-mcp/ffi/cartridge_shim.zig+`] +— [line-through]#112 of 114 in-tree shims are byte-identical to it#. ++ +____ +*Correction (2026-08-07):* the "`112 of 114`" figure did not match the +tree and its provenance is unknown. Recounted on `+main+`: *116 shims, +115 byte-identical to canon*. The single exception is +`+cartridges/domains/gaming/npc-mcp/ffi/cartridge_shim.zig+`, which +differs _only in comments_ — identical API surface (same seven `+RC_*+` +constants, same three helpers). Left struck through rather than silently +rewritten, because this section is a dated historical record. +____ + +==== Fixed + +* `+browser_mcp_error_recover+` now rejects non-Error states with `+-2+` +(#32). The build never previously ran for browser-mcp because of the +shim-path issue, so the test logic bug was masked. Fixed alongside the +#29 build-path rewrite. diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index c6df2139..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,86 +0,0 @@ - - - -# Changelog - -All notable changes to `boj-server-cartridges` are recorded here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -> **No release has ever been tagged.** There are no git tags in this repository and no GitHub releases. The `[0.1.0]` heading below marks the 2026-06-01 milestone, not a published artefact — treat it as a dated section, not a version you can fetch. - -## [Unreleased] - -Everything landed on `main` since the 2026-06-01 milestone — 71 commits, none of which were recorded here. - -### Added - -- **This repository became the sole source of BoJ cartridges.** `boj-server` retired its own bundled `cartridges/` tree in [boj-server#300](https://github.com/hyperpolymath/boj-server/pull/300) (merged 2026-08-04). There is no second copy: what lands here is what every host fetches. -- **Foundry** — a high-assurance cartridge-making subsystem under [`tools/foundry/`](tools/foundry/), gated by [`.github/workflows/foundry.yml`](.github/workflows/foundry.yml), with a machine-checked Idris2 design proof at [`tools/foundry/proof/Foundry.idr`](tools/foundry/proof/Foundry.idr). Landed across `002ac93` (factory + textkit-mcp, A1 closure), `29e1734` (the checked design proof), `0b54a8a` (Provision stage — capability partition + enforcement), `1fb2349` (per-kind obligation bundles, #44) and `caeb14e` (the missing Configure stage; the wizard now fails closed, #102). -- **Proofs Gate** — `368143a` (#40) added Idris2 to CI here for the first time and reconciled **23 cartridge ABI proofs across 21 cartridges** that had silently stopped type-checking in this repo while their `boj-server` twins still passed. Nothing had run `idris2` in this repository before. -- **Foundry Wave-1 "Golden Dozen"** (`be17f66`) — the first 12 cartridges marked `"available": true`. They remain the only 12. -- New cartridges: **bug-filing-mcp** (`373dce6`, wrapping the feedback-o-tron engine; `5a8be0c` v0.2 interactive loop tools + full cartridge layout; `d0d89f6` unified adapter) and **cicd-squabbler-mcp** (`77a2edb`, with review follow-ups in `6767196`). -- **Presence site** for [cartridges.boj-server.net](https://cartridges.boj-server.net/) — `1bab028` added [`site/`](site/) plus a Cloudflare Pages deploy action; `b1c09f2` (#93) added docs deployment via Ddraig SSG. -- SonarCloud scan workflow, config and badge (`bf92407`, #64); OpenSSF Best Practices badge (`5734305`). -- [`docs/cartridge-authoring.adoc`](docs/cartridge-authoring.adoc), [`docs/known-issues/adapters.adoc`](docs/known-issues/adapters.adoc) and [`docs/decisions/ADR-0006-cartridge-invoke-abi.adoc`](docs/decisions/ADR-0006-cartridge-invoke-abi.adoc) — the layer contract and ABI were previously documented only inside a tool config file, and 458 in-tree files cited an ADR-0006 that did not exist here. -- [`tools/build-catalog/`](tools/build-catalog/) — generates `site/catalog.json` from the manifests. It had been hand-maintained and had drifted; there was no generator at all. -- `just mint`, `just validate`, `just catalog`, `just catalog-check`. The minter script already existed but had no recipe. - -### Changed - -- **`README.md` → `README.adoc`** (`e75661f`, #69) per the estate `.adoc`-default policy. This broke the two `README.md` links in `CONTRIBUTING.md`, now repaired. -- **`GOVERNANCE.adoc` removed, `GOVERNANCE.md` kept** (`c2da9ed`). Note this inverts the repo's own `.adoc`-default policy, under which `GOVERNANCE` is not an exempt filename — see the open conflict noted below. -- Licence normalised to the canonical MPL-2.0 + CC-BY-SA-4.0 pair (`4f1d042`, #60). -- Retired local issue/discussion templates in favour of the org `.github` canon (`2ec1bff`). -- Secret scanning standardised on TruffleHog (`f20955a`), then re-pinned onto the real gitleaks gate with the retired inline job dropped (`5013853` #99, `10d92c0` #101). -- Substantial CI remediation: path-filtered required gates made to always report (`d9c7898`), 7 startup-failing workflows repaired and the schema mirror re-pinned (`de20566`, #70), reusable-call job permissions granted (`65e91da`, #71), the governance gate closed on SPDX/permissions/SHA pins (`b04274c`, #103), and estate-wide foundational remediation (`18afa91`, #105). -- `SCHEMA-MIRROR.md` pin values reconciled with `PINNED-SHA` (`08bb723`, #73). - -### Fixed - -- **CWE-704** — unchecked `@ptrCast` removed from every cartridge shim (`47f1ac3`, #89, 115 files) and from the bug-filing-mcp adapter dispatch call (`cb4c0cc`, #91). The shims now use `std.mem.sliceTo(ptr, 0)` instead of re-typing a raw pointer. -- `linear-mcp` implemented against the real Linear GraphQL API (`5b4cad8`, #83). The cartridge itself was not new — it shipped in the original 125. -- `007-mcp`: `BindAddress.proof` renamed to `.witness` (`594d08f`, #34, closes #33). -- Six hard-coded `139`s in `site/index.html` and three cartridges missing from `site/catalog.json`; the catalogue also claimed all 139 entries were `available: true` when only 12 manifests say so. -- Counts across `README.adoc`, `CONTRIBUTING.md` and `schemas/SCHEMA-MIRROR.md` that no longer matched the tree. - -### Known issues - -- **The `adapter/` tree does not build and no CI job compiles it.** `zig-test.yml` globs `cartridges/**/ffi/**` only, so none of the 99 `adapter/build.zig` files is gated. The canonical template's adapter calls `ffi.gossamer_init()`, a symbol defined nowhere in the repository, and `just mint` copies the defect into every new cartridge. This predates the Zig 0.16 work. See [`docs/known-issues/adapters.adoc`](docs/known-issues/adapters.adoc). -- **Shim drift is unenforced.** Nothing in CI compares a cartridge's `cartridge_shim.zig` against the canonical copy. 115 of the 116 in-tree shims are byte-identical; `npc-mcp`'s differs in comments only. -- `GOVERNANCE.md` versus the repo's `.adoc`-default policy, and `.machine_readable/contractiles/Mustfile.a2ml` still requiring a `GOVERNANCE.adoc` that `c2da9ed` deleted. - -### Not in this section - -The **Zig 0.16.0 migration** ([#109](https://github.com/hyperpolymath/boj-server-cartridges/pull/109)) is **open, not merged**, and is therefore deliberately absent above. `.tool-versions` on `main` still pins `zig 0.15.1`, and `main` carries 116 shims, not the 118 that PR describes. Move those entries up when it lands. - -## [0.1.0] — 2026-06-01 - -### Added - -- Initial population from `boj-server/cartridges/` (snapshot 2026-05-26): 125 cartridges migrated into the taxonomied layout under [`cartridges/`](cartridges/) per [`docs/decisions/ADR-001-taxonomy.adoc`](docs/decisions/ADR-001-taxonomy.adoc). -- Schema-validation foundation: SHA-pinned mirror of [`hyperpolymath/standards/cartridges/cartridge-v1.json`](https://github.com/hyperpolymath/standards/blob/main/cartridges/cartridge-v1.json) under [`schemas/cartridge-v1.json`](schemas/cartridge-v1.json) (pin in [`schemas/PINNED-SHA`](schemas/PINNED-SHA), mirror discipline in [`schemas/SCHEMA-MIRROR.md`](schemas/SCHEMA-MIRROR.md)). -- Zero-dependency Deno validator at [`tools/validate-cartridges/`](tools/validate-cartridges/) with three tasks: `audit`, `audit-verbose`, `strict`. -- Strict-mode CI gate ([`.github/workflows/cartridge-schema.yml`](.github/workflows/cartridge-schema.yml)) live since 2026-06-01: any manifest that fails schema validation blocks the PR. -- Wave additions bundled into the v0.1 baseline: vector-DB cartridge wave (boj-server#100) and multi-modal cartridge wave (boj-server#101). -- Wiki bootstrapped with Home + Cartridge-Schema-Validation + Refresh-Discipline pages. (Verified 2026-08-07: true — commit `c5647a8` in [the wiki repository](https://github.com/hyperpolymath/boj-server-cartridges/wiki) adds exactly those three pages. The wiki is a separate git repository, which is why it is not in this tree.) -- Documented downstream consumer relationship (the on-demand fetch contract) at `boj-server#183`. - -### Changed - -- Drift-remediation campaigns closed in the run-up to the strict gate flip: #18 (`category` field backfill), #19 (`auth.method` enum mismatches), #20 (canonical-only / missing top-level fields / name-pattern renames). Post-remediation baseline: 139 / 139 manifests passing — see [`audits/cartridge-schema-2026-06-01.md`](audits/cartridge-schema-2026-06-01.md). -- Per-cartridge `cartridge_shim.zig` is now the de facto FFI shim layout (#29 / #31): 97 `build.zig` files rewritten to resolve `b.path("cartridge_shim.zig")` against the local directory (the `adapter/build.zig` case uses `"../ffi/cartridge_shim.zig"`). The canonical shim source remains [`cartridges/templates/gossamer-mcp/ffi/cartridge_shim.zig`](cartridges/templates/gossamer-mcp/ffi/cartridge_shim.zig) — ~~112 of 114 in-tree shims are byte-identical to it~~. - - > **Correction (2026-08-07):** the "112 of 114" figure did not match the tree and its provenance is unknown. Recounted on `main`: **116 shims, 115 byte-identical to canon**. The single exception is `cartridges/domains/gaming/npc-mcp/ffi/cartridge_shim.zig`, which differs *only in comments* — identical API surface (same seven `RC_*` constants, same three helpers). Left struck through rather than silently rewritten, because this section is a dated historical record. - -### Fixed - -- `browser_mcp_error_recover` now rejects non-Error states with `-2` (#32). The build never previously ran for browser-mcp because of the shim-path issue, so the test logic bug was masked. Fixed alongside the #29 build-path rewrite. - -[Unreleased]: https://github.com/hyperpolymath/boj-server-cartridges/commits/main - - - diff --git a/CODE_OF_CONDUCT.adoc b/CODE_OF_CONDUCT.adoc new file mode 100644 index 00000000..df469534 --- /dev/null +++ b/CODE_OF_CONDUCT.adoc @@ -0,0 +1,28 @@ +== Code of Conduct + +`+boj-server-cartridges+` adopts the +https://www.contributor-covenant.org/version/2/1/code_of_conduct/[Contributor +Covenant 2.1] verbatim as its code of conduct. + +=== Scope + +Applies to all project spaces: this repository, the +https://github.com/hyperpolymath/boj-server-cartridges/wiki[wiki], issue +trackers, pull-request discussions, and any cross-repo coordination +touching `+boj-server-cartridges+` (notably the downstream consumer +relationship with +https://github.com/hyperpolymath/boj-server[hyperpolymath/boj-server]). + +=== Reporting + +Report violations to `+j.d.a.jewell@open.ac.uk+`. Reports are +confidential by default. Use the same address as SECURITY.md; +subject-line tag `+[conduct]+` (not `+[security]+`) so the intake routes +correctly. + +=== Enforcement + +Per the Contributor Covenant 2.1 enforcement guidelines, four-level +ladder (Correction → Warning → Temporary Ban → Permanent Ban). The +Contributor Covenant text is canonical; this file does not paraphrase or +override it. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 7620ebd9..00000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,18 +0,0 @@ - - - -# Code of Conduct - -`boj-server-cartridges` adopts the [Contributor Covenant 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) verbatim as its code of conduct. - -## Scope - -Applies to all project spaces: this repository, the [wiki](https://github.com/hyperpolymath/boj-server-cartridges/wiki), issue trackers, pull-request discussions, and any cross-repo coordination touching `boj-server-cartridges` (notably the downstream consumer relationship with [hyperpolymath/boj-server](https://github.com/hyperpolymath/boj-server)). - -## Reporting - -Report violations to `j.d.a.jewell@open.ac.uk`. Reports are confidential by default. Use the same address as [SECURITY.md](SECURITY.md); subject-line tag `[conduct]` (not `[security]`) so the intake routes correctly. - -## Enforcement - -Per the Contributor Covenant 2.1 enforcement guidelines, four-level ladder (Correction → Warning → Temporary Ban → Permanent Ban). The Contributor Covenant text is canonical; this file does not paraphrase or override it. diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc new file mode 100644 index 00000000..a3b7eb09 --- /dev/null +++ b/CONTRIBUTING.adoc @@ -0,0 +1,147 @@ +== Contributing to boj-server-cartridges + +`+boj-server-cartridges+` is the *canonical BoJ cartridge registry* — +and, since `+boj-server+` retired its bundled `+cartridges/+` tree in +https://github.com/hyperpolymath/boj-server/pull/300[boj-server#300] +(merged 2026-08-04), the _only_ source of cartridges. Hosts +(`+boj-server+`, `+panll+`, others) fetch from this repo on demand into +a host-local cache. Anything you land here ships to every downstream +host on its next fetch — treat additions accordingly. + +Read README.adoc first for taxonomy + role suffixes, then +link:docs/cartridge-authoring.adoc[`+docs/cartridge-authoring.adoc+`] +for the layer contract and the ABI. The canonical spec lives at +https://github.com/hyperpolymath/standards/blob/main/cartridges/CARTRIDGE-FORMAT.adoc[hyperpolymath/standards]. + +____ +*Before you touch `+adapter/+`:* it does not build, and no CI job +compiles it. See +link:docs/known-issues/adapters.adoc[`+docs/known-issues/adapters.adoc+`]. +The `+ffi/+` layer is fine. +____ + +=== The minimum bar + +[arabic] +. Every new `+cartridge.json+` MUST validate against +link:schemas/cartridge-v1.json[`+schemas/cartridge-v1.json+`]. The +schema is a SHA-pinned mirror of the canonical spec at +https://github.com/hyperpolymath/standards/blob/main/cartridges/cartridge-v1.json[hyperpolymath/standards]; +see link:schemas/SCHEMA-MIRROR.md[`+schemas/SCHEMA-MIRROR.md+`] and +link:schemas/PINNED-SHA[`+schemas/PINNED-SHA+`]. +. CI runs the validator in *strict mode* — +link:.github/workflows/cartridge-schema.yml[`+.github/workflows/cartridge-schema.yml+`] +blocks any PR that introduces an invalid manifest. The current baseline +is *142/142 passing*; run `+just validate+` for the live figure rather +than quoting a number. (The 139/139 in +link:audits/cartridge-schema-2026-06-01.md[`+audits/cartridge-schema-2026-06-01.md+`] +is the 2026-06-01 snapshot, not today’s tree.) +. Cartridge name MUST match +`+^[a-z0-9-]+-(mcp|lsp|dap|bsp|debug|format|lint|build|nesy|agentic|fleet)$+`. +See link:README.adoc#_cartridge_roles[README.adoc §"`Cartridge roles`"] +for the role suffix table. +. Adding or removing a cartridge MUST be followed by `+just catalog+`, +so the public site at +https://cartridges.boj-server.net/[cartridges.boj-server.net] matches +the tree. `+just catalog-check+` fails if it has drifted. +. Commits MUST be GPG-signed. + +=== Workflow + +.... +$EDITOR minter.toml # name, description, version, domain, protocols, tier +just mint minter.toml # scaffolds from cartridges/templates/gossamer-mcp +$EDITOR cartridges/domains///cartridge.json +just validate # strict schema check — the CI gate +just catalog # regenerate site/catalog.json +.... + +Use `+just mint+` rather than copying the template by hand: it also +performs the name substitutions through `+cartridge.json+`, `+mod.js+` +and `+README.adoc+`, and records the `+minter.toml+` in the new +cartridge so the mint is reproducible. Full walkthrough in +link:docs/cartridge-authoring.adoc[`+docs/cartridge-authoring.adoc+`]. + +`+deno task audit+` walks every manifest in the tree and prints a +one-line summary per cartridge; exit 0 regardless. +`+deno task audit-verbose+` expands each violation. `+deno task strict+` +is the CI gate — run it locally before pushing if your change touches +manifests at scale. + +[width="100%",cols="50%,50%",options="header",] +|=== +|Where |What +|`+cartridges/domains///+` |Domain-bound cartridges +(cloud, database, ci-cd, languages, security, research, …). + +|`+cartridges/cross-cutting///+` |Cartridges not bound +to a single domain. Seven categories: agentic, build, debug, fleet, +health, nesy, orchestration. + +|`+cartridges/templates/gossamer-mcp/+` |Canonical scaffold. Use this as +the starting point for new cartridges. +|=== + +Taxonomy ratified in +link:docs/decisions/ADR-001-taxonomy.adoc[`+docs/decisions/ADR-001-taxonomy.adoc+`]. + +=== PR discipline + +* *Auto-merge is enabled by default for this repo.* Open the PR, mark it +auto-merge, let CI do its job. +* One cartridge per PR where possible. Cartridge-wave PRs (e.g. the +vector-DB / multi-modal waves bundled into v0.1) are the exception — +call them out in the PR description and link the upstream campaign. +* Cross-link the canonical schema home +(https://github.com/hyperpolymath/standards/tree/main/cartridges[hyperpolymath/standards]) +in PR descriptions when proposing schema-shape changes; those land +upstream first, then mirror here via a `+PINNED-SHA+` bump. + +=== CI / required checks + +Required status-check workflows must *always report*. Never add +`+on.*.paths+` to a required workflow (`+proofs.yml+`, `+zig-test.yml+`, +`+foundry.yml+`): a path-filtered required check that doesn’t trigger is +reported as permanently "`Expected`" and leaves the PR `+blocked+` even +when green. The estate pattern — keep the workflow always-triggered, add +an always-run `+changes+` job that recomputes the gate’s path set via +`+git diff origin/...HEAD+`, and gate each heavy job with +`+needs: changes+` + `+if: needs.changes.outputs.run == 'true'+` (a job +skipped via `+if:+` counts as a passing required check). Fail safe: +default to running. Mirrors boj-server’s gates (boj-server PR #216, this +repo PR #45). + +=== What lives elsewhere + +* The cartridge *spec* itself (schema shape, role suffix conventions, +version semantics): +https://github.com/hyperpolymath/standards[hyperpolymath/standards] +`+cartridges/+`. +* The cartridge *host runtime* (catalog refresh, fetch contract, tray +UI): +https://github.com/hyperpolymath/boj-server[hyperpolymath/boj-server] — +fetcher contract documented at `+boj-server#183+`. +* Cross-cartridge integration patterns, walkthroughs, and the +refresh-discipline page: the +https://github.com/hyperpolymath/boj-server-cartridges/wiki[wiki] — +https://github.com/hyperpolymath/boj-server-cartridges/wiki/Home[Home], +https://github.com/hyperpolymath/boj-server-cartridges/wiki/FFI-Shim-Layout[FFI +Shim Layout], +https://github.com/hyperpolymath/boj-server-cartridges/wiki/Cartridge-Schema-Validation[Schema +Validation], +https://github.com/hyperpolymath/boj-server-cartridges/wiki/Refresh-Discipline[Refresh +Discipline]. The wiki is a separate git repository +(`+…/boj-server-cartridges.wiki.git+`), so it is not in this tree and +has no publishing workflow — that is normal for a GitHub wiki, not a +sign it is missing. + +The *layer contract, ABI, minting and gates* are _not_ on the wiki — +they are in-tree at +link:docs/cartridge-authoring.adoc[`+docs/cartridge-authoring.adoc+`], +because they have to version alongside the code they describe. + +=== Machine-readable summary + +link:0-AI-MANIFEST.a2ml[`+0-AI-MANIFEST.a2ml+`] is the project’s +machine-readable manifest. Update it when adding a top-level structural +element (a new domain, a new role suffix, a new tool under `+tools/+`). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index ccdbfacc..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,62 +0,0 @@ - - - -# Contributing to boj-server-cartridges - -`boj-server-cartridges` is the **canonical BoJ cartridge registry** — and, since `boj-server` retired its bundled `cartridges/` tree in [boj-server#300](https://github.com/hyperpolymath/boj-server/pull/300) (merged 2026-08-04), the *only* source of cartridges. Hosts (`boj-server`, `panll`, others) fetch from this repo on demand into a host-local cache. Anything you land here ships to every downstream host on its next fetch — treat additions accordingly. - -Read [README.adoc](README.adoc) first for taxonomy + role suffixes, then [`docs/cartridge-authoring.adoc`](docs/cartridge-authoring.adoc) for the layer contract and the ABI. The canonical spec lives at [hyperpolymath/standards](https://github.com/hyperpolymath/standards/blob/main/cartridges/CARTRIDGE-FORMAT.adoc). - -> **Before you touch `adapter/`:** it does not build, and no CI job compiles it. See [`docs/known-issues/adapters.adoc`](docs/known-issues/adapters.adoc). The `ffi/` layer is fine. - -## The minimum bar - -1. Every new `cartridge.json` MUST validate against [`schemas/cartridge-v1.json`](schemas/cartridge-v1.json). The schema is a SHA-pinned mirror of the canonical spec at [hyperpolymath/standards](https://github.com/hyperpolymath/standards/blob/main/cartridges/cartridge-v1.json); see [`schemas/SCHEMA-MIRROR.md`](schemas/SCHEMA-MIRROR.md) and [`schemas/PINNED-SHA`](schemas/PINNED-SHA). -2. CI runs the validator in **strict mode** — [`.github/workflows/cartridge-schema.yml`](.github/workflows/cartridge-schema.yml) blocks any PR that introduces an invalid manifest. The current baseline is **142/142 passing**; run `just validate` for the live figure rather than quoting a number. (The 139/139 in [`audits/cartridge-schema-2026-06-01.md`](audits/cartridge-schema-2026-06-01.md) is the 2026-06-01 snapshot, not today's tree.) -3. Cartridge name MUST match `^[a-z0-9-]+-(mcp|lsp|dap|bsp|debug|format|lint|build|nesy|agentic|fleet)$`. See [README.adoc §"Cartridge roles"](README.adoc#_cartridge_roles) for the role suffix table. -4. Adding or removing a cartridge MUST be followed by `just catalog`, so the public site at [cartridges.boj-server.net](https://cartridges.boj-server.net/) matches the tree. `just catalog-check` fails if it has drifted. -5. Commits MUST be GPG-signed. - -## Workflow - -``` -$EDITOR minter.toml # name, description, version, domain, protocols, tier -just mint minter.toml # scaffolds from cartridges/templates/gossamer-mcp -$EDITOR cartridges/domains///cartridge.json -just validate # strict schema check — the CI gate -just catalog # regenerate site/catalog.json -``` - -Use `just mint` rather than copying the template by hand: it also performs the name substitutions through `cartridge.json`, `mod.js` and `README.adoc`, and records the `minter.toml` in the new cartridge so the mint is reproducible. Full walkthrough in [`docs/cartridge-authoring.adoc`](docs/cartridge-authoring.adoc). - -`deno task audit` walks every manifest in the tree and prints a one-line summary per cartridge; exit 0 regardless. `deno task audit-verbose` expands each violation. `deno task strict` is the CI gate — run it locally before pushing if your change touches manifests at scale. - -| Where | What | -|---|---| -| `cartridges/domains///` | Domain-bound cartridges (cloud, database, ci-cd, languages, security, research, …). | -| `cartridges/cross-cutting///` | Cartridges not bound to a single domain. Seven categories: agentic, build, debug, fleet, health, nesy, orchestration. | -| `cartridges/templates/gossamer-mcp/` | Canonical scaffold. Use this as the starting point for new cartridges. | - -Taxonomy ratified in [`docs/decisions/ADR-001-taxonomy.adoc`](docs/decisions/ADR-001-taxonomy.adoc). - -## PR discipline - -- **Auto-merge is enabled by default for this repo.** Open the PR, mark it auto-merge, let CI do its job. -- One cartridge per PR where possible. Cartridge-wave PRs (e.g. the vector-DB / multi-modal waves bundled into v0.1) are the exception — call them out in the PR description and link the upstream campaign. -- Cross-link the canonical schema home ([hyperpolymath/standards](https://github.com/hyperpolymath/standards/tree/main/cartridges)) in PR descriptions when proposing schema-shape changes; those land upstream first, then mirror here via a `PINNED-SHA` bump. - -## CI / required checks - -Required status-check workflows must **always report**. Never add `on.*.paths` to a required workflow (`proofs.yml`, `zig-test.yml`, `foundry.yml`): a path-filtered required check that doesn't trigger is reported as permanently "Expected" and leaves the PR `blocked` even when green. The estate pattern — keep the workflow always-triggered, add an always-run `changes` job that recomputes the gate's path set via `git diff origin/...HEAD`, and gate each heavy job with `needs: changes` + `if: needs.changes.outputs.run == 'true'` (a job skipped via `if:` counts as a passing required check). Fail safe: default to running. Mirrors boj-server's gates (boj-server PR #216, this repo PR #45). - -## What lives elsewhere - -- The cartridge **spec** itself (schema shape, role suffix conventions, version semantics): [hyperpolymath/standards](https://github.com/hyperpolymath/standards) `cartridges/`. -- The cartridge **host runtime** (catalog refresh, fetch contract, tray UI): [hyperpolymath/boj-server](https://github.com/hyperpolymath/boj-server) — fetcher contract documented at `boj-server#183`. -- Cross-cartridge integration patterns, walkthroughs, and the refresh-discipline page: the [wiki](https://github.com/hyperpolymath/boj-server-cartridges/wiki) — [Home](https://github.com/hyperpolymath/boj-server-cartridges/wiki/Home), [FFI Shim Layout](https://github.com/hyperpolymath/boj-server-cartridges/wiki/FFI-Shim-Layout), [Schema Validation](https://github.com/hyperpolymath/boj-server-cartridges/wiki/Cartridge-Schema-Validation), [Refresh Discipline](https://github.com/hyperpolymath/boj-server-cartridges/wiki/Refresh-Discipline). The wiki is a separate git repository (`…/boj-server-cartridges.wiki.git`), so it is not in this tree and has no publishing workflow — that is normal for a GitHub wiki, not a sign it is missing. - -The **layer contract, ABI, minting and gates** are *not* on the wiki — they are in-tree at [`docs/cartridge-authoring.adoc`](docs/cartridge-authoring.adoc), because they have to version alongside the code they describe. - -## Machine-readable summary - -[`0-AI-MANIFEST.a2ml`](0-AI-MANIFEST.a2ml) is the project's machine-readable manifest. Update it when adding a top-level structural element (a new domain, a new role suffix, a new tool under `tools/`). diff --git a/DEBT.adoc b/DEBT.adoc new file mode 100644 index 00000000..8c1237ff --- /dev/null +++ b/DEBT.adoc @@ -0,0 +1,377 @@ +== Technical debt register + +One index of known debt in this repository, measured 2026-08-07 against +`+main+`. Every item carries *the command that produced the evidence*, +so any row can be re-checked or falsified in one step. Claims that are +not verified are labelled *DIAGNOSIS (unconfirmed)* rather than +asserted. + +The sibling host keeps its own register at +https://github.com/hyperpolymath/boj-server/blob/main/DEBT.md[`+boj-server/DEBT.md+`]; +cross-repo items are noted in both and fixed once. + +Severity: *HIGH* — actively misleads, or a gate that cannot fail · +*MEDIUM* — wrong but self-evident on contact · *LOW* — cosmetic or +historical. + +''''' + +=== The single largest item + +*99 `+adapter/+` trees do not compile, and no CI job builds them.* This +is not 0.16 fallout — it predates the migration. `+zig-test.yml+` globs +only `+*/ffi/+`, so the adapter layer has never been gated; the template +adapter calls an `+init+` symbol its own FFI never defines, and the +FFI’s `+export fn+`s are not `+pub+`, so the module import cannot see +them either. Because `+just mint+` copies the template, *every minted +cartridge inherits the defect*. Meanwhile `+.claude/CLAUDE.md+` tells +contributors "`a cartridge is not complete without all three +directories`" and "`do not omit `+adapter/+` when minting`" — pointing +them straight at 99 non-compiling build files. See A-1. + +[source,sh] +---- +find cartridges -path '*/adapter/build.zig' | wc -l # 99 +grep -rn 'gossamer_init' cartridges/templates/gossamer-mcp/ +---- + +____ +*Update 2026-08-07:* PR #114 takes this to *99/99 green* on +`+zig build && zig build test+`, wires the adapter glob into CI, and +rebuilds the template properly. Two follow-ups it deliberately does +_not_ do are recorded as A-4 and A-5 below. +____ + +''''' + +=== Adapters — A + +[width="100%",cols="16%,20%,24%,40%",options="header",] +|=== +|ID |Sev |Item |Evidence +|A-1 |HIGH |_(fix in flight, #114 — 99/99 now green)_ 99 +`+adapter/build.zig+` trees, none built by CI, template broken at the +call site (see above). Needs: fix the template wiring, port the cloned +`+std.net+` listener to `+std.Io.net+`, rewrite the 99 build files to +the shape `+cartridges/domains/config/k9iser-mcp/adapter/build.zig+` +already uses (it is the only 0.16-valid one), then extend +`+zig-test.yml+`’s glob. +|`+find cartridges -path '*/adapter/build.zig' \| wc -l+` + +|A-4 |HIGH |*The 90 cloned adapters fake their dispatch.* They match a +tool name and return a hand-written `+" forwarded"+` string +*without ever calling `+boj_cartridge_invoke+`* — contradicting the +"`response passthrough`" invariant stated in their own READMEs. #114 +fixed the template properly but ported the 90 semantics-preserving; +converting them is a wire-behaviour change across 90 cartridges and +wants its own PR. +|`+grep -rl 'forwarded' cartridges --include='*_adapter.zig' \| wc -l+` + +|A-5 |MEDIUM |*Adapter test coverage is 4 of 99.* Only gossamer, k9iser, +bug-filing and 007 declare inline tests, so `+zig build test+` is +vacuous for the other 95; `+zig build+` is what makes the CI job +failable. Recorded rather than papered over — generating assertions +would have been wrong somewhere (only 56 of 94 clones even route +`+/status+`). |count adapters declaring `+test "+` + +|A-6 |LOW |*FIXED by #114, retained for provenance.* `+bsp+`, `+dap+`, +`+lang+` and `+lsp+` each bound *`+0.0.0.0+` on three listeners — 12 +public ingresses* — against ADR-0004 and their own READMEs, which say +adapters are loopback-only behind the capability gateway. Now loopback. +|`+git show :…/bsp_adapter.zig \| grep 0.0.0.0+` + +|A-2 |MEDIUM |125 `+adapter/+` dirs exist but only 99 have a +`+build.zig+` — 26 are scaffolding that nothing, including the new +`+full-sweep+`, will ever touch. Same shape on the FFI side: 131 +`+ffi/+` dirs, 118 with a `+build.zig+`. +|`+find cartridges -type d -name adapter \| wc -l+` vs +`+find cartridges -path '*/adapter/build.zig' \| wc -l+` + +|A-3 |MEDIUM |`+.claude/CLAUDE.md+` documents an invariant the tree +violates ("`not complete without all three directories`"). Either the +invariant or the tree has to give; right now the document is the thing +that is wrong. |`+grep -n 'not complete without' .claude/CLAUDE.md+` +|=== + +''''' + +=== Licence — L + +[width="100%",cols="16%,20%,24%,40%",options="header",] +|=== +|ID |Sev |Item |Evidence +|L-1 |HIGH |*480 files carry `+CC-BY-SA-4.0+` headers while root +`+LICENSE+` is MPL-2.0, and there is no `+NOTICE+` and no +`+.reuse/dep5+` to declare the split.* A scanner reading only +`+LICENSE+` mis-attributes every one of them. The sibling repo does this +correctly — copy its `+NOTICE+` + `+.reuse/dep5+` pattern. +|`+ls .reuse NOTICE+` → absent · +`+grep -rl 'CC-BY-SA-4.0' --include='*.adoc' --include='*.md' . \| wc -l+` +→ 480 + +|L-2 |MEDIUM |12 `+_source-archive/+` trees carry vendored source with +*no SPDX header and no provenance record* — no statement of origin or +upstream licence. +|`+find cartridges -type d -name _source-archive \| wc -l+` + +|L-3 |LOW |Five `+minter.toml+` files lack SPDX headers while every +other `+.toml+` has one. +|`+git ls-files '*minter.toml' \| xargs grep -L SPDX+` + +|L-5 |MEDIUM +|`+cartridges/domains/gaming/idaptik-admin-mcp/panels/manifest.json+` +declares *`+AGPL-3.0-or-later+`* in an otherwise MPL-2.0 / CC-BY-SA-4.0 +repo. *Flagged, deliberately not changed* — the estate has a history of +licence-clobber sweeps flattening genuine AGPL work, so this needs an +owner ruling, not a script. +|`+grep -rn AGPL cartridges --include='manifest.json'+` + +|L-4 |LOW |`+.github/funding.yml+` and `+.github/FUNDING.yml+` both +exist and differ. GitHub reads only the uppercase one; the lowercase one +is dead weight and also lacks SPDX. +|`+ls .github/[fF][uU][nN][dD][iI][nN][gG].yml+` +|=== + +''''' + +=== Truthfulness — T + +The estate’s central promise is that the catalogue never advertises +capability it cannot back. That invariant currently holds — but nothing +in this repository enforces it. + +[width="100%",cols="16%,20%,24%,40%",options="header",] +|=== +|ID |Sev |Item |Evidence +|T-1 |HIGH |*92 of 142 FFI implementations return canned stub JSON* +(`+"status":"stub"+`). The per-file headers are honest about it; the +scale is the debt — roughly two-thirds of the advertised surface is not +wired to anything. +|`+grep -rl '"status":"stub"' cartridges --include='*_ffi.zig' \| wc -l+` +→ 92 + +|T-2 |HIGH |*130 of 142 manifests omit `+available+` entirely*; 12 set +it `+true+`; none sets it `+false+`. The field is the host’s only +machine-readable signal for "`this is real`", and for most cartridges it +is simply absent. +|`+grep -rL '"available"' cartridges --include='cartridge.json' \| wc -l+` + +|T-4 |HIGH |_(fix in flight, #113)_ *The public site overstated +availability 139-to-12.* `+site/catalog.json+` was hand-maintained with +no generator and claimed `+available: true+` for *all 139* entries, +while only *12* manifests say so. The catalogue was advertising +availability the manifests do not back — the exact invariant this estate +exists to protect, violated on the public surface. |compare +`+site/catalog.json+` `+available+` fields against +`+grep -rl '"available": true' cartridges+` → 12 + +|T-3 |MEDIUM |The stub↔available invariant is *honoured but unenforced +here*: no cartridge advertising `+available: true+` returns a stub. The +gate that checks this (`+tests/truthfulness_check.sh+`) lives in +boj-server, which no longer holds the cartridges. The check should run +where the manifests are. |cross-check the 12 `+available: true+` +manifests against their `+*_ffi.zig+` +|=== + +''''' + +=== Proof — P + +115 `+.idr+` files with *zero* `+believe_me+`, `+postulate+`, +`+assert_total+`, `+sorry+`, `+%default partial+` or `+?hole+`. The +proofs are clean; the gate around them is not. + +[width="100%",cols="16%,20%,24%,40%",options="header",] +|=== +|ID |Sev |Item |Evidence +|P-1 |HIGH |*`+proofs.yml+` has no `+schedule:+` trigger.* The sibling +repo added a weekly cron precisely because a proof break that already +lives in `+main+` is otherwise never re-detected — that is how a +duplicate lemma sat in main behind a green gate. This repo has 115 +proofs, 23 of which had already silently rotted once, and no such +backstop. |`+grep -n 'schedule' .github/workflows/proofs.yml+` → absent + +|P-2 |MEDIUM |`+scripts/check-trusted-base.sh+` states "`boj-server +sanctions EXACTLY 5 class-(J) axioms`". It is 4 — `+charEqSym+` was +discharged 2026-06-24 and the enforcing constant there is +`+EXPECTED_AXIOMS=4+`. Cross-repo stale claim. +|`+grep -n 'EXACTLY' scripts/check-trusted-base.sh+` + +|P-4 |MEDIUM |*18 of 126 `+abi/+` directories contain no `+.idr+` file +at all* — the layer is present as scaffolding but carries no proof, +while the three-layer contract implies one. +|`+for d in $(find cartridges -type d -name abi); do [ -z "$(find $d -name '*.idr')" ] && echo $d; done \| wc -l+` + +|P-3 |LOW |*ADR-0006 is cited by all 118 shims and every +`+ffi/build.zig+`, but no ADR-0006 exists in this repo* — only +`+ADR-001-taxonomy+` and `+ADR-002+`. Now that this repo is canonical +for cartridges, the five-symbol contract must be resolvable from here. +Note also the numbering clash (`+ADR-00N+` local vs `+ADR-000N+` cited). +|`+ls docs/decisions/+` +|=== + +*Positive control:* this repo’s `+scripts/typecheck-proofs.sh+` already +carries a vacuous-pass guard that the sibling lacked until 2026-08-07. +Each repo held half the protection. + +''''' + +=== Test — T2 + +[width="100%",cols="16%,20%,24%,40%",options="header",] +|=== +|ID |Sev |Item |Evidence +|T2-1 |HIGH |*52 cartridge test scripts exist and no workflow runs any +of them.* `+zig-test.yml+` runs `+zig build test+` inside changed +`+ffi/+` dirs and nothing else. +|`+grep -rn 'tests/' .github/workflows/+` → no matches + +|T2-2 |HIGH |*88 of 142 cartridges have no test directory at all* — +overlapping heavily with the 92 that return stubs. +|`+find cartridges -type d -name tests \| wc -l+` → 54 + +|T2-3 |LOW |The new `+full-sweep+` job builds every cartridge FFI but is +`+schedule+` + `+workflow_dispatch+` only, by design (a required full +build would strand PRs). Worth knowing it is not a per-PR guarantee. +|`+grep -n 'full-sweep' -A4 .github/workflows/zig-test.yml+` +|=== + +''''' + +=== CI/CD — C + +[width="100%",cols="16%,20%,24%,40%",options="header",] +|=== +|ID |Sev |Item |Evidence +|C-1 |HIGH |*`+main-estate-audit.yml+` stays untracked deliberately — +arming it today fails `+main+` immediately.* The suite is now published +(`+hyperpolymath/cicd-suite+`, `+11b5ab51+`, all 26 actions resolve), so +the 404 is fixed. But its hard gates against this repo: +`+required-files-check+` fails on `+CODEOWNERS+` + `+ARCHITECTURE.md+`, +and `+code-hygiene-check+` matched *313 files* before cicd-suite#1; *3* +after. Satisfying the former means presence-only filler. *Fix the gates +(see cicd-suite’s README), then pin to `+11b5ab51+` and commit.* +|`+git grep -Eil 'TODO\|FIXME\|STUB\|sorry\|believe_me\|admit' \| wc -l+` +→ 313 + +|C-7 |MEDIUM |*13 of `+cicd-suite+`’s 26 actions cannot fail* — +`+::warning::+` then exit 0, while named "`Gate`". _(Was HIGH and +three-part; cicd-suite#1 fixed `+code-hygiene-check+`’s whole-tree grep +— 313 matching files here, now 3 true positives — and +`+required-files-check+`’s presence-only filler, and ended their mutual +contradiction. The advisory/enforcing split remains.)_ The consuming +workflow sits in *199 repos*, untracked in *198*. +|`+for a in ../cicd-suite/actions/*/; do grep -q 'exit 1' $a/action.yml \|\| echo $a; done \| wc -l+` +→ 13 + +|C-2 |MEDIUM |`+pages.yml+` (GitHub Pages via Ddraig SSG) and +`+pages-deploy.yml+` (Cloudflare Pages) both fire on push to main, to +different hosts, with no coordination. `+pages.yml+` copies +`+README.md+` into its source dir — *that file does not exist* +(converted to `+.adoc+`), so it publishes a one-line stub. +|`+grep -n 'README.md' .github/workflows/pages.yml+` + +|C-3 |MEDIUM |GitHub Pages 404s for this repo, and issue #97 records +that the Cloudflare Pages deploy has never succeeded (missing secrets + +DNS). Two deploy paths, neither demonstrably working. +|`+curl -s -o /dev/null -w '%{http_code}' https://hyperpolymath.github.io/boj-server-cartridges/+` + +|C-5 |HIGH |*`+hypatia-scan.yml+` cannot fail.* The scan runs +`+--exit-zero+` _and_ is suffixed `+\|\| true+` — double suppression. It +is credited as a security gate and reports success unconditionally, +whatever it finds. +|`+grep -n 'exit-zero' .github/workflows/hypatia-scan.yml+` + +|C-6 |LOW |`+flake.guix+` ships `+just+` alone in its dev shell while +claiming to "`mirror the build tooling actually present in this repo`" — +no `+zig+`, `+deno+` or `+idris2+`, so `+guix develop+` cannot build or +test anything. |`+grep -n 'packages = with pkgs' flake.guix+` +|=== + +''''' + +=== Code — D + +[width="100%",cols="16%,20%,24%,40%",options="header",] +|=== +|ID |Sev |Item |Evidence +|D-1 |HIGH |Three batch-fix tools hardcode +`+ROOT = "/home/hyperpolymath/developer/repos/boj-server-cartridges"+` — +*a path that is wrong even on the original machine* (the repo lives +under `+hyper-repos/+`). Already broken, not merely unportable. +|`+grep -rn 'developer/repos/' tools/+` + +|D-2 |MEDIUM +|`+cartridges/domains/languages/007-mcp/ffi/oo7_mcp_ffi.zig+` has an +absolute `+/var/mnt/eclipse/repos/boj-server/cartridges/007-mcp/...+` +path baked into shipped FFI source, pointing into the *retired* tree of +the other repo. |`+git grep -n '/var/mnt/eclipse'+` + +|D-3 |MEDIUM |Machine-specific binary paths in distributed config: +`+lsp-mcp/presets.json+` points at a user-specific `+rust-analyzer+`; +`+codeseeker-mcp+` FFI has `+/home/hyper/repos/myproject+`. +|`+git grep -n '/home/hyper'+` + +|D-4 |MEDIUM |_(remediation in flight)_ *A `+v+` → `+zig+` find/replace +corrupted ~140 adapter READMEs and `+PLAYBOOK.a2ml+`*, which now read as +_banning Zig_ ("`Banned: ziguage`", "`zig ban validator`") in a repo +whose entire FFI layer is Zig. The banned language was *V*, which Zig +replaced. Agent-hostile: it is machine-readable content asserting the +opposite of the truth. +|`+grep -rln 'zig banned 2026-04-10\|zig predecessor' cartridges \| wc -l+` + +|D-5 |MEDIUM |_(remediation in flight)_ `+.machine_readable/6a2/+` is +*another repository’s boilerplate*: `+STATE.a2ml+` says +`+project = "rsr-template-repo"+`, `+ECOSYSTEM.a2ml+` says +`+project = "pseudoscript"+`. An agent following +`+0-AI-MANIFEST.a2ml+`’s read order is fed facts about two unrelated +projects. |`+grep -n '^project' .machine_readable/6a2/*.a2ml+` + +|D-6 |LOW |_(fix in flight, #113)_ `+site/catalog.json+` is +hand-maintained with *no generator*, so the public site’s counts drift +permanently and it is already missing in-tree cartridges. +|`+grep -rl catalog.json .github/ tools/ scripts/ Justfile+` → nothing +|=== + +''''' + +=== Documentation — X + +[width="100%",cols="16%,20%,24%,40%",options="header",] +|=== +|ID |Sev |Item |Evidence +|X-1 |HIGH |Counts disagree three ways across the estate: this repo’s +README says *139*, boj-server says *125*, disk says *142*. +|`+find cartridges -name cartridge.json \| wc -l+` + +|X-2 |MEDIUM |`+CHANGELOG.md+`’s last entry is `+[0.1.0] — 2026-06-01+` +with *71 commits unrecorded*, no `+[Unreleased]+` section, and a link to +a `+v0.1.0+` release tag *that does not exist* (`+git tag+` is empty). +|`+git log --oneline --since=2026-06-01 \| wc -l+` · `+git tag+` + +|X-3 |MEDIUM |`+CONTRIBUTING.md+` and `+SECURITY.md+` both link +`+README.md+` — converted to `+.adoc+`, so the contributor on-ramp opens +with dead links. `+MAINTAINERS.adoc+` links `+.adoc+` names for files +that exist as `+.md+`. +|`+grep -n 'README.md' CONTRIBUTING.md SECURITY.md+` + +|X-4 |MEDIUM |`+GOVERNANCE.md+` violates the repo’s own `+.adoc+`-only +policy *and* `+Mustfile.a2ml+` requires `+GOVERNANCE.adoc+`, which was +deliberately deleted. The contractile check fails against the tree it +governs. +|`+grep -n 'GOVERNANCE' .machine_readable/contractiles/Mustfile.a2ml+` + +|X-5 |LOW |No cartridge-authoring guide in `+docs/+` — the +abi/ffi/adapter layer contract exists only in `+.claude/CLAUDE.md+`, a +tool config file humans will not find. |`+ls docs/+` +|=== + +''''' + +=== How to use this file + +Add an item when you find debt you are not fixing in the same change. +Give it the next ID in its domain, a severity, and — non-negotiably — *a +command that reproduces the evidence*. An item without a reproducible +check is an opinion, and opinions rot silently. Remove an item only when +its command proves it gone. diff --git a/DEBT.md b/DEBT.md deleted file mode 100644 index eda00bd0..00000000 --- a/DEBT.md +++ /dev/null @@ -1,155 +0,0 @@ - - - -# Technical debt register - -One index of known debt in this repository, measured 2026-08-07 against `main`. -Every item carries **the command that produced the evidence**, so any row can be -re-checked or falsified in one step. Claims that are not verified are labelled -**DIAGNOSIS (unconfirmed)** rather than asserted. - -The sibling host keeps its own register at -[`boj-server/DEBT.md`](https://github.com/hyperpolymath/boj-server/blob/main/DEBT.md); -cross-repo items are noted in both and fixed once. - -Severity: **HIGH** — actively misleads, or a gate that cannot fail · -**MEDIUM** — wrong but self-evident on contact · **LOW** — cosmetic or historical. - ---- - -## The single largest item - -**99 `adapter/` trees do not compile, and no CI job builds them.** This is not -0.16 fallout — it predates the migration. `zig-test.yml` globs only `*/ffi/`, so -the adapter layer has never been gated; the template adapter calls an `init` -symbol its own FFI never defines, and the FFI's `export fn`s are not `pub`, so the -module import cannot see them either. Because `just mint` copies the template, -**every minted cartridge inherits the defect**. Meanwhile `.claude/CLAUDE.md` -tells contributors "a cartridge is not complete without all three directories" -and "do not omit `adapter/` when minting" — pointing them straight at 99 -non-compiling build files. See A-1. - -```sh -find cartridges -path '*/adapter/build.zig' | wc -l # 99 -grep -rn 'gossamer_init' cartridges/templates/gossamer-mcp/ -``` - -> **Update 2026-08-07:** PR #114 takes this to **99/99 green** on -> `zig build && zig build test`, wires the adapter glob into CI, and rebuilds the -> template properly. Two follow-ups it deliberately does *not* do are recorded as -> A-4 and A-5 below. - ---- - -## Adapters — A - -| ID | Sev | Item | Evidence | -|----|-----|------|----------| -| A-1 | HIGH | *(fix in flight, #114 — 99/99 now green)* 99 `adapter/build.zig` trees, none built by CI, template broken at the call site (see above). Needs: fix the template wiring, port the cloned `std.net` listener to `std.Io.net`, rewrite the 99 build files to the shape `cartridges/domains/config/k9iser-mcp/adapter/build.zig` already uses (it is the only 0.16-valid one), then extend `zig-test.yml`'s glob. | `find cartridges -path '*/adapter/build.zig' \| wc -l` | -| A-4 | HIGH | **The 90 cloned adapters fake their dispatch.** They match a tool name and return a hand-written `" forwarded"` string **without ever calling `boj_cartridge_invoke`** — contradicting the "response passthrough" invariant stated in their own READMEs. #114 fixed the template properly but ported the 90 semantics-preserving; converting them is a wire-behaviour change across 90 cartridges and wants its own PR. | `grep -rl 'forwarded' cartridges --include='*_adapter.zig' \| wc -l` | -| A-5 | MEDIUM | **Adapter test coverage is 4 of 99.** Only gossamer, k9iser, bug-filing and 007 declare inline tests, so `zig build test` is vacuous for the other 95; `zig build` is what makes the CI job failable. Recorded rather than papered over — generating assertions would have been wrong somewhere (only 56 of 94 clones even route `/status`). | count adapters declaring `test "` | -| A-6 | LOW | **FIXED by #114, retained for provenance.** `bsp`, `dap`, `lang` and `lsp` each bound **`0.0.0.0` on three listeners — 12 public ingresses** — against ADR-0004 and their own READMEs, which say adapters are loopback-only behind the capability gateway. Now loopback. | `git show :…/bsp_adapter.zig \| grep 0.0.0.0` | -| A-2 | MEDIUM | 125 `adapter/` dirs exist but only 99 have a `build.zig` — 26 are scaffolding that nothing, including the new `full-sweep`, will ever touch. Same shape on the FFI side: 131 `ffi/` dirs, 118 with a `build.zig`. | `find cartridges -type d -name adapter \| wc -l` vs `find cartridges -path '*/adapter/build.zig' \| wc -l` | -| A-3 | MEDIUM | `.claude/CLAUDE.md` documents an invariant the tree violates ("not complete without all three directories"). Either the invariant or the tree has to give; right now the document is the thing that is wrong. | `grep -n 'not complete without' .claude/CLAUDE.md` | - ---- - -## Licence — L - -| ID | Sev | Item | Evidence | -|----|-----|------|----------| -| L-1 | HIGH | **480 files carry `CC-BY-SA-4.0` headers while root `LICENSE` is MPL-2.0, and there is no `NOTICE` and no `.reuse/dep5` to declare the split.** A scanner reading only `LICENSE` mis-attributes every one of them. The sibling repo does this correctly — copy its `NOTICE` + `.reuse/dep5` pattern. | `ls .reuse NOTICE` → absent · `grep -rl 'CC-BY-SA-4.0' --include='*.adoc' --include='*.md' . \| wc -l` → 480 | -| L-2 | MEDIUM | 12 `_source-archive/` trees carry vendored source with **no SPDX header and no provenance record** — no statement of origin or upstream licence. | `find cartridges -type d -name _source-archive \| wc -l` | -| L-3 | LOW | Five `minter.toml` files lack SPDX headers while every other `.toml` has one. | `git ls-files '*minter.toml' \| xargs grep -L SPDX` | -| L-5 | MEDIUM | `cartridges/domains/gaming/idaptik-admin-mcp/panels/manifest.json` declares **`AGPL-3.0-or-later`** in an otherwise MPL-2.0 / CC-BY-SA-4.0 repo. **Flagged, deliberately not changed** — the estate has a history of licence-clobber sweeps flattening genuine AGPL work, so this needs an owner ruling, not a script. | `grep -rn AGPL cartridges --include='manifest.json'` | -| L-4 | LOW | `.github/funding.yml` and `.github/FUNDING.yml` both exist and differ. GitHub reads only the uppercase one; the lowercase one is dead weight and also lacks SPDX. | `ls .github/[fF][uU][nN][dD][iI][nN][gG].yml` | - ---- - -## Truthfulness — T - -The estate's central promise is that the catalogue never advertises capability it -cannot back. That invariant currently holds — but nothing in this repository -enforces it. - -| ID | Sev | Item | Evidence | -|----|-----|------|----------| -| T-1 | HIGH | **92 of 142 FFI implementations return canned stub JSON** (`"status":"stub"`). The per-file headers are honest about it; the scale is the debt — roughly two-thirds of the advertised surface is not wired to anything. | `grep -rl '"status":"stub"' cartridges --include='*_ffi.zig' \| wc -l` → 92 | -| T-2 | HIGH | **130 of 142 manifests omit `available` entirely**; 12 set it `true`; none sets it `false`. The field is the host's only machine-readable signal for "this is real", and for most cartridges it is simply absent. | `grep -rL '"available"' cartridges --include='cartridge.json' \| wc -l` | -| T-4 | HIGH | *(fix in flight, #113)* **The public site overstated availability 139-to-12.** `site/catalog.json` was hand-maintained with no generator and claimed `available: true` for **all 139** entries, while only **12** manifests say so. The catalogue was advertising availability the manifests do not back — the exact invariant this estate exists to protect, violated on the public surface. | compare `site/catalog.json` `available` fields against `grep -rl '"available": true' cartridges` → 12 | -| T-3 | MEDIUM | The stub↔available invariant is **honoured but unenforced here**: no cartridge advertising `available: true` returns a stub. The gate that checks this (`tests/truthfulness_check.sh`) lives in boj-server, which no longer holds the cartridges. The check should run where the manifests are. | cross-check the 12 `available: true` manifests against their `*_ffi.zig` | - ---- - -## Proof — P - -115 `.idr` files with **zero** `believe_me`, `postulate`, `assert_total`, `sorry`, -`%default partial` or `?hole`. The proofs are clean; the gate around them is not. - -| ID | Sev | Item | Evidence | -|----|-----|------|----------| -| P-1 | HIGH | **`proofs.yml` has no `schedule:` trigger.** The sibling repo added a weekly cron precisely because a proof break that already lives in `main` is otherwise never re-detected — that is how a duplicate lemma sat in main behind a green gate. This repo has 115 proofs, 23 of which had already silently rotted once, and no such backstop. | `grep -n 'schedule' .github/workflows/proofs.yml` → absent | -| P-2 | MEDIUM | `scripts/check-trusted-base.sh` states "boj-server sanctions EXACTLY 5 class-(J) axioms". It is 4 — `charEqSym` was discharged 2026-06-24 and the enforcing constant there is `EXPECTED_AXIOMS=4`. Cross-repo stale claim. | `grep -n 'EXACTLY' scripts/check-trusted-base.sh` | -| P-4 | MEDIUM | **18 of 126 `abi/` directories contain no `.idr` file at all** — the layer is present as scaffolding but carries no proof, while the three-layer contract implies one. | `for d in $(find cartridges -type d -name abi); do [ -z "$(find $d -name '*.idr')" ] && echo $d; done \| wc -l` | -| P-3 | LOW | **ADR-0006 is cited by all 118 shims and every `ffi/build.zig`, but no ADR-0006 exists in this repo** — only `ADR-001-taxonomy` and `ADR-002`. Now that this repo is canonical for cartridges, the five-symbol contract must be resolvable from here. Note also the numbering clash (`ADR-00N` local vs `ADR-000N` cited). | `ls docs/decisions/` | - -**Positive control:** this repo's `scripts/typecheck-proofs.sh` already carries a -vacuous-pass guard that the sibling lacked until 2026-08-07. Each repo held half -the protection. - ---- - -## Test — T2 - -| ID | Sev | Item | Evidence | -|----|-----|------|----------| -| T2-1 | HIGH | **52 cartridge test scripts exist and no workflow runs any of them.** `zig-test.yml` runs `zig build test` inside changed `ffi/` dirs and nothing else. | `grep -rn 'tests/' .github/workflows/` → no matches | -| T2-2 | HIGH | **88 of 142 cartridges have no test directory at all** — overlapping heavily with the 92 that return stubs. | `find cartridges -type d -name tests \| wc -l` → 54 | -| T2-3 | LOW | The new `full-sweep` job builds every cartridge FFI but is `schedule` + `workflow_dispatch` only, by design (a required full build would strand PRs). Worth knowing it is not a per-PR guarantee. | `grep -n 'full-sweep' -A4 .github/workflows/zig-test.yml` | - ---- - -## CI/CD — C - -| ID | Sev | Item | Evidence | -|----|-----|------|----------| -| C-1 | HIGH | **`main-estate-audit.yml` stays untracked deliberately — arming it today fails `main` immediately.** The suite is now published (`hyperpolymath/cicd-suite`, `11b5ab51`, all 26 actions resolve), so the 404 is fixed. But its hard gates against this repo: `required-files-check` fails on `CODEOWNERS` + `ARCHITECTURE.md`, and `code-hygiene-check` matched **313 files** before cicd-suite#1; **3** after. Satisfying the former means presence-only filler. **Fix the gates (see cicd-suite's README), then pin to `11b5ab51` and commit.** | `git grep -Eil 'TODO\|FIXME\|STUB\|sorry\|believe_me\|admit' \| wc -l` → 313 | -| C-7 | MEDIUM | **13 of `cicd-suite`'s 26 actions cannot fail** — `::warning::` then exit 0, while named "Gate". *(Was HIGH and three-part; cicd-suite#1 fixed `code-hygiene-check`'s whole-tree grep — 313 matching files here, now 3 true positives — and `required-files-check`'s presence-only filler, and ended their mutual contradiction. The advisory/enforcing split remains.)* The consuming workflow sits in **199 repos**, untracked in **198**. | `for a in ../cicd-suite/actions/*/; do grep -q 'exit 1' $a/action.yml \|\| echo $a; done \| wc -l` → 13 | -| C-2 | MEDIUM | `pages.yml` (GitHub Pages via Ddraig SSG) and `pages-deploy.yml` (Cloudflare Pages) both fire on push to main, to different hosts, with no coordination. `pages.yml` copies `README.md` into its source dir — **that file does not exist** (converted to `.adoc`), so it publishes a one-line stub. | `grep -n 'README.md' .github/workflows/pages.yml` | -| C-3 | MEDIUM | GitHub Pages 404s for this repo, and issue #97 records that the Cloudflare Pages deploy has never succeeded (missing secrets + DNS). Two deploy paths, neither demonstrably working. | `curl -s -o /dev/null -w '%{http_code}' https://hyperpolymath.github.io/boj-server-cartridges/` | -| C-5 | HIGH | **`hypatia-scan.yml` cannot fail.** The scan runs `--exit-zero` *and* is suffixed `\|\| true` — double suppression. It is credited as a security gate and reports success unconditionally, whatever it finds. | `grep -n 'exit-zero' .github/workflows/hypatia-scan.yml` | -| C-6 | LOW | `flake.guix` ships `just` alone in its dev shell while claiming to "mirror the build tooling actually present in this repo" — no `zig`, `deno` or `idris2`, so `guix develop` cannot build or test anything. | `grep -n 'packages = with pkgs' flake.guix` | - ---- - -## Code — D - -| ID | Sev | Item | Evidence | -|----|-----|------|----------| -| D-1 | HIGH | Three batch-fix tools hardcode `ROOT = "/home/hyperpolymath/developer/repos/boj-server-cartridges"` — **a path that is wrong even on the original machine** (the repo lives under `hyper-repos/`). Already broken, not merely unportable. | `grep -rn 'developer/repos/' tools/` | -| D-2 | MEDIUM | `cartridges/domains/languages/007-mcp/ffi/oo7_mcp_ffi.zig` has an absolute `/var/mnt/eclipse/repos/boj-server/cartridges/007-mcp/...` path baked into shipped FFI source, pointing into the **retired** tree of the other repo. | `git grep -n '/var/mnt/eclipse'` | -| D-3 | MEDIUM | Machine-specific binary paths in distributed config: `lsp-mcp/presets.json` points at a user-specific `rust-analyzer`; `codeseeker-mcp` FFI has `/home/hyper/repos/myproject`. | `git grep -n '/home/hyper'` | -| D-4 | MEDIUM | *(remediation in flight)* **A `v` → `zig` find/replace corrupted ~140 adapter READMEs and `PLAYBOOK.a2ml`**, which now read as *banning Zig* ("Banned: ziguage", "zig ban validator") in a repo whose entire FFI layer is Zig. The banned language was **V**, which Zig replaced. Agent-hostile: it is machine-readable content asserting the opposite of the truth. | `grep -rln 'zig banned 2026-04-10\|zig predecessor' cartridges \| wc -l` | -| D-5 | MEDIUM | *(remediation in flight)* `.machine_readable/6a2/` is **another repository's boilerplate**: `STATE.a2ml` says `project = "rsr-template-repo"`, `ECOSYSTEM.a2ml` says `project = "pseudoscript"`. An agent following `0-AI-MANIFEST.a2ml`'s read order is fed facts about two unrelated projects. | `grep -n '^project' .machine_readable/6a2/*.a2ml` | -| D-6 | LOW | *(fix in flight, #113)* `site/catalog.json` is hand-maintained with **no generator**, so the public site's counts drift permanently and it is already missing in-tree cartridges. | `grep -rl catalog.json .github/ tools/ scripts/ Justfile` → nothing | - ---- - -## Documentation — X - -| ID | Sev | Item | Evidence | -|----|-----|------|----------| -| X-1 | HIGH | Counts disagree three ways across the estate: this repo's README says **139**, boj-server says **125**, disk says **142**. | `find cartridges -name cartridge.json \| wc -l` | -| X-2 | MEDIUM | `CHANGELOG.md`'s last entry is `[0.1.0] — 2026-06-01` with **71 commits unrecorded**, no `[Unreleased]` section, and a link to a `v0.1.0` release tag **that does not exist** (`git tag` is empty). | `git log --oneline --since=2026-06-01 \| wc -l` · `git tag` | -| X-3 | MEDIUM | `CONTRIBUTING.md` and `SECURITY.md` both link `README.md` — converted to `.adoc`, so the contributor on-ramp opens with dead links. `MAINTAINERS.adoc` links `.adoc` names for files that exist as `.md`. | `grep -n 'README.md' CONTRIBUTING.md SECURITY.md` | -| X-4 | MEDIUM | `GOVERNANCE.md` violates the repo's own `.adoc`-only policy **and** `Mustfile.a2ml` requires `GOVERNANCE.adoc`, which was deliberately deleted. The contractile check fails against the tree it governs. | `grep -n 'GOVERNANCE' .machine_readable/contractiles/Mustfile.a2ml` | -| X-5 | LOW | No cartridge-authoring guide in `docs/` — the abi/ffi/adapter layer contract exists only in `.claude/CLAUDE.md`, a tool config file humans will not find. | `ls docs/` | - ---- - -## How to use this file - -Add an item when you find debt you are not fixing in the same change. Give it the -next ID in its domain, a severity, and — non-negotiably — **a command that -reproduces the evidence**. An item without a reproducible check is an opinion, and -opinions rot silently. Remove an item only when its command proves it gone. diff --git a/GOVERNANCE.adoc b/GOVERNANCE.adoc new file mode 100644 index 00000000..9b836fb2 --- /dev/null +++ b/GOVERNANCE.adoc @@ -0,0 +1,60 @@ +== Governance + +=== Overview + +This project is governed by the following principles and structures to +ensure transparent, inclusive, and effective decision-making. + +=== Roles and Responsibilities + +==== Maintainers + +Maintainers are responsible for: - Reviewing and merging pull requests - +Managing releases and versioning - Ensuring code quality and standards - +Triaging issues and bug reports - Community engagement and support + +==== Contributors + +Contributors are expected to: - Follow the code of conduct - Submit +well-documented pull requests - Write tests for new functionality - +Maintain existing tests - Update documentation as needed + +=== Decision Making + +==== Minor Changes + +* Can be made by any maintainer +* Include bug fixes, documentation updates, dependency updates + +==== Major Changes + +* Require discussion in issues or pull requests +* Include new features, architectural changes, API changes +* Need approval from at least 2 maintainers + +==== Breaking Changes + +* Require RFC (Request for Comments) process +* Need approval from majority of maintainers +* Must include migration guide + +=== Code of Conduct + +All participants are expected to follow our Code of Conduct. Violations +can be reported to the maintainers. + +=== Communication + +* *Issues*: For bug reports and feature requests +* *Discussions*: For questions and general discussion +* *Pull Requests*: For code contributions + +=== Licensing + +All contributions are made under the terms of the repository’s LICENSE +file. By submitting a pull request, you agree to license your +contributions accordingly. + +''''' + +_Last updated: 2026-07-18_ diff --git a/GOVERNANCE.md b/GOVERNANCE.md deleted file mode 100644 index e27364c7..00000000 --- a/GOVERNANCE.md +++ /dev/null @@ -1,60 +0,0 @@ -# Governance - -## Overview - -This project is governed by the following principles and structures to ensure transparent, inclusive, and effective decision-making. - -## Roles and Responsibilities - -### Maintainers - -Maintainers are responsible for: -- Reviewing and merging pull requests -- Managing releases and versioning -- Ensuring code quality and standards -- Triaging issues and bug reports -- Community engagement and support - -### Contributors - -Contributors are expected to: -- Follow the code of conduct -- Submit well-documented pull requests -- Write tests for new functionality -- Maintain existing tests -- Update documentation as needed - -## Decision Making - -### Minor Changes -- Can be made by any maintainer -- Include bug fixes, documentation updates, dependency updates - -### Major Changes -- Require discussion in issues or pull requests -- Include new features, architectural changes, API changes -- Need approval from at least 2 maintainers - -### Breaking Changes -- Require RFC (Request for Comments) process -- Need approval from majority of maintainers -- Must include migration guide - -## Code of Conduct - -All participants are expected to follow our Code of Conduct. Violations can be reported to the maintainers. - -## Communication - -- **Issues**: For bug reports and feature requests -- **Discussions**: For questions and general discussion -- **Pull Requests**: For code contributions - -## Licensing - -All contributions are made under the terms of the repository's LICENSE file. -By submitting a pull request, you agree to license your contributions accordingly. - ---- - -*Last updated: 2026-07-18* diff --git a/SECURITY.adoc b/SECURITY.adoc new file mode 100644 index 00000000..6d53c46a --- /dev/null +++ b/SECURITY.adoc @@ -0,0 +1,66 @@ +== Security Policy + +=== Reporting a Vulnerability + +Email `+j.d.a.jewell@open.ac.uk+` with subject +`+[security] boj-server-cartridges: +`. + +The mailbox is the canonical estate intake; do not file public issues +for unpatched vulnerabilities. Expect an acknowledgement within 72 hours +and an initial assessment within 7 days. RFC 9116 (`+security.txt+`) +advertising lives at the organisation root; the canonical security +policy is mirrored from +https://github.com/hyperpolymath/standards[hyperpolymath/standards]. + +=== Scope + +`+boj-server-cartridges+` is a *registry* — it ships cartridge manifests +(`+cartridge.json+`), in-tree adapter / FFI code where present, the +SHA-pinned schema mirror under link:schemas/[`+schemas/+`], and the +zero-dep Deno validator under +link:tools/validate-cartridges/[`+tools/validate-cartridges/+`]. The +security-relevant surface is: + +[width="100%",cols="50%,50%",options="header",] +|=== +|Surface |What can go wrong +|`+auth.method+` declarations in `+cartridge.json+` |Mis-declared auth +contract leading a host to under- or over-trust a cartridge. + +|`+tools/validate-cartridges/+` (Deno, zero-dep) |A validator bug that +silently accepts an invalid manifest in strict CI. + +|`+schemas/cartridge-v1.json+` + +link:schemas/PINNED-SHA[`+schemas/PINNED-SHA+`] |An out-of-sync mirror +against canonical `+hyperpolymath/standards+`. + +|Fetcher contract documented at +https://github.com/hyperpolymath/boj-server/issues/183[`+boj-server#183+`] +|Misuse by a downstream host that fetches manifests from this registry +on demand. + +|Per-cartridge FFI / adapter source (Zig, Deno) |Standard memory- and +IO-safety concerns. +|=== + +Per-cartridge runtime backends are process-isolated on loopback per +README.adoc; a single-cartridge compromise does not by construction +reach a sibling. + +=== Out of scope + +* Vulnerabilities in upstream tools (Deno, Zig, Idris2). Report those +upstream. +* Issues in the cartridge spec itself: file against +https://github.com/hyperpolymath/standards[hyperpolymath/standards] +under `+cartridges/+`. +* Host-side concerns (cache poisoning on a host using this registry, +host-local credential handling): file against `+boj-server+` or the +relevant host. + +=== Disclosure + +Coordinated disclosure preferred. Public advisory after a fix is shipped +to `+main+` and the schema-strict CI gate +(link:.github/workflows/cartridge-schema.yml[`+.github/workflows/cartridge-schema.yml+`]) +is green on the patched baseline. diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 4f0898f2..00000000 --- a/SECURITY.md +++ /dev/null @@ -1,34 +0,0 @@ - - - -# Security Policy - -## Reporting a Vulnerability - -Email `j.d.a.jewell@open.ac.uk` with subject `[security] boj-server-cartridges: `. - -The mailbox is the canonical estate intake; do not file public issues for unpatched vulnerabilities. Expect an acknowledgement within 72 hours and an initial assessment within 7 days. RFC 9116 (`security.txt`) advertising lives at the organisation root; the canonical security policy is mirrored from [hyperpolymath/standards](https://github.com/hyperpolymath/standards). - -## Scope - -`boj-server-cartridges` is a **registry** — it ships cartridge manifests (`cartridge.json`), in-tree adapter / FFI code where present, the SHA-pinned schema mirror under [`schemas/`](schemas/), and the zero-dep Deno validator under [`tools/validate-cartridges/`](tools/validate-cartridges/). The security-relevant surface is: - -| Surface | What can go wrong | -|---|---| -| `auth.method` declarations in `cartridge.json` | Mis-declared auth contract leading a host to under- or over-trust a cartridge. | -| `tools/validate-cartridges/` (Deno, zero-dep) | A validator bug that silently accepts an invalid manifest in strict CI. | -| `schemas/cartridge-v1.json` + [`schemas/PINNED-SHA`](schemas/PINNED-SHA) | An out-of-sync mirror against canonical `hyperpolymath/standards`. | -| Fetcher contract documented at [`boj-server#183`](https://github.com/hyperpolymath/boj-server/issues/183) | Misuse by a downstream host that fetches manifests from this registry on demand. | -| Per-cartridge FFI / adapter source (Zig, Deno) | Standard memory- and IO-safety concerns. | - -Per-cartridge runtime backends are process-isolated on loopback per [README.adoc](README.adoc); a single-cartridge compromise does not by construction reach a sibling. - -## Out of scope - -- Vulnerabilities in upstream tools (Deno, Zig, Idris2). Report those upstream. -- Issues in the cartridge spec itself: file against [hyperpolymath/standards](https://github.com/hyperpolymath/standards) under `cartridges/`. -- Host-side concerns (cache poisoning on a host using this registry, host-local credential handling): file against `boj-server` or the relevant host. - -## Disclosure - -Coordinated disclosure preferred. Public advisory after a fix is shipped to `main` and the schema-strict CI gate ([`.github/workflows/cartridge-schema.yml`](.github/workflows/cartridge-schema.yml)) is green on the patched baseline. diff --git a/audits/cartridge-schema-2026-06-01.adoc b/audits/cartridge-schema-2026-06-01.adoc new file mode 100644 index 00000000..ba333d7a --- /dev/null +++ b/audits/cartridge-schema-2026-06-01.adoc @@ -0,0 +1,8 @@ +== Cartridge manifest validation report + +Schema: schemas/cartridge-v1.json Manifests: 139 total / 139 passing / 0 +failing + +=== Top recurring issues + +=== Per-manifest failures diff --git a/audits/cartridge-schema-2026-06-01.md b/audits/cartridge-schema-2026-06-01.md deleted file mode 100644 index d5381f2c..00000000 --- a/audits/cartridge-schema-2026-06-01.md +++ /dev/null @@ -1,7 +0,0 @@ -# Cartridge manifest validation report -Schema: schemas/cartridge-v1.json -Manifests: 139 total / 139 passing / 0 failing - -## Top recurring issues - -## Per-manifest failures diff --git a/audits/panic-attack-scan-2026-06-01.adoc b/audits/panic-attack-scan-2026-06-01.adoc new file mode 100644 index 00000000..2a3a3d1a --- /dev/null +++ b/audits/panic-attack-scan-2026-06-01.adoc @@ -0,0 +1,190 @@ +== panic-attack scan + hand-audit — cartridge schema validator foundation + +*Date:* 2026-06-01 *Branch:* +`+feat/cartridge-schema-validator-foundation+` *Auditor:* automated +panic-attack `+assail+` v2.1.0 + hand-audit *Scope:* the six new/changed +files introduced for the schema validator + audit-mode CI gate. + +=== Tool availability + +panic-attack is fully runnable from this session: a pre-built release +binary exists at +`+/home/hyperpolymath/developer/repos/panic-attack/target/release/panic-attack+` +(v2.1.0), and `+assail+` (its static-analysis subcommand) accepts +`+--headless --output-format json+` for non-interactive use. The +analyzer maps `+.ts+`/`+.tsx+` to the JavaScript family (see +`+src/assail/analyzer.rs+` +`+language_detect_typescript_maps_to_javascript+` test); +`+.yml+`/`+.a2ml+`/`+PINNED-SHA+` are scanned as `+language: unknown+` +with the generic pattern set. Four scans were executed at ~1s each — no +extensive setup was required. The pre-flight warning +`+failed to read AI manifest: reading A2ML manifest 0-AI-MANIFEST.a2ml+` +was emitted (panic-attack expected `+0-AI-MANIFEST.a2ml+` but the new +file is `+0.1-AI-MANIFEST.a2ml+`); this is benign and does not affect +the assail pass. + +=== Scan results — panic-attack assail (headless) + +[width="99%",cols="20%,16%,16%,16%,16%,16%",options="header",] +|=== +|Target |Detected language |Lines |weak_points |unsafe / panic / unwrap +|eval / io / threading +|`+tools/validate-cartridges/+` (main.ts + main_test.ts) |javascript +|322 |0 |0 / 0 / 0 |0 / 0 / 0 + +|`+.github/workflows/cartridge-schema.yml+` |unknown |50 |0 |0 / 0 / 0 +|0 / 0 / 0 + +|`+0.1-AI-MANIFEST.a2ml+` |unknown |89 |0 |0 / 0 / 0 |0 / 0 / 0 + +|`+schemas/PINNED-SHA+` |unknown |14 |0 |0 / 0 / 0 |0 / 0 / 0 +|=== + +panic-attack reported zero findings across every target. Note this is +the expected outcome for a small, dependency-light validator that does +not use `+eval+`, FFI, `+unsafe+`, dynamic require, or shell-out — i.e., +panic-attack has nothing to flag. A clean panic-attack run does not by +itself prove the absence of higher-level concerns (regex DoS, workflow +injection, path traversal); those are covered by the hand-audit below. + +=== Hand-audit — per file + +==== `+tools/validate-cartridges/main.ts+` (162 lines) + +* *Injection (shell, eval, dynamic import):* none. Module imports are +static `+jsr:@std/...@1+` only; no `+eval+`, no `+new Function+`, no +`+Deno.run+` / shell-out. +* *Unsafe deserialisation:* `+JSON.parse+` of both the schema and each +manifest; per-manifest parse is wrapped in `+try / catch+` and surfaced +as a validation issue rather than crashing the walker (lines 106-114). +Schema parse is _not_ wrapped — acceptable because schema is repo-owned +content gated by `+PINNED-SHA+`; a corrupt schema should fail loud. +* *Path traversal:* `+walk(CARTRIDGES_DIR, …)+` from `+jsr:@std/fs@1+`. +`+ROOT+` is derived from `+import.meta.url+`; the walker is rooted at +`+cartridges/+` under the repo. Read permission is the only granted +capability (`+--allow-read+` in `+deno.json+`); no write/net/run/env. +The validator cannot escape the repo even if a manifest path was +attacker-controlled — and it isn’t (paths come from the local filesystem +walk, not from manifest content). +* *Regex DoS:* `+new RegExp(schema.pattern).test(value)+` at line 59 +with a try/catch around it. The pattern source is +`+schemas/cartridge-v1.json+`, which is content-pinned via +`+schemas/PINNED-SHA+` and verified by CI (see workflow analysis below). +The `+value+` side is manifest-controlled, but manifests are also +repo-owned content. Therefore the only realistic +catastrophic-backtracking surface is a malicious commit to either the +schema or a manifest — i.e., a code-review concern, not a runtime one. +No catch-and-continue swallow: bad-pattern errors are surfaced as +validation issues, and a runaway match would block the CI job rather +than silently pass. *Risk: informational.* +* *Resource use:* no streaming; every manifest is read in full via +`+Deno.readTextFile+`. Cartridge manifests are sub-kB, ~150 of them; +bounded. +* *Error handling:* `+(e as Error).message+` cast is benign — Deno’s +throw surface for `+readTextFile+`/`+JSON.parse+` is `+Error+`. + +==== `+tools/validate-cartridges/main_test.ts+` (162 lines) + +* Tests are pure-data and pure-function; no FS, net, or shell. The +inlined `+validate+` here intentionally mirrors `+main.ts+` to keep +tests dependency-free — drift between the two definitions is the only +concern, but it is a correctness/maintenance issue, not a security one. +* Note: line 57 (`+new RegExp(schema.pattern).test(value)+`) is *not* +try/catch-wrapped in the test mirror, unlike `+main.ts+` line 58. This +is a small drift between the two copies. *Risk: informational* (test +inputs are hard-coded). + +==== `+tools/validate-cartridges/deno.json+` + +* All tasks pass `+--allow-read+` only — least-privilege is correctly +enforced. No `+--allow-all+`, `+--allow-run+`, `+--allow-net+`, or +`+--allow-env+`. + +==== `+.github/workflows/cartridge-schema.yml+` (50 lines) + +* *Workflow injection (`+pwn-request+`):* none. The job uses +`+actions/checkout@v4+` without +`+ref: ${{ github.event.pull_request.head.sha }}+` games, and the shell +step does *not* interpolate any `+${{ github.event.* }}+` value into +bash. `+$GITHUB_STEP_SUMMARY+` is the only env interpolation in shell +and is a GitHub-supplied path. *Safe.* +* *Permissions:* `+contents: read+` at the workflow level; no per-job +elevation. Correct for an audit-mode validator. +* *Concurrency:* `+cancel-in-progress: true+` keyed by workflow + ref — +safe. +* *Action pinning:* `+actions/checkout@v4+` and +`+denoland/setup-deno@v2+` are pinned to major-version tags, not commit +SHAs. This matches the rest of the repo’s workflows (`+governance.yml+` +/ `+secret-scanner.yml+` use the same convention) and the standards +reusable’s expectation, so calling it a finding here would be +inconsistent. *Risk: low / consistent-with-estate.* +* *Schema-mirror SHA check:* the bash step uses `+set -euo pipefail+`, +`+sha256sum+`, and a strict equality check before failing the job with +an `+::error::+` annotation. Cannot be silently bypassed. + +==== `+schemas/PINNED-SHA+` + +* TOML-ish key/value pairs only. No executable content. +`+canonical_commit+` and `+canonical_blob_sha+` are 40-char hex; +`+content_sha256+` is 64-char hex. Workflow extracts `+content_sha256+` +via `+awk -F'"' '/content_sha256/'+` — a malicious value containing a +`+"+` would simply fail the comparison rather than execute. Safe. + +==== `+0.1-AI-MANIFEST.a2ml+` + +* Metadata-only YAML-ish manifest. No URLs that the validator follows, +no template expansion, no executable hooks. The benign panic-attack +warning about the filename (`+0-AI-MANIFEST.a2ml+` expected, +`+0.1-AI-MANIFEST.a2ml+` actual) is a _discovery_ gap, not a security +gap — the file is still visible to humans and to the standards-side +a2ml-validate. + +=== Risk classification + +[width="100%",cols="50%,50%",options="header",] +|=== +|Finding |Class +|Regex DoS surface through user-supplied `+schema.pattern+` × manifest +value |*informational* — both inputs are repo-owned + content-pinned + +code-reviewed + +|`+main_test.ts+` mirrors `+main.ts+`’s `+validate+` without try/catch +around `+new RegExp+` |*informational* — test inputs are hard-coded + +|Workflow uses major-tag action pins instead of commit SHAs |*low* — +consistent with rest of repo, not a regression + +|panic-attack `+0-AI-MANIFEST.a2ml+` discovery filename vs new +`+0.1-AI-MANIFEST.a2ml+` |*informational* — tool-side discovery gap, not +a security issue + +|No medium/high findings |— +|=== + +=== Recommendations + +[arabic] +. (Optional, low-priority) When the audit-mode gate flips to +`+--strict+`, consider time-bounding the regex test in `+main.ts+` +(e.g., schema-side `+maxLength+` on the matched value, or a Deno timer +race) to defang the informational regex DoS surface. Defer until strict +mode lands. +. (Optional) Factor `+validate+` into a shared module so `+main.ts+` and +`+main_test.ts+` cannot drift. This is a maintainability fix; current +drift (try/catch on bad-pattern errors) is not exploitable. +. (Optional, out-of-scope for this PR) File an issue against the parent +session if you want a follow-up that pins `+denoland/setup-deno@v2+` and +`+actions/checkout@v4+` to commit SHAs estate-wide — do not single-PR +this workflow. +. No changes are recommended inside the scope of this PR. + +=== Conclusion + +*Safe to merge.* Both panic-attack `+assail+` (4 targets, 0 weak points) +and the hand-audit (6 OWASP-style categories per file) found no medium +or higher findings. The validator is correctly sandboxed +(`+--allow-read+` only), the workflow does not interpolate untrusted +inputs into shell, the SHA-pin step is fail-loud, and the only +theoretical concern — regex catastrophic backtracking through +`+schema.pattern+` — is gated by the very SHA-pin mechanism that this PR +introduces. diff --git a/audits/panic-attack-scan-2026-06-01.md b/audits/panic-attack-scan-2026-06-01.md deleted file mode 100644 index 33491cbe..00000000 --- a/audits/panic-attack-scan-2026-06-01.md +++ /dev/null @@ -1,157 +0,0 @@ - - - -# panic-attack scan + hand-audit — cartridge schema validator foundation - -**Date:** 2026-06-01 -**Branch:** `feat/cartridge-schema-validator-foundation` -**Auditor:** automated panic-attack `assail` v2.1.0 + hand-audit -**Scope:** the six new/changed files introduced for the schema validator + audit-mode CI gate. - -## Tool availability - -panic-attack is fully runnable from this session: a pre-built release binary -exists at `/home/hyperpolymath/developer/repos/panic-attack/target/release/panic-attack` -(v2.1.0), and `assail` (its static-analysis subcommand) accepts `--headless --output-format json` -for non-interactive use. The analyzer maps `.ts`/`.tsx` to the JavaScript family -(see `src/assail/analyzer.rs` `language_detect_typescript_maps_to_javascript` -test); `.yml`/`.a2ml`/`PINNED-SHA` are scanned as `language: unknown` with the -generic pattern set. Four scans were executed at ~1s each — no extensive setup -was required. The pre-flight warning `failed to read AI manifest: reading A2ML -manifest 0-AI-MANIFEST.a2ml` was emitted (panic-attack expected `0-AI-MANIFEST.a2ml` -but the new file is `0.1-AI-MANIFEST.a2ml`); this is benign and does not affect -the assail pass. - -## Scan results — panic-attack assail (headless) - -| Target | Detected language | Lines | weak_points | unsafe / panic / unwrap | eval / io / threading | -|---|---|---|---|---|---| -| `tools/validate-cartridges/` (main.ts + main_test.ts) | javascript | 322 | 0 | 0 / 0 / 0 | 0 / 0 / 0 | -| `.github/workflows/cartridge-schema.yml` | unknown | 50 | 0 | 0 / 0 / 0 | 0 / 0 / 0 | -| `0.1-AI-MANIFEST.a2ml` | unknown | 89 | 0 | 0 / 0 / 0 | 0 / 0 / 0 | -| `schemas/PINNED-SHA` | unknown | 14 | 0 | 0 / 0 / 0 | 0 / 0 / 0 | - -panic-attack reported zero findings across every target. Note this is the -expected outcome for a small, dependency-light validator that does not use -`eval`, FFI, `unsafe`, dynamic require, or shell-out — i.e., panic-attack -has nothing to flag. A clean panic-attack run does not by itself prove the -absence of higher-level concerns (regex DoS, workflow injection, path -traversal); those are covered by the hand-audit below. - -## Hand-audit — per file - -### `tools/validate-cartridges/main.ts` (162 lines) - -- **Injection (shell, eval, dynamic import):** none. Module imports are static - `jsr:@std/...@1` only; no `eval`, no `new Function`, no `Deno.run` / shell-out. -- **Unsafe deserialisation:** `JSON.parse` of both the schema and each manifest; - per-manifest parse is wrapped in `try / catch` and surfaced as a validation - issue rather than crashing the walker (lines 106-114). Schema parse is *not* - wrapped — acceptable because schema is repo-owned content gated by - `PINNED-SHA`; a corrupt schema should fail loud. -- **Path traversal:** `walk(CARTRIDGES_DIR, …)` from `jsr:@std/fs@1`. `ROOT` is - derived from `import.meta.url`; the walker is rooted at `cartridges/` under - the repo. Read permission is the only granted capability (`--allow-read` in - `deno.json`); no write/net/run/env. The validator cannot escape the repo even - if a manifest path was attacker-controlled — and it isn't (paths come from - the local filesystem walk, not from manifest content). -- **Regex DoS:** `new RegExp(schema.pattern).test(value)` at line 59 with a - try/catch around it. The pattern source is `schemas/cartridge-v1.json`, - which is content-pinned via `schemas/PINNED-SHA` and verified by CI - (see workflow analysis below). The `value` side is manifest-controlled, - but manifests are also repo-owned content. Therefore the only realistic - catastrophic-backtracking surface is a malicious commit to either the - schema or a manifest — i.e., a code-review concern, not a runtime one. - No catch-and-continue swallow: bad-pattern errors are surfaced as - validation issues, and a runaway match would block the CI job rather than - silently pass. **Risk: informational.** -- **Resource use:** no streaming; every manifest is read in full via - `Deno.readTextFile`. Cartridge manifests are sub-kB, ~150 of them; bounded. -- **Error handling:** `(e as Error).message` cast is benign — Deno's throw - surface for `readTextFile`/`JSON.parse` is `Error`. - -### `tools/validate-cartridges/main_test.ts` (162 lines) - -- Tests are pure-data and pure-function; no FS, net, or shell. The inlined - `validate` here intentionally mirrors `main.ts` to keep tests dependency-free - — drift between the two definitions is the only concern, but it is a - correctness/maintenance issue, not a security one. -- Note: line 57 (`new RegExp(schema.pattern).test(value)`) is **not** - try/catch-wrapped in the test mirror, unlike `main.ts` line 58. This is a - small drift between the two copies. **Risk: informational** (test inputs - are hard-coded). - -### `tools/validate-cartridges/deno.json` - -- All tasks pass `--allow-read` only — least-privilege is correctly enforced. - No `--allow-all`, `--allow-run`, `--allow-net`, or `--allow-env`. - -### `.github/workflows/cartridge-schema.yml` (50 lines) - -- **Workflow injection (`pwn-request`):** none. The job uses `actions/checkout@v4` - without `ref: ${{ github.event.pull_request.head.sha }}` games, and the - shell step does **not** interpolate any `${{ github.event.* }}` value into - bash. `$GITHUB_STEP_SUMMARY` is the only env interpolation in shell and is - a GitHub-supplied path. **Safe.** -- **Permissions:** `contents: read` at the workflow level; no per-job - elevation. Correct for an audit-mode validator. -- **Concurrency:** `cancel-in-progress: true` keyed by workflow + ref — safe. -- **Action pinning:** `actions/checkout@v4` and `denoland/setup-deno@v2` are - pinned to major-version tags, not commit SHAs. This matches the rest of the - repo's workflows (`governance.yml` / `secret-scanner.yml` use the same - convention) and the standards reusable's expectation, so calling it a - finding here would be inconsistent. **Risk: low / consistent-with-estate.** -- **Schema-mirror SHA check:** the bash step uses `set -euo pipefail`, - `sha256sum`, and a strict equality check before failing the job with an - `::error::` annotation. Cannot be silently bypassed. - -### `schemas/PINNED-SHA` - -- TOML-ish key/value pairs only. No executable content. `canonical_commit` and - `canonical_blob_sha` are 40-char hex; `content_sha256` is 64-char hex. - Workflow extracts `content_sha256` via `awk -F'"' '/content_sha256/'` — a - malicious value containing a `"` would simply fail the comparison rather - than execute. Safe. - -### `0.1-AI-MANIFEST.a2ml` - -- Metadata-only YAML-ish manifest. No URLs that the validator follows, no - template expansion, no executable hooks. The benign panic-attack warning - about the filename (`0-AI-MANIFEST.a2ml` expected, `0.1-AI-MANIFEST.a2ml` - actual) is a *discovery* gap, not a security gap — the file is still - visible to humans and to the standards-side a2ml-validate. - -## Risk classification - -| Finding | Class | -|---|---| -| Regex DoS surface through user-supplied `schema.pattern` × manifest value | **informational** — both inputs are repo-owned + content-pinned + code-reviewed | -| `main_test.ts` mirrors `main.ts`'s `validate` without try/catch around `new RegExp` | **informational** — test inputs are hard-coded | -| Workflow uses major-tag action pins instead of commit SHAs | **low** — consistent with rest of repo, not a regression | -| panic-attack `0-AI-MANIFEST.a2ml` discovery filename vs new `0.1-AI-MANIFEST.a2ml` | **informational** — tool-side discovery gap, not a security issue | -| No medium/high findings | — | - -## Recommendations - -1. (Optional, low-priority) When the audit-mode gate flips to `--strict`, - consider time-bounding the regex test in `main.ts` (e.g., schema-side - `maxLength` on the matched value, or a Deno timer race) to defang the - informational regex DoS surface. Defer until strict mode lands. -2. (Optional) Factor `validate` into a shared module so `main.ts` and - `main_test.ts` cannot drift. This is a maintainability fix; current drift - (try/catch on bad-pattern errors) is not exploitable. -3. (Optional, out-of-scope for this PR) File an issue against the parent - session if you want a follow-up that pins `denoland/setup-deno@v2` and - `actions/checkout@v4` to commit SHAs estate-wide — do not single-PR this - workflow. -4. No changes are recommended inside the scope of this PR. - -## Conclusion - -**Safe to merge.** Both panic-attack `assail` (4 targets, 0 weak points) and -the hand-audit (6 OWASP-style categories per file) found no medium or higher -findings. The validator is correctly sandboxed (`--allow-read` only), the -workflow does not interpolate untrusted inputs into shell, the SHA-pin step -is fail-loud, and the only theoretical concern — regex catastrophic -backtracking through `schema.pattern` — is gated by the very SHA-pin -mechanism that this PR introduces. diff --git a/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/ABI-FFI-README.md b/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/ABI-FFI-README.adoc similarity index 74% rename from cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/ABI-FFI-README.md rename to cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/ABI-FFI-README.adoc index f41a54e4..04be86a3 100644 --- a/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/ABI-FFI-README.md +++ b/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/ABI-FFI-README.adoc @@ -1,19 +1,22 @@ -{{~ Aditionally delete this line and fill out the template below ~}} +\{\{~ Aditionally delete this line and fill out the template below ~}} -# {{PROJECT}} ABI/FFI Documentation +== \{\{PROJECT}} ABI/FFI Documentation -## Overview +=== Overview -This library follows the **Hyperpolymath RSR Standard** for ABI and FFI design: +This library follows the *Hyperpolymath RSR Standard* for ABI and FFI +design: -- **ABI (Application Binary Interface)** defined in **Idris2** with formal proofs -- **FFI (Foreign Function Interface)** implemented in **Zig** for C compatibility -- **Generated C headers** bridge Idris2 ABI to Zig FFI -- **Any language** can call through standard C ABI +* *ABI (Application Binary Interface)* defined in *Idris2* with formal +proofs +* *FFI (Foreign Function Interface)* implemented in *Zig* for C +compatibility +* *Generated C headers* bridge Idris2 ABI to Zig FFI +* *Any language* can call through standard C ABI -## Architecture +=== Architecture -``` +.... ┌─────────────────────────────────────────────┐ │ ABI Definitions (Idris2) │ │ src/abi/ │ @@ -45,11 +48,11 @@ This library follows the **Hyperpolymath RSR Standard** for ABI and FFI design: │ Any Language via C ABI │ │ - Rust, AffineScript, Julia, Python, etc. │ └─────────────────────────────────────────────┘ -``` +.... -## Directory Structure +=== Directory Structure -``` +.... {{project}}/ ├── src/ │ ├── abi/ # ABI definitions (Idris2) @@ -77,15 +80,17 @@ This library follows the **Hyperpolymath RSR Standard** for ABI and FFI design: ├── rust/ ├── affinescript/ └── julia/ -``` +.... -## Why Idris2 for ABI? +=== Why Idris2 for ABI? -### 1. **Formal Verification** +==== 1. *Formal Verification* -Idris2's dependent types allow proving properties about the ABI at compile-time: +Idris2’s dependent types allow proving properties about the ABI at +compile-time: -```idris +[source,idris] +---- -- Prove struct size is correct public export exampleStructSize : HasSize ExampleStruct 16 @@ -97,13 +102,14 @@ fieldAligned : Divides 8 (offsetOf ExampleStruct.field) -- Prove ABI is platform-compatible public export abiCompatible : Compatible (ABI 1) (ABI 2) -``` +---- -### 2. **Type Safety** +==== 2. *Type Safety* Encode invariants that C/Zig cannot express: -```idris +[source,idris] +---- -- Non-null pointer guaranteed at type level data Handle : Type where MkHandle : (ptr : Bits64) -> {auto 0 nonNull : So (ptr /= 0)} -> Handle @@ -111,13 +117,14 @@ data Handle : Type where -- Array with length proof data Buffer : (n : Nat) -> Type where MkBuffer : Vect n Byte -> Buffer n -``` +---- -### 3. **Platform Abstraction** +==== 3. *Platform Abstraction* Platform-specific types with compile-time selection: -```idris +[source,idris] +---- CInt : Platform -> Type CInt Linux = Bits32 CInt Windows = Bits32 @@ -125,13 +132,14 @@ CInt Windows = Bits32 CSize : Platform -> Type CSize Linux = Bits64 CSize Windows = Bits64 -``` +---- -### 4. **Safe Evolution** +==== 4. *Safe Evolution* Prove that new ABI versions are backward-compatible: -```idris +[source,idris] +---- -- Compiler enforces compatibility abiUpgrade : ABI 1 -> ABI 2 abiUpgrade old = MkABI2 { @@ -140,71 +148,78 @@ abiUpgrade old = MkABI2 { -- Can add new fields new_features = defaults } -``` +---- -## Why Zig for FFI? +=== Why Zig for FFI? -### 1. **C ABI Compatibility** +==== 1. *C ABI Compatibility* Zig exports C-compatible functions naturally: -```zig +[source,zig] +---- export fn library_function(param: i32) i32 { return param * 2; } -``` +---- -### 2. **Memory Safety** +==== 2. *Memory Safety* Compile-time safety without runtime overhead: -```zig +[source,zig] +---- // Null check enforced at compile time const handle = init() orelse return error.InitFailed; defer free(handle); -``` +---- -### 3. **Cross-Compilation** +==== 3. *Cross-Compilation* Built-in cross-compilation to any platform: -```bash +[source,bash] +---- zig build -Dtarget=x86_64-linux zig build -Dtarget=aarch64-macos zig build -Dtarget=x86_64-windows -``` +---- -### 4. **Zero Dependencies** +==== 4. *Zero Dependencies* No runtime, no libc required (unless explicitly needed): -```zig +[source,zig] +---- // Minimal binary size pub const lib = @import("std"); // Only includes what you use -``` +---- -## Building +=== Building -### Build FFI Library +==== Build FFI Library -```bash +[source,bash] +---- cd ffi/zig zig build # Build debug zig build -Doptimize=ReleaseFast # Build optimized zig build test # Run tests -``` +---- -### Generate C Header from Idris2 ABI +==== Generate C Header from Idris2 ABI -```bash +[source,bash] +---- cd src/abi idris2 --cg c-header Types.idr -o ../../generated/abi/{{project}}.h -``` +---- -### Cross-Compile +==== Cross-Compile -```bash +[source,bash] +---- cd ffi/zig # Linux x86_64 @@ -215,13 +230,14 @@ zig build -Dtarget=aarch64-macos # Windows x86_64 zig build -Dtarget=x86_64-windows -``` +---- -## Usage +=== Usage -### From C +==== From C -```c +[source,c] +---- #include "{{project}}.h" int main() { @@ -237,16 +253,19 @@ int main() { {{project}}_free(handle); return 0; } -``` +---- Compile with: -```bash + +[source,bash] +---- gcc -o example example.c -l{{project}} -L./zig-out/lib -``` +---- -### From Idris2 +==== From Idris2 -```idris +[source,idris] +---- import {{PROJECT}}.ABI.Foreign main : IO () @@ -259,11 +278,12 @@ main = do free handle putStrLn "Success" -``` +---- -### From Rust +==== From Rust -```rust +[source,rust] +---- #[link(name = "{{project}}")] extern "C" { fn {{project}}_init() -> *mut std::ffi::c_void; @@ -282,11 +302,12 @@ fn main() { {{project}}_free(handle); } } -``` +---- -### From Julia +==== From Julia -```julia +[source,julia] +---- const lib{{project}} = "lib{{project}}" function init() @@ -312,27 +333,30 @@ try finally cleanup(handle) end -``` +---- -## Testing +=== Testing -### Unit Tests (Zig) +==== Unit Tests (Zig) -```bash +[source,bash] +---- cd ffi/zig zig build test -``` +---- -### Integration Tests +==== Integration Tests -```bash +[source,bash] +---- cd ffi/zig zig build test-integration -``` +---- -### ABI Verification (Idris2) +==== ABI Verification (Idris2) -```idris +[source,idris] +---- -- Compile-time verification %runElab verifyABI @@ -342,44 +366,44 @@ main = do verifyLayoutsCorrect verifyAlignmentsCorrect putStrLn "ABI verification passed" -``` +---- -## Contributing +=== Contributing When modifying the ABI/FFI: -1. **Update ABI first** (`src/abi/*.idr`) - - Modify type definitions - - Update proofs - - Ensure backward compatibility - -2. **Generate C header** - ```bash - idris2 --cg c-header src/abi/Types.idr -o generated/abi/{{project}}.h - ``` - -3. **Update FFI implementation** (`ffi/zig/src/main.zig`) - - Implement new functions - - Match ABI types exactly - -4. **Add tests** - - Unit tests in Zig - - Integration tests - - ABI verification tests - -5. **Update documentation** - - Function signatures - - Usage examples - - Migration guide (if breaking changes) - -## License +[arabic] +. *Update ABI first* (`+src/abi/*.idr+`) +* Modify type definitions +* Update proofs +* Ensure backward compatibility +. *Generate C header* ++ +[source,bash] +---- +idris2 --cg c-header src/abi/Types.idr -o generated/abi/{{project}}.h +---- +. *Update FFI implementation* (`+ffi/zig/src/main.zig+`) +* Implement new functions +* Match ABI types exactly +. *Add tests* +* Unit tests in Zig +* Integration tests +* ABI verification tests +. *Update documentation* +* Function signatures +* Usage examples +* Migration guide (if breaking changes) + +=== License MPL-2.0 -## See Also +=== See Also -- [Idris2 Documentation](https://idris2.readthedocs.io) -- [Zig Documentation](https://ziglang.org/documentation/master/) -- [Rhodium Standard Repositories](https://github.com/hyperpolymath/rhodium-standard-repositories) -- [FFI Migration Guide](../ffi-migration-guide.md) -- [ABI Migration Guide](../abi-migration-guide.md) +* https://idris2.readthedocs.io[Idris2 Documentation] +* https://ziglang.org/documentation/master/[Zig Documentation] +* https://github.com/hyperpolymath/rhodium-standard-repositories[Rhodium +Standard Repositories] +* link:../ffi-migration-guide.md[FFI Migration Guide] +* link:../abi-migration-guide.md[ABI Migration Guide] diff --git a/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/README.adoc b/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/README.adoc new file mode 100644 index 00000000..427411d4 --- /dev/null +++ b/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/README.adoc @@ -0,0 +1,254 @@ +== poly-orchestrator-lsp + +*Orchestration layer for 12 hyperpolymath LSP servers with stapeln +integration* + +link:./LICENSE[image:https://img.shields.io/badge/license-MPL--2.0-brightgreen.svg[License]] +https://elixir-lang.org/[image:https://img.shields.io/badge/elixir-1.17+-purple.svg[Elixir]] +https://www.erlang.org/[image:https://img.shields.io/badge/OTP-27+-red.svg[OTP]] +link:#[image:https://img.shields.io/badge/tests-47%2F47%20passing-brightgreen.svg[Tests]] +link:./vscode-extension[image:https://img.shields.io/badge/VSCode-AffineScript-blue.svg[Extension]] + +=== Overview + +poly-orchestrator-lsp is the 13th LSP server in the hyperpolymath +ecosystem, providing *orchestration and coordination* for the other 12 +domain-specific LSP servers. It enables *automated stack deployment* by +parsing `+stack.compose.toml+` files and executing multi-service +workflows. + +=== Architecture + +.... +┌─────────────────────────────────────┐ +│ stapeln (Visual Layer) │ +│ - Drag-and-drop stack designer │ +│ - miniKanren security reasoning │ +│ - Exports stack.compose.toml │ +└──────────────┬──────────────────────┘ + │ + │ stack.compose.toml + ↓ +┌─────────────────────────────────────┐ +│ poly-orchestrator-lsp (This!) │ +│ - Parse and validate stacks │ +│ - Build dependency graphs │ +│ - Orchestrate 12 LSP servers │ +│ - Handle rollbacks │ +└──────────────┬──────────────────────┘ + │ + │ LSP Protocol + ↓ +┌─────────────────────────────────────┐ +│ 12 Domain-Specific LSP Servers │ +│ poly-cloud, poly-db, poly-k8s... │ +└─────────────────────────────────────┘ +.... + +=== Features + +* ✅ *Stack Orchestration* - Execute multi-component deployments +* ✅ *Dependency Resolution* - Automatic topological sorting +* ✅ *Parallel Execution* - Run independent components concurrently +* ✅ *LSP-to-LSP Communication* - Coordinate 12 LSP servers +* ✅ *Rollback Support* - Cascade rollback on failure +* ✅ *Security Validation* - miniKanren policy enforcement +* ✅ *VeriSimDB Integration* - Shared orchestration history +* ✅ *LSP Features* - Completion, diagnostics, hover for stack files +* ✅ *Progress Tracking* - Real-time execution status +* ✅ *Verification* - Post-deployment health checks + +=== Supported Component Types + +[cols=",,",options="header",] +|=== +|Type |LSP Server |Examples +|`+cloud.*+` |poly-cloud-lsp |Provision VPC, subnets +|`+database.*+` |poly-db-lsp |PostgreSQL, MongoDB, Redis +|`+container.*+` |poly-container-lsp |Build images +|`+kubernetes.*+` |poly-k8s-lsp |Deploy to K8s +|`+observability.*+` |poly-observability-lsp |Prometheus, Grafana +|`+secrets.*+` |poly-secret-lsp |Vault, SOPS +|`+git.*+` |poly-git-lsp |Create repos +|`+queue.*+` |poly-queue-lsp |RabbitMQ, NATS +|`+ssg.*+` |poly-ssg-lsp |Static site generation +|`+iac.*+` |poly-iac-lsp |OpenTofu, Pulumi +|`+browser.*+` |claude-firefox-lsp |Browser automation +|`+proof.*+` |poly-proof-lsp |Formal verification +|=== + +=== Installation + +==== Server + +[source,bash] +---- +git clone https://github.com/hyperpolymath/poly-orchestrator-lsp.git +cd poly-orchestrator-lsp +mix deps.get +mix compile +mix test # 47 tests, 0 failures +---- + +==== VSCode Extension + +*From Marketplace* (once published): + +[source,bash] +---- +code --install-extension hyperpolymath.poly-orchestrator-lsp +---- + +*From Local Build*: + +[source,bash] +---- +cd vscode-extension +npm install && npm run build +./node_modules/.bin/vsce package +code --install-extension poly-orchestrator-lsp-0.1.0.vsix +---- + +*Extension Features*: - ✅ Auto-completion for component types and LSP +servers - ✅ Real-time diagnostics (validation, cycles, security) - ✅ +Hover documentation with duration estimates - ✅ Commands: Execute +Stack, Validate, Estimate Duration, Restart Server - ✅ Built with +*AffineScript* (type-safe, 195ms compile time) - ✅ Icon: Custom +orchestration visualization + +*Quick Start*: See QUICKSTART.md for 60-second setup guide. + +=== Usage + +==== 1. Create a Stack File + +Create `+my-stack.compose.toml+`: + +[source,toml] +---- +[metadata] +version = "1.0.0" +name = "my-web-stack" + +[[components]] +id = "cloud-infrastructure" +type = "cloud.provision" +lsp_server = "poly-cloud" +phase = 1 + +[components.config] +provider = "aws" +region = "us-west-2" + +[[components]] +id = "postgres-db" +type = "database.provision" +lsp_server = "poly-db" +phase = 2 +depends_on = ["cloud-infrastructure"] + +[components.config] +engine = "postgresql" +version = "16" +---- + +==== 2. Execute the Stack + +[source,elixir] +---- +# Parse stack +{:ok, stack} = PolyOrchestrator.Orchestrator.StackParser.parse_file("my-stack.compose.toml") + +# Build execution plan +{:ok, plan} = PolyOrchestrator.Orchestrator.Planner.build_plan(stack) + +# Execute +{:ok, result} = PolyOrchestrator.Orchestrator.Executor.execute(plan) +---- + +==== 3. Use in VSCode + +The LSP server provides: - *Completion*: Component types, LSP server +names - *Diagnostics*: Validation errors, dependency cycles - *Hover*: +Documentation for components - *Commands*: Execute stack, validate, +rollback + +=== Integration with stapeln + +poly-orchestrator-lsp consumes `+stack.compose.toml+` files exported +from https://github.com/hyperpolymath/stapeln[stapeln], the visual +container stack designer. + +*Flow*: 1. Design stack visually in stapeln 2. stapeln exports +`+stack.compose.toml+` with security policies 3. poly-orchestrator-lsp +executes the stack 4. Results stored in VeriSimDB for both systems + +=== VeriSimDB Integration + +poly-orchestrator stores orchestration history in stapeln’s VeriSimDB: + +* *Graph*: Dependency relationships +* *Vector*: Semantic search for similar stacks +* *Document*: Full stack.compose.toml files +* *Temporal*: Deployment timeline +* *Semantic*: Metadata and tags + +[source,elixir] +---- +# Query past deployments +{:ok, history} = PolyOrchestrator.VeriSimDB.Client.query_history(%{ + stack_id: "my-web-stack", + time_range: {start_time, end_time} +}) + +# Find similar stacks +{:ok, similar} = PolyOrchestrator.VeriSimDB.Client.find_similar_stacks( + "e-commerce stack with PostgreSQL" +) +---- + +=== Development + +[source,bash] +---- +# Run tests +mix test + +# Quality checks +mix quality + +# Start interactive shell +iex -S mix +---- + +=== Requirements + +* Elixir 1.17+ +* Erlang/OTP 27+ +* All 12 hyperpolymath LSP servers installed + +=== Related Projects + +* https://github.com/hyperpolymath/stapeln[stapeln] - Visual stack +designer +* https://github.com/hyperpolymath/poly-cloud-lsp[poly-cloud-lsp] - +Cloud infrastructure +* https://github.com/hyperpolymath/poly-db-lsp[poly-db-lsp] - Database +management +* https://github.com/hyperpolymath/poly-k8s-lsp[poly-k8s-lsp] - +Kubernetes orchestration +* https://github.com/hyperpolymath/poly-ssg-lsp/blob/main/LSP-SERVERS-INDEX.md[See +all 12 LSP servers] + +=== License + +MPL-2.0 (Mozilla Public License 2.0) + +=== Authors + +* *Jonathan D.A. Jewell* j.d.a.jewell@open.ac.uk +* *Co-Authored-By*: Claude Sonnet 4.5 noreply@anthropic.com + +''''' + +*Part of the https://github.com/hyperpolymath[hyperpolymath] ecosystem* diff --git a/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/README.md b/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/README.md deleted file mode 100644 index 1819a2eb..00000000 --- a/cartridges/cross-cutting/orchestration/stack-orchestrator-mcp/_source-archive/README.md +++ /dev/null @@ -1,235 +0,0 @@ -# poly-orchestrator-lsp - -**Orchestration layer for 12 hyperpolymath LSP servers with stapeln integration** - -[![License](https://img.shields.io/badge/license-MPL--2.0-brightgreen.svg)](./LICENSE) -[![Elixir](https://img.shields.io/badge/elixir-1.17+-purple.svg)](https://elixir-lang.org/) -[![OTP](https://img.shields.io/badge/OTP-27+-red.svg)](https://www.erlang.org/) -[![Tests](https://img.shields.io/badge/tests-47%2F47%20passing-brightgreen.svg)](#) -[![Extension](https://img.shields.io/badge/VSCode-AffineScript-blue.svg)](./vscode-extension) - -## Overview - -poly-orchestrator-lsp is the 13th LSP server in the hyperpolymath ecosystem, providing **orchestration and coordination** for the other 12 domain-specific LSP servers. It enables **automated stack deployment** by parsing `stack.compose.toml` files and executing multi-service workflows. - -## Architecture - -``` -┌─────────────────────────────────────┐ -│ stapeln (Visual Layer) │ -│ - Drag-and-drop stack designer │ -│ - miniKanren security reasoning │ -│ - Exports stack.compose.toml │ -└──────────────┬──────────────────────┘ - │ - │ stack.compose.toml - ↓ -┌─────────────────────────────────────┐ -│ poly-orchestrator-lsp (This!) │ -│ - Parse and validate stacks │ -│ - Build dependency graphs │ -│ - Orchestrate 12 LSP servers │ -│ - Handle rollbacks │ -└──────────────┬──────────────────────┘ - │ - │ LSP Protocol - ↓ -┌─────────────────────────────────────┐ -│ 12 Domain-Specific LSP Servers │ -│ poly-cloud, poly-db, poly-k8s... │ -└─────────────────────────────────────┘ -``` - -## Features - -- ✅ **Stack Orchestration** - Execute multi-component deployments -- ✅ **Dependency Resolution** - Automatic topological sorting -- ✅ **Parallel Execution** - Run independent components concurrently -- ✅ **LSP-to-LSP Communication** - Coordinate 12 LSP servers -- ✅ **Rollback Support** - Cascade rollback on failure -- ✅ **Security Validation** - miniKanren policy enforcement -- ✅ **VeriSimDB Integration** - Shared orchestration history -- ✅ **LSP Features** - Completion, diagnostics, hover for stack files -- ✅ **Progress Tracking** - Real-time execution status -- ✅ **Verification** - Post-deployment health checks - -## Supported Component Types - -| Type | LSP Server | Examples | -|------|-----------|----------| -| `cloud.*` | poly-cloud-lsp | Provision VPC, subnets | -| `database.*` | poly-db-lsp | PostgreSQL, MongoDB, Redis | -| `container.*` | poly-container-lsp | Build images | -| `kubernetes.*` | poly-k8s-lsp | Deploy to K8s | -| `observability.*` | poly-observability-lsp | Prometheus, Grafana | -| `secrets.*` | poly-secret-lsp | Vault, SOPS | -| `git.*` | poly-git-lsp | Create repos | -| `queue.*` | poly-queue-lsp | RabbitMQ, NATS | -| `ssg.*` | poly-ssg-lsp | Static site generation | -| `iac.*` | poly-iac-lsp | OpenTofu, Pulumi | -| `browser.*` | claude-firefox-lsp | Browser automation | -| `proof.*` | poly-proof-lsp | Formal verification | - -## Installation - -### Server - -```bash -git clone https://github.com/hyperpolymath/poly-orchestrator-lsp.git -cd poly-orchestrator-lsp -mix deps.get -mix compile -mix test # 47 tests, 0 failures -``` - -### VSCode Extension - -**From Marketplace** (once published): -```bash -code --install-extension hyperpolymath.poly-orchestrator-lsp -``` - -**From Local Build**: -```bash -cd vscode-extension -npm install && npm run build -./node_modules/.bin/vsce package -code --install-extension poly-orchestrator-lsp-0.1.0.vsix -``` - -**Extension Features**: -- ✅ Auto-completion for component types and LSP servers -- ✅ Real-time diagnostics (validation, cycles, security) -- ✅ Hover documentation with duration estimates -- ✅ Commands: Execute Stack, Validate, Estimate Duration, Restart Server -- ✅ Built with **AffineScript** (type-safe, 195ms compile time) -- ✅ Icon: Custom orchestration visualization - -**Quick Start**: See [QUICKSTART.md](QUICKSTART.md) for 60-second setup guide. - -## Usage - -### 1. Create a Stack File - -Create `my-stack.compose.toml`: - -```toml -[metadata] -version = "1.0.0" -name = "my-web-stack" - -[[components]] -id = "cloud-infrastructure" -type = "cloud.provision" -lsp_server = "poly-cloud" -phase = 1 - -[components.config] -provider = "aws" -region = "us-west-2" - -[[components]] -id = "postgres-db" -type = "database.provision" -lsp_server = "poly-db" -phase = 2 -depends_on = ["cloud-infrastructure"] - -[components.config] -engine = "postgresql" -version = "16" -``` - -### 2. Execute the Stack - -```elixir -# Parse stack -{:ok, stack} = PolyOrchestrator.Orchestrator.StackParser.parse_file("my-stack.compose.toml") - -# Build execution plan -{:ok, plan} = PolyOrchestrator.Orchestrator.Planner.build_plan(stack) - -# Execute -{:ok, result} = PolyOrchestrator.Orchestrator.Executor.execute(plan) -``` - -### 3. Use in VSCode - -The LSP server provides: -- **Completion**: Component types, LSP server names -- **Diagnostics**: Validation errors, dependency cycles -- **Hover**: Documentation for components -- **Commands**: Execute stack, validate, rollback - -## Integration with stapeln - -poly-orchestrator-lsp consumes `stack.compose.toml` files exported from [stapeln](https://github.com/hyperpolymath/stapeln), the visual container stack designer. - -**Flow**: -1. Design stack visually in stapeln -2. stapeln exports `stack.compose.toml` with security policies -3. poly-orchestrator-lsp executes the stack -4. Results stored in VeriSimDB for both systems - -## VeriSimDB Integration - -poly-orchestrator stores orchestration history in stapeln's VeriSimDB: - -- **Graph**: Dependency relationships -- **Vector**: Semantic search for similar stacks -- **Document**: Full stack.compose.toml files -- **Temporal**: Deployment timeline -- **Semantic**: Metadata and tags - -```elixir -# Query past deployments -{:ok, history} = PolyOrchestrator.VeriSimDB.Client.query_history(%{ - stack_id: "my-web-stack", - time_range: {start_time, end_time} -}) - -# Find similar stacks -{:ok, similar} = PolyOrchestrator.VeriSimDB.Client.find_similar_stacks( - "e-commerce stack with PostgreSQL" -) -``` - -## Development - -```bash -# Run tests -mix test - -# Quality checks -mix quality - -# Start interactive shell -iex -S mix -``` - -## Requirements - -- Elixir 1.17+ -- Erlang/OTP 27+ -- All 12 hyperpolymath LSP servers installed - -## Related Projects - -- [stapeln](https://github.com/hyperpolymath/stapeln) - Visual stack designer -- [poly-cloud-lsp](https://github.com/hyperpolymath/poly-cloud-lsp) - Cloud infrastructure -- [poly-db-lsp](https://github.com/hyperpolymath/poly-db-lsp) - Database management -- [poly-k8s-lsp](https://github.com/hyperpolymath/poly-k8s-lsp) - Kubernetes orchestration -- [See all 12 LSP servers](https://github.com/hyperpolymath/poly-ssg-lsp/blob/main/LSP-SERVERS-INDEX.md) - -## License - -MPL-2.0 (Mozilla Public License 2.0) - -## Authors - -- **Jonathan D.A. Jewell** -- **Co-Authored-By**: Claude Sonnet 4.5 - ---- - -**Part of the [hyperpolymath](https://github.com/hyperpolymath) ecosystem** diff --git a/cartridges/domains/development/git-lsp/_source-archive/README.adoc b/cartridges/domains/development/git-lsp/_source-archive/README.adoc new file mode 100644 index 00000000..9bd1e594 --- /dev/null +++ b/cartridges/domains/development/git-lsp/_source-archive/README.adoc @@ -0,0 +1,118 @@ +== poly-git-lsp + +____ +Language Server Protocol implementation for Git forge management +(GitHub, GitLab, Gitea, Bitbucket) +____ + +https://www.mozilla.org/en-US/MPL/2.0/[image:https://img.shields.io/badge/License-MPL--2.0-brightgreen.svg[License: +MPL-2.0]] +https://elixir-lang.org/[image:https://img.shields.io/badge/elixir-1.17+-purple.svg[Elixir +1.17+]] + +=== Overview + +*poly-git-lsp* provides IDE integration for Git forge operations across +GitHub, GitLab, Gitea, and Bitbucket. Built with Elixir’s BEAM VM, each +forge adapter runs as an isolated process with automatic fault recovery. + +=== Features + +* 🔄 *Auto-detection*: Detects Git forge from .git/config +* 📦 *Repository management*: Create repos, configure settings +* 🔀 *Pull/Merge requests*: Create, list, merge PRs/MRs +* 🐛 *Issue tracking*: Create and manage issues +* ⚡ *Commands*: Execute forge operations directly from editor +* 🛡️ *Fault isolation*: Crash in one adapter doesn’t affect others + +=== Supported Forges + +[cols=",,",options="header",] +|=== +|Forge |CLI Tool |Status +|GitHub |`+gh+` |✅ Implemented +|GitLab |`+glab+` |✅ Implemented +|Gitea |`+tea+` |✅ Implemented +|Bitbucket |API |🚧 Placeholder +|=== + +=== Installation + +[source,bash] +---- +git clone https://github.com/hyperpolymath/poly-git-lsp +cd poly-git-lsp +mix deps.get +mix compile +---- + +=== Prerequisites + +Install the CLI tools for your Git forge: + +* *GitHub*: https://cli.github.com/[gh CLI] +* *GitLab*: https://gitlab.com/gitlab-org/cli[glab CLI] +* *Gitea*: https://gitea.com/gitea/tea[tea CLI] +* *Bitbucket*: API token (no official CLI) + +=== Usage + +==== VSCode Extension + +Coming soon. Will provide commands like: + +* `+Poly-Git: Detect Forge+` +* `+Poly-Git: Create Repository+` +* `+Poly-Git: Create Pull Request+` +* `+Poly-Git: List Pull Requests+` +* `+Poly-Git: Merge Pull Request+` + +==== Direct Usage + +[source,elixir] +---- +# Detect which forge is used +PolyGit.LSP.detect_forge("/path/to/project") +# => [PolyGit.Adapters.GitHub] + +# Create a PR +PolyGit.Adapters.GitHub.create_pr("hyperpolymath", "poly-git-lsp", + title: "Add new feature", + body: "This PR adds...", + head: "feature-branch", + base: "main" +) +---- + +=== Architecture + +* *Adapters*: Each forge (GitHub, GitLab, etc.) is a separate GenServer +* *Supervision*: One-for-one supervision strategy - crashed adapters +restart independently +* *LSP Protocol*: Uses GenLSP for language server implementation +* *CLI Tools*: Wraps official CLI tools (gh, glab, tea) for reliability + +=== Development + +[source,bash] +---- +# Run tests +mix test + +# Type checking +mix dialyzer + +# Linting +mix credo --strict + +# Format code +mix format +---- + +=== License + +MPL-2.0 + +=== Author + +Jonathan D.A. Jewell j.d.a.jewell@open.ac.uk diff --git a/cartridges/domains/development/git-lsp/_source-archive/README.md b/cartridges/domains/development/git-lsp/_source-archive/README.md deleted file mode 100644 index 50520c93..00000000 --- a/cartridges/domains/development/git-lsp/_source-archive/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# poly-git-lsp - -> Language Server Protocol implementation for Git forge management (GitHub, GitLab, Gitea, Bitbucket) - -[![License: MPL-2.0](https://img.shields.io/badge/License-MPL--2.0-brightgreen.svg)](https://www.mozilla.org/en-US/MPL/2.0/) -[![Elixir 1.17+](https://img.shields.io/badge/elixir-1.17+-purple.svg)](https://elixir-lang.org/) - -## Overview - -**poly-git-lsp** provides IDE integration for Git forge operations across GitHub, GitLab, Gitea, and Bitbucket. Built with Elixir's BEAM VM, each forge adapter runs as an isolated process with automatic fault recovery. - -## Features - -- 🔄 **Auto-detection**: Detects Git forge from .git/config -- 📦 **Repository management**: Create repos, configure settings -- 🔀 **Pull/Merge requests**: Create, list, merge PRs/MRs -- 🐛 **Issue tracking**: Create and manage issues -- ⚡ **Commands**: Execute forge operations directly from editor -- 🛡️ **Fault isolation**: Crash in one adapter doesn't affect others - -## Supported Forges - -| Forge | CLI Tool | Status | -|-------|----------|--------| -| GitHub | `gh` | ✅ Implemented | -| GitLab | `glab` | ✅ Implemented | -| Gitea | `tea` | ✅ Implemented | -| Bitbucket | API | 🚧 Placeholder | - -## Installation - -```bash -git clone https://github.com/hyperpolymath/poly-git-lsp -cd poly-git-lsp -mix deps.get -mix compile -``` - -## Prerequisites - -Install the CLI tools for your Git forge: - -- **GitHub**: [gh CLI](https://cli.github.com/) -- **GitLab**: [glab CLI](https://gitlab.com/gitlab-org/cli) -- **Gitea**: [tea CLI](https://gitea.com/gitea/tea) -- **Bitbucket**: API token (no official CLI) - -## Usage - -### VSCode Extension - -Coming soon. Will provide commands like: - -- `Poly-Git: Detect Forge` -- `Poly-Git: Create Repository` -- `Poly-Git: Create Pull Request` -- `Poly-Git: List Pull Requests` -- `Poly-Git: Merge Pull Request` - -### Direct Usage - -```elixir -# Detect which forge is used -PolyGit.LSP.detect_forge("/path/to/project") -# => [PolyGit.Adapters.GitHub] - -# Create a PR -PolyGit.Adapters.GitHub.create_pr("hyperpolymath", "poly-git-lsp", - title: "Add new feature", - body: "This PR adds...", - head: "feature-branch", - base: "main" -) -``` - -## Architecture - -- **Adapters**: Each forge (GitHub, GitLab, etc.) is a separate GenServer -- **Supervision**: One-for-one supervision strategy - crashed adapters restart independently -- **LSP Protocol**: Uses GenLSP for language server implementation -- **CLI Tools**: Wraps official CLI tools (gh, glab, tea) for reliability - -## Development - -```bash -# Run tests -mix test - -# Type checking -mix dialyzer - -# Linting -mix credo --strict - -# Format code -mix format -``` - -## License - -MPL-2.0 - -## Author - -Jonathan D.A. Jewell diff --git a/cartridges/domains/formal-verification/proof-lsp/_source-archive/README.adoc b/cartridges/domains/formal-verification/proof-lsp/_source-archive/README.adoc new file mode 100644 index 00000000..6693590e --- /dev/null +++ b/cartridges/domains/formal-verification/proof-lsp/_source-archive/README.adoc @@ -0,0 +1,178 @@ +== poly-proof-lsp + +____ +Production-ready Language Server Protocol implementation for proof +assistants +____ + +https://github.com/hyperpolymath/poly-proof-lsp[image:https://img.shields.io/badge/status-production--ready-brightgreen.svg[Production +Ready]] +https://github.com/hyperpolymath/poly-proof-lsp/releases[image:https://img.shields.io/badge/version-1.0.0-blue.svg[Version: +1.0.0]] +https://www.mozilla.org/en-US/MPL/2.0/[image:https://img.shields.io/badge/License-MPL--2.0-brightgreen.svg[License: +MPL-2.0]] +https://elixir-lang.org/[image:https://img.shields.io/badge/elixir-1.17+-purple.svg[Elixir +1.17+]] + +=== Overview + +*poly-proof-lsp* provides IDE integration for formal verification tools +including Coq, Lean, Isabelle, and Agda. Built with Elixir’s BEAM VM, +each proof assistant adapter runs as an isolated process with automatic +fault recovery. + +=== Features + +* 🔍 *Auto-detection*: Detects proof assistant from project files +* ✅ *Proof checking*: Real-time validation with coqc, lean, isabelle, +agda +* 🎯 *Goal display*: Show current proof goals and hypotheses +* ✨ *Tactic completion*: Auto-complete tactics and proof commands +* 📚 *Theorem search*: Search standard libraries for relevant theorems +* 📖 *Hover docs*: Display proof state and type information +* ⚡ *Commands*: Check proofs, show goals, apply tactics directly from +editor +* 🛡️ *Fault isolation*: Crash in one adapter doesn’t affect others + +=== Supported Proof Assistants + +[width="99%",cols="29%,28%,30%,13%",options="header",] +|=== +|Proof Assistant |File Extensions |Interactive Mode |Status +|*Coq* |`+.v+` |coqtop |✅ Production + +|*Lean* |`+.lean+` |lean –server |✅ Production + +|*Isabelle* |`+.thy+` |PIDE |✅ Production + +|*Agda* |`+.agda+`, `+.lagda+`, `+.lagda.md+` |agda –interaction |✅ +Production +|=== + +=== Installation + +[source,bash] +---- +git clone https://github.com/hyperpolymath/poly-proof-lsp +cd poly-proof-lsp +mix deps.get +mix compile +---- + +=== Usage + +==== Standalone + +[source,bash] +---- +mix run --no-halt +---- + +==== With VSCode + +[arabic] +. Install the extension: ++ +[source,bash] +---- +cd vscode-extension +npm install +npm run package +code --install-extension *.vsix +---- +. Configure in `+settings.json+`: ++ +[source,json] +---- +{ + "polyProof.enable": true, + "polyProof.serverPath": "/path/to/poly-proof-lsp" +} +---- + +See USAGE.md for detailed configuration options. + +==== With Neovim + +[source,lua] +---- +require('lspconfig').poly_proof_lsp.setup{ + cmd = {'/path/to/poly-proof-lsp/bin/poly-proof-lsp'}, + filetypes = {'coq', 'lean', 'isabelle', 'agda'}, +} +---- + +=== Development + +[source,bash] +---- +# Setup +just setup + +# Run tests +just test + +# Check code quality +just quality + +# Format code +just format + +# Generate docs +just docs +---- + +=== Architecture + +Each proof assistant runs as an isolated GenServer under a supervision +tree: + +.... +PolyProof.LSP.Supervisor +├── PolyProof.Adapters.Supervisor +│ ├── PolyProof.Adapters.Coq (GenServer) +│ ├── PolyProof.Adapters.Lean (GenServer) +│ ├── PolyProof.Adapters.Isabelle (GenServer) +│ └── PolyProof.Adapters.Agda (GenServer) +└── PolyProof.LSP.Server +.... + +Crashes in one adapter automatically restart without affecting others. +Multiple proofs can be checked concurrently. + +=== Troubleshooting + +==== Server Not Starting + +* Check Elixir/OTP versions: `+elixir --version+` +* Verify dependencies: `+mix deps.get+` +* Check logs: `+tail -f log/poly_proof.log+` + +==== LSP Not Connecting + +* Verify server is running: `+ps aux | grep poly_proof+` +* Check LSP client logs in your editor +* Ensure correct file types are configured + +==== Performance Issues + +* Monitor with Observer: `+iex -S mix+`, then `+:observer.start()+` +* Check adapter health via `+health_check+` command +* Review adapter-specific logs + +See USAGE.md for more detailed troubleshooting steps. + +=== Related Projects + +* https://github.com/hyperpolymath/poly-ssg-lsp[poly-ssg-lsp] - LSP for +static site generators +* https://github.com/hyperpolymath/poly-observability-lsp[poly-observability-lsp] +- LSP for observability tools + +=== License + +MPL-2.0 + +=== Author + +Jonathan D.A. Jewell j.d.a.jewell@open.ac.uk diff --git a/cartridges/domains/formal-verification/proof-lsp/_source-archive/README.md b/cartridges/domains/formal-verification/proof-lsp/_source-archive/README.md deleted file mode 100644 index e85b531f..00000000 --- a/cartridges/domains/formal-verification/proof-lsp/_source-archive/README.md +++ /dev/null @@ -1,148 +0,0 @@ -# poly-proof-lsp - -> Production-ready Language Server Protocol implementation for proof assistants - -[![Production Ready](https://img.shields.io/badge/status-production--ready-brightgreen.svg)](https://github.com/hyperpolymath/poly-proof-lsp) -[![Version: 1.0.0](https://img.shields.io/badge/version-1.0.0-blue.svg)](https://github.com/hyperpolymath/poly-proof-lsp/releases) -[![License: MPL-2.0](https://img.shields.io/badge/License-MPL--2.0-brightgreen.svg)](https://www.mozilla.org/en-US/MPL/2.0/) -[![Elixir 1.17+](https://img.shields.io/badge/elixir-1.17+-purple.svg)](https://elixir-lang.org/) - -## Overview - -**poly-proof-lsp** provides IDE integration for formal verification tools including Coq, Lean, Isabelle, and Agda. Built with Elixir's BEAM VM, each proof assistant adapter runs as an isolated process with automatic fault recovery. - -## Features - -- 🔍 **Auto-detection**: Detects proof assistant from project files -- ✅ **Proof checking**: Real-time validation with coqc, lean, isabelle, agda -- 🎯 **Goal display**: Show current proof goals and hypotheses -- ✨ **Tactic completion**: Auto-complete tactics and proof commands -- 📚 **Theorem search**: Search standard libraries for relevant theorems -- 📖 **Hover docs**: Display proof state and type information -- ⚡ **Commands**: Check proofs, show goals, apply tactics directly from editor -- 🛡️ **Fault isolation**: Crash in one adapter doesn't affect others - -## Supported Proof Assistants - -| Proof Assistant | File Extensions | Interactive Mode | Status | -|----------------|-----------------|------------------|--------| -| **Coq** | `.v` | coqtop | ✅ Production | -| **Lean** | `.lean` | lean --server | ✅ Production | -| **Isabelle** | `.thy` | PIDE | ✅ Production | -| **Agda** | `.agda`, `.lagda`, `.lagda.md` | agda --interaction | ✅ Production | - -## Installation - -```bash -git clone https://github.com/hyperpolymath/poly-proof-lsp -cd poly-proof-lsp -mix deps.get -mix compile -``` - -## Usage - -### Standalone - -```bash -mix run --no-halt -``` - -### With VSCode - -1. Install the extension: - ```bash - cd vscode-extension - npm install - npm run package - code --install-extension *.vsix - ``` - -2. Configure in `settings.json`: - ```json - { - "polyProof.enable": true, - "polyProof.serverPath": "/path/to/poly-proof-lsp" - } - ``` - -See [USAGE.md](USAGE.md) for detailed configuration options. - -### With Neovim - -```lua -require('lspconfig').poly_proof_lsp.setup{ - cmd = {'/path/to/poly-proof-lsp/bin/poly-proof-lsp'}, - filetypes = {'coq', 'lean', 'isabelle', 'agda'}, -} -``` - -## Development - -```bash -# Setup -just setup - -# Run tests -just test - -# Check code quality -just quality - -# Format code -just format - -# Generate docs -just docs -``` - -## Architecture - -Each proof assistant runs as an isolated GenServer under a supervision tree: - -``` -PolyProof.LSP.Supervisor -├── PolyProof.Adapters.Supervisor -│ ├── PolyProof.Adapters.Coq (GenServer) -│ ├── PolyProof.Adapters.Lean (GenServer) -│ ├── PolyProof.Adapters.Isabelle (GenServer) -│ └── PolyProof.Adapters.Agda (GenServer) -└── PolyProof.LSP.Server -``` - -Crashes in one adapter automatically restart without affecting others. Multiple proofs can be checked concurrently. - -## Troubleshooting - -### Server Not Starting - -- Check Elixir/OTP versions: `elixir --version` -- Verify dependencies: `mix deps.get` -- Check logs: `tail -f log/poly_proof.log` - -### LSP Not Connecting - -- Verify server is running: `ps aux | grep poly_proof` -- Check LSP client logs in your editor -- Ensure correct file types are configured - -### Performance Issues - -- Monitor with Observer: `iex -S mix`, then `:observer.start()` -- Check adapter health via `health_check` command -- Review adapter-specific logs - -See [USAGE.md](USAGE.md) for more detailed troubleshooting steps. - -## Related Projects - -- [poly-ssg-lsp](https://github.com/hyperpolymath/poly-ssg-lsp) - LSP for static site generators -- [poly-observability-lsp](https://github.com/hyperpolymath/poly-observability-lsp) - LSP for observability tools - -## License - -MPL-2.0 - -## Author - -Jonathan D.A. Jewell diff --git a/cartridges/domains/gaming/npc-mcp/INSTALL.adoc b/cartridges/domains/gaming/npc-mcp/INSTALL.adoc new file mode 100644 index 00000000..aa7f3967 --- /dev/null +++ b/cartridges/domains/gaming/npc-mcp/INSTALL.adoc @@ -0,0 +1,47 @@ +== Installing npc-mcp + +npc-mcp lives in the canonical cartridge repository under +`+cartridges/domains/gaming/npc-mcp+`. A BoJ host fetches it on demand; +you need only build its Zig core so the shared library is present for +the host to load. + +=== Build the Zig FFI + +[source,bash] +---- +cd cartridges/domains/gaming/npc-mcp/ffi +zig build # produces zig-out/lib/libnpc_mcp.so +zig build test # unit tests for the ABI and core modules +zig build integration # synthetic JSONL stream through the core +---- + +The shared library is emitted at `+ffi/zig-out/lib/libnpc_mcp.so+`, the +`+so_path+` declared in `+cartridge.json+`. The host loads it through +the standard `+boj_cartridge_invoke+` ABI (ADR-0006); no per-cartridge +adapter wiring exists. + +=== The Fabric mod and the wire protocol + +The cartridge is only one half of the system. The companion Fabric mod +and the shared JSONL wire protocol live in the separate `+npc-mcp+` +project. The mod dials out to the host and drives this cartridge through +its tools: + +* it POSTs each protocol v1 event to `+npc_ingest_event+`; +* it polls `+npc_drain_commands+` and executes each returned command +in-game. + +Point the mod’s connection config at the host’s tool endpoint for this +cartridge. There is no inbound socket on the cartridge side. + +=== Persona + +Command tools (`+npc_say+`, `+npc_give+`, `+npc_execute_command+`) are +gated by the active persona. Load one with `+npc_load_persona+`, passing +the persona object as the arguments. Until a persona is loaded, command +tools fail closed; perception reads remain available. + +=== Uninstall + +Remove the cartridge directory from the tree; there is no host-side +wiring to reverse. diff --git a/cartridges/domains/gaming/npc-mcp/INSTALL.md b/cartridges/domains/gaming/npc-mcp/INSTALL.md deleted file mode 100644 index 7ab47b7c..00000000 --- a/cartridges/domains/gaming/npc-mcp/INSTALL.md +++ /dev/null @@ -1,43 +0,0 @@ - -# Installing npc-mcp - -npc-mcp lives in the canonical cartridge repository under -`cartridges/domains/gaming/npc-mcp`. A BoJ host fetches it on demand; you need -only build its Zig core so the shared library is present for the host to load. - -## Build the Zig FFI - -```bash -cd cartridges/domains/gaming/npc-mcp/ffi -zig build # produces zig-out/lib/libnpc_mcp.so -zig build test # unit tests for the ABI and core modules -zig build integration # synthetic JSONL stream through the core -``` - -The shared library is emitted at `ffi/zig-out/lib/libnpc_mcp.so`, the `so_path` -declared in `cartridge.json`. The host loads it through the standard -`boj_cartridge_invoke` ABI (ADR-0006); no per-cartridge adapter wiring exists. - -## The Fabric mod and the wire protocol - -The cartridge is only one half of the system. The companion Fabric mod and the -shared JSONL wire protocol live in the separate `npc-mcp` project. The mod dials -out to the host and drives this cartridge through its tools: - -- it POSTs each protocol v1 event to `npc_ingest_event`; -- it polls `npc_drain_commands` and executes each returned command in-game. - -Point the mod's connection config at the host's tool endpoint for this -cartridge. There is no inbound socket on the cartridge side. - -## Persona - -Command tools (`npc_say`, `npc_give`, `npc_execute_command`) are gated by the -active persona. Load one with `npc_load_persona`, passing the persona object as -the arguments. Until a persona is loaded, command tools fail closed; perception -reads remain available. - -## Uninstall - -Remove the cartridge directory from the tree; there is no host-side wiring to -reverse. diff --git a/cartridges/domains/gaming/npc-mcp/README.adoc b/cartridges/domains/gaming/npc-mcp/README.adoc new file mode 100644 index 00000000..4ae08d00 --- /dev/null +++ b/cartridges/domains/gaming/npc-mcp/README.adoc @@ -0,0 +1,52 @@ +== npc-mcp + +A BoJ cartridge that embeds an AI presence, a "`ghost in the machine`", +inside a Minecraft server. The cartridge holds a layered perception of +the game world and exposes curated command tools so an MCP client can +act as an unseen participant. + +=== Transport + +The cartridge holds no socket of its own. A companion Fabric mod (in the +separate `+npc-mcp+` project, alongside the shared JSONL wire protocol) +dials out to the host and drives the cartridge through ordinary tool +calls: + +* it POSTs each world event to `+npc_ingest_event+`; +* it polls `+npc_drain_commands+` for queued actions and executes them +in-game. + +So the cartridge is a passive request/response state machine: events in, +commands out. Nothing here listens on a port. + +=== Architecture + +Two layers, in the BoJ house pattern: + +* `+abi/NpcMcp/*.idr+` proves the protocol’s safety properties: +perception is read-only, command tools are persona-gated, and state +transitions are total. +* `+ffi/+` is the Zig core: a ring buffer of raw events, a world-state +model, a narrative synthesiser, a rate-limited command queue, and the +persona gate. `+npc_mcp_ffi.zig+` exposes the standard +`+boj_cartridge_invoke+` ABI (ADR-0006) over that core. + +=== Tools + +Perception (read-only): `+npc_get_narrative_context+`, +`+npc_get_world_state+`, `+npc_get_recent_events+`. + +Transport (driven by the mod): `+npc_ingest_event+`, +`+npc_drain_commands+`. + +Commands (persona-gated; queued for the mod): `+npc_say+`, `+npc_give+`, +`+npc_execute_command+`. Plus `+npc_load_persona+` to set the active +persona; until one is loaded, command tools fail closed. + +=== Tests + +.... +cd ffi +zig build test # unit tests for the ABI and every core module +zig build integration # a synthetic JSONL event stream through the core +.... diff --git a/cartridges/domains/gaming/npc-mcp/README.md b/cartridges/domains/gaming/npc-mcp/README.md deleted file mode 100644 index e8c6f10a..00000000 --- a/cartridges/domains/gaming/npc-mcp/README.md +++ /dev/null @@ -1,48 +0,0 @@ - -# npc-mcp - -A BoJ cartridge that embeds an AI presence, a "ghost in the machine", inside a -Minecraft server. The cartridge holds a layered perception of the game world and -exposes curated command tools so an MCP client can act as an unseen participant. - -## Transport - -The cartridge holds no socket of its own. A companion Fabric mod (in the -separate `npc-mcp` project, alongside the shared JSONL wire protocol) dials out -to the host and drives the cartridge through ordinary tool calls: - -- it POSTs each world event to `npc_ingest_event`; -- it polls `npc_drain_commands` for queued actions and executes them in-game. - -So the cartridge is a passive request/response state machine: events in, -commands out. Nothing here listens on a port. - -## Architecture - -Two layers, in the BoJ house pattern: - -- `abi/NpcMcp/*.idr` proves the protocol's safety properties: perception is - read-only, command tools are persona-gated, and state transitions are total. -- `ffi/` is the Zig core: a ring buffer of raw events, a world-state model, a - narrative synthesiser, a rate-limited command queue, and the persona gate. - `npc_mcp_ffi.zig` exposes the standard `boj_cartridge_invoke` ABI (ADR-0006) - over that core. - -## Tools - -Perception (read-only): `npc_get_narrative_context`, `npc_get_world_state`, -`npc_get_recent_events`. - -Transport (driven by the mod): `npc_ingest_event`, `npc_drain_commands`. - -Commands (persona-gated; queued for the mod): `npc_say`, `npc_give`, -`npc_execute_command`. Plus `npc_load_persona` to set the active persona; until -one is loaded, command tools fail closed. - -## Tests - -``` -cd ffi -zig build test # unit tests for the ABI and every core module -zig build integration # a synthetic JSONL event stream through the core -``` diff --git a/cartridges/domains/knowledge/librarian-mcp/INSTALL.adoc b/cartridges/domains/knowledge/librarian-mcp/INSTALL.adoc new file mode 100644 index 00000000..803e5d88 --- /dev/null +++ b/cartridges/domains/knowledge/librarian-mcp/INSTALL.adoc @@ -0,0 +1,74 @@ +== Installing librarian-mcp + +librarian-mcp lives in the canonical cartridge repository under +`+cartridges/domains/knowledge/librarian-mcp+`. A BoJ host (boj-server, +panll) fetches it on demand; you need only build its Zig core so the +shared library is present for the host to load. + +=== Build the Zig FFI + +[source,bash] +---- +cd cartridges/domains/knowledge/librarian-mcp/ffi +zig build # produces zig-out/lib/liblibrarian_mcp.so and the static lib +zig build test # unit tests +zig build integration # end-to-end and C-ABI round trip (offline hash backend) +---- + +The shared library is emitted at +`+ffi/zig-out/lib/liblibrarian_mcp.so+`, the `+so_path+` declared in +`+cartridge.json+`. The host loads it through the standard +`+boj_cartridge_invoke+` ABI (ADR-0006); no per-cartridge adapter wiring +is required. + +=== Embedding delegation + +The `+hf+` backend obtains real semantic vectors from the `+ml-mcp+` +cartridge’s HuggingFace feature-extraction; build that cartridge if you +intend to use it: + +[source,bash] +---- +cd ../../../cross-cutting/.../ml-mcp/ffi && zig build # adjust to ml-mcp's path in this tree +---- + +HuggingFace credentials are reused from `+ml-mcp+` (set its token as +that cartridge documents). The `+hash+` backend needs none of this and +runs offline, which is what the integration test exercises. + +=== Invoke through the host + +Once the host has loaded the cartridge, the tools are reached through +its invoke envelope, `+{"tool":"...","args":"..."}+`, where `+args+` is +itself a JSON string: + +[source,bash] +---- +# Ingest (offline hash backend; use "hf" for HuggingFace via ml-mcp): +curl -X POST http://localhost:7700/cartridge/librarian-mcp/invoke \ + -H 'Content-Type: application/json' \ + -d '{"tool":"librarian_ingest","args":"{\"collection\":\"book\",\"source_name\":\"book.pdf\",\"pdf_path\":\"/abs/book.pdf\",\"backend\":\"hash\"}"}' + +# Query: +curl -X POST http://localhost:7700/cartridge/librarian-mcp/invoke \ + -H 'Content-Type: application/json' \ + -d '{"tool":"librarian_query","args":"{\"collection\":\"book\",\"query\":\"...\",\"k\":5}"}' +---- + +The exact host route and port depend on the host’s configuration; the +envelope shape is what the cartridge guarantees. + +=== Configuration + +* `+BOJ_LIBRARIAN_HOME+` – collections root on disk. Defaults to +`+$HOME/.local/share/boj/librarian+`. The Zig core never reads the +environment itself (when loaded as a shared library from a non-Zig host, +`+std.os.environ+` is unset); the host resolves this path and passes it +to `+librarian_init+`. +* `+BOJ_LIBRARIAN_READONLY+` – if set to any value, ingest and delete +are refused (reads remain available). + +=== Uninstall + +Remove the cartridge directory from the tree; there is no host-side +wiring to reverse. diff --git a/cartridges/domains/knowledge/librarian-mcp/INSTALL.md b/cartridges/domains/knowledge/librarian-mcp/INSTALL.md deleted file mode 100644 index d490880b..00000000 --- a/cartridges/domains/knowledge/librarian-mcp/INSTALL.md +++ /dev/null @@ -1,68 +0,0 @@ - -# Installing librarian-mcp - -librarian-mcp lives in the canonical cartridge repository under -`cartridges/domains/knowledge/librarian-mcp`. A BoJ host (boj-server, panll) -fetches it on demand; you need only build its Zig core so the shared library is -present for the host to load. - -## Build the Zig FFI - -```bash -cd cartridges/domains/knowledge/librarian-mcp/ffi -zig build # produces zig-out/lib/liblibrarian_mcp.so and the static lib -zig build test # unit tests -zig build integration # end-to-end and C-ABI round trip (offline hash backend) -``` - -The shared library is emitted at -`ffi/zig-out/lib/liblibrarian_mcp.so`, the `so_path` declared in -`cartridge.json`. The host loads it through the standard `boj_cartridge_invoke` -ABI (ADR-0006); no per-cartridge adapter wiring is required. - -## Embedding delegation - -The `hf` backend obtains real semantic vectors from the `ml-mcp` cartridge's -HuggingFace feature-extraction; build that cartridge if you intend to use it: - -```bash -cd ../../../cross-cutting/.../ml-mcp/ffi && zig build # adjust to ml-mcp's path in this tree -``` - -HuggingFace credentials are reused from `ml-mcp` (set its token as that -cartridge documents). The `hash` backend needs none of this and runs offline, -which is what the integration test exercises. - -## Invoke through the host - -Once the host has loaded the cartridge, the tools are reached through its invoke -envelope, `{"tool":"...","args":"..."}`, where `args` is itself a JSON string: - -```bash -# Ingest (offline hash backend; use "hf" for HuggingFace via ml-mcp): -curl -X POST http://localhost:7700/cartridge/librarian-mcp/invoke \ - -H 'Content-Type: application/json' \ - -d '{"tool":"librarian_ingest","args":"{\"collection\":\"book\",\"source_name\":\"book.pdf\",\"pdf_path\":\"/abs/book.pdf\",\"backend\":\"hash\"}"}' - -# Query: -curl -X POST http://localhost:7700/cartridge/librarian-mcp/invoke \ - -H 'Content-Type: application/json' \ - -d '{"tool":"librarian_query","args":"{\"collection\":\"book\",\"query\":\"...\",\"k\":5}"}' -``` - -The exact host route and port depend on the host's configuration; the envelope -shape is what the cartridge guarantees. - -## Configuration - -- `BOJ_LIBRARIAN_HOME` -- collections root on disk. Defaults to - `$HOME/.local/share/boj/librarian`. The Zig core never reads the environment - itself (when loaded as a shared library from a non-Zig host, `std.os.environ` - is unset); the host resolves this path and passes it to `librarian_init`. -- `BOJ_LIBRARIAN_READONLY` -- if set to any value, ingest and delete are - refused (reads remain available). - -## Uninstall - -Remove the cartridge directory from the tree; there is no host-side wiring to -reverse. diff --git a/cartridges/domains/knowledge/librarian-mcp/README.adoc b/cartridges/domains/knowledge/librarian-mcp/README.adoc new file mode 100644 index 00000000..f4ccda0a --- /dev/null +++ b/cartridges/domains/knowledge/librarian-mcp/README.adoc @@ -0,0 +1,88 @@ +== librarian-mcp + +A document RAG cartridge for BoJ. Hold books and long-form text on the +server and serve the most relevant passages to a model on demand. +Nothing about the retrieval needs to leave the machine: the index is a +persistent, ownable set of files on disk, and the brute-force cosine +search runs in the Zig core. + +=== What it does + +Given a document, the cartridge extracts its text, reflows it, splits it +into overlapping word-window chunks that remember which pages they span, +embeds each chunk, and stores the vectors alongside the chunk metadata. +A query is embedded the same way and matched against the stored vectors +by cosine similarity; the top passages are returned with their page +references and scores. + +=== Architecture + +Two layers, in the BoJ house pattern: + +* `+abi/Librarian/Protocol.idr+` proves the protocol’s safety +properties: query, listing, and info are read-only and never denied; +ingest and deletion are writes; no operation is both; and a collection +name is path-safe, so no traversal name is representable. +* `+ffi/+` is the deterministic Zig core: extraction, cleaning, +chunking, storage, and search. It makes no network calls; embeddings are +injected. The core is reached through the standard +`+boj_cartridge_invoke+` ABI (ADR-0006): the host marshals JSON to and +from the tools and supplies embeddings. Under the `+hash+` backend the +core computes offline vectors; under the `+hf+` backend the host +delegates to `+ml-mcp+`’s HuggingFace feature-extraction. + +==== Embedding backends + +* `+hash+`: a deterministic bag-of-hashed-words embedding computed in +the core. Offline, dependency-free, and stable across runs (so persisted +indices stay valid). Good for testing and for environments with no model +access. +* `+hf+`: real semantic vectors from a HuggingFace feature-extraction +model (default `+BAAI/bge-small-en-v1.5+`, 384 dimensions), obtained +through the `+ml-mcp+` cartridge. The bge query-instruction prefix is +applied to queries. + +A collection records the backend and model it was built with; query +embeddings must match the stored dimensionality or the query is +rejected. + +=== Storage + +Each collection is a directory under `+$BOJ_LIBRARIAN_HOME+` (default +`+$HOME/.local/share/boj/librarian//+`): + +* `+vectors.bin+` – a small header (magic, dim, count) then row-major +unit-norm f32 rows (host-endian; this is a local, ownable index). +* `+chunks.json+` – the chunk metadata: id, text, page span, source. +* `+meta.json+` – index parameters: dim, backend, model, chunk and page +counts. + +Writes are staged into a sibling directory and swapped into place, so a +reader never sees a half-written collection. + +=== Tools + +Reads (never denied): `+librarian_query+`, +`+librarian_list_collections+`, `+librarian_collection_info+`. + +Gated writes: `+librarian_ingest+`, `+librarian_delete_collection+`. +Writes are bounded by per-call limits (32 MiB per document, 100k chunks +per ingest) and an adapter switch. + +=== Page references + +Page numbers are the document’s PDF position, not the printed page +number; the printed numbers are offset by any front matter. Citations +therefore name the PDF page. + +=== Tests + +The Zig core is test-driven end to end: + +.... +cd ffi +zig build test # unit tests for every module +zig build integration # build-then-query over a synthetic corpus, plus a full + # round trip through the C ABI, all on the offline hash + # backend (no network) +.... diff --git a/cartridges/domains/knowledge/librarian-mcp/README.md b/cartridges/domains/knowledge/librarian-mcp/README.md deleted file mode 100644 index 04b57d06..00000000 --- a/cartridges/domains/knowledge/librarian-mcp/README.md +++ /dev/null @@ -1,82 +0,0 @@ - -# librarian-mcp - -A document RAG cartridge for BoJ. Hold books and long-form text on the server -and serve the most relevant passages to a model on demand. Nothing about the -retrieval needs to leave the machine: the index is a persistent, ownable set of -files on disk, and the brute-force cosine search runs in the Zig core. - -## What it does - -Given a document, the cartridge extracts its text, reflows it, splits it into -overlapping word-window chunks that remember which pages they span, embeds each -chunk, and stores the vectors alongside the chunk metadata. A query is embedded -the same way and matched against the stored vectors by cosine similarity; the -top passages are returned with their page references and scores. - -## Architecture - -Two layers, in the BoJ house pattern: - -- `abi/Librarian/Protocol.idr` proves the protocol's safety properties: query, - listing, and info are read-only and never denied; ingest and deletion are - writes; no operation is both; and a collection name is path-safe, so no - traversal name is representable. -- `ffi/` is the deterministic Zig core: extraction, cleaning, chunking, - storage, and search. It makes no network calls; embeddings are injected. The - core is reached through the standard `boj_cartridge_invoke` ABI (ADR-0006): - the host marshals JSON to and from the tools and supplies embeddings. Under - the `hash` backend the core computes offline vectors; under the `hf` backend - the host delegates to `ml-mcp`'s HuggingFace feature-extraction. - -### Embedding backends - -- `hash`: a deterministic bag-of-hashed-words embedding computed in the core. - Offline, dependency-free, and stable across runs (so persisted indices stay - valid). Good for testing and for environments with no model access. -- `hf`: real semantic vectors from a HuggingFace feature-extraction model - (default `BAAI/bge-small-en-v1.5`, 384 dimensions), obtained through the - `ml-mcp` cartridge. The bge query-instruction prefix is applied to queries. - -A collection records the backend and model it was built with; query embeddings -must match the stored dimensionality or the query is rejected. - -## Storage - -Each collection is a directory under `$BOJ_LIBRARIAN_HOME` (default -`$HOME/.local/share/boj/librarian//`): - -- `vectors.bin` -- a small header (magic, dim, count) then row-major unit-norm - f32 rows (host-endian; this is a local, ownable index). -- `chunks.json` -- the chunk metadata: id, text, page span, source. -- `meta.json` -- index parameters: dim, backend, model, chunk and page counts. - -Writes are staged into a sibling directory and swapped into place, so a reader -never sees a half-written collection. - -## Tools - -Reads (never denied): `librarian_query`, `librarian_list_collections`, -`librarian_collection_info`. - -Gated writes: `librarian_ingest`, `librarian_delete_collection`. Writes are -bounded by per-call limits (32 MiB per document, 100k chunks per ingest) and an -adapter switch. - -## Page references - -Page numbers are the document's PDF position, not the printed page number; the -printed numbers are offset by any front matter. Citations therefore name the -PDF page. - -## Tests - -The Zig core is test-driven end to end: - -``` -cd ffi -zig build test # unit tests for every module -zig build integration # build-then-query over a synthetic corpus, plus a full - # round trip through the C ABI, all on the offline hash - # backend (no network) -``` diff --git a/cartridges/domains/observability/observe-lsp/_source-archive/README.adoc b/cartridges/domains/observability/observe-lsp/_source-archive/README.adoc new file mode 100644 index 00000000..367ded4d --- /dev/null +++ b/cartridges/domains/observability/observe-lsp/_source-archive/README.adoc @@ -0,0 +1,115 @@ +== poly-observability-lsp + +____ +Language Server Protocol implementation for observability tools +(Prometheus, Grafana, Loki, Jaeger) +____ + +https://www.mozilla.org/en-US/MPL/2.0/[image:https://img.shields.io/badge/License-MPL--2.0-brightgreen.svg[License: +MPL-2.0]] +https://elixir-lang.org/[image:https://img.shields.io/badge/elixir-1.17+-purple.svg[Elixir +1.17+]] + +=== Overview + +*poly-observability-lsp* provides IDE integration for observability +tools across the cloud-native ecosystem. Built with Elixir’s BEAM VM, +each tool adapter runs as an isolated process with automatic fault +recovery. + +=== Supported Tools + +* *Prometheus* - Monitoring and alerting with PromQL query language +* *Grafana* - Observability dashboards and visualization +* *Loki* - Log aggregation with LogQL query language +* *Jaeger* - Distributed tracing for microservices + +=== Features + +* 🔄 *Auto-detection*: Detects observability tools from project files +* 🔍 *Query validation*: Validate PromQL and LogQL queries before +execution +* 📊 *Dashboard integration*: List and validate Grafana dashboards +* 🚨 *Alert monitoring*: Check alert status and configuration +* ⚡ *Commands*: Execute queries directly from editor +* 🛡️ *Fault isolation*: Crash in one adapter doesn’t affect others + +=== Installation + +[source,bash] +---- +git clone https://github.com/hyperpolymath/poly-observability-lsp +cd poly-observability-lsp +mix deps.get +mix compile +---- + +=== Required CLI Tools + +Each adapter requires its corresponding CLI tool to be installed: + +* *Prometheus*: `+promtool+` (from Prometheus installation) +* *Grafana*: `+grafana-cli+` (from Grafana installation) +* *Loki*: `+logcli+` (from Loki installation) +* *Jaeger*: `+jaeger-query+` (from Jaeger installation) + +=== Usage + +==== Start the LSP Server + +[source,bash] +---- +just start +---- + +==== VSCode Extension + +See `+vscode-extension/+` directory for the VSCode extension that uses +this LSP server. + +=== Configuration + +Each observability tool is detected based on its configuration files: + +[cols=",",options="header",] +|=== +|Tool |Config Files +|Prometheus |`+prometheus.yml+` +|Grafana |`+grafana.ini+`, `+grafana/+` directory +|Loki |`+loki.yaml+`, `+loki-config.yaml+` +|Jaeger |`+jaeger-config.yml+`, `+docker-compose.yml+` (with Jaeger) +|=== + +=== Architecture + +Each adapter implements the `+PolyObservability.Adapters.Behaviour+`: + +* `+detect/1+` - Detect if tool is present in project +* `+query_metrics/3+` - Query metrics (Prometheus) +* `+query_logs/3+` - Query logs (Loki) +* `+query_traces/3+` - Query traces (Jaeger) +* `+list_dashboards/1+` - List dashboards (Grafana) +* `+alert_status/1+` - Get alert status +* `+version/0+` - Get tool version +* `+metadata/0+` - Get tool metadata + +=== Development + +[source,bash] +---- +# Install dependencies +just deps + +# Run tests +just test + +# Run quality checks +just quality + +# Start REPL +just repl +---- + +=== License + +MPL-2.0 diff --git a/cartridges/domains/observability/observe-lsp/_source-archive/README.md b/cartridges/domains/observability/observe-lsp/_source-archive/README.md deleted file mode 100644 index ac38ab70..00000000 --- a/cartridges/domains/observability/observe-lsp/_source-archive/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# poly-observability-lsp - -> Language Server Protocol implementation for observability tools (Prometheus, Grafana, Loki, Jaeger) - -[![License: MPL-2.0](https://img.shields.io/badge/License-MPL--2.0-brightgreen.svg)](https://www.mozilla.org/en-US/MPL/2.0/) -[![Elixir 1.17+](https://img.shields.io/badge/elixir-1.17+-purple.svg)](https://elixir-lang.org/) - -## Overview - -**poly-observability-lsp** provides IDE integration for observability tools across the cloud-native ecosystem. Built with Elixir's BEAM VM, each tool adapter runs as an isolated process with automatic fault recovery. - -## Supported Tools - -- **Prometheus** - Monitoring and alerting with PromQL query language -- **Grafana** - Observability dashboards and visualization -- **Loki** - Log aggregation with LogQL query language -- **Jaeger** - Distributed tracing for microservices - -## Features - -- 🔄 **Auto-detection**: Detects observability tools from project files -- 🔍 **Query validation**: Validate PromQL and LogQL queries before execution -- 📊 **Dashboard integration**: List and validate Grafana dashboards -- 🚨 **Alert monitoring**: Check alert status and configuration -- ⚡ **Commands**: Execute queries directly from editor -- 🛡️ **Fault isolation**: Crash in one adapter doesn't affect others - -## Installation - -```bash -git clone https://github.com/hyperpolymath/poly-observability-lsp -cd poly-observability-lsp -mix deps.get -mix compile -``` - -## Required CLI Tools - -Each adapter requires its corresponding CLI tool to be installed: - -- **Prometheus**: `promtool` (from Prometheus installation) -- **Grafana**: `grafana-cli` (from Grafana installation) -- **Loki**: `logcli` (from Loki installation) -- **Jaeger**: `jaeger-query` (from Jaeger installation) - -## Usage - -### Start the LSP Server - -```bash -just start -``` - -### VSCode Extension - -See `vscode-extension/` directory for the VSCode extension that uses this LSP server. - -## Configuration - -Each observability tool is detected based on its configuration files: - -| Tool | Config Files | -|------|--------------| -| Prometheus | `prometheus.yml` | -| Grafana | `grafana.ini`, `grafana/` directory | -| Loki | `loki.yaml`, `loki-config.yaml` | -| Jaeger | `jaeger-config.yml`, `docker-compose.yml` (with Jaeger) | - -## Architecture - -Each adapter implements the `PolyObservability.Adapters.Behaviour`: - -- `detect/1` - Detect if tool is present in project -- `query_metrics/3` - Query metrics (Prometheus) -- `query_logs/3` - Query logs (Loki) -- `query_traces/3` - Query traces (Jaeger) -- `list_dashboards/1` - List dashboards (Grafana) -- `alert_status/1` - Get alert status -- `version/0` - Get tool version -- `metadata/0` - Get tool metadata - -## Development - -```bash -# Install dependencies -just deps - -# Run tests -just test - -# Run quality checks -just quality - -# Start REPL -just repl -``` - -## License - -MPL-2.0 diff --git a/cartridges/domains/web/ssg-lsp/_source-archive/README.adoc b/cartridges/domains/web/ssg-lsp/_source-archive/README.adoc new file mode 100644 index 00000000..a0de8a9f --- /dev/null +++ b/cartridges/domains/web/ssg-lsp/_source-archive/README.adoc @@ -0,0 +1,34 @@ +== poly-ssg-lsp + +____ +Language Server Protocol implementation for 60+ static site generators +____ + +https://www.mozilla.org/en-US/MPL/2.0/[image:https://img.shields.io/badge/License-MPL--2.0-brightgreen.svg[License: +MPL-2.0]] +https://elixir-lang.org/[image:https://img.shields.io/badge/elixir-1.17+-purple.svg[Elixir +1.17+]] + +=== Overview + +*poly-ssg-lsp* provides IDE integration for static site generators +across 60+ languages and frameworks. Built with Elixir’s BEAM VM, each +SSG adapter runs as an isolated process with automatic fault recovery. + +=== Features + +* 🔄 *Auto-detection*: Detects SSG type from project files +* ✨ *Auto-completion*: Template syntax, frontmatter, shortcodes +* 🔍 *Diagnostics*: Build errors, configuration issues +* 📚 *Hover docs*: SSG-specific documentation +* ⚡ *Commands*: Build, serve, clean directly from editor +* 🛡️ *Fault isolation*: Crash in one adapter doesn’t affect others + +=== Installation + +```bash git clone https://github.com/hyperpolymath/poly-ssg-lsp cd +poly-ssg-lsp mix deps.get mix compile ``` + +=== License + +MPL-2.0 diff --git a/cartridges/domains/web/ssg-lsp/_source-archive/README.md b/cartridges/domains/web/ssg-lsp/_source-archive/README.md deleted file mode 100644 index 476aa2f7..00000000 --- a/cartridges/domains/web/ssg-lsp/_source-archive/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# poly-ssg-lsp - -> Language Server Protocol implementation for 60+ static site generators - -[![License: MPL-2.0](https://img.shields.io/badge/License-MPL--2.0-brightgreen.svg)](https://www.mozilla.org/en-US/MPL/2.0/) -[![Elixir 1.17+](https://img.shields.io/badge/elixir-1.17+-purple.svg)](https://elixir-lang.org/) - -## Overview - -**poly-ssg-lsp** provides IDE integration for static site generators across 60+ languages and frameworks. Built with Elixir's BEAM VM, each SSG adapter runs as an isolated process with automatic fault recovery. - -## Features - -- 🔄 **Auto-detection**: Detects SSG type from project files -- ✨ **Auto-completion**: Template syntax, frontmatter, shortcodes -- 🔍 **Diagnostics**: Build errors, configuration issues -- 📚 **Hover docs**: SSG-specific documentation -- ⚡ **Commands**: Build, serve, clean directly from editor -- 🛡️ **Fault isolation**: Crash in one adapter doesn't affect others - -## Installation - -\`\`\`bash -git clone https://github.com/hyperpolymath/poly-ssg-lsp -cd poly-ssg-lsp -mix deps.get -mix compile -\`\`\` - -## License - -MPL-2.0 diff --git a/docs/echo-types-integration-audit-2026-06-01.adoc b/docs/echo-types-integration-audit-2026-06-01.adoc new file mode 100644 index 00000000..88660391 --- /dev/null +++ b/docs/echo-types-integration-audit-2026-06-01.adoc @@ -0,0 +1,376 @@ +== Echo-types integration audit — boj-server-cartridges + +*Date:* 2026-06-01 *Auditor:* parent session (cartridges-side +architectural audit) *Upstream under audit:* +`+hyperpolymath/echo-types+` (constructive Agda library at +`+/home/hyperpolymath/developer/repos/echo-types+`) *Standing obligation +discharged by this doc:* +`+feedback_proofs_must_check_and_cross_doc_echo_types+` (owner directive +2026-06-01). Every cartridges-side architectural decision must +explicitly check echo-types relevance, reuse if applicable, extend +upstream WITH proofs if not, and cross-document. This file is the +cartridges-side cross-doc artifact for the audit; the upstream +echo-types side already documents one cartridges consumer in +`+local-coord-mcp/abi/LocalCoord/PROOF-SCHEDULE.adoc+` (Phase 3 +obligations P-17 / P-18). + +=== TL;DR + +* *Schemas-as-data (Section A):* echo-types is *NOT load-bearing* for +the `+cartridge.json+` schema itself. The schema is a flat capability +manifest (name / domain / tier / protocols / tools / FFI), not a +residue/loss carrier. No structural-loss vocabulary belongs at that +layer. +* *Schemas-as-runtime-output (Section A, second half):* a small number +of cartridges produce _result-with-information-loss_ at runtime — +notably `+codeseeker-mcp+` (Reciprocal Rank Fusion hybrid search + +knowledge-graph rerank). For these, echo-types is *potentially +load-bearing in the future*, but only at the _proof_ layer (Section B), +not in the cartridge.json schema. +* *Proofs (Section B):* *NOT load-bearing today.* 112 Idris2 `+.idr+` +proofs exist under `+cartridges/**/abi/+`; all 112 are protocol-shape / +state-machine / safety-witness style. Exactly *one* cartridge — +`+cross-cutting/agentic/local-coord-mcp+` — has explicit echo-types +obligations (P-17 audit/summary/hash-chain, P-18 tropical TTL/trust), +both *deferred to Phase 3* by `+PROOF-SCHEDULE.adoc+`. No other +cartridge has surfaced an echo-types obligation in its design log. +* *Obligation status (Section C):* this audit *closes the cross-doc +obligation for boj-server-cartridges as of 2026-06-01.* Going forward, +new architectural docs / ADRs in this repo MUST include a one-line +"`Echo-types audit: `" footnote. +* *Concrete next actions (Section D):* zero blocking actions today. +Three watch items (Phase 3 local-coord, codeseeker-mcp RRF, +kategoria-mcp ranking) with documented trigger conditions. + +=== A. Echo-types as load-bearing for cartridge SCHEMAS + +==== A.1 The `+cartridge.json+` schema itself: NOT load-bearing + +The canonical cartridge schema is anchored at +`+https://boj.dev/schemas/cartridge/v1.json+` and is instantiated in 139 +manifests across this repo. Two representative samples: + +* `+cartridges/templates/gossamer-mcp/cartridge.json+` — fields: +`+name+`, `+version+`, `+description+`, `+domain+`, `+tier+`, +`+protocols+`, `+auth+`, `+api+`, `+tools+` (with `+inputSchema+`), +`+ffi+`. Pure capability advertisement. +* `+cartridges/cross-cutting/agentic/local-coord-mcp/cartridge.json+` — +same shape plus `+bind+` (loopback + port), `+federation: "none"+`. +Again pure capability advertisement; the only "`loss`" expressed at +schema level is `+federation: "none"+` (a policy choice, not a residue). + +Mapping echo-types vocabulary against this: + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|echo-types concept |applies to `+cartridge.json+`? |why / why not +|`+Echo f y := Σ A (λ x → f x ≡ y)+` |NO |A manifest is not the output +of an irreversible map — it IS the source declaration. + +|`+ResidueForm f R+` (Tier 2, eight instances) |NO |The schema carries +no residue field. Capability adverts ≠ residues. + +|`+LossTaxonomy+` (EQUIV/INJ/SURJ/CONST function-axis) |NO |Manifests +are not functions to be classified. + +|`+DecorationStructure+` (graded / linear / access lattices) |NO |Tiers +(Ayo/Aral/Aha/etc.) are administrative classifications, not residue +lattices. The mapping would be forced. + +|`+Provenance+` audience surface |borderline |A manifest does carry +author + version + SPDX, but that is build-time provenance handled by +SPDX-FileCopyrightText, NOT semantic-fibre provenance over an +irreversible computation. + +|`+Security+` audience surface |borderline |`+local-coord-mcp+` carries +`+loopback_only: true+`. That’s a region-exit-style claim, but it’s a +boolean policy, not a region-exit _audit_ with retained witness. +|=== + +*Verdict.* The cartridge.json schema lives below echo-types’ use cases. +Adding `+--echo:+` fields to manifests would be premature taxonomy. The +schema’s job is _exact preservation_ (validator-checked); echo-types +explicitly tells callers to "`use exact preservation when available`" +(`+README.md+` §"`Semantic Fibre Vocabulary`"): + +____ +They are not a replacement for ordinary type checking, ABI proofs, FFI +discipline, typed-wasm, structural-fit systems, or any boundary system +that can preserve exact guarantees. When exact preservation is +available, use it. +____ + +The cartridge schema falls under "`any boundary system that can preserve +exact guarantees`". + +==== A.2 Cartridge runtime OUTPUTS: potentially load-bearing for a small subset + +A different question is whether the _values cartridges return_ exhibit +structured loss. Surveying the 139 cartridges, the candidates are: + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|Cartridge |Runtime output shape |Echo-shaped? +|`+domains/development/codeseeker-mcp+` |Hybrid search via Reciprocal +Rank Fusion (vector + text + path) + knowledge-graph rerank |*YES, +latent.* RRF over heterogeneous rankers is exactly a non-injective +fusion: the fused order forgets which sub-ranker contributed each rank. +Echo language fits as +`+Echo fuse fused_score = Σ (vector_score, text_score, path_score) (fuse(...) ≡ fused_score)+`. +The residue is the per-ranker contribution. + +|`+domains/education/kategoria-mcp+` |Knowledge-domain ranking |*YES, +latent.* Same pattern: any rank-fusion produces a result with +constraint-on-source but not source-reconstruction. + +|`+domains/knowledge/librarian-mcp+` + `+obsidian-mcp+` + `+zotero-mcp+` +|Document retrieval |*YES, latent.* Retrieval-with-rank is the canonical +echo-types use case per `+EchoTropical+` (argmin / argmax witnesses). + +|`+domains/gaming/npc-mcp+` (Perception.idr) |NPC perception state +|*borderline.* Perception is a projection from world-state to +belief-state — formally an echo, practically not yet stated that way. + +|Everything else (118+) |Either state-machine transitions (idempotent), +CRUD on external resources (exact), or message-passing (typed) |NO +|=== + +For the YES-latent cartridges, the echo-types relevance is *at the proof +level*, not at the cartridge.json level. None of them currently declare +a proof obligation against echo-types; see Section B. + +=== B. Echo-types as load-bearing for cartridge PROOFS + +==== B.1 Enumeration of `+.idr+` proofs under `+cartridges/**/abi/+` + +Running +`+find /home/hyperpolymath/developer/repos/boj-server-cartridges/cartridges -name "*.idr" -path "*/abi/*"+` +returns *112 files*. (Total `+.idr+` under `+cartridges/+` including +non-abi paths: 112 — every `+.idr+` lives under an `+abi/+` directory; +there are no top-level idr files.) + +Sampling the shapes: + +* Most cartridges ship a `+Protocol.idr+` or `+Safe*.idr+` defining: +** an enum of states (e.g. `+IndexState+` in +`+codeseeker-mcp/abi/CodeseekerMcp/SearchGraph.idr+` — +`+Uninitialised | Indexing | Ready | Querying | IndexError+`), +** a `+ValidTransition+` GADT enumerating allowed state edges, +** a runtime predicate (`+canIndexTransition+`), +** a `+%default total+` discipline. +* `+local-coord-mcp/abi/LocalCoord/SafeLocalCoord.idr+` is the canonical +template: loopback-bind witnesses, port-range witnesses, session-token +non-emptiness, federation-policy uninhabitedness. +* `+ephapax-mcp/abi/Ephapax.idr+`, +`+typed-wasm-mcp/abi/TypedWasm/Protocol.idr+`, +`+affinescript-mcp/abi/AffinescriptMcp/SafeCompiler.idr+` — +language-tool wrappers; protocol-shape only. + +*None of the 112 proofs use echo-types vocabulary directly.* None +imports `+Echo+`, `+EchoResidue+`, `+EchoTropical+`, +`+EchoLossTaxonomy+`, or any other echo-types module. (Mechanically +expected: Idris2 cannot import Agda modules anyway; the integration +would be at the design / specification level, with parallel sibling +proofs.) + +==== B.2 The single explicit echo-types touch-point: `+local-coord-mcp+` + +`+cartridges/cross-cutting/agentic/local-coord-mcp/abi/LocalCoord/PROOF-SCHEDULE.adoc+` +is the only cartridges-side document that names echo-types. Relevant +entries from the schedule table: + +[width="100%",cols="25%,25%,25%,25%",options="header",] +|=== +|# |Obligation |Status |Prover +|P-17 |Echo-type formalisation of audit + summary + hash chain |*Phase 3 +(deferred)* |Agda (echo-types repo) + +|P-18 |Tropical-semiring model of TTL + trust |*Phase 3 (deferred)* +|Agda (EchoTropical) +|=== + +The schedule’s prose §"`Notes on prover choice`" explicitly frames the +boundary: + +____ +Agda enters only for Phase 3 echo-type + tropical work, consuming the +`+echo-types/+` bridge library. *No echo-type obligation lives inside +the cartridge repo — it lands upstream in `+echo-types/+` with coord as +the dogfood consumer.* +____ + +This is the correct discipline. The cartridge ships Idris2 +protocol-shape proofs (P-04 through P-13 are P0/P1/P2 in Phase 1); the +echo-type work (P-17 / P-18) lives upstream in echo-types and the +cartridge consumes it as a dogfood case study. Phase 3 is gated on Phase +2 (P-15 choreographic types, P-16 epistemic types) which are themselves +deferred. + +==== B.3 Other cartridges with echo-shaped runtime output but no echo-types + +obligation yet + +Cross-referencing Section A.2’s YES-latent list against B.1’s proof +inventory: + +* `+codeseeker-mcp/abi/CodeseekerMcp/SearchGraph.idr+` — proves +state-machine validity for index lifecycle. Does NOT prove anything +about the Reciprocal Rank Fusion semantics. *Could* benefit from an +echo-types-side parallel proof (`+Echo fuse fused_score+`) — see D.2. +* `+kategoria-mcp/abi/Kategoria/Protocol.idr+` — protocol shape only. +* `+librarian-mcp+` / `+obsidian-mcp+` / `+zotero-mcp+` — +protocol/registry shape only; retrieval semantics not proved. +* `+npc-mcp/abi/NpcMcp/Perception.idr+` — perception state-machine; the +"`world-state to belief-state`" projection is implicit, not type-level. + +None of these has filed a proof obligation against echo-types. None has +a PROOF-SCHEDULE.adoc equivalent. The cartridges-side rule remains: +echo-type obligations land upstream in `+hyperpolymath/echo-types+` with +the cartridge as dogfood consumer — they do NOT land in this repo. + +==== B.4 Why parallel siblings (not direct integration) + +Mechanically: Idris2 and Agda do not share a proof kernel. The +integration shape recommended by the local-coord PROOF-SCHEDULE is: + +[arabic] +. Cartridge-side: Idris2 proves the protocol shape (states, transitions, +invariants on FFI boundaries). +. Upstream echo-types: Agda proves the echo-type semantics of the lossy +runtime operation (audit, summary, hash chain, rank fusion). +. Cross-doc reference: the cartridge’s PROOF-SCHEDULE names the upstream +echo-types theorem; the upstream `+cross-repo-bridge-status.md+` (in +echo-types) names the cartridge as a consumer. + +The upstream echo-types `+cross-repo-bridge-status.md+` is the canonical +ledger for parallel-sibling pairings. As of 2026-06-01 that ledger does +NOT yet list `+local-coord-mcp+` (because P-17/P-18 are Phase 3 deferred +and no Agda proof has been written upstream); when Phase 3 opens, the +forward-link should be added at both ends. + +=== C. Cross-doc obligation status for boj-server-cartridges + +==== C.1 Closure as of 2026-06-01 + +The standing obligation from +`+feedback_proofs_must_check_and_cross_doc_echo_types+` (owner directive +2026-06-01) is satisfied for boj-server-cartridges by this audit, on the +following grounds: + +* *L1 / L4 audit completeness.* The cartridge schema is L1 (capability +manifest) + L4 (FFI / wire format) only. L1/L4-only obligations +"`audit-and-record-as-not-relevant`" per the directive; this file is +that record. +* *L3 (echo) audit completeness.* Exactly one cartridge +(`+local-coord-mcp+`) has an L3 echo touch-point. That touch-point is +already cross-documented at +`+local-coord-mcp/abi/LocalCoord/PROOF-SCHEDULE.adoc+` P-17 + P-18, with +the upstream-as-source-of-truth discipline already spelled out. This +audit confirms that documentation is still correct and does not need +amendment as of 2026-06-01. +* *Forward-going hook.* All new architectural docs / ADRs in this repo +MUST include a one-line "`Echo-types audit: `" footnote going forward; +see C.2 for the recommended footnote forms. + +==== C.2 Mandatory footnote for future ADRs / architecture docs + +Every new doc under +`+/home/hyperpolymath/developer/repos/boj-server-cartridges/docs/decisions/+` +(ADRs) and every new architectural note in `+docs/handover/+` MUST close +with one of these three forms: + +* *`+Echo-types audit: not relevant (L1/L4 only).+`* — for ADRs about +schema fields, FFI / wire format, cartridge taxonomy, or build/CI. This +is the expected default for ~95% of cartridges-side ADRs. +* *`+Echo-types audit: defer to upstream .+`* — when the +cartridge has an L3-echo touch-point that should be proved upstream in +echo-types. Cite the upstream module by name (e.g. `+EchoTropical+`, +`+EchoProvenance+`). +* *`+Echo-types audit: in this doc, see §
.+`* — when the ADR +itself imports echo-types vocabulary structurally. Reserved for future +ADRs that explicitly model rank-fusion / lossy summarisation; expected +to be rare. + +The existing two ADRs (`+ADR-001-taxonomy.adoc+`, +`+ADR-002-stack-orchestrator-vs-fleet-mcp.adoc+`) predate this directive +and are NOT required to be amended; they fall under "`L1/L4 only, not +relevant`". + +=== D. Concrete next actions + +==== D.1 Today: zero blocking actions + +No cartridges-side proof, schema, or doc needs to change today. The +audit trail is: + +* `+cartridge.json+` schema — no echo-types vocabulary needed. +* 111 of 112 `+.idr+` proofs — protocol-shape only, no echo-types +obligation. +* 1 of 112 `+.idr+` proofs (local-coord-mcp) — already documents Phase 3 +echo-types obligations as deferred-upstream; no amendment needed. + +==== D.2 Watch items with documented trigger conditions + +* *Watch item 1: local-coord-mcp Phase 3 unlock.* When Phase 2 (P-15 +choreographic types + P-16 epistemic types) lands upstream in echo-types +or in the cartridge’s own Idris2 layer, Phase 3 P-17 + P-18 unlock. At +that moment, an upstream-echo-types-side sibling proof needs to be +written (Agda; consumes `+EchoChoreo+`, `+EchoEpistemic+`, +`+EchoTropical+`), and a forward-link added to +`+echo-types/docs/echo-types/cross-repo-bridge-status.md+`. The +cartridges-side `+PROOF-SCHEDULE.adoc+` should gain a "`LANDED upstream +YYYY-MM-DD`" stamp on P-17 / P-18. +* *Watch item 2: codeseeker-mcp RRF fusion semantics.* If at any future +point a downstream consumer asks for a semantic guarantee on RRF fused +rankings (e.g. "`the top-k under fusion is constrained by the union of +per-ranker top-k under the following bound`"), the natural home is an +upstream-echo-types proof along the lines of `+EchoTropical+`’s +argmin-with-residue. Trigger condition: someone files an issue against +`+codeseeker-mcp+` asking "`what does RRF guarantee?`" Cartridges-side +action: do NOT prove this in `+SearchGraph.idr+`; file an upstream issue +against `+hyperpolymath/echo-types+` for an `+EchoRankFusion+` module + +cite it back. +* *Watch item 3: kategoria-mcp / librarian-mcp ranking semantics.* Same +pattern as Watch item 2; same trigger condition; same cartridges-side +action (defer upstream). The four retrieval cartridges (codeseeker, +kategoria, librarian, obsidian, zotero) collectively motivate a single +upstream `+EchoRankFusion+` module rather than five per-cartridge +proofs. + +==== D.3 Trigger conditions for re-audit of this document + +This audit becomes stale and should be re-run when any of: + +[arabic] +. The cartridge.json schema gains a residue / loss / echo / fibre field +at the top level. (Not expected.) +. A new cartridge enters the repo whose primary value is rank-fusion, +summarisation, or sampling, AND it ships a proof obligation. (Watch +items 2 and 3 cover the existing latent cases; a NEW cartridge with +active proofs would be a different trigger.) +. Upstream echo-types ships `+EchoRankFusion+` (or equivalent). At that +point the four retrieval cartridges become eligible consumers and a +refresh of this audit should add forward-links. +. The standing obligation +`+feedback_proofs_must_check_and_cross_doc_echo_types+` is amended or +superseded. + +No calendar trigger. This is event-driven. + +=== E. References + +* Upstream echo-types README: +`+/home/hyperpolymath/developer/repos/echo-types/README.md+` +* Upstream echo-types EXPLAINME: +`+/home/hyperpolymath/developer/repos/echo-types/EXPLAINME.adoc+` +* Upstream echo-types CLAUDE.md (ecosystem context + +canonical-identity-suite status as of 2026-05-27): +`+/home/hyperpolymath/developer/repos/echo-types/CLAUDE.md+` +* Cartridges-side echo-types reference: +`+/home/hyperpolymath/developer/repos/boj-server-cartridges/cartridges/cross-cutting/agentic/local-coord-mcp/abi/LocalCoord/PROOF-SCHEDULE.adoc+` +* Standing obligation in memory: +`+~/.claude/projects/-home-hyperpolymath-developer-repos/memory/feedback_proofs_must_check_and_cross_doc_echo_types.md+` + +''''' + +*Echo-types audit: closed (this is the cross-doc artifact).* diff --git a/docs/echo-types-integration-audit-2026-06-01.md b/docs/echo-types-integration-audit-2026-06-01.md deleted file mode 100644 index c9996a69..00000000 --- a/docs/echo-types-integration-audit-2026-06-01.md +++ /dev/null @@ -1,320 +0,0 @@ - - -# Echo-types integration audit — boj-server-cartridges - -**Date:** 2026-06-01 -**Auditor:** parent session (cartridges-side architectural audit) -**Upstream under audit:** `hyperpolymath/echo-types` (constructive Agda library at `/home/hyperpolymath/developer/repos/echo-types`) -**Standing obligation discharged by this doc:** -`feedback_proofs_must_check_and_cross_doc_echo_types` (owner directive 2026-06-01). -Every cartridges-side architectural decision must explicitly check echo-types -relevance, reuse if applicable, extend upstream WITH proofs if not, and -cross-document. This file is the cartridges-side cross-doc artifact for the -audit; the upstream echo-types side already documents one cartridges -consumer in `local-coord-mcp/abi/LocalCoord/PROOF-SCHEDULE.adoc` (Phase 3 -obligations P-17 / P-18). - -## TL;DR - -* **Schemas-as-data (Section A):** echo-types is **NOT load-bearing** for the - `cartridge.json` schema itself. The schema is a flat capability manifest - (name / domain / tier / protocols / tools / FFI), not a residue/loss - carrier. No structural-loss vocabulary belongs at that layer. -* **Schemas-as-runtime-output (Section A, second half):** a small number of - cartridges produce *result-with-information-loss* at runtime — - notably `codeseeker-mcp` (Reciprocal Rank Fusion hybrid search + - knowledge-graph rerank). For these, echo-types is **potentially - load-bearing in the future**, but only at the *proof* layer (Section B), - not in the cartridge.json schema. -* **Proofs (Section B):** **NOT load-bearing today.** 112 Idris2 `.idr` proofs - exist under `cartridges/**/abi/`; all 112 are protocol-shape / state-machine - / safety-witness style. Exactly **one** cartridge — - `cross-cutting/agentic/local-coord-mcp` — has explicit echo-types - obligations (P-17 audit/summary/hash-chain, P-18 tropical TTL/trust), - both **deferred to Phase 3** by `PROOF-SCHEDULE.adoc`. No other cartridge - has surfaced an echo-types obligation in its design log. -* **Obligation status (Section C):** this audit **closes the - cross-doc obligation for boj-server-cartridges as of 2026-06-01.** Going - forward, new architectural docs / ADRs in this repo MUST include a - one-line "Echo-types audit: " footnote. -* **Concrete next actions (Section D):** zero blocking actions today. Three - watch items (Phase 3 local-coord, codeseeker-mcp RRF, kategoria-mcp - ranking) with documented trigger conditions. - -## A. Echo-types as load-bearing for cartridge SCHEMAS - -### A.1 The `cartridge.json` schema itself: NOT load-bearing - -The canonical cartridge schema is anchored at `https://boj.dev/schemas/cartridge/v1.json` -and is instantiated in 139 manifests across this repo. Two representative -samples: - -* `cartridges/templates/gossamer-mcp/cartridge.json` — fields: `name`, - `version`, `description`, `domain`, `tier`, `protocols`, `auth`, `api`, - `tools` (with `inputSchema`), `ffi`. Pure capability advertisement. -* `cartridges/cross-cutting/agentic/local-coord-mcp/cartridge.json` — - same shape plus `bind` (loopback + port), `federation: "none"`. Again - pure capability advertisement; the only "loss" expressed at schema - level is `federation: "none"` (a policy choice, not a residue). - -Mapping echo-types vocabulary against this: - -| echo-types concept | applies to `cartridge.json`? | why / why not | -|---|---|---| -| `Echo f y := Σ A (λ x → f x ≡ y)` | NO | A manifest is not the output of an irreversible map — it IS the source declaration. | -| `ResidueForm f R` (Tier 2, eight instances) | NO | The schema carries no residue field. Capability adverts ≠ residues. | -| `LossTaxonomy` (EQUIV/INJ/SURJ/CONST function-axis) | NO | Manifests are not functions to be classified. | -| `DecorationStructure` (graded / linear / access lattices) | NO | Tiers (Ayo/Aral/Aha/etc.) are administrative classifications, not residue lattices. The mapping would be forced. | -| `Provenance` audience surface | borderline | A manifest does carry author + version + SPDX, but that is build-time provenance handled by SPDX-FileCopyrightText, NOT semantic-fibre provenance over an irreversible computation. | -| `Security` audience surface | borderline | `local-coord-mcp` carries `loopback_only: true`. That's a region-exit-style claim, but it's a boolean policy, not a region-exit *audit* with retained witness. | - -**Verdict.** The cartridge.json schema lives below echo-types' use cases. -Adding `--echo:` fields to manifests would be premature taxonomy. The -schema's job is *exact preservation* (validator-checked); echo-types -explicitly tells callers to "use exact preservation when available" -(`README.md` §"Semantic Fibre Vocabulary"): - -> They are not a replacement for ordinary type checking, ABI proofs, FFI -> discipline, typed-wasm, structural-fit systems, or any boundary system -> that can preserve exact guarantees. When exact preservation is -> available, use it. - -The cartridge schema falls under "any boundary system that can preserve -exact guarantees". - -### A.2 Cartridge runtime OUTPUTS: potentially load-bearing for a small subset - -A different question is whether the *values cartridges return* exhibit -structured loss. Surveying the 139 cartridges, the candidates are: - -| Cartridge | Runtime output shape | Echo-shaped? | -|---|---|---| -| `domains/development/codeseeker-mcp` | Hybrid search via Reciprocal Rank Fusion (vector + text + path) + knowledge-graph rerank | **YES, latent.** RRF over heterogeneous rankers is exactly a non-injective fusion: the fused order forgets which sub-ranker contributed each rank. Echo language fits as `Echo fuse fused_score = Σ (vector_score, text_score, path_score) (fuse(...) ≡ fused_score)`. The residue is the per-ranker contribution. | -| `domains/education/kategoria-mcp` | Knowledge-domain ranking | **YES, latent.** Same pattern: any rank-fusion produces a result with constraint-on-source but not source-reconstruction. | -| `domains/knowledge/librarian-mcp` + `obsidian-mcp` + `zotero-mcp` | Document retrieval | **YES, latent.** Retrieval-with-rank is the canonical echo-types use case per `EchoTropical` (argmin / argmax witnesses). | -| `domains/gaming/npc-mcp` (Perception.idr) | NPC perception state | **borderline.** Perception is a projection from world-state to belief-state — formally an echo, practically not yet stated that way. | -| Everything else (118+) | Either state-machine transitions (idempotent), CRUD on external resources (exact), or message-passing (typed) | NO | - -For the YES-latent cartridges, the echo-types relevance is **at the proof -level**, not at the cartridge.json level. None of them currently declare a -proof obligation against echo-types; see Section B. - -## B. Echo-types as load-bearing for cartridge PROOFS - -### B.1 Enumeration of `.idr` proofs under `cartridges/**/abi/` - -Running `find /home/hyperpolymath/developer/repos/boj-server-cartridges/cartridges -name "*.idr" -path "*/abi/*"` returns **112 files**. (Total `.idr` -under `cartridges/` including non-abi paths: 112 — every `.idr` lives under -an `abi/` directory; there are no top-level idr files.) - -Sampling the shapes: - -* Most cartridges ship a `Protocol.idr` or `Safe*.idr` defining: - * an enum of states (e.g. `IndexState` in - `codeseeker-mcp/abi/CodeseekerMcp/SearchGraph.idr` — - `Uninitialised | Indexing | Ready | Querying | IndexError`), - * a `ValidTransition` GADT enumerating allowed state edges, - * a runtime predicate (`canIndexTransition`), - * a `%default total` discipline. -* `local-coord-mcp/abi/LocalCoord/SafeLocalCoord.idr` is the canonical - template: loopback-bind witnesses, port-range witnesses, session-token - non-emptiness, federation-policy uninhabitedness. -* `ephapax-mcp/abi/Ephapax.idr`, `typed-wasm-mcp/abi/TypedWasm/Protocol.idr`, - `affinescript-mcp/abi/AffinescriptMcp/SafeCompiler.idr` — - language-tool wrappers; protocol-shape only. - -**None of the 112 proofs use echo-types vocabulary directly.** None imports -`Echo`, `EchoResidue`, `EchoTropical`, `EchoLossTaxonomy`, or any other -echo-types module. (Mechanically expected: Idris2 cannot import Agda -modules anyway; the integration would be at the design / specification -level, with parallel sibling proofs.) - -### B.2 The single explicit echo-types touch-point: `local-coord-mcp` - -`cartridges/cross-cutting/agentic/local-coord-mcp/abi/LocalCoord/PROOF-SCHEDULE.adoc` -is the only cartridges-side document that names echo-types. Relevant -entries from the schedule table: - -| # | Obligation | Status | Prover | -|---|---|---|---| -| P-17 | Echo-type formalisation of audit + summary + hash chain | **Phase 3 (deferred)** | Agda (echo-types repo) | -| P-18 | Tropical-semiring model of TTL + trust | **Phase 3 (deferred)** | Agda (EchoTropical) | - -The schedule's prose §"Notes on prover choice" explicitly frames the -boundary: - -> Agda enters only for Phase 3 echo-type + tropical work, consuming the -> `echo-types/` bridge library. **No echo-type obligation lives inside the -> cartridge repo — it lands upstream in `echo-types/` with coord as the -> dogfood consumer.** - -This is the correct discipline. The cartridge ships Idris2 protocol-shape -proofs (P-04 through P-13 are P0/P1/P2 in Phase 1); the echo-type work -(P-17 / P-18) lives upstream in echo-types and the cartridge consumes it -as a dogfood case study. Phase 3 is gated on Phase 2 (P-15 choreographic -types, P-16 epistemic types) which are themselves deferred. - -### B.3 Other cartridges with echo-shaped runtime output but no echo-types -obligation yet - -Cross-referencing Section A.2's YES-latent list against B.1's proof -inventory: - -* `codeseeker-mcp/abi/CodeseekerMcp/SearchGraph.idr` — proves state-machine - validity for index lifecycle. Does NOT prove anything about the - Reciprocal Rank Fusion semantics. **Could** benefit from an - echo-types-side parallel proof (`Echo fuse fused_score`) — see D.2. -* `kategoria-mcp/abi/Kategoria/Protocol.idr` — protocol shape only. -* `librarian-mcp` / `obsidian-mcp` / `zotero-mcp` — protocol/registry - shape only; retrieval semantics not proved. -* `npc-mcp/abi/NpcMcp/Perception.idr` — perception state-machine; the - "world-state to belief-state" projection is implicit, not type-level. - -None of these has filed a proof obligation against echo-types. None has a -PROOF-SCHEDULE.adoc equivalent. The cartridges-side rule remains: -echo-type obligations land upstream in `hyperpolymath/echo-types` with -the cartridge as dogfood consumer — they do NOT land in this repo. - -### B.4 Why parallel siblings (not direct integration) - -Mechanically: Idris2 and Agda do not share a proof kernel. The integration -shape recommended by the local-coord PROOF-SCHEDULE is: - -1. Cartridge-side: Idris2 proves the protocol shape (states, transitions, - invariants on FFI boundaries). -2. Upstream echo-types: Agda proves the echo-type semantics of the lossy - runtime operation (audit, summary, hash chain, rank fusion). -3. Cross-doc reference: the cartridge's PROOF-SCHEDULE names the upstream - echo-types theorem; the upstream `cross-repo-bridge-status.md` (in - echo-types) names the cartridge as a consumer. - -The upstream echo-types `cross-repo-bridge-status.md` is the canonical -ledger for parallel-sibling pairings. As of 2026-06-01 that ledger does -NOT yet list `local-coord-mcp` (because P-17/P-18 are Phase 3 deferred and -no Agda proof has been written upstream); when Phase 3 opens, the -forward-link should be added at both ends. - -## C. Cross-doc obligation status for boj-server-cartridges - -### C.1 Closure as of 2026-06-01 - -The standing obligation from `feedback_proofs_must_check_and_cross_doc_echo_types` -(owner directive 2026-06-01) is satisfied for boj-server-cartridges by -this audit, on the following grounds: - -* **L1 / L4 audit completeness.** The cartridge schema is L1 (capability - manifest) + L4 (FFI / wire format) only. L1/L4-only obligations - "audit-and-record-as-not-relevant" per the directive; this file is - that record. -* **L3 (echo) audit completeness.** Exactly one cartridge - (`local-coord-mcp`) has an L3 echo touch-point. That touch-point is - already cross-documented at `local-coord-mcp/abi/LocalCoord/PROOF-SCHEDULE.adoc` - P-17 + P-18, with the upstream-as-source-of-truth discipline already - spelled out. This audit confirms that documentation is still correct - and does not need amendment as of 2026-06-01. -* **Forward-going hook.** All new architectural docs / ADRs in this repo - MUST include a one-line "Echo-types audit: " footnote going - forward; see C.2 for the recommended footnote forms. - -### C.2 Mandatory footnote for future ADRs / architecture docs - -Every new doc under `/home/hyperpolymath/developer/repos/boj-server-cartridges/docs/decisions/` -(ADRs) and every new architectural note in `docs/handover/` MUST close with -one of these three forms: - -* **`Echo-types audit: not relevant (L1/L4 only).`** — for ADRs about - schema fields, FFI / wire format, cartridge taxonomy, or build/CI. - This is the expected default for ~95% of cartridges-side ADRs. -* **`Echo-types audit: defer to upstream .`** — when the cartridge - has an L3-echo touch-point that should be proved upstream in - echo-types. Cite the upstream module by name (e.g. `EchoTropical`, - `EchoProvenance`). -* **`Echo-types audit: in this doc, see §
.`** — when the ADR - itself imports echo-types vocabulary structurally. Reserved for - future ADRs that explicitly model rank-fusion / lossy summarisation; - expected to be rare. - -The existing two ADRs (`ADR-001-taxonomy.adoc`, -`ADR-002-stack-orchestrator-vs-fleet-mcp.adoc`) predate this directive -and are NOT required to be amended; they fall under "L1/L4 only, -not relevant". - -## D. Concrete next actions - -### D.1 Today: zero blocking actions - -No cartridges-side proof, schema, or doc needs to change today. The audit -trail is: - -* `cartridge.json` schema — no echo-types vocabulary needed. -* 111 of 112 `.idr` proofs — protocol-shape only, no echo-types - obligation. -* 1 of 112 `.idr` proofs (local-coord-mcp) — already documents Phase 3 - echo-types obligations as deferred-upstream; no amendment needed. - -### D.2 Watch items with documented trigger conditions - -* **Watch item 1: local-coord-mcp Phase 3 unlock.** When Phase 2 - (P-15 choreographic types + P-16 epistemic types) lands upstream in - echo-types or in the cartridge's own Idris2 layer, Phase 3 P-17 + - P-18 unlock. At that moment, an upstream-echo-types-side sibling proof - needs to be written (Agda; consumes `EchoChoreo`, `EchoEpistemic`, - `EchoTropical`), and a forward-link added to - `echo-types/docs/echo-types/cross-repo-bridge-status.md`. The - cartridges-side `PROOF-SCHEDULE.adoc` should gain a "LANDED upstream - YYYY-MM-DD" stamp on P-17 / P-18. -* **Watch item 2: codeseeker-mcp RRF fusion semantics.** If at any - future point a downstream consumer asks for a semantic guarantee on - RRF fused rankings (e.g. "the top-k under fusion is constrained by - the union of per-ranker top-k under the following bound"), the - natural home is an upstream-echo-types proof along the lines of - `EchoTropical`'s argmin-with-residue. Trigger condition: someone files - an issue against `codeseeker-mcp` asking "what does RRF guarantee?" - Cartridges-side action: do NOT prove this in - `SearchGraph.idr`; file an upstream issue against `hyperpolymath/echo-types` - for an `EchoRankFusion` module + cite it back. -* **Watch item 3: kategoria-mcp / librarian-mcp ranking semantics.** - Same pattern as Watch item 2; same trigger condition; same - cartridges-side action (defer upstream). The four retrieval cartridges - (codeseeker, kategoria, librarian, obsidian, zotero) collectively - motivate a single upstream `EchoRankFusion` module rather than five - per-cartridge proofs. - -### D.3 Trigger conditions for re-audit of this document - -This audit becomes stale and should be re-run when any of: - -1. The cartridge.json schema gains a residue / loss / echo / fibre field - at the top level. (Not expected.) -2. A new cartridge enters the repo whose primary value is rank-fusion, - summarisation, or sampling, AND it ships a proof obligation. (Watch - items 2 and 3 cover the existing latent cases; a NEW cartridge with - active proofs would be a different trigger.) -3. Upstream echo-types ships `EchoRankFusion` (or equivalent). At that - point the four retrieval cartridges become eligible consumers and a - refresh of this audit should add forward-links. -4. The standing obligation - `feedback_proofs_must_check_and_cross_doc_echo_types` is amended or - superseded. - -No calendar trigger. This is event-driven. - -## E. References - -* Upstream echo-types README: - `/home/hyperpolymath/developer/repos/echo-types/README.md` -* Upstream echo-types EXPLAINME: - `/home/hyperpolymath/developer/repos/echo-types/EXPLAINME.adoc` -* Upstream echo-types CLAUDE.md (ecosystem context + canonical-identity-suite - status as of 2026-05-27): `/home/hyperpolymath/developer/repos/echo-types/CLAUDE.md` -* Cartridges-side echo-types reference: - `/home/hyperpolymath/developer/repos/boj-server-cartridges/cartridges/cross-cutting/agentic/local-coord-mcp/abi/LocalCoord/PROOF-SCHEDULE.adoc` -* Standing obligation in memory: - `~/.claude/projects/-home-hyperpolymath-developer-repos/memory/feedback_proofs_must_check_and_cross_doc_echo_types.md` - ---- - -**Echo-types audit: closed (this is the cross-doc artifact).** diff --git a/schemas/SCHEMA-MIRROR.adoc b/schemas/SCHEMA-MIRROR.adoc new file mode 100644 index 00000000..6600e141 --- /dev/null +++ b/schemas/SCHEMA-MIRROR.adoc @@ -0,0 +1,50 @@ +== Cartridge schema mirror + +The file `+cartridge-v1.json+` in this directory is a *SHA-pinned +mirror* of the canonical schema living at: + +* *Canonical home:* +https://github.com/hyperpolymath/standards/blob/main/cartridges/cartridge-v1.json[`+hyperpolymath/standards+`] +* *Canonical URL:* +`+https://hyperpolymath.dev/standards/cartridges/cartridge-v1.json+` +* *Pinned commit:* `+f5f0506a6ec88e574753eee701a268e0d4b3a7f2+` (set +2026-07-01 via hyperpolymath/standards#373; tracked via PINNED-SHA) +* *Pinned SHA-256 of file:* +`+7d03f79f9c881784eba21670ac86130371d02f54483b373c8673587c49ab8d08+` +(recorded in PINNED-SHA; enforced by +`+.github/workflows/cartridge-schema.yml+`) + +=== Why mirror + +Two reasons: + +[arabic] +. *Offline validation.* Hosts (boj-server, panll) and cartridge authors +need to validate `+cartridge.json+` without round-tripping to a network +resource. +. *Reproducibility.* A given snapshot of this repository must validate +against a deterministic schema version, so CI / fetchers must read the +bundled copy, not the canonical URL. + +=== Refresh discipline + +When the canonical schema in `+hyperpolymath/standards+` advances: + +[arabic] +. Open a PR here that updates `+cartridge-v1.json+` to the new content. +. Update `+PINNED-SHA+` with the new commit SHA in standards and the new +SHA-256 of the file. +. The PR’s description references the standards PR/commit that +introduced the change. +. Auto-merge once CI validates that *every* cartridge manifest still +parses against the new schema — `+just validate+`, which must report 0 +failing. (The count is currently 142; it was 125 when this page was +written. Read it from the validator rather than quoting a number here, +so this line cannot go stale again.) + +=== What if they disagree? + +Standards wins. Local mirror is always advancing toward standards. +Cartridges authored against an older mirror remain valid as long as the +schema change is backwards-compatible (the canonical schema is +versioned; breaking changes ship as `+cartridge-v2.json+`). diff --git a/schemas/SCHEMA-MIRROR.md b/schemas/SCHEMA-MIRROR.md deleted file mode 100644 index e309be15..00000000 --- a/schemas/SCHEMA-MIRROR.md +++ /dev/null @@ -1,31 +0,0 @@ - - - -# Cartridge schema mirror - -The file `cartridge-v1.json` in this directory is a **SHA-pinned mirror** of the canonical schema living at: - -- **Canonical home:** [`hyperpolymath/standards`](https://github.com/hyperpolymath/standards/blob/main/cartridges/cartridge-v1.json) -- **Canonical URL:** `https://hyperpolymath.dev/standards/cartridges/cartridge-v1.json` -- **Pinned commit:** `f5f0506a6ec88e574753eee701a268e0d4b3a7f2` (set 2026-07-01 via hyperpolymath/standards#373; tracked via [PINNED-SHA](PINNED-SHA)) -- **Pinned SHA-256 of file:** `7d03f79f9c881784eba21670ac86130371d02f54483b373c8673587c49ab8d08` (recorded in [PINNED-SHA](PINNED-SHA); enforced by `.github/workflows/cartridge-schema.yml`) - -## Why mirror - -Two reasons: - -1. **Offline validation.** Hosts (boj-server, panll) and cartridge authors need to validate `cartridge.json` without round-tripping to a network resource. -2. **Reproducibility.** A given snapshot of this repository must validate against a deterministic schema version, so CI / fetchers must read the bundled copy, not the canonical URL. - -## Refresh discipline - -When the canonical schema in `hyperpolymath/standards` advances: - -1. Open a PR here that updates `cartridge-v1.json` to the new content. -2. Update `PINNED-SHA` with the new commit SHA in standards and the new SHA-256 of the file. -3. The PR's description references the standards PR/commit that introduced the change. -4. Auto-merge once CI validates that **every** cartridge manifest still parses against the new schema — `just validate`, which must report 0 failing. (The count is currently 142; it was 125 when this page was written. Read it from the validator rather than quoting a number here, so this line cannot go stale again.) - -## What if they disagree? - -Standards wins. Local mirror is always advancing toward standards. Cartridges authored against an older mirror remain valid as long as the schema change is backwards-compatible (the canonical schema is versioned; breaking changes ship as `cartridge-v2.json`). diff --git a/tools/auth-method-batch-fix/README.adoc b/tools/auth-method-batch-fix/README.adoc new file mode 100644 index 00000000..de9fde5c --- /dev/null +++ b/tools/auth-method-batch-fix/README.adoc @@ -0,0 +1,38 @@ +== auth-method-batch-fix + +One-shot tool used to close issue #19 — the canonical schema restricts +`+auth.method+` to `+[none, api-key, oauth2, vault]+`, but the migration +that seeded this repo from `+boj-server/cartridges/+` carried in a wider +vocabulary (`+bearer_token+`, `+api_key+`, `+api_key_header+`, +`+session-token+`, `+bearer+`, `+basic+`, `+api_token+`, +`+optional_*+`). + +This script walks `+cartridges/+`, finds the auth.method (handling both +multi-line and inline `+auth: { ... }+` blocks), and rewrites any +non-canonical value to `+"api-key"+` — the universal "`needs a +credential`" label. The original value is preserved verbatim under a +sibling `+notes_method+` field so the credential-presentation flavour +(bearer-style header vs query-param vs basic) isn’t lost. + +The mapping is *conservative and lossy-by-design*: a follow-up may +re-classify any of these to `+"oauth2"+` or `+"vault"+` if the cartridge +in question really uses a full flow rather than a pre-issued credential. + +=== Usage + +[source,bash] +---- +cd tools/auth-method-batch-fix +deno run --allow-read --allow-write main.ts +---- + +The script is idempotent: any `+auth.method+` already in the canonical +enum is counted under `+alreadyCanonical+` and skipped. + +After running, validate with: + +[source,bash] +---- +cd ../validate-cartridges +deno task audit +---- diff --git a/tools/auth-method-batch-fix/README.md b/tools/auth-method-batch-fix/README.md deleted file mode 100644 index e0ea6b6f..00000000 --- a/tools/auth-method-batch-fix/README.md +++ /dev/null @@ -1,38 +0,0 @@ - - - -# auth-method-batch-fix - -One-shot tool used to close issue #19 — the canonical schema restricts -`auth.method` to `[none, api-key, oauth2, vault]`, but the migration that -seeded this repo from `boj-server/cartridges/` carried in a wider -vocabulary (`bearer_token`, `api_key`, `api_key_header`, `session-token`, -`bearer`, `basic`, `api_token`, `optional_*`). - -This script walks `cartridges/`, finds the auth.method (handling both -multi-line and inline `auth: { ... }` blocks), and rewrites any -non-canonical value to `"api-key"` — the universal "needs a credential" -label. The original value is preserved verbatim under a sibling -`notes_method` field so the credential-presentation flavour -(bearer-style header vs query-param vs basic) isn't lost. - -The mapping is **conservative and lossy-by-design**: a follow-up may -re-classify any of these to `"oauth2"` or `"vault"` if the cartridge in -question really uses a full flow rather than a pre-issued credential. - -## Usage - -```bash -cd tools/auth-method-batch-fix -deno run --allow-read --allow-write main.ts -``` - -The script is idempotent: any `auth.method` already in the canonical -enum is counted under `alreadyCanonical` and skipped. - -After running, validate with: - -```bash -cd ../validate-cartridges -deno task audit -``` diff --git a/tools/cartridge-minter/README.adoc b/tools/cartridge-minter/README.adoc new file mode 100644 index 00000000..c00dec39 --- /dev/null +++ b/tools/cartridge-minter/README.adoc @@ -0,0 +1,123 @@ +== Cartridge minter + +Scaffolds a new BoJ cartridge from a `+minter.toml+` configuration. + +Until this tool landed, new cartridges were created by +`+cp -r cartridges/templates/gossamer-mcp +` followed by +manual edits of `+cartridge.json+`, `+mod.js+`, etc. — the Phase-3B +completion record (in boj-server) documents that workflow. The minter +replaces it with a single command. + +=== Usage + +[source,sh] +---- +deno run --allow-read --allow-write tools/cartridge-minter/mint.ts [--dest ] +---- + +If `+--dest+` is omitted, the destination is derived from +`+minter.toml+`: + +[width="100%",cols="50%,50%",options="header",] +|=== +|`+category+` |Destination +|`+domain+` (default) +|`+cartridges/domains///+` + +|`+cross-cutting+` +|`+cartridges/cross-cutting///+` + +|`+template+` |`+cartridges/templates//+` +|=== + +=== `+minter.toml+` format + +[source,toml] +---- +# Required +name = "linear-mcp" # must end in a canonical role suffix +description = "Linear project management cartridge" +version = "0.1.0" # semver +domain = "Comms" # will be normalised (see below) +protocols = ["MCP", "GraphQL"] +tier = "Ayo" # Teranga | Shield | Ayo + +# Optional taxonomy hint +category = "domain" # domain | cross-cutting | template +cross_cutting_category = "agentic" # required when category == "cross-cutting" + +# Optional auth (string shorthand or table form both accepted) +auth = "bearer" # shorthand +# OR +[auth] +method = "bearer_token" +env_var = "LINEAR_API_KEY" +credential_source = "vault-mcp" + +# Optional API metadata +[api] +base_url = "https://api.linear.app/graphql" +content_type = "application/json" +---- + +=== Validation + +Before scaffolding, the minter validates: + +* `+name+` ends in a canonical role suffix +`+(-mcp|-lsp|-dap|-bsp|-debug|-format|-lint|-build|-nesy|-agentic|-fleet)+` +* `+version+` is valid semver +* `+tier+` is one of `+Teranga | Shield | Ayo+` +* All required fields present + +=== Domain normalisation + +Mixed-case / synonym domains in input are mapped to canonical +kebab-case: `+Cloud+` → `+cloud+`, `+CI/CD+` → `+ci-cd+`, +`+Container Orchestration+` → `+container+`, `+Package Management+` → +`+registry+`, etc. See the `+DOMAIN_NORMALISE+` map in `+mint.ts+`. + +=== Post-mint workflow + +The minter: + +[arabic] +. Copies `+cartridges/templates/gossamer-mcp/+` to the destination. +. Overwrites `+cartridge.json+` with a manifest derived from +`+minter.toml+`, conforming to the +link:../../schemas/cartridge-v1.json[canonical schema] (`+$schema+` set +to +`+https://hyperpolymath.dev/standards/cartridges/cartridge-v1.json+`). +. Drops the original `+minter.toml+` into the new cartridge dir for +re-mint reproducibility. + +You then edit: + +* `+cartridge.json+` — add your `+tools[]+` array. +* `+mod.js+` — implement the host entry point (calls your loopback +backend). +* `+adapter/+` — the Deno-side MCP server (or LSP/DAP/BSP server per +role). +* `+ffi/+` — Zig FFI bindings to native libraries. +* `+abi/+` — Idris2 ABI definitions (REQUIRED for Teranga / Shield +tier). +* `+README.adoc+` — human-facing docs. + +=== Example + +[source,sh] +---- +$ cat > /tmp/example-minter.toml < - -# Cartridge minter - -Scaffolds a new BoJ cartridge from a `minter.toml` configuration. - -Until this tool landed, new cartridges were created by `cp -r cartridges/templates/gossamer-mcp ` followed by manual edits of `cartridge.json`, `mod.js`, etc. — the Phase-3B completion record (in boj-server) documents that workflow. The minter replaces it with a single command. - -## Usage - -```sh -deno run --allow-read --allow-write tools/cartridge-minter/mint.ts [--dest ] -``` - -If `--dest` is omitted, the destination is derived from `minter.toml`: - -| `category` | Destination | -|---|---| -| `domain` (default) | `cartridges/domains///` | -| `cross-cutting` | `cartridges/cross-cutting///` | -| `template` | `cartridges/templates//` | - -## `minter.toml` format - -```toml -# Required -name = "linear-mcp" # must end in a canonical role suffix -description = "Linear project management cartridge" -version = "0.1.0" # semver -domain = "Comms" # will be normalised (see below) -protocols = ["MCP", "GraphQL"] -tier = "Ayo" # Teranga | Shield | Ayo - -# Optional taxonomy hint -category = "domain" # domain | cross-cutting | template -cross_cutting_category = "agentic" # required when category == "cross-cutting" - -# Optional auth (string shorthand or table form both accepted) -auth = "bearer" # shorthand -# OR -[auth] -method = "bearer_token" -env_var = "LINEAR_API_KEY" -credential_source = "vault-mcp" - -# Optional API metadata -[api] -base_url = "https://api.linear.app/graphql" -content_type = "application/json" -``` - -## Validation - -Before scaffolding, the minter validates: - -- `name` ends in a canonical role suffix `(-mcp|-lsp|-dap|-bsp|-debug|-format|-lint|-build|-nesy|-agentic|-fleet)` -- `version` is valid semver -- `tier` is one of `Teranga | Shield | Ayo` -- All required fields present - -## Domain normalisation - -Mixed-case / synonym domains in input are mapped to canonical kebab-case: -`Cloud` → `cloud`, `CI/CD` → `ci-cd`, `Container Orchestration` → `container`, -`Package Management` → `registry`, etc. See the `DOMAIN_NORMALISE` map in `mint.ts`. - -## Post-mint workflow - -The minter: - -1. Copies `cartridges/templates/gossamer-mcp/` to the destination. -2. Overwrites `cartridge.json` with a manifest derived from `minter.toml`, conforming to the [canonical schema](../../schemas/cartridge-v1.json) (`$schema` set to `https://hyperpolymath.dev/standards/cartridges/cartridge-v1.json`). -3. Drops the original `minter.toml` into the new cartridge dir for re-mint reproducibility. - -You then edit: - -- `cartridge.json` — add your `tools[]` array. -- `mod.js` — implement the host entry point (calls your loopback backend). -- `adapter/` — the Deno-side MCP server (or LSP/DAP/BSP server per role). -- `ffi/` — Zig FFI bindings to native libraries. -- `abi/` — Idris2 ABI definitions (REQUIRED for Teranga / Shield tier). -- `README.adoc` — human-facing docs. - -## Example - -```sh -$ cat > /tmp/example-minter.toml < - - -# category-batch-fix - -One-shot tool used to close issue #18 — the canonical schema requires a -top-level `category` field on every cartridge manifest, but the migration -that seeded this repo from `boj-server/cartridges/` did not add the field. -This script walked all 139 manifests, derived `category` from the file's -path (`domains/` → `"domain"`, `cross-cutting/` → `"cross-cutting"`, -`templates/` → `"template"`), and inserted the field via string-level -patching (preserving the rest of each manifest's formatting). - -Kept in-tree as a precedent for similar mechanical batch fixes (e.g. -future enum-mapping or missing-field campaigns under #19 / #20). - -## Usage - -```bash -cd tools/category-batch-fix -deno run --allow-read --allow-write main.ts -``` - -The script is idempotent: manifests that already have `category` are -counted under `alreadyHad` and skipped. After running, validate with: - -```bash -cd ../validate-cartridges -deno task audit -``` diff --git a/tools/missing-fields-batch-fix/README.adoc b/tools/missing-fields-batch-fix/README.adoc new file mode 100644 index 00000000..491ec66e --- /dev/null +++ b/tools/missing-fields-batch-fix/README.adoc @@ -0,0 +1,51 @@ +== missing-fields-batch-fix + +One-shot tool used to close the mechanical subset of issue #20. The +canonical schema requires several top-level + nested fields that some +"`minimal`" cartridge manifests omit. This script fills them with safe, +schema-conformant defaults: + +[width="100%",cols="50%,50%",options="header",] +|=== +|Field |Default +|`+protocols+` |Inferred from the role suffix in `+name+` (`+-mcp+` → +`+["MCP"]+`, `+-lsp+` → `+["LSP"]+`, …). + +|`+api+` +|`+{ "base_url": "local://", "content_type": "application/json" }+` + +|`+auth.env_var+` |`+null+` + +|`+auth.credential_source+` |`+null+` + +|`+tools[*].inputSchema+` |`+{ "type": "object", "properties": {} }+` +|=== + +Unlike the category/auth scripts, this one re-serialises each touched +manifest in canonical 2-space form with schema-ordered properties. The +manifests that needed patching were all single-line / heavily compact — +restructuring them to the gossamer-template shape is a wash for human +reading and makes downstream diffs comprehensible. + +The three name-pattern stragglers (`+boj-health+`, `+origenemcp+`, +`+opendatamcp+`) are *skipped*: renaming a cartridge changes its +identity downstream and needs owner direction. + +=== Usage + +[source,bash] +---- +cd tools/missing-fields-batch-fix +deno run --allow-read --allow-write main.ts +---- + +The script is idempotent: manifests already carrying every required +field are counted under `+alreadyComplete+` and skipped. + +After running, validate with: + +[source,bash] +---- +cd ../validate-cartridges +deno task audit +---- diff --git a/tools/missing-fields-batch-fix/README.md b/tools/missing-fields-batch-fix/README.md deleted file mode 100644 index 8ae83669..00000000 --- a/tools/missing-fields-batch-fix/README.md +++ /dev/null @@ -1,44 +0,0 @@ - - - -# missing-fields-batch-fix - -One-shot tool used to close the mechanical subset of issue #20. The -canonical schema requires several top-level + nested fields that some -"minimal" cartridge manifests omit. This script fills them with safe, -schema-conformant defaults: - -| Field | Default | -|---|---| -| `protocols` | Inferred from the role suffix in `name` (`-mcp` → `["MCP"]`, `-lsp` → `["LSP"]`, …). | -| `api` | `{ "base_url": "local://", "content_type": "application/json" }` | -| `auth.env_var` | `null` | -| `auth.credential_source` | `null` | -| `tools[*].inputSchema` | `{ "type": "object", "properties": {} }` | - -Unlike the category/auth scripts, this one re-serialises each touched -manifest in canonical 2-space form with schema-ordered properties. The -manifests that needed patching were all single-line / heavily compact — -restructuring them to the gossamer-template shape is a wash for human -reading and makes downstream diffs comprehensible. - -The three name-pattern stragglers (`boj-health`, `origenemcp`, -`opendatamcp`) are **skipped**: renaming a cartridge changes its -identity downstream and needs owner direction. - -## Usage - -```bash -cd tools/missing-fields-batch-fix -deno run --allow-read --allow-write main.ts -``` - -The script is idempotent: manifests already carrying every required -field are counted under `alreadyComplete` and skipped. - -After running, validate with: - -```bash -cd ../validate-cartridges -deno task audit -``` diff --git a/tools/validate-cartridges/README.adoc b/tools/validate-cartridges/README.adoc new file mode 100644 index 00000000..0466cb72 --- /dev/null +++ b/tools/validate-cartridges/README.adoc @@ -0,0 +1,34 @@ +== validate-cartridges + +Walks `+cartridges/+` and validates every `+cartridge.json+` against the +canonical schema at `+schemas/cartridge-v1.json+`. Zero-dependency Deno +script (`+jsr:@std/fs+` + `+jsr:@std/path+` only). + +=== Usage + +[source,bash] +---- +cd tools/validate-cartridges +deno task audit # summary report; exits 0 even on failure +deno task audit-verbose # adds per-manifest failure list +deno task strict # exits non-zero on any failure +---- + +=== Modes + +* `+audit+` (default) — print a summary + top recurring issues; exit 0. +Use this during the drift-inventory phase (the report tells you what to +fix). +* `+strict+` — exit non-zero if any manifest fails. Use this once drift +is fixed and as a blocking CI gate. + +=== Why a hand-rolled validator + +The schema is small and stable; pulling in a full JSON-Schema +implementation (ajv etc.) means npm or jsr-npm-shim plumbing that the +estate npm→deno policy asks us to avoid. This script covers the subset +the schema actually uses: `+type+`, `+enum+`, `+pattern+`, `+required+`, +`+properties+`, `+items+`, `+minItems+`. + +If the schema starts using `+oneOf+` / `+anyOf+` / `+$ref+`, swap in a +fuller implementation at that point. diff --git a/tools/validate-cartridges/README.md b/tools/validate-cartridges/README.md deleted file mode 100644 index 5189c3b1..00000000 --- a/tools/validate-cartridges/README.md +++ /dev/null @@ -1,34 +0,0 @@ - - - -# validate-cartridges - -Walks `cartridges/` and validates every `cartridge.json` against the canonical -schema at `schemas/cartridge-v1.json`. Zero-dependency Deno script -(`jsr:@std/fs` + `jsr:@std/path` only). - -## Usage - -```bash -cd tools/validate-cartridges -deno task audit # summary report; exits 0 even on failure -deno task audit-verbose # adds per-manifest failure list -deno task strict # exits non-zero on any failure -``` - -## Modes - -- `audit` (default) — print a summary + top recurring issues; exit 0. Use this - during the drift-inventory phase (the report tells you what to fix). -- `strict` — exit non-zero if any manifest fails. Use this once drift is fixed - and as a blocking CI gate. - -## Why a hand-rolled validator - -The schema is small and stable; pulling in a full JSON-Schema implementation -(ajv etc.) means npm or jsr-npm-shim plumbing that the estate npm→deno policy -asks us to avoid. This script covers the subset the schema actually uses: -`type`, `enum`, `pattern`, `required`, `properties`, `items`, `minItems`. - -If the schema starts using `oneOf` / `anyOf` / `$ref`, swap in a fuller -implementation at that point.