fix(worktree): add post-execution cleanup for orphan worktrees
Executor agents spawned with isolation="worktree" committed to temporary branches in separate working trees, but no step existed to merge those changes back or clean up. This left orphan worktrees and unmerged branches after every execution. Changes: - execute-phase.md: add step 4.5 "Worktree cleanup" after wave completion — merges worktree branch, removes worktree, deletes temp branch. Handles merge conflicts gracefully. - quick.md: add worktree cleanup step after executor returns, before summary verification - Both workflows skip cleanup when workflow.use_worktrees is false - Both workflows skip silently when no worktrees are found Closes #1496 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -313,6 +313,39 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
|
||||
```
|
||||
If hooks fail: report the failure and ask "Fix hook issues now?" or "Continue to next wave?"
|
||||
|
||||
4.5. **Worktree cleanup (when `isolation="worktree"` was used):**
|
||||
|
||||
When executor agents ran in worktree isolation, their commits land on temporary branches in separate working trees. After the wave completes, merge these changes back and clean up:
|
||||
|
||||
```bash
|
||||
# List worktrees created by this wave's agents
|
||||
WORKTREES=$(git worktree list --porcelain | grep "^worktree " | grep -v "$(pwd)$" | sed 's/^worktree //')
|
||||
|
||||
for WT in $WORKTREES; do
|
||||
# Get the branch name for this worktree
|
||||
WT_BRANCH=$(git -C "$WT" rev-parse --abbrev-ref HEAD 2>/dev/null)
|
||||
if [ -n "$WT_BRANCH" ] && [ "$WT_BRANCH" != "HEAD" ]; then
|
||||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# Merge the worktree branch into the current branch
|
||||
git merge "$WT_BRANCH" --no-edit -m "chore: merge executor worktree ($WT_BRANCH)" 2>&1 || {
|
||||
echo "⚠ Merge conflict from worktree $WT_BRANCH — resolve manually"
|
||||
continue
|
||||
}
|
||||
|
||||
# Remove the worktree
|
||||
git worktree remove "$WT" --force 2>/dev/null || true
|
||||
|
||||
# Delete the temporary branch
|
||||
git branch -D "$WT_BRANCH" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
**If `workflow.use_worktrees` is `false`:** Agents ran on the main working tree — skip this step entirely.
|
||||
|
||||
**If no worktrees found:** Skip silently — agents may have been spawned without worktree isolation.
|
||||
|
||||
5. **Report completion — spot-check claims first:**
|
||||
|
||||
For each SUMMARY.md:
|
||||
|
||||
@@ -565,9 +565,23 @@ ${AGENT_SKILLS_EXECUTOR}
|
||||
```
|
||||
|
||||
After executor returns:
|
||||
1. Verify summary exists at `${QUICK_DIR}/${quick_id}-SUMMARY.md`
|
||||
2. Extract commit hash from executor output
|
||||
3. Report completion status
|
||||
1. **Worktree cleanup:** If the executor ran with `isolation="worktree"`, merge the worktree branch back and clean up:
|
||||
```bash
|
||||
# Find worktrees created by the executor
|
||||
WORKTREES=$(git worktree list --porcelain | grep "^worktree " | grep -v "$(pwd)$" | sed 's/^worktree //')
|
||||
for WT in $WORKTREES; do
|
||||
WT_BRANCH=$(git -C "$WT" rev-parse --abbrev-ref HEAD 2>/dev/null)
|
||||
if [ -n "$WT_BRANCH" ] && [ "$WT_BRANCH" != "HEAD" ]; then
|
||||
git merge "$WT_BRANCH" --no-edit -m "chore: merge quick task worktree ($WT_BRANCH)" 2>&1 || echo "⚠ Merge conflict — resolve manually"
|
||||
git worktree remove "$WT" --force 2>/dev/null || true
|
||||
git branch -D "$WT_BRANCH" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
```
|
||||
If `workflow.use_worktrees` is `false`, skip this step.
|
||||
2. Verify summary exists at `${QUICK_DIR}/${quick_id}-SUMMARY.md`
|
||||
3. Extract commit hash from executor output
|
||||
4. Report completion status
|
||||
|
||||
**Known Claude Code bug (classifyHandoffIfNeeded):** If executor reports "failed" with error `classifyHandoffIfNeeded is not defined`, this is a Claude Code runtime bug — not a real failure. Check if summary file exists and git log shows commits. If so, treat as successful.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user