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:
Drew Ritter
2026-07-21 14:30:12 -07:00
parent 3921dc9998
commit d123bde46e
5 changed files with 81 additions and 7 deletions

View File

@@ -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]

View File

@@ -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}"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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 )