# How Does the Codex Review Gate Work Internally

> Explore the internal workings of the Codex review gate an optional safety mechanism that blocks session stops if issues are detected during review.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: internals
- Published: 2026-07-18

---

**The Codex review gate is an optional safety mechanism that forces a Codex review before a Claude session can be stopped, blocking the stop if the review detects issues.**

The review gate in the `openai/codex-plugin-cc` repository provides a configurable stop-time checkpoint that prevents session termination until a dedicated Codex task validates the previous turn's work. This article explains the complete internal workflow—from configuration persistence to decision emission—based on the actual source code implementation.

## Configuration and State Management

The review gate is controlled by a boolean flag stored in persistent state. In **`codex-companion.mjs`**, the `handleSetup` function processes the `--enable-review-gate` and `--disable-review-gate` flags (lines 21‑23) and persists the configuration via `setConfig` (lines 29‑35).

The `setConfig` function in **`lib/state.mjs`** writes the `stopReviewGate` key to [`state.json`](https://github.com/openai/codex-plugin-cc/blob/main/state.json) (lines 53‑59). When this flag is `true`, the plugin treats subsequent stop requests as gated reviews.

```bash

# Enable the review gate

codex:setup --enable-review-gate

# Disable the review gate

codex:setup --disable-review-gate

```

## The Stop Hook Mechanism

When Claude issues a stop command, the *Stop* hook defined in [`hooks.json`](https://github.com/openai/codex-plugin-cc/blob/main/hooks.json) executes **`stop-review-gate-hook.mjs`**. The hook begins by reading its JSON input through `readHookInput` (lines 21‑27) and resolving the workspace root (line 45).

It then loads the current configuration using `getConfig` (line 46) and checks `config.stopReviewGate` (lines 54‑57). If the gate is disabled, the hook logs any running task note and returns immediately, allowing the stop to proceed without interruption.

## Running the Stop-Gate Review Task

If the gate is enabled, the hook launches a special Codex task containing the marker defined in `STOP_REVIEW_TASK_MARKER` (line 19): *"Run a stop‑gate review of the previous Claude turn."*

The `runStopReview` function spawns a child process executing `codex-companion.mjs task …` with the marker as the prompt (lines 99‑107). This child process runs through the normal task pipeline via `executeTaskRun` in **`codex-companion.mjs`**. Because the prompt contains the marker, `buildTaskRunMetadata` (lines 40‑46) creates a job explicitly titled **"Codex Stop Gate Review"** (lines 42‑45).

The child process returns a JSON payload where the `rawOutput` field contains the final Codex response.

## Decision Handling and Blocking

After the review task completes, `parseStopReviewOutput` examines the first line of `rawOutput` (lines 79‑88):

- If the line starts with `ALLOW:` → returns `{ ok: true }`
- If the line starts with `BLOCK:` → returns `{ ok: false, reason: … }`

If the task fails, times out, or returns malformed JSON, the hook constructs a generic failure reason (lines 70‑78).

The hook then emits the final decision:

- **Block**: If `review.ok` is false, `emitDecision` (line 30) sends a payload `{ decision: "block", reason: … }` (lines 66‑71), preventing the stop and surfacing the reason to the user.
- **Allow**: If the review passes, the hook logs any running-task note (line 75) and permits the stop to continue.

```json
// Example blocked stop response
{
  "decision": "block",
  "reason": "Codex stop-time review found issues that still need fixes before ending the session: BLOCK: missing import statements"
}

```

## Summary

- **Configuration**: The `stopReviewGate` boolean flag persists in [`state.json`](https://github.com/openai/codex-plugin-cc/blob/main/state.json) via `handleSetup` and `setConfig` in **`codex-companion.mjs`** and **`lib/state.mjs`**.
- **Hook Activation**: **`stop-review-gate-hook.mjs`** runs on every stop event, checking the config flag before proceeding.
- **Task Execution**: The `runStopReview` function spawns a Codex task with a special marker, creating a "Codex Stop Gate Review" job via `buildTaskRunMetadata`.
- **Result Parsing**: The `parseStopReviewOutput` function inspects the first line for `ALLOW:` or `BLOCK:` prefixes to determine the review outcome.
- **Decision Emission**: The `emitDecision` function blocks the stop if the review fails, otherwise allows the session to terminate normally.

## Frequently Asked Questions

### How do I enable or disable the Codex review gate?

Use the setup command with the appropriate flag: `codex:setup --enable-review-gate` sets `stopReviewGate: true` in the state file, while `codex:setup --disable-review-gate` disables it. These commands invoke `handleSetup` in **`codex-companion.mjs`**, which updates the persistent configuration via **`lib/state.mjs`**.

### What happens if the review task fails or times out?

If the child process fails, times out, or returns malformed JSON, **`stop-review-gate-hook.mjs`** constructs a generic failure reason (lines 70‑78) and treats the result as a blocking condition. This ensures that network issues or process errors default to a safe state rather than allowing an unreviewed stop.

### How does the hook distinguish between review task output and regular Codex responses?

The `parseStopReviewOutput` function specifically checks the first line of the `rawOutput` field for the prefixes `ALLOW:` or `BLOCK:` (lines 79‑88). This simple protocol allows the hook to parse the review decision without complex JSON parsing, making the gate reliable and easy to debug.

### Can I customize the review criteria for the stop gate?

While the gate mechanism itself uses a fixed marker (`STOP_REVIEW_TASK_MARKER`), the actual review logic follows the standard Codex task pipeline. You can modify the prompt template in **[`plugins/codex/prompts/stop-review-gate.md`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/prompts/stop-review-gate.md)** to adjust what the review checks for, but the `ALLOW:`/`BLOCK:` parsing logic in `parseStopReviewOutput` remains constant.