A thread on Hacker News caught my eye. It traced back to a single line the mathematician and developer Mark Dominus had posted on Mastodon: "I think a lot of people misunderstand the purpose of code review." I nodded along the moment I read it, and then found I couldn't explain why I agreed. So I read the original thread to the end.
Dominus's argument goes like this. A reviewer's job is neither to find bugs nor to certify that the code is bug-free. The real primary goal, he says, is to find code that will be hard to maintain. And that kind of code should be fixed while the original author still remembers it, meaning right now.
Why review falls apart when bug hunting becomes the goal
If you set bug-finding as the goal of review, you're asking the reviewer to prove something that can't be proven. "This PR has no bugs" isn't the kind of claim a single read confirms. If there's a way to confirm it, that's the job of tests or static analysis, not a human scanning a diff. What a person can actually catch is usually shallow, typo-level mistakes. Yet when review starts with "please check there are no bugs," the reviewer can never decide on their own when it's time to hit approve. They skim and approve, or they sink into perfectionism and the review drags on forever. Both endings are bad.
The alternative: did you understand it, or not?
The replacement standard Dominus offers is simple: see if you can understand it, and complain if you can't. The condition for hitting approve shifts away from fully understanding the whole change and toward pointing at the exact line you didn't understand. Two things are different about this definition. You now have a grip on when the review should end. And anyone can say "I don't get why this function is written this way" on the spot, while nobody can confidently stamp "this PR has no bugs."
Once you move the standard this way, the question the review asks changes too. In place of "does this work correctly right now" comes "will someone seeing this code for the first time six months from now have to wrestle with it." Under this redefinition the review comments change as well. Fewer comments say "I think there's a bug here," and more of them point at the line where understanding broke down, like "I don't get why this cache TTL suddenly dropped to three minutes," naming the variable and the line. Put the two frames side by side and the difference is sharper.
| Bug-hunting frame | Understandability frame | |
|---|---|---|
| Question the reviewer asks | Is there a bug in this code? | Do I understand why this code is written this way? |
| Stopping condition | None, since the claim can't be proven, so you keep scanning | Clear: approve if you understand it, send it back if you don't |
| Representative comment | "I think there's a bug here" | "I don't get why this cache TTL dropped to three minutes" |
| As the code grows | Review becomes a more and more hopeless task | The question stays the same |
The reason this redefinition didn't feel foreign is that I'd already been drifting in this direction while running reviews in practice. At a company I used to work at, we used a CODEOWNERS file, and in hindsight it was less a device for asking "who has to confirm this code is bug-free" than one that automatically routed "who understands this code and can own it." On a team I was on, work that took less than three days, like copy edits or UI tweaks, went through code review alone, with no formal spec document. (In Korea it's common to write a planning doc before even small changes get built, so skipping it for small work was itself a deliberate call.) What the reviewer actually checked in those cases was whether it was clear enough to get at a glance. Whether it had bugs came after. When you put up a review request, the first comment usually landed within half a day, and what the reviewer really wrestled with in that half day was why it was written that way. Whether the logic was correct came second. Typos and repeated mistakes got filtered out ahead of time by a pre-commit hook, so the review time a person spent was narrowed to just "do I understand why this is written this way," not the mechanical stuff. At the time I thought of it as habit and nothing more, but after reading Dominus I realized all of it had been pointing the same way. The comment that showed up most in those reviews was "I don't get why this part is needed," not "isn't this a bug."
I checked separately, later, that this practice wasn't some quirk of one team. A 2018 paper, "Modern Code Review: A Case Study at Google", analyzed logs, interviews, and surveys across 25,000 Google developers and 9 million reviews, and it names understandability and maintainability as the "most fundamental reason" review was introduced in the first place. Catching more defects was a side effect that followed. "Expectations regarding code review are not centered around problem solving. Finding defects is welcome but is not the only focus" is the sentence the paper nails down as Finding 1. Google's official code review guide reads the same way. It writes that "the primary purpose of code review is to make sure that the overall code health of the codebase is improving over time," and states that there is no such thing as perfect code, only better code, telling reviewers not to hold up approval in the name of perfection. Google also filters style checks and repeated mistakes with pre-commit hooks, and the review a human does is handled by someone certified with ownership and readability for that code. What my team rigged up with one CODEOWNERS file and a few pre-commit hooks, Google was running at a scale of 25,000 people, with formal badges for ownership and readability certification.
Not everyone agreed with this redefinition
The comment section on the original thread didn't flow into easy agreement. People who work in security, and people who care about test coverage, pushed back that bug hunting is a legitimate part of review too. Vulnerabilities like auth bypass or a missing permission check don't get caught by the feeling that something doesn't make sense. If anything, the more smoothly code reads, the harder its hidden security holes are to see. It's fair pushback. Dominus's redefinition is a default that works broadly across ordinary feature code. It doesn't fit every kind of code unconditionally. For high-risk areas like auth, payments, and permissions, the point is that you have to lay a bug-hunting checklist on top of understandability, not that you should throw bug hunting out. Concretely: for permission-check unit tests, you take a test that only passed with an admin account token and add a case that calls the same admin API with a regular account token, to confirm that the path OWASP calls IDOR and BOLA, poking at someone else's object ID with my token, is actually blocked. For token expiry and reuse scenarios, you check whether a refresh token, once used, is immediately rejected when the same token requests again, meaning whether reuse detection and token rotation are in place. For SAST, a static-analysis tool like Semgrep or CodeQL wires SQL injection and XSS pattern rules into CI, and the checklist item is whether those results get attached automatically as reviewer comments. All three are things that "do I understand it" won't catch, and a test or a tool has to point them out separately. Understandable code and safe code are different axes, and in high-risk areas you have to review both.
AI-written code has no original author to ask
Dominus's timing principle, fix the problem code while the original author still remembers it, stands on an assumption from an era when people wrote most of the code. The assumption that if you ask the author, an answer comes back. But now that agents write a large share of the code, that assumption is the first thing to wobble. Ask Claude Code or Codex "why did you write it this way" and you do get a plausible answer back. It's just that the answer is reasoned up again in that moment, invented, and not something recalled about why this library was chosen back then, or why this exception was caught only here. By the time the PR goes up, the author's memory is already gone. The review starts with no one to ask.
So the understandability standard gets much heavier for AI-written code than for human-written code. With human code, if you couldn't understand it, the last resort was to grab the author and press them. AI-written code has no last resort. If the reviewer, looking only at the code, never manages to understand it, that code stays in the codebase with no one having understood it. Define review as bug hunting and this state passes review clean, because even a bug-hunting eye finds nothing wrong in the surface behavior. Only defining review as understandability lets you catch, at the review stage, the state where the code works correctly now but no one knows why.
This is the same gap I pointed at in an earlier piece. Giving AI write access to files, and trusting an AI's judgment without verifying it, were different problems. Same here. AI already has permission to put up a PR. Hand the job of judging whether that code is understandable to the AI too, and the permission passes fine while the judgment comes in with no one having verified it.
What holds a review up
As long as you treat review as bug hunting, review gets more hopeless the more the code grows. All that piles up is the demand to find more of what can't all be found. Move the standard to understandability and the question stays the same no matter how much the code grows. Understand it, pass it; don't, send it back. Whether a person or an agent wrote it doesn't matter. The reason Dominus's line keeps turning over in my head is that it confirmed, late, that what holds up the act of review was really understanding more than verification.


Top comments (0)