In January I wrote that programming was no longer about code — that code had become an intermediate artifact, a compilation target of something else, and that responsibility had migrated upward. I ended on a question:
Who owns the specification — and the proof that reality matches it?
I did not answer it. I had the shape of the problem and no working answer, which is the honest position for a January.
This is the answer, seven months later. Not an argument — a machine, and what it cost to build.
The question was really two questions
“Who owns the specification” turned out to be the easy half. A specification with an owner is just a document with a name on it. What makes it load-bearing is that nothing enters the system except through it: a spec is its own pull request, reviewed before any code exists, and code is written from it rather than negotiated alongside it. When the outcome is wrong, the correction lands in the spec first. That part is discipline, and discipline is cheap to describe and expensive to keep.
“And the proof that reality matches it” is the hard half. It is also where almost every AI-assisted workflow quietly gives up.
Because there is a gap that no amount of specification closes: between what the specification says should be true, and what the system will claim is true when it speaks. A model asked to summarise a result will produce a summary. It will contain numbers. The numbers will look right. And nothing in the pipeline, up to that moment, has any obligation to check them.
What “proof” turned out to mean in practice
Not formal verification. I tried thinking in that direction and it does not survive contact with the work — you cannot write a theorem prover for “the quarterly commentary is accurate.”
What survives is narrower and duller: every figure a model states must be independently recomputable from source, and anything that is not recomputable does not ship.
That sentence sounds obvious. In practice it inverts the architecture.
- The model does not calculate. A deterministic engine calculates, and the model narrates what the engine produced. If the model needs a number it does not have, it must ask a tool, not remember.
- The model’s output carries its figures as structured claims, not as prose to be parsed later. A claim is a thing you can check; a sentence is a thing you can only believe.
- A gate re-derives every claimed figure from the source data and compares. Mismatch means rejection, not a warning — and the run retries with the rejection as input.
- Arithmetically correct is not the same as verified. The sharpest case I hit: a figure was withheld from the model, and the model derived it correctly from the figures it did have. The arithmetic was right. The gate rejected it anyway, because the number had not come from the source. That rejection is the entire thesis in one event.
- What cannot be verified is not softened, hedged, or footnoted. It is removed, and its absence is visible.
The part nobody warns you about
A verification layer changes what failure looks like, and the new failure mode is worse-feeling and better.
Before, a bad number shipped quietly and someone found it weeks later, or never. After, the pipeline stops — visibly, at 2 a.m., in the middle of the run you most wanted to succeed. I have had a release blocked by my own gate on the single most important publication of the month, over a real defect that was, in the end, a formatting bug: a time written as digits was read aloud as a decimal fraction. Trivial cause. Correct refusal. The temptation to wave it through was substantial, and waving it through would have shipped audio that mispronounced the exact number the piece existed to communicate.
A gate you bypass under deadline is not a gate. It is a decoration you paid for.
The corollary is that the gate must be cheap enough to obey. If verification costs an hour every time it fires, it will be disabled within a month, honestly and for good reasons. Ours costs a retry.
Ownership, concretely
So: who owns the proof?
Not the model — it has no stake in being right and no memory of having been wrong.
Not the engineer, alone — that is just code review with extra steps, and it does not scale past the volume that generation now makes trivial.
The system owns the mechanism; a human owns the release. Those are different things and collapsing them is the common mistake. The mechanism recomputes, compares, and refuses, every time, without fatigue and without judgment. The human decides whether a correct thing should be said at all — which is a question no recomputation answers.
In the running system this is a pause: the pipeline holds the execution and waits for a person, indefinitely, and ships nothing if nobody comes. One run has ended that way. It published nothing, which is the correct outcome and looks, in the ledger, exactly like a failure. Fails closed.
What the receipts actually say
The claim is not theoretical any more, so here is what exists and what it cost.
A spec-driven factory: 470+ specifications, ~140k lines of TypeScript, roughly one line of specification for every three lines of code. Specs land as their own pull requests, reviewed before code exists. Agents run in parallel and hand work to each other. The system cuts its own releases — the last one bundled 147 commits, tagged and published by the machinery it describes. Reviews are cross-vendor by policy, because a model family reviewing its own output blocks on 0% of what a rival vendor blocks on 43% of. And the verification lab above runs on the same discipline: ~$0.003 per run, 100% of shipped figures recomputed from source, zero unverifiable numbers reaching a reader.
That is the part that worked.
Two levels, and only one of them is finished
January separated two things that get conflated constantly, and the separation is what makes the rest tractable:
- Saying what I want — the intent, the constraints, the guarantees, the failure modes. The specification.
- Building the machinery that turns that want into code — the thing that consumes the specification.
Level one is a discipline, and it works. It works today, at volume, and the receipts above are what it produces.
Level two is a compiler, and here is the part that matters: a compiler is also something you have to build. Nobody handed us one. We are writing it while using it, which is a strange position to work from and the actual position everyone in this field is in, whether or not they describe it that way.
So when I say “code is a compilation target,” that is a statement about level one — about where authorship lives. It is not a claim that level two is finished. It obviously is not.
What the compiler cannot do yet
The most visible gap: there is no incremental mode.
In practice we do not regenerate a system from its specifications. We extend it — a new spec describes a delta, agents write into the existing codebase, the previous code stays. Full regeneration is technically possible and economically absurd: enormous in tokens, time and risk, for a button that moved.
That is a tooling limitation, not a conceptual one, and it is worth being precise about the difference — because the usual objection to spec-as-source is “but you’d lose all the accumulated fixes,” and in this model you would not. A discovered bug is not a patch that lives in code and nowhere else. A discovered bug is a defect in the specification: the requirement was not strict enough, and the correction goes into the spec so that the same wrong thing cannot be generated again. That is the discipline, and it is what makes the substrate stay true rather than drift.
What is genuinely missing is cheapness. A compiler can regenerate freely because regeneration costs milliseconds. Ours costs money and hours, so we extend instead, and extension is where drift creeps in — not because the model is wrong, but because the machinery is not yet good enough to run the model at its natural cadence.
What the specifications turned out to be for
Here is the part I did not predict, and it is the reason the discipline pays for itself anyway.
The specifications are not compiler input. They are the context layer that lets an agent understand a system it did not write.
Code answers what — reliably, exhaustively, and at a cost of reading everything. Code does not answer why: why this boundary, why this constraint, why the obvious simplification was rejected two months ago and would be rejected again. That knowledge normally lives in the heads of people who were in the room, which is precisely the knowledge an agent does not have and a new hire spends a quarter reconstructing.
A spec repository is that room, written down. When an agent picks up a change, the relevant specs tell it what the system is meant to guarantee and which decisions are already settled — so it extends the design instead of relitigating it. The specs are load-bearing not because we recompile from them, but because they are the only artefact that survives the transfer of the “why.”
Which reframes the ratio: one line of specification per three lines of code is not overhead on generation. It is what makes the next generation competent.
The open problem
So the next problem is not philosophical. It is the incremental mode.
Regenerate only the part the changed specification actually governs. Cache and reuse the rest. And — this is the hard half — prove that the regenerated part still agrees with the code around it. Not a diff. An argument.
Get that, and the two levels close: intent stays the source, and the machinery can afford to honour it continuously instead of once. Miss it, and level one stays a discipline you maintain by hand — which works, at the scale of one person who cares, and stops working exactly when it starts to matter.
I do not have that yet. Nor, as far as I can tell, does anyone else. It is the piece that decides whether “specification as source” becomes engineering or stays a good sentence.
Where this leaves the January claim
I said responsibility migrates from lines of code to specifications, guarantees, validation logic, and system boundaries, and that validation becomes the core skill. Seven months of building have not moved me off that, and I would not soften it now — if anything the industry has spent this year proving the point on my behalf. Evals, guardrails, judges, gates, verification layers: the attention has moved to validation, for people and for the tools people are building. That is the whole conversation now.
What the seven months added is not a correction to the claim. It is the shape of the thing, which no amount of thinking produced and only building did:
That a claimed figure must be recomputed from source, not sanity-checked. The difference sounds pedantic and is the entire difference: a plausibility check passes an arithmetically correct number that never came from the data. A recomputation does not.
That refusal has to be the default outcome, not the escalation. A warning is a thing a pipeline steps over. A rejection is a thing it cannot.
That the gate has to be cheap enough to obey. This is the one I would not have predicted in January, and it decides whether any of the rest survives contact with a deadline. Verification that costs an hour gets disabled within a month, by reasonable people, for good reasons. Ours costs a retry, and that is why it is still on.
And that the mechanism and the release are different ownerships. The machinery recomputes and refuses without fatigue. A person decides whether a correct thing should be said at all. Collapsing those two is how “automated verification” turns into a rubber stamp with better latency.
January named the destination. The last seven months were about what it costs to actually stand there — and the honest answer is that it costs a pipeline that will stop you at two in the morning, on the release you care about most, and be right to do it.
Autonomy is earned, not granted. The gate is how it gets earned, and the pause is where it stops.
This answers the question that closed Programming Is No Longer About Code (January 2026). Part of a series on running an AI software factory: the trust ladder, pets-not-cattle, lights-on, the release button, the unbounded gate, the change cloud, the score is not the game, and the fifth capability.