mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-20 11:19:58 +08:00
PR #1983 round 1 introduced unique-suffix tmp paths so two concurrent writers no longer share a single `.tmp` file. That fix is correct under POSIX semantics — `rename(2)` is atomic between source and destination, so each writer renames onto the same target without conflict. Windows `MoveFileExW` is not the same. It fails with EPERM / EACCES / EBUSY when the target is currently being renamed by *another* process — a short race window that fires reliably under this hook's PostToolUse + statusline concurrency. Round 1's CI run made this visible: Test (windows-latest, Node 18.x, npm) — FAILURE Error: EPERM: operation not permitted, rename 'C:\…\ecc-metrics-test-bridge-race-….json.9504.4aef575a.tmp' -> 'C:\…\ecc-metrics-test-bridge-race-….json' at writeBridgeAtomic (scripts/lib/session-bridge.js:79:8) All nine Windows matrix cells (Node 18 / 20 / 22 × npm / pnpm / yarn) hit the same path. POSIX matrices (Linux + macOS) passed unchanged. Fix: extract a `renameWithRetry(tmp, target)` helper that retries `fs.renameSync` up to 5 times on EPERM / EACCES / EBUSY with exponential backoff (20 ms → 320 ms total). Other error codes (ENOENT, ENOSPC, EROFS, …) re-throw on the first attempt — they are not transient. POSIX runs hit the first try and exit immediately. The backoff uses `Atomics.wait` on a throwaway `SharedArrayBuffer` so the retry path does not busy-spin the CPU; verified on Node ≥ 17 that this works on the main thread. There is a `try/catch` fallback to a brief busy-wait for older runtimes where `Atomics.wait` is restricted to workers. `writeBridgeAtomic` calls the helper instead of `fs.renameSync` and keeps its existing best-effort tmp cleanup on terminal failure. `renameWithRetry` is added to `module.exports` so the companion `writeWarnState` in `scripts/hooks/ecc-context-monitor.js` can adopt the same retry policy without duplicating the helper. That adoption lands in the next commit. Local: `node tests/lib/session-bridge.test.js` 14/14, `yarn test` green, `yarn lint` clean. The round-1 test (two concurrent child writers, 200 iterations each) now passes on macOS without retrying at all (POSIX path) and is expected to pass on Windows via the new retry loop.