Problem
tests/unit/CoreStaticImports.test.ts > core static import closure (#1005) > ActorSystem never statically reaches fastify failed inside a full gated run on 2026-08-29 (Windows, bun 1.4.0, ACTOR_TS_SKIP_FLAKY_MNS=1 bun run test:coverage:gate):
(fail) core static import closure (#1005) > ActorSystem never statically reaches fastify [6723.89ms]
^ this test timed out after 5000ms.
It passed in a full gated run earlier the same day and passes standalone, so this is load-dependence, not a regression. The invariant it guards — that import { ActorSystem } never statically reaches Fastify — is the #1005 gate, and an intermittently red gate is one people learn to re-run.
The deadline is not declared anywhere in the file. Neither test() takes a third argument, and bunfig.toml raises nothing, so the 5 000 ms is bun's per-test default — the same number tests/unit/ci/AwaitConditionBudgets.test.ts pins as BUN_DEFAULT_TEST_TIMEOUT_MS and re-measures against a spawned child run.
What runs against that cap is staticClosure('src/ActorSystem.ts'), called inside the test body: a breadth-first walk that reads every statically reachable source file and runs three matchAll passes over each.
Evidence
Measured in this worktree at 7fb9ca08, bun 1.4.0, Windows 11:
| what |
cost |
the walk itself, src/ActorSystem.ts entry |
26.2 ms — 148 files, 383 queue pops, 1.28 MiB of source |
the walk itself, FastifyBackend.ts entry |
1.6 ms — 7 files, 69 KiB |
whole file, standalone bun test |
276 ms |
whole file, standalone bun test --coverage |
82 ms |
| the failing test, in a full gated run |
6 723.89 ms |
So the walk is not slow: 26 ms of real work was observed taking 6.7 s, ~250x, because the whole suite was running around it. The failure reports the machine, not the invariant.
That this is the runner's cap and not something in the test is measurable directly. A fixture with 6 s of synchronous work at module scope and the identical 6 s inside a test body, one bun test run:
(fail) the same work inside a test body is killed at 5000ms [6000.16ms]
^ this test timed out after 5000ms.
1 pass
1 fail
The module-scope half passes — bun applies no per-test timeout to module load.
Why not simply declare a bigger third argument
That is the remedy AwaitConditionBudgets prescribes, and it is the wrong one here. A third argument is the right fix when the number being protected is a failure budget — a wait that is supposed to expire and print a label. This walk has no budget; it is bounded work that always completes. Any literal cap would be one more encoded assumption about machine speed, which is exactly the shared defect #1376 is open to remove — and it would have to be picked against a 250x observed spread.
The three sibling repo-file guards already do the right thing: tests/unit/ci/AwaitConditionBudgets.test.ts, tests/unit/ci/WorkflowHygiene.test.ts and tests/unit/config/NoDeadConfigKeys.test.ts all scan the tree at module scope and keep their test() bodies to assertions. CoreStaticImports.test.ts is the odd one out.
Related
Noted while reading, not fixed here: tests/unit/TreeShaking.test.ts runs Bun.build in three test bodies with no explicit timeout, which is the same shape and considerably more expensive per call. It has not been observed failing; recording it so it is not rediscovered from scratch.
Acceptance criteria
Problem
tests/unit/CoreStaticImports.test.ts > core static import closure (#1005) > ActorSystem never statically reaches fastifyfailed inside a full gated run on 2026-08-29 (Windows, bun 1.4.0,ACTOR_TS_SKIP_FLAKY_MNS=1 bun run test:coverage:gate):It passed in a full gated run earlier the same day and passes standalone, so this is load-dependence, not a regression. The invariant it guards — that
import { ActorSystem }never statically reaches Fastify — is the #1005 gate, and an intermittently red gate is one people learn to re-run.The deadline is not declared anywhere in the file. Neither
test()takes a third argument, andbunfig.tomlraises nothing, so the 5 000 ms is bun's per-test default — the same numbertests/unit/ci/AwaitConditionBudgets.test.tspins asBUN_DEFAULT_TEST_TIMEOUT_MSand re-measures against a spawned child run.What runs against that cap is
staticClosure('src/ActorSystem.ts'), called inside the test body: a breadth-first walk that reads every statically reachable source file and runs threematchAllpasses over each.Evidence
Measured in this worktree at
7fb9ca08, bun 1.4.0, Windows 11:src/ActorSystem.tsentryFastifyBackend.tsentrybun testbun test --coverageSo the walk is not slow: 26 ms of real work was observed taking 6.7 s, ~250x, because the whole suite was running around it. The failure reports the machine, not the invariant.
That this is the runner's cap and not something in the test is measurable directly. A fixture with 6 s of synchronous work at module scope and the identical 6 s inside a test body, one
bun testrun:The module-scope half passes — bun applies no per-test timeout to module load.
Why not simply declare a bigger third argument
That is the remedy
AwaitConditionBudgetsprescribes, and it is the wrong one here. A third argument is the right fix when the number being protected is a failure budget — a wait that is supposed to expire and print a label. This walk has no budget; it is bounded work that always completes. Any literal cap would be one more encoded assumption about machine speed, which is exactly the shared defect #1376 is open to remove — and it would have to be picked against a 250x observed spread.The three sibling repo-file guards already do the right thing:
tests/unit/ci/AwaitConditionBudgets.test.ts,tests/unit/ci/WorkflowHygiene.test.tsandtests/unit/config/NoDeadConfigKeys.test.tsall scan the tree at module scope and keep theirtest()bodies to assertions.CoreStaticImports.test.tsis the odd one out.Related
tests/util/TimerTolerance.tstoday offers onlyTIMER_QUANTUM_MSandminimumElapsedMs(), both lower bounds for measured elapsed time. Nothing scales an upper bound.Noted while reading, not fixed here:
tests/unit/TreeShaking.test.tsrunsBun.buildin three test bodies with no explicit timeout, which is the same shape and considerably more expensive per call. It has not been observed failing; recording it so it is not rediscovered from scratch.Acceptance criteria
ActorSystemmust still be proven never to statically reachFastifyBackend.tsor a barefastify, and the canary must still prove the walker is not blind.ACTOR_TS_SKIP_FLAKY_MNS=1 bun run test:coverage:gateand underbun run test:stressscoped to the file.