07Resources · Guide

How we review AI-generated code before it ships.

The checklist our engineers run on every meaningful change. It exists because AI output fails differently from human output — and needs to be read differently.

Guide28 May 20263 min read
Pull request diff with reviewer comments on screen

01

Why it needs a different read.

Human mistakes usually look like mistakes. The code is messy where the author was unsure, the naming wobbles, and the reviewer's eye is drawn to the uncertainty.

Model output has no such tells. It is uniformly confident, stylistically consistent and correctly formatted whether or not it is right. A subtly wrong function looks exactly like a correct one, so reviewing by vibe fails completely — you have to check specific things deliberately.

02

Logic.

Read the change against the requirement, not against itself. The most common failure is code that does something reasonable which is not the thing that was asked for.

  • Does this implement the requirement, or a plausible neighbour of it?
  • Boundary conditions: empty, one, many, and the maximum you will realistically see
  • Error paths — what happens when the call it depends on fails?
  • Invented helpers or config that do not exist elsewhere in the codebase
  • Silent catch blocks that turn a failure into a success

03

Data.

This is where cheap mistakes become expensive ones, because the cost arrives as a migration months later.

  • Does the schema change match the domain, or just the current screen?
  • Nullability and defaults stated on purpose
  • Indexes for the queries actually introduced by this change
  • N+1 queries hidden inside a loop that reads perfectly well
  • Migrations that are reversible, and safe to run while the app is up

04

Access and authorisation.

Models are good at authentication, which is a solved and well-documented pattern, and much weaker at authorisation, which is specific to your domain and rarely written down anywhere it could have learned from.

  • Every new endpoint or query checks who is asking, not just that someone is
  • Object-level checks — can user A load user B's record by changing an identifier?
  • Tenancy boundaries enforced in the query, not filtered in the view
  • Nothing sensitive leaked into logs, error messages or serialised responses
  • Secrets from configuration, never inline, and never in a test fixture

05

Dependencies and tests.

Two smaller checks that catch a surprising amount. Any new package gets a look: does it exist, is it maintained, is it doing something a dozen lines of our own code would do, and is the licence acceptable.

For tests, the question is whether they could fail. Generated tests have a habit of asserting the implementation back at itself — mocked so thoroughly that they pass regardless of whether the feature works.

06

What we reject outright.

A change comes back rather than getting comments if it is too large to review properly, if the author cannot explain what it does without the tool open, or if it quietly restructures something unrelated along the way.

That last one matters most. A model asked for a small fix will sometimes tidy three other files as a courtesy, and that courtesy is how unreviewed changes enter a codebase attached to a legitimate one.

In short

If you take three things from this

  1. 01

    Model output is uniformly confident, so reviewing by feel does not work.

  2. 02

    Authorisation and data shape are where the expensive misses cluster.

  3. 03

    If the author cannot explain the diff unaided, it is not ready.

Next step

Want this bar on your project?

Every build and partner engagement we run includes engineer review of code, data and access paths.