# Spec Review Codex

> Use when a brainstorming design spec has been written and needs adversarial review before implementation planning, using OpenAI Codex as the independent reviewer. Requires the codex CLI. Triggers on: spec review codex, codex spec review, review spec with codex, codex review, review spec, spec review.

- Skill: `adelrioj/spec-review-codex` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add adelrioj/spec-review-codex`
- Raw SKILL.md: https://api.skillmd.com/api/skills/adelrioj/spec-review-codex/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: adelrioj (https://skillmd.com/u/adelrioj)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/adelrioj/spec-review-codex

---


# 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

1. Locate the spec file
2. Send to Codex for adversarial review
3. Read findings
4. If verdict is NEEDS REVISION: fix the spec, loop back to step 2
5. If verdict is PASS: report clean to user
6. 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.**

```bash
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

1. If the user provided a file path as argument, use it
2. Otherwise, scan `docs/superpowers/specs/` for the most recent spec by date prefix (YYYY-MM-DD). Match `*-design.md`
3. 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.

```bash
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):

1. Read the quoted spec text from the finding
2. Read the suggested fix
3. 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
4. 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 reviewed
- `findings_files`: List of findings file paths (for audit trail)
- `fixed_count`: Total findings fixed across all iterations
- `important_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.

