Agentic Strategies

Definition of Done: Why a Checklist Decides When AI-Assisted Work Is Finished

A fixed set of gates instead of an agent's own judgment, the operating model behind it, codebase habits that help or hurt, and what's actually worth measuring.

Published September 2026

Why this exists

A companion to Implementer, Reviewer, Tester — that piece is the story of one feature. This one is everything underneath that story: the operating model, why a fixed checklist beats trusting an agent's own sense of "done," the codebase habits that make agent work easier or harder, and what's actually worth measuring.

Human scoping · decisions · wrong assumptions not replaced Claim Check Evidence Next step the bottleneck is how fast a claim can be checked fed by: permanent tests + a second reviewer, no shared context

A closed loop, not a straight line. Only scoping, decisions, and catching wrong assumptions stay human — that part was never replaced.

1. The agent doesn't decide when it's done — a fixed list of gates does

An agent reports success the moment it stops working. That's not the same claim as finished. So "finished" gets written down, in full, before the work starts — and it doesn't change while the work is happening. Each gate can fail. On failure, the work goes back a step; it doesn't continue past it. And the gates stay deliberately boring, on purpose: boring means a person can check one without having to read the code behind it.

The list I actually use runs to dozens of checks across the five phases below. Two rules sit underneath all of them and never bend: never push unless the full suite is green, and never hand a change to a person while it's carrying commits no CI run has ever seen.

Before code Development Local verification Publish Review hand-off a gate fails → go back a step, don't continue never push unless the full suite is green · never hand off commits no CI run has seen

Five phases, a fixed checklist inside each one. A failed gate sends the work back a step — it doesn't get to carry on.

2. Four roles, and why the reviewer must not share context

Four roles, not one blurred one. Each sees only what it needs, and findings get reported with evidence attached, not just a conclusion.

Implementer writes the change + its own tests no shared context Reviewer requirement, standards, correctness Tester runs the suite, checks the counts Human opens the real screen, looks findings go back — reviewer doesn't fix

The divider is the point: a reviewer who shares context with the implementer only confirms their own assumptions.

RoleDoesDoes not
ImplementerWrites the change and its tests, one small step at a time.Does not review its own work.
ReviewerChecks the requirement, the standards, and correctness — with the strongest model available.Does not re-run the tests.
TesterRuns the suite. Checks that test and assertion counts actually moved, not just the pass/fail line.Does not write the change.
HumanOpens the real screen and looks at it.Does not skip this step.

The reviewer must never share context with the implementer. A reviewer who wrote the code, or watched it get written, only confirms their own assumptions back to themselves. A reviewer with zero stake in the implementation, told specifically what to check, finds a different class of bug than the author ever will in their own code — and when it finds something, that finding goes back to the implementer to fix. The reviewer's job stops at finding it.

3. What a green suite can't see

A green suite is not a review. It only proves the tests you wrote agree with the code you wrote — it says nothing about the tests you never thought to write. Every row below got through a fully green suite. None of these are hypothetical — each is a real class of defect the suite itself was structurally unable to catch, which is the actual reason a separate gate exists for it.

Full suite green everything green can't see Static analysis gap Plausible fabrication Invented justification Uncovered guard a syntax check confirms the file parses, not that a method exists a name, requirement, or ticket can be invented with the same confidence as real code can be right while its stated reason is invented a guard isn't covered until you've watched it fail

Four classes of defect a fully green suite let through — each is the reason a separate, specific gate exists.

GateWhat it catches
Static analysis, not just a syntax checkA syntax checker confirms the file parses. It has no idea whether a method actually exists — an invented method name only fails once its exact line runs, and in an error branch that can be never.
A confidence check on names and identifiersAn agent writes a plausible method name, a plausible requirement, and a plausible ticket number with exactly the same confidence it writes correct ones. Only the first of those three can ever fail a test on its own.
Trace every change back to an actual requirementA design choice the agent made on its own, written up as something the ticket demanded, sails through every test — the code is right, the justification is invented, and the build stays green. Only tracing the change back to a real line in the requirement finds it.
Break the guard on purposeA guard isn't covered until you've actually watched its test fail. Delete the guard and re-run; if the test still passes, it was never testing the guard in the first place.

4. Codebase habits that make agent work harder

None of these are bugs. Every example passed review and CI. An agent doesn't skim — it reads every comment as if it were true, and it copies the style of whatever code sits around it. A habit a human reader would just shrug off becomes something an agent actively repeats.

One fact written in four places Copies all four — three go stale "Why we chose this" in a docblock Reads it as current, settled truth Two styles in one commit Copies whichever it read last A check bypassed instead of fixed Treats the bypass as convention the cost isn't paid by the author — it's paid by the next person, and every agent that reads the file afterward

Four of the five habits below, as a shape: a human habit on the left, what an agent does with it on the right.

HabitWhat the agent does with it
One fact written in four places — a commit message plus three docblocksCopies all four. The next time the fact changes, three of the four quietly go stale.
"Why we chose this" explained in a docblock instead of the ticket or an ADRReads it as current, settled truth. Inline narrative can't be reviewed, can't be tested, and nobody ever goes back to update it.
Two styles in one commit — typed on one method, not the nextCan't tell which one is the actual convention, so it copies whichever one it happened to read most recently.
A check bypassed instead of fixedTreats the bypass as the local convention. The real defect goes untracked, and one bypass quietly becomes the pattern.
Writing against an old convention while a migration sits mid-reviewThe conversion cost stays invisible to whoever wrote it, and grows a little with every file added on the old pattern in the meantime.

One more rule, separate from the table above: no AI attribution anywhere, in a commit, a PR, or a comment. That one isn't about agent behavior — it's about who a commit history is allowed to credit.

5. Tests that actually find bugs

The problem is rarely too few tests — agents write plenty. The problem is tests that keep passing while the code underneath them is broken. One question filters out most of the weak ones: what can actually break in this change?

Weak testStrong test
Store a value, reload it, confirm it's the same.Send 250 and 251 characters at a length limit.
Tests the ORM, which every field already shares.Confirms the value is rejected before any database write happens, with the right error key.
Survives almost any bug in the feature.Fails the moment the validation actually breaks.
A trap worth naming: stashing a fix, watching the test fail, restoring the fix, watching it pass again proves the test's result changed. It does not prove the test exercises the fixed code. In one real case the test flipped for a reason that had nothing to do with the actual fix. Confirm why it flips — not only that it flips.

None of this calls for more tests. It calls for one habit before writing any test: name, specifically, what would have to be true for it to fail. If the honest answer is "nothing short of a full outage," it isn't testing the thing that actually matters.

6. Confidence and claims

An agent writes an unproven theory in exactly the same confident style it writes a proven fact. From the prose alone, a reader can't tell them apart.

This isn't about doubting everything an agent says. It's one habit: separate "I checked this" from "this is consistent with what I'd expect" before either gets written down as fact. The two look identical in finished prose and are not remotely the same claim.

7. Tooling: engineering gaps vs. decision gaps

Not every gap here is a process problem. Some of it is tooling — and it's worth being specific about which is which, because an engineering gap and a decision sitting above engineering need completely different kinds of pressure to move.

8. Adoption plan

A real onboarding attempt happened exactly once, and nobody currently owns repeating it. That's a real gap, not a detail to gloss over — so here's the actual plan, not just the admission.

9. Measurement

What to measure, and specifically what not to. Coverage gets reported on every single run already — close to nobody, including me on plenty of weeks, actually reads it, which is as much an argument for keeping the measured thing simple and specific as any argument for adding more metrics.