Skill: specify
Turns a one-line idea into a reviewed spec.md: a lightweight interview captures and stress-tests the idea, then the skill drafts a product spec (context → goals → user stories → acceptance criteria → NFRs → KPIs), validates it Socratically, and runs a clean-context critic before writing. Less typing, more reviewing. This file is the spine; detail lives in references/.
The Socratic machine, the critic, and the size matrix are shared — this skill keeps only its deltas:
→ ../_shared/socratic-loop.md · ../_shared/critic.md · ../_shared/size-matrix.md · ../_shared/ask-style.md
Depth governs question volume + autonomy (and which ideation analyses run) → ../_shared/interview-depth.md.
Document prose follows the project's artifact_language setting — section headings, frontmatter and machine tokens stay English → ../_shared/artifact-language.md.
Owner
PM + Tech Lead (co-authors). PM drives goals / non-goals / KPIs; Tech Lead drives context patterns and the acceptance-criteria coverage.
Inputs
<slug>— kebab-case feature slug.- (Optional)
CONTEXT.md— the two-level glossary: read both repo-root (project-wide) anddocs/features/<slug>/CONTEXT.md(feature-scoped); per-feature wins on conflict →../glossary/SKILL.md. If present, its roles/terms are canonical and override anything that contradicts them. docs/features/<slug>/.size— depth hint (MVP vs Full per the size matrix). Read if present; established here if absent (step 1 classifies + writes it), so downstream stages never silently default to M.classify-sizere-classifies when scope changes.- (Optional) prior notes / a reference module / a ticket the user already has.
Protocol
- Ensure the settings file (first thing, after this skill's own gate). If
.claude/sdd.local.mdis absent, create it now from the canonical template — documented defaults + the self-documenting body — and patch.gitignore; if it exists, read it and never overwrite. The one procedure lives in../_shared/settings-file.md. Creating is unconditional; changing values is only ever offered byconfig. Say one line: «.claude/sdd.local.mdcreated with documented defaults —/sdd:configto tune it». Then read context + set the interview depth. If aCONTEXT.mdexists (read both repo-root anddocs/features/<slug>/— per-feature wins on conflict), load its## Glossaryas session state (canonical roles + terms). If.sizeexists, read it to size the spec's depth; if it's absent, establish it now — run theclassify-sizeprotocol inline (the canon:../classify-size/SKILL.md+ the mapping in../_shared/size-matrix.md); the four signals fold into one bundledAskUserQuestionhere (ateasydepth, take the matrix default and record it in the assumptions ledger), and writedocs/features/<slug>/.size+.route(the route defaults from the size — XS/S→quick, M→standard, L/XL→full— and is confirmed in the same bundled question, per the Routes table in../_shared/size-matrix.md) — so every later stage reads a real size instead of silently defaulting to M (the gap that otherwise surfaces only atplan-tests).classify-sizestays the utility to re-classify when scope changes. Ifdocs/architecture-map.mdexists (fromsurvey), read it so the spec is architecture-aware — it informs §1 Context, §2 Constraints, and §3 Non-goals (what the existing system already does / can't do). Absent → suggest runningsurveyfirst, but proceed (the spec is product-level and can be captured without it). Do not leak the map's tech into §5 AC — AC stay business-observable; the map shapes constraints, not acceptance criteria. Then set the interview depth (the opening question): readinterview_depthfrom the settings file ensured in the first sentence of this step (else default medium), and — unless a--depth=easy|medium|hardarg was passed (which skips the question) — ask ONE depth-selectionAskUserQuestionphrased per../_shared/ask-style.md, with the saved/medium value as the «(Recommended)» first option, overridable per run. The chosen level governs the step-2 deep-dive volume, the step-3 ideation suite, and the step-7 Socratic volume →../_shared/interview-depth.md. (Completeness — §5's 5-type AC floor — is unaffected by depth.) - Capture the idea (interview front). One
AskUserQuestionfor the raw idea in 1–3 sentences (persist verbatim as the baseline). Then a Socratic deep-dive across problem clarity / success criteria / constraints / strategic fit, delivered in batches of 2–3 — its volume scales with the depth dial (easy: only the few un-inferable ones, then a stated-assumptions ledger; medium: 3–5; hard: walk every angle, foreground each trade-off). Phrase every question per../_shared/ask-style.md. - Ideation suite (depth-gated, named subagents). Run the ideation analyses as named-subagent dispatches gated by the interview-depth dial (size as a secondary trimmer) →
./references/ideation.md: easy → skip the suite (deep-dive only; the chosen approach is recorded as a ledger assumption); medium →researcher(sdd:researcher, competitive/web) +devils-advocate(sdd:devils-advocate, failure-mode mode); hard → full suiteresearcher+strategist(sdd:strategist, 3 approaches) +analyst(sdd:analyst, multi-perspective) +devils-advocate, then the Claude-proposed RICE/feasibility confirm. Analyses stay product-level (no tech names — that'sdesign); the confirmed recommendation becomes §1 ¶3. Dispatch withsubagent_type: "sdd:<name>"per../_shared/agent-roster.md(general-purposefallback);researcherneeds web — accept itsRESEARCH_LIMITEDoutput as a noted gap if web is unavailable. - Reconcile the glossary in-flow (a hard rule, at every depth). On every new or unknown domain term that surfaces in the interview or the draft, invoke
glossary <slug>for it immediately — compare it againstCONTEXT.mdand add/update the definition before continuing. By the time the spec is written, every §4 role and §5 domain term is already glossary-canonical; the glossary is never a deferred batch. (Plan-mode nuance: still decide add/update per term in-flow; if writes are blocked until the spec write-point, persist the reconciled terms together with the spec, but never skip the per-term compare.) - Ask which extra channels to read (multi-select
AskUserQuestion): reference module code / project docs / MCP-Atlassian (Confluence/Jira) / knowledge-base / none. For each picked channel ask the specific path/query — no silent broad scans. - Read the template + draft §1–§8. Read
./templates/spec.md(its<!-- instruction -->comments are the per-section contract). Draft per./references/draft-generation.md: per-section sources, the 5 AC coverage types (happy / error / authorization / domain invariant / cross-context), and the stack-agnostic forbidden-token rule for acceptance criteria. - Socratic validation. Walk §4 US → §5 AC → §6 NFR → §7 KPI with the shared 4-state machine (per-decision question volume scales with the depth dial — at easy, the un-asked decisions land in the assumptions ledger for a batch veto). Specify delta →
./references/socratic.md: AC has a 5th option «Add another AC»; the §5 coverage gate enforces two floors after drops/OQ-migrations — (a) ≥1 AC of each of the 5 coverage types, and (b) ≥1 AC per retained §4 user story (regenerate/add a replacement if a type or a user story is left empty). Both are floors, not dials — enforced at every depth; only the question volume scales. The (b) floor closes the §4→§5 link so the downstreamsequencesuse-case coverage +reviewtrace can't be undermined by a user story that lost its only AC. Maintain the edits-log. - Critic + write + commit. Dispatch the
criticagent —subagent_type: "sdd:critic"(model perjudgment_model, efforthigh—xhighon L/XL viaCLAUDE_CODE_EFFORT_LEVEL; clean-isolated context per../_shared/agent-roster.md) — with the specify delta in./references/critic.md(over../_shared/critic.md) — inline the draft + edits-log, it ReadsCONTEXT.md+ the idea source itself. Resolve findings viaAskUserQuestion(Accept revert / Accept amendment / Override-with-rationale → §1 ¶4 bullet). Run the forbidden-token regex scan as the F6 backstop. On pass, writedocs/features/<slug>/spec.md(glossary already reconciled in-flow per step 4) and propose commitspec: <slug>. Register on the roadmap: indocs/roadmap.md(viaroadmap) set the matching step'sStatus: spec'dand link this feature folder; no matching step → append one (source anchor = this spec). (If there's no roadmap yet, skip — it's optional.) Then emit the stage-handoff block per../_shared/handoff.md— What I did + Review (spec.md,.size,.route) + Run next — resolve the next stage per.route(the Routes table in../_shared/size-matrix.md; route-resolved variant in handoff.md): forward/sdd:clarify <slug>;clarify's N/A condition = zero §8 open questions and no AC flagged ambiguous, skip target/sdd:ux-flows <slug>(onquick— auto-skip with the reason + inverted↳ or; onstandard— offer the↳ or; onfull— no skip line). When clarify is legally skipped, carry the next condition forward: evaluateux-flows' N/A condition too (no human-facing UI — every §4 actor a system/service, or the repo has no UI at all, per../_shared/size-matrix.md) → holds ⇒ the skip target becomes/sdd:design <slug>. (Ifcriticis unavailable, fall back to ageneral-purposeAgent with the same delta.)
Definition of Done
docs/features/<slug>/spec.mdwritten; all sections filled (or<!-- N/A: reason -->).docs/features/<slug>/.sizeand.routeexist after this stage (read if present, else classified + written here) — the backbone no longer reachesdesign…plan-testson a silent M default, and every handoff resolves per a real route.- §5 holds ≥1 AC of each of the 5 coverage types after drops/OQ-migrations, every §4 user story has ≥1 AC (the use-case floor — no retained US left with zero ACs), and 0 forbidden tokens (HTTP verbs / URL paths / status-code numerics /
module.error_namestrings / JSON fragments / SQL constructs). - §4 roles match the
CONTEXT.mdglossary exactly (no inventeduser/admin). - §8 Open Questions each carry owner + due (no lone «TBD»).
- Edits-log maintained; critic ran on the post-Socratic draft; every finding resolved or overridden.
- The step-8 critic + the forbidden-token regex backstop are this skill's structural self-check (
../_shared/self-check.md); its result is reported in the handoff.
Anti-patterns
- Skipping the interview front and reconstructing the idea from the model's guess. Capture + deep-dive must actually fire
AskUserQuestion. - Naming concrete technologies in §1–§3 (a specific datastore, broker, framework, or library). The spec is WHAT + WHY; technology choices belong to
design. - Implementation leak in AC — HTTP/status/error-code/SQL detail. That mapping lives in
apianddecide-adr. - Running the full ideation suite at
easydepth — over-production. The depth dial gates it (easy skips entirely; medium runs research + devil's-advocate; hard runs all). Feature size only trims volume within a level — it's no longer the gate. - Inventing competitors / RICE numbers to fill the ideation pass. Better
N/A — internal toolthan fake research; accept theresearcheragent'sRESEARCH_LIMITEDover fabricated rows.
References & template
./references/ideation.md— depth-gated ideation orchestration: which named subagent (researcher/strategist/analyst/devils-advocate) runs at which level, what each returns, how outputs feed the spec.../_shared/interview-depth.md— the easy/medium/hard dial set in step 1 (question volume, autonomy, which analyses run)../references/draft-generation.md— per-section sources, 5 AC coverage types, stack-agnostic forbidden tokens../references/socratic.md— specify's delta over the shared Socratic loop../references/critic.md— specify's delta over the shared critic (F6 = forbidden tokens)../templates/spec.md— output scaffold; inline comments are the per-section generation contract.