Skip to content

fix(finishing): check in with human partner when worktree removal hits untracked files#2024

Open
obra wants to merge 1 commit into
devfrom
fix/worktree-cleanup-untracked-checkin
Open

fix(finishing): check in with human partner when worktree removal hits untracked files#2024
obra wants to merge 1 commit into
devfrom
fix/worktree-cleanup-untracked-checkin

Conversation

@obra

@obra obra commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Who is submitting this PR? (required)

Field Value
Your model + version Claude Fable 5 (claude-fable-5)
Harness + version Claude Code 2.1.218 (macOS)
All plugins installed superpowers (dev), superpowers-chrome, superpowers-lab, elements-of-style, episodic-memory, frontend-design, plugin-dev, agent-sdk-dev, mcp-server-dev, code-simplifier, claude-code-setup, context7, linear, github-triage, claude-session-driver, release-radar, summarize-meetings, worldview-synthesis, primeradiant-ops, plus personal skills
Human partner who reviewed this diff Jesse Vincent (@obra) — maintainer; specified this exact design interactively during triage of #2016/#1223 and reviews the final diff on this PR

What problem are you trying to solve?

git worktree remove refuses when the worktree contains modified or untracked files, and Step 6 of finishing-a-development-branch gave no guidance for that refusal. The error message itself suggests --force, so the natural agent response destroys files that exist nowhere else. Reported from two independent real sessions:

Both prior fix attempts baked in a policy: #2016 force-committed plan documents into every user's history (declined — not everyone wants superpowers plans committed), #1223 hard-refused with "commit or stash first, then re-run" (a wall that invites workarounds). Maintainer decision: the destruction point should check in with the human partner instead.

What does this PR change?

Step 6 now treats a refused git worktree remove as a stop-and-ask moment: never --force on the skill's own initiative; show git -C "$WORKTREE_PATH" status --porcelain output to the human partner and offer commit-to-branch / move-to-main-root / delete, then remove the worktree after the choice. One matching row is added to Common Rationalizations.

Is this change appropriate for the core library?

Yes — it modifies an existing core skill's cleanup step only. Applies to any project on any harness that uses worktrees; no dependencies, no domain-specific content.

What alternatives did you consider?

Does this PR contain multiple unrelated changes?

No. One file; the rationalization row exists solely to reinforce the new Step 6 behavior.

Existing PRs

Environment tested

Harness (e.g. Claude Code, Cursor) Harness version Model Model version/ID
Claude Code (macOS) 2.1.218 Claude Fable 5 claude-fable-5

New harness support (required if this PR adds a new harness)

N/A — no new harness.

Evaluation

  • Initial prompt: maintainer-directed, during interactive triage of fix(writing-plans): commit the plan document so worktree cleanup can't destroy it #2016: "not everyone wants to commit their superpowers plans" → "[the finishing-side guard] is not just about untracked superpowers docs, but about untracked files. it should check in with its human partner."
  • Loss path verified: the destruction this guards against was reproduced deterministically in-session with fix(writing-plans): commit the plan document so worktree cleanup can't destroy it #2016's pure-git recipe (refusal → --force → untracked file unrecoverable, committed file survives).
  • Behavioral micro-tests: not yet run. Honest scope note: this is an additive refusal-path branch (the omitted-element failure class), not a rewording of tuned content, but RED/GREEN fresh-context micro-tests per writing-skills methodology have not been executed for this wording. They can be run before or after merge at the maintainer's discretion.

Rigor

  • If this is a skills change: I used superpowers:writing-skills and completed adversarial pressure testing (paste results below)
  • This change was tested adversarially, not just on the happy path
  • I did not modify carefully-tuned content (Red Flags table, rationalizations, "human partner" language) without extensive evals showing the change is an improvement — the existing rows are untouched; one new row is added, flagged here for maintainer attention

The first two boxes are honestly unchecked: adversarial pressure testing is pending, as stated in Evaluation. The maintainer directed this change and owns the merge decision with that gap visible.

Human review

  • A human has reviewed the COMPLETE proposed diff before submission — the human partner is the repo maintainer, who commissioned the change and performs that review on this PR

…s untracked files

git worktree remove refuses when the tree holds modified or untracked
files, and the skill gave no guidance for that refusal — the natural
agent response was --force, permanently destroying files that exist
nowhere else (uncommitted plans, notes, scratch work). Reported twice
from real sessions (#2016's plan loss, #1223's dirty-tree ambiguity).

Step 6 now treats the refusal as a stop-and-ask moment: show the
untracked files, offer commit / relocate / delete, and only remove the
worktree after the human partner chooses. Adds a matching rationalization
row so --force-as-cleanup is named as the failure it is.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant