Plan: Make createWorktree() Idempotent#
Summary#
Replace the destructive nuke-and-recreate logic in WorktreeService.createWorktree() with an idempotent flow that detects existing worktrees/branches and reuses them, fixing the permanent stuck-loop caused when a branch is already checked out elsewhere (#246).
Files#
| File | Action | Description |
|---|---|---|
src/worktree/worktree.service.ts | modify | Replace lines 77–128 with idempotent worktree/branch detection and reuse logic |
src/worktree/worktree.service.spec.ts | modify | Add 4 new test cases covering all idempotent paths; update existing tests for new flow |
Steps#
- Add
isValidWorktree(path)private helper inworktree.service.ts— runsgit worktree list --porcelainand checks if the given path appears as a registered worktree. - Replace lines 77–95 (stale worktree cleanup) with: if worktree directory exists AND
isValidWorktree()returns true, log reuse and skip to fetch+reset. If directory exists but is NOT a valid worktree, remove the directory and fall through. - Remove lines 100–118 (aggressive
git branch -Dblock) entirely — this is the root cause of the silent failure. - Replace lines 120–128 (unconditional
git worktree add -b) with three-path logic: (a) if worktree was reused in step 2, rungit fetch origin+git reset --hard origin/masterinside the worktree; (b) if no worktree but branch exists locally (git branch --list <branch>is non-empty), rungit worktree add <path> <branch>(no-b); (c) if neither exists, rungit worktree add -b <branch> <path> origin/master(current fresh-start behavior). - Add unit test: worktree directory exists and is valid → reused without removal, fetch+reset executed.
- Add unit test: worktree directory exists but is invalid → directory removed, falls through to branch-check logic.
- Add unit test: branch exists locally but no worktree directory →
git worktree add <path> <branch>called (no-b). - Add unit test: neither branch nor worktree exist →
git worktree add -b <branch> <path> origin/mastercalled (existing behavior preserved). - Update existing tests that assert the old
git branch -Dor forced removal behavior to match the new idempotent flow.
Verification#
npm run testpasses with all new and updated worktree tests green.npm run lintpasses with zero warnings.- No changes outside
src/worktree/directory.
Risks#
git reset --hard origin/masterin reuse path discards uncommitted worktree changes — acceptable since agent worktrees are ephemeral and always start fromorigin/master. The issue explicitly requests this behavior.