--- name: codex-lanes description: Reference recipe for invoking the Codex CLI (`codex exec`) from the codex-flow skills. Use when composing any codex exec call - it carries the mandatory guards, the implementer (terra/low) and review (sol/xhigh) lanes, the result schema, and the adversarial prompts. Loaded by brainstorming-codex, writing-plans-codex, and sdd-with-codex-implementer. --- # Codex `codex exec` lanes (shared recipe) Shared invocation recipe for the codex-flow skills. Read this before composing any `codex exec` call. The guards below are not optional; each maps to a real Codex-CLI failure. ## 1. Availability gate (run once, before any Codex step) ```bash if ! command -v codex >/dev/null 2>&1; then echo NO_CODEX elif ! codex login status >/dev/null 2>&1; then echo NO_CODEX_AUTH else echo HAVE_CODEX; fi ``` `NO_CODEX` → skip the Codex seam, run the plain `superpowers:*` skill instead, tell the user once ("Codex CLI not found — running plain superpowers"). `NO_CODEX_AUTH` → the binary is installed but not logged in. **Treat it exactly like `NO_CODEX`** — degrade to plain superpowers — but tell the user something they can act on: "Codex CLI found but not logged in (`codex login`) — running plain superpowers". Never launch `codex login` yourself; it is interactive and will hang a non-TTY run. Checking the binary alone is not enough: an unauthenticated CLI passes `command -v`, the flow commits to the Codex path, and the first `codex exec` then dies mid-flow with an empty result file — which §4 will lead you to misread as the foreground-600s mistake. Never fabricate Codex output or pass off a Claude self-review as the Codex pass. ## 2. Guards — on EVERY `codex exec` call - **stdin must be fed or closed.** Either pipe the prompt in (`- < prompt.md`) OR add `< /dev/null`. Never leave stdin open — in a non-TTY (the Claude Code Bash tool) Codex hangs forever waiting for EOF. The #1 failure. Pick exactly one per call: - short prompt → positional arg + `< /dev/null` - long/structured prompt → `- < prompt.md` (the file IS stdin; do NOT also add ` taste > cost. Cost is a tie-breaker only. Inside `Agent`/`Workflow` fan-outs the model param takes Claude models only — to reach the Codex lanes there, wrap it: a `sonnet`/low agent whose prompt says "compose a self-contained codex prompt, run the lane's `codex exec` via Bash, return the parsed `-o` JSON". ## 4. Review lane — invocation (xhigh, structured findings) The review lane never edits the artifact. Codex returns findings as JSON (schema below); Claude **adjudicates** — accept or reject each finding with a one-line reason — and applies the accepted fixes itself. This holds for specs, plans, and code diffs alike. xhigh reviews routinely run past 10 min, so run this in the **background** — never a plain foreground call (Claude Code's foreground Bash tool hard-caps at 600s). `-o` isolates the findings JSON; the full transcript (startup banner, reasoning, echoed tool output, token footer) goes to `$LOG` and is read only on failure — never fold it into context: ```bash _REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" _RUN="${TMPDIR:-/tmp}/codex-flow"; mkdir -p "$_RUN" _TIMEOUT="$(command -v gtimeout || command -v timeout || true)" # empty on stock macOS → no prefix, still fine SCHEMA="$_RUN/review-schema.json"; cat > "$SCHEMA" <<'JSON' { "type":"object","additionalProperties":false,"required":["verdict","findings"], "properties":{ "verdict":{"enum":["approve","needs_changes"]}, "findings":{"type":"array","items":{"type":"object","additionalProperties":false, "required":["severity","location","claim","why","suggested_fix"], "properties":{ "severity":{"enum":["blocker","major","minor"]}, "location":{"type":"string"}, "claim":{"type":"string"}, "why":{"type":"string"}, "suggested_fix":{"type":"string"}}}}}} JSON OUT="$_RUN/review-out.json"; LOG="$_RUN/review.log" : > "$OUT" # truncate any previous run's result echo "OUT=$OUT LOG=$LOG" # ← these literal paths are how you read the result later $_TIMEOUT ${_TIMEOUT:+3600} codex exec -m gpt-5.6-sol \ -c 'model_reasoning_effort="xhigh"' \ -c 'mcp_servers.node_repl.enabled=false' \ -C "$_REPO_ROOT" -s read-only --skip-git-repo-check \ --output-schema "$SCHEMA" \ -o "$OUT" \ " Target: ." \ < /dev/null > "$LOG" 2>&1 ``` Fast mode (§3): insert `-c 'service_tier="fast"' -c 'features.fast_mode=true'` after the effort line. Launch with the Bash tool's `run_in_background: true`. **Shell variables do not survive to the next Bash call** — read the result by its literal path, not by `$OUT`: `$TMPDIR/codex-flow/review-out.json` (the launch call echoes the resolved path; on Linux `TMPDIR` is usually unset, so it's `/tmp/codex-flow/review-out.json`). Empty or malformed → read `$TMPDIR/codex-flow/review.log`. If the process died at ~600s, that's the foreground-launch mistake (§2), not a Codex failure. **Adjudication (Claude, after every review call):** for each finding — accept or reject with a one-line reason; apply accepted fixes to the artifact yourself; record the adjudication (accepted/rejected + why) in the stage's summary. Never apply a finding unexamined, never let Codex rewrite the artifact. ## 5. Implementer lane — invocation (terra low, structured result) The result schema is not shipped on disk — write it to a throwaway file first: **Every implementer prompt starts with the fixed preamble** in this skill's `codex-implementer-prompt.md`, verbatim, then the caller's task content. The schema below constrains the *shape* of the result; the preamble is what defines the meaning — when to report `partial` vs `failed`, the no-questions rule (stop, don't guess through ambiguity), and the self-review pass. A dispatch without it gets plausible-looking field values from a model that was never told what they mean. ```bash _REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" _RUN="${TMPDIR:-/tmp}/codex-flow"; mkdir -p "$_RUN" TASK="${TASK:?set TASK to the task number or cluster slug}" _TIMEOUT="$(command -v gtimeout || command -v timeout || true)" # empty on stock macOS → no prefix, still fine SCHEMA="$_RUN/impl-schema.json"; cat > "$SCHEMA" <<'JSON' { "type":"object","additionalProperties":false, "required":["status","files_modified","issues","summary","verification_summary"], "properties":{ "status":{"enum":["completed","partial","failed"]}, "files_modified":{"type":"array","items":{"type":"string"}}, "issues":{"type":"array","items":{"type":"string"}}, "summary":{"type":"string"}, "verification_summary":{"type":"string"}}} JSON OUT="$_RUN/impl-$TASK.json"; LOG="$_RUN/impl-$TASK.log" : > "$OUT" echo "OUT=$OUT LOG=$LOG" $_TIMEOUT ${_TIMEOUT:+3600} codex exec -m gpt-5.6-terra \ -c 'model_reasoning_effort="low"' \ -c 'mcp_servers.node_repl.enabled=false' \ -C "$_REPO_ROOT" -s workspace-write --skip-git-repo-check \ --output-schema "$SCHEMA" \ -o "$OUT" \ - < "$PROMPT_FILE" > "$LOG" 2>&1 ``` (`- < "$PROMPT_FILE"` feeds the prompt via stdin, so no `< /dev/null` here.) Launch with the Bash tool's `run_in_background: true`. Read the result by literal path when the process exits — `$TMPDIR/codex-flow/impl-.json`, echoed by the launch call — never via `$OUT`, which is gone with the shell that launched it. Transcript in `impl-.log`, read only on failure. Fast mode (§3): insert `-c 'service_tier="fast"' -c 'features.fast_mode=true'` after the effort line. ## 6. Prompts - **Spec / plan adversarial review:** "You are an adversarial reviewer. Challenge every assumption in . Surface unstated assumptions, missing edge cases, failure modes, and anything that contradicts this repo's conventions. Findings only, ranked by severity — no praise. `location` = the section heading (or file:line) each finding anchors to." - **Final code challenge (branch diff):** "Assume this diff is broken. Find the strongest reasons it should not ship: auth, data loss, races, rollback, empty-state, schema drift. Ground every finding in a file:line. Findings only."