| name | spec |
| description | Interactive spec builder: takes a product name + natural language description and produces a full feature spec document (markdown) with machine-readable FeatureSpec JSON. Covers objective, user stories, requirements, acceptance criteria, constraints, integration points, out of scope, AI boundaries, and the JSON extract for /factory. Use when the user says "/spec <product> <description>", "/spec --edit path/to/spec.md", or "/spec --validate path/to/spec.md".
|
| argument-hint | [product] [description] or --edit/--validate path |
| disable-model-invocation | true |
Spec Skill Invoked
User has requested: /spec $ARGUMENTS
Step 0: Parse args
Flags:
--edit <path> — load an existing spec for interactive editing. Strip flag + path.
--validate <path> — validate spec against the target project's decisions without running factory. Strip flag + path.
--project-root <path> — override project root for decision lookup and integration point discovery. Strip flag + path.
Input modes (remaining tokens after flag stripping):
- Edit mode:
--edit was provided. Read the file, display current spec, proceed to Step 2 for refinement.
- Validate mode:
--validate was provided. Read the file, run Step 4 (decision check) only, report and stop.
- Build mode (default): First token is the product name. Everything after is the natural language description. If no description provided, ask:
"Describe the feature you want to add to :"
Step 0.5: Scope gate (build mode only)
Before entering the clarification loop, determine whether the input describes a single feature or a full product/application.
Product signals (any 2+ of these → product, not feature):
- Multiple distinct features or subsystems described (e.g., "voice pipeline + memory + GitHub integration")
- Multiple external services or APIs involved (e.g., Deepgram, Claude, Cartesia, GitHub)
- Custom infrastructure requirements (e.g., WebRTC, streaming pipelines, background workers)
- Multiple data models that aren't related to a single entity (e.g., User, Fact, Conversation, WebhookEvent)
- The description reads like a product brief, not a feature request
Set scope_type based on detection:
- If product detected: set
scope_type = "product" and inform the user:
"This looks like a product spec (multiple features/services). I'll build a product-level spec — acceptance criteria, constraints, boundaries, and architecture overview. No FeatureSpec JSON (use /presearch + /plan-stories to decompose into stories)."
- Otherwise: set
scope_type = "feature"
Proceed to Step 0.75 in either case.
Step 0.75: Clarification loop (build mode only)
Before extracting spec sections, analyze the description for gaps. The goal: every spec section should have enough input that extraction is grounded in user intent, not hallucination.
Coverage checklist
Score each section as covered (description provides clear input or user confirmed a suggestion) or gap (must ask):
| Section | Covered when... |
|---|
| Objective | Description states both what and why |
| User stories | Roles and actions are clear |
| Requirements | Concrete behaviors mentioned (not just "add X") |
| Acceptance criteria | Derived from requirements — covered if requirements are covered |
| Constraints | Any exclusions, NFRs, or known limits mentioned |
| Integration points | Existing systems/models/APIs referenced, OR --project-root set for auto-discovery |
| Out of scope | Explicit or inferable from description |
| Boundaries | Sensitive data or auth implications clear |
| FeatureSpec JSON | Pattern, entity, and field types determinable. N/A for product specs — skip this section. |
Clarification round
For each gap and inferable section, generate questions grouped into batches of 2-4. Each question MUST include a suggested answer:
I have a few questions before building the spec:
1. **User roles**: Who uses this feature? (I'm guessing: end user + admin — the admin manages [entity] settings)
2. **Data model**: What fields does a [entity] need? (From your description I see: name, email. Missing: phone? address? notes?)
3. **Access control**: Can all users create [entity], or only certain roles? (Guessing: any authenticated user)
Rules:
- Lead with your best guess — the user should be able to say "yes" or just correct the wrong parts
- Never ask a question you can confidently answer from the description or project context
- If
--project-root is set, scan the project first — don't ask about things you can discover (existing models, auth patterns, API style)
- Group related questions (don't ask about roles in one round and permissions in the next)
Loop protocol
- Present the batch. Wait for user response.
- Incorporate answers. Show updated coverage status — list which sections moved from gap → covered/excluded. This is mandatory, not optional.
- If gaps remain, present next batch.
- When all sections are covered or excluded, state coverage summary and confirm:
"All sections covered. Ready to generate the spec?"
- User confirms → proceed to Step 1. User adds more context → incorporate, re-show coverage, and re-check.
Exit condition: coverage, not round count. The loop ends when every section is either covered (user provided or confirmed input) or excluded (user explicitly said skip). No round cap. No [INFERRED] markers. No guessing.
Persistent gap escalation
If a section remains a gap after being asked about, the question failed — not the user. Escalate the approach:
- First attempt — suggest-and-ask. Lead with your best guess, let the user confirm or correct. (This is the default from the clarification round above.)
- Second attempt — rephrase with concrete options. Don't re-ask the same question. Break it down smaller or offer 2-3 specific alternatives the user can react to instead of generating from scratch. Example: "For access control, here are three common approaches: (a) any authenticated user can CRUD, (b) creator + admin only, (c) role-based with custom permissions. Which fits?"
- Third attempt — ask if the section applies at all. "Does this feature need access control, or should we explicitly exclude it?" If the user says skip, mark it excluded — that's a decision, not a gap.
Never proceed with a gap. Never infer what the user didn't say. Every section resolves to a user decision.
Fast-path: If the description is detailed enough that all sections score covered on first analysis, skip the loop entirely — state "Description is comprehensive, generating spec" and proceed to Step 1.
Step 1: Extract from description (build mode only)
From the natural language description, extract content for each of the 9 spec sections.
1a: Objective
One sentence: what the feature is and why it exists. If the user only described what, infer the why from context (e.g., "add contacts" → "so users don't re-enter recipient details for every document").
1b: User Stories
1-3 stories in the format: "As a [role], I want to [action] so that [benefit]."
Infer roles from the description. If no roles mentioned, use generic "user." If the product has teams/orgs, include an admin story.
1c: Requirements
Functional requirements as bullet points. Extract every concrete behavior mentioned in the description. Add obvious implied requirements (e.g., if "list contacts" is mentioned, pagination is implied).
1d: Acceptance Criteria
Testable given/when/then statements. One per requirement minimum. These must be behavioral — no implementation references (no function names, file paths, or technology choices).
1e: Constraints
Three categories combined in one section:
- What NOT to build — features the user explicitly excluded, or features that are obviously out of the current scope. If the user didn't mention exclusions, infer reasonable ones (e.g., "no bulk import for v1").
- Project decisions that apply — if
--project-root is set and decisions.sql exists, parse it and list decisions relevant to this feature. If not available, note: "Run /scout --bootstrap first to detect project decisions."
- Non-functional requirements — only if the feature has specific NFRs beyond project defaults (e.g., "p99 latency under 200ms", "HIPAA compliant data handling"). Don't add generic NFRs like "must be fast" — those are noise.
1f: Integration Points
Existing code, services, or data models this feature connects to. If --project-root is set, scan for:
- Related models in the database schema (Prisma, SQL, etc.)
- Existing API routes or functions this feature would call or extend
- Shared utilities (auth, validation, error handling) the feature must use
If no project root available, ask: "Does this feature integrate with any existing code? (models, APIs, services)"
1g: Out of Scope
Explicitly excluded features. This prevents AI agents from hallucinating related functionality. If the user didn't mention exclusions, propose reasonable ones based on the feature (e.g., for "contacts": "contact groups, CRM sync, merge/dedup, CSV import").
Present these as proposals — the user can add or remove.
1h: Boundaries
Three-tier system for AI agent behavior during implementation:
- Always do — safe actions for this feature (e.g., "follow existing test patterns", "use project error handling")
- Ask first — high-impact decisions (e.g., "adding new dependencies", "changing shared models", "modifying auth logic")
- Never do — hard stops (e.g., "never expose sensitive fields in API responses", "never modify migration files from other features", "never bypass permission checks")
Infer from the feature description and project decisions. Sensitive fields get a "never expose" boundary automatically.
1i: FeatureSpec JSON
Skip this section entirely when scope_type = "product".
Extract the machine-readable FeatureSpec from the sections above:
- product — from args
- pattern — infer from description:
- DB/CRUD/API/UI/form/list →
crud-ui
- External service/sync/webhook →
integration
- State machine/approval/lifecycle →
workflow
- Dashboard/metrics/reports →
analytics
- Add function/validator/module/extend →
library-extension
- If ambiguous, ask with equal-detail options
- entity — primary noun from objective
- fields — from requirements. Infer types: names → string, counts → number, flags → boolean, dates → date, status/role → enum (with values), FKs → reference. Sensitive fields marked.
- permissions — from constraints/user stories if access control mentioned
- audit — true if requirements or constraints mention logging/tracking
- integrations — from integration points if external services involved
- ui — from requirements if UI views mentioned. Empty for library-extension.
Step 2: Present and refine
Display the full spec document:
# <Entity> — Feature Spec
## Objective
<one sentence>
## User Stories
- As a <role>, I want to <action> so that <benefit>
- ...
## Requirements
- <requirement 1>
- <requirement 2>
- ...
## Acceptance Criteria
- Given <precondition>, when <action>, then <outcome>
- ...
## Constraints
**What NOT to build:**
- <exclusion>
**Project decisions:**
- [decision-N] <decision content>
**Non-functional (if non-default):**
- <specific NFR>
## Integration Points
- <model/service/utility this connects to>
- ...
## Out of Scope
- <excluded feature 1>
- <excluded feature 2>
## Boundaries
- Always: <safe actions>
- Ask first: <high-impact decisions>
- Never: <hard stops>
## FeatureSpec
```json
{
"product": "...",
"pattern": "...",
...
}
Then ask:
Anything to change? (sections, fields, scope, etc. — or "good" to save)
Note any **excluded** sections from Step 0.5 — these were explicitly skipped by the user and should not appear in the spec.
**Refinement loop:**
- User requests changes → apply, re-display affected section
- User says "good" / "save" / "yes" → proceed to Step 3
- Max 5 rounds. After 5, proceed.
---
## Step 3: Decision conflict pre-check
Locate the target project's `decisions.sql`:
- `--project-root` flag value + `/.claude/decisions.sql`
- Current working directory + `/.claude/decisions.sql`
- If not found, skip: `"No decisions.sql found — skipping conflict pre-check. Run /scout --bootstrap to enable."`
If found, run conflict detection (same logic as `/factory` Step 0.75):
- Skip FeatureSpec JSON conflict check when `scope_type = "product"`. Still check other constraints against decisions.
- Parse decisions from SQL
- Check spec constraints against each decision
- Classify as CONFLICT or WARNING
**Report inline** (informational — don't block):
Decision pre-check:
No conflicts
or:
Decision pre-check:
3 conflicts (will surface in /factory for resolution):
[decision-1] error-handling: spec implies generic errors, project uses AppError
[decision-6] api-design: spec implies REST, project uses tRPC
[decision-10] translations: spec has no i18n, project requires Lingui
Conflicts found here are already included in the Constraints section. `/factory` handles the actual adapt/change resolution.
---
## Step 4: Write spec file
Determine output path:
- If `--edit` mode: overwrite the original file
- If build mode and `scope_type = "product"`: write to `specs/<product-lowercase>-product.md` (relative to project root or cwd). Create `specs/` directory if needed.
- If build mode and `scope_type = "feature"`: write to `specs/<entity-lowercase>.md` (relative to project root or cwd). Create `specs/` directory if needed.
Write the full markdown document. The FeatureSpec JSON is embedded in the `## FeatureSpec` section — `/factory` can extract it from there, or the user can copy it to a standalone `.json` file.
---
## Step 5: Report
**When `scope_type = "feature"`:**
Spec saved:
Objective:
Pattern:
Entity:
Fields: ()
Stories:
Acceptance criteria:
Constraints: (including project decisions)
Out of scope: items
Decision pre-check: <N conflicts, M warnings | clean>
Run: /factory specs/.md
(or extract the FeatureSpec JSON and run /factory specs/.json)
**When `scope_type = "product"`:**
Spec saved:
Scope: product
Objective:
Features: (high-level)
Acceptance criteria:
Constraints: (including project decisions)
Out of scope: items
Next: /presearch specs/-product.md
(or /plan-stories to decompose into stories)