Commit graph pcbjam/tests/kicad/quasimodal-strand.spec.ts
Author SHA1 Message Date
Gergő Törcsvári
48da418f34
design-b D3: fix the doc-19 hang — quasi-modals off the coroutine stack
THE BUG IS FIXED. tests/kicad/quasimodal-strand.spec.ts flips from a
test.fail() pin to a plain green regression test: 3/3 runs
closed=true dialogs=0 refused-resumes=0 (was closed=false dialogs=1
refused-resumes=1 on every run).

Mechanism: a quasi-modal's nested event loop parked on the TOOL
COROUTINE's stack, which suspends the fiber's body where the fiber layer
cannot see it — so the stale-fiber guard quarantined the fiber and then
refused its own resume, the dispatch guard was never released, and every
click after that was deferred forever. Bouncing the nested loop onto the
main stack leaves the coroutine suspended the legitimate way (a recorded
fiber swap), so nothing is quarantined and nothing is refused.

Layering, so this is not a pile of WASM ifdefs in KiCad:
- wx (3d37db3bf1) owns the POLICY and the hook; it must not know what a
  coroutine is.
- wasm/bindings/main_stack_runner.h is the only place that may know both
  sides: it finds the frame's TOOL_MANAGER and bounces via RunMainStack.
  Header-only and self-installing, so no build-script change; included by
  every editor's binding TU.
- KiCad gets ONE ifdef-free method (2c777efede), needed only because
  TOOL_STATE is opaque outside TOOL_MANAGER. libcontext and dialog_shim
  are untouched — an earlier draft edited both and was reverted.

This also reframes the remaining plan: the doc-19 class is closed WITHOUT
migrating tool coroutines onto scheduler contexts. Note it does not make
the wait a context yield — waits still park in place, just never on a
coroutine stack.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEHGiiXMShNXbBr7gSJ7iz
2026-08-10 10:14:17 +02:00
Gergő Törcsvári
73a239e0be
design-b D0: land the doc-19 strand as a deterministic red spec
Doc 20 D0 second deliverable (doc 21 §4). tests/kicad/quasimodal-strand.spec.ts
reproduces the Symbol Properties hang on demand, in two parts:

- "staging" (GREEN): double-click the fixture symbol → Symbol Properties
  opens → arm the parking timer (wasm/bindings/timer_park.h) WHILE the
  dialog is up. Because the opener's fiber park is open-ended, a timer
  firing now necessarily parks on top of it — the overlap is structural,
  not a won race. Asserts the dialog opened, the timer fired, its OK
  button is hittable, and the shim beaconed concurrent contexts. Keeps
  the red pin from rotting into vacuity, and fails loudly on its own.
- "doc-19 red" (test.fail()): clicks OK and asserts the desired end state
  — dialog closes, zero fiber-resume-refused beacons, wait books balanced
  (no unresolved nested/modal wait). Goes green at D3, when Playwright
  will report "expected to fail but passed" and the marker comes off.

Verified 6/6 consecutive full-file runs, identical outcome each time:
closed=false dialogs=1 refused-resumes=1 — the doc-19 mechanism exactly
(quarantined fiber's legitimate resume refused, dialog never closes).

Deliberately NOT asserted in staging: the timer park COMPLETING (whether
a park survives the aliasing is the disease under test) and sawParked (a
100ms sampler can miss a short park) — both are reported, not gated.

Retires tests/kicad/dialog-deadlock-probe.spec.ts: the 8/4 throwaway probe
that established the mechanism. This spec supersedes it and, unlike it, is
deterministic (the probe's 3 blind waitForTimeouts were the only
determinism-lint violations in the tree; the guard is now clean).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEHGiiXMShNXbBr7gSJ7iz
2026-08-10 10:14:15 +02:00