Spec-Driven Development | WhiteFish Creative
Spec-Driven Development
Make A Splash!

Spec-Driven Development: What It Is, What It Isn’t, and Why Your Last Build Went Sideways

The project was ninety percent done in November.

It was ninety percent done in December. In January there was a difficult meeting, some restructuring, and a new estimate. By March it was ninety percent done, and by then you’d stopped asking, because the answer had stopped meaning anything.

Nobody lied to you. That’s the part worth sitting with. Every person who told you ninety percent believed it. They could see the thing working on their machine. The demo ran. What none of them could tell you, what nobody in the building could have told you, was what the other ten percent contained, because it had never been written down. It was a collection of private assumptions, distributed across four people’s heads, that had never been compared.

The ten percent wasn’t work remaining. It was disagreement, and it had been there since week one.

This is the most common way software projects fail, and it has almost nothing to do with engineering skill. I’ve spent a lot of the last few years being called in after it happens. The code is usually fine. Sometimes it’s genuinely good. What’s missing is any artefact, anywhere, that says what the thing was supposed to do, precisely enough that two people could disagree about whether it does it.

Spec-driven development is the name the industry has recently attached to fixing that. It’s having a moment: tooling, conference talks, a research literature, vendors. Most of what’s written about it is either a product tutorial wearing a methodology costume, or a rebranded requirements process with an academic citation stapled on.

So here’s the useful version. What it actually is, what it definitely isn’t, and the bit almost nobody covers, which is how you’d know whether it worked.

What it is

A specification is a document that says what you’re building, precisely enough that a competent stranger could build the right thing from it without asking you a question.

Spec-driven development is the discipline of writing that document first, keeping it in the repository next to the code, treating it as the thing that governs the work, and updating it deliberately when reality argues back.

That’s it. That’s the whole idea. If it sounds like something the industry has known since about 1968, that’s because it is, and we’ll get to why it’s back in a moment.

The reason it’s back is that we started handing the work to machines.

Give a junior developer a vague ticket and they’ll come and find you. They’ll stand awkwardly by your desk and ask what happens if the email already exists. That question is annoying, it breaks your concentration, and it is the single most valuable event in the entire process, because it surfaces a decision that nobody had made, at a point where making it costs thirty seconds.

Give an agent the same vague ticket and it does not come and find you. It decides. Instantly, plausibly, and at enormous speed, in a way that looks exactly like progress. It picks an answer to the question your junior would have asked, and it picks a different answer to the next forty-three questions, and none of those decisions are recorded anywhere, and by Thursday you have eleven thousand lines of code embodying four hundred choices that no human made.

The machine didn’t create this problem. Your requirements were always vague. It removed the person who used to quietly compensate for it.

That’s the whole shift. Everything else is detail.

Before I sell you this, here’s how it goes wrong

There is a way to read everything above and reach a catastrophically bad conclusion, and it is the most likely conclusion for a certain kind of experienced manager to reach, and I want to block it before we go any further.

The bad conclusion is: right, so we should specify the system up front.

Do not do that. That’s waterfall. We tried it for thirty years, it failed for reasons that haven’t changed, and none of those reasons were “we didn’t have good enough tools.” It failed because the act of building software teaches you things about the problem that were genuinely unknowable beforehand, and a process that can’t absorb those lessons will produce, very efficiently, exactly the wrong thing.

I’m not the only one worried about this. ThoughtWorks, who are not sceptics about AI tooling, put spec-driven development in the Assess ring of their Technology Radar, which is the ring that means “interesting, look into it, don’t bet the company.” Their specific warning was that the approach carries a bias towards heavy up-front specification and big-bang releases, and that this bias is an antipattern.

That’s the failure mode. It’s not hypothetical and it’s not rare. It’s the natural resting state of any organisation that has heard “write it down first” and has a project manager with a Gantt chart habit.

The distinction that saves you is small and it’s everything: you specify a slice, not a system. You write down what one feature does, in detail, including what it must never do. You build it. You check it. You learn something. You update the spec, deliberately and on the record. Then you do the next slice.

The spec is a document that changes. It changes through a decision, made by a person, written down. What it never does is change silently, which is what happens when there’s no spec at all and the code is the only record of what anyone intended.

Waterfall is a spec that can’t change. No process at all is a spec that changes constantly and invisibly. The thing you want is in between, and it’s less exciting than either.

What it isn’t

Now the rest of it, because most of the confusion here is people arguing about six different things under one name.

It isn’t a PRD

A product requirements document is read once, mostly in a meeting, and then it goes into a folder and dies. Everyone knows this. Nobody says it.

A spec is executed. It’s in the repo, it’s diffed in pull requests, tests reference it by section number, and when it’s wrong someone has to change it on purpose. The difference isn’t the content. A PRD and a spec might contain identical words. The difference is that one of them has consequences.

If your spec lives in Confluence, you have a PRD. I’m sorry.

It isn’t documentation

Documentation describes what got built. A spec constrains what gets built. They’re aimed in opposite directions in time, and that turns out to matter enormously.

A spec written after the code isn’t a spec. It’s a description, and it’s a description written by someone who now has a strong emotional interest in believing the code is correct. It will describe the bug as a feature, and it will do so sincerely.

It isn’t a tool

This is the one I’d most like you to take away, because the entire internet has a commercial incentive to tell you otherwise.

There are good tools in this space. GitHub ships Spec Kit, Amazon has Kiro, there’s OpenSpec and BMAD and a dozen others, and some of them are genuinely well made. They scaffold the discipline. They give you file structures and slash commands and a place to put things.

None of them give you the discipline. You either write down what you’re building or you don’t, and installing a CLI has never once caused anyone to start. It’s a gym membership. The membership is not the exercise, and the person who’s already running every morning doesn’t become fitter by buying one.

Everything in the action pack that goes with this post is a markdown file. Every single one. The whole method runs on a text editor and the willingness to be specific. If you take nothing else from this: you do not need to buy anything to do this. A team with a spec file, a list of things they’ve decided not to build, and a habit of checking will beat a team with the entire toolchain and no habit, every time, and it isn’t close.

It isn’t free

Here’s where I’ll disagree with most of the people selling this.

Writing a spec costs time. Real time, up front, before anything visibly exists, at exactly the moment when everyone is most impatient to see something on a screen. That cost is real and the advocates are strangely quiet about it.

It doesn’t pay off on everything. If you’d fix it in one follow-up prompt, don’t spec it. If you’d be annoyed at someone interpreting it differently than you meant, spec it. That’s the whole heuristic and it’s not sophisticated, but applying it honestly is what separates this from ceremony.

Applied indiscriminately, this becomes bureaucracy, and bureaucracy is how you get back to waterfall by a different road. A process that costs more than the mistakes it prevents is not a good process. It’s just a process.

It isn’t a substitute for judgement

Nothing in a spec decides whether the feature is worth building. Nothing in a spec tells you the customer is wrong about what they want. Nothing in a spec catches the fact that the whole project is solving a problem that stopped existing in February.

This moves judgement upstream. It doesn’t remove it. If anything it concentrates it, because the decisions all happen earlier now, in a smaller number of moments, made by fewer people. That’s better, mostly. It’s also a different failure mode, and it’s worth knowing you’ve swapped one for the other rather than eliminated it.

It isn’t proven by the numbers you’ve been shown

You’ve probably seen the figures.

Amazon says Kiro turned a forty-hour feature into under eight. GitHub claims an order of magnitude fewer regenerate-from-scratch cycles. Various vendors have various before-and-afters, all of them impressive, none of them audited, all of them describing their own product.

I don’t think anyone’s lying. I think these are self-reported numbers from people with an enormous interest in the result, uncontrolled, with no baseline anyone can inspect, and if a member of my team brought me that as evidence I’d send them away.

The honest position is that the research is young. There’s a reasonable arXiv paper from Piskala in January that at least tries to be rigorous, and it lands on something more modest and more useful than any vendor claim: this is a spectrum, not a switch. You can be spec-first, or spec-anchored, or treat the spec as the source that code is generated from, and they’re wildly different commitments with wildly different costs.

Almost everyone should be in the middle. The spec governs. The code is still the truth. The tests are what enforce the agreement between them. The pure version, where the spec is the real artefact and code is disposable output, is a research position, and if you adopt it because a conference talk was persuasive you’re going to have an interesting year.

So: adopt this because the reasoning holds, not because someone showed you a chart.

The bit nobody sells you

Here’s what I actually think is going on with spec-driven development as a topic, and why it’s worth the argument.

Everyone covers writing the spec. It’s the fun part. It’s the part with templates, it demos well, and it’s what the tools do.

Almost nobody covers what happens next.

Because writing the spec is the easy half. The hard half is everything after: building against it without drifting, proving that what got built matches what was agreed, and noticing when it doesn’t. That part has no product to sell, doesn’t demo well, and is where the entire value of the exercise actually lives.

A spec you never check against is a spec you wrote to feel organised.

Let me be concrete, with a worked example I’ve built out in full in the action pack. It’s a composite, stitched together from failures I’ve watched happen more than once, because this particular shape of disaster is depressingly common.

A login feature. Well specified. One of the criteria said, explicitly, that a password must never reach the logs, including when the code throws an exception. Clear. Testable. Agreed by everyone.

It was built. The test suite passed. Line coverage was ninety-four percent. There was a test named test_no_password_in_logs, and it passed, and it had passed for eleven days. Four people reviewed the code and approved it.

And in the exception handler there was one line that wrote the entire login request, password included, in plaintext, into the log aggregator.

The test covered two of the three paths the criteria named. It skipped the exception path, because writing a test that forces an unhandled exception felt contrived. The reviewers read the test’s name and believed it. Everyone was honest. Every tick was made in good faith. The process, as far as anyone in it could see, was working.

It took ninety minutes to find, and it was found by one thing: someone who hadn’t built it, sitting down with the list of criteria and asking, for each one, which test proves this, and does it actually prove it? Nine rows. Eight fine. One green tick that was theatre.

That check has no vendor. It’s a table. Nobody’s selling it to you because there’s nothing to sell, and it’s the only part of this that would have caught the thing that mattered.

The same exercise found three features that had been built and that nobody had asked for, including two that were on the explicit list of things the team had decided not to build. Not because anyone rebelled. Because a capable, literal thing building a login form produces the login form it has seen ten thousand times, and nothing was comparing the output to the agreement.

That’s what drift is. It isn’t the machine misbehaving. It’s a gate that doesn’t exist.

What this means for you

If you’re reading this because a build went sideways, here’s the diagnosis. It’s usually one of four things, and it’s rarely the one people reach for.

Nobody wrote down what done meant. Not in a way that could be checked by someone who wasn’t in the room. Every status report was sincere and none of them were information. Your ninety percent was four people’s private, different, ninety percents.

The decisions were made by whoever was typing. Not by you, not by the client, not in a meeting. By a developer at 4pm, or by an agent at four hundred words a second. Every one individually reasonable. Nobody could reconstruct how you got here, because nobody recorded a single one of them, because they didn’t feel like decisions at the time.

Nothing was ever checked against anything. The tests tested the code. The code was reviewed against itself. At no point did anyone compare what shipped against what was agreed, because there was no artefact stating what was agreed, so the comparison was not available to be done.

And the scope moved without anyone deciding it should. Not through a change request. Through forty small, sensible additions, none of which was the problem, all of which were.

None of that is an engineering failure. You can’t hire your way out of it. Adding developers to a project with no spec is how you get more code embodying more unrecorded decisions, faster, which is not the same thing as progress, though it looks identical from a distance for about four months.

And none of it is new. That’s genuinely the uncomfortable part. Every one of those four failure modes was fully understood before I was born. We just spent twenty years telling ourselves that knowing what you were building was bureaucracy, that the code was the documentation, that we’d moved past all that. And it half worked, because humans quietly patch it. They ask. They hesitate. They come and stand by your desk.

Then we automated the humans out of the loop, and the patch went with them, and now the most modern tool in the industry is sat there demanding the most old-fashioned discipline in it.

That’s not irony. It’s just the bill arriving.

Where to start

Not with a tool. With a file.

Open a markdown file in your repo. Write what you’re building. Write what you’re not building, and why. That one’s separate, and it’s the one that saves you. Write what must never happen. Write how you’d know if it worked.

Then build one slice, and check it against what you wrote. Not the tests, the criteria. Read each one and ask what proves it.

You’ll find something. Everyone finds something. That’s not a failure of your team; it’s the first evidence you’ve ever had about a question you’ve been answering with vibes.

The action pack that goes with this post has the templates for all of it, eleven of them, with worked examples carrying the same feature the whole way through, including the login one above, drift and all. It’s free, it’s ungated, and it’s markdown, because that’s all this ever needed to be.

If you want the detail, the six posts after this one go through the loop properly:

  • Forming the Spec: how to interrogate a request into a specification, and why “the client said X” isn’t a requirement.
  • Decomposing It: turning a spec into work that can be independently verified.
  • Building Without Drift: the gates, and why “I also added…” is a failure.
  • Proving It: tests that verify agreements rather than exercise lines.
  • The Audit: the ninety-minute exercise above, in full.
  • The Untold Truth: including the part where the tooling you were about to install is a genuine security problem.

Start with the file. You’ll know within a fortnight whether it’s working, which is a fortnight faster than you found out last time.

The action pack

Eleven blank templates, eleven worked examples carrying one login feature the whole way through, and six portable agent skills. Thirty markdown files, nothing to install, no email address required. Unzip it into your repo and start.

Download the pack Read how to use it

ZIP, 65 KB. Markdown only, so you can read every file before you run anything.