fix(worktree): use hard reset to correct file tree when branch base is wrong (#1982)
* fix(worktree): use hard reset to correct file tree when branch base is wrong (#1981) The worktree_branch_check mitigation detects when EnterWorktree creates branches from main instead of the current feature branch, but used git reset --soft to correct it. This only fixed the commit pointer — the working tree still contained main's files, causing silent data loss on merge-back when the agent's commits overwrote feature branch code. Changed to git reset --hard which safely corrects both pointer and file tree (the check runs before any agent work, so no changes to lose). Also removed the broken rebase --onto attempt in execute-phase.md that could replay main's commits onto the feature branch, and added post-reset verification that aborts if the correction fails. Updated documentation from "Windows" to "all platforms" since the upstream EnterWorktree bug affects macOS, Linux, and Windows alike. Closes #1981 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(worktree): update settings.md worktree description to say cross-platform Aligns with the workflow file updates — the EnterWorktree base-branch bug affects all platforms, not just Windows. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -97,7 +97,7 @@ For each gap, fill the debug-subagent-prompt template and spawn:
|
||||
|
||||
```
|
||||
Task(
|
||||
prompt=filled_debug_subagent_prompt + "\n\n<worktree_branch_check>\nFIRST ACTION: run git merge-base HEAD {EXPECTED_BASE} — if result differs from {EXPECTED_BASE}, run git reset --soft {EXPECTED_BASE} to correct the branch base (fixes Windows EnterWorktree creating branches from main).\n</worktree_branch_check>\n\n<files_to_read>\n- {phase_dir}/{phase_num}-UAT.md\n- .planning/STATE.md\n</files_to_read>\n${AGENT_SKILLS_DEBUGGER}",
|
||||
prompt=filled_debug_subagent_prompt + "\n\n<worktree_branch_check>\nFIRST ACTION: run git merge-base HEAD {EXPECTED_BASE} — if result differs from {EXPECTED_BASE}, run git reset --hard {EXPECTED_BASE} to correct the branch base (safe — runs before any agent work). Then verify: if [ \"$(git rev-parse HEAD)\" != \"{EXPECTED_BASE}\" ]; then echo \"ERROR: Could not correct worktree base\"; exit 1; fi. Fixes EnterWorktree creating branches from main on all platforms.\n</worktree_branch_check>\n\n<files_to_read>\n- {phase_dir}/{phase_num}-UAT.md\n- .planning/STATE.md\n</files_to_read>\n${AGENT_SKILLS_DEBUGGER}",
|
||||
subagent_type="gsd-debugger",
|
||||
${USE_WORKTREES !== "false" ? 'isolation="worktree",' : ''}
|
||||
description="Debug: {truth_short}"
|
||||
|
||||
@@ -348,21 +348,24 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
|
||||
Run:
|
||||
```bash
|
||||
ACTUAL_BASE=$(git merge-base HEAD {EXPECTED_BASE})
|
||||
CURRENT_HEAD=$(git rev-parse HEAD)
|
||||
```
|
||||
|
||||
If `ACTUAL_BASE` != `{EXPECTED_BASE}` (i.e. the worktree branch was created from an older
|
||||
base such as `main` instead of the feature branch HEAD), rebase onto the correct base:
|
||||
base such as `main` instead of the feature branch HEAD), hard-reset to the correct base:
|
||||
```bash
|
||||
git rebase --onto {EXPECTED_BASE} $(git rev-parse --abbrev-ref HEAD~1 2>/dev/null || git rev-parse HEAD^) HEAD 2>/dev/null || true
|
||||
# If rebase fails or is a no-op, reset the branch to start from the correct base:
|
||||
git reset --soft {EXPECTED_BASE}
|
||||
# Safe: this runs before any agent work, so no uncommitted changes to lose
|
||||
git reset --hard {EXPECTED_BASE}
|
||||
# Verify correction succeeded
|
||||
if [ "$(git rev-parse HEAD)" != "{EXPECTED_BASE}" ]; then
|
||||
echo "ERROR: Could not correct worktree base — aborting to prevent data loss"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
If `ACTUAL_BASE` == `{EXPECTED_BASE}`: the branch base is correct, proceed immediately.
|
||||
|
||||
This check fixes a known issue on Windows where `EnterWorktree` creates branches from
|
||||
`main` instead of the current feature branch HEAD.
|
||||
This check fixes a known issue where `EnterWorktree` creates branches from
|
||||
`main` instead of the current feature branch HEAD (affects all platforms).
|
||||
</worktree_branch_check>
|
||||
|
||||
<parallel_execution>
|
||||
|
||||
@@ -72,7 +72,7 @@ grep -n "type=\"checkpoint" .planning/phases/XX-name/{phase}-{plan}-PLAN.md
|
||||
| Verify-only | B (segmented) | Segments between checkpoints. After none/human-verify → SUBAGENT. After decision/human-action → MAIN |
|
||||
| Decision | C (main) | Execute entirely in main context |
|
||||
|
||||
**Pattern A:** init_agent_tracking → capture `EXPECTED_BASE=$(git rev-parse HEAD)` → spawn Task(subagent_type="gsd-executor", model=executor_model) with prompt: execute plan at [path], autonomous, all tasks + SUMMARY + commit, follow deviation/auth rules, report: plan name, tasks, SUMMARY path, commit hash → track agent_id → wait → update tracking → report. **Include `isolation="worktree"` only if `workflow.use_worktrees` is not `false`** (read via `config-get workflow.use_worktrees`). **When using `isolation="worktree"`, include a `<worktree_branch_check>` block in the prompt** instructing the executor to run `git merge-base HEAD {EXPECTED_BASE}` and, if the result differs from `{EXPECTED_BASE}`, reset the branch base with `git reset --soft {EXPECTED_BASE}` before starting work. This corrects a known issue on Windows where `EnterWorktree` creates branches from `main` instead of the feature branch HEAD.
|
||||
**Pattern A:** init_agent_tracking → capture `EXPECTED_BASE=$(git rev-parse HEAD)` → spawn Task(subagent_type="gsd-executor", model=executor_model) with prompt: execute plan at [path], autonomous, all tasks + SUMMARY + commit, follow deviation/auth rules, report: plan name, tasks, SUMMARY path, commit hash → track agent_id → wait → update tracking → report. **Include `isolation="worktree"` only if `workflow.use_worktrees` is not `false`** (read via `config-get workflow.use_worktrees`). **When using `isolation="worktree"`, include a `<worktree_branch_check>` block in the prompt** instructing the executor to run `git merge-base HEAD {EXPECTED_BASE}` and, if the result differs from `{EXPECTED_BASE}`, hard-reset the branch with `git reset --hard {EXPECTED_BASE}` before starting work (safe — runs before any agent work), then verify with `[ "$(git rev-parse HEAD)" != "{EXPECTED_BASE}" ] && exit 1`. This corrects a known issue where `EnterWorktree` creates branches from `main` instead of the feature branch HEAD (affects all platforms).
|
||||
|
||||
**Pattern B:** Execute segment-by-segment. Autonomous segments: spawn subagent for assigned tasks only (no SUMMARY/commit). Checkpoints: main context. After all segments: aggregate, create SUMMARY, commit. See segment_execution.
|
||||
|
||||
|
||||
@@ -567,8 +567,10 @@ ${USE_WORKTREES !== "false" ? `
|
||||
<worktree_branch_check>
|
||||
FIRST ACTION before any other work: verify this worktree branch is based on the correct commit.
|
||||
Run: git merge-base HEAD ${EXPECTED_BASE}
|
||||
If the result differs from ${EXPECTED_BASE}, run: git reset --soft ${EXPECTED_BASE}
|
||||
This corrects a known issue on Windows where EnterWorktree creates branches from main instead of the feature branch HEAD.
|
||||
If the result differs from ${EXPECTED_BASE}, hard-reset to the correct base (safe — runs before any agent work):
|
||||
git reset --hard ${EXPECTED_BASE}
|
||||
Then verify: if [ "$(git rev-parse HEAD)" != "${EXPECTED_BASE}" ]; then echo "ERROR: Could not correct worktree base"; exit 1; fi
|
||||
This corrects a known issue where EnterWorktree creates branches from main instead of the feature branch HEAD (affects all platforms).
|
||||
</worktree_branch_check>
|
||||
` : ''}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ AskUserQuestion([
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "Yes (Recommended)", description: "Each parallel executor runs in its own worktree branch — no conflicts between agents." },
|
||||
{ label: "No", description: "Disable worktree isolation. Use on platforms where EnterWorktree is broken (e.g. Windows with feature branches). Agents run sequentially on the main working tree." }
|
||||
{ label: "No", description: "Disable worktree isolation. Agents run sequentially on the main working tree. Use if EnterWorktree creates branches from wrong base (known cross-platform issue)." }
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
Reference in New Issue
Block a user