Back to all writing

The gates machine-written code has to pass

2026-08-18 · 4 min read

Most of the code I ship these days is written by a coding agent. That sentence still makes some engineers flinch, and I understand why. The follow-up question is always the same: how do you know it’s right? My answer is unsatisfying if you want a trick, and specific if you want a system. I stopped relying on review alone and started building gates.

A gate, as I use the word, is a check that runs on the merge path and cannot be skipped by being busy, tired, or confident. Human review is still there. But review is a judgment call made at 5 p.m. by someone who has read forty diffs that day; a gate applies the same standard to the first diff and the four-hundredth. When code arrives faster than anyone can read it carefully — which is exactly what agents do — the standard has to live in machinery, not in willpower.

Not everything on that path is a gate, and the distinction is worth keeping sharp. A gate blocks: it fails closed, before merge. An audit observes: it runs after the fact, and it exists to catch whatever went around the gates. And some calls stay with a human on purpose — releases, money movements, anything irreversible. Teams that blur these three end up treating alerts as if they were gates, and quietly disabling the gates that block them.

The gates worth running come from incidents. The examples that follow are representative failure classes, deliberately blurred across the production systems I have worked on. A billing bug becomes an idempotency check that fails the build if a money path can execute twice. Configuration that quietly diverges between environments becomes a drift check that compares what is declared against what is actually running. A change that reaches the mainline around the process becomes a separate after-the-fact audit that watches the merge path and alerts on known bypass patterns. The pattern is always the same: write the postmortem, fix the root cause, then turn the fix into a check so that class of failure cannot come back quietly.

Here is one chain end to end, anonymized. The contract: a paid action charges exactly once, whether the client retries, the network duplicates the request, or a background job replays it. The scenario list comes from the contract, not from the code: the same request sent twice; two requests racing; a failure after the charge but before delivery; a replay a day later. The seam in production is a request-scoped idempotency key that every money mutation must present. The gate asserts the observable outcome — at most one charge in the ledger per key — and fails the build if any code path can violate it. When the gate goes red, the merge stops, and nobody gets to argue that the retry probably won’t happen.

The audit side needs an ending too. When the mainline audit flags a commit that arrived outside the process, the response is defined in advance: the commit gets its review after the fact, the path it used is either closed or formalized, and the audit’s own invariants are updated. An alert nobody acts on is decoration.

What surprised me is how much this changes the way I work with the agent itself. When the gates are good, I can be generous upstream. I let the agent propose more, try more, refactor more, because I am not the last line of defense; the merge path is. The anxiety moves out of my head and into the CI configuration, where it can be reviewed, versioned, and improved.

One failure mode is worth naming: tests written by looking at the implementation. An agent is very good at producing assertions that agree with the code it just wrote, which is the same bug written twice and labeled as coverage. Tests only work as a gate when the expected values come from somewhere other than the code under test: the contract, the boundary conditions, the null cases, the abuse cases, the observable side effects. I write the scenario list before I look at the diff. An assertion that merely agrees with the implementation is the implementation, restated.

None of this makes machine-written code safe by default. It makes safety a property of the path the code has to travel, instead of a property of the person reading it. That distinction matters, because the path scales and attention doesn’t.

Get in touch

© 2026 Angelo Zhang