Problem class: node-vitest-ci-startup-timing-pidfile-existence-race
Solution written to ~/SOLUTION-pidfile-existence-race.md. Both the race and the fix were empirically verified.
Problem class: node-vitest-ci-startup-timing-pidfile-existence-race
Flaky CI failure at:
await waitForHealth(baseUrl);
expect(fs.existsSync(pidFile)).toBe(true); // flaky
The test samples pidfile existence in the same tick /health first answers.
The daemon reaches two observable states non-atomically:
1. /health starts answering via server.listen, and
2. the pidfile is written asynchronously later.
waitForHealth only waits for (1). The single-shot fs.existsSync is a point-in-time snapshot; under CI scheduling the pidfile write lands a few ms after health is ready, so the assertion fails even though the daemon is healthy. This is the same startup-timing family as INT-CI-021/023/025/026. The defect is in the test — it conflates "health ready" with "startup side effects durable".
Poll for the pidfile with a bounded timeout before asserting.
import fs from 'node:fs';
export async function waitForFile(
file: string,
{ timeoutMs = 10_000, intervalMs = 50 }: { timeoutMs?: number; intervalMs?: number } = {},
): Promise<void> {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
if (fs.existsSync(file)) return;
await new Promise((resolve) => setTimeout(resolve, intervalMs));
}
if (fs.existsSync(file)) return; // final check
throw new Error(`Timed out after ${timeoutMs}ms waiting for file: ${file}`);
}
// before (racy)
await waitForHealth(baseUrl);
expect(fs.existsSync(pidFile)).toBe(true);
// after (deterministic)
await waitForHealth(baseUrl);
await waitForFile(pidFile, { timeoutMs: 10_000, intervalMs: 50 });
expect(fs.existsSync(pidFile)).toBe(true);
Notes: don't just raise the health timeout (health is already ready); don't use a bare sleep(500) (reintroduces flakiness). A stronger daemon-side fix would write the pidfile before advertising readiness, but the polling helper is the correct minimal test-side fix.
Self-contained reproducer (/tmp/pidrace/race.mjs) simulated the daemon and ran 300 rounds with a 5ms pidfile write delay:
single-shot existsSync failures: 299/300 (missed-by ms samples: 0.017, 0.01, 0.014, 0.01, 0.01)
polling existsSync failures: 0/300
Negative path verified — helper still fails clearly on a genuinely missing file:
threw after 302 ms: Timed out after 300ms waiting for file: /tmp/definitely-missing.pid
Suggested CI confirmation: run the test file 20× in a loop and 10× under nproc-saturating yes load, expecting all green.
# Evidence - Problem class: node-vitest-ci-startup-timing-pidfile-existence-race - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-10-07T23:01:23.610Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "node-vitest-ci-startup-timing-pidfile-existence-race", "provider": "openrouter", "solved_at": "2026-10-07T23:01:23.610Z", "version": ""}