Article
Why I’m moving to Spec-Driven Development (and what finally convinced me)

Part 1 of 2 — Part 2 covers a hands-on OpenSpec demo, from init to your first delta.
The weekend the model picker got shorter
On the evening of June 12, 2026, at 5:21pm ET, Anthropic received a US government export-control directive. The order required the company to suspend access to its two newest and most capable models — Claude Fable 5 and Claude Mythos 5 — for any foreign national, whether they were outside the United States or sitting inside it, including Anthropic’s own non-US employees.
Because Anthropic had no way to verify nationality at the API or product layer in real time, the only compliant move was the blunt one: disable both models, for everyone, worldwide, with no warning and no migration window. Fable 5 had shipped to the general public days earlier. Mythos 5 — the same underlying model without the public-facing safety classifiers — had gone out to a small set of vetted partners. Both vanished from the model picker over a weekend.
I’m not going to relitigate the national-security reasoning here. Fable 5 and Mythos 5 had only been out a few days, so realistically nobody had production logic riding on them yet. But swap the scenario: imagine Anthropic (or GitHub) triples token pricing for Claude Code or Copilot overnight, and your team needs to switch tools by Monday. What actually moves with you — and what’s stuck inside the old tool’s prompts, custom instructions, and “the agent just knows to do X” habits?
That’s the real question: if your product’s logic only exists as an emergent property of one tool’s behaviour, you don’t own that logic. You’re renting it — and the landlord can change the price, or the locks, with a few hours’ notice.
It’s also the moment I stopped treating “spec-driven development” as a nice-to-have process tweak and started actually adopting it — not because the framework changed that weekend, but because it was the clearest demonstration I’d seen of why it exists. Here’s what changed in how I work, and why OpenSpec specifically is the framework I landed on to keep engineering intent durable, transparent, and portable — independent of whichever model happens to be available this month.
Takeaway 1 — The bottleneck moved from writing syntax to defining intent
A line from the spec-driven development community has been doing the rounds, and it’s worth sitting with:
“The engineering bottleneck has shifted from writing syntax to defining intent.”
A year or two ago, this would have sounded like motivational poster filler. Today it’s closer to an operational fact. Coding agents can produce thousands of lines of working syntax in seconds — the bottleneck on most teams I talk to is no longer “can we write this,” it’s “do we actually agree on what this is.”
That changes what a senior engineer’s time is worth. The valuable skill isn’t typing out a function anymore — it’s describing, precisely enough that an agent can execute without guessing, what that function has to do, including the edge cases nobody wants to think about on a Friday afternoon. Three things follow from that:
- Design over syntax. Success is measured by how unambiguous the instruction was, not by how many lines of code came out the other end.
- Systems thinking over boilerplate. Engineers spend their attention on architecture, constraints, and failure modes — the things that don’t show up in autocomplete.
- Staying the architect. When you define intent precisely, the agent stays a very fast builder. When you don’t, the agent quietly becomes the designer, by default, one undocumented decision at a time.
None of this means “stop writing code.” It means the code is increasingly a compiled artifact of a decision that was made somewhere else — and if that decision only lives in a chat transcript, you’ve just created a second, invisible codebase that nobody can read, review, or port.
Takeaway 2 — Paying down the “ambiguity tax”
Here’s the mechanism behind a lot of those “AI didn’t actually save us time” stories.
When a requirement is vague, an agent doesn’t stop and ask — most of the time, it guesses, generates something plausible-looking, and moves on. You read the output, realize it solved a slightly different problem than the one you had, and send it back for another pass. Repeat three or four times and you’ve burned a meaningful amount of compute and review time on a problem that was never about the model’s capability — it was about an unclarified requirement.
The spec-driven development community calls this the ambiguity tax: the accumulated cost of hallucinated assumptions, throwaway generations, and rework, all caused by requirements that were “clear enough” to a human but not to an agent. It’s a real line item — teams that skip a clarification step before kicking off implementation routinely report spending several times more on compute and developer hours than teams that front-load that conversation, simply because they’re paying to “prompt-engineer” their way out of a problem that was underspecified from the start.
Spec-Driven Development’s pitch is almost boringly simple: move the clarification conversation earlier. Before a single token of implementation code gets generated, the team (human and AI) agrees on what “done” looks like, in concrete, checkable terms. That’s not extra process for its own sake — it’s the cheapest debugging you’ll ever do, because you’re debugging a sentence instead of a pull request.
Takeaway 3 — A spec is a behaviour contract, and it outlives the model
It’s tempting to file specifications under “boring documentation nobody reads.” That framing misses what a good spec actually is: a behaviour contract — a precise, checkable description of how the system is supposed to behave under specific conditions, written so both humans and AI agents can act on it.
Frameworks built around this idea (OpenSpec among them) lean on a structure borrowed from Behaviour-Driven Development (BDD) — the familiar Gherkin shape:
- Given — the initial state or context
- When — the triggering action or event
- Then — the observable, expected outcome
This is worth pausing on, because it’s easy to blur two related-but-different things:
- BDD is a testing technique. Its job is to answer “does this behave the way we said it would?” — usually inside the test phase, with tools like Cucumber, SpecFlow, or Behave, in a Given/When/Then format that product, QA, and engineering can all read.
- SDD is a full development methodology. It uses that same Given/When/Then language, but as the input to the AI agent, structuring the entire path from intent to shipped code — proposal → specs → design → tasks.
In other words: BDD is a component inside SDD, not a synonym for it. SDD answers “how do we tell the AI what to build?”; BDD (inside SDD) answers “how do we phrase that description so it’s checkable?”
Why does this distinction matter for the ownership argument? Because a Given/When/Then spec is model-agnostic by construction. It doesn’t reference a prompt template, a system message, or a model’s quirks — it describes business behaviour. Code is ephemeral, and increasingly, so are the agents writing it. The spec corpus is the asset that survives a model change, a pricing change, or — as a lot of teams discovered on June 13th — a regulatory change. If your provider disappears overnight, your specs are still the definitive record of how your business is supposed to behave; you’ve lost the “how,” not the “why.”
Takeaway 4 — “Fluid, not rigid”: OpenSpec vs. the phase-gate approach
Spec-driven development isn’t a single framework — it’s closer to a small family of “dialects” that share the BDD foundation above but differ in how rigidly they sequence the work.
GitHub Spec Kit, one of the frameworks that helped popularize this whole conversation, follows a deliberately sequential cycle:
Constitution → Specify → Clarify → Plan → Tasks → Implement / Iterate
Each stage is effectively a phase gate — “Clarify,” in particular, is a mandatory checkpoint before planning can begin. If your team works in a context where you want an explicit sign-off between “we agree on the spec” and “we start building,” and you’re already deep in the GitHub Copilot ecosystem, that rigidity is a feature, not a bug.
OpenSpec takes a different position, summarized by its own description as “fluid, not rigid.” Its artifacts — Proposal, Specs, Design, Tasks — can be generated and refined in pretty much any order, because the framework assumes (correctly, in my experience) that understanding deepens while you work, not only before you start.
The mechanism that makes this safe is delta-based change tracking: every change to a spec is expressed as ADDED, MODIFIED, or REMOVED sections, rather than a rewrite of the whole document. This sounds like a small implementation detail, but it solves a real problem — most real-world engineering is brownfield: modifying a complex system that already exists, not painting on a blank canvas. Deltas let you make a surgical change to one slice of behaviour without dragging the rest of the spec along for the ride, and they let two people (or two agents) work on different parts of the same spec without stepping on each other's changes, because each delta only captures the intent of its own change.
Neither approach is objectively “better” — they’re optimized for different risk profiles. Spec Kit’s gates suit teams that need an auditable, sequential sign-off trail. OpenSpec’s fluidity suits teams doing continuous, brownfield work across a shared spec corpus, especially with multiple agents involved. What matters is recognizing which one you’re actually running, because the two “feel” very different in day-to-day use even though they share the same Given/When/Then DNA underneath.
How this actually runs day to day
It helps to see the shape of the workflow before Part 2 walks through it command by command.
An OpenSpec project has exactly two folders that matter:
openspec/
├── specs/ ← source of truth: how your system behaves *today*
└── changes/ ← proposed modifications, one folder per change,
each containing its own deltas
specs/ is the agreed, current behaviour — the accumulated result of every change that's been merged so far. changes/ is where work-in-progress lives: each change gets its own folder, with its own proposal.md, delta specs/, design.md, and tasks.md. Nothing in changes/ affects specs/ until it's explicitly merged.
Within a single change, the artifacts follow a loose dependency order — proposal → specs → design → tasks → implement — but it's drawn as a loop, not a line, because OpenSpec expects you to go back and refine earlier artifacts as you learn during implementation. Discover mid-task that a requirement was underspecified? You update the delta spec right there, not in a separate "change request" three weeks later.
Zoomed out, a change moves through three stages:
- Start the change — describe the idea; OpenSpec scaffolds the change folder.
- Create artifacts — proposal, delta specs, design, and tasks get generated based on what the schema says depends on what (this is the step Part 2’s demo focuses on).
- Implement, then merge — work through tasks.md; once done, the change's deltas merge into specs/ and the change folder moves to changes/archive/.
The piece that ties this back to Takeaway 4: because step 2 isn’t a single irreversible gate, and because “merge” is a delta operation rather than a file overwrite, two changes can be in flight against the same area of specs/ without one blocking the other — they just need to merge cleanly, the same way two branches do. That's what "fluid, not rigid" looks like in the file system, not just in the philosophy.
Core vs. Extended: how much of the workflow do you actually need?
The three-stage loop above is the concept. In practice, OpenSpec exposes it through two command profiles, and picking the right one is a five-minute decision that saves a lot of friction later.
Core is the default. It installs five commands:

That’s the loop most changes need: /opsx:propose → review → /opsx:apply → /opsx:archive. For a well-scoped feature or bug fix, this is the whole interaction — one command to get a full planning package, one to build it, one to close it out.
Extended adds finer-grained control by unlocking additional commands on top of Core:

You turn Extended on with openspec config profile (select the extra workflows) and apply it with openspec update.
When Core is enough: a classic feature with a reasonably clear scope, where you’re happy to review the full artifact set after /opsx:propose generates it in one shot, and where exploring before committing (/opsx:explore) covers your "let me think about this first" cases.
When you’ll want Extended:
- You want to review and approve each artifact individually — proposal first, then specs, then design, then tasks — rather than getting all four at once. /opsx:new + /opsx:continue gives you that.
- Several changes are in flight against overlapping parts of the spec, and you need /opsx:bulk-archive to merge them together deliberately rather than one at a time.
- You want a hard checkpoint — /opsx:verify — that confirms the code actually does what the spec says before you let the change merge into specs/ and disappear into archive/.
A reasonable rule of thumb: start on Core. If you find yourself wishing you could pause between “specs look right” and “now generate the design,” or you’re regularly running multiple changes in parallel against the same module, that’s your signal to flip on Extended — it’s additive, not a different framework, so nothing about your existing changes breaks.
Takeaway 5 — Portability is real, but let’s be honest about where the line is
This is the part of the pitch that connects directly back to June 12th.
OpenSpec lets a team move between AI coding agents — say, from Claude Code to Codex, or to any of the two dozen-plus tools it now supports — using openspec update. And the headline claim is true: your specs and your change history are fully portable. They're plain Markdown, they don't reference any vendor's prompt format, and they don't go anywhere when you switch agents.
But — and this is the part worth saying out loud, because overclaiming it is how you lose a client’s trust the first time they actually test it — the integration layer is not automatically portable. Each agent has its own way of “reading” your spec corpus: Claude Code uses a .claude/skills/ and .claude/commands/ layout, Codex uses its own prompt and skill locations, and so on. As of OpenSpec 1.0, this integration layer is generated entirely through the skills system — earlier per-tool config files like CLAUDE.md and AGENTS.md are no longer created by openspec init, and existing ones get cleaned up on upgrade. Some tools — ForgeCode and Trae among them — only support the skills format and don't generate local command files at all.
What that means in practice: switching providers is one command (openspec init --tools <new-tool> or openspec update), not zero commands. The regeneration step is fast and mechanical, but it's a real step, and "100% zero-config portability" is a slightly different (and false) promise from "your intellectual capital survives a provider switch, and re-pointing it at a new agent takes minutes, not weeks."
That distinction is exactly what made the difference on the weekend Fable 5 and Mythos 5 went dark. Teams whose product logic lived in openspec/specs/ could regenerate their integration layer for a different model family and keep moving. Teams whose product logic lived inside a specific model's learned behaviour had no equivalent command to run.
Multi-provider portability earns its keep in at least three recurring situations:
- Token economics shift. A provider changes its pricing, and the cheapest model for your workload is suddenly a different one.
- Sovereign / regulatory requirements. New rules require certain data or logic to be processed by a specific, locally-approved model.
- Forced failover. A government directive, an outage, or a sudden capability regression takes your primary model offline with no notice — as happened, very publicly, in June 2026.
None of these are exotic edge cases anymore. They’re Tuesday.
Ownership vs. rental
The events of June 12–13, 2026 were a very public demonstration of something that’s been quietly true for a while: a lot of organisations had outsourced their product’s reasoning to a single model, and didn’t fully realise it until that model’s access was switched off by a government order, not a technical failure.
Spec-Driven Development — and OpenSpec specifically — isn’t a silver bullet, and it won’t make a regulatory directive any less disruptive. What it does do is draw a clean line between the parts of your system that are genuinely yours (the why and the what, captured as behaviour contracts in openspec/specs/) and the parts that are increasingly commodity (the how, delegated to whichever agent is available and compliant this week).
Build the spec first. The code — and the model that writes it — is the part you were always going to have to replace eventually. Make sure it’s the only part.
In Part 2, I’ll walk through what this actually looks like day to day: initializing an OpenSpec repo for two agents at once, writing a first proposal, and watching it turn into specs, a design doc, and a task list — all from the terminal.
Sources :
- Spec-Driven Development | Specifications for the AI Era
- GitHub - Fission-AI/OpenSpec: Spec-driven development (SDD) for AI coding assistants.
- Spec-Driven Development
I’m Camille Lebrun, a Data Consultant. I write about AI and data engineering.
Found this useful? Clap on Medium to help other analytics engineers find it. What’s the most misleading aggregation you’ve seen shipped to a stakeholder? Drop it in the comments.