Definition of done when an agent wrote the code
Stefan-Iulian Tesoi · · 7 min read

Done means a person has compared the returned work against criteria written before it started, and the repository supports the claim. A commit message is a claim; the diff, the commands that ran, and the files that changed are the evidence.
That distinction did no work for twenty years, because the person making the claim and the person who would be embarrassed by it being wrong were the same person. They are not any more.
What does done mean when the author is an agent?
Every definition of done is a list of conditions plus an unstated assumption: that whoever ticks the box has read the thing. The list survives the arrival of coding agents. The assumption does not.
An agent will tell you it finished. It is not lying — it has satisfied its own reading of the item, and its own reading is the only one it has. Where that reading is wrong, the report is confident and the work is wrong in the same breath, which is a failure mode almost nothing in a normal process is shaped to catch.
So a definition of done for AI agents has to name the evidence rather than the feeling. Not "the work is complete" but "these commands were run and these were their exit codes".
Why is a commit message not evidence?
Because it is written by the same process that did the work, at the same time, with no independent observation in between.
We have watched a story marked complete sit on top of a diff that did not implement it. Nothing about that was malicious or even careless: the item asked for two things, the agent built one, the summary described the one it built, and everyone reading the summary agreed it sounded finished. The claim and the code diverged and nothing in the chain compared them.
A commit message says what someone intended. The diff says what happened. Reviewing the first and calling it verification is the whole problem in one habit.
This is the same shape as the status-versus-code failure in a backlog an agent can actually read, arriving from the other end. There, the item claimed more than the code delivered. Here, the report does.
What evidence should an agent hand back?
Four things, and the fourth is the one teams forget:
- The commands it ran, with exit codes. Not "tests pass" — the invocation and the number.
pnpm run ciexiting 0 is evidence; "CI is green" is a claim about evidence. - The files it changed. A list, because the list is what a reviewer scans before deciding how carefully to read.
- Which acceptance criterion each change satisfies. The mapping is where specification defects surface: a change that satisfies no criterion, or a criterion satisfied by no change, is visible in seconds.
- What it could not verify. Explicitly, as a list. Everything a machine cannot check has to be named, or it silently becomes nobody's job.
That fourth item is what makes evidence-based done work in practice. An agent that reports only its successes hands you a green wall and no idea where the gaps are. An agent that says "I could not check the email actually arrives; somebody should send one" has told you precisely where to spend your two minutes.
| What arrives | What it proves |
|---|---|
| "Implemented and tested" | Nothing checkable |
"Added 4 tests, pnpm test exit 0" | The suite ran and passed |
"Criterion 3 satisfied by src/lib/export.ts:40" | The change maps to what was asked |
| "Criterion 4 not verified — needs a real send" | Where a person is still required |
Why does the last step stay human?
Because a system that writes the acceptance criteria and also rules on whether they were met contains no independent check at any point. That is a structural property, not a maturity problem, and it does not improve as the models improve.
There is also a practical half. Roughly half the work we send back turns out to be a specification defect rather than an implementation one — the code did what the criterion said and the criterion was wrong. Telling those two apart requires knowing what was actually wanted, which is exactly the knowledge that never made it into the item. Only the person who had the original conversation can adjudicate it.
So code review changes shape rather than disappearing: verifying agent work is two-sided, asking both whether the diff satisfies the criteria and whether the criteria were right. Rejections get labelled as one or the other, because sending a specification defect back unchanged produces a second failure for the same reason, and the second failure gets blamed on the builder.
How do you catch a status that disagrees with the repository?
Compare three lists, monthly, and look at what appears in only one:
- Items marked done.
- Commits merged.
- Behaviour a user can now observe.
Work in the first list but not the second is the dangerous case — a claim with nothing behind it. Work in the second but not the first is more common than anyone expects and less harmful: shipped work with no item, invisible to every progress report but at least real.
The audit takes an hour and is worth repeating precisely because it is boring. Nothing else in a normal process ever asks whether the board and the repository agree, which is why they drift for months without anyone noticing.
Writing a definition of done your team will actually apply
The failure mode of a good definition of done is length. A fourteen-point list gets agreed in a workshop, printed on a wall, and consulted never, because nobody can hold it while reviewing a diff at five o'clock.
Ours is four lines, and each one is a thing a reviewer can check rather than a thing they can intend:
- Every acceptance criterion has evidence attached: a command and its result, or a named observation.
- The diff has been read, not the summary.
- Anything the agent could not verify is listed, and each entry has been either checked or explicitly accepted.
- A person moved it to done. Never the author.
That last line is the one with teeth. In Laimonade, finished work moves to review carrying its evidence and stops there; a person closes it. It is the cheapest structural guarantee available, and it is the one that makes the other three worth writing down.
How Laimonade works covers where the evidence is recorded, and the sprint workflow covers when the review happens in a week. For the wider argument that delivery metrics measure movement rather than correctness, DORA's four keys are the reference — they tell you how fast work moves once it exists, and say nothing about whether it did what was asked.
Frequently asked questions
Can an agent ever close its own story?
Not in a system worth trusting. An agent closing its own story removes the only independent step in the chain, and what it removes is precisely the check that catches confident wrong work. The cost is small — a person reading a diff against criteria they already have takes a couple of minutes — and the thing it buys is the ability to believe the board.
What counts as sufficient test evidence?
An invocation and an outcome, for every criterion that has a test surface. pnpm run ci with exit code 0 is sufficient for the criteria that suite covers; a screenshot is sufficient for a visual criterion. What is never sufficient is a summary sentence, because a summary is the agent's report of the evidence rather than the evidence itself.
How do you handle work with no automated tests?
Name the observation instead of the test. "The pricing page's second heading reads X" is checkable in five seconds by a person and needs no suite. The honest failure case is work where you cannot state any observation at all, and that is a signal the item was never specified rather than a gap in tooling.
Does this slow delivery down?
It moves the cost earlier and shrinks it. Reading a diff against criteria you already wrote is fast; discovering the same defect a fortnight later, after something was built on top of it, is not. The thing that genuinely slows a team down is not trusting "done" — because then every piece of work gets re-verified informally by whoever touches it next.
What about work an agent says is blocked?
Blocked is a legitimate outcome and should be reported as evidence too: what it tried, what it found missing, and which item would unblock it. The common case is a circular dependency where two individually sensible items each need the other's output. That is a sequencing error for a person to resolve, and nobody should be rewriting code over it.