What does Spec-Driven Development Loop (SDDL) do?
Open Source: https://github.com/xt-mahh/sddl (2026-08-06, MIT License) Full methodology + checker scripts + example projects available in the GitHub repository.
Overview
SDDL upgrades AI programming from 'conversation-driven' to 'spec-driven'. Core commitment: First define clearly what to do, then write code — using a structured Spec as the single source of truth, with a dual loop closure ensuring quality and auditability.
Formation Loop (answers 'what to do') Derivation Loop (answers 'how to do it right')
Requirements ──▶ Interview ──▶ Spec Draft ──▶ Freeze Spec ──▶ tests/code/docs ──▶ Converge
└─▶ SQC Quality Check ──┘ └─▶ C1-C4 Consistency Checks ──┘
└─▶ Decision Point Confirmation ──┘
Why SDDL: The pain points of conversational programming — context drift (forgetting agreements made 50 turns ago), multiple artifact desynchronization (code changes without test/doc updates), and subjective acceptance ('feels right' instead of 'meets spec'). SDDL solves these with a stable, fully loadable Spec + layered consistency checks.
When to Use
Triggers:
- User wants to start a new project development, write core features, or design system architecture
- User says 'let's plan', 'let's design', 'let's write a spec', 'how to implement this feature'
- Tasks requiring multiple synchronized artifacts (code + tests + docs)
- Project with ≥ 5 interfaces, or ≥ 5 must-level acceptance criteria, expected lifespan > 2 weeks
Not applicable (write code directly, do not use this skill):
- One-off scripts / prototypes / proofs of concept / exploratory research code
- Single-file utilities (< 5 interfaces, no multi-artifact requirement)
- User explicitly says 'just code it' or 'do it quickly'
Phase Commands (core interaction method of this skill):
| Command | Phase | Action | Output |
|---|---|---|---|
/sddl:init | Initialization | Create directory structure, read existing code/requirements | sddl/ skeleton + state.yaml |
/sddl:interview | Formation | Layered requirements interview (L0-L2 required) | Requirements statement |
/sddl:spec | Formation | Generate L1-L5 spec draft + decision point markers | specs/<domain>/spec.yaml |
/sddl:confirm | Formation | Decision point summary + clarify confirmation | decisions/<domain>-confirmation.yaml |
/sddl:freeze | Formation | SQC check + freeze | spec_status: frozen |
/sddl:derive | Derivation | Derive tests/code/docs from spec | src/ tests/ docs/ |
/sddl:verify | Derivation | C1-C4 consistency checks + convergence evaluation | checks/*.json + convergence/routing |
/sddl:archive | Archive | Change archiving, spec merge | specs/ update + CHANGELOG |
Core Principles
- Spec is the oracle, but can be challenged: Spec defects found during derivation → unfreeze → return to Formation Loop for revision → refreeze (full quality gate, no shortcuts)
- Determinism first: If static analysis/schema/test execution can solve it, never rely on LLM guessing
- Convergence is an engineering system: Hard condition gates + Soft condition consensus rate + Budget constraints + Human override
- Decision points are not silent: AI provides defaults for ambiguities + marks decision points, user confirms before freezing
- Progress is in the directory: Phase completion = file existence (Convention over Config), free interruption recovery
Directory as State (Convention over Config)
No need to read a state file; the directory shows progress. This is the progress visibility mechanism of this skill (with git commits as checkpoints).
<project>/
├── sddl/
│ ├── specs/ # Exists = interview complete, spec generated
│ │ └── <domain>/spec.yaml # status: frozen = freeze complete
│ ├── changes/ # Change proposals (incremental development, can be parallel)
│ ├── decisions/ # Decision point confirmation records
│ │ └── <domain>-confirmation.yaml
│ ├── checks/ # Check report archive (machine-readable JSON)
│ │ ├── sqc-<domain>-v1.json
│ │ └── c1-c4-<domain>-v1.json
│ └── state.yaml # Single metadata file: phase pointer + budget + latest check
├── src/ # Appears after Derivation Loop
├── tests/ # Appears after Derivation Loop
├── docs/ # Appears after Derivation Loop (includes current/planned sections)
└── (git commit after each phase completion)
Minimal state.yaml (stores only pointers, not detailed progress):
spec_status: frozen # interviewing | drafting | reviewing | frozen | evolved
current_phase: derivation # formation | derivation | complete
budget: { formation: 40%, implementation: 12%, revision: 100% }
last_check: { type: sqc, spec: auth-v0.1.0, result: pass, at: 2026-08-06T16:00 }
Recovery Rules: When the skill reloads, scan the directory — no specs/ = start from interview; specs/ exists but no decisions/ = start from confirm; decisions/ exists but spec not frozen = start from freeze; src/ exists but no checks/ = start from derive; checks/ exists = start from verify.
Phase completion = git commit (AI assistant helps): After each successful command execution, commit (feat(sddl): interview complete), ensuring traceability.
Dual Loop Process Orchestration
Formation Loop (do the right thing) — 5 commands
/sddl:interview → /sddl:spec → /sddl:confirm → /sddl:freeze
│ │ │ │
└─ Revision ──┴──────┴──────┘
(SQC fails / user changes decision point → return to previous step, max 5 iterations)
| Command | Key Action | Checkpoint |
|---|---|---|
| interview | Layered questioning L0-L2 (≤10 questions required), produce requirements statement | Complete requirements statement |
| spec | Generate L1-L5 spec + decision point markers (register DP for ambiguities) | SQC-def skeleton passes |
| confirm | Decision point summary → clarify item-by-item confirmation (including custom input) | No pending decision points |
| freeze | Full SQC check + confirmation record signing | SQC no blocker + frozen |
Derivation Loop (do things right) — 3 commands
/sddl:derive → /sddl:verify → (converge) → complete
│ │
└─ Route ─────┘
(violation → regenerate code/tests/docs or unfreeze back to Formation Loop)
| Command | Key Action | Checkpoint |
|---|---|---|
| derive | Derive tests/code/docs from spec | Artifacts runnable |
| verify | C1-C4 layered checks + convergence evaluation | Hard gates + Soft consensus + must coverage |
| archive | Change archiving, spec merge | CHANGELOG + spec update |
Checker Scripts (scripts/) — Deterministic Evidence, Not Semantic Judgment
Scripts are only responsible for deterministic evidence (type checks/test execution/symbol tables/YAML), semantic review is performed by the agent's LLM capability:
# SQC deterministic check (Formation Loop gate) — script provides facts
python3 scripts/check_sqc.py sddl/specs/<domain>/spec.yaml --verbose
# C1-C4 deterministic check (Derivation Loop gate) — script provides facts
python3 scripts/check_c1_c4.py . --verbose
# State recovery (after interruption) — scan directory and output current progress + next command
python3 scripts/sddl_status.py .
- Exit code: 0 = pass/converged, 1 = fail (can be used in CI)
--jsonoutputs machine-readable evidence (for LLM review citation)
Division of Responsibilities (important):
| Layer | Responsible |
|---|---|
| Deterministic evidence (hard conditions): schema validity/interface existence/test passing/symbol tables | Scripts |
| Semantic review (soft conditions): behavior coverage/THEN assertability/test true coverage/doc authenticity | Agent's LLM (see references/llm-review.md) |
Do not use heuristic scripts for semantic judgment — string matching will cause false negative explosions (T1 measured C1-sem at 0.48). Scripts are evidence collectors, the agent is the judge.
When to Read Which Reference
Load on demand, not all at once (progressive disclosure):
| Scenario | Read |
|---|---|
| Executing interview | references/formation-loop.md (Phase 1) |
| Generating spec | references/spec-schema.md + templates/spec-template.yaml |
| SQC check | references/sqc-checklist.md (def via script, sem via LLM) |
| Decision point confirmation | templates/decision-summary.md |
| Deriving artifacts | references/derivation-loop.md (Phases 1-2) |
| C1-C4 checks | references/checker-matrix.md (def via script, sem via LLM) |
| Semantic review operations | references/llm-review.md (core: how LLM does review) |
| Routing/revert/budget | references/derivation-loop.md (Phases 3-5) |
| Change proposals | references/formation-loop.md (Change management) |
Budget and Degradation
- Three budgets: formation (2M tokens / 5 iterations) / implementation (15M / 4 sessions) / revision (5M, L2 deducts 10%, L3 deducts 25%, first L3 free)
- Budget recorded in state.yaml, updated after each command
- Budget exhausted → switch to human-driven, no automatic degradation (spec quality is the foundation)
- Degradation paths: D1 Semantic degradation → D2 Move should/could to risk list → D3 Reduce variation → D4 Split spec → D5 Best effort delivery
Experience Guidelines (Important)
- Phased commands: Never complete the entire dual loop in a single response — each command is an independent interaction unit with checkpoints between them
- Decision points use clarify, custom input explicitly visible: One clarify per decision point, with an explanation of impact; Business choice options ≤3, the 4th slot is fixed for 'Custom Input (Other)' (tested: clarify without auto-Other, choices max 4, must explicitly reserve a slot); question text hints 'For other values, please select Custom Input'; custom user values follow a capture protocol (record value+reason → sync spec → mark confirmation as modified); open-ended decision points use clarify directly without choices
- Progress visibility: Report current phase + next step at the beginning/end of each command
- State writing: Write state.yaml + git commit after each command ends
- Check reports: Write every check (SQC/C1-C4) to
checks/*.json, report human-readable summary + machine-readable details
Common Pitfalls
- Skipping the Formation Loop and going directly to Derivation — Writing code without freezing the spec = returning to conversational programming.
/sddl:freezeis a hard boundary; no derivation without freezing. - Silent decision making on decision points — Not marking DP for ambiguities and directly writing default values = distorting user intent. Any 'choosing for the user' must register a DP.
- Checker self-confirmation loop — Trusting AI-applied labels. C1-def must perform structural reverse engineering (parsing test AST), not trust labels.
- Absolute semantic check scores — LLM ratings of 0-100 are not reliable. Use Checklist binary classification + voting consensus rate (objective counting).
- Revert bypassing quality gates — Directly modifying spec for
spec_error= self-relaxing standards. Must unfreeze → return to Formation Loop → refreeze. - State file bloat — Writing all progress into state.yaml = returning to 'document lies'. state.yaml stores only pointers; details are in the files themselves.
- No budget recording — Not updating state.yaml budget = cost runaway. Update after each command ends.
- Using crude string matching for semantic checks — T1 measured: keyword matching reduces C1-sem to 0.48 (false negative explosion). Prioritize Checklist LLM voting; heuristics only as fallback, and must be semantic (AST extraction of assertions + structured keywords). First iteration results are not trustworthy and require manual review.
- Shared state leaks between tests — T1 measured: in-memory store shared across tests causing assertion failures. During derivation, isolated fixtures must be added (autouse reset); test assertions should go through public interfaces, not directly access internal
_store. - Pure query functions with side effects — T1 measured:
detectDiscrepancyinternally modifies status, violating spec B006 (should remain draft). Pure query interfaces (returning reports/queries) must not modify state; C2-sem should check.
Verification Checklist
-
sddl/directory structure correct (specs/changes/decisions/checks/state.yaml) - spec.yaml passes SQC-def (valid schema/complete references/assertability/decision point coverage)
- All decision points confirmed/modified/delegated (no pending)
- Confirmation record signed (overall: approved)
- spec_status: frozen before entering derivation
- C1-def has performed structural reverse engineering (not trust labels)
- All hard conditions pass (C1-def/C2-def/C3/C4b-def)
- Soft condition consensus rates met (c1_sem≥0.95 c2_sem≥0.95 c4a≥0.90 c4b_sem≥0.90)
- Must-level acceptance criteria 100% covered
- state.yaml budget updated
- Phase completion git commit created
One-Shot Recipes
Starting a New Project from Scratch
/sddl:init → /sddl:interview → /sddl:spec → /sddl:confirm → /sddl:freeze
→ /sddl:derive → /sddl:verify → /sddl:archive
Backfilling Spec for Existing Code (Migration Project)
/sddl:init (read existing code) → /sddl:spec (reverse extract current state + mark decision points)
→ /sddl:confirm → /sddl:freeze → /sddl:verify (validate spec↔code consistency)
Incremental Feature Development (Spec Already Frozen)
/sddl:init → write changes/<name>/ proposal → /sddl:confirm (affected decision points)
→ /sddl:freeze → /sddl:derive → /sddl:verify → /sddl:archive
Related Skills
writing-plans: Writing implementation plans (SDDL's changes/tasks.md can use it)test-driven-development: TDD is SDDL's verification method (C3 test execution)hermes-agent-skill-authoring: This skill's own authoring guidelines