Bugs in Spec Driven Development
Spec Driven Development is compelling for new features — write the spec, derive the implementation, keep the two in sync. Then a bug surfaces, and the workflow hits a wall. Where does it go? A ticket in the bug tracker? A message in chat? A comment in the code?
The reason is that the SDD literature has focused on greenfield features. Bug handling has been left to community extensions or pushed outside the methodology entirely — into a separate tool with its own conventions.
A Bug Is a Gap at One of Three Tiers
The insight that changes everything is simple: a bug is not a standalone event. It is evidence that a requirement somewhere is missing, ambiguous, or unmet. The “somewhere” has structure — three tiers, ordered by scope:
- Rules are cross-cutting requirements that apply across many features — security controls, performance budgets, observability commitments, accessibility minimums. A rule is written once and cited by every spec that depends on it.
- Specs describe one feature broadly — its behavior, its acceptance criteria, its constraints.
- Scenarios are situational — specific conditions with concrete behavior, attached to the spec they elaborate.
Every bug exposes a gap at one of these tiers. The fix lands at the same tier as the gap.
The Decision Tree
Before opening a ticket, ask which tier has the gap. The first matching condition determines the route:
- No rule covers this cross-cutting concern — a performance regression, an observability blind spot, a security gap visible across endpoints. Promote a new or amended rule at the rule tier, then fix the code.
- No spec exists for the behavior — the bug is a feature-level gap. Write the spec first, then fix the code.
- The spec exists but is ambiguous — the spec is incomplete. Correct or enhance it, then fix the implementation to match.
- The spec is clear and the implementation is wrong — add a scenario capturing the correct behavior, then fix the code to satisfy it.
In all four cases, the artifact at the right tier becomes more precise. This is the compounding value that issue trackers struggle to deliver: closed tickets bury knowledge; the rule, spec, or scenario captures it permanently.
Scenarios
At the scenario tier, the fix adds a concrete description of behavior in a particular situation, attached to the spec it elaborates. Whether the spec was silent on the situation or the implementation drifted from a clear spec, the scenario captures the case permanently.
The directory layout makes the relationship visible:
specs/
security-backend.md ← rule file (cross-cutting)
001-user-auth/
spec.md
scenarios/
token-expiry.md
invalid-credentials.md
002-checkout/
spec.md
scenarios/
rounding-error.md
spec.md stays high-level — the authoritative description of what a feature does. Scenarios live alongside it, each one capturing the specifics of a particular situation. The scenario file for a bug that was just fixed tells the whole story: what situation triggered it, what the correct behavior is, and what edge cases surround it.
A scenario uses the same conventions as a spec, just at narrower scope. In skeleton form:
---
title: "{NNN-feature-name} — scenario: {slug}"
spec-ref: "{NNN-feature-name} — {Section}"
tags: []
---
# Scenario Name
## Context
The specific situation or precondition.
## Behavior
What the system does in this situation.
## Edge Cases
Boundary conditions and exceptions. Optional — remove if none apply.
## Open Questions
Uncertainties still being worked through.
- ...
## Resolved Questions
Answered questions, preserved with their reasoning.
- ...
No Given/When/Then syntax required. No separate methodology to learn. A scenario is a spec at a lower level of abstraction — same discipline, same source of truth.
Rules
At the rule tier, the fix is a citable requirement that any spec touching the area can reference. A rule belongs at this tier when its verification can be expressed as a step a reviewer or validation tool can check.
In skeleton form:
### {RULE-ID}
> A single RFC 2119 sentence (MUST, MUST NOT, SHOULD, SHOULD NOT).
**Rationale:** The threat or risk the rule mitigates.
**Verification:** A step a reviewer or validation tool can check against feature artifacts.
**Source:** External authority (optional — e.g., OWASP, RFC, internal standard).
Rule files ship at the root of the spec tree and are referenced from feature specs by ID. When validation runs, each rule’s verification step is checked against the feature artifacts that cite it.
Cross-cutting concerns are easy to scatter — a performance budget added to one spec as an acceptance criterion, then re-derived for the next feature, then forgotten for the third. The rule tier is the antidote: written once, cited everywhere it applies, enforced by validation.
What This Means for Bug Files
If the rule, spec, or scenario absorbs the knowledge, what is a bug file — a standalone document describing a defect, its reproduction steps, its fix — actually for? In most cases, nothing. The artifact at the right tier captures the correct behavior. The git history on that file records when it was added and why. A descriptive commit message covers the rest.
A bug file only earns its place when the root cause or reproduction context is complex enough that losing it would be costly — a subtle race condition, a dependency on a third-party service, a class of inputs that are genuinely hard to reason about. Even then, the bar should be high. If the information belongs in a rule, spec, or scenario, that is where it should live.
Replacing the Bug Tracker
Bug trackers exist because teams need somewhere to put work that isn’t code. But if every bug refines a rule, a spec, or a scenario, the spec repository becomes the complete record of system behavior and the problems that refined it. Nothing lives in a separate tool. Nothing gets buried in a closed ticket.
The one concession for brownfield projects is a temporary inbox.md at the root of the spec tree — a flat list of known issues that haven’t been assigned to a feature spec yet. As specs get written for each area of the system, items migrate from the inbox into their proper home. The goal is for that file to eventually disappear.
The Discipline That Makes It Work
None of this functions without one principle: no work begins without a written requirement to satisfy. Not a bug fix, not a refactor, not a hotfix under pressure. The artifact at the right tier always comes first.
This is the discipline that separates SDD from documentation theater. When the rule, spec, and scenario tiers are genuinely the source of truth — when implementation is derived from them, and bugs flow back into them — the system gets more precise over time rather than more fragile. Every bug that surfaces sharpens the artifact at the right tier. Every rule, spec, or scenario added narrows the space where the next bug can hide.
Spec-driven development is gaining traction as the workflow for the AI-assisted era. But the conversation has been almost entirely about greenfield features, and the rule tier — the place where cross-cutting requirements actually belong — is under-developed. The teams that figure out how to handle bugs with the same rigor across all three tiers will end up with something much more powerful: a living specification that is also a complete history of everything the system learned.