Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD across contents and paths, upstream package/repo coordinates -> @golem15/msd-core and golem15com/msd-core. Deep links into upstream history, sibling upstream packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is. Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line, package/plugin identity, regenerated lockfile, install-tree fixtures, derived registries and benchmark baseline; migration checksum baseline re-locked (MSD keeps its own install state, so no install had applied the old sums); sort-order and regex-escaped expectations in tests adjusted.
5.6 KiB
5.6 KiB
Executor self-repair of a worktree base mismatch via git reset --hard
Source: #4463 Decision: wontfix — No-go as filed; conflicts with the shipped #48 design Date: 2026-09-07
Proposal summary
Reporter ran a controlled probe on Claude Code and reported two findings, plus a proposal:
- Measurement: the harness worktree it was dispatched into forked from the
orchestrator session's HEAD (the main checkout's current branch tip), not from
origin/HEADas the#3659/#3779/#48family assumed. The reporter is explicit that this does not mean theworktree.base-checkdegrade is wrong in the case they observed — the stated reason for the degrade may be inaccurate even where the degrade itself is still warranted. - Measurement: because a linked worktree shares the common git object/ref store,
the phase branch is reachable as a local ref with no
git fetch, andgit reset --hard <phase-branch>on the executor's own branch is cheap, does not switch or detach HEAD, and does not conflict with "branch already checked out elsewhere" (that check only fires ongit checkout, not on moving one's own branch pointer viareset). - Proposal: where
worktree-branch-checkcurrently halts withexit 42on a base mismatch, let the executor repair itself —git reset --hard <orchestrator HEAD>on its own branch — and proceed, converting the halt into a self-heal.
Why MSD does not own this
- This is the exact primitive #48 removed, for the exact failure mode #48 was filed
to fix. #48 (closed,
approved-enhancement, shipped) replaced sub-agent-sidegit reset --hardrecovery with a verify-only, fail-closedexit 42check, specifically because (a) a permission deny-rule ongit reset --hard*— common in safety-conscious host configurations — can make the recovery command itself fail, and depending on shell error handling the sub-agent may silently proceed on the wrong base or report success without re-verifying; and (b) a sub-agent should not hold state-correction primitives (reset, force-move, branch-switch) on a worktree it did not create — that responsibility belongs to the lifecycle owner, the orchestrator. #4463's proposal reintroduces precisely this: the executor mutating its own worktree state in response to a detected mismatch, on the sub-agent side. - The shipped design is live in current source, not just historically decided.
msd-core/workflows/execute-phase/steps/worktree-recovery-policy.md:7states, verbatim: "worktree_branch_checkis verify-only — an executor that hits a base/HEAD-namespace mismatch printsFATAL:and exits 42 instead of self-recovering... The orchestrator — the worktree lifecycle owner — performs any base correction... the sub-agent never does." This is an active architectural invariant, not stale rationale from a closed issue. - The "it costs almost nothing and nothing objects" framing is exactly what #48 warned
about. #4463's own Finding 3 confirms
git reset --hardran with no hook and no refusal in its probe — which is the absence of a safety net #48 is trying to compensate for by moving the responsibility off the sub-agent entirely, not evidence the operation is safe to grant back to it.
What this does NOT cover
- The fork-base measurement itself is not denied and is worth keeping. If the
harness-worktree fork base is genuinely the orchestrator session's HEAD rather than
origin/HEAD, that is new information relevant to#3659's and#3779's closure rationale and to howworktree.base-check's degrade condition is described. A follow-up that only re-verifies and documents this measurement (with the session cwd inside a feature worktree, which the original probe did not test) is not this proposal and is welcome. - Orchestrator-side repair is a different proposal. #48's split explicitly assigns
base correction to the orchestrator (e.g., recreate the worktree on
{EXPECTED_BASE}, or fast-forward the branch from the orchestrator side before dispatch). A proposal that moves the repair step to the orchestrator, before or around dispatch, rather than having the executor self-repair after detecting a mismatch, is not denied here and would need its own review. - Fixing
#4415(cleanup-wave blocking when Claude Code has already removed the executor's worktree) is unrelated and not affected by this decision.
Re-open criteria
- A proposal that keeps repair on the orchestrator side of the #48 split (the lifecycle owner), not the sub-agent side — matching, not reversing, the shipped architecture.
- Or: a demonstrated, host-enforced guarantee that the executor's
git reset --hardcall cannot be silently denied or misreported by a permission policy — removing the specific failure mode #48 was filed against. Absent that guarantee, granting the primitive back to the sub-agent reintroduces the original risk regardless of how cheap the operation is in the success case.