specpipe 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -311
- package/package.json +2 -1
- package/src/cli.js +16 -6
- package/src/commands/diff.js +1 -1
- package/src/commands/init-agents.js +48 -20
- package/src/commands/init-global.js +104 -33
- package/src/commands/init-interactive.js +71 -0
- package/src/commands/init.js +68 -20
- package/src/commands/remove.js +159 -49
- package/src/commands/upgrade.js +21 -56
- package/src/lib/agent-guards.js +34 -78
- package/src/lib/agent-install.js +38 -25
- package/src/lib/agents.js +53 -11
- package/src/lib/claude-global.js +55 -77
- package/src/lib/hooks.js +203 -0
- package/src/lib/installer.js +104 -62
- package/src/lib/reconcile.js +13 -8
- package/templates/{.claude/hooks → hooks}/file-guard.js +26 -21
- package/templates/hooks/specpipe-read-guard.sh +94 -21
- package/templates/hooks/specpipe-shell-guard.sh +121 -29
- package/templates/rules/specpipe-rules.md +77 -0
- package/templates/skills/sp-build/SKILL.md +101 -1
- package/templates/skills/sp-build-behavior-matrix/SKILL.md +876 -0
- package/templates/skills/sp-challenge/SKILL.md +34 -0
- package/templates/skills/sp-challenge-behavior-matrix/SKILL.md +289 -0
- package/templates/skills/sp-explore/SKILL.md +132 -0
- package/templates/skills/sp-explore-behavior-matrix/SKILL.md +862 -0
- package/templates/skills/sp-fix/SKILL.md +73 -1
- package/templates/skills/sp-fix-behavior-matrix/SKILL.md +338 -0
- package/templates/skills/sp-investigate/SKILL.md +70 -0
- package/templates/skills/sp-investigate-behavior-matrix/SKILL.md +718 -0
- package/templates/skills/sp-plan/SKILL.md +90 -0
- package/templates/skills/sp-plan-behavior-matrix/SKILL.md +1037 -0
- package/templates/skills/sp-review/SKILL.md +29 -3
- package/templates/skills/sp-review-behavior-matrix/SKILL.md +294 -0
- package/templates/.claude/CLAUDE.md +0 -79
- package/templates/.claude/hooks/path-guard.sh +0 -118
- package/templates/.claude/hooks/self-review.sh +0 -27
- package/templates/.claude/hooks/sensitive-guard.sh +0 -227
- package/templates/.claude/settings.json +0 -68
- package/templates/docs/WORKFLOW.md +0 -325
- package/templates/docs/specs/.gitkeep +0 -0
- package/templates/rules/specpipe-guards.md +0 -40
- package/templates/scripts/test-hooks.sh +0 -66
- /package/templates/{.claude/hooks → hooks}/comment-guard.js +0 -0
- /package/templates/{.claude/hooks → hooks}/glob-guard.js +0 -0
|
@@ -0,0 +1,862 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: |
|
|
3
|
+
Feature discovery as Client Technical Lead — clarify one feature deeply
|
|
4
|
+
before writing spec. Asks targeted questions until requirements are concrete
|
|
5
|
+
enough to hand off to /sp-plan.
|
|
6
|
+
Use when asked to "explore this feature", "khám phá tính năng", "tôi muốn làm",
|
|
7
|
+
"I want to build X", "scope this feature", "discovery", or "clarify requirements".
|
|
8
|
+
Proactively invoke this skill (do NOT write spec directly) when the user
|
|
9
|
+
describes a new feature in vague or ambiguous terms — running /sp-plan with
|
|
10
|
+
unclear requirements produces unclear specs.
|
|
11
|
+
Skip if the user already has detailed acceptance criteria written down.
|
|
12
|
+
Hands off to /sp-plan when discovery is complete — or, for a brand-new project
|
|
13
|
+
with no codebase yet, also decides app-type + stack and hands off to /sp-scaffold first.
|
|
14
|
+
allowed-tools: Read, Glob, Grep, Bash, AskUserQuestion, WebSearch, mcp__graphatlas__*
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Feature discovery as Client Technical Lead. The client says "I want feature X". Your job is to ask until you understand enough to hand off to spec — nothing missing, nothing extra, nothing misunderstood.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Operating principles
|
|
22
|
+
|
|
23
|
+
**Ask at most 2 questions per AskUserQuestion call. Wait for the answer before continuing.**
|
|
24
|
+
Each follow-up must depend on the previous answer — if two questions are truly independent, batch them in one call.
|
|
25
|
+
|
|
26
|
+
**Paraphrase before moving on.**
|
|
27
|
+
After any long or vague answer: "So what I understand is [X]. Is that right?" Fix misunderstandings immediately.
|
|
28
|
+
|
|
29
|
+
**Use concrete examples, not abstract questions.**
|
|
30
|
+
"If user A is on screen B and clicks C, what do they see?" works better than "describe the expected behavior".
|
|
31
|
+
|
|
32
|
+
**Flag contradictions and risks immediately.**
|
|
33
|
+
Don't wait until the end. Contradiction: "Earlier you said X, now you're saying Y — which is correct?" Risk: "⚠ This feature has a concurrency issue / requires a large migration / depends on an external service that hasn't been verified" — flag it in the current phase, not Phase 7.
|
|
34
|
+
|
|
35
|
+
**Record the reason behind every decision.**
|
|
36
|
+
Not just "client chose A". Write "client chose A because B — if B changes, reconsider C."
|
|
37
|
+
|
|
38
|
+
**Split features when you discover them, not at the end.**
|
|
39
|
+
If during discovery you realize this is 2-3 independent features → pause and propose splitting immediately.
|
|
40
|
+
|
|
41
|
+
**Good-enough mindset.** The goal is clear enough to write a spec, not perfect. If you've asked 10-15 questions and still aren't done → create a draft summary with what you have, mark the gaps as Open questions, iterate later. Don't hold the client indefinitely.
|
|
42
|
+
|
|
43
|
+
**Early stop — know when you have enough.** Stop asking when all 3 conditions are met:
|
|
44
|
+
1. You can write the happy path without guessing
|
|
45
|
+
2. Permissions and UI expectations are clear
|
|
46
|
+
3. No remaining ambiguity that blocks implementation (who approves? where is data stored? what is the trigger?)
|
|
47
|
+
|
|
48
|
+
Non-critical edge cases don't need to be resolved now — log them as Open questions and confirm later.
|
|
49
|
+
|
|
50
|
+
**Time budget priority.** If the session is short (client has 10-15 minutes), prioritize: scope + happy path (Phase 1-2) → permissions + UI expectation (Phase 2.5-3) → business rules (Phase 4). Edge cases (Phase 5) and scenario confirmation (Phase 6) can be done async — log as Open questions.
|
|
51
|
+
|
|
52
|
+
**Done when:** The Done checklist at the end of this document is fully checked — no unchecked items.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## AskUserQuestion format
|
|
57
|
+
|
|
58
|
+
All questions to the user go through the AskUserQuestion tool — never ask inline in text.
|
|
59
|
+
|
|
60
|
+
**Rules:**
|
|
61
|
+
- `options` is **required** — every question must have 2–4 options. There is no open-ended format.
|
|
62
|
+
- Each option requires both `label` and `description`.
|
|
63
|
+
- `header` is a chip label — **HARD LIMIT: ≤ 12 characters**. Count before submitting. "Remove/Strip" = 13 ❌. "Strip" = 5 ✓. "Rule type" = 9 ✓.
|
|
64
|
+
- Do NOT add an "Other" option — it is added automatically by the UI.
|
|
65
|
+
- For open-ended questions (free-form expected), use the most likely answers as options. The user can type freely via the automatic "Other" option.
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"questions": [{
|
|
70
|
+
"question": "<context> — <question>?",
|
|
71
|
+
"header": "<≤12 chars>", // COUNT THE CHARACTERS BEFORE USING
|
|
72
|
+
"multiSelect": false,
|
|
73
|
+
"options": [
|
|
74
|
+
{"label": "A) [option]", "description": "[1-line implication]"},
|
|
75
|
+
{"label": "B) [option]", "description": "[1-line implication]"},
|
|
76
|
+
{"label": "C) [option]", "description": "[1-line implication]"}
|
|
77
|
+
]
|
|
78
|
+
}]
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Batch at most 2 questions in one call, only when they are truly independent (the answer to one does not affect the other).
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## WebSearch trigger rules
|
|
87
|
+
|
|
88
|
+
Search when the model's knowledge is not reliable enough for the decision at hand:
|
|
89
|
+
|
|
90
|
+
1. **Client references an external service/product/API** ("integrate with Stripe", "like Notion") → search actual capabilities, limitations, pricing, and API availability before going deeper.
|
|
91
|
+
2. **Client describes a pattern you're not confident about** → search `{pattern} best practice {current year}`.
|
|
92
|
+
3. **Client mentions a specific library/SDK** → search current status, maintenance, and compatibility with the tech stack in CLAUDE.md.
|
|
93
|
+
4. **Sensitive/stealth context** → ask the user before searching. Use generic terms, not the actual product name.
|
|
94
|
+
|
|
95
|
+
*Note: {current year} = current year from system clock (`date +%Y`), never hard-coded. Ensures search results stay relevant when the skill runs next year.*
|
|
96
|
+
|
|
97
|
+
**Do NOT search for:** internal business logic, code already in the repo, core language knowledge, anything already verified by codebase scan.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Phase 0a — Graphatlas probe (run once, silently)
|
|
102
|
+
|
|
103
|
+
Before any discovery step, probe whether graphatlas (GA) is connected:
|
|
104
|
+
|
|
105
|
+
1. Call `mcp__graphatlas__ga_architecture` with `max_modules: 1`.
|
|
106
|
+
2. Interpret:
|
|
107
|
+
- Returns `modules` → **GA available.** Use `ga_*` for every code-discovery step. Grep is fallback only.
|
|
108
|
+
- Error `STALE_INDEX` → call `mcp__graphatlas__ga_reindex` (mode `"full"`), retry once, then treat as available.
|
|
109
|
+
- Tool not found / connection error / any other failure → **GA unavailable.** Skip every `ga_*` recommendation below and use grep/glob directly. Do not re-probe per step.
|
|
110
|
+
3. Record the outcome internally and carry it through the rest of the run.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Phase 0 — Codebase scan (before asking the user anything)
|
|
115
|
+
|
|
116
|
+
Run silently. The client does not need to know about this step.
|
|
117
|
+
|
|
118
|
+
| # | Action | Purpose |
|
|
119
|
+
|---|--------|---------|
|
|
120
|
+
| S1 | Read `CLAUDE.md` | Project context, conventions, tech stack |
|
|
121
|
+
| S2 | List `docs/specs/` and `docs/explore/` | Does a spec or explore doc already exist? Any related spec? If an explore doc already exists for this feature → ask: "An explore doc already exists for this feature. Start fresh or update it?" Wait for answer before continuing. |
|
|
122
|
+
| S3 | **If GA available (per Phase 0a):** start with `ga_architecture` to map modules, then `ga_symbols` for each `$ARGUMENTS` keyword to resolve definitions, then `ga_file_summary` on the matched files to scope the surface. **If GA unavailable or returns empty for free-text:** grep the keywords directly. | Existing related code — how much already exists? Indexed symbol table + module map are more reliable than textual grep. |
|
|
123
|
+
| S4 | List related screens/routes — if GA available, use `ga_symbols` on the route/handler name then `ga_callers` to find where they are mounted; otherwise grep | Understand the system surface area |
|
|
124
|
+
|
|
125
|
+
**Fallback — if scan yields nothing useful** (no CLAUDE.md, messy codebase, graphatlas + grep both empty): skip scan results, ask the user directly at the start of Phase 1:
|
|
126
|
+
> "Does this feature have any existing code, or is it completely new? If it exists, where is it in the system?"
|
|
127
|
+
|
|
128
|
+
Internal classification (if scan succeeds):
|
|
129
|
+
|
|
130
|
+
- **Virgin territory:** no existing code — ask from scratch
|
|
131
|
+
- **Partial exist (< 50%):** some code exists — ask "extend or change current behavior?"
|
|
132
|
+
- **Mostly exist (≥ 50%):** nearly complete — ask "what specifically needs to change?"
|
|
133
|
+
- **Spec exists, not yet implemented:** read the spec — ask "is this spec still accurate, or has it changed?"
|
|
134
|
+
- **Already implemented:** ask "what's broken, or what behavior needs to change?"
|
|
135
|
+
|
|
136
|
+
→ This classification shapes the opening question in Phase 1.
|
|
137
|
+
|
|
138
|
+
**Project-level greenfield check (run with S1)** — distinct from "virgin territory" above (which is no code for THIS feature). If the repo has NO runnable project at all — no `package.json` / `pyproject.toml` / `Cargo.toml` / `go.mod` / equivalent, no real `src/`, and CLAUDE.md has no stack filled in — there is no codebase to build on. Set **GREENFIELD PROJECT = true**: discovery must ALSO decide app-type + stack (Phase 2.6) and emit a **Bootstrap Brief** (Phase 7) so `/sp-scaffold` can stand up a runnable skeleton BEFORE `/sp-plan`. Pipeline becomes **sp-explore → /sp-scaffold → /sp-plan → /sp-build**. (Existing codebase → leave the flag false; the brief and Phase 2.6 are skipped.)
|
|
139
|
+
|
|
140
|
+
Also note the **project domain** from CLAUDE.md (payment, booking, content, healthcare, logistics...) → used for domain-specific edge cases in Phase 4.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Phase 0.5 — Sibling Discovery Pass (candidate only)
|
|
145
|
+
|
|
146
|
+
Run this after Phase 0 when the feature changes an existing operation, fixes a bug, or touches state/viewer/surface behavior. Purpose: find sibling entry-points that perform the same domain operation but may not be named in the ticket.
|
|
147
|
+
|
|
148
|
+
This pass produces candidates, not requirements. A candidate may become a confirmed surface only after the user/spec/code evidence supports it. Do not auto-promote noisy matches into acceptance scenarios.
|
|
149
|
+
|
|
150
|
+
**Inputs:** raw symptom text, feature nouns, touched component/module, existing code hits from Phase 0, matching project-local `docs/invariants/INV-*.md` entries, and any shared anchors/constants already found.
|
|
151
|
+
|
|
152
|
+
**Deterministic recipe:**
|
|
153
|
+
|
|
154
|
+
1. **Seed nouns and verbs:** extract 3-8 terms such as domain object (`appointment`, `invite`, `matchup`), operation (`create`, `reschedule`, `cancel`, `send`), and surface nouns (`outreach`, `modal`, `guide`, `calendar`, `queue`).
|
|
155
|
+
2. **Shared-anchor callers:** if a helper/constant/schema appears central, use `ga_callers` when GA is available; otherwise grep the anchor. Examples: `_stamp_*`, `*_status`, `send_*invite*`, `log_*outcome*`, `create_*`.
|
|
156
|
+
3. **Fuzzy sibling names:** search for parallel naming patterns: `create_from_*`, `*_from_<source>`, `send_*invite*`, `*_outcome*`, `reschedule*`, `book_next*`, `cancel*`, `delete*`, and domain-specific verbs from Phase 0.
|
|
157
|
+
4. **Git change-coupling:** inspect recent co-change around seed files with `git log --name-only -- <seed-file>` and look for files/functions repeatedly changed with the seed. This is recall-oriented evidence, not proof.
|
|
158
|
+
5. **GA blast radius if available:** use `ga_impact` for touched symbols/files to find connected blast radius, but do not treat importers-only output as complete sibling discovery. Siblings may be co-changed or share anchors without importing each other.
|
|
159
|
+
|
|
160
|
+
Record every plausible sibling in a table:
|
|
161
|
+
|
|
162
|
+
| Candidate | Operation | Evidence | Confidence | Obligation |
|
|
163
|
+
|---|---|---|---|---|
|
|
164
|
+
| `<surface/path/symbol>` | same create/update/delete/send/read op? | `ga_callers` / grep / co-change / invariant / user text | high / medium / low | cover / GAP / ignore(reason) |
|
|
165
|
+
|
|
166
|
+
Rules:
|
|
167
|
+
|
|
168
|
+
- `high`: direct shared anchor, explicit invariant sibling, or same operation named in user/spec text.
|
|
169
|
+
- `medium`: strong fuzzy naming or repeated co-change with the seed.
|
|
170
|
+
- `low`: weak name similarity only.
|
|
171
|
+
- `cover`: candidate is confirmed in current scope and must feed `/sp-plan` surfaces.
|
|
172
|
+
- `GAP`: candidate seems material but expected behavior/scope is unknown.
|
|
173
|
+
- `ignore(reason)`: candidate is false positive or intentionally out of scope.
|
|
174
|
+
|
|
175
|
+
Exit condition: every high/medium candidate has `cover`, `GAP`, or `ignore(reason)`. Low-confidence candidates can be listed as notes and do not block handoff.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Phase 1 — Why, not what
|
|
180
|
+
|
|
181
|
+
**If Phase 0 found existing code > 30%:**
|
|
182
|
+
Use AskUserQuestion:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"questions": [{
|
|
187
|
+
"question": "This feature already has [brief description of what exists]. What do you want to do with it?",
|
|
188
|
+
"header": "Existing",
|
|
189
|
+
"multiSelect": false,
|
|
190
|
+
"options": [
|
|
191
|
+
{"label": "A) Change behavior", "description": "Something isn't working right"},
|
|
192
|
+
{"label": "B) Extend it", "description": "Add new functionality to what's already there"},
|
|
193
|
+
{"label": "C) Rebuild from scratch", "description": "Start fresh with a different approach"}
|
|
194
|
+
]
|
|
195
|
+
}]
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Wait for the answer. It changes the entire direction of the conversation.
|
|
200
|
+
|
|
201
|
+
**If virgin territory or spec not yet implemented:**
|
|
202
|
+
Use AskUserQuestion:
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"questions": [{
|
|
207
|
+
"question": "What specific problem is happening that requires this feature? Who is experiencing it, in which flow, at which step?",
|
|
208
|
+
"header": "Problem",
|
|
209
|
+
"multiSelect": false,
|
|
210
|
+
"options": [
|
|
211
|
+
{"label": "Users are blocked", "description": "A specific role hits a blocker in an existing flow"},
|
|
212
|
+
{"label": "Manual workaround", "description": "Users do something manually that should be automated"},
|
|
213
|
+
{"label": "Missing capability", "description": "Something can't be done at all today"}
|
|
214
|
+
]
|
|
215
|
+
}]
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Wait for the answer. Then depending on context:
|
|
220
|
+
|
|
221
|
+
**If the answer is vague ("users need to export PDF")** → push for specificity with AskUserQuestion:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"questions": [{
|
|
226
|
+
"question": "More specifically: what is the user trying to do and where are they stuck? How are they handling it today — workaround, manually, asking an admin, or they simply can't do it?",
|
|
227
|
+
"header": "Specifics",
|
|
228
|
+
"multiSelect": false,
|
|
229
|
+
"options": [
|
|
230
|
+
{"label": "Manual workaround", "description": "User does it by hand each time"},
|
|
231
|
+
{"label": "Asks an admin", "description": "User has to escalate or request help"},
|
|
232
|
+
{"label": "Can't do it at all", "description": "No workaround exists — user is fully blocked"}
|
|
233
|
+
]
|
|
234
|
+
}]
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**If the answer is specific enough** → paraphrase and confirm with AskUserQuestion:
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"questions": [{
|
|
243
|
+
"question": "So [user role X] is [stuck at Y] and currently handles it by [Z]. Is that right?",
|
|
244
|
+
"header": "Paraphrase",
|
|
245
|
+
"multiSelect": false,
|
|
246
|
+
"options": [
|
|
247
|
+
{"label": "Yes, correct", "description": "Understanding is accurate — proceed"},
|
|
248
|
+
{"label": "Partially right", "description": "Some details need correction"},
|
|
249
|
+
{"label": "Not quite", "description": "Significant misunderstanding — clarify"}
|
|
250
|
+
]
|
|
251
|
+
}]
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Purpose:** Avoid building the wrong thing. "Export PDF" vs "share a report with someone who has no account" leads to completely different solutions.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Phase 2 — Desired behavior
|
|
260
|
+
|
|
261
|
+
Ask:
|
|
262
|
+
> "Walk me through it step by step: the user opens the app, what do they want to do, where do they click, what do they see, and what is the final result?"
|
|
263
|
+
|
|
264
|
+
After the user explains:
|
|
265
|
+
|
|
266
|
+
1. **Paraphrase the full flow:**
|
|
267
|
+
> "So: the user is on [screen A] → clicks [button B] → the system [does C] → the user sees [result D]. Is that right?"
|
|
268
|
+
|
|
269
|
+
2. **Identify the trigger:**
|
|
270
|
+
> "Is this triggered by the user clicking something, by the system automatically (cron, webhook, event from another service), or by someone else triggering it for them?"
|
|
271
|
+
|
|
272
|
+
3. **Identify the final result:**
|
|
273
|
+
> "What exactly does the user expect as the final outcome? New data appearing? A file created? A notification sent? A status change?"
|
|
274
|
+
|
|
275
|
+
Iterate the paraphrase until the user confirms it's accurate.
|
|
276
|
+
|
|
277
|
+
**Multi-role check — run immediately after getting the flow:**
|
|
278
|
+
> "Does this flow involve only one role, or do multiple people participate in sequence?"
|
|
279
|
+
|
|
280
|
+
If multi-role → follow up for each role:
|
|
281
|
+
> "After [role A] submits, who handles it next? Does [role B] approve? Does a manager review? Or is it automatic? If there's an approval chain — how many steps, who at each step, and what's the timeout if no one acts?"
|
|
282
|
+
|
|
283
|
+
Draw the cross-role flow if needed:
|
|
284
|
+
```
|
|
285
|
+
[Staff] Submit → [Manager] Approve/Reject → [System] Notify Staff → [Admin] Final review (if amount > X)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Scope check — run after the full flow is clear:**
|
|
289
|
+
If the flow actually describes 2-3 independent features → **pause immediately:**
|
|
290
|
+
> "What you described is actually 3 separate things: [A], [B], [C]. A doesn't depend on B, B doesn't depend on C. These should be 3 separate specs so they can be implemented independently. Which one do you want to explore first?"
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Phase 2.5 — UI/UX expectation
|
|
295
|
+
|
|
296
|
+
Ask after understanding the flow, before getting into technical boundaries.
|
|
297
|
+
|
|
298
|
+
> "Do you have a mockup, wireframe, or screenshot of an app as a reference for this feature?"
|
|
299
|
+
|
|
300
|
+
**If yes:** "Send it over. I'll use it as a reference when writing the spec."
|
|
301
|
+
|
|
302
|
+
**If no:** Ask follow-up:
|
|
303
|
+
> "What kind of UI do you have in mind? For example: a simple data table, an input form, a multi-step wizard, drag-and-drop, a dashboard with charts, or as simple as possible?"
|
|
304
|
+
|
|
305
|
+
**If the client is unsure or says "up to you"** → offer a sensible default instead of asking more:
|
|
306
|
+
> "My default suggestion: a table with search + pagination, editing via modal, no animations. Simple, easy to build, scales well. Is that OK or do you want something different?"
|
|
307
|
+
|
|
308
|
+
**If the client says "as simple as possible"** → confirm:
|
|
309
|
+
> "Simplest means: 1 data table + 1 form, no animations, no drag-drop. Mobile responsive or desktop-only? I need this clear so the dev team doesn't improvise."
|
|
310
|
+
|
|
311
|
+
**If the client chooses a table → specific follow-up:**
|
|
312
|
+
> "Does the table need search/filter? Sort by which columns? Inline edit or click a row to open a form? Pagination or infinite scroll?"
|
|
313
|
+
|
|
314
|
+
**If the client chooses a form → specific follow-up:**
|
|
315
|
+
> "Single-step or multi-step wizard? Any conditional fields (show/hide depending on another field's value)? Save as draft or submit once only?"
|
|
316
|
+
|
|
317
|
+
**If the client references another app** ("like Notion's feature X"):
|
|
318
|
+
→ Trigger WebSearch: look up the actual behavior of that feature. Then paraphrase:
|
|
319
|
+
> "Feature X in [App] works like this: [description]. Do you want it 100% the same, or are there differences?"
|
|
320
|
+
|
|
321
|
+
**Implementation-aware suggestions.** When the client describes complex UI, proactively suggest a simpler approach if it achieves the same goal:
|
|
322
|
+
- Complex animations → "Would plain CSS animation or canvas be enough? If you don't need 3D or complex timelines, it's much simpler to build and maintain."
|
|
323
|
+
- Real-time collaboration → "Would WebSocket be necessary, or would polling every 5 seconds be enough? Polling is far simpler if data doesn't need to update instantly."
|
|
324
|
+
- Complex drag-and-drop → "Sortable list (reorder items) or kanban board (drag between columns)? A sortable list is 5x simpler than kanban."
|
|
325
|
+
|
|
326
|
+
**Purpose:** "Simple table" vs "interactive dashboard" is a 5x effort difference. This must be clear before writing the spec.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Phase 2.6 — Greenfield: app-type & stack _(only if GREENFIELD PROJECT, per Phase 0)_
|
|
331
|
+
|
|
332
|
+
There is no codebase yet, so before boundaries/data, decide WHAT KIND of app this is and WHICH stack — this pre-fills the **Bootstrap Brief** that `/sp-scaffold` consumes to stand up a runnable skeleton. By Phase 1–2 you know the problem and the flow; that's enough to pick a stack. Keep it light — propose sensible defaults and let the client confirm, same posture as Phase 2.5. The canonical stack-decision matrix lives in `/sp-scaffold`; here you only pin the answers.
|
|
333
|
+
|
|
334
|
+
**Research current stack first (WebSearch) — do NOT propose from training memory.** Model knowledge of versions and "current best practice" goes stale fast. Before proposing any default, search the *current* stable/LTS releases and current best practice for the candidate area — using the current year from the system clock (`date +%Y`), never a hardcoded year (so this stays correct when the skill runs next year). The proposed stack + its rationale must reflect what you find, not cutoff memory. (This is exactly the WebSearch trigger "pattern you're not confident about / specific library status" applied to the whole stack choice.)
|
|
335
|
+
|
|
336
|
+
1. **App-type** — if not already obvious from the flow, ask (one question):
|
|
337
|
+
|
|
338
|
+
```json
|
|
339
|
+
{"questions":[{"question":"What kind of application is this? (decides how it's scaffolded and run)","header":"App type","multiSelect":false,"options":[
|
|
340
|
+
{"label":"Full-stack web","description":"Frontend + backend + DB"},
|
|
341
|
+
{"label":"Backend API only","description":"Service/API, no UI in this repo"},
|
|
342
|
+
{"label":"Web frontend only","description":"UI talking to an existing/external API"},
|
|
343
|
+
{"label":"Other","description":"Mobile / desktop / CLI / library — specify"}]}]}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
2. **Stack** — propose a full default stack WITH a one-line rationale per major choice, then confirm. Decide each axis that applies: language/runtime · framework · datastore (if any) · repo shape (single vs monorepo) · test runner · **architecture conventions** (state mgmt · validation · data layer · forms · UI kit · API/response shape — the patterns every feature will follow). Default heuristics: the app-type's mainstream language; a framework that has an official scaffolder; Postgres for relational; single package unless ≥2 deployable units. **Conventions:** if the project / CLAUDE.md already states house conventions, adopt them; otherwise the research step above proposes current best-practice for the stack. If the client says "up to you" → pick the defaults and state them; don't stall.
|
|
347
|
+
|
|
348
|
+
```json
|
|
349
|
+
{"questions":[{"question":"Proposed stack: <one-line summary>. RECOMMENDATION: <X> because <reason>. Confirm or adjust?","header":"Stack","multiSelect":false,"options":[
|
|
350
|
+
{"label":"Confirm","description":"<stack> — proceed"},
|
|
351
|
+
{"label":"Adjust","description":"I'll change a piece"}]}]}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Record every choice + its reason — this becomes the Bootstrap Brief (Phase 7). A choice without a reason is a future regret (Decision-rationale principle).
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Phase 3 — Boundaries
|
|
359
|
+
|
|
360
|
+
Ask in pairs — never dump everything at once:
|
|
361
|
+
|
|
362
|
+
**Pair 1 — Impact:**
|
|
363
|
+
> "Which existing screens or flows does this feature affect? Or is it an entirely new screen?"
|
|
364
|
+
|
|
365
|
+
**Pair 2 — Data:**
|
|
366
|
+
> "Will this change any existing data? Adding fields, adding tables, or changing the meaning of existing fields?"
|
|
367
|
+
|
|
368
|
+
**If there are data changes → ask about migration:**
|
|
369
|
+
> "Does existing data need to be migrated? For example: old records need to be backfilled with new values, old fields need format conversion, or old data needs to be cleaned up before the feature works?"
|
|
370
|
+
|
|
371
|
+
**Pair 3 — Out of scope (important):**
|
|
372
|
+
> "What is explicitly NOT part of this feature? Clients often say 'while we're at it, let's also do...'. I need you to confirm what's out so we can split it out."
|
|
373
|
+
|
|
374
|
+
**Pair 4 — Permissions:**
|
|
375
|
+
> "Who can use this feature? Who cannot — which roles are completely blocked?"
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## Phase 3.5 — Scope optimization
|
|
380
|
+
|
|
381
|
+
Ask after scope is clear, before diving into edge case details:
|
|
382
|
+
|
|
383
|
+
> "If you needed to release quickly, what's the simplest version that still delivers value? What could be deferred to phase 2?"
|
|
384
|
+
|
|
385
|
+
**If the client wants to phase the work** → document clearly:
|
|
386
|
+
- Phase 1 (ship first): [items]
|
|
387
|
+
- Phase 2 (defer): [items]
|
|
388
|
+
- Dependencies between phases: [if any]
|
|
389
|
+
|
|
390
|
+
**If the client says "do it all at once"** → confirm and move on. Don't push further.
|
|
391
|
+
|
|
392
|
+
**Purpose:** A Tech Lead doesn't just understand correctly — they build the right thing at the right time. This question helps the client prioritize and avoids the situation where a large scope meets a short timeline and has to be cut mid-build.
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Phase 4 — Business rules & validation
|
|
397
|
+
|
|
398
|
+
**Conditions:**
|
|
399
|
+
> "Are there any conditions that gate this feature? For example: only allowed when status = X?"
|
|
400
|
+
|
|
401
|
+
**Formulas/calculations:**
|
|
402
|
+
> "Is there any calculation involved? If so, give me a concrete example with real numbers."
|
|
403
|
+
|
|
404
|
+
**Input validation:**
|
|
405
|
+
> "What validation rules apply to the fields the user fills in? Format (email, phone, date)? Min/max length? Allowed or forbidden special characters? Any field that must be unique?"
|
|
406
|
+
|
|
407
|
+
If the client isn't sure → offer sensible defaults:
|
|
408
|
+
> "If you're not sure, I'll write: email must be valid format, text max 255 chars, number must be > 0. You can confirm or adjust when reviewing the spec."
|
|
409
|
+
|
|
410
|
+
**Notifications:**
|
|
411
|
+
> "When a status changes, does anyone need to be notified — email, push, in-app? What's the content?"
|
|
412
|
+
|
|
413
|
+
If notifications exist → clarify template:
|
|
414
|
+
> "Does this notification use an existing template in the system, or does it need a new one? If new, I'll note it as a separate task or log it in Out of scope."
|
|
415
|
+
|
|
416
|
+
**Time constraints:**
|
|
417
|
+
> "Are there any time limits? For example: only allowed within the first 24 hours?"
|
|
418
|
+
|
|
419
|
+
**Concurrency:**
|
|
420
|
+
> "If two people act on the same record at the same time, how should the system handle it?"
|
|
421
|
+
|
|
422
|
+
**Non-functional requirements:**
|
|
423
|
+
> "A few technical questions that shape the implementation:
|
|
424
|
+
> 1. Scale: how many users/records does this touch at peak? (tens? thousands? millions?)
|
|
425
|
+
> 2. Performance SLA: any response time or processing time requirement?
|
|
426
|
+
> 3. Security/compliance: does this touch PII, payment data, or need an audit trail?
|
|
427
|
+
> 4. Availability: if this feature is down for 1 hour, what's the business impact?"
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Phase 5 — Edge cases
|
|
432
|
+
|
|
433
|
+
Ask in groups, still in pairs:
|
|
434
|
+
|
|
435
|
+
**Group: empty & error:**
|
|
436
|
+
> "If there's no data, what is displayed? For errors — is there a difference between a server timeout message and a validation error message?"
|
|
437
|
+
|
|
438
|
+
**Group: submit & network:**
|
|
439
|
+
> "What happens if the user clicks twice in quick succession? What happens if the connection drops mid-processing?"
|
|
440
|
+
|
|
441
|
+
**Group: limits:**
|
|
442
|
+
> "Are there any limits? Max items, file size, timeout, number of times an action can be performed?"
|
|
443
|
+
|
|
444
|
+
**Group: sensitivity:**
|
|
445
|
+
> "Does this feature touch any sensitive data — PII, payment, health data?"
|
|
446
|
+
|
|
447
|
+
**Group: external integration** (if the feature calls an external service):
|
|
448
|
+
> "If [service name] is down or slow, what does the user see? Is there automatic retry? Should the request be queued for later processing?"
|
|
449
|
+
|
|
450
|
+
**Group: domain-specific** — based on the project domain noted in Phase 0 (CLAUDE.md):
|
|
451
|
+
|
|
452
|
+
| Domain | Priority edge cases |
|
|
453
|
+
|--------|-------------------|
|
|
454
|
+
| Payment/Fintech | Double-charge, partial refund, currency mismatch, idempotency |
|
|
455
|
+
| Booking/Scheduling | Overbooking, timezone conflicts, cancellation window |
|
|
456
|
+
| Content/Social | Content moderation, spam, unicode/emoji handling, max length |
|
|
457
|
+
| Healthcare | Data retention policy, audit trail, consent withdrawal |
|
|
458
|
+
| E-commerce | Inventory race condition, price change mid-checkout, coupon stacking |
|
|
459
|
+
| Logistics | Address validation, delivery window conflicts, partial fulfillment |
|
|
460
|
+
|
|
461
|
+
If the domain is not in the table → the generic groups above are sufficient.
|
|
462
|
+
|
|
463
|
+
*Note:* This is where a Technical Lead earns their keep — asking what the client hasn't thought of. Many clients will think about these for the first time when you ask.
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## Phase 6 — Confirm with concrete scenarios
|
|
468
|
+
|
|
469
|
+
Stop asking new questions. Write out **the happy path + at least 2 unhappy paths** with fake data, then confirm via AskUserQuestion:
|
|
470
|
+
|
|
471
|
+
**Happy path:**
|
|
472
|
+
> "Example: User Jane Smith, role Staff, opens Order #1234 and clicks 'Request Cancel'. System checks: status = 'Confirmed', placed 2 hours ago (< 24h) → shows a reason form → Jane types 'Ordered by mistake' → submits → order moves to 'Cancel Requested' → admin receives a notification."
|
|
473
|
+
|
|
474
|
+
**Unhappy path 1 — business rule block:**
|
|
475
|
+
> "User Bob opens Order #5678 (status = 'Shipped') and clicks 'Request Cancel'. What does Bob see — is the Cancel button visible, hidden entirely, or visible but disabled?"
|
|
476
|
+
|
|
477
|
+
**Unhappy path 2 — edge case:**
|
|
478
|
+
> "User Carol submits a cancel request but loses connection mid-way. When she reconnects, what state is the order in? Has the cancel been sent or not?"
|
|
479
|
+
|
|
480
|
+
**If multi-role flow — add a cross-role scenario:**
|
|
481
|
+
> "Staff A submits a cancel request. Manager B opens the approve screen, but Admin C has already rejected it. What does Manager B see?"
|
|
482
|
+
|
|
483
|
+
After presenting the scenarios, confirm via AskUserQuestion:
|
|
484
|
+
|
|
485
|
+
```json
|
|
486
|
+
{
|
|
487
|
+
"questions": [{
|
|
488
|
+
"question": "I've just described [N] scenarios for this feature. Is anything wrong or missing?",
|
|
489
|
+
"header": "Scenarios",
|
|
490
|
+
"multiSelect": false,
|
|
491
|
+
"options": [
|
|
492
|
+
{"label": "All correct", "description": "Proceed to handoff summary"},
|
|
493
|
+
{"label": "Needs fixing", "description": "Point out what's wrong"},
|
|
494
|
+
{"label": "Add a scenario", "description": "Describe an additional scenario to cover"}
|
|
495
|
+
]
|
|
496
|
+
}]
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
If B or C → fix and confirm again. Do not proceed to Phase 6.5 until the user selects A.
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## Phase 6.25 — Behavior Matrix discovery axes
|
|
505
|
+
|
|
506
|
+
Run this before the self-audit when the feature touches any state/status/stage, permissions, multiple roles/viewers, repeated read surfaces, cross-module write/read propagation, notification, feed, dashboard, calendar, or external integration.
|
|
507
|
+
|
|
508
|
+
Purpose: capture the three axes that `/sp-plan` needs to build `## Behavior Matrix`. Do not fill matrix cells here. Discovery only identifies axes, source paths, and open questions.
|
|
509
|
+
|
|
510
|
+
### Axis A — States / lifecycle
|
|
511
|
+
|
|
512
|
+
Derive from the user's flow, business rules, existing code, and scenarios:
|
|
513
|
+
|
|
514
|
+
- Explicit statuses/states/stages, including terminal states.
|
|
515
|
+
- Transition triggers: user action, system event, webhook, cron, retry, admin override.
|
|
516
|
+
- Blocked states: states where the action is hidden, disabled, rejected, or should be `N/A`.
|
|
517
|
+
- Timing: immediate, eventually consistent, queued, retryable, or external-service-dependent.
|
|
518
|
+
|
|
519
|
+
If any state is implied but unnamed, ask:
|
|
520
|
+
> "This behavior depends on record state. Which statuses should support it, and which statuses should block it?"
|
|
521
|
+
|
|
522
|
+
### Axis B — Viewers / roles / relationships
|
|
523
|
+
|
|
524
|
+
Derive from permissions, multi-role flow, ownership, assignment, and notification recipients:
|
|
525
|
+
|
|
526
|
+
- Actor roles: who can perform the write action.
|
|
527
|
+
- Viewer roles: who can see the result after the write.
|
|
528
|
+
- Relationship variants: owner vs assignee vs manager vs admin vs unrelated user vs invited participant.
|
|
529
|
+
- Recipient identity rules: which email/account/contact identity is authoritative when notifications/calendar/events are sent.
|
|
530
|
+
|
|
531
|
+
If the same role can be in different relationships to the record, treat those as separate viewers. Example: `trainer assigned` and `trainer unassigned` are different viewers even if both have role `trainer`.
|
|
532
|
+
|
|
533
|
+
If any viewer is implied but unnamed, ask:
|
|
534
|
+
> "After this change, who needs to see the updated state: actor only, assigned user, manager/admin, external participant, or everyone with list access?"
|
|
535
|
+
|
|
536
|
+
### Axis C — Surfaces / module paths
|
|
537
|
+
|
|
538
|
+
Derive from codebase scan, UI sketches, affected screens, APIs, notifications, and integrations:
|
|
539
|
+
|
|
540
|
+
- Write surfaces: page/action/form/API/webhook/cron/provider callback that can create or change the state.
|
|
541
|
+
- Read surfaces: list row, detail page, dashboard count, worklist/queue, feed/activity log, API list, API single-get, export/report, email, push/in-app notification, calendar/provider event, search/index, audit log.
|
|
542
|
+
- Module Dependency Map: for each write surface, list every read surface/module expected to reflect it.
|
|
543
|
+
- Existing evidence: attach file paths or route names when Phase 0 found them; mark unknown surfaces as `X / needs confirmation`.
|
|
544
|
+
|
|
545
|
+
For every material write/read pair, record:
|
|
546
|
+
|
|
547
|
+
| Write / CREATE surface | Read surface | Direction | Timing tier | Source of truth | Open question |
|
|
548
|
+
|------------------------|--------------|-----------|-------------|-----------------|---------------|
|
|
549
|
+
| `<form/API/event>` | `<list/detail/feed/...>` | write -> read | `sync` / `async` / `external-down` | DB/read model/provider/cache | `none` / question |
|
|
550
|
+
| `<read/API/provider>` | `<write form/action>` | read -> write | `sync` / `async` / `external-down` | DB/read model/provider/cache | `none` / question |
|
|
551
|
+
|
|
552
|
+
Use both directions when the read surface can initiate or constrain the next write. Example: a worklist row is not just read-only if it contains a reschedule/assign/cancel action.
|
|
553
|
+
|
|
554
|
+
Timing tier definitions:
|
|
555
|
+
|
|
556
|
+
- `sync` — user should see the result immediately after the transaction or page refresh.
|
|
557
|
+
- `async` — background worker, projection, queue, webhook, polling, or eventual consistency is expected.
|
|
558
|
+
- `external-down` — behavior changes when a provider/API is unavailable, delayed, or retries.
|
|
559
|
+
|
|
560
|
+
If any surface pair is unknown, ask:
|
|
561
|
+
> "Besides the detail page, where else must this state appear or be actionable: list, dashboard, queue/worklist, feed, API, email, calendar, or reports?"
|
|
562
|
+
|
|
563
|
+
Exit condition: the handoff has non-empty States, Viewers, and Surfaces lists for stateful features, plus at least one write/read pair for every write surface. If a list is genuinely not applicable, record `N/A` with reason.
|
|
564
|
+
|
|
565
|
+
---
|
|
566
|
+
|
|
567
|
+
## Phase 6.5 — Self-audit (blind spot sweep)
|
|
568
|
+
|
|
569
|
+
**Purpose:** Before writing the handoff summary, step back and think like a senior dev who just received this spec. What would they immediately ask? This step catches the 80% of obvious questions that phase-by-phase discovery misses because it was too focused on following the script. The more thorough this step is, the fewer surprises during implementation.
|
|
570
|
+
|
|
571
|
+
**How it works:**
|
|
572
|
+
|
|
573
|
+
1. **Silently generate a list of 5-8 questions** that a senior developer, QA engineer, or domain expert would ask within the first 5 minutes of reading this spec. Think from all 8 angles:
|
|
574
|
+
|
|
575
|
+
| # | Angle | What to ask |
|
|
576
|
+
|---|-------|-------------|
|
|
577
|
+
| 1 | **Algorithm correctness** | What can go wrong with the core approach? False positives? False negatives? Race conditions? Data corruption? Off-by-one? |
|
|
578
|
+
| 2 | **User safety** | What's the worst thing that happens if the feature malfunctions? Data loss? Financial loss? Security breach? Can the user undo? |
|
|
579
|
+
| 3 | **Platform/environment** | What OS, hardware, permission, or dependency constraints could break this? Sandboxing? File system quirks? |
|
|
580
|
+
| 4 | **Scale & performance** | What if there are 10x more items than expected? What if the operation takes 10x longer? What's the expected wait time? |
|
|
581
|
+
| 5 | **Dependencies** | What external services, APIs, system features does this rely on? What if they change or are unavailable? |
|
|
582
|
+
| 6 | **UI interaction conflicts** | Are there conflicting behaviors on the same element? Click, hover, drag on the same area doing 2 different things? Gesture overlap? |
|
|
583
|
+
| 7 | **Lifecycle/trigger** | When does each main operation fire? On appear? On user action? On schedule? On data change? If unclear → ask. |
|
|
584
|
+
| 8 | **Existing pattern fit** | This feature reuses which components/patterns from the codebase? Does each one fit the new data characteristics (range, density, format)? Which existing UI features (search, filter, sort, bulk actions) should be kept, dropped, or adapted? |
|
|
585
|
+
|
|
586
|
+
2. **Filter out** questions already answered in previous phases. Keep only the unanswered ones.
|
|
587
|
+
|
|
588
|
+
3. **If any unanswered questions remain** → ask the user via AskUserQuestion (max 2 per call, as usual). Do NOT skip this — these are the questions that would become bugs or spec rewrites later.
|
|
589
|
+
|
|
590
|
+
4. **If all questions are already answered** → proceed to Phase 7. State: "I did a blind spot check — all critical questions are already covered."
|
|
591
|
+
|
|
592
|
+
**Exit condition:** Every question from the self-audit is either answered by the user or explicitly logged as an Open question. Do not proceed to Phase 7 with unasked questions.
|
|
593
|
+
|
|
594
|
+
**Trap to avoid:** Do not generate vague questions ("have you thought about edge cases?"). Every question must be specific to THIS feature, referencing concrete details from the discovery so far.
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
598
|
+
## Phase 7 — Handoff summary
|
|
599
|
+
|
|
600
|
+
Compile before handing off to sp-plan:
|
|
601
|
+
|
|
602
|
+
```markdown
|
|
603
|
+
## Explore: <Feature Name>
|
|
604
|
+
_<$(date +%Y-%m-%d)>_
|
|
605
|
+
|
|
606
|
+
**Feature:** [1-line description]
|
|
607
|
+
**Trigger:** [user action / system event / external event]
|
|
608
|
+
**UI expectation:** [simple table / form / wizard / dashboard / reference: "like X in App Y"]
|
|
609
|
+
|
|
610
|
+
**Bootstrap Brief:** _(GREENFIELD PROJECT only — consumed by `/sp-scaffold`; omit entirely for a feature on an existing codebase)_
|
|
611
|
+
- **App-type:** [web-frontend | backend-API | full-stack | mobile | desktop | CLI | library] (+ monorepo? yes/no)
|
|
612
|
+
- **Stack:** language/runtime [X — why] · framework [X — why] · datastore [X | none — why] · repo shape [single | monorepo+tool — why] · test runner [X]
|
|
613
|
+
- **Conventions:** state mgmt [X] · validation [X] · data layer [X] · forms [X] · UI kit [X] · API/response shape [X] — the patterns the scaffold's example module demonstrates and every feature follows (from house conventions, else researched best-practice)
|
|
614
|
+
- **Scaffold command:** [official create-* / framework CLI / degit template, or "freeform — no blessed generator"]
|
|
615
|
+
- **Smoke contract:** [what "runs" means for this app-type — see /sp-scaffold Phase 3]
|
|
616
|
+
- **Known constraints:** [deploy target, must-use libs, anything that pins the skeleton]
|
|
617
|
+
|
|
618
|
+
**UI sketches:** _(optional — include for UI-bearing features when human visualization helps)_
|
|
619
|
+
|
|
620
|
+
[Free-form layout sketches (ASCII boxes / bullet outlines / nested lists). Each component, section, button, or surface **MUST carry an E/N/X tag**:
|
|
621
|
+
|
|
622
|
+
- `[E]` existing — already shipped, file path confirmed in codebase
|
|
623
|
+
- `[N]` NEW — must be built this feature
|
|
624
|
+
- `[X]` MISSING / unclear — placeholder, needs clarification
|
|
625
|
+
|
|
626
|
+
**UI codebase scan — required before tagging:**
|
|
627
|
+
|
|
628
|
+
*Read budget = 7. What counts:* `ga_symbols` / `ga_callers` / `ga_callees` = 0 reads. `ga_file_summary` / preview = 0.5 read. Full file read = 1 read. Hard cap 7 total.
|
|
629
|
+
|
|
630
|
+
*3-block flow (Locate → Scan & Match → Verify & Tag):*
|
|
631
|
+
|
|
632
|
+
1. **LOCATE** — anchor host page/route file(s) from the happy path's "user opens X" sentence (1–2 files).
|
|
633
|
+
2. **SCAN & MATCH** — build candidate list:
|
|
634
|
+
- Prototype URL (rendered structure) — use for **naming/shape only**. NEVER counts as evidence for `[E]`.
|
|
635
|
+
- `ga_symbols` on 3–5 keywords from happy-path nouns (GA available)
|
|
636
|
+
- 1 glob `components/**/<domain>*` + 1 grep (GA unavailable). NO recursive grep over whole repo.
|
|
637
|
+
3. **VERIFY & TAG**:
|
|
638
|
+
- `[E]` requires **file path evidence** from Verify step (`file_summary` or read). Path attached as `file:path` next to the tag. No evidence → demote to `[X]`.
|
|
639
|
+
- `[N]` = no match in code AND feature requires it.
|
|
640
|
+
- `[X]` discipline: (a) only after ≥1 scan step — do NOT skip straight to `[X]`; (b) if >30% of components in the sketch end up `[X]`, STOP and ask user for repo path / route name (the scan was too coarse).
|
|
641
|
+
|
|
642
|
+
*Anti-patterns* (token-greedy + accuracy-lowering):
|
|
643
|
+
- Full file read when `file_summary` suffices
|
|
644
|
+
- Exhaustive recursive grep
|
|
645
|
+
- Tagging `[E]` on prototype-only evidence ("the prototype shows it") — that's intended UI, not existing code
|
|
646
|
+
- Skipping scan and dumping unclear surfaces into `[X]`
|
|
647
|
+
|
|
648
|
+
**Example sketch (legend literally embedded):**
|
|
649
|
+
|
|
650
|
+
```
|
|
651
|
+
┌─ Appointments page [E] components/appointments/page.tsx ─────────┐
|
|
652
|
+
│ Header [E] │
|
|
653
|
+
│ ╔ Pending Matchups (3) [N] ════════════════════════════════╗ │
|
|
654
|
+
│ ║ Row: trainee + [Assign] [N] ║ │
|
|
655
|
+
│ ╚════════════════════════════════════════════════════════════╝ │
|
|
656
|
+
│ Tabs [E] Filters [E] │
|
|
657
|
+
│ Appointment cards [E] + MatchupStatusBadge [N] │
|
|
658
|
+
└──────────────────────────────────────────────────────────────────┘
|
|
659
|
+
|
|
660
|
+
Legend: [E] existing · [N] NEW · [X] MISSING / clarify
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
sp-plan reads this sketch and routes by tag:
|
|
664
|
+
- `[N]` → `## UI Notes` Component Tree (build targets)
|
|
665
|
+
- `[E]` → `## What Already Exists § UI Inventory` (reuse refs with evidence path)
|
|
666
|
+
- `[X]` → `## Gaps (status: open)` (unclear surfaces)
|
|
667
|
+
|
|
668
|
+
ASCII stays in explore as provenance. If sketch carries no E/N/X legend, sp-plan treats all components as `[N]` and emits a Clarification flagging the assumption.
|
|
669
|
+
|
|
670
|
+
If neither sketches nor a prototype URL exist for a UI-bearing feature → sp-plan emits `GAP-NNN (status: open)` about UI structure.]
|
|
671
|
+
|
|
672
|
+
**Happy path:**
|
|
673
|
+
1. [Step 1]
|
|
674
|
+
2. [Step 2]
|
|
675
|
+
3. [Final result]
|
|
676
|
+
|
|
677
|
+
**Multi-role flow:** _(if applicable)_
|
|
678
|
+
[Role A] → action → [Role B] → action → [System] → result
|
|
679
|
+
Timeout: [if role B does not act within X hours then...]
|
|
680
|
+
|
|
681
|
+
**Phasing:** _(if client chose to phase the work)_
|
|
682
|
+
- Phase 1 (ship first): [items]
|
|
683
|
+
- Phase 2 (defer): [items]
|
|
684
|
+
- Dependencies: [if any]
|
|
685
|
+
|
|
686
|
+
**Business rules:**
|
|
687
|
+
- [Condition X → behavior Y]
|
|
688
|
+
- [Formula: concrete example with real numbers]
|
|
689
|
+
- [Time constraints if any]
|
|
690
|
+
|
|
691
|
+
**Input validation:**
|
|
692
|
+
- [Field A: format, min/max length, unique?]
|
|
693
|
+
- [Field B: required?, allowed values]
|
|
694
|
+
|
|
695
|
+
**Edge cases:**
|
|
696
|
+
- Empty state: [what is displayed]
|
|
697
|
+
- Error: [server timeout → message A / validation error → message B]
|
|
698
|
+
- Double submit: [prevent / idempotent / show warning]
|
|
699
|
+
- Network loss: [retry / rollback / show state]
|
|
700
|
+
- Concurrent edit: [last-write-wins / lock / merge / show conflict]
|
|
701
|
+
- Domain-specific: [e.g. double-charge prevention, overbooking check]
|
|
702
|
+
|
|
703
|
+
**External integration:** _(if applicable)_
|
|
704
|
+
- Service: [name]
|
|
705
|
+
- Service down: [what user sees, retry?, queue?]
|
|
706
|
+
- Rate limit: [exists or not, how handled]
|
|
707
|
+
|
|
708
|
+
**Permissions:**
|
|
709
|
+
- Allowed: [role list]
|
|
710
|
+
- Blocked: [role list + reason]
|
|
711
|
+
|
|
712
|
+
**Notifications:** _(if applicable)_
|
|
713
|
+
- [Event X → notify role Y via email/push/in-app]
|
|
714
|
+
- Template: [use existing template "{name}" / needs new template → separate task]
|
|
715
|
+
|
|
716
|
+
**Data impact:**
|
|
717
|
+
- [New or changed fields/tables]
|
|
718
|
+
- Migration: [backfill needed / format conversion / data cleanup]
|
|
719
|
+
|
|
720
|
+
**Behavior Matrix discovery axes:** _(required for stateful / role-sensitive / multi-surface features; consumed by `/sp-plan`)_
|
|
721
|
+
|
|
722
|
+
Sibling Candidate Table: _(required when Phase 0.5 ran; consumed by `/sp-plan`)_
|
|
723
|
+
| Candidate | Operation | Evidence | Confidence | Obligation |
|
|
724
|
+
|---|---|---|---|---|
|
|
725
|
+
| [surface/path/symbol] | [same create/update/delete/send/read op?] | [ga_callers / grep / co-change / invariant / user text] | high / medium / low | cover / GAP / ignore(reason) |
|
|
726
|
+
|
|
727
|
+
Confirmed sibling surfaces for planning:
|
|
728
|
+
- [surface/path/symbol confirmed from candidate table, or N/A with reason]
|
|
729
|
+
|
|
730
|
+
States / lifecycle:
|
|
731
|
+
- [State/status/stage 1 — transition trigger, terminal? yes/no, blocked? yes/no]
|
|
732
|
+
- [State/status/stage 2 — transition trigger, terminal? yes/no, blocked? yes/no]
|
|
733
|
+
|
|
734
|
+
Viewers / roles / relationships:
|
|
735
|
+
- [Actor/viewer 1 — role + relationship to record + allowed actions]
|
|
736
|
+
- [Actor/viewer 2 — role + relationship to record + allowed actions]
|
|
737
|
+
- [Recipient identity rule if notifications/calendar exist]
|
|
738
|
+
|
|
739
|
+
Surfaces / module paths:
|
|
740
|
+
- Write surfaces: [form/action/API/webhook/cron/provider callback + file/route evidence if known]
|
|
741
|
+
- Read surfaces: [list/detail/dashboard/worklist/feed/API/email/calendar/search/audit/export + file/route evidence if known]
|
|
742
|
+
- Unknown surfaces: [X / needs confirmation, or N/A with reason]
|
|
743
|
+
|
|
744
|
+
CREATE/READ pair map:
|
|
745
|
+
| Write / CREATE surface | Read surface | Direction | Timing tier | Source of truth | Open question |
|
|
746
|
+
|------------------------|--------------|-----------|-------------|-----------------|---------------|
|
|
747
|
+
| [write surface] | [read surface] | write -> read | sync / async / external-down | DB/read model/provider/cache | none / question |
|
|
748
|
+
| [read/action surface] | [write surface] | read -> write | sync / async / external-down | DB/read model/provider/cache | none / question |
|
|
749
|
+
|
|
750
|
+
**Impact on existing system:**
|
|
751
|
+
- [Affected screens/flows + description of impact]
|
|
752
|
+
|
|
753
|
+
**Out of scope:**
|
|
754
|
+
- [Item 1 — reason for exclusion]
|
|
755
|
+
- [Item 2 — reason for exclusion]
|
|
756
|
+
|
|
757
|
+
**Decision rationale:**
|
|
758
|
+
- [Client chose A over B because C. If C changes → reconsider B.]
|
|
759
|
+
- [Client chose to hide the button instead of disabling it — didn't want users wondering why they can't click.]
|
|
760
|
+
|
|
761
|
+
**Assumptions:** _(inferred, needs explicit client confirmation)_
|
|
762
|
+
- [e.g. "Timezone is UTC+7 for all time constraints"]
|
|
763
|
+
- [e.g. "Email notification uses existing system template, no new template needed"]
|
|
764
|
+
|
|
765
|
+
**Open questions:** _(unanswered, needs follow-up)_
|
|
766
|
+
- [...]
|
|
767
|
+
|
|
768
|
+
**Success metrics:** _(only if client mentioned a measurable goal in Phase 1)_
|
|
769
|
+
- [e.g. "Reduce cancel processing time from 30 minutes to < 2 minutes"]
|
|
770
|
+
|
|
771
|
+
**Complexity signal:** [low / medium / high]
|
|
772
|
+
Based on: [number of new screens, data model changes, external integrations, edge case density, multi-role]
|
|
773
|
+
|
|
774
|
+
**Non-functional requirements:**
|
|
775
|
+
- Scale: [expected load — records, users, concurrent operations]
|
|
776
|
+
- Performance SLA: [response time, throughput, processing window]
|
|
777
|
+
- Security/compliance: [PII, payment, audit, encryption requirements]
|
|
778
|
+
- Domain risks: [e.g., double-charge (payment), overbooking (scheduling)]
|
|
779
|
+
- Availability impact: [what breaks if this feature is down]
|
|
780
|
+
|
|
781
|
+
**Technical risks:**
|
|
782
|
+
- [e.g. "Never integrated with service X before — needs a spike first"]
|
|
783
|
+
- [e.g. "Concurrent edit requires a locking strategy — no existing pattern in the codebase"]
|
|
784
|
+
- [e.g. "Data migration on a large table — needs time estimate"]
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
After writing the summary, confirm via AskUserQuestion:
|
|
788
|
+
|
|
789
|
+
```json
|
|
790
|
+
{
|
|
791
|
+
"questions": [{
|
|
792
|
+
"question": "Is this summary complete enough to hand off to /sp-plan?",
|
|
793
|
+
"header": "Handoff",
|
|
794
|
+
"multiSelect": false,
|
|
795
|
+
"options": [
|
|
796
|
+
{"label": "Yes, save & hand off", "description": "Write to docs/explore/; greenfield → /sp-scaffold, else → /sp-plan"},
|
|
797
|
+
{"label": "Needs additions", "description": "Point out what's missing before saving"},
|
|
798
|
+
{"label": "Open questions first", "description": "Work through unresolved questions first"}
|
|
799
|
+
]
|
|
800
|
+
}]
|
|
801
|
+
}
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
If A → write to `docs/explore/<feature-slug>.md`. **If GREENFIELD PROJECT:** next step is `/sp-scaffold` (it reads the Bootstrap Brief to stand up the runnable skeleton), THEN `/sp-plan` for the first feature spec. Otherwise hand straight to `/sp-plan` — it auto-detects this file and skips redundant discovery when run on the same feature.
|
|
805
|
+
|
|
806
|
+
If B or C → resolve and confirm again.
|
|
807
|
+
|
|
808
|
+
---
|
|
809
|
+
|
|
810
|
+
## Done checklist
|
|
811
|
+
|
|
812
|
+
Self-check before writing the output file:
|
|
813
|
+
|
|
814
|
+
- [ ] Happy path described step by step — no guessing required
|
|
815
|
+
- [ ] At least 2 unhappy paths confirmed with the user *(can be deferred if time-boxed — log as Open questions)*
|
|
816
|
+
- [ ] Business rules have concrete examples with real numbers
|
|
817
|
+
- [ ] Input validation is clear for every user-facing field
|
|
818
|
+
- [ ] Permissions are clear for every relevant role
|
|
819
|
+
- [ ] If multi-role: cross-role flow confirmed, including timeouts and conflicts
|
|
820
|
+
- [ ] If stateful / role-sensitive / multi-surface: Behavior Matrix discovery axes are filled with States, Viewers, Surfaces, and CREATE/READ pair map
|
|
821
|
+
- [ ] If existing-operation or bug-fix discovery ran: Sibling Candidate Table lists every high/medium candidate with cover / GAP / ignore(reason)
|
|
822
|
+
- [ ] UI expectation confirmed — dev team has no room to improvise
|
|
823
|
+
- [ ] Edge cases covered for critical paths *(can be deferred if time-boxed — log as Open questions)*
|
|
824
|
+
- [ ] Out of scope has at least 1 item listed
|
|
825
|
+
- [ ] No unresolved contradictions
|
|
826
|
+
- [ ] Data migration asked about (if there are data changes)
|
|
827
|
+
- [ ] External integration: failure/retry/queue asked about (if there is an external service)
|
|
828
|
+
- [ ] Assumptions listed separately from Open questions
|
|
829
|
+
- [ ] Decision rationale recorded for every significant choice
|
|
830
|
+
- [ ] Client confirmed the handoff summary
|
|
831
|
+
- [ ] Handoff summary is structured enough for /sp-plan to use directly without re-asking basic discovery questions
|
|
832
|
+
- [ ] If GREENFIELD PROJECT: app-type + stack decided with rationale; Bootstrap Brief filled for /sp-scaffold
|
|
833
|
+
|
|
834
|
+
If any item is unchecked → return to the corresponding phase and ask more — do not write the file.
|
|
835
|
+
|
|
836
|
+
---
|
|
837
|
+
|
|
838
|
+
## Traps — Common mistakes to avoid
|
|
839
|
+
|
|
840
|
+
| # | Trap | Consequence |
|
|
841
|
+
|---|------|-------------|
|
|
842
|
+
| T1 | Dumping many questions at once | Client overwhelmed, skips questions, answers get mixed up |
|
|
843
|
+
| T2 | Not paraphrasing after a long answer | Misunderstanding carries into the spec, caught late |
|
|
844
|
+
| T3 | Not asking "what is NOT in scope" | Client scope creep, spec bloat |
|
|
845
|
+
| T4 | Skipping Phase 0 codebase scan | Asking about a feature that's already 80% implemented |
|
|
846
|
+
| T5 | Not flagging contradictions and risks immediately | Contradiction/risk buried in spec, dev team guesses |
|
|
847
|
+
| T6 | Waiting until Phase 7 to realize it's 3 features | Wrong scope explored for the entire session |
|
|
848
|
+
| T7 | Writing "client chose X" without the reason | Future devs don't know why, make the wrong change during refactor |
|
|
849
|
+
| T8 | Only confirming the happy path | Unhappy paths found during QA, dev has to rework |
|
|
850
|
+
| T9 | Not asking about UI expectation | Dev builds "simple table", client expected "interactive dashboard" |
|
|
851
|
+
| T10 | Not asking about input validation | Dev has to ask again or guess — spec gets patched late |
|
|
852
|
+
| T11 | Not distinguishing assumptions from open questions | Dev treats assumptions as confirmed facts, builds the wrong thing |
|
|
853
|
+
| T12 | Not asking about data migration when there are data changes | Feature deployed, old data incompatible, production bug |
|
|
854
|
+
| T13 | Single-role flow for a multi-role feature | Spec missing approval chain, timeout handling, conflict resolution |
|
|
855
|
+
| T14 | Generic edge cases only, skipping domain-specific ones | Misses double-charge (payment), overbooking (scheduling) |
|
|
856
|
+
| T15 | Over-indexing edge cases in a short session | Runs out of time before scope and happy path are clear |
|
|
857
|
+
| T16 | Feature calls external service but failure handling not asked | Service goes down → blank screen, no retry, no error message |
|
|
858
|
+
| T17 | No phasing discussion | Large scope, short timeline, features cut mid-build with no plan |
|
|
859
|
+
| T18 | Only asking, never suggesting defaults when client is unsure | Client gets stuck, session drags, no decision made |
|
|
860
|
+
| T19 | Not suggesting a simpler approach when client's expectations are high | Spec says Three.js for a simple animation — CSS was enough; WebSocket for 5-minute data updates — polling was enough |
|
|
861
|
+
| T20 | Not extracting state/viewer/surface axes | `/sp-plan` has to reconstruct the matrix from prose and misses lifecycle/parity bugs |
|
|
862
|
+
| T21 | Listing surfaces without CREATE/READ timing | Async projections, external-down behavior, and stale read paths are left to QA to discover after code |
|