mirror of
https://github.com/obra/superpowers.git
synced 2026-04-21 00:49:06 +08:00
docs: add worktree rototill design spec (PRI-974)
Design for detect-and-defer worktree support. Superpowers defers to native harness worktree systems when available, falls back to manual git worktree creation when not. Covers Phases 0-2: detection, consent, native tool preference, finishing state detection, and three bug fixes (#940, #999, #238). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
279
docs/superpowers/specs/2026-04-06-worktree-rototill-design.md
Normal file
279
docs/superpowers/specs/2026-04-06-worktree-rototill-design.md
Normal file
@@ -0,0 +1,279 @@
|
||||
# Worktree Rototill: Detect-and-Defer
|
||||
|
||||
**Date:** 2026-04-06
|
||||
**Status:** Draft
|
||||
**Ticket:** PRI-974
|
||||
**Subsumes:** PRI-823 (Codex App compatibility)
|
||||
|
||||
## Problem
|
||||
|
||||
Superpowers is opinionated about worktree management — specific paths (`.worktrees/<branch>`), specific commands (`git worktree add`), specific cleanup (`git worktree remove`). Meanwhile, Claude Code, Codex App, Gemini CLI, and Cursor all provide native worktree support with their own paths, lifecycle management, and cleanup.
|
||||
|
||||
This creates three failure modes:
|
||||
|
||||
1. **Duplication** — on Claude Code, the skill does what `EnterWorktree`/`ExitWorktree` already does
|
||||
2. **Conflict** — on Codex App, the skill tries to create worktrees inside an already-managed worktree
|
||||
3. **Phantom state** — skill-created worktrees at `.worktrees/` are invisible to the harness; harness-created worktrees at `.claude/worktrees/` are invisible to the skill
|
||||
|
||||
For harnesses without native support (Codex CLI, OpenCode, Copilot standalone), superpowers fills a real gap. The skill shouldn't go away — it should get out of the way when native support exists.
|
||||
|
||||
## Goals
|
||||
|
||||
1. Defer to native harness worktree systems when they exist
|
||||
2. Continue providing worktree support for harnesses that lack it
|
||||
3. Fix three known bugs in finishing-a-development-branch (#940, #999, #238)
|
||||
4. Make worktree creation opt-in rather than mandatory (#991)
|
||||
5. Replace hardcoded `CLAUDE.md` references with platform-neutral language (#1049)
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Per-worktree environment conventions (`.worktree-env.sh`, port offsetting) — Phase 4
|
||||
- PreToolUse hooks for path enforcement — Phase 4
|
||||
- Multi-repo worktree documentation — Phase 4
|
||||
- Brainstorming checklist changes for worktrees — Phase 4
|
||||
- `.superpowers-session.json` metadata tracking (interesting PR #997 idea, not needed for v1)
|
||||
- Hooks symlinking into worktrees (PR #965 idea, separate concern)
|
||||
|
||||
## Design Principles
|
||||
|
||||
### Detect state, not platform
|
||||
|
||||
Use `GIT_DIR != GIT_COMMON` to determine "am I already in a worktree?" rather than sniffing environment variables to identify the harness. This is a stable git primitive (since git 2.5, 2015), works universally across all harnesses, and requires zero maintenance as new harnesses appear.
|
||||
|
||||
### Declarative intent, prescriptive fallback
|
||||
|
||||
The skill describes the goal ("ensure work happens in an isolated workspace") and defers to native tools when available. It prescribes specific git commands only as a fallback for harnesses without native worktree support. Structurally, the native-tool path (Step 1a) comes first and is short; the git fallback (Step 1b) comes second and is long. This prevents agents from anchoring on the detailed fallback and skipping the preferred path.
|
||||
|
||||
### Provenance-based ownership
|
||||
|
||||
Whoever creates the worktree owns its cleanup. If the harness created it, superpowers doesn't touch it. If superpowers created it (via git fallback), superpowers cleans it up. The heuristic: if the worktree lives under `.worktrees/`, superpowers owns it. Anything else (`.claude/worktrees/`, `~/.codex/worktrees/`, `.gemini/worktrees/`) belongs to the harness.
|
||||
|
||||
## Design
|
||||
|
||||
### 1. `using-git-worktrees` SKILL.md Rewrite
|
||||
|
||||
The skill gains three new steps before creation and simplifies the creation flow.
|
||||
|
||||
#### Step 0: Detect Existing Isolation
|
||||
|
||||
```bash
|
||||
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
|
||||
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
|
||||
BRANCH=$(git branch --show-current)
|
||||
```
|
||||
|
||||
Three outcomes:
|
||||
|
||||
| Condition | Meaning | Action |
|
||||
|-----------|---------|--------|
|
||||
| `GIT_DIR == GIT_COMMON` | Normal repo checkout | Proceed to Step 0.5 |
|
||||
| `GIT_DIR != GIT_COMMON`, named branch | Already in a linked worktree | Skip to Step 3 (project setup). Report: "Already in isolated workspace at `<path>` on branch `<name>`." |
|
||||
| `GIT_DIR != GIT_COMMON`, detached HEAD | Externally managed worktree (e.g., Codex App sandbox) | Skip to Step 3. Report: "Already in isolated workspace at `<path>` (detached HEAD, externally managed)." |
|
||||
|
||||
Step 0 does not care who created the worktree or which harness is running. A worktree is a worktree regardless of origin.
|
||||
|
||||
#### Step 0.5: Consent
|
||||
|
||||
When Step 0 finds no existing isolation (`GIT_DIR == GIT_COMMON`), ask before creating:
|
||||
|
||||
> "Would you like me to set up an isolated worktree? This protects your current branch from changes. (y/n)"
|
||||
|
||||
If yes, proceed to Step 1. If no, work in place — skip to Step 3 with no worktree.
|
||||
|
||||
This step is skipped entirely when Step 0 detects existing isolation (no point asking about what already exists).
|
||||
|
||||
#### Step 1a: Native Tools (preferred)
|
||||
|
||||
> If your platform provides a worktree or workspace-isolation tool, use it. You know your own toolkit — the skill does not need to name specific tools. Native tools handle directory placement, branch creation, and cleanup automatically.
|
||||
|
||||
After using a native tool, skip to Step 3 (project setup).
|
||||
|
||||
This section is deliberately short (3 lines). Agents already know their available tools. Listing examples would risk agents attempting tools that don't exist on their platform.
|
||||
|
||||
#### Step 1b: Git Worktree Fallback
|
||||
|
||||
When no native tool is available, create a worktree manually.
|
||||
|
||||
**Directory selection** (priority order):
|
||||
1. Check for existing `.worktrees/` or `worktrees/` directory — if found, use it. If both exist, `.worktrees/` wins.
|
||||
2. Check the project's agent instruction file (CLAUDE.md, GEMINI.md, AGENTS.md, .cursorrules, or equivalent) for a worktree directory preference.
|
||||
3. Default to `.worktrees/`.
|
||||
|
||||
No interactive directory selection prompt. No global path option (`~/.config/superpowers/worktrees/` is dropped — no demonstrated user demand, adds cleanup and cross-device complexity).
|
||||
|
||||
**Safety verification** (project-local directories only):
|
||||
|
||||
```bash
|
||||
git check-ignore -q .worktrees 2>/dev/null
|
||||
```
|
||||
|
||||
If not ignored, add to `.gitignore` and commit before proceeding.
|
||||
|
||||
**Create:**
|
||||
|
||||
```bash
|
||||
git worktree add "$path" -b "$BRANCH_NAME"
|
||||
cd "$path"
|
||||
```
|
||||
|
||||
**Sandbox fallback:** If `git worktree add` fails with a permission error, treat as a restricted environment. Skip creation, work in current directory, proceed to Step 3.
|
||||
|
||||
#### Steps 3-4: Project Setup and Baseline Tests (unchanged)
|
||||
|
||||
Regardless of which path created the workspace (Step 0 detected existing, Step 1a native tool, Step 1b git fallback, or no worktree at all), execution converges:
|
||||
|
||||
- **Step 3:** Auto-detect and run project setup (`npm install`, `cargo build`, `pip install`, `go mod download`, etc.)
|
||||
- **Step 4:** Run the test suite. If tests fail, report failures and ask whether to proceed.
|
||||
|
||||
### 2. `finishing-a-development-branch` SKILL.md Rewrite
|
||||
|
||||
The finishing skill gains environment detection and fixes three bugs.
|
||||
|
||||
#### Step 1: Verify Tests (unchanged)
|
||||
|
||||
Run the project's test suite. If tests fail, stop. Don't offer completion options.
|
||||
|
||||
#### Step 1.5: Detect Environment (new)
|
||||
|
||||
Re-run the same detection as Step 0 in creation:
|
||||
|
||||
```bash
|
||||
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
|
||||
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
|
||||
```
|
||||
|
||||
Three paths:
|
||||
|
||||
| State | Menu | Cleanup |
|
||||
|-------|------|---------|
|
||||
| `GIT_DIR == GIT_COMMON` (normal repo) | Standard 4 options | No worktree to clean up |
|
||||
| `GIT_DIR != GIT_COMMON`, named branch | Standard 4 options | Provenance-based (see Step 5) |
|
||||
| `GIT_DIR != GIT_COMMON`, detached HEAD | Reduced menu: push as new branch + PR, keep as-is, discard | No merge options (can't merge from detached HEAD) |
|
||||
|
||||
#### Step 2: Determine Base Branch (unchanged)
|
||||
|
||||
#### Step 3: Present Options
|
||||
|
||||
**Normal repo and named-branch worktree:**
|
||||
|
||||
1. Merge back to `<base-branch>` locally
|
||||
2. Push and create a Pull Request
|
||||
3. Keep the branch as-is (I'll handle it later)
|
||||
4. Discard this work
|
||||
|
||||
**Detached HEAD:**
|
||||
|
||||
1. Push as new branch and create a Pull Request
|
||||
2. Keep as-is (I'll handle it later)
|
||||
3. Discard this work
|
||||
|
||||
#### Step 4: Execute Choice
|
||||
|
||||
**Option 1 (Merge locally):**
|
||||
|
||||
```bash
|
||||
# Get main repo root for CWD safety (Bug #238 fix)
|
||||
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
|
||||
|
||||
# Remove worktree BEFORE deleting branch (Bug #999 fix)
|
||||
cd "$MAIN_ROOT"
|
||||
git worktree remove "$WORKTREE_PATH" # only if superpowers owns it
|
||||
|
||||
# Now safe to work with branches
|
||||
git checkout <base-branch>
|
||||
git pull
|
||||
git merge <feature-branch>
|
||||
<run tests>
|
||||
git branch -d <feature-branch>
|
||||
```
|
||||
|
||||
**Option 2 (Create PR):**
|
||||
|
||||
Push branch, create PR. Do NOT clean up worktree — user needs it for PR iteration. (Bug #940 fix: remove contradictory "Then: Cleanup worktree" prose.)
|
||||
|
||||
**Option 3 (Keep as-is):** No action.
|
||||
|
||||
**Option 4 (Discard):** Require typed "discard" confirmation. Then remove worktree (if superpowers owns it), force-delete branch.
|
||||
|
||||
#### Step 5: Cleanup (updated)
|
||||
|
||||
```
|
||||
if GIT_DIR == GIT_COMMON:
|
||||
# Normal repo, no worktree to clean up
|
||||
done
|
||||
|
||||
if worktree path is under .worktrees/:
|
||||
# Superpowers created it — we own cleanup
|
||||
cd to main repo root # Bug #238 fix
|
||||
git worktree remove <path>
|
||||
|
||||
else:
|
||||
# Harness created it — hands off
|
||||
# If platform provides a workspace-exit tool, use it
|
||||
# Otherwise, leave the worktree in place
|
||||
```
|
||||
|
||||
Cleanup only runs for Options 1 and 4. Options 2 and 3 always preserve the worktree. (Bug #940 fix.)
|
||||
|
||||
### 3. Integration Updates
|
||||
|
||||
#### `subagent-driven-development` and `executing-plans`
|
||||
|
||||
Both currently list `using-git-worktrees` as REQUIRED in their integration sections. Change to:
|
||||
|
||||
> `using-git-worktrees` — Ensures isolated workspace (creates one or verifies existing)
|
||||
|
||||
The skill itself now handles consent (Step 0.5) and detection (Step 0), so calling skills don't need to gate or prompt.
|
||||
|
||||
#### `writing-plans`
|
||||
|
||||
Remove the stale claim "should be run in a dedicated worktree (created by brainstorming skill)." Brainstorming is a design skill and does not create worktrees. The worktree prompt happens at execution time via `using-git-worktrees`.
|
||||
|
||||
### 4. Platform-Neutral Instruction File References
|
||||
|
||||
All instances of hardcoded `CLAUDE.md` in worktree-related skills are replaced with:
|
||||
|
||||
> "your project's agent instruction file (CLAUDE.md, GEMINI.md, AGENTS.md, .cursorrules, or equivalent)"
|
||||
|
||||
This applies to directory preference checks in Step 1b.
|
||||
|
||||
## Bug Fixes (bundled)
|
||||
|
||||
| Bug | Problem | Fix | Location |
|
||||
|-----|---------|-----|----------|
|
||||
| #940 | Option 2 prose says "Then: Cleanup worktree (Step 5)" but quick reference says keep it. Step 5 says "For Options 1, 2, 4" but Common Mistakes says "Options 1 and 4 only." | Remove cleanup from Option 2. Step 5 applies to Options 1 and 4 only. | finishing SKILL.md |
|
||||
| #999 | Option 1 deletes branch before removing worktree. `git branch -d` can fail because worktree still references the branch. | Reorder: remove worktree first, then delete branch. | finishing SKILL.md |
|
||||
| #238 | `git worktree remove` fails silently if CWD is inside the worktree being removed. | Add CWD guard: `cd` to main repo root before `git worktree remove`. | finishing SKILL.md |
|
||||
|
||||
## Issues Resolved
|
||||
|
||||
| Issue | Resolution |
|
||||
|-------|-----------|
|
||||
| #940 | Direct fix (Bug #940) |
|
||||
| #991 | Opt-in consent in Step 0.5 |
|
||||
| #918 | Step 0 detection + Step 1.5 finishing detection |
|
||||
| #1009 | Step 0 detects harness-created worktrees and defers |
|
||||
| #999 | Direct fix (Bug #999) |
|
||||
| #238 | Direct fix (Bug #238) |
|
||||
| #1049 | Platform-neutral instruction file references |
|
||||
| #279 | Solved by detect-and-defer — native paths respected because we don't override them |
|
||||
| #574 | Partially addressed: consent prompt replaces the implicit handoff gap. Full fix (brainstorming checklist step) deferred to Phase 4 |
|
||||
|
||||
## Risks
|
||||
|
||||
### Step 1a agent anchoring
|
||||
|
||||
The highest-risk element. Step 1a is deliberately short (3 lines) to prevent agents from anchoring on it over the detailed Step 1b fallback. However, the inverse risk exists: agents may skip the short Step 1a and go straight to the detailed Step 1b. Mitigation: TDD validation using Claude Code's native worktree support (the richest available), with RED/GREEN tests confirming agents use native tools when available.
|
||||
|
||||
### Provenance heuristic
|
||||
|
||||
The `.worktrees/ = ours, anything else = hands off` heuristic works for every current harness. If a future harness adopts `.worktrees/` as its convention, we'd have a false positive (superpowers tries to clean up a harness-owned worktree). Low risk — every harness uses branded paths — but worth noting.
|
||||
|
||||
### Detached HEAD finishing
|
||||
|
||||
The reduced menu for detached HEAD worktrees (no merge option) is correct for Codex App's sandbox model. If a user is in detached HEAD for another reason, the reduced menu still makes sense — you genuinely can't merge from detached HEAD without creating a branch first.
|
||||
|
||||
## Future Work (not in this spec)
|
||||
|
||||
- **Phase 3 remainder:** `$TMPDIR` directory option (#666), setup docs for caching and env inheritance (#299)
|
||||
- **Phase 4:** PreToolUse hooks for path enforcement (#1040), per-worktree env conventions (#597), brainstorming checklist worktree step (#574), multi-repo documentation (#710)
|
||||
Reference in New Issue
Block a user