sdd-derive
SDD Derive
Generate SDD artifacts from user intent and existing code. Produces either a change directory (for new/modified behavior) or baseline specs (for retroactive documentation).
SPECS_ROOTis resolved by thesddrouter before this skill runs. Replace.specs/with your project's actual specs root in all paths below.
Invocation Notice
- Inform the user when this skill is being invoked by name:
sdd-derive.
When to Use
- User describes a feature to specify: "derive SDD specs for the auth flow"
- User wants a change directory for a new feature against an existing codebase
- User wants retroactive specs documenting existing behavior
- User says "spec this out", "create an SDD change for X", "document this in SDD"
When Not to Use
- Translating specs from another tool — use
sdd-translate - No codebase and no existing behavior — use
sdd-proposedirectly
Determine Output Type
Baseline specs (.specs/specs/) document implemented behavior — they are the source of truth for what the codebase currently does.
Only write baseline specs when there is existing code to document.
If the codebase has no relevant implementation yet, all specs are aspirational and belong in a change directory.
digraph output_type {
".specs/specs/ exists?" [shape=diamond];
"Codebase has relevant\nimplementation?" [shape=diamond];
"New or existing behavior?" [shape=diamond];
"Generate change directory\n(.specs/changes/<name>/)\nADDED-only delta specs" [shape=box];
"Generate change directory\n(.specs/changes/<name>/)" [shape=box];
"Generate baseline specs\n(.specs/specs/)" [shape=box];
".specs/specs/ exists?" -> "Codebase has relevant\nimplementation?" [label="no"];
"Codebase has relevant\nimplementation?" -> "Generate baseline specs\n(.specs/specs/)" [label="yes — retroactive doc"];
"Codebase has relevant\nimplementation?" -> "Generate change directory\n(.specs/changes/<name>/)\nADDED-only delta specs" [label="no — greenfield"];
".specs/specs/ exists?" -> "New or existing behavior?" [label="yes"];
"New or existing behavior?" -> "Generate change directory\n(.specs/changes/<name>/)" [label="new or modified"];
"New or existing behavior?" -> "Generate baseline specs\n(.specs/specs/)" [label="retroactive doc"];
}
Greenfield check: When .specs/specs/ does not exist, survey the codebase (Phase 2) before deciding output type.
If the survey finds no relevant implementation for the target capability, generate a change directory with ADDED-only delta specs — not baseline specs.
This prevents .specs/specs/ from asserting behavior that hasn't been built yet.
Process
Checklist
- Phase 1: Understand User Intent
- Phase 2: Analyze Existing Code
- Phase 3: Schema Discovery
- Phase 4: Assess Scope and Plan Decomposition
- Phase 5: Lift Behaviors to Contracts
- Phase 6: Generate Artifacts
- Phase 7: Validate
Phase 1: Understand User Intent
Extract from the request:
- Which capability(s) does this touch? (auth, payments, UI, etc.)
- What behavior is being specified? (new feature, modification, retroactive doc)
- What's in scope vs. out of scope? Ask one targeted question if truly ambiguous.
Don't speculate on large surface areas — confirm scope before generating anything.
Phase 2: Analyze Existing Code
One-time suggestion: Check .specs/.sdd/suggested-tools.
- If
code-review-graphis not listed: present the suggestion below, then appendcode-review-graphto that file (create the file and directory if needed). Do this once and only once. - If already listed: skip the suggestion.
Suggestion (first run only):
code-review-graphis a CLI tool that builds a structural AST graph of your codebase. It improves codebase analysis — entry points, dependency chains, and capability boundaries — compared to ad-hoc file reading. Install:uv tool install code-review-graph. Say "skip" to dismiss. This won't appear again.
Optional: Graph-Aided Survey (if code-review-graph is installed)
- Build or update the graph:
code-review-graph build - Query entry points and blast radius for the target capability
- Use graph findings to guide the targeted file reading below — skip files the graph shows are unrelated
If not installed, proceed with the manual survey.
Code Survey
Survey the codebase for the relevant capability:
-
Find high-value files:
- Entry points, routes, controllers
- Service / business logic files
- Schema / model / type files
- Config or environment files
-
Extract observable behavior (not internals):
- What inputs are accepted? What are the shapes?
- What outputs or side effects occur?
- What validations or business rules apply?
- What error conditions exist?
-
Identify capability boundaries — if the request spans multiple unrelated concerns, plan decomposition.
Phase 3: Schema Discovery (if applicable)
After the code survey, check for machine-readable schema artifacts. This runs in parallel with the code survey — use whichever source provides higher-fidelity evidence.
-
Detect schema artifacts — look for: committed specs (
openapi.yaml,swagger.json,openapi.json,docs/api/,openapi/); schema files (.proto,.graphql,.prisma,.avsc,schema.sql); or framework markers implying runtime schema generation (FastAPI, NestJS, Spring Boot, DRF, Rails API, Go Echo/Gin, Laravel, GraphQL servers, gRPC). Seereferences/sdd-schema.md§ 3 for config examples. -
Check for
.specs/.sdd/schema-config.yaml— if it exists, use the configured extraction commands. If not, and schema artifacts were detected, suggest creating one (one-time, using thesuggested-toolspattern):"Detected
<files>. > Consider creating.specs/.sdd/schema-config.yamlto configure schema extraction for SDD verification. > Seereferences/sdd-schema.md§ 3 for the format. > Say 'skip' to dismiss." -
Generate snapshots — if extraction is configured, run the commands and store output in
.specs/schemas/. -
Diff authored vs. generated — if the repo contains a committed authored schema (e.g.,
docs/openapi.yaml) and a generated snapshot was produced, diff them:- Paths in authored but not generated → aspirational (planned but not yet implemented)
- Paths in generated but not authored → undocumented drift
- Type or shape mismatches → potential bugs or stale spec Use these findings to inform requirement writing: aspirational paths suggest ADDED candidates; undocumented drift suggests missing requirements.
-
Enrich generated specs — where a requirement maps to a specific schema path, add a
**Schema reference:**annotation to the relevant scenario (seereferences/sdd-schema.md§ 1 for the format).
Phase 4: Assess Scope and Plan Decomposition
| Signal | Action |
|---|---|
| ≤ 8 requirements | Single capability, proceed |
| 9–20 requirements | Split into 2–4 capabilities, proceed |
| 20+ requirements | Present split to user, wait for confirmation |
When splitting, tell the user before generating:
This covers 3 capabilities. I'll generate:
- auth/ → login, session, token management
- profile/ → user settings, preferences
- permissions/ → role-based access control
Proceed with this split? (or suggest changes)
Phase 5: Lift Behaviors to Contracts
sdd-derive starts from mechanism — the code you just surveyed is the implementation.
Before writing any requirement, translate from "what the code does" to "what property the code maintains."
This lift step is the skill's distinguishing move; without it, requirements echo code structure instead of stating contracts.
Read references/sdd-spec-formats.md § 1 before lifting.
It defines contract shapes (guarantee / invariant / prohibition / precondition-consequence / observable-state relationship) and the authoring primitive.
For each observable behavior from Phase 2, ask: what property of the system does this code maintain?
Worked example:
| Observed in code | Naive echo (wrong) | Lifted contract (right) |
|---|---|---|
UserService.activate() runs db.users.update(is_active=True, updated_at=now()) and enqueues a confirmation email job |
"The system SHALL update users.is_active to true and send a confirmation email on activate()." |
"Given an inactive user account, when the account is activated, the account SHALL be in the active state and the user SHALL be notified." |
search() filters by tfidf_score > 0.3 then sorts descending |
"The search SHALL filter terms by TF-IDF > 0.3 and sort descending." | "The search SHALL return documents ranked by relevance to the query, with the most relevant first." |
Rules for lifting:
- Pair each code behavior with the property it serves. One-to-many is fine; a single code path often serves several properties.
- Name the property, not the path. If you can't articulate the property, you don't have a requirement yet — you have a mechanism.
- When a chosen algorithm, threshold, or data structure appears in the code, record it as a design note for Phase 6 generation (it will surface later if the user runs
sdd-proposefor a full artifact set). The property the algorithm produces is the contract; the algorithm is not. - If the property is universal over a space of inputs, state it universally — "for any {input class}, the system SHALL {outcome}."
Output of this phase: a list of lifted contracts per capability, ready to format in Phase 6.
Phase 6A: Change Directory (new or modified behavior)
Create .specs/changes/<change-name>/ with artifacts in this order:
proposal.md— intent, scope, approachspecs/<capability>/spec.md— delta specs (ADDED/MODIFIED/REMOVED sections)tasks.md— when implementation steps are clear from code analysis
Note: sdd-derive produces a partial change directory — no design.md.
If the user needs a full artifact set including design decisions, use sdd-propose instead. sdd-derive is optimized for code-first derivation; sdd-propose is the complete change creation workflow.
See references/sdd-change-formats.md (proposal, tasks) and references/sdd-spec-formats.md (delta specs) for the formats.
Write each requirement from the lifted contracts produced in Phase 5 — not from the code directly. If a draft requirement still names a function, class, table, or library from the code, return to Phase 5 and re-lift that behavior.
Add a generation note at the top of each delta spec:
Generated from code analysis on {date} Source files: {list of analyzed files}
Phase 6B: Baseline Specs (retroactive documentation)
Create .specs/specs/<capability>/spec.md per capability.
See references/sdd-spec-formats.md for the baseline spec format.
Add a generation note at the top of each spec:
Generated from code analysis on {date} Source files: {list of analyzed files}
Phase 7: Validate
- Requirements use RFC 2119 keywords (SHALL/MUST/SHOULD/MAY)
- Scenarios use
#### Scenario:with GIVEN/WHEN/THEN (bold, exact casing) - Each requirement is a lifted contract, not a restatement of code structure — states the property the code maintains, not the code's actions (see
references/sdd-spec-formats.md§ 1 and the Phase 5 worked example) - Delta specs (change directory) use ADDED/MODIFIED/REMOVED sections
- Baseline specs have no delta markers
- Baseline specs include a
## Purposesection - Each generated spec has a generation note blockquote (date and source files listed)
- Large surface areas are decomposed into multiple capability specs
Output
Change directory (new/modified behavior):
.specs/changes/<name>/proposal.md.specs/changes/<name>/specs/<capability>/spec.md(delta format).specs/changes/<name>/tasks.md(when applicable)
Baseline specs (retroactive):
.specs/specs/<capability>/spec.mdper capability
Report: capabilities covered, requirement count, assumptions made.
Common Mistakes
- Skipping the Phase 5 lift step and writing requirements directly from code — this is the dominant failure mode in
sdd-deriveand produces specs that faithfully describe mechanism instead of contract - Generating one massive spec for a large surface area instead of decomposing by capability
- Using delta format (ADDED/MODIFIED/REMOVED) in baseline
.specs/specs/files - Using baseline format (no delta markers) in change directory specs
- Generating specs without reading relevant code first
- Speculating on scope rather than asking when the request is ambiguous
- Writing baseline specs in a greenfield project —
.specs/specs/asserts implemented behavior; if nothing is built yet, use a change directory with ADDED-only delta specs
References
references/sdd-spec-formats.md— baseline spec, delta spec, scenario formatsreferences/sdd-change-formats.md— proposal, design, tasks formatsreferences/sdd-schema.md— schema artifacts and lifecycle policyreferences/sdd-derive-output-type.dot— canonical DOT source for the output type decision above