|
| 1 | +// SPDX-License-Identifier: CC-BY-SA-4.0 |
| 2 | +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk> |
| 3 | + |
| 4 | += BoJ completion plan — 2026-07-01 ground-truth refresh |
| 5 | +:toc: |
| 6 | +:toc-placement: preamble |
| 7 | +:icons: font |
| 8 | + |
| 9 | +*Date:* 2026-07-01 · |
| 10 | +*Companion:* `docs/planning/v1-critical-chain-2026-06-11.adoc` (the ordering |
| 11 | +doctrine — gates G0–G6, chains A–E — which this document *refreshes*, not |
| 12 | +replaces) · |
| 13 | +*Inputs:* two-agent ground-truth survey of both repos + three-critic |
| 14 | +adversarial verification of this document's own claims (accuracy / |
| 15 | +completeness / sequencing), live CI forensics, and the 2026-06-25→07-01 |
| 16 | +remediation history. |
| 17 | + |
| 18 | +Everything in the critical chain still stands. This refresh records (1) what |
| 19 | +moved since 2026-06-11, (2) what a fresh adversarial audit found that the |
| 20 | +chain does not yet carry, and (3) the decision list that currently blocks the |
| 21 | +critical path. Line-level citations were spot-verified on 2026-07-01. |
| 22 | + |
| 23 | +== 1. What moved since the critical chain was written |
| 24 | + |
| 25 | +* *Proof break found and fixed* — duplicate `allTake` in `SafetyLemmas.idr` |
| 26 | + had the core `boj.ipkg` failing to typecheck; repaired, 105/105 PASS |
| 27 | + (PR #256). The `typecheck-proofs.sh` exit-code bug is fixed; a Monday cron |
| 28 | + re-baselines main (PR #257). |
| 29 | +* *Licence + README + counts reconciled on main* — MPL-2.0 everywhere |
| 30 | + (owner kept idaptik AGPL), real Markdown README, one 125/68/0.4.7 story |
| 31 | + (PRs #255–#265). *Issue #186 is therefore fixed in fact — verified |
| 32 | + 2026-07-01 — and can be closed* (owner action, see §4). |
| 33 | +* *The registry repo's CI was dark and is now lit* (2026-07-01): seven |
| 34 | + workflows had *never successfully started* on `boj-server-cartridges`. |
| 35 | + Three stacked causes, all fixed: invalid `timeout-minutes` on |
| 36 | + reusable-workflow-call jobs (PR cartridges#70); an `allowed_actions: |
| 37 | + selected` policy with an *empty* allow-list, start-blocking |
| 38 | + `mlugg/setup-zig` and `dawidd6/action-send-mail` (repo setting aligned to |
| 39 | + boj-server: `all` + `sha_pinning_required`); and caller jobs not granting |
| 40 | + the permissions their called reusable workflows request (PR cartridges#71). |
| 41 | + Consequence worth stating plainly: *zig adapter/FFI tests had never |
| 42 | + actually executed in the registry repo*. The Cartridge Schema red was a |
| 43 | + stale `PINNED-SHA` record only (mirror already matched canonical |
| 44 | + standards@f5f0506a); re-pinned in #70. |
| 45 | +* *Checkout hygiene* — the duplicate-looking local checkout was a symlink |
| 46 | + (removed); both local mains reset to origin; diverged never-pushed commits |
| 47 | + preserved on `rescue/main-local-2026-06-04` (boj-server) and |
| 48 | + `rescue/main-local-2026-06-11` (cartridges). |
| 49 | +* *boj-server.net changed state* — no longer the June 522/dead-Verpex-IP |
| 50 | + story: the apex now answers HTTP 200 behind a Cloudflare managed |
| 51 | + challenge (origin/content unverified), and `api.boj-server.net` does not |
| 52 | + resolve at all (NXDOMAIN — no record, not a dead one). The Phase/G3–G4 |
| 53 | + DNS work is therefore "create + verify", not "replace". |
| 54 | + |
| 55 | +== 2. New findings the chain does not yet carry (adversarially verified) |
| 56 | + |
| 57 | +=== 2.1 G0 has silently regressed in the registry |
| 58 | + |
| 59 | +The truthful-baseline gate (G0, "DONE 2026-06-05") holds in *boj-server* |
| 60 | +(125 manifests, exactly 1 `available:true` = `feedback-mcp`) but *not* in |
| 61 | +`boj-server-cartridges`: *12 manifests say `available:true`* |
| 62 | +(`textkit`, `lang`, `conflow`, `reposystem`, `kategoria`, `burble-admin`, |
| 63 | +`container`, `local-memory`, `hesiod`, `feedback`, `model-router`, |
| 64 | +`boj-health`). Both `site/catalog.json` files (each repo has one) advertise |
| 65 | +*139 cartridges, all `available:true`*. And the external manifest surface |
| 66 | +(`smithery.yaml`, `jsr.json` — "125 formally verified domain cartridges" — |
| 67 | +`glama.json`, `gemini-extension.json`, `ai-plugin.json`, `openapi.yaml`) |
| 68 | +still carries the pre-G0 claims. JSR is *published* at 0.4.7 alongside npm, |
| 69 | +and `publish.yml` hard-couples the release tag to `jsr.json`'s version — so |
| 70 | +the next release cut breaks unless the manifest sweep happens first. |
| 71 | + |
| 72 | +*Rule to adopt* (chain E2 already states it): one-count-one-place — counts |
| 73 | +are *generated* from the catalogue (the committed-on-main basis), everything |
| 74 | +else links. Regenerate rather than hand-edit; regenerate the bridge's |
| 75 | +offline menu (`mcp-bridge/lib/generate-offline-menu.js`) in the same pass |
| 76 | +and assert it in the surface-drift gate, or it desynchronises the moment the |
| 77 | +catalogs are corrected. |
| 78 | + |
| 79 | +=== 2.2 The two cartridge trees have fully diverged |
| 80 | + |
| 81 | +Not one of the 125 shared cartridges is byte-identical across the repos: the |
| 82 | +registry copies carry an extra `capabilities` block (universe / locked_down |
| 83 | +/ inertness) plus header drift. So O2/A5 ("registry is canonical, boj-server |
| 84 | +becomes a build-time fetch") is *not a no-op copy* — it is a schema |
| 85 | +reconciliation. Raising the stakes: `release.yml:38` *already* builds |
| 86 | +release artifacts from the registry via `scripts/fetch-cartridges.sh`, so |
| 87 | +releases and the runtime currently see *different* cartridge sources. The |
| 88 | +runtime side is one default away (`elixir/lib/boj_rest/application.ex` |
| 89 | +already honours `BOJ_CARTRIDGES_PATH` in its fallback chain) — days of |
| 90 | +wiring, not weeks; the proof-tree canonicalisation (cartridges#36) is the |
| 91 | +week-plus workstream and should be split out so it never gates the flip. |
| 92 | + |
| 93 | +=== 2.3 The Foundry's Configure stage is the load-bearing gap |
| 94 | + |
| 95 | +`tools/foundry/`: Mint / Provision / Harness are real and tested, and the |
| 96 | +pipeline is modelled + typechecked in Idris2 (`proof/Foundry.idr` — |
| 97 | +no-dropped-proofs, least-authority). *Configure is a `say` line* — no stage |
| 98 | +script exists (`foundry.sh` §3). Direct evidence in the registry working |
| 99 | +tree: three freshly-minted, uncommitted cartridges — `notebooks-mcp` and |
| 100 | +`visualization-mcp` stranded with `tools: []` and verbatim gossamer-template |
| 101 | +adapters; `datacloud-mcp` completed *by hand* (bespoke `mod.js`, 2 tools) — |
| 102 | +hand-editing being precisely the workaround Configure exists to eliminate. |
| 103 | +Two stray root `*.minter.toml` duplicates ride along. Chain A1's "fresh mint |
| 104 | +that flips truthfully to available:true" is exactly this: build Configure, |
| 105 | +then finish notebooks/visualization through it as the pilot, and re-run |
| 106 | +hand-made datacloud through the harness as the control. |
| 107 | + |
| 108 | +=== 2.4 Two cross-cutting stories the plan must carry explicitly |
| 109 | + |
| 110 | +* *Auth before exposure* (chain B1, pending since April): |
| 111 | + `docs/AUTH-DESIGN.adoc` marks HTTP-layer caller auth on the invoke |
| 112 | + endpoint as an *OPEN GAP*. Wiring `api.boj-server.net` to a deployed |
| 113 | + backend before B1 lands would put an unauthenticated side-effect executor |
| 114 | + on the public internet. B1's dual-posture recommendation (loopback default |
| 115 | + + HCG tier-2 for exposed mode) is the answer; the *decision* is the |
| 116 | + blocker, not the design. |
| 117 | +* *Credentials before the credentialed waves*: `vault-mcp`, the Elixir |
| 118 | + `credential_decryptor` + `trust_policy`, and B4's delegation truth |
| 119 | + ("keyed cartridges are not delegatable to community nodes in v1") must be |
| 120 | + stated as the credential architecture for Wave-2 cartridges — the |
| 121 | + truthfulness probe cannot even run against them without it. |
| 122 | + |
| 123 | +=== 2.5 Smaller carried items |
| 124 | + |
| 125 | +* *Deployment-artifact sprawl*: `Containerfile`, fly variant, `k8s/`, |
| 126 | + `wrangler.toml`, `selur-compose.toml`, `stapeln.toml`, `packaging/` — the |
| 127 | + O3 hosting decision should name ONE canonical path (chain C1 publishes its |
| 128 | + images) and mark the rest secondary or delete them, so re-filed #262 |
| 129 | + doesn't add a sixth. |
| 130 | +* *`instant-sync.yml` authenticates with `FARM_DISPATCH_TOKEN`* — a secret |
| 131 | + the estate identity-rebuild plan intends to DROP; migrate to its successor |
| 132 | + or disable deliberately, before it silently dies mid-plan. |
| 133 | +* *Residual "115" docs debt* (most was fixed by PR #256; the real remaining |
| 134 | + sites): `docs/status/ROADMAP.adoc:79–86`, `docs/READINESS.adoc:179,182`, |
| 135 | + `docs/architecture/README.adoc:178,179,277`, |
| 136 | + `docs/decisions/0007…:19`, `0008…:152`. Plus chain E3's |
| 137 | + `FUTURE_PLANS.adoc` deletion. |
| 138 | +* *Registry mod.js census*: ~125 of 140 registry cartridges have adapters; |
| 139 | + 14 are canonical-only manifests (per its README); boj-server's 125 split |
| 140 | + is 1 ready / 109 catalogued / 10 stub / 5 ffi_only. |
| 141 | +* *Duplicate mint tooling*: `tools/cartridge-minter` coexists with the |
| 142 | + Foundry (plus three one-off batch-fix scripts) — declare the Foundry the |
| 143 | + sole mint path when Configure lands; keep `validate-cartridges` as a gate |
| 144 | + input. |
| 145 | +* *`.machine_readable` naming*: the estate mandate renames `6a2` → |
| 146 | + `descriptiles`; fold into #202's layout move rather than moving it twice. |
| 147 | +* *#214 (`secrets-mcp` stub + insecure GraphQL dispatch)* is |
| 148 | + security-flagged and independent of backend/Foundry — pull it forward |
| 149 | + into the immediate window; do not queue it behind Waves. |
| 150 | + |
| 151 | +== 3. Refreshed sequencing (docked into the chain) |
| 152 | + |
| 153 | +[cols="1,4,2",options="header"] |
| 154 | +|=== |
| 155 | +| Window | Work | Docks at |
| 156 | + |
| 157 | +| Now (days) |
| 158 | +| Truth reconvergence: 12→probe-judged availability flags in the registry; |
| 159 | + regenerate both `site/catalog.json` + offline-menu from the catalogue; |
| 160 | + external-manifest sweep (smithery/jsr/glama/gemini/ai-plugin/openapi); |
| 161 | + residual 115 sites; delete FUTURE_PLANS; commit-or-discard the three |
| 162 | + scaffolds' *manifests* (code completion waits for Configure); remove stray |
| 163 | + minter.tomls; fix #214; verify the two CI-fix PRs hold (zig-test's first |
| 164 | + real run may surface real findings — that is the point). |
| 165 | +| G0 re-established, E2/E3 |
| 166 | + |
| 167 | +| Next (after O2; ~days for the flip) |
| 168 | +| Registry-canonical cut-over: schema reconciliation (capabilities block), |
| 169 | + flip the runtime default to the registry path, embedded set becomes |
| 170 | + derived cache; #36 proof canonicalisation runs as a *parallel* workstream. |
| 171 | +| A5, #183 contract |
| 172 | + |
| 173 | +| Parallel track 1 (after B1 decision; 1–2 weeks) |
| 174 | +| Invoke-auth dual posture + backend deployment on the O3 host behind it; |
| 175 | + create `api.` DNS; verify what the apex serves; elixir suite green against |
| 176 | + the deployed config; e2e smoke via feedback-mcp. *v0.9 "honest beta" cut |
| 177 | + here* (chain E1), not after the Waves. |
| 178 | +| G1, G3, B1–B3 |
| 179 | + |
| 180 | +| Parallel track 2 (highest engineering leverage) |
| 181 | +| Build Configure; pilot notebooks/visualization + re-harness datacloud; |
| 182 | + declare Foundry sole mint path; then required checks |
| 183 | + (truthfulness/proofs/zig-test/abi-drift) flipped ON in the registry — |
| 184 | + *before* any batch waves, per chain A4 and inverted from the old |
| 185 | + Phase-6-last ordering. |
| 186 | +| A1, A4, #200 |
| 187 | + |
| 188 | +| Then |
| 189 | +| Golden Dozen (A2) → batch waves (A3/#201) with the credential story |
| 190 | + stated for Wave 2; G4–G6 community/operator chain as written. |
| 191 | +| G2, G4–G6, v1.0 |
| 192 | + |
| 193 | +| Long arcs (post-v1) |
| 194 | +| #87 items 14/11/12 (HTTP transport impl, last axioms, composition proof); |
| 195 | + AffineScript ports (cartridges#46, #67, #48) — gated on AffineScript v1 |
| 196 | + readiness; obleeny (#198); the autonomous bug-reporting pipeline |
| 197 | + sub-issues (held on O1/D0); coord-tui v0.2/v0.3 roadmap; federation |
| 198 | + ADR-0010 upgrade. |
| 199 | +| Chain B5, post-v1 |
| 200 | +|=== |
| 201 | + |
| 202 | +== 4. Decisions currently blocking the critical path (O-list) |
| 203 | + |
| 204 | +[cols="1,5,3",options="header"] |
| 205 | +|=== |
| 206 | +| # | Decision | Recommendation / state |
| 207 | + |
| 208 | +| O1 | feedback-o-tron ↔ feedback-mcp identity (D0: Converge vs Separate); |
| 209 | + then run the staged issue re-file |
| 210 | + (`~/.claude/jobs/2fe11a32/tmp/apply-refile.sh --go` — umbrella + clean |
| 211 | + re-files of #262/#263/#264; held sub-issues D0/C1/C2/C3 wait on this) |
| 212 | + | Pending since 2026-06-28 |
| 213 | + |
| 214 | +| O2 | Registry-canonical cut-over + sync direction (#36, #183, chain A5) — |
| 215 | + note it is a schema reconciliation, not a copy |
| 216 | + | Registry canonical; boj-server = derived cache |
| 217 | + |
| 218 | +| O3 | Backend host + ONE canonical deployment artifact + CF token with |
| 219 | + Pages scope for the domains |
| 220 | + | mesh-server-1 (exists, Guix-managed); Quadlet/container path per |
| 221 | + chain C |
| 222 | + |
| 223 | +| O4 | B1 invoke-auth decision (open since April) — v1 dual posture |
| 224 | + | Approve chain B1 as written |
| 225 | + |
| 226 | +| O5 | The three stranded scaffolds |
| 227 | + | Finish as the Configure pilot (notebooks/visualization); re-harness |
| 228 | + hand-made datacloud |
| 229 | + |
| 230 | +| O6 | (a) `panll`-the-host in v1? (b) `panll/` ReScript panel: maintain, |
| 231 | + freeze, or fold into #67 |
| 232 | + | Chain C already cuts tray+PanLL from v1 support surface — ratify |
| 233 | + |
| 234 | +| O7 | Umoja federation + tray + coord-tui scope for v1 |
| 235 | + | Chain B5/C already scopes these (constellation-not-mesh; coord-tui in, |
| 236 | + tray out) — ratify |
| 237 | + |
| 238 | +| O8 | External publication acts: close #186 (verified fixed), Glama |
| 239 | + claim + Sync, MCP Registry listing (#188, after G2 locks), and *N* — |
| 240 | + how many verified-real cartridges gate v1.0 (chain says the Dozen) |
| 241 | + | Bundle as one ratification |
| 242 | + |
| 243 | +| O9 | Governance advisory-red stance estate-wide (now visible in the |
| 244 | + registry repo since its CI lit up) |
| 245 | + | cicd-squabbler domain; not BoJ-specific |
| 246 | +|=== |
| 247 | + |
| 248 | +== 5. Definition of complete (unchanged, restated) |
| 249 | + |
| 250 | +v1.0 = G6: one version number everywhere; every advertised surface |
| 251 | +generated from the probe-judged catalogue; backend deployed behind decided |
| 252 | +auth; registry canonical and fetched on demand; Foundry minting |
| 253 | +proof-carrying cartridges end-to-end; gates enforced as required checks; |
| 254 | +operator + contributor paths proven by a non-maintainer. The standing |
| 255 | +invariant behind all of it: *a cartridge is `available:true` iff the |
| 256 | +truthfulness probe says so — and every count everywhere is derived, not |
| 257 | +declared.* |
0 commit comments