@pavp/storywright 1.5.0 → 1.6.0
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/package.json +1 -1
- package/skills/story-from-figma/SKILL.md +170 -51
- package/skills/story-generate/SKILL.md +197 -106
- package/skills/story-split/SKILL.md +240 -115
package/package.json
CHANGED
|
@@ -1,30 +1,75 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: story-from-figma
|
|
3
|
-
description: Generate user stories from a Figma
|
|
3
|
+
description: Generate Cohn+Gherkin user stories from a Figma URL. Maps prototype flows to stories (one per user goal, not per frame). Asks ONLY in terminal.
|
|
4
4
|
trigger: "/story-from-figma | story from figma | generate from figma | analizar figma | https://www.figma.com/"
|
|
5
|
-
intent: Multimodal entrypoint
|
|
6
|
-
version:
|
|
5
|
+
intent: Multimodal entrypoint. Inspects a Figma design, infers flows and screens, and emits one canonical story per logical user goal. Honors v2.2 hard rules (terminal-only Q, no mini-PRD, mechanical deps for split, V audit per child).
|
|
6
|
+
version: 2.2.0
|
|
7
7
|
inputs:
|
|
8
8
|
- figma-link
|
|
9
9
|
outputs:
|
|
10
|
-
- story.
|
|
11
|
-
- story.
|
|
12
|
-
-
|
|
10
|
+
- story-<N>.standard.md
|
|
11
|
+
- story-<N>.jira-wiki.md
|
|
12
|
+
- flow-summary.md
|
|
13
|
+
- .storywright-context.json
|
|
13
14
|
composes:
|
|
14
15
|
- _components/clarification-questions
|
|
15
16
|
- _components/acceptance-criteria
|
|
16
17
|
- _components/invest-checklist
|
|
17
|
-
- _components/definition-of-done
|
|
18
|
-
- _components/business-rules
|
|
19
|
-
- _components/edge-cases
|
|
20
|
-
- _components/analytics-events
|
|
21
|
-
- _components/risks-and-dependencies
|
|
22
18
|
- _components/jira-wiki-formatter
|
|
23
19
|
---
|
|
24
20
|
|
|
25
21
|
## Purpose
|
|
26
22
|
|
|
27
|
-
A Figma file usually represents N screens / N flows. This skill maps that visual structure into stories — one story per logical user goal, not one per frame.
|
|
23
|
+
A Figma file usually represents N screens / N flows. This skill maps that visual structure into Cohn+Gherkin stories — **one story per logical user goal, not one per frame**. Splits aggressively if any flow has multiple outcomes.
|
|
24
|
+
|
|
25
|
+
## Hard rules (v2.2 parity with refine/generate/split)
|
|
26
|
+
|
|
27
|
+
1. **Terminal-only clarifications.** Never write any sidecar question file (no `clarifications.md`). All gap questions through `AskUserQuestion`, batched ≤4. Non-blocking gaps → `⚠️ Assumed` inline.
|
|
28
|
+
|
|
29
|
+
2. **Cohn + Gherkin canonical per story.** Each generated story has ONE Use Case + ONE AC scenario (one Given chain + one `When` + one `Then`). If a flow naturally has >1 `When`/`Then` → STOP and hand off to `[[story-split]]`.
|
|
30
|
+
|
|
31
|
+
3. **No mini-PRDs.** Prohibited in each generated story:
|
|
32
|
+
- NFR blocks — DoD only
|
|
33
|
+
- Edge Cases enumerations as a section — fold into AC failure paths
|
|
34
|
+
- Dependencies as prose — Jira links only
|
|
35
|
+
- Per-claim visual specs — single banner (rule 5)
|
|
36
|
+
- Generation logs >3 lines (>5 if SPLIT recommended)
|
|
37
|
+
|
|
38
|
+
4. **Output language matches the user's chat language**, not the Figma file's. Auto-detect via rule 4a; ask only if signals split. Persist via rule 9.
|
|
39
|
+
|
|
40
|
+
5. **Visual inference confidence — single banner only.** Since the source IS Figma, the banner is always `**Source: Figma → values can be tokenized at implementation.**`. If MCP Figma is unavailable and the user falls back to PNG exports, switch the banner to raster (`pixel-derived, not token-confirmed`).
|
|
41
|
+
|
|
42
|
+
6. **Sibling task IDs.** When the inventory phase produces multiple flows, ticket slugs follow rule F (naming pattern). Do NOT invent slugs without consulting `.storywright-context.json`.
|
|
43
|
+
|
|
44
|
+
7. **Mockup chrome detection — closed list** (nav rail, top bar, footer, toast slot, modal scrim, app tabs). If a frame shows chrome that's NOT explicitly part of a flow, ask via `AskUserQuestion` whether it's a separate story, shared shell, or out-of-scope.
|
|
45
|
+
|
|
46
|
+
8. **Anti-PRD is part of each story's INVEST `Small` criterion** — see `[[invest-checklist]]` Small.
|
|
47
|
+
|
|
48
|
+
9. **Cross-skill context persistence.** Read `<output-folder>/.storywright-context.json` first (exact folder only). Write resolved answers back. Schema same as other v2.2 skills, plus:
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"extra": {
|
|
52
|
+
"figma_url": "<url>",
|
|
53
|
+
"figma_scope": "file | page | frame",
|
|
54
|
+
"mcp_available": true | false
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
10. **Mechanical NxN dep matrix when emitting multiple stories (rule A).** If N>1 flows produce N stories, parse each story's `Given` lines for surface nouns owned by sibling flows. Mark `DEP(Sj → Si)` per match. Render the matrix in `flow-summary.md`. No intuition.
|
|
60
|
+
|
|
61
|
+
11. **Per-story V audit (rule C).** For each candidate story, one-line test: "If only this story ships and no sibling flow exists, does a real user complete a real task?". If no → `WEAK · merge-upstream-candidate`. Recommend merging in `flow-summary.md`.
|
|
62
|
+
|
|
63
|
+
12. **Passive-goal downstream prompt (rule G).** If a story's `I want to` verb is observational AND `so that` lacks downstream action → ask once via `AskUserQuestion`.
|
|
64
|
+
|
|
65
|
+
### 4a. Language auto-detect — expanded signals (E)
|
|
66
|
+
Same weighted table as refine/generate/split (Gherkin keywords, persona phrasing, column names, domain verbs, title). Plus Figma-specific signal: **frame names** and **layer text** in M = medium weight.
|
|
67
|
+
|
|
68
|
+
### Rule F. Naming pattern — ask once, persist
|
|
69
|
+
Same options. Persist in `naming_pattern` inside `.storywright-context.json`. Used for all story slugs in this run.
|
|
70
|
+
|
|
71
|
+
### Rule D. Surface vs styling
|
|
72
|
+
Same deterministic rule. A frame counts as a separate flow ONLY if it has its own user goal (verb where the user *does something*). A purely visual variant (color theme, light/dark) is NOT a new flow.
|
|
28
73
|
|
|
29
74
|
## When to use
|
|
30
75
|
|
|
@@ -40,86 +85,160 @@ A Figma file usually represents N screens / N flows. This skill maps that visual
|
|
|
40
85
|
|
|
41
86
|
## Application (step-by-step)
|
|
42
87
|
|
|
43
|
-
### Phase 0 — MCP availability
|
|
44
|
-
|
|
45
|
-
1. Verify an MCP Figma server is connected to Claude Code. See `mcp-figma-notes.md` in this skill folder for setup options.
|
|
46
|
-
2. If MCP is unavailable:
|
|
47
|
-
- Ask the user to either (a) install an MCP Figma server, (b) export the relevant frames as PNGs and drop them in chat, or (c) paste a textual description of the flows.
|
|
48
|
-
- Continue under the chosen fallback. The rest of the skill works with screenshots via Claude vision.
|
|
88
|
+
### Phase 0 — MCP availability + context load
|
|
49
89
|
|
|
50
|
-
|
|
90
|
+
1. Verify MCP Figma server is connected. See `mcp-figma-notes.md`.
|
|
91
|
+
2. **Read prior context.** If `<output-folder>/.storywright-context.json` exists (exact folder only), load it.
|
|
92
|
+
3. If MCP unavailable:
|
|
93
|
+
- Ask via `AskUserQuestion`: install MCP / export PNGs / paste textual flow descriptions.
|
|
94
|
+
- If user falls back to PNG, set `design_source = raster` in context file and use the raster banner per rule 5.
|
|
51
95
|
|
|
52
|
-
|
|
53
|
-
- **Accompanying text** (goal, story draft, constraints) — treat as canonical for `User Story / Scope / Business Goal`. Figma is canonical for `Components / States / Flows`.
|
|
54
|
-
- **Reference screenshots** — usually redundant when Figma is available; use only if Figma frames are missing states the screenshots show.
|
|
96
|
+
### Phase 0.5 — Companion inputs + language
|
|
55
97
|
|
|
56
|
-
|
|
98
|
+
1. Detect companion text or PNGs.
|
|
99
|
+
2. Run language auto-detect (rule 4a). Adopt silently if signals agree; ask if split.
|
|
100
|
+
3. Persona sharpening: if persona ambiguous, ask via `AskUserQuestion`.
|
|
57
101
|
|
|
58
|
-
### Phase 1 — Inventory
|
|
102
|
+
### Phase 1 — Inventory (MCP)
|
|
59
103
|
|
|
60
104
|
1. List pages in the file (if MCP allows).
|
|
61
105
|
2. For the target page, list frames with:
|
|
62
106
|
- Frame name
|
|
63
107
|
- Frame type (entry, modal, error state, empty state, success state, loading, etc.)
|
|
64
|
-
- Outgoing prototype links
|
|
65
|
-
3. Identify
|
|
108
|
+
- Outgoing prototype links
|
|
109
|
+
3. Identify **flows** by grouping frames connected by prototype links. One flow = one candidate story (or epic if large).
|
|
110
|
+
4. Apply rule D: visual variants of the same flow do NOT count as new flows.
|
|
66
111
|
|
|
67
112
|
### Phase 2 — Per-flow inference
|
|
68
113
|
|
|
69
114
|
For each flow:
|
|
70
115
|
|
|
71
|
-
1. Identify the **goal** (what user outcome
|
|
72
|
-
2. Identify the **entry point
|
|
73
|
-
3. Enumerate **states**: empty
|
|
74
|
-
4. Identify **components**
|
|
75
|
-
5. Score confidence per inference: HIGH
|
|
76
|
-
6.
|
|
116
|
+
1. Identify the **goal** (what user outcome).
|
|
117
|
+
2. Identify the **entry point**.
|
|
118
|
+
3. Enumerate **states**: empty / loading / success / error / edge. Fold into AC failure paths (rule 3); do NOT emit an Edge Cases section.
|
|
119
|
+
4. Identify **components** and their **inputs/outputs**.
|
|
120
|
+
5. Score confidence per inference: HIGH / MEDIUM / LOW. Below HIGH → `⚠️ Assumed` inline.
|
|
121
|
+
6. Run passive-goal check (rule G).
|
|
122
|
+
7. Run pre-split deterministic counter (rule D) on the flow. If count ≥2 → recommend `[[story-split]]` for THAT flow before drafting.
|
|
123
|
+
|
|
124
|
+
### Phase 3 — Draft canonical block per flow
|
|
125
|
+
|
|
126
|
+
```markdown
|
|
127
|
+
### [Flow Title]
|
|
128
|
+
|
|
129
|
+
#### Use Case
|
|
130
|
+
- **As a** [persona]
|
|
131
|
+
- **I want to** [action]
|
|
132
|
+
- **so that** [outcome with downstream action — rule G]
|
|
77
133
|
|
|
78
|
-
|
|
134
|
+
#### Acceptance Criteria
|
|
135
|
+
- **Scenario:** [single-outcome scenario name]
|
|
136
|
+
- **Given:** [context — surface nouns drive flow-summary dep matrix]
|
|
137
|
+
- **When:** [single trigger]
|
|
138
|
+
- **Then:** [single observable outcome]
|
|
79
139
|
|
|
80
|
-
|
|
140
|
+
#### Design Reference
|
|
141
|
+
**Source: Figma → values can be tokenized at implementation.**
|
|
142
|
+
- <frame URL or frame names>
|
|
81
143
|
|
|
82
|
-
|
|
144
|
+
#### INVEST
|
|
145
|
+
- I/N/V/E/S/T — one line each.
|
|
146
|
+
- **Verdict:** READY | SPLIT RECOMMENDED | NEEDS REFINEMENT | NOT A STORY
|
|
147
|
+
|
|
148
|
+
#### Generation log (≤3 lines)
|
|
149
|
+
- Mapped from frames: <FRAME-IDs>; pattern: <if any>.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Phase 4 — Multi-flow analysis (if N>1)
|
|
153
|
+
|
|
154
|
+
1. **Mechanical NxN dep matrix (rule 10).** Parse each story's Given lines for surface nouns owned by sibling flows. Emit in `flow-summary.md`.
|
|
155
|
+
|
|
156
|
+
2. **Per-story V audit (rule 11).** Flag merge-upstream candidates loudly.
|
|
157
|
+
|
|
158
|
+
3. **Coherence check** — verify the union of stories covers the user journey shown in Figma. Flag gaps.
|
|
159
|
+
|
|
160
|
+
### Phase 5 — Output
|
|
83
161
|
|
|
84
162
|
For each story:
|
|
85
|
-
-
|
|
86
|
-
|
|
163
|
+
- `story-<N>.standard.md` + `story-<N>.jira-wiki.md`.
|
|
164
|
+
|
|
165
|
+
Plus single `flow-summary.md`:
|
|
166
|
+
```markdown
|
|
167
|
+
### Flow Summary — <Figma file/page>
|
|
168
|
+
|
|
169
|
+
| # | Story | Frames | INVEST verdict | V audit |
|
|
170
|
+
|---|---|---|---|---|
|
|
171
|
+
| 1 | login-google-web | AUTH-001, AUTH-002 | READY | PASS |
|
|
172
|
+
| 2 | login-google-mobile | AUTH-101 | READY (after #1) | PASS |
|
|
173
|
+
| 3 | recovery-flow | AUTH-201..AUTH-212 | SPLIT RECOMMENDED | — |
|
|
174
|
+
|
|
175
|
+
**Dependency matrix (rule 10):**
|
|
176
|
+
|
|
177
|
+
| | #1 | #2 | #3 |
|
|
178
|
+
|-----|----|----|----|
|
|
179
|
+
| #1 | — | | |
|
|
180
|
+
| #2 |DEP | — | |
|
|
181
|
+
| #3 | | | — |
|
|
87
182
|
|
|
88
|
-
|
|
183
|
+
**Build order:** #1 → #2 (parallel: #3 after its own split).
|
|
184
|
+
|
|
185
|
+
**Design source:** Figma (or raster, if PNG fallback).
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Plus `.storywright-context.json` updated.
|
|
189
|
+
|
|
190
|
+
NO `clarifications.md`. NO Edge Cases sections. NO NFR blocks. NO per-claim visual tags.
|
|
89
191
|
|
|
90
192
|
## Examples
|
|
91
193
|
|
|
92
194
|
### Good
|
|
93
|
-
|
|
94
195
|
Input: Figma file URL with 3 flows on the "Auth" page (login, signup, password reset).
|
|
95
|
-
|
|
96
196
|
Output:
|
|
97
|
-
- 3 stories
|
|
98
|
-
-
|
|
99
|
-
-
|
|
197
|
+
- 3 canonical stories.
|
|
198
|
+
- `flow-summary.md` with mechanical matrix (#2 DEP #1; #3 independent).
|
|
199
|
+
- V audit: all PASS.
|
|
200
|
+
- Recovery flow has 12 frames → pre-split counter ≥2 → recommend `[[story-split]]` for #3 only.
|
|
201
|
+
|
|
202
|
+
### Good — PNG fallback
|
|
203
|
+
MCP unavailable. User exports 3 PNGs. Skill switches banner to raster, marks `design_source = raster`, generates 3 stories with `[mockup-pixel-derived]`-style inheritance (single banner per Design Reference).
|
|
204
|
+
|
|
205
|
+
### Good — passive goal fires
|
|
206
|
+
Flow goal inferred as "view dashboard". Skill detects passive verb → asks: "What does the user do with the dashboard data?". User: "Spot anomalies and drill into them." So-that strengthened.
|
|
100
207
|
|
|
101
208
|
### Bad
|
|
209
|
+
One story per frame. Frames are screens; stories are user goals.
|
|
102
210
|
|
|
103
|
-
|
|
211
|
+
### Bad
|
|
212
|
+
Emitting `clarifications.md`. Violates rule 1.
|
|
213
|
+
|
|
214
|
+
### Bad
|
|
215
|
+
Skipping the mechanical matrix in `flow-summary.md` when N>1.
|
|
104
216
|
|
|
105
217
|
## Common Pitfalls
|
|
106
218
|
|
|
107
219
|
- Treating each frame as a story.
|
|
108
|
-
- Skipping prototype-link analysis — without flow structure,
|
|
109
|
-
- Ignoring empty/error/loading states. Designers usually include them;
|
|
110
|
-
- Trusting MEDIUM/LOW inferences silently
|
|
111
|
-
- Generating stories without verifying
|
|
220
|
+
- Skipping prototype-link analysis — without flow structure, user goals are guesses.
|
|
221
|
+
- Ignoring empty/error/loading states. Designers usually include them; fold into AC failure paths.
|
|
222
|
+
- Trusting MEDIUM/LOW inferences silently — mark `⚠️ Assumed`.
|
|
223
|
+
- Generating stories without verifying coverage of all error paths.
|
|
224
|
+
- Skipping per-story V audit (rule 11) — figma flows are easy to over-split.
|
|
225
|
+
- Re-asking questions already in `.storywright-context.json`.
|
|
226
|
+
- Tagging every visual claim instead of using the single Figma banner.
|
|
112
227
|
|
|
113
228
|
## References
|
|
114
229
|
|
|
115
230
|
- [[story-generate]]
|
|
116
231
|
- [[story-split]]
|
|
232
|
+
- [[story-refine]]
|
|
117
233
|
- [[clarification-questions]]
|
|
118
|
-
- `./mcp-figma-notes.md` (
|
|
234
|
+
- `./mcp-figma-notes.md` (MCP server setup)
|
|
119
235
|
|
|
120
236
|
<claude-specific>
|
|
121
|
-
- Use Claude
|
|
237
|
+
- Use Claude vision when MCP is unavailable and the user drops PNGs.
|
|
122
238
|
- Use extended thinking for flow grouping — prototype links can be ambiguous.
|
|
123
239
|
- Cache the Phase 2 inference checklist across calls.
|
|
124
|
-
- When MCP Figma is available, batch frame metadata fetches into one round trip
|
|
240
|
+
- When MCP Figma is available, batch frame metadata fetches into one round trip.
|
|
241
|
+
- Read `.storywright-context.json` ONLY from the exact target output folder.
|
|
242
|
+
- Build the multi-story dependency matrix from Given-text parsing (rule 10), not intuition.
|
|
243
|
+
- Never call Write for any sidecar question file. Use `AskUserQuestion`.
|
|
125
244
|
</claude-specific>
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: story-generate
|
|
3
|
-
description: Transform an ambiguous prompt, half-baked story, screenshot, or Figma link into a Jira-ready user story
|
|
3
|
+
description: Transform an ambiguous prompt, half-baked story, screenshot, or Figma link into a Jira-ready user story. Cohn+Gherkin canonical. Asks clarifications ONLY in terminal.
|
|
4
4
|
trigger: "/story-generate | generate a user story | write a user story | turn this into a story | crear historia de usuario"
|
|
5
|
-
intent: Top-level orchestrator
|
|
6
|
-
version:
|
|
5
|
+
intent: Top-level orchestrator that drafts a fresh story from any input. Follows the same hard rules as story-refine v2.2 (Cohn philosophy, terminal-only Q, no mini-PRD, deterministic split gate).
|
|
6
|
+
version: 2.2.0
|
|
7
7
|
inputs:
|
|
8
8
|
- text
|
|
9
9
|
- image
|
|
10
10
|
- figma-link
|
|
11
11
|
outputs:
|
|
12
|
-
- story.jira-wiki.md
|
|
13
12
|
- story.standard.md
|
|
14
|
-
-
|
|
13
|
+
- story.jira-wiki.md
|
|
14
|
+
- .storywright-context.json
|
|
15
15
|
composes:
|
|
16
16
|
- _components/clarification-questions
|
|
17
17
|
- _components/acceptance-criteria
|
|
@@ -26,7 +26,82 @@ composes:
|
|
|
26
26
|
|
|
27
27
|
## Purpose
|
|
28
28
|
|
|
29
|
-
Take whatever the PM has — a one-liner, a half-baked story, a screenshot, a Figma link — and produce a story
|
|
29
|
+
Take whatever the PM has — a one-liner, a half-baked story, a screenshot, a Figma link — and produce a Cohn+Gherkin story an engineer can pick up and ship without follow-up questions. If the input is too broad, recommend `/story-split` instead of producing a mini-PRD.
|
|
30
|
+
|
|
31
|
+
## Hard rules (no exceptions)
|
|
32
|
+
|
|
33
|
+
1. **Terminal-only clarifications.** Never write any sidecar question file (no `clarifications.md`). All gap questions go through `AskUserQuestion` (batch in groups of ≤4). Non-blocking gaps → mark `⚠️ Assumed` inline.
|
|
34
|
+
|
|
35
|
+
2. **Cohn + Gherkin canonical.** One Use Case block. One AC scenario per story (one Given chain, one `When`, one `Then`). If the input naturally needs >1 `When`/`Then` → STOP drafting, recommend `/story-split`.
|
|
36
|
+
|
|
37
|
+
3. **No mini-PRDs.** Prohibited in story output:
|
|
38
|
+
- NFR blocks (a11y/i18n/perf/tokens) — these live in the team's DoD
|
|
39
|
+
- Edge Cases enumerations as a section — surface inside AC failure paths only
|
|
40
|
+
- Dependencies as prose — Jira links only
|
|
41
|
+
- Per-claim visual specs — use single banner (rule 5)
|
|
42
|
+
- Refinement logs >3 lines (>5 if SPLIT)
|
|
43
|
+
|
|
44
|
+
4. **Output language matches the user's chat language**, not the input's. Auto-detect first (see rule 4a); only ask via `AskUserQuestion` if signals split.
|
|
45
|
+
|
|
46
|
+
5. **Visual inference confidence — single banner only.** ONE banner at the top of the Design Reference block declares the source type. Claims under it inherit confidence:
|
|
47
|
+
- Raster source (PNG/JPG) → `**Source: raster mockup → all visual specs are pixel-derived, not token-confirmed.**`
|
|
48
|
+
- Figma source → `**Source: Figma → values can be tokenized at implementation.**`
|
|
49
|
+
- Design-token source → `**Source: design tokens → values are authoritative.**`
|
|
50
|
+
- Never assert hex / px / spacing from raster without the raster banner.
|
|
51
|
+
|
|
52
|
+
6. **Sibling task IDs.** If the draft references "next task / future task / another story" → check `<output-folder>/.storywright-context.json` first. If unresolved, ask. Tentative slugs follow rule F.
|
|
53
|
+
|
|
54
|
+
7. **Mockup chrome detection — closed list.** Chrome = `left nav rail / sidebar`, `top bar`, `footer`, `persistent toast/snackbar slot`, `persistent modal scrim`, `app-level tabs`. If image shows any AND the input does not mention them, ask via `AskUserQuestion` whether each is in-scope, sibling-scope, or out-of-scope. Anything not on the list is NOT chrome.
|
|
55
|
+
|
|
56
|
+
8. **Anti-PRD is part of INVEST `Small`.** See `[[invest-checklist]]` Small criterion (line-count ceiling lives there).
|
|
57
|
+
|
|
58
|
+
9. **Cross-skill context persistence.** When the skill resolves clarifications, write answers to `<output-folder>/.storywright-context.json`. Read only from the exact output folder of the current invocation; never search siblings or parents. Schema:
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"version": 1,
|
|
62
|
+
"decided_at": "<ISO date>",
|
|
63
|
+
"decided_by_skill": "story-generate",
|
|
64
|
+
"language": "EN | ES | ...",
|
|
65
|
+
"chrome_scope": "in-scope | in-scope-placeholder | sibling | out-of-scope",
|
|
66
|
+
"siblings": "TODO | <list of IDs> | not-applicable",
|
|
67
|
+
"design_source": "raster | figma | tokens",
|
|
68
|
+
"naming_pattern": "<see rule F>",
|
|
69
|
+
"extra": {}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
10. **Mixed input conflict detection.** When text + image + Figma disagree, surface as BLOCKING `AskUserQuestion`. Never silently pick a winner. (See source priority below.)
|
|
74
|
+
|
|
75
|
+
11. **Passive-goal downstream prompt (G).** If `I want to` verb is observational (`view, see, read, browse, look at, inspect, monitor`) and `so that` lacks a follow-up user action → ask once via `AskUserQuestion`: "What does the user do with this?". Strengthen the `so that` accordingly.
|
|
76
|
+
|
|
77
|
+
### 4a. Language auto-detect — expanded signals (E)
|
|
78
|
+
|
|
79
|
+
| Signal | Where | Weight |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| Gherkin keywords ("Given/When/Then") | AC block | high |
|
|
82
|
+
| Persona phrasing ("As a user" vs "Como un usuario") | Use Case | high |
|
|
83
|
+
| Column / field names ("Phone - primary", "Teléfono - principal") | AC bullets | medium |
|
|
84
|
+
| Domain verbs ("clicking" vs "hacer clic") | AC bullets | medium |
|
|
85
|
+
| Title language | header | low |
|
|
86
|
+
|
|
87
|
+
**Decision:**
|
|
88
|
+
- High+medium signals agree on M → adopt M silently. Mark inline `⚠️ Assumed: output language = <M> (auto-detected from <signals>)`.
|
|
89
|
+
- Signals split → ask once.
|
|
90
|
+
- Persist via rule 9.
|
|
91
|
+
|
|
92
|
+
### Rule F. Naming pattern — ask once, persist
|
|
93
|
+
|
|
94
|
+
When the skill needs to invent a tentative ticket slug AND `.storywright-context.json` has no `naming_pattern`, ask once:
|
|
95
|
+
- kebab-case feature-action (`customer-search-bar-wire`)
|
|
96
|
+
- verb-noun (`wire-search-bar`)
|
|
97
|
+
- domain-action (`search.customer.wire-input`)
|
|
98
|
+
- Jira prefix + numeric (`CSB-001`)
|
|
99
|
+
|
|
100
|
+
Persist in `.storywright-context.json`. Reuse for all sibling slugs.
|
|
101
|
+
|
|
102
|
+
### Rule D. Surface vs styling (deterministic)
|
|
103
|
+
|
|
104
|
+
A "named UI surface" counts as a separate outcome ONLY if it has its own user goal (verb where the user *does something with it*). If a noun is mentioned only in a styling context (color, padding, background) or as a sub-component of a parent surface (column inside a grid) → it is NOT a surface, it is styling. Count = 0.
|
|
30
105
|
|
|
31
106
|
## When to use
|
|
32
107
|
|
|
@@ -34,139 +109,155 @@ Take whatever the PM has — a one-liner, a half-baked story, a screenshot, a Fi
|
|
|
34
109
|
- The user pastes a vague story and wants it production-ready.
|
|
35
110
|
- The user drops an image/Figma link and asks for stories.
|
|
36
111
|
|
|
112
|
+
For inputs that clearly cover multiple outcomes → run the deterministic split gate (step 6 below) and recommend `/story-split` instead of drafting.
|
|
113
|
+
|
|
37
114
|
## Inputs & how to interpret each
|
|
38
115
|
|
|
39
116
|
### Text prompts
|
|
40
|
-
Anything from a
|
|
117
|
+
Anything from a phrase to a paragraph. If only a feature is named, infer the implicit user goal and confirm via rule G if passive.
|
|
41
118
|
|
|
42
119
|
### Local images (PNG/JPG)
|
|
43
|
-
Use vision. Extract
|
|
44
|
-
- UI elements (buttons, fields, navigation)
|
|
45
|
-
- Visible states (loading, error, success)
|
|
46
|
-
- Inferred flow (what does each element trigger?)
|
|
47
|
-
- Confidence per inference (high / medium / low). Anything below high → add `> ⚠️ Assumed:` blockquote in the output and surface in clarifications.
|
|
120
|
+
Use vision. Extract UI elements, visible states, inferred flow, confidence per inference. Anything below high confidence → mark inline `⚠️ Assumed`. NEVER assert pixel-precise visual specs inline with each claim — use the single banner (rule 5).
|
|
48
121
|
|
|
49
122
|
### Figma links
|
|
50
|
-
If MCP Figma is available (see `[[story-from-figma]]`), use it
|
|
51
|
-
|
|
52
|
-
### Mixed inputs (text + image + Figma)
|
|
53
|
-
|
|
54
|
-
The skill is designed to **fuse multiple sources** in a single invocation. Common pairings:
|
|
55
|
-
|
|
56
|
-
- **Text + screenshot** — text states the goal, image shows the proposed UI. Use text for `User Story / Goal / Scope`, image for `Components / States / Edge cases / UX flow`.
|
|
57
|
-
- **Text + Figma link** — text gives intent, Figma gives implementation surface. Use text for `User Story / Business goal`, Figma for `Technical considerations / Edge cases / Components / Multi-screen flows`.
|
|
58
|
-
- **Text + image + Figma** — full triangulation. Highest fidelity; also highest chance of conflict.
|
|
123
|
+
If MCP Figma is available (see `[[story-from-figma]]`), use it. If not, fall back to asking the user for screenshots.
|
|
59
124
|
|
|
60
|
-
|
|
125
|
+
### Mixed inputs (text + image + Figma) — source priority
|
|
61
126
|
|
|
62
127
|
| Section | Primary | Secondary | Tertiary |
|
|
63
128
|
|---|---|---|---|
|
|
64
|
-
| User Story / Goal | Text | Figma
|
|
65
|
-
|
|
|
129
|
+
| User Story / Goal | Text | Figma frame titles | Image |
|
|
130
|
+
| Scope | Text | Figma | Image |
|
|
66
131
|
| UI Components / States | Figma | Image | Text |
|
|
67
|
-
|
|
|
68
|
-
| Technical Considerations | Figma (component naming, design system refs) | Text | Image |
|
|
69
|
-
| Acceptance Criteria | Triangulate all three | — | — |
|
|
132
|
+
| AC observable outcomes | Triangulate | — | — |
|
|
70
133
|
|
|
71
|
-
**
|
|
134
|
+
**Conflicts → BLOCKING `AskUserQuestion`.** Never silently pick a winner.
|
|
72
135
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
136
|
+
## Canonical output shape
|
|
137
|
+
|
|
138
|
+
```markdown
|
|
139
|
+
### [Title]
|
|
140
|
+
|
|
141
|
+
#### Use Case
|
|
142
|
+
- **As a** [persona — never just "user"]
|
|
143
|
+
- **I want to** [action]
|
|
144
|
+
- **so that** [outcome with downstream action — rule G]
|
|
145
|
+
|
|
146
|
+
#### Preconditions (optional)
|
|
147
|
+
- ...
|
|
148
|
+
|
|
149
|
+
#### Out of Scope (optional)
|
|
150
|
+
- ...
|
|
151
|
+
|
|
152
|
+
#### Acceptance Criteria
|
|
153
|
+
- **Scenario:** [single-outcome scenario name]
|
|
154
|
+
- **Given:** [context — surface nouns drive downstream dep matrix]
|
|
155
|
+
- **and Given:** [context]
|
|
156
|
+
- **When:** [single trigger]
|
|
157
|
+
- **Then:** [single observable outcome]
|
|
158
|
+
|
|
159
|
+
#### Design Reference (optional)
|
|
160
|
+
**Source: <raster | figma | tokens> → <banner from rule 5>**
|
|
161
|
+
- [link or path]
|
|
162
|
+
- visual notes: [...]
|
|
163
|
+
|
|
164
|
+
#### INVEST
|
|
165
|
+
- I/N/V/E/S/T — one line each.
|
|
166
|
+
- **Verdict:** READY | SPLIT RECOMMENDED | NEEDS REFINEMENT | NOT A STORY
|
|
167
|
+
|
|
168
|
+
#### Generation log (≤3 lines; ≤5 if SPLIT)
|
|
169
|
+
- ...
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Nothing else. No NFR. No edge-cases enumeration. No deps prose. No Assumptions block.
|
|
77
173
|
|
|
78
174
|
## Application (step-by-step)
|
|
79
175
|
|
|
80
|
-
|
|
81
|
-
- **Single source** → process as before.
|
|
82
|
-
- **Mixed sources** → run the "Mixed inputs" protocol above, including source-priority lookup and explicit conflict detection BEFORE drafting.
|
|
83
|
-
2. **Intake gap check** — invoke `[[clarification-questions]]`. If it returns BLOCKING questions, **ask first** before drafting.
|
|
84
|
-
3. **Detect language** of input (es | en | other). Output in the input language.
|
|
85
|
-
4. **Draft skeleton** of the structured story (all 15 sections from the template).
|
|
86
|
-
5. **Fill the CORE first** (always required, in order):
|
|
87
|
-
1. **Title** — concise, ≤8 words.
|
|
88
|
-
2. **Summary** — single value-focused sentence ("Enable Google login for trial users to reduce signup friction"), NOT a feature label ("Add Google button"). Elevator pitch.
|
|
89
|
-
3. **User Story** (As a / I want to / so that).
|
|
90
|
-
- **Persona check:** if role is "user" or "customer", push for sharper ("trial user", "Workspace admin"). Generic personas hide motivation.
|
|
91
|
-
- **"So that" check:** outcome must be distinct from action. "So I can save my work" = restating; "So I don't lose progress if tab crashes" = real motivation.
|
|
92
|
-
4. **Acceptance Criteria** via `[[acceptance-criteria]]` — at minimum the happy path + one failure mode.
|
|
93
|
-
5. **Definition of Done** via `[[definition-of-done]]`.
|
|
94
|
-
|
|
95
|
-
6. **Fill OPTIONAL sections only if they have real content.** Drop any that would be empty or boilerplate:
|
|
96
|
-
- Contexto / Business goal — include when there's a stated trigger or KPI
|
|
97
|
-
- Scope / Out of scope — include when boundaries are non-obvious
|
|
98
|
-
- `[[business-rules]]` — include when invariants exist beyond the ACs
|
|
99
|
-
- Technical considerations — include when surface/SDK/flag matters
|
|
100
|
-
- `[[edge-cases]]` — include when ≥3 high-impact edges exist
|
|
101
|
-
- `[[analytics-events]]` — include when story has measurable funnel
|
|
102
|
-
- `[[risks-and-dependencies]]` — include when there are real blockers or unknowns
|
|
103
|
-
|
|
104
|
-
The bias is **less is more**. A clean 4-section story beats a 15-section one full of `N/A`.
|
|
105
|
-
6. **Run INVEST self-check** via `[[invest-checklist]]`:
|
|
106
|
-
- `READY` → continue.
|
|
107
|
-
- `NOT A STORY` (V failed) → STOP. Tell the user this is a tech task, not a user story. Suggest reframing or combining with user-facing work.
|
|
108
|
-
- `NEEDS REFINEMENT` (T or N failed) → revise the failing sections in place.
|
|
109
|
-
- `RUN A SPIKE` (E failed on unknowns) → recommend a 1–2 day investigation; do not split or generate yet.
|
|
110
|
-
- `SPLIT RECOMMENDED` (I, E, or S failed) → STOP. Hand off to `[[story-split]]`. **Never auto-split.**
|
|
111
|
-
7. **Render outputs** via `[[jira-wiki-formatter]]`:
|
|
112
|
-
- `story.jira-wiki.md` — Jira wiki markup
|
|
113
|
-
- `story.standard.md` — CommonMark
|
|
114
|
-
8. **If clarifications remain unresolved** (user skipped them, or low-confidence visual inferences exist):
|
|
115
|
-
- Emit `clarifications.md` with the outstanding questions
|
|
116
|
-
- Mark the story output with a `DRAFT` banner at the top
|
|
117
|
-
- Tell the user explicitly what would unblock promoting from DRAFT to READY
|
|
118
|
-
9. **Present both artifacts** as fenced code blocks. Ask the user whether to save to disk (offer paths under `./stories/<slug>/`).
|
|
176
|
+
0. **Detect input types** — text / image / figma-link / combination. Run conflict detection (rule 10) BEFORE drafting. Run chrome detection (rule 7).
|
|
119
177
|
|
|
120
|
-
|
|
178
|
+
1. **Read prior context.** If `<output-folder>/.storywright-context.json` exists (exact folder only), load it.
|
|
121
179
|
|
|
122
|
-
|
|
123
|
-
Input: *"Permitir login con Google"*
|
|
180
|
+
2. **Language resolution** (rule 4 + 4a). Auto-detect using expanded signals; ask only on split.
|
|
124
181
|
|
|
125
|
-
|
|
126
|
-
1. Run gap check → 3 BLOCKING questions: scope of accounts, account linking, surface (web/mobile/both).
|
|
127
|
-
2. Ask the 3 questions, wait for answers.
|
|
128
|
-
3. Draft + fill all 15 sections.
|
|
129
|
-
4. INVEST → `READY`.
|
|
130
|
-
5. Render both outputs.
|
|
131
|
-
6. Done.
|
|
182
|
+
3. **Persona sharpening.** If persona is "user" / "customer" / "person", ask via `AskUserQuestion` for the specific role (e.g., "Sales person", "Workspace admin"). Generic personas hide motivation.
|
|
132
183
|
|
|
133
|
-
|
|
134
|
-
Input: screenshot of a dashboard with a filter sidebar.
|
|
184
|
+
4. **Passive-goal check (rule G).** If `I want to` verb is observational + `so that` lacks downstream action → ask once.
|
|
135
185
|
|
|
136
|
-
|
|
137
|
-
1. Vision: extract filter categories, infer apply/reset actions.
|
|
138
|
-
2. Confidence on "filters persist across navigation" → MEDIUM → mark as `⚠️ Assumed` and surface in clarifications.
|
|
139
|
-
3. Run gap check → 1 BLOCKING (does this replace or augment current filters?).
|
|
140
|
-
4. Ask, draft, fill, INVEST, render.
|
|
186
|
+
5. **Gap-check** via `[[clarification-questions]]`. BLOCKING gaps → `AskUserQuestion` batched ≤4. Non-blocking → fill inline `⚠️ Assumed`.
|
|
141
187
|
|
|
142
|
-
|
|
188
|
+
6. **Deterministic pre-split test.** Count outcomes using the same rule as `[[story-refine]]`:
|
|
189
|
+
- +1 per AC bullet with action verb at user level
|
|
190
|
+
- +1 per distinct `When [event]`
|
|
191
|
+
- +1 per named UI surface with its own user goal (rule D)
|
|
192
|
+
- 0 for styling, sub-components, passive layout assertions
|
|
193
|
+
- Count ≥2 → STOP. Recommend `/story-split`. List candidate children + per-pair dep notes (rule A) + V audit (rule C from refine).
|
|
143
194
|
|
|
195
|
+
7. **Draft the canonical block** (Use Case + AC + Design Ref + INVEST). Preserve user wording where good.
|
|
196
|
+
|
|
197
|
+
8. **Run INVEST** via `[[invest-checklist]]`.
|
|
198
|
+
- `READY` → render.
|
|
199
|
+
- `SPLIT RECOMMENDED` → STOP, recommend split.
|
|
200
|
+
- `NEEDS REFINEMENT` → iterate failing dimension, max 1 cycle, then STOP.
|
|
201
|
+
- `NOT A STORY` → tell user it's a tech task and stop.
|
|
202
|
+
|
|
203
|
+
9. **Render** both outputs via `[[jira-wiki-formatter]]`. Files: `story.standard.md` + `story.jira-wiki.md`. Plus `.storywright-context.json`. No other files.
|
|
204
|
+
|
|
205
|
+
10. **Generation log** ≤3 bullets (≤5 if SPLIT) at end of story.
|
|
206
|
+
|
|
207
|
+
## Examples
|
|
208
|
+
|
|
209
|
+
### Good — text prompt
|
|
210
|
+
Input: *"Permitir login con Google"*
|
|
211
|
+
1. Language auto-detect → ES (persona "usuario", verbs "permitir").
|
|
212
|
+
2. Persona sharpening → ask: trial user? admin? signed-out visitor?
|
|
213
|
+
3. Pre-split count = 1 (one auth flow). Continue.
|
|
214
|
+
4. Draft Use Case + 1 AC (happy path, failure as `and Given`).
|
|
215
|
+
5. INVEST → READY.
|
|
216
|
+
6. Render.
|
|
217
|
+
|
|
218
|
+
### Good — image input
|
|
219
|
+
Input: dashboard screenshot with filter sidebar.
|
|
220
|
+
1. Vision extracts filters; one inference at MEDIUM confidence → mark `⚠️ Assumed` inline.
|
|
221
|
+
2. Pre-split count = 1 (one filter interaction surface).
|
|
222
|
+
3. Draft + INVEST → READY.
|
|
223
|
+
|
|
224
|
+
### Good — passive-goal prompt fires
|
|
225
|
+
Input: "As a user, I want to view list of customers, so that I find details."
|
|
226
|
+
- Detected: `view` (passive) + thin `so that`.
|
|
227
|
+
- Ask: "What does the user do with the customer they find?"
|
|
228
|
+
- User: "Call them."
|
|
229
|
+
- Refined `so that`: "so that I can find and call a customer to schedule a service."
|
|
230
|
+
|
|
231
|
+
### Bad — broad input drafted as one story
|
|
144
232
|
Input: *"Build the new dashboard"*
|
|
233
|
+
- Pre-split count ≥2 → STOP. Recommend `/story-split`. Do NOT draft a 15-section story.
|
|
145
234
|
|
|
146
|
-
|
|
235
|
+
### Bad — clarifications.md
|
|
236
|
+
Writing any sidecar question file. Violates rule 1.
|
|
237
|
+
|
|
238
|
+
### Bad — per-claim visual tag
|
|
239
|
+
`[mockup-pixel-derived]` on every line instead of the single banner. Violates rule 5.
|
|
147
240
|
|
|
148
241
|
## Common Pitfalls
|
|
149
242
|
|
|
150
|
-
- Drafting before
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
-
|
|
243
|
+
- Drafting before running the deterministic split gate (step 6).
|
|
244
|
+
- Auto-splitting. Never. Propose, wait for `/story-split`.
|
|
245
|
+
- Mixing languages. Pick one via rule 4 + 4a.
|
|
246
|
+
- Re-asking questions already resolved in `.storywright-context.json`.
|
|
247
|
+
- Letting per-claim `[mockup-pixel-derived]` tags litter the output.
|
|
248
|
+
- Treating image visual specs as authoritative without the rule-5 banner.
|
|
155
249
|
|
|
156
250
|
## References
|
|
157
251
|
|
|
158
|
-
- [[story-refine]] (
|
|
159
|
-
- [[story-split]] (
|
|
160
|
-
- [[story-from-figma]] (
|
|
252
|
+
- [[story-refine]] (when input is an existing story)
|
|
253
|
+
- [[story-split]] (when INVEST fails on I/E/S)
|
|
254
|
+
- [[story-from-figma]] (when input is Figma URL)
|
|
161
255
|
- [[clarification-questions]]
|
|
162
256
|
|
|
163
|
-
## Output templates
|
|
164
|
-
|
|
165
|
-
See `templates/story.jira-wiki.md` and `templates/story.standard.md` in this skill's folder for the canonical section ordering and formatting.
|
|
166
|
-
|
|
167
257
|
<claude-specific>
|
|
168
|
-
- Use extended thinking for INVEST
|
|
169
|
-
-
|
|
170
|
-
-
|
|
171
|
-
-
|
|
258
|
+
- Use extended thinking for INVEST + pre-split counting.
|
|
259
|
+
- Attach images in the same message for native vision; don't describe-then-reason in two steps.
|
|
260
|
+
- Read `.storywright-context.json` ONLY from the exact target output folder.
|
|
261
|
+
- Never call Write for any sidecar question file. Use `AskUserQuestion`.
|
|
262
|
+
- Treat step 6 (deterministic pre-split test) as a hard gate; do not skip even when the user wants a single story.
|
|
172
263
|
</claude-specific>
|
|
@@ -1,196 +1,321 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: story-split
|
|
3
|
-
description:
|
|
3
|
+
description: Split an oversize story into an epic plus Cohn+Gherkin children. Mechanical NxN dep matrix and per-child V audit. Asks ONLY in terminal. Never auto-splits.
|
|
4
4
|
trigger: "/story-split | split this story | divide this story | dividir historia | this is too big"
|
|
5
|
-
intent: Splitting skill
|
|
6
|
-
version:
|
|
5
|
+
intent: Splitting skill driven by INVEST failure reasons. Produces an epic plus N child story stubs in the v2.2 canonical Cohn+Gherkin shape, with mechanical dependency matrix and Valuable audit per child.
|
|
6
|
+
version: 2.2.0
|
|
7
7
|
inputs:
|
|
8
8
|
- text
|
|
9
9
|
- image
|
|
10
10
|
- figma-link
|
|
11
11
|
outputs:
|
|
12
|
-
- split-plan.md
|
|
13
12
|
- epic.md
|
|
14
|
-
- story-1.md
|
|
13
|
+
- story-1.md
|
|
14
|
+
- story-2.md
|
|
15
|
+
- .storywright-context.json
|
|
15
16
|
composes:
|
|
16
17
|
- _components/invest-checklist
|
|
17
18
|
- _components/clarification-questions
|
|
19
|
+
- _components/acceptance-criteria
|
|
20
|
+
- _components/jira-wiki-formatter
|
|
18
21
|
---
|
|
19
22
|
|
|
20
23
|
## Purpose
|
|
21
24
|
|
|
22
|
-
When a story is an epic in disguise, splitting badly is worse than not splitting. This skill uses
|
|
25
|
+
When a story is an epic in disguise, splitting badly is worse than not splitting. This skill uses established INVEST-compatible patterns to propose a clean decomposition, then mechanically verifies each child's independence and value before saving. The user always approves the plan before any child is written.
|
|
23
26
|
|
|
24
|
-
##
|
|
27
|
+
## Hard rules (v2.2 parity with refine/generate)
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
- User explicitly asks: "this story is too big, split it".
|
|
28
|
-
- Input visibly mixes ≥2 flows.
|
|
29
|
+
1. **Terminal-only clarifications.** Never write any sidecar question file. All gap questions through `AskUserQuestion`, batched ≤4. Non-blocking gaps → `⚠️ Assumed` inline.
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
2. **Children are Cohn+Gherkin canonical.** Each child has ONE Use Case block + ONE AC scenario (one Given chain + one `When` + one `Then`). If a child still needs >1 `When`/`Then` → recursive re-split.
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
- **image (optional)** — companion mockup. Use to validate scope and reveal hidden sub-flows the text doesn't mention.
|
|
34
|
-
- **figma-link (optional)** — companion design. Often makes splitting easier: prototype links and frame structure reveal natural flow boundaries that map to children.
|
|
33
|
+
3. **No mini-PRDs in children.** Same prohibition list as refine v2.2 — no NFR blocks, no Edge Cases enumerations, no Dependencies prose, no per-claim visual specs, refinement logs ≤3 lines (≤5 if recursive split).
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
4. **Output language matches the user's chat language.** Auto-detect via rule 4a; ask only if signals split. Persist via rule 9.
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
- **Text is canonical for User Story / Scope / Business Goal** of the epic.
|
|
40
|
-
- **Figma / image is canonical for flow structure** — use prototype links to enumerate candidate sub-flows. Each flow is a candidate child story.
|
|
41
|
-
- **Conflict handling:** if Figma shows N flows but text only mentions K (K < N), surface this in the gap-check via `[[clarification-questions]]` BEFORE drafting the split plan. Ask: "Figma includes flows for X, Y, Z — include in this epic, or scope out?" Never silently expand or shrink scope.
|
|
42
|
-
- See `[[story-generate]]` "Mixed inputs" for the full source-priority matrix.
|
|
37
|
+
5. **Visual inference confidence — single banner only** in each child's Design Reference block. No per-claim `[mockup-pixel-derived]` tags.
|
|
43
38
|
|
|
44
|
-
|
|
39
|
+
6. **Sibling task IDs.** When referencing tickets that don't exist yet, follow rule F (naming pattern) instead of inventing slugs.
|
|
40
|
+
|
|
41
|
+
7. **Chrome detection — closed list** (nav rail, top bar, footer, toast slot, modal scrim, app tabs). If image shows chrome and the input doesn't mention it, ask whether to add as its own child, attach to an existing child, or scope out.
|
|
42
|
+
|
|
43
|
+
8. **Anti-PRD is part of each child's INVEST `Small` criterion** — see `[[invest-checklist]]` Small.
|
|
44
|
+
|
|
45
|
+
9. **Cross-skill context persistence.** Read `<output-folder>/.storywright-context.json` first (exact folder only). Write updated answers back at the end. Schema:
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"version": 1,
|
|
49
|
+
"decided_at": "<ISO date>",
|
|
50
|
+
"decided_by_skill": "story-split",
|
|
51
|
+
"language": "EN | ES | ...",
|
|
52
|
+
"chrome_scope": "in-scope | in-scope-placeholder | sibling | out-of-scope",
|
|
53
|
+
"siblings": "TODO | <list of IDs> | not-applicable",
|
|
54
|
+
"design_source": "raster | figma | tokens",
|
|
55
|
+
"naming_pattern": "<see rule F>",
|
|
56
|
+
"extra": { "split_pattern": "...", "core_complexity": "..." }
|
|
57
|
+
}
|
|
58
|
+
```
|
|
45
59
|
|
|
46
|
-
|
|
60
|
+
10. **Children independence — mechanical detection (A).** For each child Cj, parse its `Given:` lines for surface nouns owned by sibling Ci. If matched → `DEP(Cj → Ci)`. The dependency matrix IS the union of those matches. No intuition-based deps. Affected child's INVEST `Independent` becomes `PARTIAL · depends on <Ci>`. Build order in epic.md is a topological sort of the matrix.
|
|
47
61
|
|
|
48
|
-
|
|
62
|
+
11. **Per-child V audit (C).** For each candidate child, run one-line test: "If only this child ships and no sibling exists, does a real user complete a real task?". If answer is "no, useless until <other> ships" → mark V = `WEAK · merge-upstream-candidate` and recommend merging into the parent surface. Do not let stylistic/UI-fragment children survive the split.
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
- **Testable FAILS** → **fix in place** via `[[story-refine]]` first. Splitting an untestable story produces untestable children.
|
|
52
|
-
- **Negotiable FAILS** → fix in place; the story is over-prescriptive, not too big.
|
|
53
|
-
- **Estimable FAILS due to unknowns** → run a **spike** (Pattern 9 below), not a split.
|
|
54
|
-
- **Independent / Estimable / Small FAIL** → continue to pattern selection.
|
|
64
|
+
12. **Passive-goal downstream prompt (G).** If any child's `I want to` verb is observational (view/see/read/browse/look/inspect/monitor) AND `so that` lacks a follow-up action → ask once via `AskUserQuestion` per child (batched ≤4 across children).
|
|
55
65
|
|
|
56
|
-
|
|
66
|
+
13. **Determinism on counts.** Use the same deterministic surface-vs-styling counter (rule D from refine v2.2) inside child re-split checks.
|
|
57
67
|
|
|
58
|
-
|
|
68
|
+
### 4a. Language auto-detect — expanded signals (E)
|
|
69
|
+
Same weighted signal table as refine v2.2 (Gherkin keywords, persona phrasing, column names, domain verbs, title). Adopt silently when high+medium signals agree; ask only if split.
|
|
59
70
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
### Rule F. Naming pattern — ask once, persist
|
|
72
|
+
Same kebab / verb-noun / domain-action / Jira-prefix options. Persist in `naming_pattern`. Reuse across this run AND future skills.
|
|
73
|
+
|
|
74
|
+
### Rule D. Surface vs styling (deterministic)
|
|
75
|
+
A noun counts as a separate surface ONLY if it has its own user goal (verb). Styling, sub-components, and passive layout assertions do not count.
|
|
76
|
+
|
|
77
|
+
## When to use
|
|
78
|
+
|
|
79
|
+
- `[[invest-checklist]]` returned `SPLIT RECOMMENDED` (I, E, or S fail).
|
|
80
|
+
- User explicitly asks: "this story is too big, split it".
|
|
81
|
+
- `[[story-refine]]` or `[[story-generate]]` deterministic pre-split test ≥2.
|
|
82
|
+
|
|
83
|
+
## Inputs & interpretation
|
|
64
84
|
|
|
65
|
-
|
|
85
|
+
- **text** — the oversize story (or epic-scoped one-liner).
|
|
86
|
+
- **image (optional)** — companion mockup. Use to validate scope and reveal hidden sub-flows.
|
|
87
|
+
- **figma-link (optional)** — companion design. Prototype links / frame structure reveal natural flow boundaries.
|
|
66
88
|
|
|
67
|
-
|
|
89
|
+
### Mixed inputs source-priority
|
|
68
90
|
|
|
69
|
-
|
|
91
|
+
- Text canonical for `User Story / Scope / Business Goal` of the epic.
|
|
92
|
+
- Figma / image canonical for `flow structure / candidate children`.
|
|
93
|
+
- Conflicts → BLOCKING `AskUserQuestion`. Never silently expand or shrink scope.
|
|
70
94
|
|
|
71
|
-
|
|
95
|
+
## Pre-split gate (STOP conditions)
|
|
72
96
|
|
|
73
|
-
|
|
97
|
+
Run `[[invest-checklist]]` first:
|
|
74
98
|
|
|
75
|
-
|
|
99
|
+
- **V FAILS** → STOP. Not a story. Combine with related user-facing work. Do not split.
|
|
100
|
+
- **T FAILS** → fix in place via `[[story-refine]]`. Splitting untestable input produces untestable children.
|
|
101
|
+
- **N FAILS** → fix in place. Story is over-prescriptive, not too big.
|
|
102
|
+
- **E FAILS due to unknowns** → recommend a spike, not a split.
|
|
103
|
+
- **I / E (size) / S FAIL** → proceed to pattern selection.
|
|
76
104
|
|
|
77
|
-
|
|
105
|
+
## Pattern catalog (apply in order; stop at first that fits)
|
|
78
106
|
|
|
79
|
-
|
|
107
|
+
Humanizing Work methodology (Lawrence & Green).
|
|
80
108
|
|
|
81
|
-
**
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
|
|
109
|
+
1. **Workflow steps — thin end-to-end slices.** NOT step1/step2 of the journey. Each child delivers the FULL workflow with increasing sophistication.
|
|
110
|
+
- ❌ Wrong: editorial / legal / publish. Story 1 alone delivers nothing.
|
|
111
|
+
- ✅ Right: publish immediately. Story 2 adds editorial. Story 3 adds legal.
|
|
112
|
+
2. **CRUD operations.** "Manage" / "handle" / "maintain" → split into C/R/U/D.
|
|
113
|
+
3. **Business rule variations.** Same feature, different rules (members / VIP / first-time).
|
|
114
|
+
4. **Data type variations.** One story per data shape (jpg / pdf / mp4).
|
|
115
|
+
5. **Data entry / UI complexity.** Basic input first; fancy UI (calendar, autocomplete) as follow-ups.
|
|
116
|
+
6. **Major effort.** First implementation does the heavy infrastructure lift; subsequent stories are trivial additions.
|
|
117
|
+
7. **Simple / complex.** Strip variations from the core. Story 1 = simplest case that still delivers value.
|
|
118
|
+
8. **Defer performance.** Make-it-work before make-it-fast.
|
|
119
|
+
9. **Spike (last resort).** Time-boxed investigation. Not a story.
|
|
85
120
|
|
|
86
|
-
|
|
121
|
+
**Anti-patterns (NOT splits):**
|
|
122
|
+
- Horizontal slicing (frontend / backend) — no user value per child.
|
|
123
|
+
- Task decomposition ("set up DB", "write endpoint").
|
|
124
|
+
- Meaningless halves.
|
|
87
125
|
|
|
88
|
-
|
|
126
|
+
## Cynefin domain calibration
|
|
89
127
|
|
|
90
|
-
- **Obvious / Complicated** —
|
|
91
|
-
- **Complex** —
|
|
92
|
-
- **Chaotic** —
|
|
128
|
+
- **Obvious / Complicated** — enumerate all children, prioritize by value/risk.
|
|
129
|
+
- **Complex** — produce 1–2 learning stories that ship something observable; let usage teach the rest.
|
|
130
|
+
- **Chaotic** — defer splitting; stabilize first.
|
|
93
131
|
|
|
94
|
-
|
|
132
|
+
## Meta-pattern (every pattern)
|
|
95
133
|
|
|
96
|
-
For any pattern you pick:
|
|
97
134
|
1. Name the **core complexity** that makes the story big.
|
|
98
135
|
2. List **all variations** of that complexity.
|
|
99
136
|
3. Pick **one variation** as the simplest complete vertical slice.
|
|
100
137
|
4. Each other variation becomes its own story.
|
|
101
138
|
|
|
102
|
-
|
|
139
|
+
## Application (step-by-step)
|
|
140
|
+
|
|
141
|
+
0. **Read prior context.** Load `<output-folder>/.storywright-context.json` if present (exact folder only). Apply resolved answers.
|
|
142
|
+
|
|
143
|
+
1. **Detect input types + companion sources.** Run conflict detection (mixed inputs). Run chrome detection (rule 7).
|
|
144
|
+
|
|
145
|
+
2. **Language resolution** via rule 4a.
|
|
146
|
+
|
|
147
|
+
3. **Pre-split gate.** Run `[[invest-checklist]]`. Honor STOP conditions above.
|
|
148
|
+
|
|
149
|
+
4. **Pattern selection.** Apply catalog in order. Name first fit. Name the meta-pattern's "core complexity". Note Cynefin domain.
|
|
150
|
+
|
|
151
|
+
5. **Draft split plan** as a terminal table (no file yet):
|
|
103
152
|
|
|
104
|
-
1. Run `[[invest-checklist]]` and apply the pre-split gates above. If you should not split, say so explicitly and stop.
|
|
105
|
-
2. Apply the pattern catalog in order. Name the first pattern that fits and the meta-pattern's "core complexity".
|
|
106
|
-
3. **Draft a split plan** as a Markdown table:
|
|
107
153
|
```
|
|
108
154
|
### Split Plan
|
|
155
|
+
Rationale: <INVEST failure reasons>
|
|
156
|
+
Core complexity: <meta-pattern>
|
|
157
|
+
Pattern(s): <names>
|
|
158
|
+
Cynefin: <domain>
|
|
109
159
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
160
|
+
| # | Proposed child | Pattern | V audit (rule 11) |
|
|
161
|
+
|---|---|---|---|
|
|
162
|
+
| 1 | ... | Workflow simple | PASS / WEAK·merge |
|
|
163
|
+
| 2 | ... | Data variation | PASS |
|
|
164
|
+
```
|
|
113
165
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
166
|
+
6. **Strategic check before approval:**
|
|
167
|
+
- Does the split reveal low-value work we can deprioritize or kill?
|
|
168
|
+
- Are the children roughly equal in size?
|
|
169
|
+
If neither holds, try a different pattern.
|
|
117
170
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
171
|
+
7. **STOP and ask the user to approve via `AskUserQuestion`:**
|
|
172
|
+
- Approve → proceed to step 8.
|
|
173
|
+
- Adjust → edit, re-loop.
|
|
174
|
+
- Cancel → mark original as `NEEDS REFINEMENT`, stop.
|
|
175
|
+
|
|
176
|
+
8. **For each approved child, write the canonical block** (Use Case + AC + Design Ref + INVEST):
|
|
177
|
+
|
|
178
|
+
```markdown
|
|
179
|
+
### [Child Title]
|
|
180
|
+
|
|
181
|
+
#### Use Case
|
|
182
|
+
- **As a** [persona]
|
|
183
|
+
- **I want to** [action]
|
|
184
|
+
- **so that** [outcome — rule G applied]
|
|
124
185
|
|
|
125
|
-
|
|
186
|
+
#### Acceptance Criteria
|
|
187
|
+
- **Scenario:** [single outcome]
|
|
188
|
+
- **Given:** [context — surface nouns drive dep matrix]
|
|
189
|
+
- **When:** [single trigger]
|
|
190
|
+
- **Then:** [single observable outcome]
|
|
191
|
+
|
|
192
|
+
#### Design Reference (optional)
|
|
193
|
+
**Source: <raster | figma | tokens> → <banner from rule 5>**
|
|
194
|
+
- [link / path]
|
|
195
|
+
|
|
196
|
+
#### INVEST
|
|
197
|
+
- I — <PASS | PARTIAL · depends on <Ci>>
|
|
198
|
+
- N/V/E/S/T — one line each
|
|
199
|
+
- **Verdict:** READY | READY (after <Ci> builds) | WEAK·merge-upstream-candidate
|
|
200
|
+
|
|
201
|
+
#### Refinement log (≤3 lines)
|
|
202
|
+
- Split from parent; pattern: <name>.
|
|
126
203
|
```
|
|
127
|
-
4. **Split evaluation (strategic check before approval).** Ask:
|
|
128
|
-
- **Does the split reveal low-value work we can deprioritize or kill?** Good splits surface 80/20 — e.g., after splitting flight search, "flexible dates" turns out to be rarely used → drop it.
|
|
129
|
-
- **Are the children roughly equal in size?** Equal-sized children give PMs prioritization flexibility mid-sprint.
|
|
130
|
-
If neither holds, try a different pattern.
|
|
131
|
-
5. **STOP and ask the user to approve the plan.** Options:
|
|
132
|
-
- "Approve plan" → proceed to step 6
|
|
133
|
-
- "Adjust" → user edits the table or merges/splits rows
|
|
134
|
-
- "Cancel" → leave the story unsplit (mark it as `NEEDS REFINEMENT` for the team to negotiate)
|
|
135
|
-
6. **After approval:**
|
|
136
|
-
- Write `epic.md` — title, description, child story list, business goal, dependencies between children
|
|
137
|
-
- Write one stub per child: title + 1-line user story + open clarifications. **Do not run the full story-generate flow yet** — stubs are placeholders; user invokes `[[story-generate]]` per child when ready.
|
|
138
|
-
7. **Coherence check** — verify the children together cover the original scope. If any child overlaps another or the union has gaps, flag it before saving.
|
|
139
|
-
8. **Recursive re-split check.** For each child, ask: still >1 sprint? If yes, restart at the pattern catalog **for that child**. Keep splitting until every leaf is sprint-shippable. Surface the tree visually in the plan.
|
|
140
|
-
9. **Save all artifacts** under `./stories/<epic-slug>/`:
|
|
141
|
-
- `epic.md`
|
|
142
|
-
- `story-1.md`, `story-2.md`, …
|
|
143
|
-
- `split-plan.md` (the decision trail)
|
|
144
204
|
|
|
145
|
-
|
|
205
|
+
9. **Build the dependency matrix mechanically (rule 10).** Parse each child's `Given` lines for surface nouns owned by other children. Emit the matrix in `epic.md`.
|
|
146
206
|
|
|
147
|
-
|
|
207
|
+
10. **Run V audit per child (rule 11).** Flag merge-upstream candidates in `epic.md`. Recommend merging instead of keeping standalone.
|
|
208
|
+
|
|
209
|
+
11. **Recursive re-split check.** For each child, run the deterministic counter (rule D). If count ≥2 for any child → recursive split of that child. Surface the tree in `epic.md`.
|
|
210
|
+
|
|
211
|
+
12. **Coherence check** — verify children together cover the original scope. Flag gaps or overlaps before saving.
|
|
212
|
+
|
|
213
|
+
13. **Write `epic.md`** at `<output-folder>/`:
|
|
214
|
+
|
|
215
|
+
```markdown
|
|
216
|
+
### EPIC: <title>
|
|
217
|
+
|
|
218
|
+
**Why split:** <pattern + core complexity + INVEST failure reasons>
|
|
219
|
+
|
|
220
|
+
**Cynefin domain:** <domain>
|
|
221
|
+
|
|
222
|
+
**Children independence matrix (mechanical, rule 10):**
|
|
223
|
+
|
|
224
|
+
| | C1 | C2 | C3 | ... |
|
|
225
|
+
|--------|----|----|----|-----|
|
|
226
|
+
| C1 | — | | | |
|
|
227
|
+
| C2 |DEP | — | | |
|
|
228
|
+
| ... | | | | |
|
|
229
|
+
|
|
230
|
+
**Build order (topological):** C1 → C2 → ...
|
|
148
231
|
|
|
149
|
-
|
|
232
|
+
**V audit (rule 11):**
|
|
233
|
+
- C1 — PASS
|
|
234
|
+
- C2 — PASS
|
|
235
|
+
- C3 — WEAK · merge-upstream-candidate (merge into C2)
|
|
150
236
|
|
|
237
|
+
**Children:**
|
|
238
|
+
1. story-1.md — <slug per naming pattern F>
|
|
239
|
+
2. story-2.md
|
|
240
|
+
...
|
|
241
|
+
|
|
242
|
+
**Design source:** <raster | figma | tokens>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
14. **Write all `story-N.md` files** and `.storywright-context.json` updated with `split_pattern` and `core_complexity` under `extra`.
|
|
246
|
+
|
|
247
|
+
## Validate every child (must pass all 6)
|
|
248
|
+
|
|
249
|
+
1. Delivers user value independently (rule 11 V audit PASS).
|
|
250
|
+
2. Developable with explicit build order from the matrix (no implicit deps).
|
|
251
|
+
3. Testable: single Given/When/Then with observable outcome.
|
|
252
|
+
4. Sprintable (1–5 days work).
|
|
253
|
+
5. Union equals original scope (coherence check).
|
|
254
|
+
6. ≤60 lines per child story (anti-PRD via INVEST Small).
|
|
255
|
+
|
|
256
|
+
A "no" on any line → revise the split.
|
|
257
|
+
|
|
258
|
+
## Examples
|
|
259
|
+
|
|
260
|
+
### Good
|
|
261
|
+
Original: "Permitir login con Google" with INVEST Small + Estimable FAIL.
|
|
151
262
|
Split:
|
|
152
263
|
1. Web — new accounts only (Simple)
|
|
153
264
|
2. Mobile — new accounts only (Simple)
|
|
154
|
-
3. Account linking with existing email/password (
|
|
155
|
-
4. Workspace domain restriction (
|
|
265
|
+
3. Account linking with existing email/password (Major effort)
|
|
266
|
+
4. Workspace domain restriction (Business rule variation)
|
|
156
267
|
|
|
157
|
-
|
|
268
|
+
Matrix mechanical:
|
|
269
|
+
- C2.Given mentions "Google sign-in handshake" owned by C1 → DEP(C2 → C1)
|
|
270
|
+
- C3.Given mentions "Google account exists" owned by C1 → DEP(C3 → C1)
|
|
271
|
+
- C4 independent.
|
|
158
272
|
|
|
159
|
-
|
|
273
|
+
V audit: all PASS.
|
|
160
274
|
|
|
161
|
-
|
|
275
|
+
Build order: C1 → {C2, C3} → C4 (C4 parallel anytime).
|
|
162
276
|
|
|
163
|
-
|
|
277
|
+
### Good — merge recommendation
|
|
278
|
+
Original story produced child "results counter" + child "grid". Counter's V audit:
|
|
279
|
+
- "If only counter ships and no grid exists, does a user complete a task?" → no.
|
|
280
|
+
- V = WEAK · merge-upstream-candidate.
|
|
281
|
+
- Epic recommends merging counter into grid child.
|
|
164
282
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
3. **Testable** with concrete ACs?
|
|
168
|
-
4. **Sprintable** (1–5 days of work, single sprint)?
|
|
169
|
-
5. **Union equals original** — together do they cover the original scope?
|
|
283
|
+
### Bad
|
|
284
|
+
Splitting "Permitir login con Google" into "Backend auth endpoint" + "Frontend login button". Task split, not story split. Both fail rule 11.
|
|
170
285
|
|
|
171
|
-
|
|
286
|
+
### Bad
|
|
287
|
+
Claiming all 5 children Independent without running rule 10 matrix.
|
|
288
|
+
|
|
289
|
+
### Bad
|
|
290
|
+
Writing any sidecar question file. Violates rule 1.
|
|
172
291
|
|
|
173
292
|
## Common Pitfalls
|
|
174
293
|
|
|
175
|
-
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
182
|
-
-
|
|
183
|
-
-
|
|
184
|
-
-
|
|
185
|
-
-
|
|
294
|
+
- Skipping the INVEST pre-split gate. Splitting non-V or non-T input.
|
|
295
|
+
- Workflow split done step-by-step instead of thin end-to-end.
|
|
296
|
+
- Horizontal slicing (frontend / backend / DB).
|
|
297
|
+
- Task splits.
|
|
298
|
+
- Splitting on size alone without naming pattern or core complexity.
|
|
299
|
+
- Forcing a pattern that doesn't fit.
|
|
300
|
+
- Auto-splitting without user approval.
|
|
301
|
+
- Skipping the mechanical matrix (rule 10).
|
|
302
|
+
- Skipping per-child V audit (rule 11).
|
|
303
|
+
- Letting tree go >5 children — that's an initiative, not an epic.
|
|
304
|
+
- Splitting in Chaotic Cynefin — stabilize first.
|
|
305
|
+
- Re-asking questions already in `.storywright-context.json`.
|
|
186
306
|
|
|
187
307
|
## References
|
|
188
308
|
|
|
189
309
|
- [[invest-checklist]]
|
|
190
310
|
- [[story-generate]]
|
|
311
|
+
- [[story-refine]]
|
|
191
312
|
- [[clarification-questions]]
|
|
192
313
|
|
|
193
314
|
<claude-specific>
|
|
194
|
-
- Use extended thinking
|
|
195
|
-
- Cache the
|
|
315
|
+
- Use extended thinking for pattern selection (compare options explicitly).
|
|
316
|
+
- Cache the 9-pattern catalog and the v2.2 hard-rule list.
|
|
317
|
+
- Build the dependency matrix from Given-text parsing (rule 10), not intuition.
|
|
318
|
+
- Run V audit per child (rule 11) and flag merge candidates loudly.
|
|
319
|
+
- Never call Write for any sidecar question file. Use `AskUserQuestion`.
|
|
320
|
+
- Read `.storywright-context.json` ONLY from the exact target output folder.
|
|
196
321
|
</claude-specific>
|