Spec Review via Codex
Adversarial review of design specs using Codex as an independent reviewer. Loops until the spec passes with zero CRITICAL and zero IMPORTANT findings.
Why a different agent: The spec was written by this Claude instance. Self-review has author bias — the same blind spots that produced the issue prevent detecting it. Codex is a fresh model with no shared conversation context, making it an effective adversarial reviewer. Codex has filesystem access, so it verifies file paths and code references against the actual repo.
Sibling skills: spec-review-local does the same review with a local model served by LMStudio — use it when offline or when Codex is unavailable, and keep the two spec-review-prompt.md copies byte-identical. /linear-spec-ticket writes the spec this hardens and deliberately never runs this review itself; /ship-it invokes this as its first step.
This skill edits the spec in place, which means any copy of it elsewhere goes stale. In particular, /linear-spec-ticket uploads the spec to its Linear ticket as an attachment, and that attachment is not updated by anything here. Step 5 names the one command that fixes it. Do not run that command yourself — this skill's writes stop at the file.
The Job
- Locate the spec file
- Send to Codex for adversarial review
- Read findings
- If verdict is NEEDS REVISION: fix the spec, loop back to step 2
- If verdict is PASS: report clean to user
- Maximum 3 review iterations (prevent infinite loops)
Do NOT proceed to implementation planning until the spec passes review.
Prerequisite: codex must be on PATH and authenticated. Both are checked in Step 0, before the first review is attempted.
Step 0: Preflight — on PATH, and Logged In
Two sub-second checks. Run them before anything else; either one failing is a STOP, not a retry.
command -v codex >/dev/null 2>&1 || { echo "CODEX-MISSING"; exit 1; }
codex login status || { echo "CODEX-UNAUTHENTICATED"; exit 1; }
| Outcome | Report, verbatim | Human action |
|---|---|---|
CODEX-MISSING |
codex CLI not found on PATH. This skill has no fallback reviewer. |
install the codex CLI |
CODEX-UNAUTHENTICATED |
codex is installed but not authenticated (\codex login status` → not logged in). No review was attempted.` |
run codex login (interactive browser flow), or set a valid OPENAI_API_KEY for the codex CLI |
Why this exists, and why it is not folded into Step 2's error handling. An expired credential and a genuine timeout produce the same symptom downstream — codex exec hangs, hits the 120s cap, and returns nothing — so a run against dead auth burns two full attempts and four minutes, then reports "could not run" without saying which. That is exactly what happened on an observed run's spec-review stage. codex login status answers the question in well under a second and names the remediation, and the two failures need different human actions: a timeout says retry or reduce scope, dead auth says log in — nothing else will ever make it work.
Never treat an unauthenticated codex as a timeout, and never retry through it. Retrying a 401 is the one loop guaranteed to cost the full budget and learn nothing. Equally: never silently skip the review. An autonomous caller (/ship-it, a Symphony stage) may be instructed to advance anyway — that is its decision to record, made from this skill's explicit CODEX-UNAUTHENTICATED report, not something to decide here by returning a hollow PASS. There is no verdict without a review.
Step 1: Locate the Spec
- If the user provided a file path as argument, use it
- Otherwise, scan
docs/superpowers/specs/for the most recent spec by date prefix (YYYY-MM-DD). Match*-design.md - If no spec found, ask the user for the path (this is the only blocking question — without a spec there is nothing to review)
Read the spec file, then announce and proceed immediately — do not wait for confirmation:
"Sending
<spec-path>to Codex for adversarial review."
This skill runs autonomously: it is a self-validator that hardens the spec before it reaches the user. Pausing for human approval at the start or between iterations defeats its purpose. Go straight to Step 2.
Step 2: Send to Codex for Review
Build the Codex command. The review prompt lives at ${CLAUDE_PLUGIN_ROOT}/skills/spec-review-codex/spec-review-prompt.md.
The reviewer needs to read the spec and the codebase but must not modify anything, so run Codex with the read-only sandbox. Capture the findings via --output-last-message (which writes Codex's final message to the findings file) rather than asking the model to write the file itself.
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT}"
REVIEW_PROMPT="${PLUGIN_ROOT}/skills/spec-review-codex/spec-review-prompt.md"
SPEC_FILE="<path-to-spec>"
FINDINGS_FILE="/tmp/spec-review-findings-$(date +%s).md"
codex exec -m "${CODEX_MODEL_REVIEW:-gpt-5.6-sol}" -c model_reasoning_effort="${CODEX_EFFORT_REVIEW:-high}" --sandbox read-only --output-last-message "$FINDINGS_FILE" "$(cat "$REVIEW_PROMPT")
---
# Spec to Review
$(cat "$SPEC_FILE")
---
# Instructions
1. Follow the review procedure above against this spec.
2. Verify all file paths, function names, and line numbers referenced in the spec against the actual codebase. The repository root is the current working directory. You are sandboxed read-only — do not attempt to write or modify files.
3. Your final message must be the complete findings document.
4. Use the exact output format specified in the review prompt.
5. End with the Summary table and Verdict."
Run this via Bash. Codex's final message (the findings) lands in $FINDINGS_FILE via --output-last-message.
Model and reasoning effort are both pinned by this skill, not inherited. Adversarial review runs on gpt-5.6-sol at high — the frontier agentic-coding model, on the pass whose entire job is finding what you missed. Neither value comes from ~/.codex/config.toml, so a machine set to gpt-5.4-mini at low still gets a real review, with no setup from the user. $CODEX_MODEL_REVIEW / $CODEX_EFFORT_REVIEW are the escape hatches. Type both ${…:-…} fragments literally; never resolve them or substitute a model or effort of your own.
Pinning a model has a real cost, accepted deliberately here: slugs age and entitlements vary, so gpt-5.6-sol will eventually be gone or unavailable on some account, and codex fails with an unhelpful error. ship-it's preflight verifies the resolved model and its effort against ~/.codex/models_cache.json before spending a run. Invoked standalone, this skill has no such gate — if codex rejects the model, re-run with CODEX_MODEL_REVIEW=<an entitled slug>. See docs/codex-tuning.md.
Timeout: 120 seconds. If Codex times out, report the timeout as a timeout — Step 0 has already proven the credential was live, so this is a slow or oversized review, not an auth problem — and ask whether to retry or skip.
On any other failure (network error, model rejected, entitlement): codex exits non-zero. Report the exact stderr to the user and stop — do not loop. If the stderr mentions 401, Unauthorized, or an invalid/expired token, say plainly that the credential died between Step 0 and here and name codex login — do not retry, and do not let it read as a timeout.
Step 3: Read and Present Findings
Read the findings file. Parse the summary table at the bottom for counts and verdict.
Present to the user:
Spec Review — Iteration N/3
Severity Count CRITICAL X IMPORTANT X ADVISORY X MINOR X Spec altitude: design / detailed-implementation Verdict: PASS / NEEDS REVISION
If PASS → go to Step 5. (ADVISORY/MINOR findings may remain on a PASS — surface them as notes, do not loop on them.) If NEEDS REVISION → go to Step 4.
List each CRITICAL and IMPORTANT finding (not ADVISORY or MINOR) with its title, problem, and suggested fix so the run stays transparent, then go straight to Step 4 and fix them. Do not ask for approval before fixing — the autonomous fix/re-review loop is the core of the skill. Only CRITICAL and IMPORTANT findings drive the loop; ADVISORY and MINOR are reported, never fixed-and-re-reviewed.
Step 4: Fix and Loop
For each finding (CRITICAL first, then IMPORTANT — ignore ADVISORY and MINOR here):
- Read the quoted spec text from the finding
- Read the suggested fix
- Decide comply vs reframe (see Fixing Guidelines): a normal finding gets the fix applied with the Edit tool; an altitude finding (one demanding the spec transcribe detail a named source of truth already pins) gets reframed into a coverage rule, not enumerated
- Apply the edit and briefly note what was changed
Convergence / enumeration-creep check (before re-running): Compare this iteration's IMPORTANT findings to the previous iteration's. If they are the same category AND merely finer-grained versions of the same underlying concern (e.g. round 2 said "enumerate the error branches," round 3 says "enumerate even more error branches"), the loop is ratcheting on altitude, not substance. Stop early and report:
"Findings are converging on enumeration detail, not substance. The design appears sound; the remaining findings are altitude disagreements better treated as ADVISORY. Treating as PASS with notes."
Then go to Step 5 — this is a PASS-with-notes outcome, not a max-iteration failure.
Otherwise, after all fixes are applied:
- Increment the iteration counter
- If iteration < 3 → go back to Step 2
- If iteration = 3 → report to user:
"Reached maximum review iterations (3). Remaining findings: [list]. Please review the spec manually before proceeding."
Step 5: Report Clean
When Codex returns PASS:
"Spec passed adversarial review (iteration N/3, zero CRITICAL/IMPORTANT findings)."
If there are MINOR findings, list them: "N MINOR suggestions (non-blocking): [titles]"
The spec is now ready for implementation planning.
Then name the stale copy, if there is one. The spec file has just been edited in place. If its filename is identifier-keyed (<IDENT>-design.md, which is what /linear-spec-ticket writes), a Linear ticket is almost certainly carrying the pre-review draft as an attachment. Add two lines to the report and stop — do not run either one:
Next: /linear-spec-ticket <IDENT> refresh — re-upload the hardened spec to the ticket
/spec-to-symphony <IDENT> — push it to the remote and arm the pipeline
For a date-prefixed spec there is no ticket to infer, so say nothing.
Fixing Guidelines
When fixing findings:
- CRITICAL (contradictions, wrong references): Verify the correct information from the codebase before fixing. Do not guess.
- CRITICAL (missing file paths / functions): Grep the codebase to find the correct path or function name. Update the spec with verified information.
- IMPORTANT (ambiguous requirements): Pick the most reasonable interpretation and make it explicit. Add a "Decision:" note inline so the user sees what was decided.
- IMPORTANT (missing error paths): Add a brief failure handling paragraph. Keep it proportional to the spec's existing level of detail.
- IMPORTANT (missing edge cases): Add to the relevant section. If there's an edge cases table, add rows. If not, add a bullet list.
- Never remove content to fix a finding. Clarify, correct, or expand instead.
- Never change the architectural approach to fix a finding. If a finding suggests the approach is wrong, flag it to the user instead of changing it.
- Reframe, don't comply, on altitude findings. If a finding asks the spec to transcribe implementation detail (enumerate more branches, cases, or guard returns) that a named external source of truth already pins — a characterization suite, golden master, or referenced source range — do NOT enumerate. Instead reframe the requirement as a coverage rule pointing at that source, and add a one-line
Decision:note recording the choice. This is the altitude analogue of "never change the architectural approach": the reviewer is pushing the spec to the wrong altitude, and the right response is to reframe, not obey. If the finding was already ADVISORY, no spec edit is needed at all — just note it.
Iteration State
Track across iterations:
iteration: Current iteration number (1-3)spec_path: Path to the spec being reviewedfindings_files: List of findings file paths (for audit trail)fixed_count: Total findings fixed across all iterationsimportant_categories: The set of categories of this iteration's IMPORTANT findings — compared against the previous iteration to detect enumeration creep (Step 4 convergence check)
All findings files are preserved in /tmp/ for the user to inspect after the review completes.