agentsclimarketplace

Codex review

Skill lookatitude/guild/skills/meta/codex-review

DEPRECATED lifecycle entry-point (D-BR-A) — now the internal Codex adapter invoked BY `guild:review-broker`, never called directly from Guild lifecycle gates. Route `--review=cross` / `review: cross` to `guild:review-broker`. Survives as the Codex-specific adapter: dispatches `codex:codex-rescue` against an artifact, loops until `## SATISFIED` on its own line (cap=5 rounds, `--codex-cap=N`), writes trail to `.guild/runs/<run-id>/codex-review/<gate>.md`, skips gracefully when `codex --version` fails. TRIGGER on: "invoke the Codex adapter", "codex adapter for gate", "dispatch codex adversarial review", "run Codex critique on artifact", "one-off Codex gate review". DO NOT TRIGGER for: `--review=cross` lifecycle entry (→ `guild:review-broker`), Guild internal loops L1–L4, skill evolution.From its SKILL.md

Install
npx -y skills add lookatitude/guild --skill codex-review

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

21.9 KB, as published. Nobody here has run it

guild:codex-review

⚠️ DEPRECATED as a lifecycle entry-point (ADR D-BR-A, the v2-review-broker-and-artifact-bus ADR). This skill is now the internal Codex adapter invoked by guild:review-broker. All lifecycle gate wiring (--review=cross, review: cross) routes through the broker. Direct invocation is permitted only for one-off Codex-only artifact critiques that bypass the broker intentionally. New lifecycle gates must not call this skill directly.

The Codex-specific adapter beneath guild:review-broker. Dispatches codex:codex-rescue, manages the ## SATISFIED sentinel loop, and writes the per-gate trail. The broker owns author/reviewer resolution; this adapter owns the Codex dispatch mechanism.

Previously shipped as a first-class user-facing lifecycle gate. That role is superseded by guild:review-broker (host-agnostic, bidirectional, structured review_result.v1). This skill's sentinel + trail + telemetry mechanics are unchanged — the broker relies on them.

Gates

Three gates, one per load-bearing lifecycle artifact:

GateWhen invokedArtifact reviewed
G-specAfter guild:brainstorm writes .guild/spec/<slug>.md, before guild:team-composeThe spec file
G-planAfter guild:plan writes .guild/plan/<slug>.md, before the user-approval gateThe plan file
G-laneAfter each lane's handoff receipt is written, before the next lane dispatchesThe lane's handoff receipt
G-diagnoseAfter guild:diagnose writes a diagnosis/fix plan, before the user approval gateThe diagnosis report

Input shape

type CodexReviewInput = {
  gate: "G-spec" | "G-plan" | "G-diagnose" | `G-lane:${string}`;  // which gate is firing
  artifact_path: string;                              // repo-relative path to the artifact
  run_id: string;                                     // .guild/runs/<run-id>/ scope
  codex_cap?: number;                                 // rounds cap; default 5, max 10
  prior_trail_path?: string;                          // path to prior round trail (rounds 2+)
};

Availability check

Alignment with provider detection (Unit 4). This adapter is the Codex ADAPTER beneath the broker, not the lifecycle front door — --review=cross routes through guild:review-broker, which calls scripts/lib/provider-detect.ts to decide WHO reviews. That detection models two Codex providers: codex-plugin (this codex:codex-rescue adapter — selectable when detected) and codex-cli (selectable when authed). The availability check below is the same probe contract provider-detect uses for the codex family: codex --version exits 0 AND usable auth exists (stored ~/.codex/auth.json or OPENAI_API_KEY). Per OD-6, a detected-but-unauthed codex is not selectable for a cross gate; per AC-8, the broker also refuses Codex entirely when the author host is Codex (same-family self-review). When invoked directly as a one-off, this adapter still applies its own availability check below and skips gracefully.

Before dispatching Codex, check availability:

codex --version >/dev/null 2>&1

If this fails (non-zero exit, or command not found), emit to stdout:

warn: codex-review skipped — codex plugin not installed (gate: <gate>)

And return immediately with status: "skipped". Do not hard-block the lifecycle — the run continues without adversarial review.

If codex --version exits 0, also verify that usable auth exists before dispatching:

# (a) codex login path — present and non-empty
AUTH_FILE="${CODEX_HOME:-$HOME/.codex}/auth.json"
[ -s "$AUTH_FILE" ] && AUTH_OK=1

# (b) legacy env-var path
[ -n "$OPENAI_API_KEY" ] && AUTH_OK=1

Codex is available iff codex --version exits 0 AND AUTH_OK is set (either path). If codex --version succeeds but neither auth path is satisfied, emit:

warn: codex-review skipped — codex not authenticated (gate: <gate>)

And return status: "skipped".

Known false-negative (codex ≥0.x stored-creds auth). Gating availability on OPENAI_API_KEY alone produces a false negative for any codex version that authenticates via codex login (stored in ~/.codex/auth.json). The OPENAI_API_KEY env var is never set in that flow, so a check that only tests the env var will incorrectly report codex as unavailable even when it is fully authenticated and reachable. Always check BOTH paths (a) and (b) above. Do not reintroduce an env-var-only gate.

Codex-skip sentinel gate-read (FU-E enforcement)

This is the consuming half of the FU-E codex-skip discipline contract. The Stop hook hooks/maybe-reflect.ts writes the sentinel; this skill reads it. The full loop: skip → sentinel + non-zero Stop exit (hook) → gate surfaces/refuses (here) → install codex or a codex_review: RAN reflection clears it (guild:reflect).

At the START of every gate (before the availability check, before round 1), read the sentinel:

cat .guild/codex-skip-streak.json 2>/dev/null   # absent ⇒ no block, proceed normally

Parse it as schema_version: guild.codex_skip_streak.v1 with fields streak, threshold, blocked, updated_at, reason, clear_by. Only act when blocked == true (a malformed/unparseable file ⇒ treat as no block and proceed; never let a bad sentinel stall the lifecycle). The hook maintains this file; trust it — do not recompute the streak here (that is the hook's job, walking the reflection trail newest-first).

Enforcement is CONFIGURABLE via .guild/settings.json key codex_skip_enforcement and DEFAULTS TO NON-BLOCKING:

codex_skip_enforcementBehavior when blocked: true
warn (default, or key absent)SURFACE loudly, then PROCEED. Print the block to stdout and continue the gate normally.
block (opt-in)HARD-REFUSE. Halt this gate and do not run the review/proceed until the sentinel clears or the operator explicitly overrides.

warn (default — do NOT brick the operator's workflow)

Print, then continue into the normal availability check / round loop:

warn: codex-skip discipline OVERDUE (gate: <gate>)
  codex adversarial review skipped on <streak> consecutive self-build reflections
  (threshold <threshold>; sentinel updated <updated_at>).
  Codex review is overdue. To resolve:
    1. install + authenticate codex (`codex --version` exits 0, then run `codex login` OR set OPENAI_API_KEY) so this gate runs, OR
    2. record a reflection with `codex_review: RAN` (a real review breaks the streak), OR
    3. delete .guild/codex-skip-streak.json after an explicit operator override, OR
    4. set `codex_skip_enforcement: block` in .guild/settings.json to hard-enforce.
  Proceeding (enforcement: warn).

block (opt-in hard-refuse)

Halt the gate and surface via AskUserQuestion (header: "Codex-skip discipline", multiSelect: false) — do not silently proceed:

Codex adversarial review is BLOCKED at gate <gate> (codex_skip_enforcement: block).
<streak> consecutive self-build reflections skipped codex review (threshold <threshold>).
  [run-codex]  Install/authenticate codex now and run the gate review (clears via a RAN reflection).
  [override]   Operator override — delete .guild/codex-skip-streak.json and proceed this once.
  [rework]     Return to the prior lifecycle step.

Wait for an explicit choice. Do not proceed to the round loop while blocked: true under block enforcement unless the operator chooses override.

How the sentinel clears

The sentinel is hook-maintained, so the durable clear is to make the hook recompute streak < threshold:

  • A codex_review: RAN reflection (written by guild:reflect after codex actually runs) breaks the consecutive-skip streak; the next Stop-hook evaluation computes streak = 0 and does not re-arm. This is the canonical clear.
  • When this gate successfully runs codex review (status: "satisfied" / force_passed) and blocked: true, delete the stale sentinel as the gate-side acknowledgement that review just happened: rm -f .guild/codex-skip-streak.json. The authoritative reset still comes from the next RAN reflection — this deletion just stops the current gate from re-warning after a real review this turn.
  • An explicit operator override (or manual rm) clears it unconditionally.

Coordinate with the hook semantics: the hook counts consecutive skips and re-derives the streak every Stop, so the gate-read trusts the hook-maintained blocked flag rather than maintaining its own counter.

NOTE (config schema): codex_skip_enforcement (warn | block, default warn) is registered in the config schema as a security-sensitive closed key — config-schema.ts declares it in SECURITY_ENUM_OVERRIDES (enum_values: ["warn", "block"], most_restrictive: "block"), config-defaults.ts defaults it to warn, and guild:config validates the closed enum (an out-of-range value is rejected). See the Guild docs site → https://guildstack.dev/docs/configuration.

Dispatch

For each round (1-indexed, up to codex_cap):

  1. Read the artifact at artifact_path.
  2. Build the adversarial prompt (see ## Adversarial prompt).
  3. Dispatch: Agent({ subagent_type: "codex:codex-rescue", prompt: <adversarial_prompt> }).
  4. Classify the dispatch result as VERDICT-LESS or REVIEWED — see ## Verdict-less rounds for the deterministic predicate. A verdict-less round runs the bounded retry there and, if still verdict-less, terminates the loop with status: "no_verdict".
  5. Parse Codex's response for the sentinel ## SATISFIED on its own line (exact match, trimmed).
  6. Append round result to trail file .guild/runs/<run-id>/codex-review/<gate>.md.
  7. Emit exactly ONE codex_review_round event per LOGICAL round to .guild/runs/<run-id>/logs/v1.4-events.jsonl, after step 4's retry (if any) has resolved — never one per transport attempt (see ## Telemetry).
  8. If sentinel found → return status: "satisfied".
  9. If round equals codex_cap → escalate (see ## Cap handling).
  10. Otherwise → continue to next round, passing prior trail as context.

Verdict-less rounds

A round is VERDICT-LESS when the dispatch produced no reviewable response at all. This is decided by a DETERMINISTIC predicate on the transport result, never by judging how substantive the prose looks:

  • the Agent(...) dispatch threw, timed out, or returned no content; or
  • the response is empty or whitespace-only; or
  • the provider declined to answer — the response is a provider-level refusal or error envelope rather than a review (e.g. a cybersecurity risk / can't help with that classifier message, or an ERROR:-prefixed transport failure), carrying no assessment of the artifact.

Everything else is a REVIEWED round, including a rejection with no bullet list. A response such as "I cannot approve this because criterion X is missing" IS a verdict — it assesses the artifact — and is handled as an ordinary non-satisfied round (continue, or escalate at cap). Prose that is merely terse, unstructured, or hard to parse is NEVER verdict-less. This deliberately matches the malformed-sentinel rule below: when in doubt the round is non-terminated and the loop continues. Erring the other way would let a substantive rejection exit the gate as no_verdict — an escape hatch.

Bounded retry — at most two transport attempts per logical round, no recursion:

  1. Attempt 1 dispatches the round's prompt. If it is REVIEWED, the round proceeds at step 5 above; the retry never runs.
  2. If attempt 1 is VERDICT-LESS: record the refusal verbatim in the trail, then run attempt 2 ONCE with the SAME review request reframed — describe what the component does and must not do, rather than enumerating attack constructions. (Observed cause: a prompt reading as an attack catalogue trips a provider's cyber-risk classifier when the artifact is security or scoping code.)
  3. Classify attempt 2 by the same predicate. If REVIEWED, the round proceeds normally — the reframed attempt IS the round's result, and the round counter does not advance.
  4. If attempt 2 is also VERDICT-LESS, return status: "no_verdict" immediately. Do not attempt a third time, do not advance the round counter, and do not fall through to the cap escalation in step 9.

Terminal-disposition rule. satisfied is the ONLY status meaning Codex reviewed the artifact and raised nothing. The others are not interchangeable: cap_hit / cap_pushback / cap_verify all assert substantive review happened and reached the cap; skipped asserts Codex was unavailable; no_verdict asserts the review never produced a judgement at all. Never report a verdict-less round as any cap status or as satisfied — a caller reading a cap status will believe the artifact was scrutinized N times.

Trail + broker disposition. A no_verdict gate writes final_status: no-verdict verbatim in the trail. Like a bare cap_hit, that value is NOT in the validator's clean set, so it DELIBERATELY fails scripts/verify-codex-review-trail.ts as an audit exception — the gate did not clear and the trail says so. guild:review-broker must treat an adapter no_verdict as a non-clearing outcome that never resolves the gate (see that skill's ## Broker action by status); it is specifically NOT mapped to the broker's skipped, which can legitimately continue the lifecycle.

Adversarial prompt

Round 1:

You are an adversarial reviewer. Read the artifact below and find any:
- Missing success criteria or acceptance tests
- Scope ambiguities that would allow a specialist to misinterpret the work
- Security or autonomy-policy gaps
- Untestable or unmeasurable claims
- Dependencies or risks not surfaced

If you find no issues, emit ONLY the line: ## SATISFIED

If you find issues, list them as bullets. Do NOT emit ## SATISFIED unless
you are genuinely satisfied that the artifact is production-ready.

Artifact (<gate>):
<artifact content>

Rounds 2+: prepend the prior Q&A trail before the artifact so Codex sees what was already raised and addressed.

Termination sentinel

## SATISFIED must appear exactly once as a standalone trimmed line in Codex's response. The sentinel is not valid if:

  • It appears inline (e.g., See ## SATISFIED above)
  • It appears more than once
  • The response also contains unresolved questions after the sentinel

If the sentinel is malformed (multiple occurrences or unresolved questions follow it), treat the round as non-terminated and continue.

Cap handling

On round codex_cap + 1, halt the loop and surface to the user with three options:

Codex adversarial review reached round cap (<codex_cap>) for gate <gate>.
Codex has not emitted ## SATISFIED. Options:
  [force-pass]   Proceed without Codex sign-off. The trail remains for audit.
  [extend-cap N] Continue for N more rounds (N = 1–5).
  [rework]       Return to the prior lifecycle step and revise the artifact.

Wait for an explicit user choice before proceeding.

The two named cap terminal states (the only clean ways to end at the cap)

A review that reaches the cap WITHOUT a ## SATISFIED may still terminate cleanly — but only through one of exactly TWO named terminal states, each of which leaves a complete audit trail. Anything else at the cap (a bare cap_hit, or [force-pass] with no recorded rationale) is an audit exception, not a clean terminal: it writes its value verbatim and DELIBERATELY fails scripts/verify-codex-review-trail.ts (## Trail format).

  1. Cap + reasoned pushback recorded — final_status: cap-pushback-recorded. The cap was hit and, rather than an unaudited force-pass, the artifact author recorded a technical rebuttal to Codex's remaining findings in the trail — the same "push back only with technical evidence" discipline guild:review uses. The disagreement is ON RECORD (each open finding + why it is judged a non-blocker), so the trail is audit-complete and validates. Choose this when the operator [force-pass]es and the reasons are captured; a force-pass with no recorded rationale stays the force_passed audit exception.
  2. Verification-only round beyond cap — final_status: cap-verification-only. The round(s) taken past the cap were verification-only: confirming a just-applied fix, raising NO new adversarial surface. This is bounded (it ends the moment Codex confirms — write satisfied then — or is exhausted) and is distinct from [extend-cap N], which re-opens a fresh adversarial round. Use it to let Codex re-check the exact fix its last finding demanded without treating that as an unbounded extension.

Record the chosen terminal state's final_status: in the trail (## Trail format) and carry it in the in-memory status (## Output shape).

Output shape

type CodexReviewOutput = {
  // cap_pushback / cap_verify are the two NAMED cap terminal states (§Cap handling):
  //   cap_pushback → trail final_status: cap-pushback-recorded
  //   cap_verify   → trail final_status: cap-verification-only
  // cap_hit remains the UN-audited cap exception (fails the trail validator).
  status:
    | "satisfied" | "skipped" | "cap_hit" | "force_passed" | "extended" | "rework"
    | "cap_pushback" | "cap_verify"
    // no_verdict: the review never produced a judgement (provider refusal,
    // dispatch error, empty response) — see §Verdict-less rounds. Trail writes
    // final_status: no-verdict, an audit exception like a bare cap_hit.
    | "no_verdict";
  gate: string;
  rounds: number;               // total rounds executed
  trail_path: string;           // .guild/runs/<run-id>/codex-review/<gate>.md
  satisfied_at_round?: number;  // present when status="satisfied"
};

Trail format

.guild/runs/<run-id>/codex-review/<gate>.md:

---
gate: G-spec
run_id: <run-id>
artifact: .guild/spec/<slug>.md
started_at: <ISO-8601>
final_status: satisfied
rounds: 2
---

## Round 1

**Codex response:**
<response text>

---

## Round 2

**Codex response:**
## SATISFIED

final_status: is the trail-completeness field read by the SC11 validator scripts/verify-codex-review-trail.ts (per .guild/wiki/standards/codex-adversarial-review.md). It is the persisted disposition and is distinct from the in-memory status of the output shape. The validator accepts exactly four clean terminal values — two un-capped and the two named cap terminal states (## Cap handling) — write one of these:

in-memory statustrail final_status:
satisfied / force_passed with a real sign-offsatisfied
skipped (codex unavailable / unauthenticated)skipped-codex-unavailable
cap_pushback (cap + reasoned pushback recorded)cap-pushback-recorded
cap_verify (verification-only round beyond cap)cap-verification-only

A gate that ends without a clean disposition (a bare cap_hit, or a force_passed operator override without Codex sign-off and without a recorded rebuttal) writes that terminal value verbatim and deliberately fails the completeness validator — it is an audit exception that must be resolved, not papered over. The two cap-* values are the ONLY capped terminals that validate, precisely because each leaves a complete trail (a recorded rebuttal, or a bounded verification-only round). When the availability check skips the gate (returns status: "skipped"), still write the trail with final_status: skipped-codex-unavailable so the per-gate trail exists and validates.

Telemetry

Emit one codex_review_round event per round to .guild/runs/<run-id>/logs/v1.4-events.jsonl via the shared helper:

npx tsx ${GUILD_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-$HOME/.local/share/guild/dist/claude-code}}/scripts/emit-loop-event.ts \
  --event codex_review_round \
  --gate <G-spec|G-plan|G-diagnose|G-lane:lane-id> \
  --round <N> \
  --terminated <satisfied|false> \
  [--run-id <run-id>] [--cwd <repo-root>]

Use --terminated satisfied on the final round when ## SATISFIED is emitted or the user force-passes. Use --terminated false for non-final rounds. The codex_review_round event type is defined in the v1.4-jsonl-schema spec (§12) in the separate guild-benchmark repo; do not append these rows directly.

Config resolution

codex_cap resolves in this order (first wins):

  1. --codex-cap=N CLI flag — a supported power-user flag, parsed by the --codex-cap= case in scripts/read-guild-config.ts's arg-parse switch; clamped to [1,10]. It is kept in v2 (not deleted/folded into --rigor), alongside its siblings --loops / --loop-cap.
  2. .guild/settings.json key codex_cap
  3. Default: 5

Maximum: 10. Values above 10 are clamped to 10 with a warning.

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.