mirror of
https://github.com/Jeuners/ECC.git
synced 2026-09-09 15:02:30 +02: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. |
||
|---|---|---|
| .. | ||
| ci | ||
| codemaps | ||
| codex | ||
| codex-git-hooks | ||
| hooks | ||
| lib | ||
| auto-update.js | ||
| build-opencode.js | ||
| catalog.js | ||
| claw.js | ||
| consult.js | ||
| discussion-audit.js | ||
| doctor.js | ||
| ecc.js | ||
| gan-harness.sh | ||
| gemini-adapt-agents.js | ||
| harness-adapter-compliance.js | ||
| harness-audit.js | ||
| install-apply.js | ||
| install-plan.js | ||
| list-installed.js | ||
| loop-status.js | ||
| observability-readiness.js | ||
| operator-readiness-dashboard.js | ||
| orchestrate-codex-worker.sh | ||
| orchestrate-worktrees.js | ||
| orchestration-status.js | ||
| platform-audit.js | ||
| preview-pack-smoke.js | ||
| release.sh | ||
| repair.js | ||
| session-inspect.js | ||
| sessions-cli.js | ||
| setup-package-manager.js | ||
| skill-create-output.js | ||
| skills-health.js | ||
| status.js | ||
| sync-ecc-to-codex.sh | ||
| uninstall.js | ||
| work-items.js | ||