The Spec and the Skill
Why Skills are the Question before every build answer
When generation was expensive, a specification was a promissory note. You wrote it, you argued over it, you got sign-off, and then you abandoned it the moment code existed, because the code was the thing that cost money and the code was therefore the thing that was true. The spec went to a wiki to die. Within a quarter it described a system nobody had built, and everyone knew to ignore it. This was not a discipline failure. It was a rational response to which artefact was scarce: making the thing was hard, so the thing you made was the truth, and the statement of what you meant was a luxury you stopped paying for as soon as you could.
Free generation inverts the scarcity. The code is no longer the expensive part; the precise statement of what you meant is. And that statement now has two faces. Written forward, before the build, it is a specification. Packaged for reuse, after the build, it is a skill. They are the same artefact seen from opposite ends, and the interesting engineering is no longer in either face but in the loop that runs between them: you specify, you generate, you verify, you package the verified thing as a skill, you watch it work, you distil what it actually does back into the spec, and you go round again. The loop is the new unit of building. This article is about what runs inside it.
1. The oldest idea in computing, just returned
In 1953, designing the ARMAC machine in Amsterdam, Edsger Dijkstra wrote that he would describe the machine “in so far as it concerns the user: it will be described what the machine does, not how the machine works.” Historians of computing reasonably call this one of the first explicit statements of the interface concept, the wall between what a thing promises and how it delivers. It is also the seed of every specification language since. The whole inheritance, from design by contract to VDM to TLA+, is a sixty-year attempt to state intent precisely enough that the implementation becomes a derivation rather than an invention. Tony Hoare put the stakes in a sentence: a program that has not been specified cannot be incorrect, it can only be surprising.
So why did formal specification stay a niche pursuit, admired and unused? Two reasons, and they were the same reason wearing different clothes. The notation was forbidding, a second language most engineers were never going to learn. And the payoff arrived too late to be worth it, because when you were going to type every line of the implementation by hand anyway, the bottleneck was the typing, not the thinking, and a rigorous spec saved you nothing on the part that actually hurt. The discipline was sound. The economics were wrong. What has changed is not the discipline but the economics: the typing is now free, the thinking is the whole job, and the artefact that captures the thinking is suddenly the most valuable thing in the building. Formal specification was never wrong. It was early.
2. The spec is the source of truth, not the scaffolding
GitHub Next’s SpecLang project states the new posture cleanly: the specification is the main thing you maintain, and the executable code it produces is secondary, something you will rarely have to inspect. They call it “prose code,” and the distinction from no-code matters. You are not waving at an app builder and hoping. You are still thinking like a programmer; you are simply doing your thinking at the level of intent and letting the model handle the plumbing of getting that intent to compile. The spec is where the work lives, and the work is choosing what the system does and where its behaviour must be exact.
This is Brooks’s distinction made operational. Essential complexity, the part no tool can absorb, is deciding what to build and where the boundaries fall and whether the result is any good. Accidental complexity is everything incidental to that: the syntax, the glue, the boilerplate. The spec is essential complexity with the accidental scaffolding stripped away. Writing it is doing the irreducible work directly, which is why it feels harder than the old way even though the machine is doing more; you have lost the busywork that used to let you feel productive while you avoided the decision. SpecLang’s own loop, which it calls “create by reacting,” leans into this: start deliberately underspecified, run the thing, and refine only the parts that came out wrong. The danger hides in that convenience. Under-specification is a gift only if you can see what the model decided on your behalf and pull those decisions back up into the spec. If you cannot, the model is quietly authoring intent you never stated, and you will not find out until the intent ships.
3. Why prose alone will not hold
The obvious objection is that you already have a place for intent: a Markdown document, a Confluence page, a well-written README. Why does the spec need to be anything more than careful prose? Because prose drifts. The team behind Allium, a behavioural specification language built for exactly this moment, put the problem precisely: conversational context drifts within a session and evaporates across sessions; by the twentieth prompt the model is pattern-matching on its own earlier output rather than on your original intent, and when the chat ends the constraints vanish with it. Prose in a wiki has the same disease more slowly. It captures requirements, but it gives you no machinery for catching the moment two of them contradict each other.
That is the real gap. You can write “users must be authenticated” in one section and “guest checkout is supported” in another, and nothing in the document will flag the collision. A capable model will simply resolve it, silently, in whichever direction its training nudges it, and you will have shipped a decision you never made. A structured specification does the work that diligence alone otherwise has to: when two rules have incompatible preconditions, the form exposes the conflict, so the model does not need to be clever enough to notice. This also answers the tidy objection that a spec alongside code violates single-source-of-truth. Code is not a clean source of truth; it captures intentional and accidental behaviour with no way to tell them apart. Is that authentication quirk a feature or a bug? The code cannot say. You need something outside the code even to articulate “this behaviour is wrong,” and that something is the spec. It is the same logic by which types and tests are not duplication but resilience. This is also where David Parnas earns his place in the phase: information hiding is decision hiding, and a good spec names which decisions are load-bearing and which are free. An agent that can see only an interface cannot weave the cross-cutting tangle that ages a system to death, but only if the spec has said where the seams are meant to fall.
4. The spec is written from both ends
A document becomes a loop when it is written from both ends at once. Allium describes two processes that feed the same artefact from opposite directions. Elicitation works forwards, from intent: a structured conversation that draws out what you actually meant, surfacing the constraints you would never have thought to write down. Distillation works backwards, from the running implementation: it reads what you actually built and writes down what it actually does, including the behaviours nobody ever decided on. One captures what you meant. The other captures what exists.
The value is in the gap between them. When elicitation and distillation diverge, you have found something worth investigating, and the divergence is information rather than error. Maybe the implementation drifted from intent. Maybe the intent was naive and the implementation is right. Either way, the gap is a question the spec is now forcing you to answer, instead of a silent assumption riding quietly into production. This is Ohno’s discipline relocated from the factory floor to the codebase. Standard work, for Ohno, is not a rule carved in stone; it is the current best description of how the job is done, held as a hypothesis that the next observation is allowed to correct. The spec is standard work for intent. Distillation is going to the gemba, standing where the system actually runs, and writing down what is genuinely happening rather than what the plan said should happen. A spec that is only ever written forwards, and never corrected by what the build reveals, is not standard work. It is wishful thinking with good formatting.
Anyone who has met domain-driven design will recognise what is happening here, because this loop is Eric Evans recovered rather than invented. Evans built his discipline on a ubiquitous language, a single vocabulary shared by the people who understand the domain and the people who build the system, kept rigorously the same in conversation and in code so that nothing is lost in translation between them. A behavioural specification is that ubiquitous language given a durable home. His other central move was the insistence that the domain model is a designed artefact, deliberately separated from the database, the framework, and the wiring, none of which the business actually cares about. Watch what distillation does in practice and you are watching exactly that separation enforced: the discipline reads the running code and asks, of every detail, whether a stakeholder would care about it or whether it is mere implementation. The token format goes; the seven-day expiry stays. The database choice goes; the order of the workflow states stays. The question “would the business care?” is Evans’s boundary between domain and plumbing, and what he drew by argument the loop now runs as a step. He taught a generation to describe a domain precisely before acting on it, and the precision was always the point. It is also what makes a specification executable rather than decorative. A vague spec is a wish. A spec written in a real ubiquitous language is something a machine can build against and a property test can check.
5. Verification: how you know the spec is true
A loop that only specifies and generates is an open loop, and an open loop is just a faster way to ship your assumptions. The thing that closes it is verification, and the relevant advance is in how cheaply you can now check a spec’s claims against a build. Anthropic’s work on agentic property-based testing shows the shape of it. Ordinary tests are example-based: you assert that sorting the list [2, 10, 5, 4] returns [2, 4, 5, 10], and you have checked exactly one case and missed every edge you did not think of. Property-based testing inverts this. You state a property that should hold for all inputs, that deserialising is the inverse of serialising, say, or that samples from a given distribution are always positive, and the framework goes hunting for a counterexample.
The properties come from the spec, and a model is genuinely good at reading a function’s name, its docstring, and the way it is called, and inferring the property that ought to hold, because that is reasoning at the level of intent rather than example. The spec states the properties; the agent writes tests that try to break them; the build either survives or returns a result you have to read. Anthropic’s agent found real, merged bugs in NumPy, in tokenizers, in AWS tooling, this way. But keep the honest limit in view, because it is the whole point. When the agent tested a date library, it flagged a function that returned a non-Sunday Easter date, and the maintainers explained it was intended behaviour under a different calendar system. The “bug” was a misread intent. Verification surfaced the question; it could not answer it, because only a human knows what the system was for. This is Beer’s POSIWID and Ohno’s jidoka in one mechanism. The purpose of a system is what it does, not what its spec claims, and the property test is how you discover what it does before the customer discovers it for you. It is the andon cord, wired into the build, stopping the line the instant the build stops keeping the spec’s promise.
Testing has a precise word for the thing a test consults to decide whether output is right: the oracle. It is the source of truth the check appeals to, the judge that says pass or fail. In most testing the oracle is buried and ad hoc, a hard-coded expected value here, a developer’s memory of what good looks like there, which is why tests rot the moment the person who wrote them moves on. The move this whole framework turns on is to make the specification the oracle, named and explicit and outside the code. The property test does not consult a hard-coded answer; it consults the spec. The build is judged against the stated intent rather than against whatever the last person assumed. Once the oracle is the spec, a question with real teeth becomes askable: is the build wrong, or is the oracle wrong? The Easter date was the oracle being wrong, a property asserted that the domain never actually required. Either way you have learned something, and you have learned it because the judge was written down where you could argue with it.
6. The skill is the spec made reusable
The spec’s second face arrived as a standard. In December 2025 Anthropic published Agent Skills as an open standard, and within weeks it had been adopted across a startling range of competing tools. A skill is a folder containing a SKILL.md file: a little YAML frontmatter for metadata, then Markdown instructions, packaging a piece of procedural knowledge that an agent loads only when a task actually calls for it. Strip away the novelty and look at what a skill structurally is. It declares what it can do, what must be true before it runs, what tools it needs, and what shape its output takes. That is a specification. It is intent written for reuse and addressed to an agent rather than to a compiler.
This is why the skill matters to anyone running a technology function rather than writing the code themselves. For most people most of the time, the unit they touch is not the model and not the codebase; it is the skill. The skill is the interface to capability, the thing that is invoked, governed, shared, and audited. And the specification is how that capability gets defined and improved. The two are the same object at different stations of the loop. The early evidence rewards treating them that way: benchmarks show that curated, human-authored skills reliably improve an agent’s performance while skills a model generates from its own parametric knowledge rarely do, and that a small set of focused skills beats one bloated document every time. The discipline that produces a good specification is exactly the discipline that produces a good skill: precision about what it does, clarity about its boundaries, and the restraint to leave out what does not belong. A skill, in Ohno’s terms, is restraint made reusable, and a bloated skill is overproduction in the form of instruction. The waste argument that governs the rest of this phase applies one level up, to the instructions themselves.
The symmetry runs deeper than reuse, and this is what makes the loop more than a metaphor. The skill is not only the thing the loop produces. It is also the thing that operates the loop. Allium ships its workflow as skills: an elicit skill that runs the forward conversation from intent, a distil skill that reads a running codebase back into a specification, and maintenance skills it calls tend and weed that keep the spec aligned with the code as both move. The capability that turns code into spec is itself a packaged, reusable specification of how to do that. So the loop folds back on itself: skills maintain the spec, the spec defines the skills, and improving either improves your ability to improve the other. This is the point at which a development practice stops being a sequence of steps and becomes a system that compounds.
7. How the loop actually runs
Walk one full turn, concretely, because the detail is where the discontinuity lives. You begin with elicitation: a structured conversation that pulls intent out of a stakeholder and lays it down as a specification, filtering out the implementation ideas that surface along the way. You generate an implementation from that spec. You verify the implementation against the spec’s stated properties, and the build either keeps its promises or returns a result you have to read. You package the verified capability as a skill, with its preconditions and boundaries named on the front. Then comes the return leg, the one organisations forget exists: distillation. You point a distil skill at the running system and ask it not what the code says but what the code means; it filters out the database columns, the token formats, the framework plumbing, and writes down the domain behaviour that is actually there, including the behaviour nobody remembers deciding on. Allium’s own guidance is unambiguous about the status of what comes back: the extracted spec is a hypothesis, to be validated against both the developers who wrote the system and the stakeholders who wanted it. The loop closes when that distilled hypothesis is reconciled with the spec you started from, and the reconciliation is where the learning is.
This has already left the whiteboard. The most rigorous published account is the Kitchen Loop, a framework run over two production systems for more than 285 iterations and over a thousand merged changes with, on the authors’ regression oracle, no regressions. It runs a six-phase cycle, groom the backlog, use the product, turn findings into tickets, branch and fix, review and merge, then regress, and every phase is driven by a skill operating against a single trust model. Two of its design principles are worth lifting out verbatim, because they are the ones an enterprise will be tempted to violate first. The first they call spec-anchored improvement: a self-improving loop must optimise toward satisfying the specification, not toward a proxy metric, because the moment you point the machine at a number it can move, it will move the number and let the product rot in the dimensions the number does not see. The second is drift before failure: an autonomous loop needs continuous trend monitoring, not just a binary pass-or-fail gate at the end, because the failure you can catch is the one you watched coming. The human role, in their telling, moves to where it belongs: asynchronous specification design and backlog curation, not synchronous coding and manual QA. You stop writing the build and start authoring and curating the thing the build is judged against.
8. The half that fails silently
One thing in this loop is genuinely new. When both the unit you author and the unit other people consume are natural-language specifications, the distance between intent, implementation, and reuse can be closed continuously, turn by turn, rather than only at the release boundaries where it always used to be reconciled in a lump. That continuous closure has no clean classical analogue, and it is the real prize. But it depends entirely on the half of the loop that does not feel like progress, and that half is distillation. Generation feels like output; you can watch the skills pile up and the tickets close. Reading the build back into the spec feels like bookkeeping, and it is the first thing cut when a quarter gets tight.
Cut it and the loop does not stop. It degrades, quietly, in a way the research community has now named and measured. The failure mode of an unanchored self-improving loop is not a crash; it is drift. Skill libraries that evolve without a specification to answer to suffer what one recent study calls library drift, where the system keeps changing, keeps scoring well on whatever it measures, and steadily loses the plot on everything it does not. It is Goodhart’s law wearing engineering clothes: optimise the proxy, lose the purpose. This is exactly the failure Beer warned of from the other direction; the purpose of a system is what it does, and a loop that has stopped checking what it does against what it was meant to do has quietly adopted a new purpose without telling anyone. The skill becomes the author of intent that nobody ever stated. You get more capability and less and less idea of what any of it actually promises, which is the precise shape of overproduction Ohno spent a career fighting, now reproduced at the level of instructions rather than parts.
The defence is the same in every serious account of these loops, and it is cheap relative to what it protects: anchor the loop to something the loop cannot move. A specification it must satisfy. An oracle outside the code, one the builder cannot quietly weaken to make the result pass. A trend you watch between gates rather than a gate you hit at the end. The most dangerous specification is not the one that is wrong; a wrong spec gets caught the first time the build contradicts it. The dangerous one is the spec that stopped being checked against the thing it describes and was believed anyway, because nothing contradicts a document nobody reads. The spec and the skill are the same artefact seen from the two ends of one loop. The engineering is not in either end. It is in keeping the loop closed.
(An Organisational Prompt is something you can do now....)
Organisational Prompt
Close one loop, end to end
Pick one capability your organisation already builds with AI and currently treats as a pile of code plus a folder of prompts. Just one. Now write its specification: not how it is implemented, but what it must do, under which conditions, and, the part everyone skips, what it must never do. Keep it short. The discipline is not length; it is making the contradictions visible enough that you cannot pretend they are not there.
Then distil. Read the running implementation back and write down what it actually does, including the behaviour nobody remembers deciding on. Put the two documents side by side, what you meant and what exists, and look hard at where they disagree. That gap is not a tidiness problem to be cleaned up later. It is the most useful thing you will learn this quarter, because it is the intent your system has been acting on without telling you.
Now state one property that must hold for all inputs, not one example, a property, and have an agent try to break it. If it cannot, you have a verified claim rather than a hope. Package that claim as a skill, with its preconditions and its boundaries named on the front.
The test of whether you did this well is not whether you produced three documents. It is whether, three weeks from now, the spec still describes the skill, and the skill still keeps the spec’s promise. If they have drifted apart and nobody noticed, you were never running the loop. You were just writing the same thing down in two places and trusting both.
Further Reading
Edsger Dijkstra’s role in the origin of the interface concept, including the 1953 ARMAC line about describing what the machine does and not how it works, is recounted in Dijkstra, Blaauw, and the origin of computer architecture. The cleanest short route into where all of this began.
GitHub Next, SpecLang. The clearest statement of the spec as the maintained source of truth and the code as a secondary artefact, with the “prose code” and “create by reacting” framing this article draws on.
JUXT, Allium. A behavioural specification language built for LLM-era development; read it for why prose alone cannot surface contradiction, and for the elicitation and distillation pair that turns a spec into a loop. The two skills themselves are worth reading directly, because they are specifications of how to specify: elicit runs the forward conversation, and distill reads a running codebase back into a spec, treating the result explicitly as a hypothesis to be validated.
Eric Evans, Domain-Driven Design Reference (2015), the freely available distillation of his 2003 book. Read it for the ubiquitous language and for the insistence that the domain model is a designed artefact kept clean of implementation; the loop in this article is that discipline made executable, and Evans even calls the move that abstracts code back to domain by the same name, distillation.
Yannick Roy, The Kitchen Loop: User-Spec-Driven Development for a Self-Evolving Codebase (2026). The most rigorous published account of the spec-anchored loop running in production, over 285 iterations and a thousand-plus merged changes. Read it for the six-phase cycle and for the two principles that keep it honest: optimise toward the specification, not a proxy, and watch for drift before failure rather than only at the gate. The code is open.
Anthropic, Finding bugs with Claude and property-based testing. Verification at the level of intent rather than example, including the honest limitation that an agent cannot decide what a system was for.
The Agent Skills specification. The open standard that makes the skill a portable, declarative contract; read it as a specification format that happens to be addressed to an agent.
On the failure mode: the library drift paper (2026) names and measures what happens when a self-evolving skill library has nothing to answer to, and Addy Osmani’s Self-Improving Coding Agents is the most practical survey of the loop in the wild, including the periodic-refocusing discipline that combats drift in long runs.
Fred Brooks, No Silver Bullet: Essence and Accidents of Software Engineering (1986). The essential-versus-accidental distinction the whole argument sits on, freely available as Brooks’s own technical report.
Disclaimer
I write about the industry and its approach in general. None of the opinions or examples in my articles necessarily relate to present or past employers. I draw on conversations with many practitioners and all views are my own.

