Insight

What the Spec Doesn't Decide, the Model Will

A vague spec was always a debt. With an agent implementing it, every unwritten line becomes a decision the model takes for you, confidently and on average.

Alaa Almallah 9 min read

A team adopts spec-driven development on a Monday. The spec for the new feature is three paragraphs of intent: what it should do, who it serves, and a line about handling failures gracefully. The agent builds for forty minutes. The demo passes. The pull request is two thousand lines and reads clean.

Three weeks later the seams show. The sync job retries three times against a dead endpoint, because nobody said what gracefully means. The empty state ships copy nobody approved. The migration runs before the safety check, because the spec mentioned the check second in a sentence where order did not feel load-bearing.

Every one of those behaviors looks deliberate. None of them was decided.

The team concludes the agent is not good enough yet. The agent was fine. The spec made decisions nobody noticed making.

The spec changed jobs

Spec-driven development is the practice of treating the specification as the primary work product and letting an AI coding agent generate the implementation from it. The 2025 tooling wave, Amazon's Kiro and GitHub's Spec Kit, packaged the practice into named stages: constitution, spec, plan, tasks. The packaging is new. The inversion underneath it is newer than most teams have internalized.

For most of software history, the spec was a lossy compression of intent. Somebody compressed, and a careful engineer decompressed. That engineer sat between the document and the code, noticed the gaps, and filled them with judgment. Sometimes by asking. More often silently, at the keyboard, close to the consequences.

Code generation inverts the direction. The code is now a lossy decompression of the spec, and the thing filling the gaps is not a careful engineer. It is a model completing the most probable implementation of an underdetermined description.

That is the mechanism, stated plainly. Every gap in the spec is filled. The average implementation is fluent, typed, and internally coherent. The fluency is the problem. A vague spec used to arrive in review as a question. Now it arrives in the codebase as a decision that looks deliberate.

The delegated decision

A delegated decision is any point where two competent implementations would both satisfy the spec and behave differently where it matters.

Retry counts. Error ownership. Ordering. Idempotency. What the user sees when a list is empty. Which permission denies by default. What happens when half a job succeeds. None of these are exotic. They are the sentences that read fine at eleven at night and admit three readings each in production.

This is Every Edge Case Is a Decision the System Never Owned with a new second act. The edge case was always an unowned decision. With an agent in the loop, it gets owned anyway, silently, by whatever the average of every repository the model has ever read suggests. The decision is not skipped. It is taken without you.

Why does a vague spec cost more with an agent than without one?

Without the agent, vagueness hit a human. The human was a friction layer. They noticed the ambiguity, asked the question, left the TODO, shouted across the room. Slow, but the ambiguity stayed visible until someone resolved it.

The agent is a friction remover. It converts the same ambiguity into an average, silently, at a volume no human matches. When a person guesses your intent, you get one file you can argue with. When the agent does, you get twenty files, consistent, typed, passing lint, coherent around a decision you never made. Disagreeing now means excavating generated code for decisions that would have cost one sentence in the spec.

The review bottleneck moves with it. Teams know how to review code, roughly. Almost nobody has a practice for reviewing specs, because for twenty years the spec was a suggestion and the code was the law. This is Automation Does Not Remove Judgment. It Reassigns It at the moment of writing: judgment has not left the system, it has moved to the spec, earlier in the week, with less information and nobody watching.

It is also a control question. Every Useful AI Workflow Is a Negotiation Between Probability and Control, and the spec is your side of the negotiation. An underspecified region of the spec is the part of the system where you accepted maximum probability and called it a deadline.

Spec theater

The failure mode has a shape. The team adopts the form, the stages, the templates. The decisions do not come. The spec is a longer prompt with a cover page, and adjectives do the work decisions should do: robust, graceful, clean, intuitive, secure by default. The agent grants the wish.

The output reads done because it is fluent and complete, which is exactly the trap in Confident Wrong Output Marked Done Is the Agentic Failure Mode. The demo passes for the same reason the seams appear late. Fluency reviews well. Reviewing is not reading.

What this is not

Not waterfall returning. Waterfall tried to decide everything before writing anything. The move here is narrower: decide what is cheap to decide now, mark the rest open, and let generation work inside the decided region. The spec is a decision record with a border, not a requirements cathedral.

Not a call for complete specs. Completeness is a mirage, and chasing it produces documents nobody rereads. The goal is not more words. The goal is more decisions per word. A one-page spec where every sentence admits exactly one implementation that matters beats a ten-page spec held together by gracefully.

And not a case against agents. The agent is doing precisely what it was asked to do. That is the uncomfortable part.

The two-implementation test

The Monday-size move is a reading discipline, not a document standard:

  1. Read the spec sentence by sentence. Requirements only; skip the prose that sets context.
  2. For each sentence, ask: could two competent implementations both satisfy this sentence and behave differently where it matters?
  3. Where the answer is yes, you have found a delegated decision. Decide it in one sentence, or mark it OPEN with a default and an owner.
  4. After generation, review against that list. The question stops being "is this code good" and becomes "which of my open decisions did it take?"

The common hiding places are predictable enough to check by name:

The sentenceThe decision it delegatesWhere it surfaces
Handle failures gracefullyretry count, backoff, when to stopa dead endpoint, three weeks in
Keep the two systems in syncordering, conflict winner, partial failureduplicate rows at the month-end close
Clean, intuitive UIwhat the empty state says and doessupport tickets with screenshots
Secure by defaultwhich permission denies when unspecifieda locked-out admin on a Friday

This is the same discipline as the five-line handoff in Agent Conversations Without Contracts Are Faster Confusion, one level up. There, every hop between agents needed ready, done, authority, failure, and evidence. Here the hop is between you and the agent, and the spec is the contract. If the contract does not say, the counterparty decides.

Take-home

  • Run the two-implementation test on the last spec you handed an agent. The count of delegated decisions is usually the explanation for the review you just suffered.
  • Adopt an OPEN convention: one line per open decision, a default, an owner. More than ten OPENs in a short spec means it is still a wish list.
  • In the next generated pull request, review for decisions before style. List what the code decided that the spec never said, and take that list to the author of the spec, who is probably you.

Code generation does not remove the decisions from your week. It removes the moment where you used to notice them. The spec is now the only artifact where judgment lives, and the code is downstream of it. So, mostly, is the team.

If your team's generated code keeps passing review and failing in production, the place to look is not the model. It is the spec, and the decisions it never made. If you want help turning wishful specs into decision records before more code builds on them, book a discovery call.

FAQ

What is spec-driven development?

Spec-driven development is the practice of treating the specification as the primary work product and letting an AI coding agent generate the implementation from it. Tools like Amazon's Kiro and GitHub's Spec Kit package it into named stages: constitution, spec, plan, tasks.

What is a delegated decision?

A delegated decision is any point where two competent implementations would both satisfy the spec and behave differently where it matters. Retry counts, error ownership, ordering, idempotency, empty states, and permission defaults are the usual carriers. The gap does not skip the decision. The model takes it, silently, as the most probable average.

Why do vague specs cost more with AI coding agents than without them?

Without an agent, ambiguity hits a human who asks a question or leaves a TODO, so it stays visible. An agent converts the same ambiguity into a fluent, internally coherent implementation that reviews well. The cost moves from a one-sentence decision at spec time to an excavation of generated code at review time.

Does spec-driven development mean writing longer specs?

No. Length is the wrong axis. The goal is more decisions per word: a one-page spec where every requirement sentence admits only one implementation that matters outperforms a ten-page spec held together by adjectives. Mark whatever you are not deciding yet as OPEN, with a default and an owner.

How do you find spec gaps before the agent builds?

Run the two-implementation test. Read each requirement sentence and ask whether two competent implementations could both satisfy it and behave differently where it matters. Where the answer is yes, decide it in one sentence or mark it open. After generation, diff the behavior against that list instead of reviewing style.

Related