Building a Review Protocol for Code You Didn't Write Line by Line
A concrete, practical review workflow for AI-generated code at a small team — scoped by risk tier, not by pretending every line deserves equal scrutiny.
Most small teams handle AI-generated code review one of two ways, and both are failure modes. The first is reviewing everything with the same intensity as before, which quietly becomes reviewing nothing thoroughly, because the volume has grown past what the old process can sustain and something has to give — usually depth, silently, without anyone deciding that on purpose. The second is reviewing nothing meaningfully, on the theory that the code mostly works and deadlines don't wait, which is precisely the path that leads to the 65% of production apps with security issues that opened this series.
Neither is a protocol. A protocol is a deliberate, repeatable set of rules for how much scrutiny a given piece of code gets, decided in advance, not improvised under deadline pressure when it's easiest to skip. Here's one that works for small teams without a dedicated security function — built around a single organizing idea: not all code deserves the same review, but every piece of code should get a review level someone consciously chose, rather than one nobody decided at all.
Step one: tier the code before you generate it, not after
The single highest-leverage decision in this whole protocol happens before a single line is written: deciding what tier this piece of code belongs to. Three tiers cover almost everything a small team builds:
Tier 1 — Throwaway and exploratory. Prototypes, internal scripts, anything with a natural expiration date, code that will never touch a real user or real data. This is exactly the domain vibe coding was built for, as the first piece in this series argued — full-speed generation, minimal review, accept and move on.
Tier 2 — Internal-facing production code. Admin tools, internal dashboards, anything that runs in production but isn't exposed to customers or handling sensitive data directly. Gets a real review pass, but a fast one — a single reviewer, checked against the pattern list from the vulnerability-patterns piece, no deep architecture debate required.
Tier 3 — Customer-facing or data-handling code. Anything touching authentication, payments, user data, or public-facing input. This is where the review protocol below applies in full, no shortcuts, regardless of how confident the generated code looks or how much deadline pressure exists.
The tier gets decided at the moment the task is assigned, not after the code exists — because deciding after the fact is exactly when "this looks fine, let's just ship it" pressure creeps in and erodes the tier that should have applied.
Step two: the Tier 3 checklist
For code that touches the parts of the system that actually matter, run through a fixed, short checklist before approving — the same one every time, so it becomes habit rather than a fresh judgment call under pressure:
- Does any user-controlled input reach an output context — HTML, logs, SQL, shell, file paths — without going through an escaping or parameterization step? This single question catches the majority of what the XSS and log injection piece documented.
- Are there any credentials, tokens, or keys anywhere in this diff that aren't referenced through an environment variable or secrets manager? A grep for common key patterns before human eyes even get involved catches most of the leak-rate problem automatically.
- Does this code check not just that the requester is authenticated, but that they're authorized for this specific resource? The authentication-versus-authorization gap is easy to miss on a fast read and expensive when missed.
- Are the defaults here the restrictive option or the permissive one? CORS, file upload limits, rate limiting — check that the generated code chose "secure by default," not "works easily in a demo."
- Does this duplicate logic that already exists elsewhere in the codebase? Not a security question, but the debt question from earlier in this series — catching duplication here is dramatically cheaper than untangling it eighteen months later.
Five questions, answerable in minutes by someone who's internalized the pattern list, not a multi-hour architecture review. The goal isn't exhaustiveness — it's catching the specific, well-documented, high-frequency failure classes that the research in this series shows repeat constantly.
Step three: assign review, don't hope for it
On a small team, the most common reason a review protocol fails isn't that nobody knows the checklist — it's that nobody's clearly responsible for running it, so it quietly doesn't happen on the day everyone's busy. Two structural fixes handle this without adding process overhead:
- Bake the checklist into the pull request template itself, as checkboxes the author has to interact with before requesting review, and the reviewer has to interact with before approving. This doesn't guarantee thoughtful application, but it guarantees the questions get asked out loud rather than silently skipped.
- Rotate a "Tier 3 reviewer" role weekly even on a two- or three-person team, so there's always a named person whose job that week includes taking Tier 3 code seriously, rather than diffusing the responsibility across everyone and therefore effectively no one.
Step four: let automation carry what it's good at
Not everything on the checklist needs a human doing the checking. Secret-scanning, as covered earlier in this series, should run automatically pre-commit — question 2 above shouldn't depend on a human remembering to grep for key patterns. Static analysis tools can flag unescaped template interpolation and missing parameterization automatically, taking a real bite out of question 1 before a reviewer even opens the diff. The human review budget, which is always the scarcest resource on a small team, should go toward the judgment calls automation can't make — authorization logic, whether a default is actually appropriate for this specific use case, whether duplication is real or coincidental.
A review protocol that assumes a human will catch everything is a protocol that will fail exactly when the team is busiest — which is precisely when the highest-risk code tends to get written. Automate what's mechanical, and spend the scarce human attention on what actually requires judgment.
Why this is different from "just review more carefully"
The instinct after reading about the 65%, the 3.2%, the 86-and-88% failure rates is to resolve to be more careful. That resolution doesn't survive contact with a real deadline, because "be more careful" isn't a process — it's a hope. A tiered protocol with a fixed checklist, assigned ownership, and automation carrying the mechanical checks survives deadline pressure precisely because it doesn't depend on anyone's discipline in the moment. It depends on a system that was designed, once, when there was time to think clearly about what actually needs catching.
That's the real difference between a team that ends up in the failure statistics this series has covered and a team that doesn't. Not more talent. Not more caution as a personality trait. A protocol that runs the same way whether it's a calm Tuesday or the night before a launch.
Part of the "From Vibe Coding to Production" series on aiskill.market.