Checks that keep working at high speed

The quality gates that should block a merge

A gate is a check that stops a change reaching the main branch without a person deciding. Everything else is a suggestion. This page covers which checks deserve that power, why a short blocking list beats a long advisory one, how to keep the gates trustworthy, and what to do about the changes that still need a human.

Published September 1, 2026. Editorial.

Key takeaways

  • If a check can be ignored when the team is busy, it is not a gate. It is a report nobody reads.
  • Keep the blocking list short and absolute. Five gates that always block beat twenty that sometimes warn.
  • A gate an agent can edit is not a gate. Check definitions and pipeline configuration need stricter protection than the code they protect.
  • Human review still exists, on a defined and much smaller set: money, credentials, personal data, public contracts, migrations.

Code review used to be the main quality step. It worked because the volume of code was limited by the number of people writing it, so there were enough people to read it. That relationship is gone. One engineer can now open more pull requests in a morning than a team can review carefully in a day.

The response most teams try first is more review: rotas, review SLAs, reminders in chat. It does not work, because the input rate is the problem. What works is moving as much of the judgment as possible into checks that run without anyone deciding to run them.

What makes something a gate

A gate has three properties. It runs automatically on every change. Its result is binary. And when it says no, the change does not merge, without an exception path that a busy engineer can take at four on a Friday.

That third property is the one teams get wrong. A check with an override is a check that will be overridden precisely when the pressure is highest, which is when you most needed it. If a gate genuinely has to be bypassable, the bypass should require a second person and leave a record, so it is visible in a postmortem rather than invisible in a habit.

Anthropic's guidance for Claude Code describes the same step up in enforcement from the agent's side: a check in a prompt works for one task, while a hook that runs your check as a script and blocks the turn from ending is what makes an unattended run finish correctly [1]. The same principle applies to a delivery pipeline without change. The stronger the enforcement, the less it depends on someone being attentive.

The gates that deserve to block

Our default list is short on purpose. Each of these blocks, always.

The build. It compiles, it type-checks, it starts. This sounds too obvious to list, and then you find a repository where the type errors are at 400 and everyone has learned to ignore the output. A number that only goes up is not a signal.

The test suite, including the checks written from the specification. Not just that tests pass, but that the tests which encode the acceptance criteria pass. The distinction matters because generated tests can pass while testing nothing, which is covered in test strategy when the AI writes the tests too and, in depth, in the eval-driven development guide.

Secret scanning. Nothing that looks like a credential reaches the main branch. This gate is cheap, has almost no false-positive cost compared to what it prevents, and catches a failure mode that generated code produces regularly because example code is full of placeholder credentials.

Dependency policy. New dependencies are checked against known advisories, and a new package cannot be added silently as part of an unrelated change. Models invent package names at measurable rates: research presented at USENIX Security 2025 found references to invented packages in at least 5.2 percent of commercial model output and 21.7 percent of open-source output across 576,000 samples [2]. OWASP's Top 10:2025 lists Software Supply Chain Failures as A03 [3]. The detail is in dependency control when an agent picks the packages.

Migration and destructive-change detection. Any change that alters a schema, deletes data, or cannot be reversed by a redeploy gets flagged and sent to a human. This is the one gate that does not decide correctness. It decides who looks.

That is five. Most teams can implement all five in a week, and they cover a large share of what actually reaches production broken.

What should warn rather than block

Style, formatting, complexity scores, coverage percentages, and most static-analysis suggestions belong in the group of checks that only warn. Two reasons.

The first is that blocking on them trains people to bypass gates. Once an engineer has learned that the pipeline says no for reasons that do not matter, the habit spreads to the gate that did matter.

The second is that several of these measure the wrong thing when code is generated. Coverage is the clearest example. An agent asked to raise coverage will raise coverage, and the tests it adds to do so are often assertions that the code does what it does. A coverage gate in an AI-native repository mostly measures compliance with the coverage gate.

Formatting is a special case: it should be applied automatically rather than checked. A formatter that rewrites the file removes the argument entirely, which is worth more than any consistency gate.

Protect the gates from the code they check

This is the failure that surprises teams, and we have seen it more than once. An agent asked to make the build pass will make the build pass. If it can edit the test that fails, or the configuration that runs it, that is a legitimate path to the goal as stated.

So the gate definitions need stronger protection than the code. In practice: check definitions and pipeline configuration live behind a required human approval, changes to them are visible in review as their own diff rather than hidden in a feature branch, and the pipeline runs from a protected configuration rather than from whatever is on the branch. A pipeline that runs the branch's own config is a pipeline any change can disable.

The same rule applies to the acceptance checks. If the criteria that decide whether a feature is done can be relaxed by the session implementing the feature, the whole standard becomes advisory. This is the practical version of an old idea: the thing being measured should not control the measurement. Our post on never let the model grade its own work makes the argument in full.

Keeping gates trustworthy

A gate is only as useful as its signal, and the fastest way to destroy a gate is to let it fail for reasons unrelated to the change. Flaky tests are the usual cause, and they are worse in an AI-native team because volume multiplies them: a test that fails one run in fifty is a curiosity at ten merges a week and a daily interruption at a hundred.

Treat a flaky check as a broken gate rather than as an annoyance. Take it out of the pipeline, fix it, and put it back. Leaving it in place teaches the team that a failing pipeline might mean nothing, which is the same as having no pipeline. The specific reasons this gets worse with generated tests are in why flaky tests are worse when agents write them.

Speed matters too. A gate that takes forty minutes is a gate people work around by batching changes, which makes each change larger and each failure harder to attribute. Fast feedback is not a comfort feature, it is what keeps units small.

What still needs a person

Automating the routine is not the same as removing review. It is what makes the remaining review affordable. Our default is that a human reads a change when it touches money, credentials, personal data, a public contract, or a migration, and otherwise the gates decide.

That list is short enough to be real. A senior engineer can read every change that touches those five categories in a normal week, which is not true of every change. The result is deeper review on the changes where depth is worth it and none on the changes where it did not.

If a category of problem keeps arriving at human review, that is a gate that should be written. The habit worth building is to treat every repeated review comment as a bug report about the pipeline.

Where the gate runs matters

The same check has a different value depending on when it runs, and teams often place them badly.

Before the merge is where anything that decides correctness belongs, because a change that reaches the main branch has already become everyone else's problem: other work builds on it, reverting it affects people who did nothing wrong, and the cost of removal rises hourly.

After the merge is the right place for slow, broad, or expensive checks: long integration suites, performance comparisons, deep security scans. These cannot gate every change without destroying the feedback speed that keeps units small, so they run on the main branch and their failure triggers a fix or a revert rather than blocking a queue.

The mistake is a check that runs in neither place and instead produces a weekly report. That is the worst of the options, because the finding arrives after the code has been built on, the person who could fix it is working on something else, and nobody owns the report. If a check is worth running, it belongs in one of the two positions above, with an owner and a defined response.

There is a third position worth using in an AI-native team: inside the agent's own work, as a check it runs itself before it hands anything over. That is the cheapest place of all, because a failure there costs no human attention and no pipeline time, and it is exactly what Anthropic's guidance means by giving the model a check it can run [1].

Where this connects

Gates enforce the standard set in what done means when an agent writes the code, and they are what makes it safe to release often, as covered in progressive delivery for AI-written changes. The specific practice of writing checks from the specification, and the ways those checks can give false confidence, is the eval-driven development guide. The main guide puts the whole model together, and this is usually the first thing we build on an AI development engagement.

Best for

  • Checks with a binary result and a low false-positive rate: build, type check, specification tests, secret scanning
  • Anything with a security or supply chain consequence, including new dependencies
  • Detecting changes that cannot be reversed by a redeploy, so they can be routed to a person

Avoid if

  • The check produces a score rather than a verdict, such as coverage or complexity
  • It is a style or formatting rule that a formatter could simply apply
  • It fails intermittently for reasons unrelated to the change

Check before you decide

  • Confirm the pipeline runs from protected configuration, not from the branch under review
  • Confirm a change to a gate definition is visible as its own diff and needs a human approval
  • Check the bypass path: if one engineer can override a gate alone with no record, it is not a gate

Common questions

Which checks should block a merge in an AI-native pipeline?

Five carry most of the value: the build and type check, the tests that encode the acceptance criteria, secret scanning, dependency policy including advisory checks on anything newly added, and detection of migrations or destructive changes so a person can look. Each is binary, cheap to run, and rarely wrong for reasons unrelated to the change.

Why should code coverage not block a merge when AI writes the code?

Because an agent asked to raise coverage will raise coverage, usually by adding assertions that the code does what it does. The number goes up while the evidence does not. Coverage is useful as a trend to investigate, but as a gate it mostly measures compliance with the gate rather than whether behaviour is correct.

Can an agent disable the checks that are supposed to catch its mistakes?

Yes, if you let it. An agent asked to make the build pass will make the build pass, and editing a failing test or the pipeline config is a legitimate route to that goal as stated. Gate definitions and pipeline configuration need stronger protection than the code, and the pipeline should run from protected configuration rather than from the branch.

How many blocking gates should a team have?

Few and absolute rather than many and negotiable. Five that always block beat twenty that sometimes warn, because every override teaches the team that a failing pipeline is a matter of opinion. Once that habit exists it spreads to the gate that actually mattered.

What should happen to style and formatting rules?

Apply them automatically instead of checking them. A formatter that rewrites the file removes the argument and the failed build together. Reserve blocking for checks about correctness and safety, and put complexity scores and static-analysis suggestions in a group of checks that only warn, so no one has to override them.

Which changes should still get human review?

Changes touching money, credentials, personal data, a public contract other people depend on, or a data migration. That list is short enough that a senior engineer can genuinely read all of it in a week, which is the point. Reviewing everything at the old depth is what turns the review queue into the step that slows all delivery.

What do we do about a flaky check in a high-volume pipeline?

Treat it as a broken gate rather than an annoyance. A check that fails one run in fifty is a curiosity at ten merges a week and a daily interruption at a hundred, and it teaches the team that a failure might mean nothing. Take it out of the pipeline, fix it, and put it back rather than living with it.

How fast do quality gates need to run?

Fast enough that nobody batches changes to avoid waiting. A forty-minute pipeline pushes engineers to bundle work, which makes each change larger and each failure harder to attribute, undoing the benefit of small units. Pipeline speed is a delivery control, not a developer comfort.

Should a gate ever be bypassable?

If it must be, the bypass should require a second person and leave a record, so it appears in a postmortem instead of becoming a habit. An override that one engineer can use alone will be used exactly when pressure is highest, which is when the gate was most valuable.

How do we know which new gate to build next?

Watch what human review keeps catching. A class of problem that appears in three reviews in a row is a bug report about your pipeline, not a review success. Converting each repeated comment into an automated check is how the blocking list grows for real reasons rather than by copying someone else's template.

Start a project