Context
#555 (closed) fenced effect-handler lowering to fail loud on every compiled backend. The interpreter has one residual, silent shape that survived that fix and now has no open tracker. This is it.
The shape (interpreter path only)
// handler: op() => resume(5)
let x = op();
x + 100 // returns 5, NOT 105
The tree-walking interpreter's continuation is shallow: PerformEffect aborts the whole handle body, and resume(v) returns v as the entire handle result. For a non-tail single-shot resume the bind chain has already unwound, so the post-resume code (x + 100) is discarded and unrecoverable at that point.
What is already correct/loud (not this issue):
Class
residual (pinned) — silent-wrong value, interpreter only. Pinned by an executable test so it cannot regress unnoticed and will flip to failing the day it is fixed:
- fixture
test/e2e/fixtures/handle_resume_nontail.affine
- test
test_resume_nontail_known_shallow in test/test_e2e.ml (asserts the wrong-but-known VInt 5).
Fix + why it's blocked
The correct fix is real delimited continuations = a CPS rewrite of Interp.eval. Blocked: OCaml 4.14 has no native effect handlers, and the interpreter must stay js_of_ocaml-compatible — so it's an architecture-level change against the full suite + the jsoo build. Needs owner steer before starting (see docs/reports/HANDOFF-2026-06-17-soundness.adoc §7.1). Do not silently begin a CPS rewrite.
Status
Canonical, test-anchored status: docs/SOUNDNESS.adoc (the #555 interpreter non-tail row). v1 readiness ledger: #563.
Filed from the docs-soundness pass (PR #622).
Context
#555 (closed) fenced effect-handler lowering to fail loud on every compiled backend. The interpreter has one residual, silent shape that survived that fix and now has no open tracker. This is it.
The shape (interpreter path only)
The tree-walking interpreter's continuation is shallow:
PerformEffectaborts the whole handle body, andresume(v)returnsvas the entirehandleresult. For a non-tail single-shot resume the bind chain has already unwound, so the post-resume code (x + 100) is discarded and unrecoverable at that point.What is already correct/loud (not this issue):
interp.mlresume-invocation counter, Refs tracking: general effect-handler dispatch (post-CORE-02 residual) — silent arm-drop on 3 backends; DECISION: back-port loud failure now? #555);codegen.ml/codegen_deno.ml, Refs tracking: general effect-handler dispatch (post-CORE-02 residual) — silent arm-drop on 3 backends; DECISION: back-port loud failure now? #555).Class
residual (pinned)— silent-wrong value, interpreter only. Pinned by an executable test so it cannot regress unnoticed and will flip to failing the day it is fixed:test/e2e/fixtures/handle_resume_nontail.affinetest_resume_nontail_known_shallowintest/test_e2e.ml(asserts the wrong-but-knownVInt 5).Fix + why it's blocked
The correct fix is real delimited continuations = a CPS rewrite of
Interp.eval. Blocked: OCaml 4.14 has no native effect handlers, and the interpreter must stayjs_of_ocaml-compatible — so it's an architecture-level change against the full suite + the jsoo build. Needs owner steer before starting (seedocs/reports/HANDOFF-2026-06-17-soundness.adoc§7.1). Do not silently begin a CPS rewrite.Status
Canonical, test-anchored status:
docs/SOUNDNESS.adoc(the#555interpreter non-tail row). v1 readiness ledger: #563.Filed from the docs-soundness pass (PR #622).