v0.1.21 still trapped with ZERO jump-refused beacons: the fatal swap PASSED
the C++ swap_suspended guard. Mechanism (async/16 round 2): a fresh JS entry
executing while g_current_context still points at a parked fiber gets
attributed to that fiber — fiber_swap writes a fresh, valid-LOOKING foreign
suspension into the parked fiber's struct and re-marks the flag. The flag
lies; the resume rewinds garbage.
This guard tracks truth at the emscripten-fiber layer (handlesleep.js wraps
Fibers.finishContextSwitch):
- valid suspensions = real swap-outs (currData == oldFiber+20 when the
trampoline runs), consumed on rewind;
- internally-parked = an entered slice that ended in a handleSleep park
(currData set, no nextFiber) — quarantined until a GENUINE swap-out,
where genuine means the fiber's pending sleep has resolved
(__pendingSleepContexts), so a laundering write cannot lift it;
- entering a quarantined or suspension-less fiber is REFUSED
([wx-asyncify] fiber-resume-refused, ghost contract).
The ROOT context is exempt from quarantine and refusal: its rewound
continuation runs the whole main loop, whose routine yield park says nothing
about a fiber body — the first build of this guard quarantined main off that
signal and starved every coroutine return (19 collab e2e reds, empty
results). Root = the old side of the first switch ever.
.ci-cache-epoch 2→3: the wasm output cache key omits scripts/**.
Red/green: fiber-resume-park.spec.ts scenario 2 (laundered resume → exactly
one refusal beacon, both coroutines complete); full fiber-heavy sweep green
(21 passed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019SE4o46Lnq3hF574FFq8x4