fix(server): recreate a thread's worktree before starting a turn - #7839
fix(server): recreate a thread's worktree before starting a turn#7839mackinleysmith wants to merge 2 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a self-contained bug fix that defensively recreates missing worktree directories before starting a turn. The implementation includes proper error handling (failures are logged but don't block), follows existing patterns, and has comprehensive test coverage. Notes:
You can add or adjust custom eligibility rules. Learn more. |
Problem
When a thread's worktree directory disappears, every later turn on that thread fails. The provider session is tied to the persisted cwd, and provider CLIs key their transcript store off that path, so the resume fails and the user sees a generic "session not found". The conversation isn't actually lost. Our projection still has every message and the transcript is still on disk. The directory the session is addressed by is gone, and nothing tries to bring it back.
This is the narrow version of the fix from #6197, which also changed session resume guards and Claude error classification. This PR does one thing.
Fix
Before
ProviderCommandReactorresolves a session for a turn, it checks whether the thread'sworktreePathstill exists. If it doesn't and the thread has a branch, it runsgit worktree prune(a directory deleted by hand leaves an admin entry that makesgit worktree addrefuse the path) and then recreates the worktree from the thread's branch in the project'sworkspaceRoot.Failures are logged and the turn continues, so the existing failure path reports the real error. Interrupts are re-raised. A failed stat counts as "exists" so a transient filesystem error can't trigger a recreate over a healthy worktree.
Out of scope here: a thread activity telling the user that uncommitted work in the old worktree is gone, and recovery when the branch itself was deleted. Those can follow if wanted.
Verification
apps/servertypecheck clean.ProviderCommandReactor.test.ts, 46/46 passing, including a new test that a missing worktree path triggers prune andcreateWorktreewith the thread's branch beforestartSession.Written with Claude Fable 5 in T3 Code.
Note
Medium Risk
Touches turn-start orchestration and git worktree lifecycle. Recreate failures are logged and the turn still proceeds, so a missing path can still fail later rather than blocking.
Overview
On
thread.turn.start,ProviderCommandReactornow checks that the thread'sworktreePathstill exists. If it is gone and the thread has a branch, it prunes stale git worktree admin entries and recreates the worktree at the recorded path from that branch in the project root.Adds
pruneWorktrees(git worktree prune) on the git driver andGitWorkflowService. A failed existence check is treated as present so a transient FS error cannot overwrite a healthy worktree. Non-interrupt recreate failures are logged and the turn continues so the real provider error still surfaces.Reviewed by Cursor Bugbot for commit 130bcc4. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Recreate missing thread worktree before starting a turn
thread.turn.start, the reactor now checks if the thread'sworktreePathexists; if missing, it resolves the projectcwd, prunes stale worktree admin entries, and recreates the worktree from the thread branch before proceeding.pruneWorktreestoGitWorkflowServiceandGitVcsDriverinterfaces; the core driver runsgit worktree prunewith a 15s timeout and invalidates list-refs caches.ensureThreadWorktreein ProviderCommandReactor.ts silently swallows non-interrupt errors — a persistently broken worktree will produce warnings but not abort the turn.Macroscope summarized 130bcc4.