Repository navigation
Estate-wide re-validation of the #199/#205 closure ABI (was static-only until #225 PR2 ran it in a real wasm engine) #235
Description
Activity
- added 3 commits that reference this issue
on May 19, 2026 Deliverable (1) shipped (PR #279):
tests/codegen/closure_indirect_dispatch.{affine,mjs}— the #199[fnId@0,envPtr@4]closure ABI is now engine-validated via the exported__indirect_function_tablewith no async/CPS transform involved (imports onlyenv.invokeCallback, nothenableThen). This is the negative-control thehttp_cps_*tests cannot isolate; it protects the shared closure path for every consumer independent of #205. Full wasm harness +dune test --force290 green.Deliverable (2) — estate-consumer audit:
Consumer Uses Runtime-smoke needed? rsr-certifier (standards#123, satellites/rsr-certifier/extensions/vscode/src/extension.affine)full #199 closures + #205 httpPostJson/thenableThen/thenableResultJson/jsonField; ships its ownwrapHandlerclone (src/affine-vscode-adapter.cjs); zero wasm testsYES — genuinely needs one (the only materially-exposed consumer; this is exactly the static-only blind spot that hid the PR2 defects) my-lang ( vscode-extension/src/extension.affine)#199 registerCommandclosures only, no #205No — covered upstream by (1) idaptik / reposystem .tsgenericvscoderegisterCommand— not the AffineScript wasm ABIN/A boj-server / gitbot-fleet no .affineconsumer (boj-server is the HTTP peer ofhttpPostJson)N/A Remaining tracked item: a runtime smoke for rsr-certifier in the standards repo (cross-repo; the ABI it depends on is now upstream-guaranteed by (1), so this is hardening, not a correctness gap). Leaving #235 open for that.
- added a commit that references this issue
on May 19, 2026 Status refresh (2026-05-30):
The original "surfaced by #225 PR2 → static-only until real-wasm-engine validation" framing is partly resolved: fix PR #233 merged 2026-05-19 with real-wasm-engine exercise of the #199/#205 closure ABI.
Remaining work on this issue:
- Estate-wide re-validation pass (run the validation rig against every
.affinefixture across the estate, not just the one in stdlib Http: typed-wasm target (convergence ABI; shared with Ephapax) #225). - Regression test capturing the failure mode that drove feat(codegen): #225 PR2 — WasmGC CPS transform, Async base case (ADR-013) #233.
Title could be re-scoped to
Estate audit + regression test for #199/#205 closure ABI (post-#233)if that's clearer.- Estate-wide re-validation pass (run the validation rig against every
- addedbindingsABI, FFI, WASM, and cross-language interop surfacesABI, FFI, WASM, and cross-language interop surfacesscope:estateAffects many or all repos across the estateAffects many or all repos across the estatetestingTests, benchmarks, fuzzing, property checks, coverageTests, benchmarks, fuzzing, property checks, coverage
on Aug 27, 2026 Re-measured the estate-wide half today (2026-09-19) — the language-side exercise is in place; the consumer side has no evidence, so this issue is currently the only tracker for it.
The thread's 2026-05-30 refresh records that #233 merged with real-wasm-engine exercise of the #199/#205 closure ABI, leaving "estate-wide re-validation" as the remaining work. Where that stands now:
Repo files referencing the closure ABI / indirect function table affinescript14 — including tests/codegen/closure_indirect_dispatch.affineandlib/codegen.mltyped-wasm1 — spec/async-convergence-abi.adoc(spec text, not an executable exercise)boj-server0 So the producer side is exercised end-to-end, and I can find no consumer repo that runs the closure ABI through a real engine —
typed-wasmcarries only the spec. That matches the issue's own framing: it exists precisely because static verification missed two latent defects, and it is the only artifact tracking that consumers have not re-run since.Suggested action to make it closable: convert it to an explicit per-consumer checklist (which repos consume the closure ABI, each with its own real-engine exercise), then close when the checklist is green. As written it cannot be finished, because "estate-wide" has no denominator.
- addedpriority:p2Normal - queue itNormal - queue itstatus:readyFully specified and ready to be picked upFully specified and ready to be picked upfeeds:valence-shellFeeds valence-shell's proofs/engineering (D127): judge progress by what it contributes thereFeeds valence-shell's proofs/engineering (D127): judge progress by what it contributes there
on Sep 30, 2026
Problem
#225 PR2 surfaced that the #199 closure ABI / #205 Thenable path had never been executed in a real WebAssembly engine anywhere in the estate. PR1's skeleton was pure pass-through (no closure dispatch); PR2's continuation is the first true end-to-end exercise, and it immediately surfaced two latent defects that static verification had never caught:
__indirect_function_table(host dispatch impossible);closure_codeusedLocalTeewhere the surrounding code assumesLocalSet, leaving a 2-value stack imbalance (invalid wasm).Both are fixed in PR #233. But the implication is estate-wide: every downstream consumer that "dogfooded" the #199/#205 surface (e.g. standards#123 rsr-certifier extension, idaptik, boj-server bridges) was static-only — compiled, never run in a wasm host. Their runtime correctness is unverified.
Proposed work
tests/codegenregression that exercises the Deno source-to-source host→guest callback ABI (blocks withProgress/registerCommand/onDidSave) #199 closure dispatch independent of the async transform (a plain captured-closure call through__indirect_function_table), so the shared path is protected for all closure users.Surfaced by #225 PR2. Refs #225, #199, #205.