A1.01 · The two failure modes · dive 1
Vibe coding
Vibe coding is generation with no specification and no acceptance test — the diff is kept because it runs. It fails in exactly one way: nothing ever said what done meant, so nothing can confirm the code is right.
This is the first of the two failure modes, and the cheaper one to fall into. A prompt produces a diff; the diff compiles; the diff is committed. Four forces turn that habit into a system that drifts: the figure beside this traces how ambiguity compounds, and a meter below measures how much of a diff goes unread.
Ambiguity compounds · rungs with no acceptance
The term, defined
Vibe coding is generation without a specification and without an acceptance test: a request is sent to a Claude agent, a diff comes back, and the diff is kept because it compiles and appears to run, not because it was shown to be right. The decision to keep it rests on a vibe — the code looks plausible, the page loads, the test that was never written did not fail — rather than on a written definition of what the change was supposed to do.
The distinction is precise, and it is the whole topic. Running code answers does this execute. A specification answers what is this supposed to do. An acceptance test answers does it do that. Vibe coding has the first and skips the other two. The code that results is not necessarily wrong — it is unaccountable: there is no artifact against which anyone, human or agent, could say whether it is correct.
An agent makes the habit cheaper, not safer. The Pragmatic Programmer calls the underlying mistake programming by coincidence — relying on code that happens to work, without knowing why. A fast implementer that produces large diffs on request widens the gap between what runs and what was understood, because the volume grows faster than the reading does.
- runs
- The code compiles and executes without an error in the path that was tried. Says nothing about correctness.
- specified
- A written statement of the behaviour the change must produce. Absent in vibe coding.
- accepted
- A check — a test, a story, a sign-off — that confirms the specified behaviour holds. Absent in vibe coding.
Why it fails — four forces
Vibe coding does not fail because agents write bad code. It fails because four forces act on any stream of unspecified, unaccepted diffs. Each is independent; each compounds the others.
1 · No definition of done
A change can be accepted only against a statement of what it should do. Vibe coding never writes that statement, so there is nothing to accept against. "It runs" is not acceptance — a function can run and return the wrong value, omit a case, or corrupt state on the path nobody tried. With no definition of done, done collapses into compiles, and the two are not the same claim.
2 · Unreviewable diffs
A human reviews a bounded number of lines in the time available. Past that bound, the rest of a diff is committed without being read — not from carelessness but from arithmetic: the diff is larger than the budget. An agent can emit hundreds of lines in one response, so the share actually reviewed shrinks toward zero as the diff grows. The meter below computes exactly this.
3 · Compounding entropy
Each new change builds on the unspecified work before it. Because no prior rung was pinned to a definition, every later rung inherits its ambiguity and adds more. Drift does not stay constant; it accelerates, because the surface that the next change must reason about is itself undefined. A small unaccountable base becomes a large unaccountable system one accepted diff at a time.
4 · Silent regressions
With no invariants and no tests, a break announces itself only when something downstream finally trips over it — often many changes later, far from the diff that caused it. There is no failing check at the moment of breakage, so the regression is invisible until it surfaces as a bug whose origin has been buried. The cost is paid later, with interest, and the trail back to the cause has gone cold.
Four forces, one root: a diff kept for running rather than for being right has no point at which anyone could have caught what was wrong.
The reviewability meter
The second force is the one that can be measured directly. Fix a review budget — the number of lines a person can read closely in the time a change is given. Here the budget is 50 lines. Now move the size of an agent-generated diff. The share that gets reviewed is min(100%, budget / size); the rest is accepted unseen.
Drag the slider. Past a small size, the reviewed share falls away and almost the entire diff is committed without a human reading it. The figure is not a metaphor — it is that fraction, computed.
Reviewability · budget 50 lines, fixed
The reviewed share is not a matter of effort — it is the budget divided by the size, and beyond a small diff it rounds to nothing.
Worked example: vibe-coding the store
The Portal — the learning platform this course builds end to end — begins with a store: the
component that holds entities and mints their branded identifiers, the ones that read like
USR0NbAb1xcFCy. A vibe-coded start asks for the whole thing at once.
$ # the prompt $ claude "build the store for the Portal" … # 420 lines across 6 files, all compiling, all green on a suite that does not exist
The diff runs. The page that exercises it loads, an identifier comes back, nothing throws. By the four forces it is already in trouble. No definition of done: no statement said what the store must guarantee — that an id is never reissued, that a lookup of a missing entity is distinguishable from a stored one, that two callers minting at the same instant get different ids. Unreviewable: at 420 lines and a 50-line budget, the meter above puts the reviewed share near twelve percent; the rest is accepted on faith. Nobody can state what the store does, only that it did not error on the path that was tried.
Then the next feature lands on top of it. A second component asks the store for an id and assumes it is unique; the store, never specified to guarantee uniqueness, happens to collide under concurrency. Nothing fails at the moment of the change — the suite that would have caught it was never written. The break surfaces later, in a different surface, as a duplicated record whose cause has gone cold. The store could not be signed off, so the feature built on it inherited a defect that no check could see. That is a silent regression riding on compounding entropy, both traceable to the missing definition of done.
The principle
Generation without acceptance is unaccountable. A change kept because it runs has no artifact that states what it should do, so no one can ever confirm it is right — correctness is asserted, never checked.
On the Portal
A store nobody can sign off, because nothing said what done was: 420 compiling lines, no stated guarantee on its ids, and a uniqueness break that surfaces only once a later feature trusts it.
The failure is not bad code from the agent; it is a kept diff with no contract behind it — generation the workflow can run but cannot accept.
Recap
Vibe coding keeps a diff for running, not for being right. Four forces make that fail: with no definition of done there is nothing to accept against; unreviewable diffs are committed mostly unseen once they pass a fixed review budget; compounding entropy accelerates drift as each unspecified rung builds on the last; and silent regressions stay invisible until far downstream because no invariant or test marks the break. The reviewability meter shows the second force exactly: past a small size, almost all of an unspecified diff is accepted without being read.
The opposite failure is over-planning — a single enormous specification written before any code, which is its own way of never shipping a proven increment. That is the next dive, A1.01.2 · Big-bang specs. The resolution of both — the thin, provable slice — is A1.01.3 · Thin slices.
References
Primary sources for this failure mode, and where it connects in the course.
Sources
- Hunt, A. & Thomas, D. — The Pragmatic Programmer — "Programming by Coincidence": relying on what happens to work rather than on what is understood.
- Beck, K. — Extreme Programming Explained — fast, concrete feedback over hope; a change is proven, not assumed.
- Anthropic — Building effective agents.
Related in this course
- A1.01.2 · Big-bang specs — the opposite, over-planning failure.
- A1.01.3 · Thin slices — the thin, provable slice that resolves both.
- A1.01 · The two failure modes — the module hub.
- A1 · Why an agile agent workflow — the chapter.