fix(acp): retry a failed session directory removal after the agent exits

Merged
VA
4d ago
+84-3

Fixes #1623.

On Windows, teardown() sent SIGTERM to the agent and then removed its session directory at once. Windows refuses to remove a directory while a process still has it as its working directory, so rmSync threw EPERM synchronously and took the worker down with WORKER_CRASH. Because the test never passed, no recording was saved, so every rerun burned another model call.

The directory is now removed at once, and retried after the agent exits when the first removal fails. On POSIX the first removal usually succeeds while the agent is still stopping, so a worker exiting right after the attempt leaves nothing behind; on Windows a process the agent started in the directory still holds it, so the removal fails there and waits for the exit. A failed removal never throws: a leftover temp directory is harmless.

Verified

  • 2 regression tests in packages/acp/tests/executor.test.ts: the removal is retried after the agent exits when the first try fails (forced by a file in a read-only directory), and on POSIX the directory is gone at once while the agent is still alive. The new immediate-path test fails on the remove-only-after-exit code (red verified) and passes with the fix. Both are skipped on Windows, where Node terminates the child immediately for SIGTERM and the delay handler cannot run, so they check the ordering on POSIX only. The fallback test also skips as root, where a read-only directory does not block removal.
  • packages/acp executor tests 33/33 pass; full acp suite 36/39. The 3 cli.test.ts failures are pre-existing and unrelated: identical on clean origin/main, caused by Chromium refusing to launch as root without --no-sandbox in this sandbox; they should pass in CI.
  • typecheck clean, oxlint clean.
  • The Windows EPERM itself cannot reproduce on Linux (POSIX allows removing a live process's cwd), and no CI workflow runs on Windows, so the EPERM path itself is unverified.