The runtime is JSPI-only; this removes everything that still pretended
otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove
the inventory; every deletion verified by grep closure + full gates.
Broken-right-now fixes:
- deploy-staging.yml passed the retired opt_level input — the workflow
could not even start. Removed.
- env.sh carried dead exports with a live -sASYNCIFY=1 inside
(WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the
WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason.
- docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone.
Dead weight removed:
- binaryen submodule (nothing builds or invokes it), wasm-opt-bench
workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines
of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess
scaffolding (existed to parallelize the deleted wasm-opt phase; the
postprocess is a seconds-long node script and now runs inline),
build-monitor's dead asyncify rows, sched-context orphan build
output, dead .gitignore entries, the .jspi-assets spike dir (the two
wf-result research JSONs moved to docs/features/async/migration-evidence/).
- bindings: fiber_park.h + its 12 embind registrations (broken-if-
called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route,
main_stack_runner.h + 5 includes, the always-null context-sleep weak
hook in nanosleep_yield.c.
- shim: the backend field (installed-flag idempotency instead),
noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the
WasmTool fallback and string-dump normalize branch).
- web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts
(gerber-demo keeps it: it loads the deployed CDN release, which
predates emscripten 6 — noted inline).
Conditionals: all 'backend === jspi' checks reduced to scheduler-
presence checks; races_quiescent re-keyed from Asyncify.state (vacuous)
to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive,
which is the probing activation's own window by definition).
Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→
JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS,
kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests),
collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→
wasmTrapSignatures (lists byte-identical).
Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused
asserts re-keyed to live JSPI beacons; eeschema-load's failure message
no longer sends the developer to a deleted script; wait-beacons' dead
families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is
unconstructible); the embind test.fail re-gated with the JSPI reason
(plain embind invokers cannot suspend — verified still failing);
lint-determinism now scans tests/jspi (166 files clean);
eeschema-collab local-move gated to chromium (~50% flaky on FF even
solo; pcbnew twin covers both engines).
Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md
describes the single-phase build; docs/features/async/README.md
banner-marked historical and repointed at the NEW
23-jspi-runtime.md (current architecture: export census, turnstile,
libcontext ownership + refusal contract, embind call shapes, the
em-pthread service-wrapper trick, exception policy, known gaps).
Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the
quiescence-probe fix; the 3 other reds were verified contention flakes
solo-green or the documented FF gate), web 76/0, jspi 18/18 both
engines, vitest 295/295 + 17/17, all lints green, live-app census
clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
Doc 20 D-1 (legacy runtime deletion), first slice: races_test_noheal /
races_test_nosleepfix pinned behavior of the legacy handlesleep shim,
which is being deleted — the pins now assert properties of a runtime
that no longer exists. Drops the two Makefile.wasm link+inject variants
(SHIM_DISABLE_TRAMPOLINE_HEAL / SHIM_DISABLE_HANDLESLEEP), the
shim-redundancy pin specs in asyncify-races.spec.ts, and resolves the
tests/README.md open task. The green battery still runs every scenario
against the scheduler glue.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEHGiiXMShNXbBr7gSJ7iz
Replace the legacy Emscripten JS-exceptions model with native wasm-EH (legacy
encoding) across the whole build, keeping Asyncify coroutines working via a
from-source Binaryen --hoist-cpp-catches pre-pass. Net result: native-EH is the
only build mode, the 3D viewer is on by default, and pcbnew shrinks substantially.
Highlights:
- Binaryen submodule everywhere + --hoist-cpp-catches integration in apply-asyncify;
post-link Asyncify covers every app wasm (not just standalone test wasm).
- Build deps (incl. OpenCASCADE without OCC_CONVERT_SIGNALS) and all KiCad apps
with -fwasm-exceptions; emscripten_sleep added to the post-link asyncify-imports.
- libcontext fiber entry wired under native exceptions; while-loop main loop +
currData shim injected into all wx apps.
- Native-EH collab apply fixed: DEBUG-define the embind TU + match all out-of-CMake
C++ TUs' ABI flags to the core, fixing the vtable-layout skew / mis-dispatch.
- 3D viewer enabled by default (real raytracer linked, not the stub).
- Retire the EH-spike scaffolding; flip the asyncify-races ablation pins to
shim-redundancy pins (native-EH stays clean with the legacy shims ablated).
- Fix the asyncify-races quiescence check to not require Asyncify.currData==0:
under the native-EH per-frame-yield top loop the main stack is asyncify-suspended
every frame, so currData legitimately churns (a freed-but-not-yet-nulled buffer,
not a leak). Refresh the pcbnew toolbar screenshot baseline for the new kicad.
- CI: drop the obsolete binaryen_version input/env (the build uses the binaryen
submodule fork's wasm-opt, not a version download); key the wasm-output cache on
the binaryen submodule SHA instead.
Bumps the wxwidgets + binaryen submodules to their squashed feature commits.
Validated green: all 7 apps native-EH (real 3D in pcbnew); KiCad e2e 63/63
Firefox + Chromium (3D viewer renders); wx 336; coroutine 34/34 both engines;
asyncify 7/7 both engines.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The asyncify single-slot work, executed red-green (full ledger:
docs/features/asyncify-arbiter/redgreen.md; decisions record:
docs/features/async/07-decisions-and-outcome.md):
- tests/apps/standalone/asyncify-races/ + tests/asyncify/ + dedicated
playwright config: 8 scenarios reproducing the KiCad asyncify failure
family with the kicad-faithful startup topology (pre-park fiber swap →
park throw through the live trampoline). Built in 3 variants; the
SHIM_DISABLE_TRAMPOLINE_HEAL / SHIM_DISABLE_HANDLESLEEP ablation builds
keep the historical hang and index-out-of-bounds crash reproducible
forever (mutation-style pins for the existing shims).
- scripts/common/shims/handlesleep.js: catch the "unwind" park sentinel
in the wakeUp path — when main's last pre-park suspension was a sleep,
the main-loop park throw escaped through that sleep's promise reaction
as an uncaught rejection (the calculator/gerbview console errors).
- scripts/common/inject-dyncall-shims.sh: SHIM_DISABLE_* ablation knobs.
- Spec tightening (the acceptance bar): 'uncaught exception: unwind'
tolerance DELETED from pcbnew/eeschema specs; load-pcb gained a hard
clean-console gate over 5 asyncify corruption signatures.
- wxwidgets pointer bump: modal LIFO resolvers, pump resolve-on-error,
sync clipboard IsSupported (014f67e6c1).
Final state: asyncify suite 7/7, wx e2e 291/292 (1 skip), KiCad e2e 40
passed / 2 skipped with ZERO corruption signatures in any log across all
six apps.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>