Code of Conduct
Existing issues
What happened?
tracker-columns-tests.mjs is registered at test-all.mjs:368 with no timeoutMs, so it runs on the shared DEFAULT_SCRIPT_TIMEOUT_MS (30_000, tests/helpers.mjs:37). On windows-latest it crosses that line often enough to redden a PR that has nothing to do with it:
❌ tracker-columns-tests.mjs crashed (exit null, signal SIGTERM)
stdout: PASS merge into 10-col tracker exits 0
It had already passed its first case, so it was running correctly and was killed for time. The log entry before it lands at 19:24:47.595 and the kill at 19:25:17.611, exactly 30.0s.
That happened on #4008, a three-file change under web/ that this suite does not touch. ubuntu-latest and macos-latest passed on the same commit, as did CodeQL, cv-visual, dependency-review, the no-user-data guard, and web typecheck plus build. Retriggering with byte-identical content turned the leg green, which is what rules out a real failure.
The measurements
Elapsed on windows-latest, taken as the delta between the previous suite's runs OK line and this suite's, so it includes this suite's own setup:
| Run |
Branch |
Elapsed |
| 34154514034 |
dev/4004-tool-claim-prose |
10.90s |
| 34148068976 |
feat/personio-tenant-pin |
11.71s |
| 34157015801 |
dev/4003 (the retrigger) |
11.88s |
| 34154539119 |
fix/analyze-patterns-flag-validation |
12.01s |
| 34154934619 |
feat/verdict-lead-block |
12.39s |
| 34147993447 |
feat/bwi-provider |
13.80s |
| 34155386224 |
dev/4003 (the kill) |
> 30.0s, SIGTERM |
Six runs in a 10.9s to 13.8s band, then one that ran past 30s. Locally on an idle macOS box it is 4.1s to 4.4s over three runs. The suite spawns five node subprocesses (merge-tracker.mjs, verify-pipeline.mjs) against throwaway mkdtempSync trees, and Windows process creation on a loaded 2-core runner is where the spread comes from.
It is also the slowest suite in that whole section on Windows. Slowest ten on the green run:
11.88s tracker-columns-tests.mjs
11.64s tracker-writer-lock-tests.mjs
8.70s set-status-tests.mjs
7.61s agent-inbox-tests.mjs
3.79s update-system.mjs check
3.48s followup-seed-tests.mjs
1.17s updater-migration-tests.mjs
0.74s paste-reply-tests.mjs
0.40s img-to-pdf.mjs --self-test
0.39s archive-posting.mjs --help
The suite immediately below it, at essentially the same cost, is tracker-writer-lock-tests.mjs, which already carries timeoutMs: 180_000 at test-all.mjs:387 for exactly this symptom (#2906). Two suites, 11.88s and 11.64s on the same run, one budgeted at 180s and the other at 30s. Nothing about the two costs justifies the difference; the second one just got caught first.
Why the creep warning could not catch it
SLOW_SCRIPT_WARN_FRACTION is 0.75 (test-all.mjs:310), so the "close to being killed for time" warning fires above 22.5s. At a typical 12s this suite never warns. It is not creeping toward the ceiling, it is spiking past it, so it goes from completely silent to killed with nothing in between. That is the gap the warning was built to close, and this shape slips through it.
Expected behavior
The same treatment its list-neighbour already has: timeoutMs: 180_000 on test-all.mjs:368.
This keeps the policy stated at test-all.mjs:382-386 intact. The budget is raised for the outlier rather than in run()'s default, so every other script keeps the 30s bound and a new script that starts taking half a minute still fails loudly. Applied consistently, that policy names two outliers rather than one.
I am deliberately not touching set-status-tests.mjs (8.70s) or agent-inbox-tests.mjs (7.61s). Neither has ever been killed, and both sit far enough below the line that raising them would be pre-emptive rather than evidenced.
Interaction with #3736, worth deciding before this lands
#3736 proposes moving five root *-tests.mjs suites into tests/, and tracker-columns-tests.mjs is one of the five. It also records why tracker-writer-lock-tests.mjs stays: the discovery path has no timeout mechanism, so moving a suite that carries a tuned budget "trades a tuned budget for none".
Giving tracker-columns-tests.mjs a budget puts it in exactly that position, so #3736 would become four that can move rather than five, unless the per-suite budget in runDiscovered that #3736 itself suggests lands first.
Either way the 30s budget is wrong today and is reddening unrelated PRs today, so I do not think this should wait on that. But it is the author's call which order they want, and I would rather raise it than have it turn up after the fact.
CLI tool
Claude Code
OS and Node.js version
CI: windows-latest / Node 24. Local: macOS 26 / Node 26.
Output of npm run doctor
Not applicable: this is a CI harness budget, reproduced from GitHub Actions job logs rather than a local install.
Code of Conduct
Existing issues
What happened?
tracker-columns-tests.mjsis registered attest-all.mjs:368with notimeoutMs, so it runs on the sharedDEFAULT_SCRIPT_TIMEOUT_MS(30_000,tests/helpers.mjs:37). Onwindows-latestit crosses that line often enough to redden a PR that has nothing to do with it:It had already passed its first case, so it was running correctly and was killed for time. The log entry before it lands at
19:24:47.595and the kill at19:25:17.611, exactly 30.0s.That happened on #4008, a three-file change under
web/that this suite does not touch.ubuntu-latestandmacos-latestpassed on the same commit, as did CodeQL, cv-visual, dependency-review, the no-user-data guard, and web typecheck plus build. Retriggering with byte-identical content turned the leg green, which is what rules out a real failure.The measurements
Elapsed on
windows-latest, taken as the delta between the previous suite'sruns OKline and this suite's, so it includes this suite's own setup:Six runs in a 10.9s to 13.8s band, then one that ran past 30s. Locally on an idle macOS box it is 4.1s to 4.4s over three runs. The suite spawns five node subprocesses (
merge-tracker.mjs,verify-pipeline.mjs) against throwawaymkdtempSynctrees, and Windows process creation on a loaded 2-core runner is where the spread comes from.It is also the slowest suite in that whole section on Windows. Slowest ten on the green run:
The suite immediately below it, at essentially the same cost, is
tracker-writer-lock-tests.mjs, which already carriestimeoutMs: 180_000attest-all.mjs:387for exactly this symptom (#2906). Two suites, 11.88s and 11.64s on the same run, one budgeted at 180s and the other at 30s. Nothing about the two costs justifies the difference; the second one just got caught first.Why the creep warning could not catch it
SLOW_SCRIPT_WARN_FRACTIONis 0.75 (test-all.mjs:310), so the "close to being killed for time" warning fires above 22.5s. At a typical 12s this suite never warns. It is not creeping toward the ceiling, it is spiking past it, so it goes from completely silent to killed with nothing in between. That is the gap the warning was built to close, and this shape slips through it.Expected behavior
The same treatment its list-neighbour already has:
timeoutMs: 180_000ontest-all.mjs:368.This keeps the policy stated at
test-all.mjs:382-386intact. The budget is raised for the outlier rather than inrun()'s default, so every other script keeps the 30s bound and a new script that starts taking half a minute still fails loudly. Applied consistently, that policy names two outliers rather than one.I am deliberately not touching
set-status-tests.mjs(8.70s) oragent-inbox-tests.mjs(7.61s). Neither has ever been killed, and both sit far enough below the line that raising them would be pre-emptive rather than evidenced.Interaction with #3736, worth deciding before this lands
#3736 proposes moving five root
*-tests.mjssuites intotests/, andtracker-columns-tests.mjsis one of the five. It also records whytracker-writer-lock-tests.mjsstays: the discovery path has no timeout mechanism, so moving a suite that carries a tuned budget "trades a tuned budget for none".Giving
tracker-columns-tests.mjsa budget puts it in exactly that position, so #3736 would become four that can move rather than five, unless the per-suite budget inrunDiscoveredthat #3736 itself suggests lands first.Either way the 30s budget is wrong today and is reddening unrelated PRs today, so I do not think this should wait on that. But it is the author's call which order they want, and I would rather raise it than have it turn up after the fact.
CLI tool
Claude Code
OS and Node.js version
CI: windows-latest / Node 24. Local: macOS 26 / Node 26.
Output of npm run doctor
Not applicable: this is a CI harness budget, reproduced from GitHub Actions job logs rather than a local install.