Skip to content

fix: keep SDD writes inside active worktree#1588

Closed
YOMXXX wants to merge 2 commits into
obra:devfrom
YOMXXX:fix/worktree-path-isolation
Closed

fix: keep SDD writes inside active worktree#1588
YOMXXX wants to merge 2 commits into
obra:devfrom
YOMXXX:fix/worktree-path-isolation

Conversation

@YOMXXX
Copy link
Copy Markdown

@YOMXXX YOMXXX commented May 21, 2026

What problem are you trying to solve?

Fixes #1040.

using-git-worktrees creates or detects an isolated worktree, but the current workflow does not preserve that write boundary through the rest of implementation. In the reported failure mode, exploration/research agents return absolute paths from the parent checkout, and the controller or implementer passes those paths directly to write/edit/git commands. That silently writes changes into the main checkout or another worktree instead of the active implementation worktree.

This breaks the core promise of the worktree workflow: protecting the user's current branch from implementation changes.

What does this PR change?

  • Adds an explicit active workspace root contract to using-git-worktrees via WORKTREE_ROOT=$(git rev-parse --show-toplevel).
  • Threads that active root through subagent-driven-development and its implementer/spec-reviewer/code-reviewer prompt templates.
  • Adds a static regression test ensuring SDD keeps implementer and reviewer work inside the active worktree.

Is this change appropriate for the core library?

Yes. This is core workflow safety for all projects that use Superpowers worktrees and SDD. It is not project-specific, domain-specific, or tied to a third-party service. The change reinforces an existing core behavior: implementation work should stay inside the isolated worktree that Superpowers creates or detects.

What alternatives did you consider?

  1. Add hook-based hard enforcement around file writes. That would be stronger, but it would broaden this PR into platform-specific hook behavior and create a larger review surface.
  2. Only update using-git-worktrees. That would leave SDD implementer and reviewer prompts without the active root, which is where the issue reproduces when paths are passed between agents.
  3. Rely on "Work from: [directory]" alone. That text existed already and was not explicit enough to prevent stale absolute paths from being reused.

This PR keeps the fix small: establish the boundary once and make every SDD subagent prompt carry it.

Does this PR contain multiple unrelated changes?

No. All changes are tied to one problem: ensuring implementation and review work stays inside the active worktree root.

Existing PRs

#1121 established the native-tool-first worktree flow. #1153 and #1167 covered earlier worktree workflow adjustments. #170 was a broader closed safety-gates PR. I did not find an open or closed PR that specifically fixes #1040 by carrying an active workspace root through SDD implementer and reviewer prompts.

Environment tested

Harness (e.g. Claude Code, Cursor) Harness version Model Model version/ID
Claude Code CLI 2.1.141 Claude default CLI model
Shell/static tests macOS zsh n/a n/a

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

Not applicable. This PR does not add a new harness.

Clean-session transcript for "Let's make a react todo list"
Not applicable. This PR does not add a new harness.

Evaluation

  • What was the initial prompt you (or your human partner) used to start the session that led to this change?

  • How many eval sessions did you run AFTER making the change?

    • 3 short Claude Code pressure prompts after the change, plus static regression tests.
  • How did outcomes change compared to before the change?

    • Before: tests/claude-code/test-worktree-write-boundary.sh failed with 12 missing-boundary assertions.
    • After: the same test passes and verifies that using-git-worktrees, SDD, implementer prompts, and reviewer prompts all carry the active-root/write-boundary contract.
    • Pressure prompt 1: with active root /repo/.worktrees/feature-a and explorer path /repo/src/api.ts, Claude mapped the implementer path to /repo/.worktrees/feature-a/src/api.ts.
    • Pressure prompt 2: with Work from: /repo/.worktrees/feature-a, Claude answered that editing /repo/src/api.ts directly is not okay and corrected it to /repo/.worktrees/feature-a/src/api.ts.
    • Pressure prompt 3: as spec reviewer, Claude chose to inspect /repo/.worktrees/feature-a/src/api.ts rather than the parent checkout path.

Verification run:

bash tests/claude-code/test-worktree-write-boundary.sh
bash tests/claude-code/test-worktree-path-policy.sh
bash tests/hooks/test-session-start.sh
bash tests/opencode/run-tests.sh
git diff --check HEAD~1 HEAD

All commands above completed successfully in this environment.

Note: I also attempted the Claude Code skill test runner earlier, but this macOS environment does not have a timeout command in PATH, so I ran the relevant static tests directly and used direct claude -p pressure prompts for the skill-behavior checks.

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

Adversarial pressure results:

  1. Explorer returns a parent-checkout path while active root is a worktree.

    • Prompt: Active workspace root is /repo/.worktrees/feature-a; explorer reports /repo/src/api.ts.
    • Result: Claude passed /repo/.worktrees/feature-a/src/api.ts to the implementer and explained the remap.
  2. Implementer receives Work from as a worktree but task text includes a parent-checkout path.

    • Prompt: Work from is /repo/.worktrees/feature-a; task includes /repo/src/api.ts.
    • Result: Claude answered "No" to editing the parent path and corrected it to /repo/.worktrees/feature-a/src/api.ts.
  3. Spec reviewer receives an implementer report with a stale parent-checkout path.

    • Prompt: Review from /repo/.worktrees/feature-a; report lists /repo/src/api.ts.
    • Result: Claude chose the active worktree path and stated the parent checkout should not be inspected.

Human review

  • A human has reviewed the COMPLETE proposed diff before submission

@YOMXXX
Copy link
Copy Markdown
Author

YOMXXX commented May 21, 2026

Reviewer note

This PR is one of six small, independent PRs opened from the same triage pass. They can be reviewed and merged independently:

Focus for this PR: keep Subagent-Driven Development writes and reviews inside the active worktree root. The failure mode is a stale absolute path from a parent checkout being reused by implementers or reviewers after using-git-worktrees has selected an isolated workspace.

Review surface: skill/prompt text plus a static regression test. No runtime hook or new harness support.

Verification: worktree boundary test, worktree path policy test, hook tests, OpenCode tests, and Claude Code pressure prompts that remapped parent-checkout paths back into the active worktree.

Risk to check: whether the added root-boundary language is explicit enough without over-constraining legitimate reads outside the worktree.

@obra obra added bug Something isn't working subagents Subagent-driven development and dispatch worktrees Git worktree management labels May 23, 2026
@obra
Copy link
Copy Markdown
Owner

obra commented May 23, 2026

Closing.

#1040 is a real concern, but this PR modifies five skill files at once (using-git-worktrees, the SDD SKILL.md, and all three SDD prompt templates) for a total of 118 lines across 8 files. That's a wide blast radius for any change to carefully-tuned skill content, and there's no eval evidence that the new "active workspace root contract" prose actually changes implementer/reviewer behavior on a reproduction of the failure.

The contributor guidelines explicitly call this out:

Skills are not prose — they are code that shapes agent behavior. ... Do not modify carefully-tuned content ... without extensive evals showing the change is an improvement.

This PR is also part of a 17-PR batch which we close regardless of merit. If you want to revisit #1040, the right shape is a focused PR with a reproducible session that shows the worktree boundary actually being violated, plus before/after eval evidence on the smallest possible surface (probably just implementer-prompt.md).

#1040 stays open and labeled.

— Claude Opus 4.7, Claude Code 2.1.150

@obra obra closed this May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working subagents Subagent-driven development and dispatch worktrees Git worktree management

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants