test(vitest): unblock subprocess MCP tests on Node >= 25 dev machines (#478)#479
Conversation
…colbymchenry#478) Vitest already inherits process.env into every spawned `codegraph serve --mcp` child, but on Node >= 25 the CLI's hard-block (src/bin/codegraph.ts) kills the child before it can respond. Set CODEGRAPH_ALLOW_UNSAFE_NODE=1 via test.env so the test suite is green regardless of the contributor's Node version; the runtime guard itself is unchanged for end users.
colbymchenry
left a comment
There was a problem hiding this comment.
Nice work — diagnosis is precise (the process.execPath spawn pattern + the >=25 hard-block) and the fix is the right pinch point: vitest's test.env propagates into every spawned child, both the ones that default-inherit process.env and the ones that spread {...process.env, ...}, so a single line in the config covers all four files. Runtime guard stays intact for end users (verified node dist/bin/codegraph.js status still banners + exits 1 on a simulated >=25 box).
Validated locally end-to-end by temporarily lowering the bin's nodeMajor >= 25 to >= 22 on a Node 22 dev box, reproducing the exact Timed out. Messages so far: [] symptom from #478, then confirming the env addition flips all 5 probed tests green. Reverted the probe; no regression with the gate at 25. Thanks for the clean writeup and the n=0 → n=13 numbers!
…colbymchenry#478) (colbymchenry#479) Vitest already inherits process.env into every spawned `codegraph serve --mcp` child, but on Node >= 25 the CLI's hard-block (src/bin/codegraph.ts) kills the child before it can respond. Set CODEGRAPH_ALLOW_UNSAFE_NODE=1 via test.env so the test suite is green regardless of the contributor's Node version; the runtime guard itself is unchanged for end users.
Summary
Closes #478.
On a developer machine running Node.js 25+,
npm testagainstmainreports 13 failures across 4 files (mcp-daemon, mcp-initialize, mcp-ppid-watchdog, mcp-roots). Every failure is a subprocess test: each one spawnsdist/bin/codegraph.js serve --mcpwithprocess.execPathand waits for a JSON-RPC response. On Node ≥25 the spawned child hits the CLI's hard-block (src/bin/codegraph.ts:65) and exits before responding, sowaitForMessagetimes out.The CLI's block exists to keep end users off Node 25's V8 turboshaft WASM JIT Zone bug (#81). Test scenarios don't actually exercise that path — they spin up short-lived servers, exchange a few JSON-RPC frames, and tear down — so the right thing is to opt the test runner's spawned children out of the block, while leaving the runtime guard intact for everyone else.
Change
One added field in
vitest.config.ts:Vitest puts this into
process.envfor the test process. Every affected test either (a) spawns withoutenv(default = inheritprocess.env) or (b) spawns withenv: { ...process.env, ... }, so the variable flows into the child unchanged. No test file or production source is modified.Validation
On Node 26.0.0 (this dev box), before:
After:
The runtime guard is still enforced when
codegraphis invoked directly —node dist/bin/codegraph.js statuson Node 26 still prints the banner and exits with code 1.Notes for review
node-version-check.test.tsunit tests (which assert the banner content) are unrelated and continue to pass — they call the banner builders directly, not via spawn.CLAUDE.md's "Known pre-existing Windows failures" note explains the Windows failure mode formcp-initialize.test.ts/mcp-roots.test.ts(EPERM in afterEach). The macOS/Linux Node ≥25 failure mode is different (timeouts on the parent side, child exits 1 on startup), and is now addressed by this PR — happy to add a follow-up doc tweak to CLAUDE.md if useful.Test plan
npm testgreen on Node 26.0.0node dist/bin/codegraph.js statusstill prints the unsupported-version banner and exits 1 on Node 26.0.0 (guard intact for end users)