B-546T-cli-spawn-tests-flake-under-load
sdlc quality run --config sdlc.yaml is the release gate, and its test
command flakes. Measured across three consecutive full-suite runs of
bun test solutions/ontological scripts:
| Run | Result |
|---|---|
| 1 | config CLI parity > set then get round-trips via the CLI failed (11321ms) |
| 2 | entities-audit evals > frontmatter-error failed (5359ms) |
| 3 | 2331 pass, 0 fail |
Neither test reproduces in isolation. bun test of both config test files
alone: 31 pass, 0 fail in 3.1s. The same tests take 5-11s inside the full
suite, so contention is the differentiator, not input.
Both are slow subprocess-spawning tests reached through
lib/tests/_cli_harness.ts#runCli, which under NODE_ENV=test routes to
easy-git’s runViaChildRedirect. Both failed in the shape a failed spawn
produces: a short-or-empty capture at exit 1. For frontmatter-error the
expected exit IS 1, so only the substring assertion caught it; for the
config test the exit assertion caught it.
That door was hardened in fix(easy-git): a failed capture must say so, not look like exit 1 — proc.error now reaches stderr and a missing redirect
file reads as empty instead of throwing ENOENT. That makes the failure
legible. It does not prove the cause, and the flake is not confirmed fixed:
no run since has reproduced it, which is also true of runs before the
change.
Next step is to re-measure with the hardening in place. If a flake recurs, stderr should now name the spawn error. If it names EAGAIN or a similar resource failure, the fix is to bound test-suite spawn concurrency rather than to touch either test.
Context: the release workflow has failed 8 of its last 10 runs on main
going back to 2026-07-14, so this gate has not been giving a reliable
signal for a month. Two of those failures were deterministic corpus drift,
fixed separately; this flake is the remaining known cause.