The SPL lane's copy of the deadlock found live in Timers and fixed there in 1.5.1 (#30), which flagged this file as the same latent pattern. In start(), if (missing !== BUILDING) skipped the retry while a build was in flight, and ensureCaptureBinary's onReady only fires on build success — so a failed build left the listener waiting forever on a callback that never comes ("Building the capture tool…" indefinitely), and a binary scp'd in from outside (the required path on AB, whose CLT cannot compile spl-capture) was never picked up without a module remount.
Same fix as #30: onReady stays as the fast path (successful build → immediate start), and the 30-second retry now stays armed in every not-ready state, so a failed build keeps re-checking and an externally supplied binary is found within half a minute.
Reproduced the production shape both ways with a swiftc that fails like AB's CLT: pre-fix, the build fails at 0 s, the binary is copied in at 3 s, and at 38 s it has never been spawned; post-fix, the 30 s retry spawns it (the binary's own "no input device matches" answer proves the real spawn path ran). spl-capture --selftest is unchanged against the IEC 61672 table (worst A error 3.14 dB @ 16 kHz/48 kHz, 0.59 dB @ 96 kHz — the documented bilinear-warping numbers).
Module 0.4.2 → 0.4.3, no shell changes. Stacked on #18 (0.4.2, the code running on AB and NA), so this PR's base is claude/spl-devices-without-binary: merge #18 first and then retarget this one to main by hand before merging it — Gitea does not retarget stacked PRs on its own here. Not deployed to AB or NA.
The SPL lane's copy of the deadlock found live in Timers and fixed there in 1.5.1 (#30), which flagged this file as the same latent pattern. In `start()`, `if (missing !== BUILDING)` skipped the retry while a build was in flight, and `ensureCaptureBinary`'s `onReady` only fires on build **success** — so a failed build left the listener waiting forever on a callback that never comes ("Building the capture tool…" indefinitely), and a binary scp'd in from outside (the required path on AB, whose CLT cannot compile spl-capture) was never picked up without a module remount.
Same fix as #30: `onReady` stays as the fast path (successful build → immediate start), and the 30-second retry now stays armed in **every** not-ready state, so a failed build keeps re-checking and an externally supplied binary is found within half a minute.
Reproduced the production shape both ways with a swiftc that fails like AB's CLT: pre-fix, the build fails at 0 s, the binary is copied in at 3 s, and at 38 s it has never been spawned; post-fix, the 30 s retry spawns it (the binary's own "no input device matches" answer proves the real spawn path ran). `spl-capture --selftest` is unchanged against the IEC 61672 table (worst A error 3.14 dB @ 16 kHz/48 kHz, 0.59 dB @ 96 kHz — the documented bilinear-warping numbers).
Module 0.4.2 → 0.4.3, no shell changes. **Stacked on #18** (0.4.2, the code running on AB and NA), so this PR's base is `claude/spl-devices-without-binary`: merge #18 first and then retarget this one to `main` by hand before merging it — Gitea does not retarget stacked PRs on its own here. Not deployed to AB or NA.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
michael
changed target branch from claude/spl-devices-without-binary to main2026-09-28 11:31:29 -04:00
Same deadlock the Timers module hit live on AB (fixed there in 1.5.1):
start() skipped scheduling its retry while a build was in flight, and
ensureCaptureBinary's onReady only fires on build SUCCESS. A failed
build therefore left the listener waiting forever on a callback that
never comes — "Building the capture tool…" indefinitely — and a binary
scp'd in from outside (the required path on AB, whose CLT cannot
compile) was never picked up without a module remount.
onReady stays as the fast path; the 30-second retry is now armed in
every not-ready state, so a failed build keeps re-checking and an
externally supplied binary is found within half a minute.
Reproduced pre-fix (build fails at 0s, binary copied in at 3s, still
untouched at 38s) and verified post-fix (retry at 30s spawns it).
spl-capture --selftest unchanged against the IEC 61672 table.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
michael
merged commit 92b98b6579 into main2026-09-28 11:31:51 -04:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The SPL lane's copy of the deadlock found live in Timers and fixed there in 1.5.1 (#30), which flagged this file as the same latent pattern. In
start(),if (missing !== BUILDING)skipped the retry while a build was in flight, andensureCaptureBinary'sonReadyonly fires on build success — so a failed build left the listener waiting forever on a callback that never comes ("Building the capture tool…" indefinitely), and a binary scp'd in from outside (the required path on AB, whose CLT cannot compile spl-capture) was never picked up without a module remount.Same fix as #30:
onReadystays as the fast path (successful build → immediate start), and the 30-second retry now stays armed in every not-ready state, so a failed build keeps re-checking and an externally supplied binary is found within half a minute.Reproduced the production shape both ways with a swiftc that fails like AB's CLT: pre-fix, the build fails at 0 s, the binary is copied in at 3 s, and at 38 s it has never been spawned; post-fix, the 30 s retry spawns it (the binary's own "no input device matches" answer proves the real spawn path ran).
spl-capture --selftestis unchanged against the IEC 61672 table (worst A error 3.14 dB @ 16 kHz/48 kHz, 0.59 dB @ 96 kHz — the documented bilinear-warping numbers).Module 0.4.2 → 0.4.3, no shell changes. Stacked on #18 (0.4.2, the code running on AB and NA), so this PR's base is
claude/spl-devices-without-binary: merge #18 first and then retarget this one tomainby hand before merging it — Gitea does not retarget stacked PRs on its own here. Not deployed to AB or NA.🤖 Generated with Claude Code