Articles
Spec-Driven Development: write the contract before the agent writes the code
Prompt-driven coding dies with the chat. Specs survive: SHALL requirements, acceptance tests, and regeneration prompts so another agent can rebuild the same product. Here is how we run SDD on Analytica Copilot.

Coding agents are fast. They are also forgetful. A Saturday chat that produced a dashboard is gone by Monday — and the next agent has no idea what “done” meant, which SQL was forbidden, or why APAC decline is the demo story. Spec-Driven Development (SDD) exists so the contract outlives the session.
Loading diagram…
Prompt vs spec
Vibe coding feels productive because the agent is always moving. The cost shows up later: silent architecture drift, untestable “almost” behaviour, and a product that only the original chat could recreate. A spec is slower to start and cheaper to continue.
Loading diagram…
- Prompt: “Make an analytics copilot that answers questions.”
- Spec: the agent SHALL generate a QueryPlan; SHALL NOT execute arbitrary SQL; SHALL return answer, evidence, visualisation, and the plan itself.
- Prompt dies with the tab. Spec is git-versioned, reviewable, and reusable by the next agent.
- Prompt hopes the model remembers constraints. Spec makes constraints executable via tests and runtime traces.
The loop we actually run
On Analytica Copilot (the SDD Analytics Copilot demo behind https://analytica-demo.suherman.net) every major capability is numbered SDD-001 … SDD-013. The tree is the authority — not a README written after the UI looked nice.
- 01Product vision, personas, and the Bahasa demo journey.
- 02SHALL requirements SDD-001 … SDD-013 (workspace, dataset, copilot, governance, dashboards, tenancy, locale, ops).
- 03Domain, OpenAPI, and agent-tool contracts — QueryPlan, semantic model, dashboard DSL.
- 04Implementation in src/ against those contracts.
- 05Acceptance tests + Gherkin. Then runtime traces in the product UI (Jejak).
Traceability is the point. If a behaviour exists in the UI, you should be able to point at a requirement ID, a contract, a test, and a runtime trace. If you cannot, it is not specified — it is a prototype accident.
A concrete spec: SDD-004
Conversational analytics is the hero flow: “Why did revenue drop last month?” The spec does not say “use an LLM to query the database.” It freezes the safety rails first.
# SDD-004 Conversational Analytics
The system SHALL allow a user to ask an analytical
question using natural language.
The agent SHALL resolve metrics against the semantic model.
The agent SHALL generate a QueryPlan.
The agent SHALL NOT directly execute arbitrary SQL.
The engine SHALL validate the QueryPlan before execution.
The system SHALL return:
answer, result data, evidence,
visualisation recommendation, QueryPlan.Acceptance is Gherkin, not a vibe check. One scenario from the same file:
Scenario: Ask for monthly revenue
Given the commerce semantic model is loaded
And the SQLite demo database contains order data
When the user asks "What was revenue last month?"
Then the agent resolves the "revenue" metric
And creates a governed QueryPlan
And the analytics engine executes the query
And the answer contains the resulting revenue
And the evidence shows the metric definition
And the execution trace is persistedLoading diagram…
Governance is the product
Without SDD, an analytics agent will eventually emit SQL. That is convenient in a demo and unacceptable in a tenant. QueryPlan is the contract: the model proposes a plan, the engine validates it against the semantic model, then compiles SQL. The LLM never talks to SQLite directly. That rule lives in SDD-004, SDD-005, and the ADRs — so a regeneration agent cannot “helpfully” skip it.
Specs as a regeneration kit
The strongest SDD test is uncomfortable: delete src/, keep specs/, and ask a coding agent to rebuild. Analytica Copilot is written so that is possible. specs/regeneration/ holds the blueprint and copy-paste prompts. Non-negotiable invariants sit at the top: no arbitrary SQL, dashboards are JSON specs (not generated React trees), Next.js monolith + SQLite, demo clock 2026-09-05, soft multi-tenancy, Bahasa Indonesia UI.
Loading diagram…
How to start in your own repo
You do not need thirteen requirements on day one. You need numbered contracts that a later agent cannot shrug off.
- Give every behaviour an ID (PROJ-001 …). One file per ID under specs/requirements/.
- Write SHALL and SHALL NOT in the same file. Constraints belong next to the feature, not in a Slack thread.
- Add one Gherkin scenario that would fail if the agent “just shipped UI”.
- Freeze contracts the model must obey: OpenAPI, tool schemas, semantic metrics, ADRs.
- Point the coding agent at the spec ID — not at a paragraph in chat. Implementation is a diff against the contract.
- Keep a regeneration prompt beside the specs. If src/ vanished tomorrow, that prompt is the bootstrap.
What SDD is not
- Not waterfall. Specs stay small, numbered, and revisable. We approve them; we do not freeze a 40-page novel.
- Not “write docs after the demo.” If the spec is updated to match the code, the code won. Flip that.
- Not a substitute for human merge. Agents prepare; people still decide FINAL_REVIEW. That is the same rail as Agent On Rails.
Where this lives on suherman.net
We already used this loop live in the sharing session with SDD Analitik Kopilot: natural-language question → governed QueryPlan → evidence → dashboard. The same specs are what a coding agent reads when regenerating the app.
- Live prototype: https://analytica-demo.suherman.net
- Product site: https://analytica.suherman.net
- Reference repo: https://github.com/iman-suherman/sdd-analytics-copilot
- Specs index: specs/README.md in that repo (SDD-001 … SDD-013).
- Microsoft Spec Kit (background reading): https://developer.microsoft.com/blog/spec-driven-development-spec-kit/
- Related article: https://suherman.net/articles/agent-on-rails-escalation-watchdog
Bottom line: Spec-Driven Development is how you keep coding agents on rails without babysitting every prompt. Write the contract first. Let the agent implement. Keep tests and traces as proof. When the chat is gone, the spec is still there — and that is the only artefact another agent, or another Saturday, can trust.
