spec
Create a specification with requirements, scenarios, and design rationale. Use when the user wants to write a spec, formalize requirements, convert an ADR to a specification, or says "create a spec".
Governing Artifacts
Usage
/sdd:spec [capability name or ADR reference] [--review] [--module <name>]
Required Tools
BashReadWriteEditGlobGrepTaskWebFetchWebSearchTeamCreateTeamDeleteTaskCreateTaskUpdateTaskListTaskGetSendMessageAskUserQuestion
Overview
You are creating or updating an OpenSpec specification. Every spec is a paired artifact: spec.md (requirements — what the system does) and design.md (architecture and rationale — how and why it does it).
You MUST ALWAYS create or update BOTH files together. They are a single unit of truth. Never create, edit, or deliver one without the other.
When updating an existing spec, you MUST review the companion file for alignment. If spec.md changes, read design.md and update it where the architectural decisions or rationale no longer reflect the updated requirements — and vice versa. The two files MUST remain internally consistent at all times.
When creating a new spec from scratch, both files are created together — alignment is automatic. The pairing review obligation applies to subsequent updates where one file may change without the other.
Process
<!-- Governing: ADR-0016 (Workspace Mode), SPEC-0014 REQ "Artifact Path Resolution" -->
-
Resolve artifact paths: Follow the Artifact Path Resolution pattern from
references/shared-patterns.mdto determine the spec directory. If$ARGUMENTScontains--module <name>, resolve paths relative to that module. The resolved spec directory is referred to as\{spec-dir\}below. -
Determine the capability name: Use kebab-case (e.g.,
web-dashboard,webhook-trigger). If converting from an ADR, derive from the ADR title. If$ARGUMENTSis empty (ignoring flags like--reviewand--module), useAskUserQuestionto ask the user what capability they want to specify. -
Check for existing directory: If
\{spec-dir\}/\{capability-name\}/already exists, useAskUserQuestionto ask whether to update the existing spec or choose a different name. If updating: read both the existingspec.mdanddesign.mdbefore making changes, then update both files maintaining alignment between them. -
Determine the next SPEC number: Scan
\{spec-dir\}for existing spec.md files, find the highest SPEC number used, and increment. SPEC numbers are formatted asSPEC-XXXX(e.g., SPEC-0001). Start at SPEC-0001 if none exist. IMPORTANT: The prefix isSPEC-, NOTRFC-. Do not confuse spec numbering with RFC 2119 (which is a language standard for requirements keywords).
3a. qmd-aware edge pre-search (v5.0.0+):
<!-- Governing: ADR-0024 (qmd as hard dependency), SPEC-0019 REQ "qmd-Smart Authoring Skills" -->
Before drafting, qmd-search the existing spec corpus to find related prior specs whose IDs SHOULD appear in the new spec's frontmatter as requires, extends, or supersedes edges. Also search ADRs to identify which ADRs the new spec should declare it implements.
-
Construct a hybrid query per
references/qmd-helpers.md§ "Hybrid Retrieval":lex: capability name + key technologies/conceptsvec: a one-sentence framing of what the new spec coversintent: "/sdd:spec — find related prior specs and governing ADRs to suggest as frontmatter edges"collections: ["\{repo\}-specs", "\{repo\}-adrs"](or per-module variants perqmd-helpers.md§ "This-Repo Collection Identification")limit: 8,minScore: 0.3
-
Classify each result above the threshold:
- requires (spec → spec): the new spec depends on capability the matched spec provides
- extends (spec → spec): the new spec is a behavioral extension of the matched spec
- supersedes (spec → spec): the new spec replaces the matched spec
- implements (spec → ADR): the new spec realizes the matched ADR's decision
-
Surface candidate edges via
AskUserQuestionBEFORE writing the file. Show each with the matched artifact's ID, title, and proposed edge classification. Options for each: "Include as\{edge\}", "Include as different edge", "Skip". -
If qmd returns zero results above the threshold, proceed without surfacing edge suggestions and emit: "No related specs or ADRs found — drafting from scratch."
-
On qmd unreachable / timeout per
qmd-helpers.md§ "Error Handling", surface the error and stop. Per 📝 ADR-0024, no fallback in v5. -
Choose drafting mode: Check if
$ARGUMENTScontains--review.Default (no
--review): Single-agent mode. Research the codebase (read relevant files, understand the current architecture), draft both spec.md and design.md directly, self-review against the architect's checklist in the Rules section, then write both files.With
--review: Team review mode.- Tell the user: "Creating a drafting team to write and review the spec. This takes a minute or two."
- Create a Claude Team with
TeamCreateto draft and review:- Spawn a spec-writer agent (
general-purpose) to write both spec.md and design.md based on the user's description or ADR:$ARGUMENTS. Remind the spec-writer that specs useSPEC-XXXXnumbering, NOTRFC-XXXX. - Spawn an architect agent (
general-purpose) to review both documents for completeness, accuracy, RFC 2119 keyword compliance, and proper scenario format. The architect MUST verify the spec usesSPEC-XXXXnumbering, notRFC-XXXX. - The architect MUST review and approve BOTH documents before they are finalized
- If converting from an ADR, the spec-writer should read the ADR and use it as the basis
- If
TeamCreatefails, fall back to single-agent mode: draft both files directly, then self-review against the architect's checklist in the Rules section before writing.
- Spawn a spec-writer agent (
4b. Optional call graph generation (v5.1.0+):
<!-- Governing: ADR-0033 (cgg call graph integration), SPEC-0034 REQ "Call Graph Generation Uses cgg With Filtering" -->
After requirements are authored (Step 4) and before writing to disk (Step 5), ask the user whether to generate call graphs showing the current implementation scope.
Opt-in prompt: Use AskUserQuestion with the text:
Generate call graphs showing current implementation scope? (yes / no / skip)
Default to no on timeout or in batch/non-interactive mode. If the user answers no or skip, skip this step entirely — spec.md and design.md are written without an ## Implementation section. No error, no deviation.
When user answers yes:
-
Availability check: Run
which cgg >/dev/null 2>&1perreferences/cgg-integration.md§ "Availability Check". If cgg is not found, surface the one-line unavailability notice from that section and skip to Step 5 — write spec.md without an## Implementationsection. -
Extract requirement keywords: For each
### Requirement:section heading in the drafted spec.md, extract the requirement name (text after### Requirement:). Apply the From requirement keywords filter derivation fromreferences/cgg-integration.md§ "Filter Derivation Strategy":- Lowercase and split on spaces/punctuation
- Strip common stop words
- Compose a regex alternation from remaining terms (e.g.,
payment|processing|token|validation)
-
Find implementing code files via qmd: Search the
\{repo\}-codecollection (or\{repo\}-\{module\}-codein workspace mode) using the requirement keywords as query terms. This surfaces the file paths most likely to implement each requirement. -
Invoke cgg: Use the invocation pattern from
references/cgg-integration.md§ "cgg Invocation Pattern":- Derive
--filterby combining qmd file-path stems with requirement keyword terms per § "Filter Derivation Strategy" → "From qmd code matches" - Apply the 20-node cap and Mermaid normalization per § "Node cap" and § "Mermaid Output Normalization"
- Handle all exit codes and degradation cases per § "Exit code handling" and § "Graceful Degradation"
- In workspace mode, scope
<target-path>to the module directory per § "Workspace-Mode Scoping"
- Derive
-
Build the
## Implementationsection: Append to the in-memory spec.md draft (not yet on disk):## Implementation
> Call graphs generated from current codebase. Re-run `/sdd:spec --update SPEC-XXXX` after implementation to refresh.
### Requirement-to-Function Mapping
**REQ "{Requirement Name}"**: functions `fn_a()` → `fn_b()` → `fn_c()`
*(One line per requirement. List functions extracted from the call graph for that requirement's filter. If cgg returned no nodes for a requirement, omit that requirement's line rather than showing an empty entry.)*
### Call Graph
<!-- Call graph: <filter used>, generated <date> -->
```mermaid
graph TD
...
%% Showing entry points + main flow; internal helpers omitted -
Before/after for
--update: When running/sdd:spec --update SPEC-XXXXand the existing spec.md already contains an## Implementationsection, produce side-by-side Mermaid blocks labeled "Before" and "After":### Call Graph
**Before** (prior to this update):
<!-- Call graph: <prior filter>, generated <prior date> -->
```mermaid
graph TD
... (preserved from prior run)After (current implementation scope):
<!-- Call graph: <new filter>, generated <new date> -->
Preserve the prior Mermaid block exactly as it appeared in the existing spec.md. -
Write both files:
{spec-dir}/{capability-name}/spec.md— include the user-confirmed frontmatter edges from Step 3a (per the canonical edge schema inreferences/shared-patterns.md§ "Graph Edge Resolution"){spec-dir}/{capability-name}/design.md
5a. Tier 1 mutation update (v5.0.0+):
After writing both files, trigger a narrow re-sync of {repo}-specs so the qmd index reflects the new artifacts. Use the canonical update pattern from references/qmd-helpers.md § "Update Patterns" → "Narrow update". Synchronous and silent on success. On failure, append a one-line warning to the report ("Index refresh failed for {repo}-specs — run /sdd:index update manually") but report the spec creation itself as successful.
-
Clean up the team when done (if
--reviewwas used). -
Summarize what happened (files created, spec documented, review outcome).
-
Suggest sprint planning: After the spec is written, suggest: "To break this spec into trackable issues, run
/sdd:plan SPEC-XXXX." -
CLAUDE.md integration: Check if this is the first spec (i.e.,
{spec-dir}was just created or contains only this new directory). If so:- Check if a
CLAUDE.mdexists at the module root (or project root for single-module projects) - If it exists, check if it already references the spec directory
- If no reference exists, ask the user: "I can add an Architecture Context section to your CLAUDE.md so future sessions know about your specs. Shall I?"
- If the user says yes, append an
## Architecture Contextsection with- Specifications are in {spec-dir} - If
CLAUDE.mddoesn't exist, suggest creating one
- Check if a
Team Handoff Protocol (only for --review mode)
Follow the standard team handoff protocol from the plugin's references/shared-patterns.md. The drafter is the spec-writer; the reviewer is the architect who checks both spec.md and design.md against the Rules checklist below.
Rules
- You MUST ALWAYS create or update BOTH spec.md AND design.md together -- never one without the other
- When ANY change is made to spec.md, design.md MUST be reviewed and updated where requirements have changed the architecture, decisions, or rationale -- and vice versa. Both files MUST remain consistent with each other at all times.
- spec.md MUST use RFC 2119 language (SHALL, MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, REQUIRED, RECOMMENDED, OPTIONAL) for ALL normative requirements
- spec.md MUST use spec numbering: SPEC-XXXX (sequential, zero-padded to 4 digits). NEVER use RFC-XXXX -- "RFC 2119" refers to the requirements language standard, NOT the spec numbering scheme
- Scenarios MUST use exactly 4 hashtags (
####) -- using 3 hashtags or bullets will cause silent failures in downstream tooling - Every requirement MUST have at least one scenario
- design.md focuses on HOW and WHY -- architecture and rationale, not line-by-line implementation details
- Self-review (default) or architect review (
--review) MUST check for:- RFC 2119 compliance (every normative statement uses the proper keywords)
- Scenario format correctness (exactly
####level headings with WHEN/THEN) - Completeness of both documents
- Alignment between spec requirements and design decisions
- Security section present for web-facing specs (Governing: 📝 ADR-0018, SPEC-0016)
- Auth-by-default applied to all endpoint tables (Governing: 📝 ADR-0018, SPEC-0016)
- Accessibility section present for UI-facing specs (Governing: 📝 ADR-0019, SPEC-0016)
- If converting from an ADR, reference the ADR number in the spec's Overview section
- design.md MUST include at least one Mermaid architecture diagram. Prefer C4 context/container diagrams for system-level, sequence diagrams for flows, and ERDs for data models.
- When implementing code governed by this spec, agents MUST leave governing comments per
references/shared-patterns.md§ "Governing Comment Format":// Governing: ADR-XXXX (desc), SPEC-XXXX REQ "Requirement Name" - For web-facing specs: MUST inject the Security Requirements section covering authentication, rate limiting, security headers, body size limits, CSRF protection, and redirect validation (Governing: 📝 ADR-0018, SPEC-0016 REQ "Mandatory Security Section in Web Specs")
- For web-facing specs: MUST apply auth-by-default — every endpoint defaults to "Auth: Required"; public endpoints need "Auth: Public" with explicit justification (Governing: 📝 ADR-0018, SPEC-0016 REQ "Auth-by-Default")
- MUST NOT inject the Security Requirements section for non-web specs (CLI tools, libraries, batch jobs, data migrations, background workers)
- For UI-facing specs: MUST inject the Accessibility Requirements section covering WCAG 2.1 AA, ARIA landmarks,
aria-labelon icon-only controls,aria-livefor dynamic content, keyboard navigation, and focus management (Governing: 📝 ADR-0019, SPEC-0016 REQ "Accessibility Requirements for UI Specs") - MUST NOT inject the Accessibility Requirements section for non-UI specs (API-only, CLI, batch jobs, background workers, internal libraries)
- v5.0.0+: MUST run qmd-aware edge pre-search per Step 3a — surface candidate
requires/extends/supersedes/implementsedges to the user via AskUserQuestion before drafting. The user's confirmed edges land in the new spec's frontmatter (Governing: 📝 ADR-0024, SPEC-0019 REQ "qmd-Smart Authoring Skills") - v5.0.0+: MUST trigger Tier 1
{repo}-specsre-sync after writing both files per Step 5a — best-effort, silent on success (Governing: 📝 ADR-0026, SPEC-0019 REQ "Tier 1 Mutation-Aware Updates") - v5.0.0+: On qmd unreachable / timeout during the edge pre-search, MUST surface the error and stop — never fall back to "draft without edge suggestions" (per 📝 ADR-0024)
- For backend specs with error handling: MUST inject error wrapping, sentinel errors, no silent swallowing, and structured logging requirements (Governing: SPEC-0016 REQ "Go Code Quality Guidelines")
- For backend specs with concurrency: MUST inject context propagation, worker lifecycle, race safety, and race detection CI requirements (Governing: SPEC-0016 REQ "Go Code Quality Guidelines")
- For backend specs with database interactions: MUST inject transaction, connection lifecycle, and parameterized query requirements
- ALL backend quality guidelines MUST be language-agnostic — use "structured logging" not "slog", "error wrapping" not "%w", "project manifest" not "go.mod", "parallel workers" not "goroutines"
- MUST NOT inject backend quality requirements for non-backend specs (static docs, pure frontend, CSS, declarative config)
- v5.1.0+ call graph (opt-in): MUST use
AskUserQuestionwith text "Generate call graphs showing current implementation scope? (yes / no / skip)" AFTER requirements are drafted and BEFORE writing files (Step 4b). Default to no on timeout or in batch mode (Governing: 📝 ADR-0033, SPEC-0034 REQ "Call Graph Generation Uses cgg With Filtering") - v5.1.0+ call graph (opt-in): When user answers yes, MUST probe for cgg availability before invoking; if unavailable, surface the one-line notice from
references/cgg-integration.md§ "Availability Check" and write spec.md without## Implementationsection — no hard failure (Governing: 📝 ADR-0033, SPEC-0034) - v5.1.0+ call graph (opt-in): When generating, MUST derive
--filterfrom requirement keywords perreferences/cgg-integration.md§ "Filter Derivation Strategy" → "From requirement keywords"; MUST apply 20-node cap and Mermaid normalization per that reference; MUST handle all exit codes and degradation cases (Governing: SPEC-0034 REQ "Call Graph Generation Uses cgg With Filtering") - v5.1.0+ call graph (opt-in): The
## Implementationsection MUST list each requirement name alongside the functions from the call graph in the format:**REQ "{name}"**: functions \fn_a()` → `fn_b()` → `fn_c()`` (Governing: SPEC-0034) - v5.1.0+ call graph (opt-in): When user answers no or skip, MUST write spec.md without
## Implementationsection; MUST NOT produce any error or deviation from normal workflow (Governing: SPEC-0034) - v5.1.0+ call graph (opt-in): When
/sdd:spec --update SPEC-XXXXis used and existing spec.md already has## Implementation, MUST produce side-by-side "Before" / "After" Mermaid blocks preserving the prior block exactly as it appeared (Governing: SPEC-0034) - v5.1.0+ call graph (opt-in): MUST NOT produce unfiltered call graphs by default;
--unfilteredescape hatch is only available when explicitly passed (Governing: SPEC-0034 REQ "Call Graph Generation Uses cgg With Filtering")
Web-Facing Detection and Security Injection
Before writing the spec, determine whether the capability is web-facing. A spec is web-facing if ANY of the following are true:
- It defines or modifies HTTP endpoints (REST API, GraphQL, gRPC-web, etc.)
- It involves web server routes or middleware
- It includes browser-rendered UI (HTML templates, HTMX, SPAs)
- It describes an API consumed over HTTP/HTTPS
- The capability name or description references: API, dashboard, webhook, web, HTTP, endpoint, route, server, frontend, UI, portal, gateway
A spec is NOT web-facing if it exclusively involves: CLI tools, internal libraries, batch/cron jobs, data migrations, background workers, message queue consumers, or purely offline processing.
When the spec IS web-facing
You MUST inject a ## Security Requirements section into spec.md, placed after the functional ## Requirements section. This section MUST cover all six topics below. Use the template in the "Security Requirements Section Template" below.
You MUST also apply auth-by-default: when generating endpoint tables or lists, every endpoint MUST default to "Auth: Required". Any endpoint the spec author wants to be public MUST be listed as "Auth: Public" with an explicit justification (e.g., "Health check — required for load balancer probes"). Do NOT leave any endpoint without an auth designation.
When the spec is NOT web-facing
Do NOT inject the Security Requirements section. Proceed with the standard spec template only.
Security Requirements Section Template
Read the Security Requirements template from references/security-requirements-template.md and inject it into the spec after the functional requirements. The template covers all six required topics: authentication, rate limiting, security headers, request body size limits, CSRF protection, and redirect validation.
UI-Facing Detection and Accessibility Injection
Before writing the spec, determine whether the capability is UI-facing. A spec is UI-facing if ANY of the following are true:
- It involves HTML templates or server-rendered pages (Go
html/template, Django, Rails, Jinja, etc.) - It includes browser-rendered UI or interactive frontend components
- It uses HTMX, Alpine.js, or other frontend interaction libraries
- It defines modals, dialogs, forms, dashboards, or other interactive UI elements
- The capability name or description references: UI, dashboard, frontend, template, page, form, modal, dialog, widget, component
A spec is NOT UI-facing if it exclusively involves: API-only backends consumed by other services, CLI tools, batch/cron jobs, data migrations, background workers, message queue consumers, internal libraries, or purely offline processing.
Note: A spec can be both web-facing AND UI-facing (e.g., a web dashboard with HTTP endpoints). When both apply, inject BOTH the Security Requirements section and the Accessibility Requirements section.
When the spec IS UI-facing
You MUST inject an ## Accessibility Requirements section into spec.md, placed after the functional ## Requirements section (and after the Security Requirements section if both apply). This section MUST cover all six topics below. Use the template in the "Accessibility Requirements Section Template" below.
When the spec is NOT UI-facing
Do NOT inject the Accessibility Requirements section. Proceed with the standard spec template only.
Accessibility Requirements Section Template
## Accessibility Requirements
This spec involves user-facing UI. The following accessibility requirements are MANDATORY per WCAG 2.1 AA.
### WCAG 2.1 AA Compliance
All UI components produced by this spec MUST meet WCAG 2.1 Level AA conformance as the minimum accessibility target.
### ARIA Landmarks
Page structure elements MUST include ARIA landmark roles:
- `role="banner"` on the site header
- `role="navigation"` on navigation regions
- `role="main"` on the primary content area
- `role="contentinfo"` on the site footer
### Icon-Only Controls
All icon-only controls (buttons, links) that have no visible text label MUST include an `aria-label` attribute describing the control's purpose.
### Dynamic Content Regions
Dynamically updated content (HTMX swaps, auto-refresh panels, real-time status updates) MUST use `aria-live` regions:
- `aria-live="polite"` for non-urgent updates
- `aria-live="assertive"` for critical status changes
### Keyboard Navigation
All interactive elements MUST be operable via keyboard:
- Logical tab order following visual layout
- Enter/Space to activate buttons and controls
- Escape to dismiss popups, dropdowns, and dialogs
- Arrow keys for navigation within composite widgets (tabs, menus, tree views)
### Focus Management
Modals and dialogs MUST implement focus management:
- Focus MUST be trapped within the modal when open (Tab/Shift+Tab cycles within the modal)
- Focus MUST move to the modal's first focusable element on open
- Focus MUST return to the triggering element when the modal is closed
Backend Quality Detection and Guidelines Injection
<!-- Governing: ADR-0020, SPEC-0016 REQ "Go Code Quality Guidelines" -->
Before writing the spec, determine whether the capability involves backend quality concerns. Detect backend projects by examining the codebase for indicators:
Detection Signals
A spec involves backend quality concerns if ANY of the following are true:
- Concurrency: The capability involves parallel workers, async tasks, threads, coroutines, background jobs, worker pools, fan-out/fan-in patterns, or concurrent request handling
- Error handling: The capability involves service boundaries, external API calls, database operations, file I/O, network requests, or any operation that can fail at runtime
- Database interactions: The capability involves queries, migrations, transactions, connection pooling, or ORM usage
- Backend manifests: The project contains backend manifests (
go.mod,requirements.txt,Cargo.toml,pom.xml,build.gradle,Gemfile,mix.exs,Package.swift,composer.json, or similar)
A spec does NOT involve backend quality concerns if it exclusively involves: static documentation, pure frontend UI (no backend logic), CSS/styling, or purely declarative configuration.
When Backend Quality Concerns Are Detected
Inject the relevant subsections below into the spec's ## Requirements section as additional requirements. Only inject subsections that match the detected signals — do not inject all subsections for every backend spec.
When Error Handling Is Involved
Inject error handling guidelines as a requirement:
### Requirement: Error Handling Standards
All error-producing operations MUST follow structured error handling:
- Errors MUST be wrapped with contextual information at each layer boundary (e.g., "failed to create user: database insert failed: connection refused")
- Sentinel errors MUST be defined for domain-specific failure modes that callers need to distinguish programmatically
- Silent error swallowing MUST NOT occur — every error MUST be either returned to the caller, logged with sufficient context, or explicitly handled with a documented reason for suppression
- Structured logging MUST be used for error reporting (key-value pairs, not string interpolation)
When Concurrency Is Involved
Inject concurrency guidelines as a requirement:
### Requirement: Concurrency Safety
All concurrent operations MUST follow safe concurrency patterns:
- Context propagation MUST be used for cancellation and timeout signaling across all concurrent boundaries (parent tasks, worker pools, background jobs)
- Worker lifecycle MUST be explicitly managed — all workers MUST have clean startup and graceful shutdown sequences
- Race safety MUST be ensured — shared mutable state MUST be protected by appropriate synchronization primitives or eliminated via message passing
- Concurrent tests MUST be run with race detection enabled in CI
When Database Interactions Are Involved
Inject database guidelines as a requirement:
### Requirement: Database Operation Standards
All database operations MUST follow structured data access patterns:
- Transactions MUST be used for multi-step mutations that require atomicity
- Connection lifecycle MUST be explicitly managed — connections MUST be returned to the pool after use, with timeouts configured
- Query parameters MUST use parameterized queries — string interpolation in queries MUST NOT occur
When Backend Quality Concerns Are NOT Detected
Do NOT inject backend quality requirements. Proceed with the standard spec template only.
Auth-by-Default in Endpoint Tables
<!-- Governing: ADR-0018 (Security-by-Default), SPEC-0016 REQ "Auth-by-Default" -->
When a web-facing spec includes an endpoint table or endpoint list, you MUST apply auth-by-default:
- Every endpoint defaults to "Auth: Required"
- If the spec author identifies endpoints that should be public, mark them as "Auth: Public" and require a justification
- Justifications MUST be specific (e.g., "Health check — load balancer requires unauthenticated access"), not generic (e.g., "public endpoint")
Example endpoint table with auth-by-default:
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET | /api/items | Required | List items |
| POST | /api/items | Required | Create item |
| GET | /health | Public | Health check — required for load balancer probes |
| GET | /login | Public | Login page — must be accessible to unauthenticated users |
spec.md Template
---
status: draft
date: {YYYY-MM-DD}
# Optional graph edges (per ADR-0023 / SPEC-0018). All fields are lists of artifact IDs.
# Only include the fields that apply; omit unused fields entirely. Forward-only:
# inverse edges (governed-by, implemented-by, depended-on-by, etc.) are derived by
# /sdd:graph at build time and MUST NOT be authored.
# implements: [ADR-XXXX] # ADRs this spec realizes
# requires: [SPEC-XXXX] # capability dependency on another spec
# extends: [SPEC-XXXX] # behavioral extension of another spec
# supersedes: [SPEC-XXXX] # hard replacement; target moves to status: deprecated
---
# SPEC-XXXX: {Capability Title}
## Overview
{Brief description of what this capability does and why it exists. If derived from an ADR, reference it here (e.g., "See ADR-0003").}
## Requirements
### Requirement: {Descriptive Name}
{Description using RFC 2119 keywords. Every normative statement MUST use SHALL, MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, REQUIRED, RECOMMENDED, or OPTIONAL per RFC 2119.}
#### Scenario: {Scenario Name}
- **WHEN** {precondition or trigger}
- **THEN** {expected outcome}
#### Scenario: {Another Scenario}
- **WHEN** {precondition or trigger}
- **THEN** {expected outcome}
### Requirement: {Another Requirement}
{Description with RFC 2119 keywords.}
#### Scenario: {Scenario Name}
- **WHEN** {precondition or trigger}
- **THEN** {expected outcome}
Note: For web-facing specs, append the Security Requirements section (from the template above) after the functional requirements. For UI-facing specs, append the Accessibility Requirements section after the functional requirements (and after Security Requirements if both apply).
design.md Template
# Design: {Capability Title}
## Context
{Background, current state, constraints, stakeholders. Reference the spec and any related ADRs.}
## Goals / Non-Goals
### Goals
- {goal 1}
- {goal 2}
### Non-Goals
- {non-goal 1}
- {non-goal 2}
## Decisions
### {Decision 1 Title}
**Choice**: {what was decided}
**Rationale**: {why this over alternatives}
**Alternatives considered**:
- {alternative A}: {why rejected}
- {alternative B}: {why rejected}
### {Decision 2 Title}
**Choice**: {what was decided}
**Rationale**: {why}
## Architecture
{High-level architecture description. MUST include at least one Mermaid diagram.}
```mermaid
{Mermaid diagram: C4 context/container for system-level, sequence for flows, ERD for data models.}
Risks / Trade-offs
- {Risk 1} → {Mitigation}
- {Risk 2} → {Mitigation}
Migration Plan
{Steps to deploy, rollback strategy if applicable. Omit if greenfield.}
Open Questions
- {question 1}
- {question 2}
## Graph Edge Frontmatter (per ADR-0023 / SPEC-0018)
<!-- Governing: ADR-0023 (Frontmatter DAG and /sdd:graph Skill), SPEC-0018 REQ "Frontmatter Edge Schema" -->
Specs MAY declare relationships to other artifacts via optional frontmatter fields. All edge fields MUST be lists of artifact IDs. All edge fields are OPTIONAL — a spec with no declared edges is valid.
| Field | Meaning | Example |
|-------|---------|---------|
| `implements` | ADRs this spec realizes | `implements: [<a href="/decisions/ADR-0009-project-grouping-and-developer-workflow-conventions" className="rfc-ref">📝 ADR-0009</a>, <a href="/decisions/ADR-0011-story-sized-issue-granularity" className="rfc-ref">📝 ADR-0011</a>]` |
| `requires` | Capability dependency on another spec | `requires: [<a href="/specs/init-and-priming/spec#spec-0007" className="rfc-ref">SPEC-0007</a>]` |
| `extends` | Behavioral extension of another spec | `extends: [<a href="/specs/init-and-priming/spec#spec-0007" className="rfc-ref">SPEC-0007</a>]` |
| `supersedes` | Hard replacement — referenced spec moves to status `deprecated` | `supersedes: [SPEC-0XXX]` |
**Forward-only convention.** Only forward edges are authored. Reverse edges (`governed-by`, `implemented-by`, `depended-on-by`, `extended-by`) are derived by `/sdd:graph` at build time and MUST NOT appear in frontmatter — the graph builder will reject them with a warning. See `references/shared-patterns.md` § "Graph Edge Resolution" for the full forward→inverse derivation table.
**Cross-module edges (workspace mode).** When referencing artifacts in another module, use the quoted `[module]/ID` syntax: `requires: ["[shared-lib]/<a href="/specs/init-and-priming/spec#spec-0001" className="rfc-ref">SPEC-0001</a>"]`. The unquoted form `[[shared-lib]/<a href="/specs/init-and-priming/spec#spec-0001" className="rfc-ref">SPEC-0001</a>]` parses as YAML nested lists and will be rejected.
**`status` and `date` fields.** The frontmatter `status` field uses the spec status enum (`draft | review | approved | implemented | deprecated`); see `/sdd:status` for transitions. The `date` field (YYYY-MM-DD) is consumed by `/sdd:list` and `/sdd:docs` for sorting and display.
**When to add edges.** Add edges as relationships become structural — typically when a spec realizes an ADR (always declare `implements`), depends on another capability (`requires`), or extends an existing spec (`extends`). Backfilling existing specs is supported via `/sdd:graph backfill`.
## Reference
### security-requirements-template.md
<!-- Governing: ADR-0018 (Security-by-Default), SPEC-0016 REQ "Mandatory Security Section in Web Specs" -->
When injecting the security section into a web-facing spec, use this template placed after the functional requirements:
```markdown
## Security Requirements
<!-- Governing: ADR-0018 (Security-by-Default), SPEC-0016 REQ "Mandatory Security Section in Web Specs" -->
### Authentication
All endpoints MUST require authentication by default. Public (unauthenticated) endpoints MUST be explicitly listed with justification.
| Endpoint | Auth | Justification |
|----------|------|---------------|
| {endpoint} | Required | — |
| {public endpoint} | Public | {why auth is not required} |
### Rate Limiting
{Declare the rate limiting strategy for this capability. Specify limits per endpoint or globally. If rate limiting is deferred, state the justification.}
### Security Headers
All HTTP responses MUST include the following security headers:
- `Content-Security-Policy`: {policy}
- `X-Frame-Options`: DENY (or SAMEORIGIN with justification)
- `X-Content-Type-Options`: nosniff
- `Referrer-Policy`: strict-origin-when-cross-origin
### Request Body Size Limits
All endpoints that accept request bodies MUST enforce size limits. Request bodies MUST be bounded (e.g., `http.MaxBytesReader` in Go, `express.json({ limit })` in Node.js) to prevent unbounded memory allocation.
Default limit: {size, e.g., 1MB} unless a specific endpoint requires a higher limit with justification.
### CSRF Protection
State-changing endpoints (POST, PUT, PATCH, DELETE) MUST implement CSRF protection. Strategy: {e.g., SameSite=Lax cookies, CSRF tokens, custom header validation}.
### Redirect Validation
Any endpoint that performs HTTP redirects with user-supplied URLs MUST validate the redirect target against an allowlist of permitted domains or paths. Open redirects MUST NOT be permitted.
Example Invocations
create a spec for the webhook delivery service
/sdd:spec
we need to formalize the auth requirements; turn ADR-0019 into a SPEC
write up the requirements for the new payment processor with RFC 2119 keywords
draft the specification document for the artifact-graph feature