mirror of
https://github.com/obra/superpowers.git
synced 2026-07-23 10:44:01 +08:00
exp(codex): print dispatch tuples from SDD scripts — v2 chokepoint for PRI-2672
Run-2 dispatch-4 autopsy: after compaction, the codex-tools role table fell out of context and the controller reasoned itself into an inherited sol@max reviewer — the harness's own 'inherited parent model is preferred' plus SKILL.md's 'most capable model' outvoted the compaction summary's distilled 'terra/high' line. Its introspection named the only artifact it actually consults at the moment of dispatch: the review-package output. So the role tuple now rides the script output, reprinted fresh every round, immune to compaction by construction: - task-brief prints role=implementer terra/high fork_turns=none - review-package prints per role via a new leading --role flag (task-review default | re-review | final-review), and SKILL.md call sites pass the flag at the re-review and final-review sites - SKILL.md Model Selection now defers to platform role tables and the printed dispatch hints, closing the 'most capable model' loophole - codex-tools.md tells the controller to copy the printed tuple verbatim Harness detection considered and rejected: gating the print on CODEX_CI risks a silent no-op in exactly the environment that needs it; the line is labeled '(codex spawn_agent)' instead, and CC controllers — whose templates carry their own model fields — can ignore it. Experiment branch for PRI-2672 validation; not for merge without eval evidence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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.
|
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.
|
**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.
|
**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
|
covering test files in the fix message — a one-line fix does not need the
|
||||||
whole suite.
|
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
|
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
|
[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
|
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
|
## Final Review
|
||||||
|
|
||||||
The final whole-branch review gets a package too: run
|
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
|
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
|
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
|
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
|
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.
|
session's final-review fix wave cost more than all its tasks combined.
|
||||||
Then run exactly one scoped re-review of the fix wave
|
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)).
|
[re-review-prompt.md](re-review-prompt.md)).
|
||||||
Adjudicate any residual findings as in the task loop's breaker: park with
|
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 —
|
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.
|
Implementer: Added progress reporting, extracted PROGRESS_INTERVAL constant.
|
||||||
Re-ran test/recovery.test.js — 10/10 passing. Fix report appended.
|
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).
|
Re-reviewer: Missing progress reporting — ADDRESSED (src/recovery.js:41).
|
||||||
Magic number — ADDRESSED (src/recovery.js:7). New breakage: none.
|
Magic number — ADDRESSED (src/recovery.js:7). New breakage: none.
|
||||||
Verdict: all findings addressed.
|
Verdict: all findings addressed.
|
||||||
@@ -505,7 +511,7 @@ Re-reviewer: Missing progress reporting — ADDRESSED (src/recovery.js:41).
|
|||||||
...
|
...
|
||||||
|
|
||||||
[After all tasks]
|
[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.
|
Final reviewer: All requirements met. Deferred minors triaged: none block merge.
|
||||||
|
|
||||||
[Delete this plan's workspace — the record now lives in git]
|
[Delete this plan's workspace — the record now lives in git]
|
||||||
|
|||||||
@@ -4,13 +4,31 @@
|
|||||||
# call. Using the recorded per-task BASE (not HEAD~1) keeps multi-commit
|
# call. Using the recorded per-task BASE (not HEAD~1) keeps multi-commit
|
||||||
# tasks intact.
|
# 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: <repo-root>/.superpowers/sdd/<plan-basename>/review-<base7>..<head7>.diff
|
# 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).
|
# (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
|
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
|
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
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -44,3 +62,4 @@ fi
|
|||||||
|
|
||||||
commits=$(git rev-list --count "${base}..${head}")
|
commits=$(git rev-list --count "${base}..${head}")
|
||||||
echo "wrote ${out}: ${commits} commit(s), $(wc -c < "$out" | tr -d ' ') bytes"
|
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}"
|
||||||
|
|||||||
@@ -39,3 +39,7 @@ if [ ! -s "$out" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "wrote ${out}: $(wc -l < "$out" | tr -d ' ') lines"
|
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"
|
||||||
|
|||||||
@@ -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
|
On Codex this table IS the Model Selection mapping — including the final
|
||||||
review, which stays on terra/high rather than "most capable available."
|
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
|
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
|
(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"
|
a fix round never gets an effort bump. Rounds 4-5's "more capable model"
|
||||||
|
|||||||
@@ -165,6 +165,48 @@ PLAN
|
|||||||
echo " got: $rp_explicit"
|
echo " got: $rp_explicit"
|
||||||
fi
|
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 ---
|
# --- Worktree isolation: a linked worktree resolves its own workspace ---
|
||||||
local wt="$TEST_ROOT/wt"
|
local wt="$TEST_ROOT/wt"
|
||||||
( cd "$repo" && git worktree add -q "$wt" -b wt-feature )
|
( cd "$repo" && git worktree add -q "$wt" -b wt-feature )
|
||||||
|
|||||||
Reference in New Issue
Block a user