Skip to content

Add optional CODEX_REVIEW_GATE_MAX_ROUNDS cap to the stop review gate#396

Open
dxcmb wants to merge 2 commits into
openai:mainfrom
dxcmb:review-gate-max-rounds
Open

Add optional CODEX_REVIEW_GATE_MAX_ROUNDS cap to the stop review gate#396
dxcmb wants to merge 2 commits into
openai:mainfrom
dxcmb:review-gate-max-rounds

Conversation

@dxcmb

@dxcmb dxcmb commented Jun 23, 2026

Copy link
Copy Markdown

Problem

The stop-time review gate has no built-in bound. stop-review-gate-hook.mjs keeps emitting {"decision":"block"} as long as the Codex review returns BLOCK:, and it does not consult the stop_hook_active flag. As the README itself warns, this can create a long-running Claude/Codex loop that drains usage limits. The only controls today are watching the session and hitting Esc, or toggling the gate off entirely.

Change

Add an opt-in cap via the CODEX_REVIEW_GATE_MAX_ROUNDS environment variable:

  • Unset or 0 → unbounded (current behavior, fully backward compatible).
  • Positive integer N → after N consecutive blocked rounds in a session, the gate allows the stop instead of blocking again, with a note pointing back to /codex:review --wait and the env var.

Rounds are counted per session:

  • stop_hook_active === false (a fresh user turn) starts the count at 0.
  • Each blocked round increments the counter; an allowed stop resets it.
  • The counter is persisted per session_id in the existing per-workspace state config (setConfig/getConfig), so no new storage mechanism is introduced.

Why an env var

It keeps the default untouched (no behavior change for anyone not setting it), needs no new setup flag or migration, and is trivial to set per-project or per-session for users who run the gate routinely and want a guaranteed ceiling.

Files

  • plugins/codex/scripts/stop-review-gate-hook.mjs — round counting + cap; imports setConfig.
  • README.md — documents the env var under the review-gate section.

Testing

Verified manually that with the gate enabled and CODEX_REVIEW_GATE_MAX_ROUNDS=N, the hook blocks for N rounds and then allows the stop, and that leaving the var unset preserves the existing unbounded behavior. Happy to add a unit test under tests/ if you'd like — pointers to the preferred harness welcome.

🤖 Generated with Claude Code

dxcmb added 2 commits June 23, 2026 13:40
The stop-time review gate has no built-in bound: it keeps blocking the
stop while Codex returns BLOCK, which can create a long-running
Claude/Codex loop (as the README itself warns).

This adds an opt-in cap via the CODEX_REVIEW_GATE_MAX_ROUNDS env var.
When set to a positive integer, the gate allows the stop after that many
consecutive blocked rounds in a session. Unset/0 keeps the previous
unbounded behavior. Rounds are counted per session via stop_hook_active
and persisted in the existing per-workspace state config.
@dxcmb dxcmb requested a review from a team June 23, 2026 11:42
fangkangmi added a commit to fangkangmi/codex-plugin-cc that referenced this pull request Jul 2, 2026
…penai#248, openai#306)

The Stop review gate treated every non-ALLOW outcome as a review BLOCK:
genuine `BLOCK:` verdicts AND transient infrastructure failures (timeout,
non-zero exit / rate limit, invalid JSON, empty or garbled output) all
returned `{ok:false}`, and `main()` mapped every `!ok` to
`decision:"block"`. A transient Codex failure therefore blocked the Stop
event, Claude re-woke, the review re-ran, hit the same failure, and looped
indefinitely — burning tokens with no useful review until the user disabled
the gate (openai#306 is the same root cause via the rate-limit path).

Split the review result into three outcomes — allow / block / infra_error.
Only a real `BLOCK:` verdict emits a Stop `block`. Infrastructure failures
now fail OPEN: warn on stderr and let the session end, so the rewake loop
can't form. Genuine ALLOW/BLOCK behavior is unchanged. Complementary to the
valid-JSON (openai#352) and opt-in round-cap (openai#396) PRs.

Adds a `stop-gate-infra` fake-codex behavior (thread/start raises a 429) and
a regression test asserting the hook fails open on an infra error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant