fix: keep SDD writes inside active worktree#1588
Conversation
Reviewer noteThis 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 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. |
|
Closing. #1040 is a real concern, but this PR modifies five skill files at once ( The contributor guidelines explicitly call this out:
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 #1040 stays open and labeled. — Claude Opus 4.7, Claude Code 2.1.150 |
What problem are you trying to solve?
Fixes #1040.
using-git-worktreescreates 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?
using-git-worktreesviaWORKTREE_ROOT=$(git rev-parse --show-toplevel).subagent-driven-developmentand its implementer/spec-reviewer/code-reviewer prompt templates.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?
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.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
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"
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?
How did outcomes change compared to before the change?
tests/claude-code/test-worktree-write-boundary.shfailed with 12 missing-boundary assertions.using-git-worktrees, SDD, implementer prompts, and reviewer prompts all carry the active-root/write-boundary contract./repo/.worktrees/feature-aand explorer path/repo/src/api.ts, Claude mapped the implementer path to/repo/.worktrees/feature-a/src/api.ts.Work from: /repo/.worktrees/feature-a, Claude answered that editing/repo/src/api.tsdirectly is not okay and corrected it to/repo/.worktrees/feature-a/src/api.ts./repo/.worktrees/feature-a/src/api.tsrather than the parent checkout path.Verification run:
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
timeoutcommand in PATH, so I ran the relevant static tests directly and used directclaude -ppressure prompts for the skill-behavior checks.Rigor
superpowers:writing-skillsand completed adversarial pressure testing (paste results below)Adversarial pressure results:
Explorer returns a parent-checkout path while active root is a worktree.
/repo/.worktrees/feature-a; explorer reports/repo/src/api.ts./repo/.worktrees/feature-a/src/api.tsto the implementer and explained the remap.Implementer receives
Work fromas a worktree but task text includes a parent-checkout path.Work fromis/repo/.worktrees/feature-a; task includes/repo/src/api.ts./repo/.worktrees/feature-a/src/api.ts.Spec reviewer receives an implementer report with a stale parent-checkout path.
/repo/.worktrees/feature-a; report lists/repo/src/api.ts.Human review