Problem
scripts/run-tests.mjs discovers every Node test file and passes all of them to one invocation:
node --test --experimental-strip-types <all .test.ts files>
Node executes test files concurrently by default. The background-terminals manager tests are different from ordinary unit tests: on Windows they create real process trees, invoke and await taskkill, observe settlement callbacks, poll descendant liveness, and clean up OS resources. When other test files are creating or terminating processes at the same time, Windows scheduling and process-tree cleanup become timing-sensitive.
This produces intermittent failures around the same 3.3-3.8 second teardown window even though the affected tests are stable in isolation.
Reproduction evidence
Observed on Windows with Node v24.12.0 and Bun 1.4.0:
- Each affected test passes when run alone.
- The three affected tests pass when run together.
- The entire
tests/extensions/background-terminals directory passes with --test-concurrency=1.
- An unmodified
bun run test reproduced the failure on the first run:
kill settles a never-exiting process... passed in about 3.32 s.
concurrent overlapping multi-id kills... failed in about 3.60 s.
taskkill terminates a Windows descendant process tree passed in about 3.62 s.
- The exact three-test selection then passed 3/3 at about 3.25-3.30 s each.
- Serial execution of the complete
background-terminals directory passed: 89 passed, 4 skipped, 0 failed.
The failures only appear under full-suite cross-file concurrency. This rules out .gitattributes, line-ending policy, and the assertions in those three tests as the primary cause.
Why this harms the whole repository
This is a test-infrastructure reliability problem, not a local inconvenience:
- False CI failures block unrelated changes. Any contributor can receive a red build even when their change does not touch background terminals or process management.
- Flakes hide real regressions. Once rerunning CI becomes normal, developers cannot tell whether a process-lifecycle failure is infrastructure noise or a genuine runtime bug.
- Debugging time is wasted in the wrong layer. The failure points at settlement, kill, or descendant assertions, encouraging investigation of production code and test assertions even though the trigger is suite-level scheduling.
- Windows contributors pay a disproportionate cost. The affected path uses real Windows process-tree semantics and
taskkill /T, so the default full-suite topology makes their development loop less trustworthy.
- Release and prepublish validation become unreliable.
prepublishOnly depends on bun run test; an intermittent infrastructure failure can delay or discourage releases.
- Failed runs can take much longer to settle. In one reproduction the Node test process stopped producing output after the failure and required interruption, increasing the cost beyond a simple retry.
A green test suite must mean the code passed, and a red suite must provide actionable evidence. The current behavior violates that contract.
Proposed direction
Keep ordinary Node test files parallel, but isolate the real-process Windows tests from cross-file contention. Possible implementations include:
- Run the
background-terminals real-process test group in a separate serial Node invocation, while keeping the rest of the suite parallel.
- Add a Windows-specific concurrency policy in
scripts/run-tests.mjs if a narrower grouping is not practical.
- Split OS-process integration tests from fast unit tests so the runner can apply concurrency deliberately instead of globally.
The narrowest option that preserves fast parallel execution for unrelated tests is preferable. The fix should live in test infrastructure rather than weakening teardown bounds or adding retries to the assertions, because those changes would mask the scheduling problem.
Acceptance criteria
- Repeated full
bun run test runs on Windows do not intermittently fail the affected process-lifecycle tests.
- The real-process
background-terminals tests do not overlap with unrelated Node test files in a way that changes their settlement or descendant-cleanup timing.
- Existing teardown bounds and behavioral assertions remain intact.
- Non-Windows and ordinary unit-test parallelism is preserved where practical.
- The test-runner policy is covered by a focused test or documented clearly enough to prevent accidental regression.
Expected result
After this is fixed, contributors should get deterministic local and CI results, process-lifecycle failures should become trustworthy signals again, Windows validation should stop penalizing unrelated changes, and releases should no longer depend on retrying a flaky full-suite run. The repository keeps the speed benefit of parallel tests without sacrificing correctness for the small subset that exercises real OS process trees.
Problem
scripts/run-tests.mjsdiscovers every Node test file and passes all of them to one invocation:Node executes test files concurrently by default. The
background-terminalsmanager tests are different from ordinary unit tests: on Windows they create real process trees, invoke and awaittaskkill, observe settlement callbacks, poll descendant liveness, and clean up OS resources. When other test files are creating or terminating processes at the same time, Windows scheduling and process-tree cleanup become timing-sensitive.This produces intermittent failures around the same 3.3-3.8 second teardown window even though the affected tests are stable in isolation.
Reproduction evidence
Observed on Windows with Node v24.12.0 and Bun 1.4.0:
tests/extensions/background-terminalsdirectory passes with--test-concurrency=1.bun run testreproduced the failure on the first run:kill settles a never-exiting process...passed in about 3.32 s.concurrent overlapping multi-id kills...failed in about 3.60 s.taskkill terminates a Windows descendant process treepassed in about 3.62 s.background-terminalsdirectory passed: 89 passed, 4 skipped, 0 failed.The failures only appear under full-suite cross-file concurrency. This rules out
.gitattributes, line-ending policy, and the assertions in those three tests as the primary cause.Why this harms the whole repository
This is a test-infrastructure reliability problem, not a local inconvenience:
taskkill /T, so the default full-suite topology makes their development loop less trustworthy.prepublishOnlydepends onbun run test; an intermittent infrastructure failure can delay or discourage releases.A green test suite must mean the code passed, and a red suite must provide actionable evidence. The current behavior violates that contract.
Proposed direction
Keep ordinary Node test files parallel, but isolate the real-process Windows tests from cross-file contention. Possible implementations include:
background-terminalsreal-process test group in a separate serial Node invocation, while keeping the rest of the suite parallel.scripts/run-tests.mjsif a narrower grouping is not practical.The narrowest option that preserves fast parallel execution for unrelated tests is preferable. The fix should live in test infrastructure rather than weakening teardown bounds or adding retries to the assertions, because those changes would mask the scheduling problem.
Acceptance criteria
bun run testruns on Windows do not intermittently fail the affected process-lifecycle tests.background-terminalstests do not overlap with unrelated Node test files in a way that changes their settlement or descendant-cleanup timing.Expected result
After this is fixed, contributors should get deterministic local and CI results, process-lifecycle failures should become trustworthy signals again, Windows validation should stop penalizing unrelated changes, and releases should no longer depend on retrying a flaky full-suite run. The repository keeps the speed benefit of parallel tests without sacrificing correctness for the small subset that exercises real OS process trees.