fix(worktree): add pre-merge deletion guard to quick.md; fix backup handling on conflict (#2275)
Three gaps in the orchestrator file-protection block (#1756, #2040): 1. quick.md never received the pre-merge deletion guard added to execute-phase.md in #2040. Added the same DELETIONS check: if the worktree branch deletes any tracked .planning/ files, block the merge with a clear message rather than silently losing those files. 2. Both workflows deleted STATE_BACKUP and ROADMAP_BACKUP on merge conflict — destroying the recovery files at exactly the moment they were needed. Changed conflict handler to: preserve both backup paths, print restore instructions, and break (halt) instead of continue (silently advancing to the next worktree). 3. Neither workflow used --no-ff. Without it a fast-forward merge produces no merge commit, so HEAD~1 in the resurrection check points to the worktree's parent rather than main's pre-merge HEAD. Added --no-ff to both git merge calls so HEAD~1 is always reliable. Closes #2208 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -614,11 +614,13 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
|
||||
continue
|
||||
fi
|
||||
|
||||
# Merge the worktree branch into the current branch
|
||||
git merge "$WT_BRANCH" --no-edit -m "chore: merge executor worktree ($WT_BRANCH)" 2>&1 || {
|
||||
# Merge the worktree branch into the current branch (--no-ff ensures a merge commit so HEAD~1 is reliable)
|
||||
git merge "$WT_BRANCH" --no-ff --no-edit -m "chore: merge executor worktree ($WT_BRANCH)" 2>&1 || {
|
||||
echo "⚠ Merge conflict from worktree $WT_BRANCH — resolve manually"
|
||||
rm -f "$STATE_BACKUP" "$ROADMAP_BACKUP"
|
||||
continue
|
||||
echo " STATE.md backup: $STATE_BACKUP"
|
||||
echo " ROADMAP.md backup: $ROADMAP_BACKUP"
|
||||
echo " Restore with: cp \$STATE_BACKUP .planning/STATE.md && cp \$ROADMAP_BACKUP .planning/ROADMAP.md"
|
||||
break
|
||||
}
|
||||
|
||||
# Restore orchestrator-owned files (main always wins)
|
||||
|
||||
@@ -628,10 +628,21 @@ After executor returns:
|
||||
# Snapshot files on main to detect resurrections
|
||||
PRE_MERGE_FILES=$(git ls-files .planning/)
|
||||
|
||||
git merge "$WT_BRANCH" --no-edit -m "chore: merge quick task worktree ($WT_BRANCH)" 2>&1 || {
|
||||
echo "⚠ Merge conflict — resolve manually"
|
||||
# Pre-merge deletion guard: block merges that delete tracked .planning/ files
|
||||
DELETIONS=$(git diff --diff-filter=D --name-only HEAD..."$WT_BRANCH" 2>/dev/null || true)
|
||||
if [ -n "$DELETIONS" ]; then
|
||||
echo "BLOCKED: Worktree branch $WT_BRANCH contains file deletions: $DELETIONS"
|
||||
echo "Review these deletions before merging. If intentional, remove this guard and re-run."
|
||||
rm -f "$STATE_BACKUP" "$ROADMAP_BACKUP"
|
||||
continue
|
||||
fi
|
||||
|
||||
git merge "$WT_BRANCH" --no-ff --no-edit -m "chore: merge quick task worktree ($WT_BRANCH)" 2>&1 || {
|
||||
echo "⚠ Merge conflict from worktree $WT_BRANCH — resolve manually"
|
||||
echo " STATE.md backup: $STATE_BACKUP"
|
||||
echo " ROADMAP.md backup: $ROADMAP_BACKUP"
|
||||
echo " Restore with: cp \$STATE_BACKUP .planning/STATE.md && cp \$ROADMAP_BACKUP .planning/ROADMAP.md"
|
||||
break
|
||||
}
|
||||
|
||||
# Restore orchestrator-owned files
|
||||
@@ -639,7 +650,7 @@ After executor returns:
|
||||
if [ -s "$ROADMAP_BACKUP" ]; then cp "$ROADMAP_BACKUP" .planning/ROADMAP.md; fi
|
||||
rm -f "$STATE_BACKUP" "$ROADMAP_BACKUP"
|
||||
|
||||
# Remove files deleted on main but re-added by worktree
|
||||
# Remove files deleted on main but re-added by worktree (--no-ff guarantees a merge commit so HEAD~1 is reliable)
|
||||
DELETED_FILES=$(git diff --diff-filter=A --name-only HEAD~1 -- .planning/ 2>/dev/null || true)
|
||||
for RESURRECTED in $DELETED_FILES; do
|
||||
if ! echo "$PRE_MERGE_FILES" | grep -qxF "$RESURRECTED"; then
|
||||
|
||||
Reference in New Issue
Block a user