diff --git a/skills/subagent-driven-development/SKILL.md b/skills/subagent-driven-development/SKILL.md index 81984994..468a71a2 100644 --- a/skills/subagent-driven-development/SKILL.md +++ b/skills/subagent-driven-development/SKILL.md @@ -158,6 +158,12 @@ conflicts that only emerge from implementation. Use the least powerful model that can handle each role to conserve cost and increase speed. +When your platform's reference file (using-superpowers → Platform +Adaptation) defines a dispatch role table, that table IS this section's +mapping for your harness. Follow it over the tier language below — including +for the final review and fix-loop escalation — and follow the +`dispatch:` hint lines the task-brief and review-package scripts print. + **Mechanical implementation tasks** (isolated functions, clear specs, 1-2 files): use a fast, cheap model. Most implementation tasks are mechanical when the plan is well-specified. **Integration and judgment tasks** (multi-file coordination, pattern matching, debugging): use a standard model. @@ -340,7 +346,7 @@ 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 `scripts/review-package PLAN_FILE FIX_BASE HEAD` +**The re-review is scoped.** Run `scripts/review-package --role re-review PLAN_FILE FIX_BASE HEAD` 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 @@ -391,7 +397,7 @@ parked-with-ruling at the cap. ## Final Review The final whole-branch review gets a package too: run -`scripts/review-package PLAN_FILE MERGE_BASE HEAD` (MERGE_BASE = the commit the +`scripts/review-package --role final-review PLAN_FILE MERGE_BASE HEAD` (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 @@ -406,7 +412,7 @@ 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 -(`scripts/review-package PLAN_FILE FIX_BASE HEAD` over the fix range, +(`scripts/review-package --role re-review PLAN_FILE FIX_BASE HEAD` over the fix range, [re-review-prompt.md](re-review-prompt.md)). Adjudicate any residual findings as in the task loop's breaker: park with rulings, or stop on load-bearing ones. There is no second fix wave — @@ -494,7 +500,7 @@ Task reviewer: Spec ❌: Implementer: Added progress reporting, extracted PROGRESS_INTERVAL constant. Re-ran test/recovery.test.js — 10/10 passing. Fix report appended. -[Run review-package PLAN_FILE FIX_BASE HEAD; dispatch scoped re-review] +[Run review-package --role re-review PLAN_FILE FIX_BASE HEAD; dispatch scoped re-review] Re-reviewer: Missing progress reporting — ADDRESSED (src/recovery.js:41). Magic number — ADDRESSED (src/recovery.js:7). New breakage: none. Verdict: all findings addressed. @@ -505,7 +511,7 @@ Re-reviewer: Missing progress reporting — ADDRESSED (src/recovery.js:41). ... [After all tasks] -[Run review-package PLAN_FILE MERGE_BASE HEAD; dispatch final code-reviewer, most capable model] +[Run review-package --role final-review PLAN_FILE MERGE_BASE HEAD; dispatch final code-reviewer, most capable model] Final reviewer: All requirements met. Deferred minors triaged: none block merge. [Delete this plan's workspace — the record now lives in git] diff --git a/skills/subagent-driven-development/scripts/review-package b/skills/subagent-driven-development/scripts/review-package index 31852e2a..26c9c985 100755 --- a/skills/subagent-driven-development/scripts/review-package +++ b/skills/subagent-driven-development/scripts/review-package @@ -4,13 +4,31 @@ # 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 [--role task-review|re-review|final-review] PLAN_FILE BASE HEAD [OUTFILE] # Default OUTFILE: /.superpowers/sdd//review-...diff # (named per range, so a re-review after fixes gets a distinct fresh file). +# +# The trailing dispatch hint rides this output because the controller reads it +# immediately before spawning the reviewer; skill text loaded at session start +# does not survive context compaction, but this line is reprinted every round. set -euo pipefail +role=task-review +if [ "${1:-}" = "--role" ]; then + [ $# -ge 2 ] || { echo "usage: review-package [--role task-review|re-review|final-review] PLAN_FILE BASE HEAD [OUTFILE]" >&2; exit 2; } + role=$2 + shift 2 +fi + +case "$role" in + task-review) hint_role=task-reviewer; hint_effort=high ;; + re-review) hint_role=scoped-re-reviewer; hint_effort=medium ;; + final-review) hint_role=final-reviewer; hint_effort=high ;; + *) echo "bad --role: ${role} (task-review|re-review|final-review)" >&2; exit 2 ;; +esac + if [ $# -lt 3 ] || [ $# -gt 4 ]; then - echo "usage: review-package PLAN_FILE BASE HEAD [OUTFILE]" >&2 + echo "usage: review-package [--role task-review|re-review|final-review] PLAN_FILE BASE HEAD [OUTFILE]" >&2 exit 2 fi @@ -44,3 +62,4 @@ fi commits=$(git rev-list --count "${base}..${head}") echo "wrote ${out}: ${commits} commit(s), $(wc -c < "$out" | tr -d ' ') bytes" +echo "dispatch (codex spawn_agent): role=${hint_role} fork_turns=none model=gpt-5.6-terra reasoning_effort=${hint_effort}" diff --git a/skills/subagent-driven-development/scripts/task-brief b/skills/subagent-driven-development/scripts/task-brief index 612e14a1..e5cd4e88 100755 --- a/skills/subagent-driven-development/scripts/task-brief +++ b/skills/subagent-driven-development/scripts/task-brief @@ -39,3 +39,7 @@ if [ ! -s "$out" ]; then fi echo "wrote ${out}: $(wc -l < "$out" | tr -d ' ') lines" +# The dispatch hint rides this output because the controller reads it +# immediately before spawning the implementer; skill text loaded at session +# start does not survive context compaction, but this line reprints per task. +echo "dispatch (codex spawn_agent): role=implementer fork_turns=none model=gpt-5.6-terra reasoning_effort=high" diff --git a/skills/using-superpowers/references/codex-tools.md b/skills/using-superpowers/references/codex-tools.md index 5aa3f5f0..f7126e26 100644 --- a/skills/using-superpowers/references/codex-tools.md +++ b/skills/using-superpowers/references/codex-tools.md @@ -32,6 +32,9 @@ Before Task 1, check your `spawn_agent` tool schema for `model` and On Codex this table IS the Model Selection mapping — including the final review, which stays on terra/high rather than "most capable available." +The task-brief and review-package scripts reprint the applicable row as a +`dispatch (codex spawn_agent):` line with their output — copy those values +onto the spawn_agent call verbatim, every time, even late in a long session. Never give a subagent your session's model when you run a frontier config (sol at xhigh or max): reviewer tier never exceeds implementer tier, and a fix round never gets an effort bump. Rounds 4-5's "more capable model" diff --git a/tests/claude-code/test-sdd-workspace.sh b/tests/claude-code/test-sdd-workspace.sh index 84172301..1178f340 100755 --- a/tests/claude-code/test-sdd-workspace.sh +++ b/tests/claude-code/test-sdd-workspace.sh @@ -165,6 +165,48 @@ PLAN echo " got: $rp_explicit" fi + # --- dispatch hints ride the script output --- + if [[ "$brief_out" == *"dispatch (codex spawn_agent): role=implementer fork_turns=none model=gpt-5.6-terra reasoning_effort=high"* ]]; then + pass "task-brief prints the implementer dispatch hint" + else + fail "task-brief prints the implementer dispatch hint" + echo " got: $brief_out" + fi + + if [[ "$rp_out" == *"dispatch (codex spawn_agent): role=task-reviewer fork_turns=none model=gpt-5.6-terra reasoning_effort=high"* ]]; then + pass "review-package defaults to the task-reviewer dispatch hint" + else + fail "review-package defaults to the task-reviewer dispatch hint" + echo " got: $rp_out" + fi + + local rp_rereview + rp_rereview="$(cd "$repo" && "$SDD_SCRIPTS/review-package" --role re-review plan-a.md HEAD~1 HEAD)" + if [[ "$rp_rereview" == *"role=scoped-re-reviewer fork_turns=none model=gpt-5.6-terra reasoning_effort=medium"* ]]; then + pass "review-package --role re-review prints the medium-effort hint" + else + fail "review-package --role re-review prints the medium-effort hint" + echo " got: $rp_rereview" + fi + + local rp_final + rp_final="$(cd "$repo" && "$SDD_SCRIPTS/review-package" --role final-review plan-a.md HEAD~1 HEAD)" + if [[ "$rp_final" == *"role=final-reviewer fork_turns=none model=gpt-5.6-terra reasoning_effort=high"* ]]; then + pass "review-package --role final-review prints the final-reviewer hint" + else + fail "review-package --role final-review prints the final-reviewer hint" + echo " got: $rp_final" + fi + + rc=0 + (cd "$repo" && "$SDD_SCRIPTS/review-package" --role bogus plan-a.md HEAD~1 HEAD >/dev/null 2>&1) || rc=$? + if [[ "$rc" -eq 2 ]]; then + pass "review-package rejects an unknown --role with exit 2" + else + fail "review-package rejects an unknown --role with exit 2" + echo " exit: $rc" + fi + # --- Worktree isolation: a linked worktree resolves its own workspace --- local wt="$TEST_ROOT/wt" ( cd "$repo" && git worktree add -q "$wt" -b wt-feature )