Verification, not vibes

How to tell when a coding agent has actually finished

Every harness that runs a coding agent eventually has to answer one question: is this task done? The three signals you reach for first all fail, in ways that are quiet enough to cost you an afternoon.

Disclosure: I build Ordewell, and this page is how it answers that question. The method is not a product feature though. It is a convention you can put in any harness in an afternoon, and the pitfalls below will bite you in any language, so they are worth reading even if you never run my tool.

The three obvious signals, and why they fail

1. The terminal went quiet. An interactive agent TUI does not close when the work is finished. It stays open, waiting for you to say something else. Silence means the model stopped printing, which is also what it does while it thinks, waits on a tool, or gives up.

2. The process exited cleanly. Exit code 0 means the program ended without an error. An agent running out of context, hitting a stop condition, or deciding the task was already satisfied exits 0 too. The exit code tells you the process finished, not the work.

3. The agent said it was done. This is the one that hurts, because it is confident. Models announce success over a build that does not compile, in a tidy paragraph, with a summary of changes that were only partly made. When a coordinator agent supervises worker agents, a version of this scales up: a model reading a model's report and ruling on it.

The fix is to stop asking for an opinion and start asking for a report. The agent is given a tool for saying it is done, and the harness accepts that call only from the attempt it started. Report present means pass. Report missing means fail, loudly, even when the session exited cleanly.

A report, not a paragraph

Every agent Ordewell runs is connected to a small tool server that ships with Ordewell. The task prompt ends with one instruction: when the work is finished, call task_complete with status done and a summary of what you did. If you can't finish, call it with blocked or failed and say why. The call also takes the handoff the next tasks will read: numbered findings with their evidence, artifacts, a commit message for a change task, and an optional long report stored with the attempt.

Three details make that call trustworthy:

The same server carries checkpoint, which pauses a task and asks you to approve or reject before it goes further. That turns "review the diff at the end" into "decide at the risky step".

What we tried first

Earlier versions of Ordewell did this with a printed marker: a unique token per task that the agent was asked to print on its last line, and that Ordewell watched for in the terminal output. It worked, and it taught us why it shouldn't be the answer.

A terminal is a rendering protocol, not a document. Colour codes, box drawing borders and soft wrapping split a token across writes, and full screen TUIs repaint a spinner in the middle of it. We ended up flattening the stream and replaying cursor moves to reconstruct the screen, just to read one line. The token also had to be kept out of the prompt itself, and out of anything handed to the next task, or the wrong task could pass on someone else's evidence.

A tool call has none of those problems. It arrives as structured data, from a known attempt, with a status and a reason attached. As of 0.8 it is the only thing that completes a task, and printed markers are no longer read at all.

When the report never comes

The goal is to make that state unmistakable. The session ended, maybe the model even claimed the work in its last message, and no report arrived. That is a failed verification, with the exit code kept beside it as separate evidence. These are the messages the task card can carry:

verdict
Verified: the runner reported completion through task_complete. Task completed successfully.

Failed verification: the runner exited cleanly but never called task_complete.

Note what the exit code does not do: it never overturns the report. A clean exit without a report is still a failure, and a blocked or failed report ends the task with the reason the agent gave.

Honest limits

If you want it already wired

Ordewell attaches the tool server, binds each attempt, runs one real coding agent session per task, and settles each one on its report. That is the whole loop:

bash
ordewell plan --goal "Add rate limiting to the public API"
ordewell run

The planner reads your repo without changing it, so planning needs no API key: a coding agent you already pay for can be the planner. Install with npm install -g ordewell, or read the docs first. The source for everything on this page is in the repo.