gap-suite (2) is red on main, and the regression it reports is not a Perry defect —
it is the Node.js oracle timing out on a fixture whose own minimum runtime exceeds the
suite's per-test cap. Filing so the fixture's author can pick a fix; I have deliberately not
changed it.
What CI reports
SKIP test_gap_9676_stdin_unref_ref_keeps_reader (Node.js TIMEOUT (killed after 10s))
[82/233] (00:12:51) test_gap_9676_stdin_unref_ref_keeps_reader … NODE_FAIL
REGRESSIONS — these were expected to pass:
- test_gap_9676_stdin_unref_ref_keeps_reader: pass -> node_fail
Why it cannot pass
test-files/test_gap_9676_stdin_unref_ref_keeps_reader.ts drives four child roles
sequentially:
const roles = ["unref-ref", "unref-ref-churn", "unref-only", "pause-resume"];
...
for (const r of roles) await run(r);
and each role's run holds open a hardcoded timer before it finishes:
// Late enough that the churn role has finished collecting first.
setTimeout(() => {
...
}, 2500);
That is 4 x 2500 ms = 10 s of intentional delay alone, before any process-spawn
overhead — against run_parity_tests.sh:58:
PERRY_RUN_TIMEOUT="${PERRY_RUN_TIMEOUT:-10}"
a single uniform 10-second wall-clock budget applied to every gap test. So the fixture
cannot fit, and the harness kills Node first — which is why the result is NODE_FAIL
rather than an output mismatch. It has failed identically on every completed CI run since
the fixture was introduced.
Introduced by 6157e569b — "fix(runtime): stop process.stdin lifecycle calls from killing
input for good (#9676)" (2026-09-04 09:19), landed via merge train #9694. The runtime fix
itself is not in question here; only the fixture's runtime budget is.
Two options, author's call
- Raise the cap for this fixture — the delays look load-bearing for the race being
pinned (the comment says the timer is "late enough that the churn role has finished
collecting first"), so if they must stay, the suite needs a per-test override rather
than the single PERRY_RUN_TIMEOUT default.
- Shorten the sleeps — e.g. 2500 ms -> 800 ms, if the ordering they enforce holds at a
smaller margin.
I did not pick between these because the delays encode timing assumptions about the
stdin-reader race that the fixture exists to pin.
Note for triage
Two other tests print FAIL … PARITY_FAIL in the same job —
test_gap_perfhooks_3088_3008_3010_3011 and test_gap_prop_plan_cache_invalidation — but
both are already recorded in test-parity/gap_snapshot.json, so scripts/gap_snapshot.py
does not count them as regressions and they do not fail the job. They are informational
noise; the fixture above is the only thing making gap-suite (2) red.
https://claude.ai/code/session_01YPfnmWZmSpSWpmnoXvH8z2
gap-suite (2)is red onmain, and the regression it reports is not a Perry defect —it is the Node.js oracle timing out on a fixture whose own minimum runtime exceeds the
suite's per-test cap. Filing so the fixture's author can pick a fix; I have deliberately not
changed it.
What CI reports
Why it cannot pass
test-files/test_gap_9676_stdin_unref_ref_keeps_reader.tsdrives four child rolessequentially:
and each role's run holds open a hardcoded timer before it finishes:
That is 4 x 2500 ms = 10 s of intentional delay alone, before any process-spawn
overhead — against
run_parity_tests.sh:58:PERRY_RUN_TIMEOUT="${PERRY_RUN_TIMEOUT:-10}"a single uniform 10-second wall-clock budget applied to every gap test. So the fixture
cannot fit, and the harness kills Node first — which is why the result is
NODE_FAILrather than an output mismatch. It has failed identically on every completed CI run since
the fixture was introduced.
Introduced by
6157e569b— "fix(runtime): stop process.stdin lifecycle calls from killinginput for good (#9676)" (2026-09-04 09:19), landed via merge train #9694. The runtime fix
itself is not in question here; only the fixture's runtime budget is.
Two options, author's call
pinned (the comment says the timer is "late enough that the churn role has finished
collecting first"), so if they must stay, the suite needs a per-test override rather
than the single
PERRY_RUN_TIMEOUTdefault.smaller margin.
I did not pick between these because the delays encode timing assumptions about the
stdin-reader race that the fixture exists to pin.
Note for triage
Two other tests print
FAIL … PARITY_FAILin the same job —test_gap_perfhooks_3088_3008_3010_3011andtest_gap_prop_plan_cache_invalidation— butboth are already recorded in
test-parity/gap_snapshot.json, soscripts/gap_snapshot.pydoes not count them as regressions and they do not fail the job. They are informational
noise; the fixture above is the only thing making
gap-suite (2)red.https://claude.ai/code/session_01YPfnmWZmSpSWpmnoXvH8z2