Spec-Driven Development¶
Spec-driven development (SDD) is a workflow where a structured written specification is agreed upon before any code is written. The spec acts as the single source of truth — agents plan, implement, and verify against it rather than interpreting a freeform prompt.
fuseraft supports SDD via the --spec flag on fuseraft run.
The problem --spec solves¶
Without a spec, the Planner synthesises brief.json from whatever you typed as the task. For short, well-scoped tasks this works well. For larger features — new APIs, multi-file refactors, greenfield modules — the Planner's interpretation can drift from your intent before a single line of code is written.
--spec gives you a place to write down the design before handing it to agents. The spec anchors brief.json, and brief.json anchors every validator. Nothing can be declared complete unless it satisfies the spec.
How it works¶
When you pass --spec path/to/spec.md:
- System-prompt injection — the spec is injected into every agent's system prompt as a
## Project Spec (authoritative)block. All agents — Planner, Developer, Reviewer — see it throughout the session, including after context compaction. - Task injection — the spec is appended to the task at turn 0 as a fenced block under
--- SPEC (authoritative ...). The Planner sees it as the mission statement. - Default task — if you supply
--specwith no task argument, the task defaults to"Implement the specification."so you never have to repeat yourself. - brief.json derivation — the Planner is instructed to derive
brief.jsondirectly from the spec.acceptance_criteriaandfiles_to_changeinbrief.jsonmust reflect what the spec describes.
Resuming a session (--resume) ignores --spec — the spec is already in the conversation history and system prompts.
Spec file format¶
The spec file can be Markdown, plain text, or JSON. There is no required schema — write what is useful for your task.
A useful spec for a software feature typically covers:
- Goal — one paragraph on what is being built and why
- User journeys — the paths a user or caller will take through the feature
- Acceptance criteria — testable statements of correctness (these map directly to
brief.json'sacceptance_criteria) - Files to change — the source files the implementation will touch (maps to
brief.json'sfiles_to_change) - Constraints — what the implementation must not do (tech stack limits, backward compatibility, performance bounds)
- Out of scope — explicit exclusions to prevent scope creep
Minimal example — spec.md¶
## Goal
Add a `/health` endpoint to the Go API server that returns the current service
status and uptime. Used by the load balancer health check.
## Acceptance criteria
- `GET /health` returns HTTP 200 with `{"status":"ok","uptime_seconds":<n>}`
- `uptime_seconds` increases between requests
- Endpoint is reachable without authentication
## Files to change
- `internal/api/routes.go` — register the `/health` route
- `internal/api/health.go` — handler implementation
- `internal/api/health_test.go` — unit tests
## Constraints
- No new dependencies
- Response time < 5 ms under normal load
Structured example — spec.json¶
{
"goal": "Add a /health endpoint to the Go API server",
"acceptance_criteria": [
"GET /health returns 200 with {\"status\":\"ok\",\"uptime_seconds\":<n>}",
"uptime_seconds increases between calls",
"Endpoint is reachable without auth"
],
"files_to_change": [
"internal/api/routes.go",
"internal/api/health.go",
"internal/api/health_test.go"
],
"constraints": [
"No new dependencies",
"Response time < 5 ms"
]
}
JSON specs work especially well when you want to feed structured data to the Planner without any prose.
Three levels of SDD¶
| Level | What you write | What agents write | When to use |
|---|---|---|---|
| Spec-first | Spec file (then discard it after the session) | brief.json + all code |
One-shot features where the spec is a convenience, not a long-term artifact |
| Spec-anchored | Spec file committed to the repo | brief.json + all code |
Features you will evolve — check the spec into version control alongside the code |
| Spec-as-source | Spec file only (you never edit code directly) | Everything | Full AI delegation — humans own the spec, agents own the implementation |
fuseraft's --spec flag supports all three levels. The difference is whether you commit the spec file and how you treat it when the feature changes.
Relationship to brief.json¶
brief.json is fuseraft's machine-validated execution contract:
spec.md |
brief.json |
|
|---|---|---|
| Written by | You (the human) | Planner agent |
| Read by | All agents (via system prompt) | Validators, Reviewer, Compactor |
| Format | Any — prose, Markdown, JSON | Structured JSON |
| Scope | Design intent, user journeys, constraints | Precise file list, testable criteria |
| Lives in | Anywhere on disk | .fuseraft/artifacts/sessions/<id>/brief.json |
With --spec, the Planner is instructed to derive brief.json from the spec rather than synthesising it from the task prompt. The spec drives the plan; the plan drives the implementation; validators enforce the plan.
Combining --spec with other flags¶
--spec composes with all other flags:
# Spec + human-in-the-loop so you can review the Planner's brief before implementation
fuseraft run --spec spec.md --hitl
# Spec + context files for supplementary reference material
fuseraft run --spec spec.md --context-file openapi.yaml --context-file schema.sql
# Spec + custom config for a specialised agent team
fuseraft run --spec spec.md -c configs/dev-team.yaml
# Spec + task override (use when the spec covers multiple features and you want one now)
fuseraft run --spec spec.md "Implement only the /health endpoint for now"
# Spec + CI mode — exits 2 if any acceptance criterion fails
fuseraft run --spec spec.md --ci
--spec differs from --context-file:
- Context files are supplementary reference material appended to the task and read from disk by agents when needed.
- The spec is framed as authoritative: all agents are instructed to treat it as the single source of truth, and
brief.jsonmust derive from it.
Quick start¶
- Write a
spec.mdin your project directory. - Run
fuseraft run --spec spec.md. - The Planner reads the spec and writes
brief.jsonwith criteria and files derived from it. - Validators block handoffs until the implementation matches the brief.
- Commit
spec.mdalongside your code if you want spec-anchored SDD.