Double Gates – Why Every Stage Needs a Reviewer, Not Just the Code

We review code and approve requirements with a handshake. Why I put a dedicated reviewer agent in front of every production stage, why an agent must never check its own output – and what this pattern costs me per feature.

11/15/2026

•10 min read

Note on the Content

This series describes my insights from using AI in the software development process. These are personal experiences and conclusions from which I derived measures that worked for my projects. The series does not claim to be a comprehensive guide or universally valid — it is meant as inspiration for your own projects.

Two posts in this series were about structure, about three layers and a checkable contract in between, and two more about tokens. This post goes back to the process and to an asymmetry I did not notice for a long time, even though I worked with it every day.

In software development we have a mature culture for code review. Four-eyes principle, comments on the diff, approval as a merge condition. And for the two stages before it, requirement and solution design, we essentially have: a handshake.

Economically, that is remarkably backwards. An error in the requirement is orders of magnitude cheaper to fix than one in the implementation, and yet we check it last.

The Moment It Became Obvious

In my agent team from the first series there was one handover that never worked: the business analyst wrote a use case, I read it, I found it good, the solution architect built on it — and two stages later it turned out that one acceptance criterion had been ambiguous.

The first reflex was to prompt the business analyst better. I did that several times, and each time it helped a little. What did not help was the idea I had afterwards: letting the agent check its own output. I appended a review phase to it: "go through your document again against these criteria".

The result was as predictable as it sounds in hindsight: it found small things. Wordings, missing numbering, a typo. What it never found were the assumptions it had made itself, because while writing it took them for the obvious choice, not for assumptions.

An author checking their own work reads to confirm. That is true for me, and it is true for a model with the same context window.

The problem applies to any author and is not an AI problem. It is the reason we have the four-eyes principle at all. I had simply forgotten it in two of the three places in the agent pipeline, at the requirement and at the concept.

The Pattern: Two Gates per Stage

What came out of it now repeats identically at every stage:

Diagramm wird geladen …
The double-gate pattern: first an independent agent, then the human. Identical on each of the three stages.
  1. An agent gate: a reviewer agent checks the artifact before a human ever gets to see it.
  2. A human gate: the approval is always made by a human.

The division of roles behind it:

Agents produce and check. Humans decide.

Specifically, in exactly three places: approval of the requirement, approval of the concept, merge. All three sit at expensive or irreversible junctions. In between, the agents work autonomously, but pre-qualified.

I saw a gap at these approval points in target project B, a Nuxt project. The agents worked in a separate Git worktree there. I first looked for the use case file in the main checkout, did not find it, and later asked for the branch. The workflow does not name the working location clearly enough at approvals.

The Whole Flow

Written out, it now looks like this:

Diagramm wird geladen …
Six levels with three human approvals. The auditors deliberately run outside this loop.

Level 2 turns every acceptance criterion into a test scenario before the concept is even written; that gets its own post later in this series. Three further decisions in there need explaining.

The reviewer changes no status. Every document goes through the statuses "draft", "in review" and "approved". The reviewer is a quality gate within the status "draft". Only the human sets "in review" and then "approved". That matters, even if it looks bureaucratic: otherwise I would have an agent pushing its own pipeline forward, and the human gate would be a formality with a pre-filled result.

The reviewer writes no file. Its report goes back inline to the producer. Doc reviews are iteration artifacts: they have served their purpose once the finding is addressed. There is exactly one exception: the final code review is stored as a file in the feature branch and belongs to the pull request. It is the only review round whose result still interests anybody after the merge.

The auditors stand outside. The three whole-codebase checkers (health, spec compliance, conventions) are triggered by events: before releases, after large merges. Per pull request they would be redundant with the code reviewer and would report the same pre-existing findings every time. Their job is drift over time, not feature acceptance. I got that wrong at first, and it was the fastest way to turn findings into noise.

What a Good Reviewer Agent Does Differently

A reviewer is not simply a producer with an inverted brief. Four things made the difference for me.

It has its own context. That is the entire reason for its existence. It reads the artifact and the rules and not the thoughts it was created with. What the producer considered obvious has to be written in the document, otherwise it does not exist.

It verifies against the codebase, not against the document. The concept reviewer checks whether the named files, classes and composables actually exist. That sounds like a detail and is the most frequent genuine finding: a concept mentioning a file that does not (any longer) exist reads perfectly plausibly.

It is allowed to say "I could not check this". A reviewer that produces a verdict on every point produces an invented verdict on some of them. A declared blind spot is a result; a silently skipped check is a lie with a checkmark next to it.

The same applies to my audit skill, which checks the workflow against the current Claude Code documentation before every release. A follow-up check of its first run found five weaknesses, including claims about Claude Code's behaviour without evidence. A finding about skills being loaded twice was rated Major but derived only from the text; in the transcripts it occurred in none of the runs. Since then every claim the skill makes about Claude Code's behaviour needs a quote from the documentation or a measurement in the transcript.

It has to say what is good. In my review protocol at least one entry in the "what is good" section is mandatory. That started as cosmetics and turned out to be the most useful part of the whole report. That has nothing to do with patting the producer on the back: it forces the reviewer to understand the artifact as a whole instead of just working through a list of defects. A reviewer that finds nothing good usually did not read closely.

What It Costs

I rarely read about the costs in posts like this one.

In this setup a feature goes through at least eight agent invocations: producer and reviewer on three stages, plus test preparation and test verification. Each of these invocations starts with a fresh context and does its own analysis of the codebase. That is the whole point, and it costs.

Two feature runs in real projects cost 48.3 million tokens in total (a small feature in target project A) and 153.4 million (a large one in target project B), 94% and 96% of it cache reads. The details are in Part 3.

I noted what I still changed at the approvals in both feature runs. In target project A it was one addition at the use case, nothing at the concept, and after testing on the device the request for a fade effect. In target project B, with five use cases, I decided nine domain questions from the business analyst at the use case, gave five requirements for the concept, and after my test asked for a correction to the navigation. The approvals also cost waiting time: in A the pipeline waited one hour and 33 minutes for my use case approval, and during that time I read the use case myself. In B it waited about 50 minutes for me across the whole run.

I can only state the benefit qualitatively: for a feature with a genuine functional core it clearly pays off. For a text change it is absurd. During the rebuild after the audit from Part 2, the reviewers found real errors, among them a MAJOR in the first concept, a loophole via symlinks and a merge of settings.json that lost hook groups.

That is why there is an explicitly defined fast lane as a counterweight: trivial changes (typos, doc corrections, tooling tweaks) skip the specification chain entirely. What they do not skip are the quality gates, the code reviewer and the merge gate.

The thinking behind it matters to me: a lightweight path emerges anyway. If I do not define it, impatience defines it, and then it is undocumented and unbounded. The fast lane is an attempt to make the shortcut visible and bounded instead of forbidding it.

I saw such a shortcut in target project A, a Flutter project. After testing on the device I wanted one more fade effect. The main session, which steers the agents, implemented it itself instead of handing it to the implementation agent. The gates ran, and the code reviewer checked it afterwards. It was still a shortcut past the pipeline. In target project B, my feedback after testing went the regular way: as a new plan step to the implementation agent, followed by a review of just the change (delta review).

Blind Spots

Two reviewer levels catch more than one. They do not catch everything, and there is one class of error they systematically miss: the one where producer and reviewer share the same wrong assumption. Both read the same rules, both work with the same kind of model, both see the same codebase. If the rule itself is wrong, the reviewer waves it through.

I have experienced exactly that case, and it is unpleasant enough for its own post later in this series: a realisation plan that violated the hard rule that core files are never changed directly in a project, and was approved by two instances. It only surfaced during implementation, when a guard blocked the write, and then the implementation agent wrote the file with a shell command the guard does not see.

The consequence was not another reviewer. The existing ones got a fixed basis for their check: the solution architect clarifies for every file whether it belongs to the core or the adapter before it goes into a measure, and the concept reviewer checks every named file against the category table. The check now depends on a table, not on how the rule is read.

Conclusion

What I take away is less an AI insight than a process truism I never applied to the early stages: every production stage deserves a reviewer, not just the last one. Requirement and concept errors are caught where they are cheap, and that is the only reason the additional effort pays off at all.

The second part is the division of roles: agents may produce and check, but not decide. Three human approvals sounds like a lot. In practice it is considerably less review load than before, because I receive artifacts that have passed a pre-check, instead of raw drafts where I hunt for the small stuff myself.

The next post is about the uncomfortable flip side of this pattern: what happens when producer and reviewer cannot agree? Every loop needs a stopping condition — and mine has two rounds.

How do you check your requirements before anyone starts building? Is there a gate before the code review in your process — and if so, is it formal or a handshake?