fix(workflow): prevent silent SUMMARY.md loss on worktree force-removal (#2073)

Closes #2070

Two-layer fix for the bug where executor agents in worktree isolation mode
could leave SUMMARY.md uncommitted, then have it silently destroyed by
`git worktree remove --force` during post-wave cleanup.

Layer 1 — Clarify executor instruction (execute-phase.md):
Added explicit REQUIRED note to the <parallel_execution> block making
clear that SUMMARY.md MUST be committed before the agent returns,
and that the git_commit_metadata step in execute-plan.md handles the
SUMMARY.md-only commit path automatically in worktree mode.

Layer 2 — Orchestrator safety net (execute-phase.md):
Before force-removing each worktree, check for any uncommitted SUMMARY.md
files. If found, commit them on the worktree branch and re-merge into the
main branch before removal. This prevents data loss even when an executor
skips the commit step due to misinterpreting the "do not modify
orchestrator files" instruction.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-04-10 21:29:56 -04:00
committed by GitHub
parent f8cf54bd01
commit 2b4b48401c

View File

@@ -382,6 +382,12 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
auto-detects worktree mode (`.git` is a file, not a directory) and skips
shared file updates automatically. The orchestrator updates them centrally
after merge.
REQUIRED: SUMMARY.md MUST be committed before you return. In worktree mode the
git_commit_metadata step in execute-plan.md commits SUMMARY.md and REQUIREMENTS.md
only (STATE.md and ROADMAP.md are excluded automatically). Do NOT skip or defer
this commit — the orchestrator force-removes the worktree after you return, and
any uncommitted SUMMARY.md will be permanently lost (#2070).
</parallel_execution>
<execution_context>
@@ -556,6 +562,17 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
fi
fi
# Safety net: commit any uncommitted SUMMARY.md before force-removing the worktree.
# This guards against executors that skipped the git_commit_metadata step (#2070).
UNCOMMITTED_SUMMARY=$(git -C "$WT" ls-files --modified --others --exclude-standard -- "*SUMMARY.md" 2>/dev/null || true)
if [ -n "$UNCOMMITTED_SUMMARY" ]; then
echo "⚠ SUMMARY.md was not committed by executor — committing now to prevent data loss"
git -C "$WT" add -- "*SUMMARY.md" 2>/dev/null || true
git -C "$WT" commit --no-verify -m "docs(recovery): rescue uncommitted SUMMARY.md before worktree removal (#2070)" 2>/dev/null || true
# Re-merge the recovery commit
git merge "$WT_BRANCH" --no-edit -m "chore: merge rescued SUMMARY.md from executor worktree ($WT_BRANCH)" 2>/dev/null || true
fi
# Remove the worktree
git worktree remove "$WT" --force 2>/dev/null || true