Skip to content

fix: serialize worktree lifecycle operations with a flock on .cwm/lock - #17

Merged
HansRobo merged 1 commit into
mainfrom
fix/serialize-worktree-lifecycle
Jun 1, 2026
Merged

HansRobo merged 1 commit into
mainfrom
fix/serialize-worktree-lifecycle

Conversation

@HansRobo

@HansRobo HansRobo commented Jun 1, 2026 •

Copy link
Copy Markdown
Owner

Summary

Worktree lifecycle operations were unsynchronized: create_worktree, remove_worktree, prune_stale and register_agent_symlink mutated .git/worktrees and the per-branch metadata under .cwm/worktrees/ with no locking. Concurrent agents driving git worktree add/prune through the PR #15 git-hook could corrupt both.

This adds cwm_lock(cwm_dir) — a blocking POSIX fcntl.flock(LOCK_EX) context manager on .cwm/lock — and wraps the critical region of each lifecycle method. The CLI commands and the agent git-hook both converge on the same WSM methods, so locking at the method boundary serializes every entry path. Build and test operations stay lockless by design, so parallel builds across worktrees remain concurrent.

Changes

  • New src/cwm/util/lock.py: cwm_lock context manager (blocking LOCK_EX, EINTR retry, lock file never deleted, body exceptions propagate unchanged).
  • src/cwm/core/wsm.py: wrap the critical region of create_worktree (incl. the existence/collision check, closing a TOCTOU window), remove_worktree, prune_stale, and register_agent_symlink.
  • New tests/unit/test_lock.py: 5 unit tests (real fcntl; a second open file description proves mutual exclusion deterministically).
  • tests/unit/test_wsm.py: TestLifecycleLocking — 4 tests asserting the lock is held across each lifecycle method's git operation.
  • README.md: "Concurrency / locking" section.

Testing

uv run python -m pytest tests/ → 179 passed (full suite, same environment as CI). The 9 new tests (test_lock.py ×5, TestLifecycleLocking ×4) all pass; no regressions.

Release: patch → v6.1.2

create_worktree, remove_worktree, prune_stale and register_agent_symlink mutated .git/worktrees and the per-branch metadata under .cwm/worktrees/ without any locking. Concurrent agents driving 'git worktree add'/'prune' through the PR #15 git-hook could corrupt both.

Add cwm_lock(cwm_dir), a blocking fcntl.flock(LOCK_EX) context manager on .cwm/lock, and wrap the critical region of each lifecycle method. Both the CLI commands and the agent git-hook converge on the same WSM methods, so locking at the method boundary serializes every entry path. Build and test operations are intentionally left lockless so parallel builds across worktrees stay concurrent.
@HansRobo HansRobo added release:patch Bump patch version on merge and removed release:patch Bump patch version on merge labels Jun 1, 2026
@HansRobo
HansRobo merged commit 5c1f1d1 into main Jun 1, 2026
22 of 24 checks passed
@HansRobo
HansRobo deleted the fix/serialize-worktree-lifecycle branch June 1, 2026 02:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:patch Bump patch version on merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant