fix(worktree): prevent zombie worktree and map leak on partial cleanup failure - #541
Conversation
|
@IBondarenko-iwg this cleanup path still feels too path-driven. First, the fallback reconstructs the current dotbot worktree layout as Second, I do not think If Git cannot remove it, I am not sure whether dotbot should stop and ask for manual cleanup or use a narrow filesystem fallback. Either way, ownership should come from Git, not from the raw filesystem path. Git should confirm this is the registered worktree for the expected task branch before dotbot does any fallback cleanup. |
|
@carlospedreira Thanks for the push on this. Turns out there were a couple of issues. On the path formula: it looks hardcoded but it's the same derivation On You're right the fallback was too blunt, though. In On |
carlospedreira
left a comment
There was a problem hiding this comment.
Looks good to me now. The concrete cleanup risk is addressed, and the remaining ownership-model idea can be follow-up work.
PR andresharpe#528 (fix andresharpe#516) landed Issue B upstream using the correct ownership fix: delete Write-TaskInputInterviewAnswer and Get-TaskInputProductDir entirely, enrich questions_resolved on the task instead. Took upstream version. PR andresharpe#540 (fix andresharpe#536) and PR andresharpe#541 (fix andresharpe#537) auto-merged cleanly. All v4-runtime issues now covered by upstream -- branch has zero unique changes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Linked issue
Closes #537
Summary of changes
Four bugs in
Dotbot.Worktree.psm1that cause orphan worktree partial setup to corrupt the filesystem on retry:Bug A —
Remove-OrphanWorktreesdeleted map entry even when the worktree directory survived removal. Next startup: dir not in map → invisible to retry machinery → permanent zombie.Bug B — No
Remove-Itemfallback aftergit worktree remove --forceinRemove-OrphanWorktrees. On Windows, open file handles cause silent failure. Added fallback +git worktree prune. Map entry now kept only when dir actually survives both attempts.Bug C —
New-TaskWorktreecalledRemove-Item -ErrorAction SilentlyContinueon stale leftover dir but never checked the result. Fell through togit worktree add, which failed with a path-collision error. Added early return withsuccess=$falsewhen removal fails.Bug D —
Complete-TaskWorktreehad the same pattern as Bug A: removed map entry even when dir survived. AddedRemove-Itemfallback + conditional map removal. Also fixed misleading return message ("cleaned up" now only emitted when dir is actually gone) and corrected a false comment claimingRemove-OrphanWorktreeswould retrydone-status tasks on next startup (it doesn't —doneis in$activeIds).Assert-PathWithinBoundscalls at new fallback sites use the canonical worktree parent dir derived from$ProjectRoot, matching the pre-existing pattern inNew-TaskWorktree.Testing notes
git worktree remove --forcefrom succeeding.Remove-OrphanWorktrees(restart the bot process). Verify:Errorlevel: "Orphan worktree removal incomplete — path still exists"Test-ProcessDispatch.ps1) — must pass clean.Checklist