The spec is the artifact

  • engineering-practice
  • specifications
  • intent-capture

For most of the history of software engineering, the question what is the artifact had a settled answer: the code. The code was the thing a team version-controlled, reviewed, refactored, and handed to the next engineer. It was the durable output of the work and the durable record of it. Whatever specification preceded it — a ticket, a design doc, a paragraph in a planning thread — was scaffolding. It got the code written and was then allowed to rot, because the code had absorbed everything the spec was trying to say. “The code is the spec” was not a slogan; it was an accurate description of where the team’s intent actually lived.

AI tools broke the second half of that arrangement — the half where the code was also the record. Two things happened to code at once. It got cheap to produce and cheap to change, so it now churns: a given piece of it is written, edited, and refactored far more often, and far more casually, than hand-written code ever was, and it rarely sits still long enough to be anyone’s stable reference. And the code that gets produced this way carries intent worse than hand-written code did — it is idiomatic rather than chosen, plausible rather than precise, so even a fixed snapshot of it is a thinner record of the team’s reasoning than it used to be. The code is still the running system. It is no longer the durable record of what the team meant by it.

That record has nowhere to live but the specification. So the spec becomes the artifact — not the disposable scaffolding that precedes the real work, but the durable thing the team has to write well, keep current, review, and hand forward, because it is now the only place the team’s intent can durably live. Most teams have not made this swap. They still maintain the code with care — grooming it, reviewing every change to it — and still treat the spec as scaffolding to be discarded once the code exists. That was the correct allocation when the code was a faithful record. It is the wrong allocation now, and the cost of the mistake stays invisible for a quarter or two before it surfaces.

Three consequences of the inversion deserve naming. None of them is about writing better prompts.

1. The prompt that isn’t a spec

The first thing the inversion exposes is that most teams do not have specs. They have prompts, and they have been calling them specs.

The distinction is not about length or precision. A prompt can be long, detailed, carefully worded, and still not be a spec. The distinguishing property is durability: a spec is an artifact that persists after the code exists and can be returned to, and a prompt is not. A prompt is a keystroke. It produces an output and is then — correctly — discarded, because its job is done the moment the output exists. A spec is the thing you keep.

The operational test is whether someone who was not there could reconstruct the work’s intent from it later. Hand the artifact to another engineer six months from now. If they can recover what the work was supposed to do, what constraints bounded it, and why it was shaped the way it was, the artifact was a spec — it carried intent forward. If all they can recover is the topic, the artifact was a prompt: it captured enough to steer one act of building and nothing durable enough to inform anyone afterward.

The most common form of the problem is a spec that was real and is now unrecoverable, because it never existed as a thing. It was distributed across a conversation — a request, a correction, a clarification, another correction — and the working specification was the sum of that exchange. The exchange is not an artifact anyone maintains. When the code came out right, the thread was abandoned, and the specification went with it.

Call this the prompt that isn’t a spec: a specification that did its job once and cannot do it again, because it was never stored as a thing. Note that such a prompt can still produce entirely correct code — and that is exactly what makes the problem invisible. The team that works this way has not skipped specifying its work. It has specified it, used the specification, and thrown it away. Because the output was fine, nobody noticed that the spec was the artifact that should have been kept and the code was the byproduct that survived on its own.

2. Spec drift

Suppose a team does keep its specs — stores them, treats them as artifacts, puts them somewhere a second person can find them. The second consequence of the inversion is a failure mode the kept spec is newly exposed to: it drifts out of agreement with the code.

The mechanism is ordinary and almost invisible. The spec is written, the code is built and reviewed — and then the code is edited directly. A review comment is addressed by changing the diff. A bug is fixed in place. A small adjustment is made because making it in the code took thirty seconds. Each of these edits is reasonable. None of them is written back to the spec. The spec now describes a system that is slightly, and then substantially, not the system in production. Call the failure mode spec drift.

This looks like the old problem of stale documentation, and it is worse than that — not because the spec decays faster, but because of what the team has decided to do with it. Stale documentation is a side-document; everyone knows to distrust it and fall back to the code. A drifted spec is the artifact the team has designated as its record of intent. A future reader does not fall back from it — they rely on it. They read the spec to learn why the system is shaped the way it is, and the spec tells them about a system that no longer exists. The drifted spec does not merely go quiet, the way stale docs do. It misinforms, with the team’s full confidence behind it.

Spec drift has a precise tell: the point at which a new engineer handed the spec would build a wrong model of the running system. Before drift, the spec and the code tell the same story, and either one teaches the system correctly. After drift, they tell different stories, and nobody can say which edits live in which — so the spec has quietly stopped being usable as the record of intent while still being presented as one. The team has demoted the spec back to scaffolding without ever deciding to. The code is the only honest record again, by default, and the code is the record that does not carry why.

The discipline that prevents this is not heavy, but it is specific: an edit to behavior is an edit to the spec, made alongside the edit to the code. If the team chooses instead to let the spec fall behind — which is sometimes the right call, under deadline — it should do so knowing it has just spent down the spec’s standing as the record of intent. Drift is not the problem. Undecided drift is the problem: the team that lets the spec and the code diverge silently has given up its record of intent without noticing it did.

3. Spec inheritance

The third consequence is the one that compounds, and it is the reason the inversion is worth getting right rather than merely worth noting.

Code was always inheritable. The next engineer read it, maintained it, extended it. But code is a poor inheritance: it carries what the system does and almost none of why, and under AI authorship it carries even less, because the structure is idiomatic rather than chosen and the names are plausible rather than load-bearing. An engineer inheriting a codebase inherits a set of answers with the questions removed.

A spec is a different inheritance. It carries the intent directly — the outcome that was wanted, the constraints that bounded it, the cases that were ruled in and ruled out. An engineer who inherits the spec inherits the questions, which is the part that was always expensive to reconstruct and is now close to impossible to reconstruct from code alone. A team that keeps its specs accumulates, with no effort beyond not throwing them away, a record of its own intent that is more useful to the next person than the code is.

Call this spec inheritance, and note that it changes two things about how a team works.

The first is the review. When the spec is the artifact, the spec is the thing to review with the attention the team used to spend on the diff. Reviewing a spec is reviewing intent — the decision itself, while it is still only a decision. Reviewing a diff is reviewing the outcome of a decision after the system has been built around it. The spec review is the meeting that should do what design review and code review were each partly doing: the conversation about whether this piece of work is the right work, correctly bounded, before it is built. Teams that move their review attention onto the spec catch the expensive mistakes while they are still sentences. Teams that keep spending it on the diff catch them as code, which is later and harder.

The second is that specs become a team asset the way a codebase is one. A spec written well — stored, named, kept in agreement with what shipped — is re-readable by the next person who needs to understand that part of the system. A team that has been keeping its specs for a year has a spec library: a navigable record of what it has built and what it meant, in the artifact that actually carries meaning. This is not a documentation initiative bolted onto the work. It is the natural residue of treating the spec as the artifact, the same way an accumulated codebase was the natural residue of treating the code as the artifact. The team gets the asset for free, provided it simply stops discarding the thing it already produces.

What the artifact question decides

The inversion is simple to state and uncomfortable to act on. For a decade, what is the artifact was answered by the code, and every habit a team has — what gets reviewed, what gets version-controlled, what gets maintained, what gets handed over — was built around that answer. The answer changed. The code stayed the running system but stopped being the durable record of intent; the spec, written deliberately and kept current, became the artifact that carries the reasoning forward. The habits did not change with it.

A team that has absorbed the inversion keeps its specs, reviews them as closely as it once reviewed code, updates them when behavior changes, and hands them forward. A team that has not absorbed it does the reverse: it spends its care on the code — grooming the codebase, reviewing every diff — and lets the spec evaporate the moment the code works. That team is not failing to specify its work. It is specifying it, using the specification, and then maintaining the one of its two artifacts that no longer carries why.

The code was never the part in danger of being lost — it is running in production; it cannot be misplaced. What gets lost is the reasoning: why the system is shaped this way, what was considered and rejected, which constraint dictated the shape. A team that maintains only the code keeps every answer its work produced and discards every question. The spec is where the questions live. Treating it as scaffolding is deciding, without quite noticing, that the next person will not get to ask them.