What replaces code review when an agent writes the code
On Giant Context an agent writes most of the code and no second engineer reads it before it ships. That arrangement has one consequence, and it decides more of this platform's architecture than any other single fact. There is no moment where a person reads a diff and asks why this is here.
A standard that depends on someone noticing does not survive that. Correctness has to be mechanical or it is not enforced at all.
There are three ways to hold a standard in place and they are not equivalent.
Generated from the schema
One OpenAPI description of this platform's API generates the typed client the console calls, the SDK in TypeScript and Python, the tool surface an agent drives, the query cache keys, the form validation, the route tables, and a permission test per route per role. None of it is written by hand. A form cannot ask for a field the server does not accept, because the field list is compiled from the same declaration the server validates against. A route with no test beside it never gets registered, so an untested endpoint is not a warning, it is an endpoint that does not exist.
The property that matters is not consistency. It is that inconsistency has nowhere to occur. There is no version of the client that disagrees with the server, because there is no second place where the shape is written down.
That is the strongest tier, it costs a generation pipeline, and it only reaches what a specification can express.
Enforced by the linter
Plenty of standards are not expressible as a schema, so they are expressed as rules instead. These four are the custom rules currently running on this codebase.
| Rule | What it rejects |
|---|---|
| no-screaming-snake-case | An owned identifier in SCREAMING_SNAKE_CASE, including constants |
| no-iife | A function invoked at the point it is defined |
| no-and | A function whose name contains And, which is two functions |
| no-unknown-cast | A value cast through unknown to reach an unrelated type |
No linter ships any of them, because they are not general standards. They are this codebase's standards, and a rule is about thirty lines of JavaScript walking a syntax tree. The one that rejects double casts found hundreds of them on the day it was written, in code where nothing had ever objected. That cast is legal TypeScript, it raises no type error, and no rule anyone ships looks for it.
The backend is one language, so there is one syntax tree, one rule file, and one gate covering every package. When it was two languages it was two of everything, and a custom rule had to be written twice or it only half existed.
There is no ceiling on how many of these I write. Any standard I can state precisely is thirty lines and a config entry away from being enforced, so the gate gets tighter every time I notice something I would have had to say out loud.
Written in a document
In January, before there was a product, I committed a repository containing coding rules and no code. Six non-negotiables at the top of it, the first being no SCREAMING_SNAKE_CASE. I wrote at the time that rules like these self-reinforce, because AI tooling writes code by reading code, so a codebase that matches its own rules teaches them to whatever writes the next file.
That was true of structure and wrong about prohibitions. A file layout gets copied because copying is the only way to produce one. A prohibition is a single token of escape that reads as reasonable in isolation, and a model that has read a thousand compliant files and one deviant file will reproduce either.
Type checking and linting from the first commit
The correction is not that I should have watched the document more closely. It is that the document was never the right instrument, and the two that are should have been switched on before the first feature.
Strict type checking and strict linting, every rule at error, from the first commit. I did half. The typecheck gate was there from the beginning and it held, which is why the type errors in this codebase are rare and shallow. The lint gate existed the whole time and was pointed at almost nothing, and everything I later had to go and find had accumulated in the half I skipped.
A rule turned on at the first commit has nothing to report. The same rule turned on in month nine reports thousands.
What an agent proposes instead
Turning a rule on late gives an agent a task with two solutions. Fix thousands of violations, or record the current count in a file, allow it to fall and never rise, and let the build go green. Twice an agent working on this proposed the second one. Both times I happened to be watching, and both times I killed it.
The proposal was incompetent. It is also standard practice. Every major linter ships the mechanism, ESLint calls it --suppress-all, and on a team with code review it is defensible, because a reviewer sees the entry appear in that file and asks about it. Here nobody sees it appear. An agent optimising for a green gate takes the cheapest legal route every time, so a bypass left in the design is a bypass that gets used. There are no thresholds on this codebase. A rule is on and satisfied, or it was never a standard.
What it costs to do it afterwards
The rule banning the non-null ! operator reported zero violations, because every file carrying one also carried a comment telling the linter not to look. Burning that back to a real zero took several weeks.
Sorted by cause the whole backlog came to four decisions, and most of it was one pattern copied forward. The fix for the largest group was a thirty-line helper that should have existed in month one.
The lesson
Drift is what a codebase does between the day a standard is written down and the day something starts checking it. Generation removes the chance to write the mistake. A rule removes the chance to commit it.
The lesson, turn on every control you have on day one, at the strictest setting the codebase will pass. Strict type checking and strict linting cost an afternoon at the start and weeks of burn-down nine months in.
Hiring an early engineer, or building something like this
Remote, Pacific time, full-time or contract. Get in touch.