Skip to content

fix(codex): bound SDD dispatch and final review#2036

Draft
arittr wants to merge 6 commits into
devfrom
codex/sdd-review-loop-fix
Draft

fix(codex): bound SDD dispatch and final review#2036
arittr wants to merge 6 commits into
devfrom
codex/sdd-review-loop-fix

Conversation

@arittr

@arittr arittr commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Who is submitting this PR? (required)

Field Value
Your model + version Branch authoring: Anthropic Claude Fable 5 (claude-fable-5). Stack preparation/submission: OpenAI gpt-5.6-sol at max effort.
Harness + version Branch authoring: Claude Code 2.1.216–2.1.218. Stack preparation/submission: Codex Desktop 0.146.0-alpha.3.1.
All plugins installed Claude Code authoring environment: cloud-build, decision-log, elements-of-style, episodic-memory, greenfield, iterative-development, linear, primeradiant-ops, superpowers-chrome, superpowers (local dev), unifi-network. Codex submission environment: documents, pdf, spreadsheets, presentations, template-creator, sites, browser, computer-use, visualize, primeradiant-ops, linear, slack, github, codex-security, superpowers (local dev), cloud-build.
Human partner who reviewed this diff Drew Ritter — reviewed and approved the complete combined diff on 2026-07-24, then explicitly directed this exact split. This PR is the lower, self-contained subset of that reviewed diff.

The commits identify Claude Fable 5 as co-author. Codex performed the current-dev rebase, deterministic verification, duplicate search, stack split, and PR submission.

This is PR 1 of 2. The Codex compaction-hook work follows in #2035.

What problem are you trying to solve?

Drew reported a real Codex/Superpowers reliability failure: SDD implementations that normally finished in 1–2 hours in Claude Code were taking 8+ hours in Codex, often without finishing. Agents looped through review and minor test fixes, expanded beyond the approved plan, or turned a bounded final review into repeated competing review waves.

The deduplicated session corpus showed 8/22 GPT-5.6-era runs spinning out versus 2/36 GPT-5.5-era runs. One 14-task run spent eight hours completing only six tasks; another reached a terminal final-review loop that continued for more than three hours without a reachable stop state.

This layer addresses three measured causes:

  1. Codex spawn_agent defaults to full-history forks, and full-history forks refuse per-call model/effort overrides.
  2. Omitted routing makes children inherit the frontier parent, accumulating expensive review/fix seats instead of explicit role routing.
  3. Final review lacked an enforceable wave-closing policy, while implementer reports could claim a full-suite gate using stale output from before later edits.

The post-compaction bootstrap loss that can reintroduce this drift is handled separately in the stacked follow-up, #2035.

What does this PR change?

This PR pins Codex SDD dispatches to fork_turns: "none" with platform-owned per-role model/effort hints, bounds final review to one fix dispatch plus one scoped fix review, and renames “re-review” to “fix review” so the target is the fix diff. It also requires exact commands and fresh output tails for implementer gate claims, with deterministic coverage for hint routing, role validation, Claude Code suppression, and the bounded review workflow.

Is this change appropriate for the core library?

Yes. Codex is an existing first-class Superpowers harness, and SDD is a general-purpose core workflow. The failure occurs across projects and customers; the changes are not Prime Radiant-specific, add no dependency, and keep Codex-specific routing values in the existing platform reference rather than hard-coding them into shared scripts.

What alternatives did you consider?

  • Keep full-history forks and only request lower tiers. Rejected because full-history forks refuse model/effort overrides and copy the largest possible context into every child.
  • Hard-code Codex model names in shared SDD scripts. Rejected because shared scripts also run under other harnesses. The role table remains platform-owned and is suppressed under Claude Code.
  • Run progressively stronger reviewers until one returns clean. Rejected because the reviewer matrix showed strong reviewers continue finding real but progressively narrower defects. Convergence needs a controller-owned wave policy.
  • Add a broad wall-clock or suite governor first. Deferred because a generic timeout would cut off legitimate work without fixing the measured dispatch and termination mechanisms.
  • Rely on prose without boundary hints. Rejected because the controller repeatedly consulted task-brief and review-package immediately before dispatch; those are the durable chokepoints for the routing tuple.

Does this PR contain multiple unrelated changes?

No. Dispatch routing, bounded final review, the scoped fix-review contract, and evidence-locked completion claims all address the same SDD spinout loop. The separable post-compaction hook and packaging work is intentionally isolated in stacked PR #2035.

Existing PRs

No duplicate PR was found for Codex SDD spinout, fork_turns pinning, role-bound review dispatch, or bounded final-review termination.

Environment tested

Harness Harness version Model Model version/ID
Codex App manual failure/fix runs Codex 0.145.0 family GPT-5.6 Sol parent with explicit Terra child routing gpt-5.6-sol; gpt-5.6-terra
superpowers-evals RED/GREEN campaign codex-spinout-scenarios @ 3c0a2f7, Codex 0.145.0 GPT-5.6 Sol parent at max; role-pinned children gpt-5.6-sol; gpt-5.6-terra
superpowers-evals regression guards campaign @ 3c0a2f7 Claude Opus 4.8 claude-opus-4-8
Fresh lower-layer deterministic check macOS, bash/zsh n/a tests/claude-code/test-sdd-workspace.sh

New harness support (required if this PR adds a new harness)

Not applicable. Codex is already supported; this changes SDD routing and review-loop behavior in that existing harness.

Clean-session transcript for "Let's make a react todo list"
Not applicable: this PR does not add a new harness or change Codex's clean-session startup path.

Evaluation

  • Initial prompt: Drew reported that roughly half of his recent Codex SDD implementations were spinning out from expected 1–2 hour executions to 8+ hours, with review loops, minor-test churn, scope expansion, and unfinished plans. He supplied three recent session IDs and requested a multi-session diagnosis before any fix.
  • Eval sessions after the change: two manual Codex App validation runs, followed by a RED/GREEN campaign of approximately 43 cells: three reps per RED/GREEN cell and two reps per regression guard.
  • Before/after: the previously spun-out final-review continuation completed in 81 minutes with a single bounded review cycle. The formerly spun-out 14-task plan then completed its remaining tasks and final review; after the v2 boundary hints, roughly 20 consecutive dispatches stayed correctly routed across two compactions.

Recorded campaign results in prime-radiant-inc/superpowers-evals branch codex-spinout-scenarios:

  • sdd-codex-dispatch-pinning: RED was bimodal/unpinned; GREEN 3/3 gauntlet passes.
  • sdd-codex-no-tier-escalation: RED 3/3 inherited or escalated; GREEN 3/3 passes.
  • sdd-final-review-contaminated-resume: RED met the planned probabilistic threshold; GREEN 3/3 passes.
  • Across those three structural scenarios, GREEN was 18/18 gauntlet plus deterministic checks.
  • sdd-implementer-evidence-locked-report: improved from 1/3 to 2/3 judge passes, so this remains an explicit partial GREEN, not a claim of full binding.
  • The critical Claude Code guard sdd-round4-escalates-model was 2/2 clean. No regression-guard failure was attributable to this branch; unrelated anomalies and infrastructure/judge failures remain documented in the campaign record.

No new behavioral eval was run merely to split the already-reviewed branch. Fresh split verification was deterministic:

git diff --check origin/dev...codex/sdd-review-loop-fix
bash tests/claude-code/test-sdd-workspace.sh
# 19/19 checks passed

Rigor

  • If this is a skills change: I used superpowers:writing-skills and completed adversarial pressure testing (results above)
  • This change was tested adversarially, not just on the happy path
  • I did not modify carefully-tuned content (Red Flags table, rationalizations, "human partner" language) without extensive evals showing the change is an improvement

The pressure cases combine frontier-parent inheritance, round-four escalation pressure, contaminated final-review history, stale evidence claims, and a Claude Code regression column. The branch adds final-wave rationalization counters because those exact rationalizations appeared in the failed field sessions; it does not broadly rewrite the skill's voice or philosophy.

Human review

  • A human has reviewed the COMPLETE proposed diff before submission

Drew reviewed the complete combined GitHub compare, explicitly approved submission on 2026-07-24, and then requested this exact two-PR split. This lower PR is an unchanged subset of that reviewed diff.

arittr and others added 6 commits July 24, 2026 12:31
…dation

Experiment branch — NOT for merge without eval evidence (writing-skills
discipline; RED/GREEN campaign to follow if the manual run validates).

Two targeted changes against the measured Codex 5.6-era spinout
(36% of SDD runs >8h, PRI-2672):

1. codex-tools.md — SDD dispatch rules: fork_turns "none" on every
   spawn (the default "all" forks the whole transcript and refuses
   model/effort overrides — S2's terminal 13-agent final wave was all
   full-history forks at sol/xhigh); capability-check for 0.145+ spawn
   params with an explicit terra/high role table (re-review terra/medium),
   no sol seats, no effort escalation between fix rounds; honest
   inheritance warning for <=0.144 where routing is impossible (T0-probed
   on 0.144.4: schema is {task_name, message, fork_turns} only, role
   TOMLs inert).

   Role-table bet: census shows task seats already ran terra/high in the
   spinout sessions — the surgical bet is fork_turns:none + no-sol-seats
   + wave termination, not task-seat downgrade. T1 cross-review matrix
   will refine reviewer tiers (may support terra/medium or lower).

2. SKILL.md final review — wave closure is policy, not a verdict:
   strong reviewers find real defects indefinitely, so "review until
   clean" never terminates; new breakage in the final fix diff joins
   residual adjudication instead of opening wave two; one-off human
   review procedures (competing reviewers, scoring) never become
   standing. Two matching rationalization-table rows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r 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>
…e termination

Codex SDD runs at frontier tiers spin out: subagents inherit the
session's model and effort, review seats find real-but-endless defects
every round, and the final whole-branch review has no reachable
termination state. Field forensics across multiple real sessions traced
the mechanism: spawn_agent's fork_turns defaults to "all" (full-context
forks that also refuse model overrides), omitted model/effort params
inherit the frontier parent, and dispatch rules loaded at session start
do not survive context compaction — a compacted controller reverts to
inheritance exactly when the session is longest and most expensive.

Three coordinated changes:
- codex-tools.md: every SDD spawn sets fork_turns "none" plus explicit
  model/reasoning_effort when the schema supports them (Codex 0.145+),
  with an inheritance warning for older builds; reviewer tier never
  exceeds implementer tier and fix rounds never get effort bumps.
- task-brief/review-package print a dispatch tuple with their output
  (review-package grows --role for re-review/final-review), putting the
  routing values in front of the controller at the moment of dispatch —
  reprinted every round, so they survive compaction by construction.
- SKILL.md: the final-review wave closing is policy, not a verdict —
  one fix dispatch, one scoped re-review, residuals adjudicated to the
  ledger; one-off review procedures never become standing; Model
  Selection defers to platform role tables where one exists.

Validated live: a previously spun-out 14-task run (8h, 6 tasks, died
mid-loop) re-executed to completion under these changes — bounded fix
loops, single-cycle final review, ~20 consecutive correctly-routed
dispatches across two compactions. Reviewer-tier matrix (125 cells)
showed no calibration cost: clean-diff approvals and planted-defect
recall are identical across tiers. Eval scenarios to follow before any
upstream submission.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…o Codex literals

Responds to maintainer review of this branch: the dispatch-hint lines
were hardcoded Codex strings inside shared skill tooling that every
harness runs.

The per-role hint lines now live in a platform-owned data file,
skills/using-superpowers/references/codex-dispatch.hints, and the
task-brief/review-package scripts only relay the current role's line.
The relay is suppressed when CLAUDECODE is set (Claude Code's dispatch
templates already carry model selection) and on any harness with no
hints file; unknown harnesses fail toward printing, because a silent
no-op in the environment that needs the hint is the failure mode this
mechanism exists to prevent. Printing at the moment of dispatch is
load-bearing: skill text loaded at session start does not survive
context compaction, but script output reprints every round.

codex-tools.md's SDD dispatch section shrinks to the behavioral rules
(fork_turns: "none" always; copy the printed hint verbatim; reviewer
tier never exceeds implementer tier; no effort bumps; the <=0.144
inheritance fallback) and points at the hints file for values.

Tests cover the relay path, the per-role efforts, and the new
CLAUDECODE suppression case.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Responds to maintainer review: "re-review" names the action badly — it
reads as "review again," which is the exact failure observed in the
field (fix reviewers re-running full reviews and package-wide suites
against explicit scope instructions). "Fix review" names the artifact
under review — the fix diff since the previous review — and makes the
scope self-enforcing.

Pure vocabulary substitution: re-review-prompt.md becomes
fix-review-prompt.md, SKILL.md and the review-package --role value
follow, and the term is introduced once as "a scoped fix review — a
review of the fix diff, not a fresh review." No behavioral rules
changed. Historical records (docs/superpowers/plans, specs,
RELEASE-NOTES) keep the old vocabulary; other skills' generic verb
usage ("no need to re-review") is untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Responds to maintainer review asking for better implementer
self-reflection. The report format already demands command+output for
TDD evidence and fix-round covering tests, but the full-suite claim
asked only for prose — and that is the claim that rotted in the field:
three consecutive fix rounds shipped a "full suite passes" claim the
fix reviewer found unreproducible, each time because the suite had run
before later edits made the result stale.

Two changes, both at the moment the report is written: every claimed
gate needs its exact command and the tail of fresh output — fresh
meaning after the final edit, otherwise rerun or report the gate as
unverified — and a missing pasted output is itself a defect for the
reviewer to flag, which puts enforcement at the consumption side the
same way the dispatch hints do. Fix reports claiming a full-suite pass
need a fresh run, not the pre-findings one.

This is verification-before-completion's gate function relocated into
the one prompt subagents actually receive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant