← Back to Blog
Claude CodeCodexCode review

Why my review gate saves each verdict under the exact commit hash

by Iliya OblakovPublished on October 22, 20265 min read3 views
Why my review gate saves each verdict under the exact commit hash

Two recent items in the Claude Code repository, a changelog fix and a bug report, describe two ways a review step can go wrong.

What Anthropic fixed in Claude Code 2.1.305

The Claude Code changelog for version 2.1.305 has this line about Code Review, Anthropic's managed pull request reviewer:

"[Code Review] Fixed Code Review sometimes not reviewing the newest commit when several pushes landed on a pull request during a review"

Source: Claude Code CHANGELOG.md, version 2.1.305.

If nothing records which commit a review actually read, a review of an older commit looks the same as a review of the newest one. Anthropic has fixed this in its own product. The same risk exists in any setup where new commits can land while a review is running, a local one included.

What issue #103536 reports

Issue #103536 was opened on 19 Oct 2026 at 20:45 Sofia time and is titled "[BUG] Model edits tracked files during a read-only review, despite loaded 'never edit unless asked / zero autonomy' rules". The reporter writes:

"While re-reviewing pull requests, the model edited a tracked file (CHANGELOG.md) on its own initiative. It removed a duplicated entry and reworded another, and the user had not asked for either."

The environment section says why nothing stopped it:

"Auto-approval allowed the Edit and Bash tools, so nothing stopped the write"

Source: anthropics/claude-code issue #103536.

According to the issue, the rules telling the model not to edit were loaded every turn from CLAUDE.md and MEMORY.md. The Edit tool was still available, so the edit went through.

How the gate ties a verdict to one commit

two-engines-gate is a free, MIT-licensed local review and merge gate for Claude Code and Codex.

bin/review.sh reads the full hash of HEAD at the start and saves the verdict as .ai/reviews/<first 12 characters of HEAD>.md (lines 22 and 23). It deletes any earlier verdict for that commit first (line 24). After the reviewer exits, it checks that HEAD is still the same commit and stops with "REVIEW VOID: HEAD moved during the review" if it has changed (line 74). The saved file starts with a Head: line that holds the full 40-character hash (line 82).

bin/merge-check.sh then looks for .ai/reviews/<first 12 characters of HEAD>.md and refuses if the file is missing or if its Head: line names a different commit (lines 21 to 23). It also needs a test pass record named after the full hash, .ai/tests/<HEAD>.pass (lines 18 to 20), and a verdict whose reviewer is a different engine from the builder (lines 24 to 27).

When a new commit lands after a review, merge-check finds no verdict for it and refuses. The README gives the reason in two sentences: "an ACCEPT for an older commit can quietly cover code nobody reviewed. A new commit needs a new review and a new test run."

How the reviewer is kept away from Edit and Write

The gate's reviewer is always the engine that didn't write the code. With the default BUILDER=claude, Codex reviews, and review.sh calls it as codex exec -s read-only (bin/review.sh, line 60). docs/engines.md (line 13) describes this as the read-only sandbox, where Codex can read files and run read-only commands such as git diff but cannot write.

With BUILDER=codex, Claude Code reviews. This is the call in bin/review.sh (lines 66 to 68), shown here without the optional model argument:

claude -p "Do the review described on standard input." --restricted --strict-mcp-config \
  --permission-mode dontAsk --tools "Read,Grep,Glob" --allowedTools "Read,Grep,Glob" \
  --disallowedTools "Bash,Edit,MultiEdit,Write,NotebookEdit,WebFetch,WebSearch,Task,Agent"

--tools "Read,Grep,Glob" limits the session to those three tools, and --disallowedTools also names Edit, MultiEdit, Write, NotebookEdit and Bash. docs/engines.md (line 30) says that with this call Claude Code "cannot run commands, git included, and cannot edit or write files", which is why review.sh puts the commits and the full diff into the prompt.

review-prompt.md also tells the reviewer "do not edit, create or delete files", and the gate doesn't depend on that sentence being obeyed. In issue #103536 the edit went through because the Edit tool was allowed, and in the gate's Claude Code call the reviewer starts without it. As a second check, review.sh runs git status after the review and stops with "REVIEW VOID: files changed during the review" if any file outside .ai/ changed (line 75).

What the gate doesn't do

The README lists its limits. It says the gate "does not make the code correct" and describes it as "a local guard against merging the wrong commit, not a security boundary", because anything with write access to the repository can write files under .ai/. It doesn't push, merge or talk to GitHub.

Try it, and the kit

The free gate is at github.com/IliyaOblakov/two-engines-gate. bash demo.sh in a clone walks one change through it with a stand-in reviewer, so it needs no model, account or network.

The Two Engines Kit is the paid kit, currently v1.0.2. In it Claude Code writes the code, Codex reviews it read-only, the review script saves the verdict under the commit Codex reviewed, and the merge script refuses to touch GitHub without a passing test run on that same commit. With REQUIRE_REVIEW=1 it also refuses a commit that has no saved ACCEPT. The Two Engines Kit is built on information gathered since the first Codex and Claude CLIs. It costs $29 for the first 30 sales, then $39, at rayastats.com/en/two-engines-kit.

Rate this article

Be the first to rate this article • 3 views

More from the blog