| name | dual-review |
| preamble-tier | 2 |
| version | 2.0.0 |
| description | Sequential Claude-Codex review loop for specs and plans with structured
JSON findings. Embedded in brainstorming and writing-plans for automatic
Codex review after self-review. Also user-invocable for manual ad-hoc
review. Max 3 rounds default, early exit if clean.
|
| user-invocable | true |
| allowed-tools | ["Bash","Read","Grep","Glob","Edit","Write","AskUserQuestion"] |
| announce-action | run a Codex adversarial review loop on `<path>` |
Preamble (run first)
if [ -f .rkstack/settings.json ]; then
cat .rkstack/settings.json
else
echo "WARNING: .rkstack/settings.json not found — detection cache missing"
fi
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
_HAS_CLAUDE_MD=$([ -f CLAUDE.md ] && echo "yes" || echo "no")
echo "BRANCH: $_BRANCH"
echo "CLAUDE_MD: $_HAS_CLAUDE_MD"
Use the detection cache and preamble output to adapt your behavior:
- TypeScript/JavaScript — see
detection.flowType (web or default). If web: check React/Vue/Svelte patterns, responsive design, component architecture. If default: CLI tools, MCP servers, backend scripts.
- Python — backend/ML/scripts. Check PEP8 conventions, pytest for testing.
- Go — backend/infra. Check error handling patterns, go test.
- Rust — systems. Check ownership patterns, cargo test.
- Java/C# — enterprise. Check build tool (Maven/Gradle/.NET), framework conventions.
- Ruby — web/scripting. Check Gemfile, Rails conventions if present.
- Terraform/HCL — infrastructure as code. Plan before apply, extra caution with state.
- Ansible — configuration management. Check inventory, role conventions, vault usage.
- Docker/Compose — containerized. Check service dependencies, .env patterns.
- justfile — task runner present. Use
just commands instead of raw shell.
- mise — tool version manager. Versions are pinned — don't suggest global installs.
- CLAUDE.md exists — read it for project-specific commands and conventions.
- Read
detection.stack for what's in the project and detection.stats for scale (files, code, complexity).
- Read
detection.repoMode for solo vs collaborative.
- Read
detection.services for Supabase and other service integrations.
AskUserQuestion Format
ALWAYS follow this structure for every AskUserQuestion call:
- Re-ground: State the project, the current branch (use the
_BRANCH value from preamble — NOT any branch from conversation history or gitStatus), and the current plan/task. (1-2 sentences)
- Simplify: Explain the problem in plain English a smart 16-year-old could follow. No raw function names, no internal jargon, no implementation details. Use concrete examples and analogies. Say what it DOES, not what it's called.
- Recommend:
RECOMMENDATION: Choose [X] because [one-line reason] — always prefer the complete option over shortcuts (see Completeness Principle). Include Completeness: X/10 for each option. Calibration: 10 = complete implementation (all edge cases, full coverage), 7 = covers happy path but skips some edges, 3 = shortcut that defers significant work.
- Options: Lettered options:
A) ... B) ... C) ... — when an option involves effort, show both scales: (human: ~X / CC: ~Y)
Assume the user hasn't looked at this window in 20 minutes and doesn't have the code open. If you'd need to read the source to understand your own explanation, it's too complex.
Completeness Principle
AI makes completeness near-free. Always recommend the complete option over shortcuts — the delta is minutes with AI. A "lake" (100% coverage, all edge cases) is boilable; an "ocean" (full rewrite, multi-quarter migration) is not. Boil lakes, flag oceans.
Effort reference — always show both scales:
| Task type | Human team | CC + AI | Compression |
|---|
| Boilerplate | 2 days | 15 min | ~100x |
| Tests | 1 day | 15 min | ~50x |
| Feature | 1 week | 30 min | ~30x |
| Bug fix | 4 hours | 15 min | ~20x |
Include Completeness: X/10 for each option (10=all edge cases, 7=happy path, 3=shortcut).
Completion Status
When completing a skill workflow, report status using one of:
- DONE — All steps completed successfully. Evidence provided for each claim.
- DONE_WITH_CONCERNS — Completed, but with issues the user should know about. List each concern.
- BLOCKED — Cannot proceed. State what is blocking and what was tried.
- NEEDS_CONTEXT — Missing information required to continue. State exactly what you need.
Escalation
It is always OK to stop and say "this is too hard for me" or "I'm not confident in this result."
Bad work is worse than no work. You will not be penalized for escalating.
- If you have attempted a task 3 times without success, STOP and escalate.
- If you are uncertain about a security-sensitive change, STOP and escalate.
- If the scope of work exceeds what you can verify, STOP and escalate.
Escalation format:
STATUS: BLOCKED | NEEDS_CONTEXT
REASON: [1-2 sentences]
ATTEMPTED: [what you tried]
RECOMMENDATION: [what the user should do next]
Dual-Review: Sequential Claude-Codex Review Loop
You are reviewing a spec or plan with Codex as an adversarial second opinion.
This skill runs in two modes:
- Embedded — called automatically by brainstorming (after self-review on
the spec) and writing-plans (after self-review on the plan).
- Standalone — user invokes
/dual-review path/to/artifact.md [--rounds N] [focus text].
Both modes use the same mechanism: sequential loops where Codex reviews with
the adversarial-review prompt contract, returns structured JSON findings,
you evaluate each finding against the document and source code, fix valid
ones, and loop until Codex returns approve (no findings) or max rounds
are reached.
Announce at start: "I'm using the dual-review skill to run a Codex adversarial review loop on <path>."
Core principle: Source code informs context, not intent. Proposed
changes in a spec or plan are not defects just because current code does
not implement them. Codex should flag conflicts with existing contracts,
circular dependencies, or missed documented constraints — not "this
doesn't exist yet." This rule is embedded in spec-review-prompt.md and
plan-review-prompt.md as a <grounding_rules> block.
Step 0: Verify Codex is ready
node "${CLAUDE_PLUGIN_ROOT}/scripts/codex/codex-companion.mjs" setup --json
Parse the JSON. If "ready": false:
codex.available: false → stop with:
"Codex CLI not found. Install: npm install -g @openai/codex. Then run !codex login to authenticate."
auth.loggedIn: false → stop with:
"Codex is installed but not authenticated. Run !codex login (ChatGPT account or API key)."
Standalone Mode: Parse Arguments
When user invokes /dual-review path/to/file.md [--rounds N] [focus text]:
-
File path — required (first positional argument). Verify it exists.
-
--rounds N — optional, default 3.
-
focus text — optional, anything after flags/path. Interpolated into
the prompt at the USER_FOCUS placeholder (double-braced, uppercase,
literally present in the prompt file) to weight the review toward a
specific concern. Default if absent: "(none — general review)".
-
Determine artifact type by reading the first 50 lines:
- Contains
## Problem and ## Solution → spec
- Contains
**Spec:** and **Goal:** and task checkboxes (- [ ]) → plan
- If ambiguous: ask user "Is this a spec or a plan?"
-
For plans: must have **Spec:** filename.md in the header. If missing, stop with:
"Plan must link its spec in the header. Add: **Spec:** path/to/spec.md"
Resolve spec path relative to the plan's directory. Verify spec file exists.
The Review Loop
Run this loop for both embedded and standalone modes.
Inputs:
ARTIFACT_PATH — absolute path to the spec or plan file
ARTIFACT_TYPE — "spec" or "plan"
MAX_ROUNDS — default 3
USER_FOCUS — optional focus text (default "(none — general review)")
- For plans:
SPEC_PATH — absolute path to the linked spec
Round N (repeat up to MAX_ROUNDS):
1. Assemble the Codex prompt
Read the appropriate XML-block prompt template:
- For specs:
${CLAUDE_PLUGIN_ROOT}/skills/dual-review/spec-review-prompt.md
- For plans:
${CLAUDE_PLUGIN_ROOT}/skills/dual-review/plan-review-prompt.md
The prompt files use double-braced uppercase placeholders. Find and
replace each one with the runtime value before sending to Codex:
| Placeholder (literal text in the prompt file) | Replacement |
|---|
ARTIFACT_PATH (double-braced) | absolute path to the spec or plan |
SPEC_PATH (double-braced) | absolute path to linked spec (plan mode only) |
USER_FOCUS (double-braced) | user focus text, or the default |
Prepend a short instruction block directing Codex to read files itself.
In the block below, <artifact-type>, <artifact-path>, and <spec-path>
are shell-style placeholders you fill in at runtime:
Read and review the <artifact-type> at <artifact-path>.
Also read CLAUDE.md for project conventions and the first 50 lines of
README.md for context. Read any source files the document references.
For plan mode: also read the linked spec at <spec-path>.
<remainder of the interpolated prompt template follows>
2. Call Codex
scripts/codex/review-doc.mjs accepts a prompt on stdin, runs it
through the shared Codex app-server broker with the structured-output
schema enforced, and prints the parsed JSON findings on stdout.
Invoke it in one Bash call with a quoted HEREDOC so the prompt is
passed verbatim — no shell expansion, no temp files:
JSON=$(node "${CLAUDE_PLUGIN_ROOT}/scripts/codex/review-doc.mjs" \
--schema "${CLAUDE_PLUGIN_ROOT}/skills/dual-review/review-schema.json" \
--cwd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)" \
--effort medium \
<<'CODEX_PROMPT' 2> /tmp/dual-review.stderr
<full interpolated prompt goes here — see step 1>
CODEX_PROMPT
) ; EXIT=$?
Use timeout: 300000 (5 min) on the Bash tool call.
3. Handle outcomes
| Situation | Action |
|---|
EXIT == 0 — $JSON contains the parsed findings | Continue to step 4 |
EXIT == 2 | Usage error (missing --schema, empty prompt). Fix the invocation. |
EXIT == 3 | Codex CLI not installed. Stop: "Codex CLI not found. Install: npm install -g @openai/codex. Then run !codex login." |
EXIT == 1 — stderr mentions auth / token / login | Stop: "Codex authentication failed. Run !codex login." |
EXIT == 1 — stderr mentions schema mismatch | Codex's output did not match the schema. Read stderr's parseError line; if transient, retry once. Otherwise report and stop. |
| Bash timeout (5 min) | Stop: "Codex timed out. Try /dual-review --rounds 1 with a smaller artifact, or split the document." |
Parse $JSON directly — it is the structured review output:
{
"verdict": "approve" | "needs-attention",
"summary": "...",
"findings": [
{
"severity": "critical" | "high" | "medium" | "low",
"title": "...",
"body": "...",
"file": "...",
"line_start": 42,
"line_end": 47,
"confidence": 0.0..1.0,
"recommendation": "..."
}
],
"next_steps": ["..."]
}
No cleanup is required — review-doc.mjs does not write any temp files,
and the broker manages its own lifecycle.
4. Evaluate each finding
Sort findings by severity (critical first). For each:
- Read the cited section of
ARTIFACT_PATH at line_start..line_end.
- If the finding cites a source file, read it.
- Classify:
- Valid — the spec/plan has a genuine gap, missing edge case, internal
contradiction, or conflicts with an existing documented constraint.
Fix it by editing the document to address the finding's
recommendation.
- Rejected — the proposed behavior is intentional and supported by
the spec's reasoning, or Codex misread current code as the intended
target. Skip with a one-line explanation captured for the summary.
- Unclear — needs human judgment. Queue it for an AskUserQuestion
at the end of the loop.
Apply the codex-result-handling contract when presenting findings: preserve
file paths and line numbers verbatim (format as path:L-L), preserve evidence
boundaries, do not harden Codex's inferences into definitive claims.
5. Fix valid findings
Edit the document file directly using the Edit tool. Do not modify source
code — dual-review only edits specs and plans.
6. Loop decision
verdict == "approve" and findings == [] → exit clean immediately.
- Made fixes AND rounds < MAX_ROUNDS → next round (go to step 1).
rounds >= MAX_ROUNDS → exit with max-rounds summary.
- All findings rejected or unclear, none fixed → exit with no-change summary
(Codex keeps flagging the same thing, you keep rejecting — surface to user).
Final Output
After all rounds complete, output:
DUAL-REVIEW: <artifact_path> (<artifact_type>)
Rounds: N of M [clean | max-rounds | no-change]
ROUND 1:
Codex verdict: needs-attention (K findings)
→ X valid (fixed)
→ Y rejected: [one-line reason per rejection]
→ Z unclear: [surfaced to user]
ROUND 2:
Codex verdict: approve (0 findings) — clean exit
RESULT: K total findings across N rounds — X fixed, Y rejected, Z unclear
If there are unclear findings, present them to the user with a single
AskUserQuestion call before reporting the final result. For each unclear
finding, include:
- The finding title and Codex's recommendation
- Your analysis of why it is unclear
- A recommended action
Error Handling
| Error | Action |
|---|
Companion setup reports ready: false | Stop with install / !codex login message |
| Codex auth failed mid-run | Stop — same message |
| Codex timeout (5 min) | Report, suggest smaller scope |
$OUTPUT_FILE empty or invalid JSON | Report stderr actionable lines, suggest re-run |
| Missing CLAUDE.md | Continue without it |
| Missing README.md | Continue without it |
| Source file cited by Codex not found | Skip from context, treat finding as unclear |
| Spec file not found (plan mode) | Stop — plan must link a valid spec |
verdict == "approve", findings empty | Exit clean immediately |
| Same finding repeats across 2+ rounds without being fixed | Treat as unclear, surface to user |
Key Rules
- Source code informs context, not intent. Proposed changes are not
defects just because current code doesn't implement them. This rule
lives in the prompt as a
<grounding_rules> block — do not weaken it.
- Sequential, never parallel. Review → evaluate → fix → re-review.
One round at a time.
- Structured output is the contract. Use
--output-schema against the
vendored review-schema.json. Do not fall back to free-form
parsing; if the JSON fails to parse, report the failure and stop.
- Evaluate before accepting. Read referenced document sections and
source code before classifying findings.
- Early exit on approve. If Codex returns
verdict: "approve" with
zero findings, done.
- Max 3 rounds default. Prevents infinite loops; user can override
with
--rounds N.
- Fix the document, not the code. Dual-review edits specs and plans,
never source code. If a finding implies a code change, that belongs in
a later skill (brainstorming / writing-plans / executing-plans).