Skip to content
Skip to content
Essay10 min readCritique

Your Coding Agent Is Lying to You (It Just Doesn’t Know It)

“Looks complete” is not malicious. It is the most expensive kind of uncertainty: a polished conclusion attached to incomplete evidence.

“Done” is a claim

Make it earn proof

critique.sh

“Implemented and tested.” Four words have launched a thousand debugging sessions. Your coding agent is not lying in the human sense; it has no intention, embarrassment, or secret plan. But it can produce the same practical outcome as a lie: a clean, confident completion message that outruns what the available evidence actually proves.

Coding agents are unusually good at making a partial result sound resolved. They can summarize files changed, tests run, and a rationale for the implementation in the same prose that they use to answer a question. That fluency collapses a distinction we need to preserve: the agent observed some things, inferred others, and asserted a conclusion. A reader sees one confident paragraph and unconsciously treats all three as proof.

There is no single villainous failure mode. The agent may have misunderstood acceptance criteria. It may have tested the happy path but not the permission boundary. It may have added a regression test that encodes the same mistaken interpretation as the patch. A command may have succeeded against local mocks while the actual environment needs a missing setting. Or the agent may simply have stopped when the first green signal appeared because it had no explicit reason to keep looking.

Do not respond by banning agents from running their own tests. Self-checking is table stakes. A good agent should inspect its own diff, run targeted tests, typecheck, lint, and iterate until obvious failures are gone. The problem begins when we use that self-check as the sole basis for a completion decision. The author picked the scope, selected the evidence, and then graded it. The loop has no reason to notice what its own framing excluded.

You can see this in ordinary human work. A developer who has been staring at a bug all afternoon will often overlook the assumption that started the bug. A reviewer who arrives fresh asks a different question, not because they are wiser, but because they are not committed to the original path. Agent systems need the same advantage without pretending that a new model call is automatically omniscient.

A credible agent finish has four parts
  • Intent: the behavior the change claims to deliver, stated plainly enough to challenge.
  • Evidence: the commands, observations, and artifacts that support the result.
  • Boundary: what was not checked, could not be reproduced, or remains an assumption.
  • Next action: a clear outcome, or a small verified repair that returns to the agent owning the task.

This is the role Critique is built to play. Your normal coding agent implements and self-checks. At the candidate finish, it calls critique finish. Critique reconstructs the current working-tree change in disposable workspaces, tests the consequential claim it can establish, and returns a deterministic result with artifacts and limits. If it proves a defect, it can prepare a bounded repair and verify that repair in a fresh workspace before it is applied back to the caller’s tree.

Imagine an agent is asked to add invoice cancellation. It updates the UI, marks the local record as cancelled, adds a unit test for the new status, and reports that tests pass. The sentence is not false in every clause. The UI may be updated; the unit test may be green. But the task might also require cancelling the payment provider subscription, preventing a retry worker from resurrecting the invoice, and blocking a customer from viewing a supposedly cancelled bill. The bad outcome is not an agent that did nothing. It is an agent that did enough to sound finished.

The right finish pass does not respond with a generic review comment like “consider edge cases.” It starts from the intended behavior, traces the affected paths it can see, and tries to falsify the completion claim. If it cannot exercise the payment provider locally, that is a limit to report. If it can reproduce the retry-worker failure, the next useful output is the smallest repair and the verification that repair passed—not an essay asking a human to become the router for two agents.

A skeptical reader should ask what Critique is actually allowed to see. Full reproduce-repair-verify runs are local-first at launch because local development and test environments are often what make a behavioral test meaningful. Critique can hydrate local development or test environment files inside disposable workspaces when configured, while excluding those files from patches, proof artifacts, and cloud uploads. The local workspace goes away after the run. That is a more useful contract than pretending every repository can be faithfully verified from an anonymous remote clone.

There is a fair objection to all of this: why trust Critique’s report instead of the first agent’s? “Fresh context” is an architecture argument, not proof of better outcomes. The proof has to be empirical. The most credible metric is disagreement rate on pre-registered real tasks: of the tasks a harness alone declared done, how often did Critique identify a failure that a hidden test suite or reviewer checklist confirms? Break those rows out by harness rather than blending them, publish the task construction and failure definition, and keep the receipts for catches people can inspect.

That is a higher bar than a benchmark screenshot, and it should be. The product asks teams to route a moment of trust through a new piece of infrastructure. The right response is not louder confidence. It is evidence that the infrastructure catches the quiet failures its users already recognize: “the tests passed,” “the diff looked good,” and then production says otherwise.

Not every change needs a full completion pass. Formatting, copy edits, and clearly mechanical refactors should stay fast. Call Critique when a wrong completion claim would cost more than a short independent check: auth, payments, migrations, destructive operations, external APIs, incident fixes, cross-file behavior changes, and work that already took an agent more than one attempt. That is not paranoia. It is a proportionate response to a new kind of output: software that looks complete before anyone has established that it is.

Not intentionally. “Lying” is a headline metaphor for a useful operational problem: an agent’s completion message is self-report and can be more confident than the evidence it has gathered.
The agent may have run a narrow or self-validating test, misunderstood the requirements, missed an affected path, or worked in an environment that does not reproduce production behavior. A passing command proves only what that command actually covered.
The primary coding agent calls Critique and consumes its JSON response mid-session. The developer does not need to manage a second conversation or read a second dashboard before the original agent can continue.
Measure confirmed disagreement rate on difficult, pre-registered tasks: how often a task the original harness called done contained a failure the verifier caught before merge. Publish the methodology and examples, not just a headline number.

Make “done” a testable claim.

Keep your agent fast. Add an independent finish pass where a polished summary is not enough proof.

Meet the completion layer