openai / openai/codex-plugin-cc

Stop-review gate: review timeout equals the hook's own 900s timeout, so a slow review ends the turn with no message

Open Beginner friendly
#766 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
33.3k
Forks
2.3k
PR merge metrics
No merged PRs in 30d

Description

We use the Codex plugin from Claude Code on a number of machines, and an automated audit of our
hooks flagged the Stop hook for how long it can hold a turn open. Reading
stop-review-gate-hook.mjs, the review's internal timeout and the hook's own declared timeout are
the same number, which I think makes the "review timed out" path unreachable. We don't have the gate
enabled anywhere, so this is from reading the code, not from hitting it. Setup: plugin v1.0.6
(byte-identical to main today), macOS, Node 26.7.0, ChatGPT auth.

What happens

plugins/codex/hooks/hooks.json gives the Stop hook "timeout": 900, and the hook spawns the
review with a timeout of the same 900 seconds:

// plugins/codex/hooks/hooks.json
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/stop-review-gate-hook.mjs\"",
"timeout": 900

// plugins/codex/scripts/stop-review-gate-hook.mjs
const STOP_REVIEW_TIMEOUT_MS = 15 * 60 * 1000;
...
const result = spawnSync(process.execPath, [scriptPath, "task", "--json", prompt], {
  cwd, env: childEnv, encoding: "utf8", timeout: STOP_REVIEW_TIMEOUT_MS
});

if (result.error?.code === "ETIMEDOUT") {
  return {
    ok: false,
    reason:
      "The stop-time Codex review task timed out after 15 minutes. Run /codex:review --wait manually or bypass the gate."
  };
}

The hook starts first and spawns the child a few milliseconds later, so the child's deadline is
always the later of the two, and Claude Code kills the hook while the child is still inside its own
window. The hook's only write to stdout happens after spawnSync returns, so at that point it has
emitted nothing at all. A review that genuinely runs long therefore leaves the user with a turn that
appears to hang for fifteen minutes and then ends with no reason given, instead of the
"run /codex:review --wait manually or bypass the gate" note the code is trying to deliver. The
branch itself is correct — spawnSync does set error.code === "ETIMEDOUT" on Node 26 — it just
doesn't look reachable.

What we ruled out

Not our configuration: stopReviewGate is false in every workspace here, so nothing we set touches
this path. Not a stale copy: the shipped stop-review-gate-hook.mjs is byte-identical to main, and
main's hooks.json still declares 900. I searched open and closed issues for "stop review gate",
"hook timeout", "ETIMEDOUT", "900" and "15 minutes"; #248 and #530 sit next to this one but neither
is about the two timeouts being equal, so I opened it separately rather than commenting there.

Reproduction

I haven't sat through a real 900s review, and by inspection it's only these two constants. To see it
quickly, set STOP_REVIEW_TIMEOUT_MS and the hooks.json timeout to the same small value, enable
the gate, and make the review hang.

One guess, and I may be reading this wrong: if the hook is meant to report its own timeout, the inner
deadline needs headroom under the outer one. Which number should move is your call, so I haven't sent
a PR picking one. Happy to test a patch.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Compare the timeout in plugins/codex/hooks/hooks.json with STOP_REVIEW_TIMEOUT_MS and the spawnSync call in plugins/codex/scripts/stop-review-gate-hook.mjs. Reproduce the condition with matching short timeouts and a hanging review. Done means the hook's timeout outcome is observable and the documented manual-review or bypass message is emitted.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
cli, tooling
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.