Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
299 changes: 35 additions & 264 deletions external/ai-agents/subagent-driven-development/SKILL.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Subagent (general-purpose):
- `[FIX_BASE_SHA]` — the head the previous review saw
- `[HEAD_SHA]` — current commit
- `[DIFF_FILE]` — the path `bash scripts/review-package PLAN_FILE FIX_BASE HEAD` printed
(run by its absolute path, from the working tree you're executing in)

**Re-reviewer returns:** per-finding verdicts (ADDRESSED / NOT ADDRESSED),
new breakage in the fix diff, out-of-scope observations, and a round verdict.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Batching Small Same-Shape Work

Part of superpowers:subagent-driven-development.

**Batch small same-shape work.** When the plan lists several tasks that are
each a small, independent edit of the same kind — the same one-line fix,
constant change, or field addition repeated across files — do not dispatch
one subagent per task. Compose ONE dispatch brief listing every file and
its change, send the whole batch to a single subagent, and review its diff
as one unit. Reserve one-dispatch-per-task for work that needs its own
judgment, its own tests, or its own review surface.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# "Cannot Verify From Diff" Items

Part of superpowers:subagent-driven-development.

The task reviewer may report "⚠️ Cannot verify from diff" items — requirements
that live in unchanged code or span tasks. These do not block the rest of the
review, but you must resolve each one yourself before marking the task
complete: you hold the plan and cross-task context the reviewer
lacks. If you confirm an item is a real gap, treat it as a failed spec
review — it enters the fix loop with the other findings.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Final Review and Finish

Part of superpowers:subagent-driven-development. Every task in the plan is
complete.

The final whole-branch review gets a package too: run
`bash scripts/review-package PLAN_FILE MERGE_BASE HEAD` by its absolute path,
from the working tree you're executing in (MERGE_BASE = the commit the
branch started from, e.g. `git merge-base main HEAD`) and include the
printed path in the final review dispatch, so the final reviewer reads
one file instead of re-deriving the branch diff with git commands. Dispatch
on the most capable available model (see SKILL.md's Model Selection), using
superpowers:requesting-code-review's
[code-reviewer.md](../../requesting-code-review/code-reviewer.md). Point it at
the ledger's deferred-minor and parked lines so it can triage which must be
fixed before merge.

If the final whole-branch review returns findings, dispatch ONE fix subagent
with the complete findings list — not one fixer per finding.
Per-finding fixers each rebuild context and re-run suites; a real
session's final-review fix wave cost more than all its tasks combined.
Then run exactly one scoped re-review of the fix wave
(`bash scripts/review-package PLAN_FILE FIX_BASE HEAD` by its absolute path,
from the working tree you're executing in, over the fix range,
[re-review-prompt.md](../re-review-prompt.md)).
Adjudicate any residual findings as in the fix loop's breaker
(references/fix-loop.md): park with rulings, or rule on the load-bearing
ones and ledger what you decided. Only the four things that stop a running
plan (top of SKILL.md) stop you here. There is no second fix wave —
residual load-bearing findings surface to your human partner when
finishing-a-development-branch presents the options.

### Finish

Before you delete anything, collect every ledger line containing `Ruling:` —
preflight rulings, parked findings, breaker adjudications, all of them — into
your final message under "Rulings I made", in the order you made them, each
with what it costs if wrong. The list is exhaustive: if the ledger holds a
ruling, the list holds it. That list is the only place the decisions you
took on your human partner's behalf reach them — they read it and rework
whatever you got wrong. A ruling that dies with the workspace was a decision
made in secret.

When the final whole-branch review is clean and its fixes are merged,
delete this plan's workspace (`rm -rf <workspace>`) — the git history is
the record now. Sibling directories belong to other plans; leave them
alone.

Use superpowers:finishing-a-development-branch.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# The Fix Loop

Part of superpowers:subagent-driven-development. The task review reported
spec ❌, a Critical or Important finding, or a ⚠️ item you confirmed as a real
gap.

Before the loop starts, two routes leave it immediately:

- Record Minor findings in the progress ledger as you go
(`Task <N>: minor (deferred): <one-liner>`), and point the final
whole-branch review at that list so it can triage which must be fixed
before merge. A roll-up nobody reads is a silent discard. Minor findings
never enter the loop.
- A finding labeled plan-mandated — or any finding that conflicts with
what the plan's text requires — is yours to rule on: weigh the finding
against the plan text, decide with the spec as the binding authority, and
ledger the ruling before you act on it. Do not dismiss the finding because
the plan mandates it, and do not dispatch a fix that contradicts the plan
without a recorded ruling.
Everything else enters the loop. A fix round is one fix dispatch plus one
scoped re-review. Five rounds maximum per task:

**Rounds 1-3 — resume the original implementer.** Send it the open findings
verbatim. Its context is intact: it knows the task, the code, and its own
choices. If your harness cannot send another message to a live subagent,
dispatch a fresh implementer carrying the brief path, the report-file path,
and the findings — the report file is the persistent memory either way.

**Rounds 4-5 — dispatch a fresh implementer on a more capable model** (per
SKILL.md's Model Selection), with the brief path, the report-file path, the open
findings, and this framing: "A prior implementer attempted this task
[N] times; you own it now. Read the report file for what was tried." A loop
that survives three resumes usually means the implementer cannot see its
own problem — fresh eyes and a capability bump in one move.

**Every round, either way:** the implementer fixes, re-runs the tests
covering the amended code, appends its fix report to the same report file,
and returns the short contract. Before re-dispatching the reviewer, confirm
the fix report contains the covering tests, the command run, and the
output; dispatch the re-review once all three are present. Name the
covering test files in the fix message — a one-line fix does not need the
whole suite.

**The re-review is scoped.** Run `bash scripts/review-package PLAN_FILE FIX_BASE HEAD`
by its absolute path, from the working tree you're executing in, where FIX_BASE is the head the previous review saw, and dispatch
[re-review-prompt.md](../re-review-prompt.md) with the findings list, the
brief, the report file, and the printed diff path. The re-reviewer verdicts
each finding ADDRESSED or NOT ADDRESSED and flags new breakage in the fix
diff only. New Critical/Important breakage in the fix diff joins the open
findings list. Out-of-scope observations go to the ledger as deferred
minors — they never extend the loop.

**After each round,** append to the ledger:
`Task <N>: fix round <R>/5 (<X> addressed, <Y> open — <finding one-liners>; commits <a7>..<b7>)`

Never fix findings yourself in the controller session — your context stays
clean for coordination, and controller fixes skip review.

**The breaker.** When round 5's re-review still leaves findings open, stop
dispatching. Adjudicate each open finding yourself — you hold the plan and
the cross-task context the reviewer lacks:

- **The reviewer is wrong, or the point is contestable:** park it —
`Task <N>: parked — <finding> — Ruling: <why the code stands>`. The final
review sees both sides.
- **Real, but nothing downstream builds on it:** park it the same way, with
a ruling that says it's real and deferred.
- **Real and load-bearing** — a later task builds on it, or it reveals a
plan defect: rule on the smallest change that unblocks the dependent work,
ledger it as `Task <N>: Ruling: <finding> — <what you decided and why>`,
and carry it into the next task's dispatch. Parking a structural failure
silently lets every dependent task build on it. Stop only when the defect
leaves every path forward a guess.

Adjudicate only at the cap. Adjudicating earlier to end a loop is
pre-judging with a different name. Every adjudication is a ledger entry —
a silent discard is forbidden.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Handling a Report That Isn't DONE

Part of superpowers:subagent-driven-development.

**DONE_WITH_CONCERNS:** The implementer completed the work but flagged doubts. Read the concerns before proceeding. If the concerns are about correctness or scope, address them before review. If they're observations (e.g., "this file is getting large"), note them and proceed to review.

**NEEDS_CONTEXT:** The implementer needs information that wasn't provided. Provide the missing context and re-dispatch.

**BLOCKED:** The implementer cannot complete the task. Assess the blocker:
1. If it's a context problem, provide more context and re-dispatch with the same model
2. If the task requires more reasoning, re-dispatch with a more capable model
3. If the task is too large, break it into smaller pieces
4. If the plan itself is wrong, rule on the correction, ledger it, and re-dispatch with the ruling carried in the dispatch

**Never** ignore an escalation or force the same model to retry without changes. If the implementer said it's stuck, something needs to change.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# The Pre-flight Scan

Part of superpowers:subagent-driven-development. Run it once, before
dispatching Task 1.

Before dispatching Task 1, scan the plan once for conflicts, writing down
what you checked as you check it:

- tasks that contradict each other or the plan's Global Constraints
- anything the plan explicitly mandates that the review rubric treats as a
defect (a test that asserts nothing, verbatim duplication of a logic block)

The scan's output is a table, not a verdict. One row for every pair of tasks
that share a file or an interface: the two tasks, what one produces against
what the other consumes, and what you found. One row for every task: whether
its own text agrees with itself — the tests it specifies against the code it
specifies, the files it creates against the files it later touches. "The scan
is clean" without those rows is not a scan you ran.

Write the table to the ledger. Rule on everything you find before execution
begins — each finding against the plan text that mandates it — and record
each ruling in the ledger. If the scan is clean, proceed without comment.
Rule on each conflict it surfaces — the spec is the binding authority, the
plan is its argument — record the ruling beside its row, and dispatch
Task 1. The review loop remains the net for conflicts that only emerge from
implementation.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Resuming From an Existing Ledger

Part of superpowers:subagent-driven-development. This plan's workspace
already has a ledger at `<workspace>/progress.md`.

If the ledger's first line names your plan file, tasks with a `Task <N>:
complete` line are DONE — do not re-dispatch them; resume at the first
task without one. A task whose last line is a fix round is mid-loop:
resume the loop at the next round. A ledger whose first line names a
different plan file — or a stray ledger at the old flat path
`.superpowers/sdd/progress.md` — is another plan's progress: leave it in
place and start your own, fresh.
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@
# call. Using the recorded per-task BASE (not HEAD~1) keeps multi-commit
# tasks intact.
#
# Usage: review-package PLAN_FILE BASE HEAD [OUTFILE]
# Usage: review-package [-C DIR] PLAN_FILE BASE HEAD [OUTFILE]
# Default OUTFILE: <repo-root>/.superpowers/sdd/<plan-basename>/review-<base7>..<head7>.diff
# (named per range, so a re-review after fixes gets a distinct fresh file).
# The repository is the one sdd-repo names; -C DIR runs as if started in DIR,
# as in sdd-workspace.
set -euo pipefail

here=$(cd "$(dirname "$0")" && pwd)
if [ "${1:-}" = "-C" ]; then
[ -d "${2:-}" ] || { echo "bad -C directory: ${2:-}" >&2; exit 2; }
cd "$2"
shift 2
fi

if [ $# -lt 3 ] || [ $# -gt 4 ]; then
echo "usage: review-package PLAN_FILE BASE HEAD [OUTFILE]" >&2
echo "usage: review-package [-C DIR] PLAN_FILE BASE HEAD [OUTFILE]" >&2
exit 2
fi

Expand All @@ -19,35 +28,37 @@ base=$2
head=$3
[ -f "$plan" ] || { echo "no such plan file: $plan" >&2; exit 2; }

git rev-parse --verify --quiet "$base" >/dev/null || { echo "bad BASE: $base" >&2; exit 2; }
git rev-parse --verify --quiet "$head" >/dev/null || { echo "bad HEAD: $head" >&2; exit 2; }
# Invoke via bash rather than direct exec: some extractors (Python zipfile)
# strip Unix exec bits when unpacking marketplace packages (#2040).
repo=$("${BASH:-bash}" "$here/sdd-repo" --with-commit)

git -C "$repo" rev-parse --verify --quiet "$base" >/dev/null || { echo "bad BASE: $base" >&2; exit 2; }
git -C "$repo" rev-parse --verify --quiet "$head" >/dev/null || { echo "bad HEAD: $head" >&2; exit 2; }

# Range guards (exit 3): a wrong-branch HEAD yields a range that is empty or
# not rooted at BASE; either would silently produce a bogus review package.
git merge-base --is-ancestor "$base" "$head" || { echo "HEAD is not a descendant of BASE: ${base}..${head}" >&2; exit 3; }
[ "$(git rev-list --count "${base}..${head}")" -gt 0 ] || { echo "empty commit range: ${base}..${head}" >&2; exit 3; }
git -C "$repo" merge-base --is-ancestor "$base" "$head" || { echo "HEAD is not a descendant of BASE: ${base}..${head}" >&2; exit 3; }
[ "$(git -C "$repo" rev-list --count "${base}..${head}")" -gt 0 ] || { echo "empty commit range: ${base}..${head}" >&2; exit 3; }

if [ $# -eq 4 ]; then
out=$4
else
# Invoke via bash rather than direct exec: some extractors (Python zipfile)
# strip Unix exec bits when unpacking marketplace packages (#2040).
dir=$("${BASH:-bash}" "$(cd "$(dirname "$0")" && pwd)/sdd-workspace" "$plan")
out="$dir/review-$(git rev-parse --short "$base")..$(git rev-parse --short "$head").diff"
dir=$("${BASH:-bash}" "$here/sdd-workspace" "$plan")
out="$dir/review-$(git -C "$repo" rev-parse --short "$base")..$(git -C "$repo" rev-parse --short "$head").diff"
fi

{
echo "# Review package: ${base}..${head}"
echo
echo "## Commits"
git log --oneline "${base}..${head}"
git -C "$repo" log --oneline "${base}..${head}"
echo
echo "## Files changed"
git diff --stat "${base}..${head}"
git -C "$repo" diff --stat "${base}..${head}"
echo
echo "## Diff"
git diff -U10 "${base}..${head}"
git -C "$repo" diff -U10 "${base}..${head}"
} > "$out"

commits=$(git rev-list --count "${base}..${head}")
commits=$(git -C "$repo" rev-list --count "${base}..${head}")
echo "wrote ${out}: ${commits} commit(s), $(wc -c < "$out" | tr -d ' ') bytes"
54 changes: 54 additions & 0 deletions external/ai-agents/subagent-driven-development/scripts/sdd-repo
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
# Print the top-level directory of the git working tree the SDD scripts use:
# the current directory's, exactly as git itself picks one. A caller that
# means a different working tree says so with the scripts' -C DIR, which
# they apply (cd) before calling this.
#
# The plan file's location never picks the repository. An executor working
# in a linked worktree commonly holds an absolute path to the plan in the
# main checkout (writing-plans leaves the plan uncommitted there), and its
# workspace and commits belong to the worktree it is working in. And a
# caller standing outside any repository, such as the skill's own directory
# in an installed plugin, is in the wrong place: guessing a repository from
# the plan would silently act on whichever checkout the path points into.
#
# Outside any working tree, stop. --with-commit also stops on a repository
# with no commit yet, for callers that need HEAD as a BASE or a review
# range. The message covers both ways to get here: running from the wrong
# directory (where 'git init' would be the wrong fix) and a new project
# that has no repository or commit yet.
#
# Single source of truth for which repository the SDD and executing-plans
# scripts work in, so no two of them can disagree.
#
# Usage: sdd-repo [--with-commit]
set -euo pipefail

with_commit=false
if [ "${1:-}" = "--with-commit" ]; then
with_commit=true
shift
fi

if [ $# -ne 0 ]; then
echo "usage: sdd-repo [--with-commit]" >&2
exit 2
fi

if root=$(git rev-parse --show-toplevel 2>/dev/null); then
if [ "$with_commit" = false ] || git -C "$root" rev-parse --verify --quiet HEAD >/dev/null; then
printf '%s\n' "$root"
exit 0
fi
said=$(git -C "$root" rev-parse --verify HEAD 2>&1 >/dev/null) || true
else
said=$(git rev-parse --show-toplevel 2>&1 >/dev/null) || true
fi

# git's own first line always follows the shared message: where git refuses
# a working tree the caller is inside (dubious ownership, git missing from
# PATH, the cwd inside .git), the shared message alone would be wrong, and
# git's line names the real fix.
echo "SDD scripts must run from inside the git working tree you're executing in, with at least one commit (current directory: $PWD). If this is a new project, run 'git init' and make a first commit, then rerun." >&2
echo "git said: ${said%%$'\n'*}" >&2
exit 2
Loading
Loading