- When generation is cheap and reliable, hand-written code stops being the primary asset. The durable artifact is the specification: requirements, interface contracts, acceptance criteria, and executable tests that an agent implements and a suite verifies.
- Tests are the executable form of the spec. A passing suite is the definition of done, and the agent iterates against it; the human works at the level of intent, not lines. A good agent prompt is itself a specification.
- The practice is strongest for well-bounded features with clear acceptance criteria and weakest for exploratory or novel-architecture work, where writing the spec is the hard part. Governance of generated code still applies; treat specs as first-class version-controlled artifacts.
The inversion: code becomes an output
For sixty years the source code was the artifact. It was what you wrote, reviewed, versioned, and defended; everything else, the design docs, the tickets, the diagrams, decayed the moment it left someone's screen because only the code was authoritative and only the code ran. That hierarchy held because writing code was the expensive, skilled, irreducible step. When a coding agent can produce a correct implementation from a precise description in minutes, the economics that made code the crown jewel quietly invert.
The move is not that code stops mattering. It is that code stops being the thing worth maintaining by hand. If an implementation can be regenerated reliably from a sufficiently precise statement of intent, then the implementation is an output, like a compiled binary, and the input is the asset. The durable artifact becomes the specification: the exact statement of what the system must do, under what constraints, verified by what tests. Code is downstream of it, the way object files are downstream of source.
This is an emerging 2025 practice, not a settled industry standard, and it earns its place by naming something teams already feel. Anyone who has watched an agent rewrite a module twice in an afternoon has noticed that the diff is no longer where the value sits; the value sits in knowing precisely what the module was supposed to do. Spec-driven development makes that observation load-bearing.
What a usable spec actually is
The word "specification" invites a lazy reading: a wishful paragraph in a ticket, a wiki page nobody opens twice. That is not what carries the weight here. A usable spec is precise enough that an agent can implement against it without guessing and a test can confirm the result without human judgment. Vagueness is the failure mode; if two competent readers would build materially different systems from the same document, it is not yet a spec.
In practice a usable spec has four parts, and the discipline is in making each one concrete rather than aspirational.
- Requirements. What the feature does, stated as observable behavior rather than implementation. Not "cache the results" but "a repeated identical query within 60 seconds returns without a second upstream call."
- Interface contracts. The exact shape of inputs and outputs, error conditions, types, and the non-functionals that decide production viability: idempotency, timeouts, rate limits, what happens on failure.
- Acceptance criteria. The conditions that must hold for the work to count as done, written so their truth is checkable rather than debatable.
- Executable tests. The acceptance criteria rendered as code the machine can run, so "done" is a green suite and not an opinion.
The line between the last two is where spec-driven development gets its power. Acceptance criteria in prose still require a human to adjudicate whether the output satisfies them; the same criteria expressed as tests are self-adjudicating. A spec that stops at prose is a better ticket. A spec that carries its own executable verification is a contract an agent can close against on its own, which is what makes regeneration cheap enough to treat code as an output in the first place.
None of this is new as an ideal; it is a restatement of behavior-driven and contract-first design that most teams admired and few practiced. What changed is the payoff. Precision used to be a courtesy to the next human. Now it is the interface to a machine that will build exactly, and only, what you specified.
Tests as the executable specification
Tests occupy a privileged position in this model because they are the one part of the spec that both humans and agents can check without interpretation. Prose describes intent; a test encodes it in a form that either passes or fails. That property is what lets the human step back. Once the acceptance criteria are tests, "is this done?" stops being a review conversation and becomes a command you run.
The workflow that follows is direct. The tests define the target. The agent writes an implementation, runs the suite, reads the failures, and iterates until everything is green, closing the loop itself on each cycle rather than returning to a human between attempts. A passing suite is the definition of done. The agent is not guessing at what you wanted; it is optimizing against an objective you wrote down, which is a far more reliable thing to hand a machine than an English paragraph.
Two honest caveats keep this from becoming magical thinking. First, tests specify what they assert and nothing more. An agent will satisfy the letter of the suite, so gaps in coverage become gaps in behavior, and an underspecified test invites an implementation that is technically green and practically wrong. The suite is now the specification, which means its blind spots are the system's blind spots. Second, tests bound behavior; they do not prove correctness across an unbounded input space, a limit that matters most in exactly the high-stakes settings where correctness is the point.
The spec-driven workflow
Assembled, the practice is a loop with the human deliberately positioned at the top of it. You write the spec and its tests. The agent implements and runs the suite. If it fails, the agent iterates. If it passes but the output reveals something the spec did not anticipate, an edge case, a wrong assumption, a missing constraint, you do not patch the code. You fix the spec, and the corrected spec becomes the thing that regenerates the code. The gradient of your effort points at intent, not implementation.
+------------------------------+
| Human: write spec + tests |
+--------------+---------------+
|
v
+------------------------------+
| Agent: implement, run suite |
+--------------+---------------+
|
suite green?
/ \
no yes
/ \
v v
+---------------+ +------------------+
| Agent iterates| | Human inspects. |
| vs the tests | | Gap in intent? |
+------+--------+ +---+----------+---+
| | |
+--<------------+ no
(loop) | |
refine spec v
(not the code) done
The counterintuitive rule is the one at the bottom of the diagram: when the output is wrong, resist editing the code. A hand-edit to a regenerable artifact is a change that lives nowhere authoritative; the next regeneration erases it, and the spec still describes the wrong thing. Fixing the spec is slower in the moment and correct over the life of the system, because it keeps the source of truth and the running system in agreement. This is the same discipline that made teams stop editing generated clients or compiled output by hand.
The loop is not free. Standing up a good suite and a precise spec front-loads effort that the old workflow spread across the whole implementation. The trade pays off when the feature will be regenerated, extended, or maintained more than once, and it does not pay off for genuine throwaways. Judgment about which is which is part of the skill.
Where prompts and specs converge
There is a second place this pattern shows up, and noticing it clarifies both. When you build an AI feature, the agent's prompt is not decoration around the model; it is the program. The system prompt states the role and rules, the constraints bound the behavior, the examples pin down the edge cases. Read plainly, that is a specification. It states intent, defines interface, and sets acceptance conditions, in natural language aimed at a probabilistic interpreter rather than a deterministic one.
Once you see a prompt as a spec, the engineering discipline transfers directly. A prompt deserves version control, a changelog, and an owner. It deserves tests: an eval suite is to a prompt exactly what a unit-test suite is to a function, the executable acceptance criteria that define whether a change is an improvement or a regression. Editing a production prompt without running its evals is the same category of mistake as editing a spec without rerunning its tests, and it fails the same way, silently. The managed-asset treatment is worked through in Prompts as Managed Assets.
The convergence is not a metaphor; it is the same underlying shift. Whether the interpreter is a compiler, a coding agent, or the model itself at runtime, the durable artifact is the precise statement of intent and the tests that verify it, and the generated behavior is downstream. Prompt engineering done well and spec-driven development are two views of one practice: write the specification precisely, verify it executably, version it like source, and treat the output as regenerable.
Where it holds and where it breaks
Skeptical CTOs are right to distrust any practice pitched as universal, and this one is not. It holds where the problem can be pinned down before the code is written and breaks where pinning it down is the actual work. The honest boundary runs along how much of the difficulty lives in the specification versus the implementation.
| Spec-driven works well | Spec-driven strains or fails |
|---|---|
| Well-bounded features with clear acceptance criteria | Exploratory work where the goal is discovered by building |
| Contract-shaped work: APIs, data transforms, validators, integrations | Novel architecture where the hard question is the shape itself |
| Behavior that is cheap to express as a test | Qualities that resist testing: taste, feel, emergent UX |
| Reimplementation, refactors, and ports against a known target | Research and prototypes meant to be thrown away |
The pattern that runs through the right-hand column is that the spec is now the bottleneck. When you can state precisely what you want, an agent building it is close to a solved problem; when you cannot, no amount of generation speed helps, and a premature spec actively harms by locking in a guess. For genuinely novel architecture the specification is the design work, and it is discovered iteratively, often by writing throwaway code to find out what the real constraints are. Spec-driven development does not remove that work. It relocates the difficulty from typing the implementation to knowing precisely what the implementation should do.
That relocation is the point, and it is also the warning. The skill that used to be spread across writing and debugging code now concentrates in specification and verification. Teams that were mediocre at saying exactly what they wanted did not have that weakness exposed, because the act of coding forced a thousand small decisions. Hand those decisions to an agent against a vague spec and it will make them for you, quickly and plausibly, and you will not notice until the gap surfaces in production.
What it means for engineering orgs
For an engineering leader, the practical consequence is a shift in where value and risk sit, not a new tool to buy. The scarce skill moves from writing code to specifying and verifying it: decomposing a problem into precise contracts, writing acceptance criteria that admit no wrong-but-passing implementation, and reading generated output critically against intent. That is a genuinely different aptitude from fluent coding, and some strong coders are weaker at it than some product-minded engineers. Hire and promote accordingly.
Review follows the artifact. If the spec and its tests are the source of truth, then the spec and tests are what get reviewed with rigor, and generated code is reviewed for what specs cannot easily capture: security posture, resource use, and adherence to standards. This does not lighten governance. Everything the Atlas says about governing AI-generated code still applies to the output; a plausible implementation from a green suite can still carry an injection flaw or a licensing problem that no functional test was watching for.
The concrete step is unglamorous: treat specifications as first-class, version-controlled artifacts, kept next to the code, reviewed on change, and owned by name. Most organizations already have the tooling; what they lack is the decision that the spec is the thing worth maintaining and the code is the thing worth regenerating. The teams that internalize the inversion stop measuring output in lines written and start measuring it in intent captured precisely enough that a machine can build it, and a test can prove it. That is the same standard good engineering always aspired to. The difference is that it is now the fast path rather than the disciplined one.