Skip to content

fix(memory): retry atomic writes under Windows file contention - #404

Merged
Phantivia merged 2 commits into
Pal-AI-Lab:mainfrom
jcs130:fix/memory-atomic-busy-20261111
Nov 12, 2026
Merged

Phantivia merged 2 commits into
Pal-AI-Lab:mainfrom
jcs130:fix/memory-atomic-busy-20261111

Conversation

@jcs130

@jcs130 jcs130 commented Nov 11, 2026

Copy link
Copy Markdown

A temporary Windows reader handle can make the final rename in GitWorkspaceMemory.writeFileAtomic fail with EPERM, aborting checkpoint publication even though the temporary file was fully written.

Reuse the existing bounded retryBusy helper for that rename. A persistent lock still raises the original error, keeps the previous checkpoint and removes the temporary file. No action or tool call is replayed.

Validation: real Windows file handles reproduce the old failure and cover successful publication after release plus preservation on persistent contention. Full suite: 5,207 passed, 4 skipped; typecheck passed. Tests ran from an identical ASCII-path worktree because the existing Vite dynamic importer cannot resolve the percent-encoded non-ASCII checkout path.

codex and others added 2 commits November 11, 2026 17:14
Atomic workspace replacement used a single rename, so a temporary reader lock aborted checkpoint publication. Reuse the bounded Windows retry and preserve the original file/error when the lock persists. Real reader-handle tests cover both outcomes; 5,207 tests pass with 4 skipped and typecheck passes in the equivalent ASCII-path worktree.
- 两个用例靠 PowerShell 子进程占住目标文件,第二个靠 3800 ms 占用和 retryBusy
  约 2970 ms 退避之间的余量成立,慢的 runner 上子进程起得晚就会翻红。
- 其余包了 retryBusy 的改名(state、timers、extensions、context-log)都没有按调用点
  测占用。

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@Phantivia
Phantivia merged commit 90b38c3 into Pal-AI-Lab:main Nov 12, 2026
3 checks passed
@Phantivia

Copy link
Copy Markdown
Member

Thanks @jcs130, merged. The rename in bots/cormini/persona/memory.ts was the one atomic write that retryBusy did not cover.

Before merging we pushed one commit to your branch that removes tests/cormini/memory-busy.test.ts. The test holds the target file with a real PowerShell child process and asserts on timing: the second case holds the file for 3800 ms against the 2970 ms that retryBusy backs off in total, so it fails on a runner that stalls for more than 830 ms between the helper reporting ready and the write starting, and both cases fail when PowerShell takes more than 5 s to start. The other renames wrapped in retryBusy (src/core/state.ts, src/core/timers.ts, src/extensions.ts, src/protocol/open-responses/context-log.ts) have no test of this kind either.

The fix ships with the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants