Specify — intent becomes a spec
This is the specify phase of the rsc-sdd chain: constitution → specify → clarify → plan → tasks → analyze → implement → verify → review → ship. Its single job is to turn a fuzzy intent into a written specification that states WHAT the change is and WHY it matters — and nothing about HOW it gets built.
A spec is a contract about behaviour and outcomes, readable by a non-technical stakeholder and precise enough that a plan can be derived from it. The output is one file: 02-DOCS/wiki/sdd/specs/<slug>.md, indexed in 02-DOCS/wiki/index.md (the Knowledge map; root CLAUDE.md keeps only a short pointer).
Detect the moment — and hold the gate
Fire on the faintest sign the user is thinking about a new feature or change — not just "spec this", but any musing: "I want to add…", "can we build…", "it should also…", "wouldn't it be nice if…", "what if we…", "I've been thinking about…", "let's brainstorm…", "tengo una idea", "se me ha ocurrido", "¿y si…?", "estaría guapo que…", "quiero añadir…", "necesito que haga…". This phase owns that moment, even if a stack skill (nextjs/fastapi/flutter…) also fired and is itching to build it. Catch it here first — being too eager to brainstorm is cheap; skipping it is expensive.
The hard gate — every feature, including the "obvious" ones:
No implementation starts — not a stack skill, not
plan-to-code, not "just a quick version" — until the user has approved a design (the spec at step 9 below) andplanhas produced the technical plan + task list. If the user says "just build it", do not; name the gate in one friendly line and run the loop. "Too simple to need a design" is the rationalization that wastes the most work — every feature gets the loop. The only thing that skips it is a literal one-line, zero-risk change (typo/copy/config) — say so out loud and do it.
You are not slowing them down; you make the intent reviewable before code exists, which is far cheaper than discovering the misunderstanding in a PR. End every spec by handing to clarify/plan — never to implement.
Your first sentence is not a verdict on the idea
Catching the intent eagerly, above, is right. What comes after catching it is where this phase has been failing: the opening line validates. "Great idea", "makes sense", "that would be really useful" — or, since half this catalog's work happens in Spanish, "buena idea", "qué gran idea", "me encanta", "tiene todo el sentido" — is a verdict you do not have the evidence for, delivered at the cheapest possible moment to be wrong, to someone who still believes you. The ban is on the judgement, in any language, not on any particular wording: the list above is what it looks like, not what it is limited to. A spec built on a validated premise is coherent, plannable, testable and pointed at the wrong thing; nothing downstream can catch that, because every later gate compares artifacts to each other and they all agree.
So the first response to an intent carries exactly two things:
- A restatement of what you understood, in one sentence, so a misread surfaces now.
- The strongest objection you can actually articulate from what you already know or can cheaply check — why this might not be worth building, or might be the wrong shape.
Never a judgement of the idea's quality, in either direction. And go look before you object: an objection sourced from the repo, the wiki or a prior spec is worth ten sourced from your priors.
If, having looked, there is no real objection, say so in one line and move on — silence is a valid result. Manufacturing an objection to look rigorous is the same failure wearing the opposite coat, and a doubt that fires on every idea measures you, not the idea. A typo fix does not get a restatement and an objection; it gets fixed.
And the objection never blocks. It is a divergence, not a veto: the user often holds context you do not — a business reason, a conversation elsewhere, a constraint nobody wrote down. If they choose to proceed anyway, do not re-argue. Write the reason into the spec and continue. That is what keeps this from being decorative without giving it power it should not have: it cannot stop the decision, it can only stop the decision from being tacit. If the thing later goes wrong, the record says the doubt was raised and overridden — not that nobody looked.
Offer autopilot once, right here. At this boundary, propose how to run the rest of the chain:
"¿Quieres que lo lleve hasta el final yo solo — spec → plan → código → verify, parando solo si algo es ambiguo — o prefieres que pare a que apruebes en cada fase?"
A yes engages autopilot (../sdd/SKILL.md): you still write the spec and every artifact, but you auto-advance through the phases without re-asking — that up-front yes is the approval that satisfies the hard gate above, for the whole run. A no (or silence) keeps the default gated flow: write the spec, hand to clarify/plan, stop for approval before code. Either way the spec gets written; autopilot only changes whether you pause between phases — and it still stops for genuine ambiguity, hard failures, or destructive/outward actions (ship still confirms). If sdd.autopilot: true in config, autopilot is the default — still surface it once.
The one rule that defines this skill
A spec is a contract: what the system will observably do, and why that matters. Every line either belongs in the contract or belongs to how the contract gets honoured — and the second kind is plan's, not yours. Framework, table schema, library, endpoint shape, file path, algorithm: all of them are how, so the moment one appears the document has stopped being a contract.
One question settles every judgement call in this skill: is this a clause of the contract, or a detail of how it gets met?
If you cannot state a requirement without naming the technology, that is a real open question — record it as a typed point to clarify, do not guess the answer.
Model tier — balanced (opt-in routing)
This phase's default model tier is balanced — it drafts the what/why spec through dialogue, not architecture. Routing is off unless models.enabled: true in 02-DOCS/wiki/sdd/config.yaml. When on: resolve this phase's tier (models.overrides wins over models.phases), map it to a model via models.tiers, and apply per ../sdd/references/model-routing.md — announce the switch per the accompaniment dial when it differs from the session model, and dispatch any Task/parallel subagents on that model. Routing off or no profile → honor the session model silently. Never fake a switch a tool can't make; skip routing on a one-line change.
Read the room first (accompaniment dial)
Before asking anything, read 02-DOCS/wiki/harness/user-profile.md for the technical level and accompaniment level, and adapt:
- L0 "cavernícola" — infer aggressively from the intent and any existing wiki/constitution. Ask only the questions whose answer would change the contract. Draft, show, move on.
- L1 "breve" — one line of why per question; ask the few that genuinely matter.
- L2 "explica decisiones" — justify each requirement as you record it; surface the trade-offs you inferred.
- L3 "acompañamiento total" — explain what a spec is and is not, walk every section, ask freely (still one round per frontier, never crossing a dependency), confirm each answer before recording it. Ideal for non-technical users.
If no profile exists, default to non-technical framing and keep questions plain. Never assume fluency.
FRAME before you ask anything — from idea-refinement
Before the frontier round, write five lines. They are the FRAME block of ../idea-refinement/SKILL.md, a skill this catalog ships and the README advertises, and that until now no phase invoked:
- Actor — who is struggling, and in what situation?
- Current workaround — what do they do today, including doing nothing?
- Desired progress — what observable change would make this useful?
- Constraints — time, money, trust, regulation, the product that already exists.
- Known vs assumed — separate what you have actually seen from what merely sounds plausible.
Then name the directions worth considering, and "don't build it" is one of them — enumerated, with its consequence, not offered as a courtesy. A direction you can dismiss in one line still had to be written down first; the ones that never get written are the ones that never get weighed.
If the idea arrives phrased as a feature ("an AI dashboard"), FRAME is where it turns back into a problem and an outcome ("operators need to spot failed jobs before customers report them"). The original phrasing stays as one candidate, not as the conclusion.
Ceremony scales with the stakes here as everywhere: FRAME earns its five lines on anything with real scope, and on a small change it collapses to the one line that matters.
Questioning discipline — ask the frontier, never cross a dependency
The failure mode of specs is the wall of twenty questions. The cure is not one question per turn: that spends a turn of the user's time per question even when the questions do not touch each other. The cure is the frontier.
- Infer first. Read the
constitution(02-DOCS/wiki/sdd/constitution.md), the existing wiki, and sibling specs. Fill every section you reasonably can from what already exists. - Ask only the gaps that change the contract. A gap earns a question only if a different answer would move scope, a goal, a user, or an acceptance criterion. Cosmetic gaps become typed points to clarify, not questions.
- Ask the whole frontier in one round. The frontier is every remaining gap whose prerequisites are already settled — the questions you can ask now without guessing at answers you have not heard yet. Number them, give each your recommended answer, then wait. Where the harness offers a native question selector, use it; where it does not, emit the same round as numbered text.
- Never cross a dependency. A gap whose answer depends on another question open in this round belongs to a later round. Recompute the frontier after every set of answers: settled decisions push it outward and unblock what waited on them. If an answer redefines a question you already emitted in the same round, discard that question out loud and re-ask it next round rather than using an answer given under a premise that just moved.
- Facts are your job; decisions are the user's. When a frontier question needs a fact from the environment, go find it — and do not block on it. A running search is an unsettled prerequisite, so only the questions downstream of it wait; ask the rest of the frontier now.
- When inference and asking both fail, type it. Anything unresolved becomes a typed entry in Points to clarify — the handoff contract to
clarify, not a defect.
A frontier of one is one question, and needs no apology. A frontier of zero is no question at all: never invent one to look diligent.
What a good spec contains
Write these sections into 02-DOCS/wiki/sdd/specs/<slug>.md using references/spec-template.md. Keep every line about behaviour and intent.
| Section | Holds | Watch for |
|---|---|---|
| Problem & why | The pain, the cost of not solving it, the trigger | A "solution" disguised as a problem |
| Cost of not building it | What concretely happens if nobody does this, and what it costs | Softening a genuinely small cost — "not much" IS the finding |
| The cheapest alternative | What would solve most of it without building this, and why that is not enough | "Nothing" — there is always a manual workaround or a smaller version |
| Goals | What success delivers, in outcome terms | A "goal" that's actually a HOW |
| Non-goals / out of scope | What is explicitly NOT done now — adjacent work, deferred features | Silence — unsaid scope becomes assumed scope |
| Users & context | Who acts, their context, what they're trying to achieve | An imagined user no one asked for |
| Behaviour | What the system does, in observable terms, incl. main + edge + error paths | A verb that's actually a HOW ("queries", "caches") |
| Acceptance criteria | Testable, binary checks that say "done" | Vague critera ("works well", "is fast") |
| Points to clarify | The typed handoff to clarify — see the four types below |
An untyped list, or pretending there are none |
Acceptance criteria carry the weight
Each criterion is a binary, observable statement — true or false, no judgement call — phrased so verify can later check it and tasks can derive a done-check from it. Prefer the Given / When / Then shape; it forces a concrete trigger and a concrete outcome.
Given a signed-in user with an empty cart
When they open the checkout page
Then they see an empty-cart message and the "pay" button is disabled
A criterion that needs a human to "decide if it's good enough" is not done yet — sharpen it or move the soft part to Points to clarify.
Two of those sections are enforced, not suggested. For a spec dated 2026-09-06 or later, spec:gate refuses the file if Cost of not building it or The cheapest alternative is missing or still holding the template's guidance. Specs written before that date are exempt — they cannot answer honestly after the fact. The two exist because every other gate in the chain compares artifacts to each other, so a spec that is wrong-but-coherent passes all of them; these are the only two lines that ask whether the thing should exist at all.
Points to clarify carry a type
Points to clarify is the handoff to clarify, and it holds four different objects that need four
different actions. An untyped list makes clarify treat all of them as questions, so it re-asks what
you already decided and touches what you deliberately deferred. Type every entry:
| Type | What it is | What clarify does with it |
|---|---|---|
| pregunta abierta | Formulable with precision right now, unanswered | Asks it |
| suposición tomada | You decided it; the basis is written down | Validates it — does it still hold? |
| decisión diferida | Sharp, out of this cycle on purpose | Leaves it alone |
| área no formulable | Known to be coming, not yet sharp enough to phrase | Notes it; it graduates when it sharpens |
The test that separates the last two from a question is sharpness, not difficulty: can you state
the question precisely now? — not can you answer it? Sharp → pregunta abierta. Not sharp →
área no formulable. Beyond what this change is for → Non-goals, where it never graduates.
Write the type in bold at the head of the entry, and give a suposición tomada its basis:
- **suposición tomada** — el enlace caduca en minutos, no en horas. *Base:* el patrón de los
proveedores que ya usamos. *Riesgo:* si el soporte pide horas, el criterio de aceptación cambia.
An entry with no type is read as pregunta abierta, the costliest of the four. The default never saves you work.
The pass, end to end
Run these in order. It is a collaborative dialogue, not a form you fill in silence — and you do not skip to a design dump. Track the steps with a todo list so none is dropped.
1. EXPLORE context → profile + sdd config + constitution + existing specs + wiki + recent git
2. SCOPE check → if the request is several independent subsystems, DECOMPOSE into sub-specs first,
then brainstorm the FIRST one; each gets its own spec → plan → build cycle
3. RESTATE + OBJECT → one sentence of what you understood, plus the strongest objection you can
actually make. No verdict on the idea. No objection to make? Say so, one line
3b. FRAME (idea-refinement)→ actor · current workaround incl. doing nothing · desired progress ·
constraints · known vs assumed; "don't build it" enumerated as a direction
4. ASK the frontier → only gaps that change the contract; whole frontier per round, numbered, each
with your recommendation; never cross a dependency; wait, record, recompute
5. PROPOSE 2-3 approaches → distinct directions with honest trade-offs; lead with your recommendation and why
6. PRESENT the design → section by section (problem, users, behaviour, acceptance), scaled to complexity;
after EACH section ask "does this look right?" and adjust before moving on
7. WRITE the spec → 02-DOCS/wiki/sdd/specs/<slug>.md (WHAT/WHY), index it in 02-DOCS/wiki/index.md
(the Knowledge map; root CLAUDE.md keeps only a short pointer), commit if a repo
8. SELF-REVIEW → run the EXIT GATE (below) until green; scan for contradictions, ambiguity,
scope creep; fix inline. On L2/L3 or high risk, add a FRESH-EYES review
9. USER APPROVES → ask them to read the written spec and confirm; loop on changes until they approve
10. HAND OFF → only now, result envelope → clarify/plan. NEVER to implement.
Steps 5-9 are the gate, stated once under Detect the moment above and not restated here: approval at step 9 is what unlocks implementation.
<slug> is a short kebab-case name derived from the feature (e.g. bulk-csv-import, magic-link-login). If a spec with that slug exists, read it and update rather than overwrite.
Exit gate — checked, not felt
"Complete enough to plan against" cannot tell done from not-done, and the write/review/approve steps are visible while you are still asking, pulling attention toward being finished. So the bound is a property of the file, not of your confidence:
Every template section carries content or an explicit typed open point, and no section holds an unmarked assumption.
Run npm run spec:gate <path> on the spec you just wrote (no path: the whole corpus). It reports the
missing and the empty sections by name, and it prints what it does not check — the unmarked
assumption is yours to catch, because no parser can. A red gate means the spec is not closed: name
the section that failed and fix it before step 9.
A gate that has never been seen fail is not known to work, so this one ships with the test that
watches it fail and pass (tests/spec-gate.test.js).
Fresh-eyes spec review (step 8, scaled to the dial)
The author's own context is blind to its own gaps — the same mind that wrote the spec self-reviews it with the same blind spots. For an L2/L3 user or a high-risk spec (multi-subsystem, security/data, irreversible, or large scope), dispatch a fresh-context subagent to read the written spec cold, before the user-approval gate (step 9), and fold its findings in:
- Hand it only the spec file (and the constitution), not your dialogue or reasoning — a fresh reviewer that inherits your context inherits your blind spots.
- Calibrated checklist: placeholders/TODOs, internal contradictions, ambiguity that would stall planning, unstated assumptions, scope creep, and YAGNI (asked-for-but-unneeded). Tell it to only flag issues that would cause a real problem at planning time and to approve unless there are serious gaps — a fresh reviewer that nitpicks everything is as useless as no reviewer.
- It returns
ApprovedorIssues foundwith a short list; you fix the real ones inline, then proceed to step 9.
Skip it for L0/L1 on a small, low-risk spec — the self-review scan is enough there; don't spin up a subagent to vet a two-paragraph spec. Like the rest of the chain, ceremony scales to the stakes.
Approval is its own exchange (step 9)
An answer to a question is not an approval. If you asked the user to decide something, they answered that question and nothing else. Their answer is an input to the spec — and it changes the spec, which means any approval you were holding before the question is the approval of a document that no longer exists.
Questions and approval are two exchanges, in that order:
ask → user answers → fold it in → say what changed → show the revised spec → ask for approval
- The recommended-option shape is where this fails most easily. When the user picks the option you recommended, the spec looks unchanged and consent looks implied. Neither is true — you proposed, they chose, the spec moved.
- None of these are approval: an answer to your question; a "go ahead" about some other step; silence; the request that started the task. If you cannot quote the words that approved this spec, you do not have approval.
- Autopilot is still valid — an up-front "run it all yourself" authorizes the whole run, and
that is a real answer to a real question. What changes is the bookkeeping: record it as
approved in autopilot, not item by item, in the spec's
status:. The spec then becomes the artifact the user reviews after the fact, and the work claims correspondingly less certainty about having captured their intent. Writing "aprobada" flat, when what happened was a blanket go-ahead, is the record telling a small lie about the strongest gate in the chain. - Rejection is information — keep it. If the user turns the spec down, revise it in place and
append the reason to
## Revisions. Never delete and start clean: what they rejected, and why, is the most useful thing in the file.
Worked shape (abridged)
# Spec — Magic-link login
## Problem & why
Password resets are the #1 support ticket and a sign-up drop-off point.
A passwordless email link removes the password entirely.
## Cost of not building it
Password resets stay the top support ticket — roughly N a week — and the
sign-up funnel keeps leaking at the password step.
## The cheapest alternative
A better password-reset email. It removes some of the tickets and none of the
drop-off, because the friction is the password itself, not the reset.
## Goals
- A user can sign in with only their email, via a one-time link.
- No password is ever stored or required.
## Non-goals / out of scope
- Social login (Google/Apple) — deferred.
- Replacing existing sessions for already-signed-in users.
## Users & context
A returning user on a new device who does not remember a password.
## Behaviour
- Main: user enters email → receives a link → following it signs them in.
- Edge: an expired link shows a "request a new link" path.
- Error: an unknown email reveals nothing (same response as a known one).
## Acceptance criteria
- Given a registered email, When the user requests a link and follows it within
its validity window, Then they are signed in.
- Given an expired link, When it is followed, Then sign-in is refused and a new
link can be requested.
## Points to clarify
- **pregunta abierta** — ¿cuánto vale la ventana de validez del enlace?
- **suposición tomada** — la ventana es corta, en minutos. *Base:* el patrón de los proveedores que
ya usamos. *Riesgo:* si soporte pide horas, cambia el criterio de aceptación.
- **decisión diferida** — límite de peticiones por email; fuera de este ciclo.
- **área no formulable** — qué pasa con las cuentas compartidas; sospecho que hay una pregunta y
todavía no sé enunciarla.
Note what is absent: no token format, no table, no email provider, no framework. Those are plan's job.
Optional proposal / pre-execution briefing
For a tiny feature, skip this. For ambiguous, architectural, high-risk, high-review-cost or research-heavy work, write a proposal before the spec:
02-DOCS/wiki/sdd/proposals/<slug>.md
Proposal grammar:
# Proposal — <slug>
## Problem
## Intent
## Scope / Non-scope
## Research input
## Alternatives considered
## Tradeoffs
## Risks
## Rollback
## Success criteria
## Recommendation
The proposal is allowed to mention options and tradeoffs; the spec that follows still stays WHAT/WHY. If research came from a transcript, doc, spike, or external briefing, cite it in Research input so the decision trail survives the chat.
Anti-patterns → STOP
Only failures with no positive statement elsewhere in this skill. The rules about the frontier, the constitution, the 2-3 approaches, the gate, and answer-is-not-approval are stated positively above (§Questioning discipline, §Detect the moment, the pass, §Approval is its own exchange) and are not repeated here as prohibitions: naming a behaviour makes it more available, not less.
| If you're about to… | Reality / Fix |
|---|---|
| Name a framework, table, endpoint, or library | That's HOW. Strip it; describe the behaviour instead, or log the open question. |
| Write "it should work well / be fast / be intuitive" | Not testable. Make it a binary Given/When/Then or move it to Points to clarify. |
Hand to plan/implement before the user approved the written spec |
The approval at step 9 is the gate. No design approved → nothing gets built. |
| Skip non-goals because "it's obvious" | Unsaid scope becomes assumed scope. State what you are not doing. |
| Resolve every ambiguity yourself to look finished | Inventing answers is worse than naming gaps. List them in Points to clarify. |
| Start designing the solution because it's clearer | Stay on WHAT/WHY. The plan is a later, separate phase. |
| Write the spec somewhere other than 02-DOCS/wiki/sdd/specs/ | That's the canonical location the rest of the chain reads. Use it. |
Project grounding (02-DOCS + CLAUDE.md)
- Read
02-DOCS/wiki/sdd/config.yamlif present. If it is missing and the change is non-trivial, recommendsdd-initbefore proceeding; if the user asks to continue, record the missing config as a risk. - Read
02-DOCS/wiki/sdd/constitution.mdfirst — its principles are inherited constraints, not things to re-decide. If it's missing, note that the project has no constitution yet and suggest theconstitutionphase before continuing (you can still draft a spec, but flag the absence). - No constitution yet? Still write the spec, but inherit nothing — lean harder on the wiki and the user's answers, and record every constraint you would have inherited as a point to clarify instead of assuming it.
- Write the spec to
02-DOCS/wiki/sdd/specs/<slug>.md. Create the directory if absent. - Add a row in
02-DOCS/wiki/index.md(the Knowledge map; rootCLAUDE.mdkeeps only a short pointer) linking the new spec under thesdd/specstopic (additive only — never delete existing rows). Create the index if absent. - Log the spec's creation and any significant scoping decision to
02-DOCS/wiki/sdd/decisions.md(append-only), so the chain keeps a trace of why scope landed where it did. This is the canonical SDD decisions log shared withconstitutionandplan— not the harness's own02-DOCS/wiki/harness/decisions.md.
Result envelope
End with:
{
"status": "complete",
"executive_summary": "Spec written with open points ready for clarify.",
"artifact": "02-DOCS/wiki/sdd/specs/<slug>.md",
"next_recommended": "clarify",
"risk": "low|medium|high",
"skill_resolution": {
"used": ["specify"],
"missing": [],
"fallback": [],
"compact_rules": ["Keep specs WHAT/WHY only.", "Acceptance criteria must be observable."]
},
"evidence": ["spec path exists", "proposal path if used", "open points listed"]
}
Next in the chain
A spec is the input to clarify, not the finish line. End by pointing there:
"Spec written to
02-DOCS/wiki/sdd/specs/<slug>.mdwith N open points. Next: runclarifyto resolve them and de-risk the spec before planning."
If clarify surfaces answers, they get baked back into this same spec file. Only once the spec is de-risked does plan derive the technical approach.
See Also
../constitution/SKILL.md— the project principles this spec inherits as constraints.../clarify/SKILL.md— the next phase: resolves the Points to clarify and de-risks the spec.../plan/SKILL.md— turns the de-risked spec into a technical implementation plan (the HOW).../harness/SKILL.md— the 02-DOCS wiki + accompaniment dial + decisions log this skill honors.references/spec-template.md— the exact section template written to02-DOCS/wiki/sdd/specs/<slug>.md.references/eliciting-requirements.md— inference checklist + the frontier-round elicitation pattern.
Orientación (siempre)
Cierra cada turno con el bloque-brújula (📍 dónde estás · ✅ qué hiciste · 🧭 por qué · ➡️ siguiente, terminando en pregunta), calibrado al dial de 02-DOCS/wiki/harness/user-profile.md. Nunca termines en seco. Protocolo completo: skill orient → skills/orient/references/orientation-contract.md. (Defiere a suggest el "¿instalo la skill que falta?".)