fix(FN-4939): preserve worktree on contamination auto-recovery

The in-line branch-cross-contamination auto-recovery in executor.ts had
two related bugs that produced transient "no-worktree-no-merge-confirmed"
stall signals in the dashboard while a live worktree was still mapped
on disk:

1. autoRecoverCrossContamination was called with repoDir=this.rootDir.
   The recovery does: git checkout --detach <baseSha> → cherry-pick
   wanted commits → git update-ref → git checkout <branch>. When the
   branch is checked out in a worktree (the normal case), that final
   recheckout in rootDir is blocked by git with "branch already used
   by worktree at ...", so the in-line happy path silently failed for
   every contaminated task that had a real worktree. Pass the task's
   worktree as repoDir when available so the operations stay internal
   to the worktree and the recheckout succeeds.

2. The successful-recovery branch called
       moveTask(taskId, 'todo', { preserveResumeState: true })
   without preserveWorktree:true. moveTask defaults to nulling
   task.worktree on requeue. The worktree directory and git mapping
   were still live — the dashboard's in-review-stall classifier
   (no-worktree-no-merge-confirmed) and TaskChangesTab both keyed off
   task.worktree being null and lied about the worktree being gone.
   Sibling recovery paths (auto-recovery-handlers/contamination.ts,
   tryBootstrapMisbindingRecovery, self-healing.ts:1639) all already
   pass preserveWorktree:true; this site was inconsistent.

Updated the existing FN-4428 regression test and added a new
FN-4939 test asserting repoDir uses task.worktree (with fallback
to rootDir when the task has no worktree pointer).

Refs: packages/core/src/in-review-stall.ts:116
This commit is contained in:
gsxdsm
2026-05-17 12:03:44 -07:00
parent 93e49b062a
commit 14c5a17844
3 changed files with 64 additions and 4 deletions

View File

@@ -0,0 +1,8 @@
---
"@runfusion/fusion": patch
---
Fix contamination auto-recovery nulling `task.worktree` while leaving a live worktree mapped on disk, which triggered transient `no-worktree-no-merge-confirmed` stall signals in the dashboard. The in-line recovery in `executor.ts` now:
- Runs `autoRecoverCrossContamination` inside the task's worktree (when one exists) so the final `git checkout <branch>` doesn't collide with the branch already being checked out elsewhere — the previous `repoDir: this.rootDir` call would silently fail for any task that had a real worktree.
- Passes `preserveWorktree: true` when requeueing to `todo`, matching the sibling recovery paths in `auto-recovery-handlers/contamination.ts`, `tryBootstrapMisbindingRecovery`, and self-healing reclaim.