Spec-driven development: When the spec becomes the product
AI can already write code. The bigger shift is what happens when code stops being the primary artefact of software development.
AI writing code is no longer the interesting part. We already have coding agents that can generate components, implement APIs, fix bugs, write tests, refactor code, and open pull requests. Give a capable model enough context and enough tools, and it can produce an extraordinary amount of software.
That creates a strange problem: If code becomes dramatically cheaper to produce, what becomes expensive? The answer, I think, is intent.
What exactly are we trying to build? For whom? Under which regulatory constraints? Which business rules are immutable? Which design patterns should be reused? What should happen across web, mobile, and backend systems? How do we know that what eventually ships still matches the product decision that started the process?
These questions have always existed. AI simply makes it impossible to hide from them.
When implementation was expensive, code was naturally the centre of gravity. Product requirements, design files, tickets, documentation, and meetings all orbited the implementation.
In an AI-native engineering system, I think that relationship needs to reverse: The spec becomes the product. The code becomes one generated representation of it. That distinction changes almost everything about how software can be built.
The bottleneck moved
The conventional story about AI coding is productivity. An engineer used to spend four hours implementing something. Now an agent can do it in forty minutes. Therefore, the engineer is ten times more productive.
That is useful, but it still treats the development process as though typing code were its fundamental constraint. It isn’t.
The more code generation improves, the more visible the real bottlenecks become: waiting, coordination, ambiguity, review, hand-offs, and context reconstruction.
A feature might begin in a conversation. Someone turns it into a ticket. Another person produces a design. An engineer interprets both. A second engineer needs a backend change. A reviewer tries to reconstruct the original intent from the implementation. QA compares the result with whatever requirements they can find. Compliance checks another document. Weeks later, everyone is arguing about whether a discrepancy is a bug, a design change, or an outdated requirement.
The cost is the queue, not the typing. That is the problem we are trying to tackle. Our model is to turn software development into something closer to an automated production line. A human defines and approves what should exist. From there, the system plans, builds, verifies, and tests it through standardised stages before another human decides whether it should reach production.
The aim is not for AI to write more code. It is much closer to: Describe the product change precisely. Let the system propagate it everywhere it needs to go.
Start with one living product specification
For this to work, the specification cannot be a document that someone writes before development and then forgets about. It has to remain alive.
Our model uses one versioned product specification as the source of truth. A new feature is expressed as a delta to that specification: what is being added, modified, or removed, alongside the proposal, design, and tasks required to implement it. Once the change ships, that delta folds back into the living spec.
That sounds like a documentation change. It is actually an architectural one. Consider the normal lifecycle of a feature: You have a current product. You want to add capability X. Traditionally, we create a requirement somewhere that says “add X”, build some code and then leave both the old documentation and new code behind.
Over time, the documentation describes an approximation of the product while the code describes the actual product. Now repeat that hundreds of times. Drift is inevitable.
A spec-delta model works differently. Instead of saying, “Here is a ticket describing a feature we want,” you are effectively saying: “Here is the precise change to our product definition.” That difference matters because a delta has a known base.
If a product currently accepts A and B and the proposed change adds C, we can reason about exactly what C changes. The system can inspect dependencies, identify affected surfaces, detect contradictory rules, and calculate the blast radius before implementation begins.
The specification is not a prelude to the implementation. Rather, it’s what’s being changed.
Every feature becomes a delta
Suppose the business wants to introduce a new product capability across the website and app.
That capability might affect positioning on the public website, onboarding inside the authenticated product, one or more API contracts, analytics events, regulatory wording, design-system components, and localisation.
The naïve AI approach is to tell an agent: “Add this feature.” The model then explores the codebase and makes its best interpretation. That works surprisingly well right up until it doesn’t. The problem is that the codebase contains history, not necessarily intent.
Legacy code may encode deprecated decisions. An existing page may contain outdated copy. A hardcoded value might be historical rather than authoritative. Two implementations may contradict each other. The model has no intrinsic way to know which artefact deserves trust.
This is why the hierarchy of context matters.
In our proposed architecture, business specifications, regulatory rules, brand and design-system context, personas, positioning, and the technical golden path are explicit inputs. Existing software remains useful as context, but it is not automatically treated as authority.
That is a subtle but important distinction for AI engineers. The largest context window in the world does not solve the problem of authority. Giving an agent more information is not the same thing as telling it which information is true.
From feature request to product change
Once intent is represented structurally, other parts of the development lifecycle can become surprisingly mechanical.
Requests may originate in different places. Someone reports a bug in Slack. A product manager proposes an enhancement. An engineer spots technical debt. A feature is approved during product planning. The origin should not determine the production workflow. The intake needs to converge.
In the system we are building towards, work becomes a tracked issue, and the approved product change enters the automated development line in a standard form. That line then moves through planning, automated plan review, implementation, verification, quality checks, and deployment.
One input shape is important because agents are significantly easier to reason about when their contracts are constrained. If every workflow begins differently, orchestration becomes prompt engineering. If every workflow begins with the same versioned artefacts, orchestration becomes infrastructure.
That is where this starts to look less like “using an AI assistant” and more like an engineering system.
The issue is the delta. The tasks are pull requests.
This also changes the role of familiar development objects. An issue no longer needs to be a vaguely worded reminder that somebody should build something. It can represent an approved change to product intent.
The system can then decompose that change into implementation tasks based on the surfaces affected.
A single feature might require work in a web repository, a mobile repository, and an API repository. Those are not three independent interpretations of the feature. They are three implementations of the same approved delta. The pull requests become execution units.
This gives us a very different traceability chain:
Product intent → spec delta → tracked issue → implementation tasks → pull requests → verification → deployed artefact.
That chain is valuable for any engineering organisation. For a regulated organisation, it becomes much more valuable.
Instead of asking, “Why is this code here?”, you can move backwards from an implementation to the exact product decision that authorised it. Instead of asking, “Did we remember to update the app too?”, the spec can tell the planner which surfaces must change. And instead of relying on somebody to update documentation after shipping, the accepted delta becomes part of the canonical product definition.
Three agents should not behave like one agent
Once a spec is approved, we currently model the automated work using three principal roles: Planner, Builder, and Verifier. The separation matters more than the names.
The Planner takes the approved delta and decomposes it into implementation work. It decides dependency order and identifies cross-repository contracts.
The Builder executes that plan. It writes code, tests the implementation, and creates the relevant pull requests.
The Verifier does something deliberately different. It independently reconstructs what the product should do from the approved specification, then compares that interpretation with what was actually built.
Why not simply let the Builder check its own work? Because generation and verification are different reasoning problems.
If the same context, assumptions, and conversation lead an agent to an incorrect implementation, asking the same agent to review the implementation can reproduce the same mistake.
The source design therefore treats isolation as a feature. Planner and Builder can share business context, but not the same session. The independent Verifier should not inherit the delivery pair’s working assumptions.
This is one of the areas where agent architecture starts to resemble mature human engineering practice. We separate authorship from approval because independence improves the quality of judgement. AI systems should not be exempt from that principle.
Verification is not the same as testing
There is another distinction worth making. A test asks whether the implementation behaves according to some expected behaviour encoded in the test. Verification asks whether we built the right thing. Those sound similar until the wrong assumption exists in both the implementation and its tests.
Imagine a specification says a certain flow requires three steps. The Builder misunderstands it as two steps and generates tests for the two-step flow. The tests pass. Coverage might be excellent. The product is still wrong.
An independent feature verifier should therefore start from intent, not from the implementation’s own interpretation of intent. Its job is to ask:
What did the approved spec require?
What did the system build?
Where do they differ?
This is product drift detection, not merely code review.
After that, conventional quality controls still matter. Security review, accessibility checks, automated tests, performance validation, and other guardrails operate on the implementation. The proposed system explicitly keeps both verification and quality automation rather than pretending one replaces the other.
Humans should own decisions, not mechanics
At this point, an obvious question appears. If the system can plan, implement, review, test, and deploy software, where should people sit? Our answer is deliberately narrow.
There are two human gates:
The first is approval of intent. Before implementation begins, a person must approve the specification change. AI can help draft, critique, and refine the proposal, but it should not unilaterally decide what the product promises.
The second is production deployment. The automated system can prepare, test, and stage the release, but putting that change into production remains an accountable human decision in the model we are designing.
Everything between those gates is a candidate for automation. That is a much more useful division of labour than simply asking where AI should “assist” a developer.
Humans provide direction. Machines perform mechanics. Humans decide whether the mechanics produced something worthy of release. It is not zero-human software engineering. It is concentrated-human software engineering.
The product team also changes
There is a second-order consequence here. If implementation gets cheaper but specification quality becomes more important, the value of precise product thinking increases dramatically.
Ambiguous requirements used to produce meetings. With an autonomous pipeline, ambiguous requirements can produce software. Very quickly. That makes ambiguity more dangerous, not less.
An AI-native product organisation therefore needs stronger ways to encode decisions about users, positioning, jurisdiction, constraints, behaviour, and design.
This is also why I don’t think “better prompts” are the destination. A prompt is usually transient. A product specification is persistent. A prompt may describe today’s task. A spec describes what the organisation believes the product is.
The more autonomy we give the development system, the less we should depend on instructions that exist only inside a conversation.
Skills become part of the engineering platform
Specifications capture what should exist. The system also needs to know how the organisation builds things. That knowledge should not live only inside engineers’ heads or in an enormous global prompt. It can be encoded as reusable skills.
A design-system component, for example, can ship with guidance describing when to use it, how to compose it, and what constraints apply. Technical repositories can expose their own patterns. Organisational rules can be packaged as machine-readable context. The source architecture explicitly treats component usage guides as skills alongside Figma Code Connect and the underlying component packages.
That creates an interesting hierarchy:
The spec says what to build.
Skills explain how this organisation builds.
Tools provide the capabilities required to do it.
The agent performs the reasoning that connects them.
The generated code is the result.
This is why I increasingly think the durable assets in AI software engineering will look different from the durable assets of the previous era.
Code obviously still matters. Production executes code, not markdown.
But if code can be regenerated more cheaply than the knowledge required to specify it correctly, then the strategic value starts moving upstream.
Code becomes more disposable
“Disposable code” sounds provocative, so it is worth being precise. It does not mean low-quality code. It does not mean architecture no longer matters. And it certainly does not mean we should generate arbitrary software and hope tests catch the damage. It means code no longer has to be the only durable representation of a software product.
If the complete product intent, constraints, behavioural rules, design system, and engineering standards are represented independently, implementation becomes more reproducible.
Change the model.
Change the framework.
Change the execution agent.
The canonical definition of the product can remain.
That gives engineering teams an escape route from a problem we have accepted for decades: knowledge becoming trapped inside implementation.
One product, many surfaces
This becomes especially useful when products span multiple technical surfaces. A customer does not experience “the website repository” and “the mobile repository” as separate products. They experience one company. Yet organisationally, we often allow each repository to accumulate its own interpretation of product behaviour.
A spec-first approach lets multiple repositories inherit intent from a shared product definition while remaining independently deployable. The source architecture deliberately uses separate generated repositories for web, app, and other surfaces while allowing one OpenSpec project to span them. That provides a useful separation:
Product truth is shared.
Implementation remains modular.
Deployment remains independent.
Regulatory and technical boundaries can remain explicit.
You do not have to choose between a monorepo and product consistency. The consistency can sit above the repository layer.
We should stop shipping features
The language we use matters because it shapes how we design systems. For years, software organisations have talked about shipping features. That made sense when the feature’s implementation was the centre of the work.
I think a better mental model for AI-native development is that we continually edit one product.
The feature is simply the delta.
The repository is simply one place where that delta materialises.
The pull request is simply one unit of execution.
The AI agent is simply one worker on the line.
The code is simply one artefact produced by the process.
The thing we actually own is the product definition.
Once you see software development this way, the AI question changes. It stops being: “How much code can an AI engineer write?” It becomes: “How much of the path from approved intent to verified production software can we make deterministic, observable, and safe?” That is a much harder problem. It is also a much more interesting one. And that is the system we are trying to build.
This article is part of a series on building an AI-native product development system where specifications define intent and autonomous agents handle the path from approved change to verified implementation.
Next: how the automated development lifecycle actually works, including agent isolation, GitHub Actions orchestration, independent verification, quality gates, and the boundary between deterministic infrastructure and non-deterministic generation.
Raunak Kathuria is a VP of Engineering at Deriv and co-leads the department of Security and Product Engineering.
Follow our official LinkedIn page for company updates and upcoming events.













