Repository navigation
Roll unified-gated-adapter + SSE + regen-trigger into the iseriser scaffold #90
Description
Activity
- addedmajorMajor / load-bearing workMajor / load-bearing workrequirements-targetTracked requirements-target item (joint-close)Tracked requirements-target item (joint-close)
on May 17, 2026 Status — 2026-05-20
Scaffold-side: shipped (with gaps). iseriser PR#12 merged 2026-05-19 (
109b656) —src/codegen/scaffold.rsnow emits both.github/workflows/<name>-regen.yml(fire-and-forget central-trigger, mirrorsk9iser-regen.yml) andadapter/<name>_adapter.zig(unified gated adapter withexposureSatisfiedZig mirror + 4 truth-table tests).cargo testgreen (49 unit + 9 integration).Estate fan-out: correctly gated on #91. PR#12 explicitly does NOT touch the 28 existing -iser repos; until the http-capability-gateway tier-2 (standards#91, ~8–12wk) is wired, the unified core stays internal/loopback and consumer K9 Dogfood gates stay red (tracked, not masked).
Audit — gaps between scaffold templates and the k9iser pilot (
boj-server/cartridges/k9iser-mcp/adapter/k9iser_adapter.zig, 293 lines). To be addressed before estate fan-out begins:- Topology question. Pilot adapter lives in
boj-server/cartridges/<name>-mcp/adapter/, alongside itsbuild.zig,cartridge.json, and the<name>_ffiZig module. Scaffold dropsadapter/<name>_adapter.ziginto the new -iser repo, where none of those exist (@import(\"{name}_ffi\")against nothing) — not buildable. Need a decision: doc-reference, copy-into-boj-server template, or rendezvous topology change. - Dispatch is a stub.
dispatchTooldiscards tool+body and writes a hardcoded{\"status\":\"dispatched\"}placeholder. Pilot'sdispatch()callsffi.boj_cartridge_invokewith null-terminated args, sized out-buffer, and a 0/-1/-2/-3 → 200/404/400/500 return-code mapping. Also missing:ffi.boj_cartridge_init/deinitlifecycle inmain(). - Two of four advertised protocols unimplemented. Module header documents REST + SSE + GraphQL + gRPC. Routing only handles
/sseand falls through to REST for everything else. NoProtocolenum,classify(), ortoolFor()covering all four. Pilot has them all plus tests. - HTTP response buffer-aliasing bug.
dispatchRestwrites the body intoresp_bufand returns a slice into it.handleConnectionthenbufPrint(&resp_buf, …, .{result.status, result.body})— overwriting the buffer before readingresult.bodyout of it. Output will be corrupted. Pilot uses a separatehdrbuffer (writeHttp). - Helper bugs.
headerValuenever trims or splits on:; won't find non-leading headers.jsonFieldsearches for literal\"key\": \"(one space after colon); the common{\"key\":\"value\"}form won't match. Pilot'sjsonStringFieldwalks colon + whitespace properly. - SSE framing differs. Pilot emits
event: open→event: result|error→event: done. Scaffold emits a singledata:line. Won't interop with pilot-compatible consumers. - Scaffold CI doesn't compile-check the generated Zig. The 4 truth-table tests live inside the template string; iseriser's
cargo testonly verifies codegen output, neverzig tests the rendered file. Coverage only fires if a downstream -iser builds. Also missing:presentedExposure,classify,toolFor,dispatchtests. - No
adapter/build.zigemitted. Pilot ships one; scaffold doesn't. - License (AGPL pilot vs PMPL scaffold — likely deliberate) and tool-name default (
{name}_generatevs pilot'sk9_generate) noted as low-priority drift.
Issue stays OPEN: fan-out + audit follow-ups both still owed. Sibling state — #91 gateway (the blocker) still open; #92 (Idris2 SoT) has live PR work landing today (iseriser #13/#14/#15/#16/#20/#21/#22); #93 stays parked behind #91.
🤖 Generated with Claude Code
- Topology question. Pilot adapter lives in
- added a commit that references this issue
on May 20, 2026 Status — 2026-05-20 (end-of-session)
Following the audit comment above, two follow-up PRs landed today:
iseriser#23 MERGED — surgical revert of the wrong-place adapter emission. The audit had identified that PR #12 emitted
adapter/<name>_adapter.ziginto the new -iser repo, but the unified transaction-gated adapter belongs to the boj-server cartridge (boj-server/cartridges/<name>-mcp/adapter/), not to the -iser repo itself. The pilot k9iser confirms: k9iser repo has no adapter; the adapter lives atboj-server/cartridges/k9iser-mcp/adapter/. PR #23 dropped the wrong-place emission (gaps 1–8 of the audit comment) while keeping<name>-regen.yml(correctly emitted in the -iser repo, since it's the trigger that fires into boj-server).iseriser#24 MERGED — new
iseriser cartridgesubcommand: full scaffolder for the boj-server cartridge skeleton (standards#89 Phase 2b). 13 files: top-level (README + cartridge.json + mod.js + panels/manifest.json), Idris2 ABI (README +<iser>-mcp.ipkg+<Iser>Mcp/Safe<Iser>.idrwith the exposure-gate contract), Zig FFI (README +build.zig+<iser>_ffi.zigimplementing the ADR-0006 5-symbol C ABI), and the unified gated adapter (README +build.zig+<iser>_adapter.zigrouting REST + SSE + GraphQL + gRPC-compat behind the transaction gate). Modelled on the k9iser-mcp pilot. End-to-end verified against the actualboj-server/cartridges/tree:idris2 --buildon the emitted.ipkgtype-checksSafeChapeliser(RC=0),zig build testonffi/passes 4/4,zig build testonadapter/passes 5/5.iseriser#25 MERGED — small correction: scaffold now emits
depends = base, contribon the cartridge ipkg to match the pilot convention.iseriser#26 OPEN — docs PR (CHANGELOG entries + README subcommand row + STATE.a2ml refresh).
Where this leaves #90
- Scaffold-side (sub-issue 1 in the parent epic Epic: -iser regeneration-cartridge pattern — wire all 28 -isers into boj-server (unified gated adapter) #89): DONE.
- iseriser
generatecorrectly emits the<name>-regen.ymlcentral trigger in new -iser repos. - iseriser
cartridgecorrectly emits the full boj-server cartridge skeleton.
- iseriser
- Estate fan-out across the 28 existing -iser repos: still owed, correctly parked behind http-capability-gateway tier-2 production-wiring (ADR-0004) #91 (http-capability-gateway tier-2 production-wiring). Until http-capability-gateway tier-2 production-wiring (ADR-0004) #91 ships, the unified core stays internal/loopback and consumer K9 Dogfood gates stay red (tracked, not masked).
#90 stays OPEN until the fan-out lands. Closing it before #91 would lose tracking of the cross-repo work.
Suggested closure when #91 is wired
The fan-out will be a 28 ×
<name>-regen.ymlPR batch (each repo trivially adds the workflow + flips its loopback URL to the gateway endpoint) plus, where missing, aiseriser cartridge --output boj-server/cartridges/invocation per absent cartridge. At that point #90 closes.🤖 Generated with Claude Code
- Scaffold-side (sub-issue 1 in the parent epic Epic: -iser regeneration-cartridge pattern — wire all 28 -isers into boj-server (unified gated adapter) #89): DONE.
- added a commit that references this issue
on May 20, 2026 Next step (re-verified 2026-08-27): one of three items landed — the scaffold emits a
*-regen.ymltrigger. SSE and the transaction gate are entirely absent:git grep -lIiE 'text/event-stream|SSE'and'transaction.gate|gated'oniseriser@origin/mainboth return 0 files. The pilot to copy from is merged (boj-server#73).→ Add the gated-dispatch adapter + SSE surface to
iseriser/src/codegen/scaffold.rs, then re-emit across the 26 -isers (not 28 — see #89 correction). Medium; do it in the same pass as #331's scaffold fix, since the emittedboj-build.ymltemplate is the broken one.- added a commit that references this issue
on Aug 28, 2026 2026-09-03 — second of the three items landed; SSE is still absent, and now deliberately so
Following the 2026-08-27 note (regen trigger landed, SSE and the transaction gate absent):
iseriserPR #101 is merged (b898428d), adding the gated adapter dispatch to the emittedboj-build.yml.Scoreboard for this issue:
Item State regen trigger ( *-regen.yml)landed (2026-08-27) unified gated adapter landed — scheme-checked endpoint, jq -nc --argpayload,curl --fail-with-body, unset = loud skipSSE still absent — see below Why SSE was not wired, and why that is a decision rather than an omission
The dispatch deliberately targets
/cartridge/:name/invoke, not/sse.boj-server's router callssend_chunked(200)before it dispatches (router.ex:100), so an SSE request returns HTTP 200 even when the work behind it fails. That cannot back a hard-failing gate — a CI step pointed at/ssewould be green by construction, which is the exact fake-gate shape this estate keeps finding.So SSE stays open here, and closing it needs either a status-bearing SSE contract on the server side or an out-of-band result channel. Recording it rather than quietly dropping it.
Still true: nothing is proven end-to-end, because CI cannot reach a BoJ server at all (#91 tier-2 gateway unbuilt).
- addedarchitectureStructural/system-level shape and runtime behaviourStructural/system-level shape and runtime behaviourpriority:p2Normal - queue itNormal - queue itscope:estateAffects many or all repos across the estateAffects many or all repos across the estatestatus:readyFully specified and ready to be picked upFully specified and ready to be picked up
on Sep 30, 2026
Roll the pilot pattern (boj-server#73) into the iseriser scaffold so every current + future
-iserships it by construction:*-regen.ymltrigger (mirrors boj-build.yml; already templated for k9iser into rsr#58/v3#76/repo#52 — generalise in the scaffold).Parent: epic. Sibling of the gateway/source-of-truth/gitignore sub-issues.