@pavp/storywright 1.5.0 → 1.6.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pavp/storywright",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "description": "PM Skills pack for Claude Code — turn ambiguous inputs (prompts, screenshots, Figma links) into Jira-ready user stories.",
5
5
  "keywords": [
6
6
  "claude",
@@ -0,0 +1,279 @@
1
+ ---
2
+ name: storywright-base
3
+ description: Shared base behavior for all storywright top-level skills. Hard rules, canonical output, terminal-only Q, context schema, mechanical deps, V audit, language detect.
4
+ trigger: "internal use by story-* skills"
5
+ intent: Component skill that holds the v2.2 baseline. Top-level skills (story-generate, story-refine, story-split, story-from-figma) compose this and add only their source-specific behavior on top.
6
+ version: 2.2.0
7
+ inputs:
8
+ - none
9
+ outputs:
10
+ - none
11
+ ---
12
+
13
+ ## Purpose
14
+
15
+ Every top-level storywright skill must behave identically except for three things:
16
+
17
+ 1. **Source** — what the input is (raw prompt / existing story / oversize story / Figma URL).
18
+ 2. **Prompt** — what the user is asking for.
19
+ 3. **Split behavior** — whether the skill produces 1 story, recommends a split, or produces N stories directly.
20
+
21
+ Everything else (how to ask questions, what shape the output takes, how to detect language, how to count outcomes, how to flag dependencies, how to persist context) lives here.
22
+
23
+ If you are reading this through a top-level skill, treat every rule below as non-negotiable for that skill too.
24
+
25
+ ## Hard rules (v2.2 — apply to all top-level storywright skills)
26
+
27
+ 1. **Terminal-only clarifications.** Never write any sidecar question file (no `clarifications.md`, no `questions.md`, nothing). All gap questions go through `AskUserQuestion`, batched ≤4 per call. Non-blocking gaps → mark `⚠️ Assumed: <text>` inline in the story body — do not ask.
28
+
29
+ 2. **Cohn + Gherkin canonical.** Every story (or child story) has:
30
+ - ONE Use Case block (`As a / I want to / so that`).
31
+ - ONE AC Scenario (one Given chain + one `When` + one `Then`).
32
+ If the input naturally needs >1 `When`/`Then`, the skill MUST stop the single-story path and route to `[[story-split]]`.
33
+
34
+ 3. **No mini-PRDs.** PROHIBITED sections in any story output:
35
+ - Non-Functional Requirements blocks (a11y/i18n/perf/tokens) — DoD only.
36
+ - Edge Cases enumerated as their own section — fold into AC failure paths.
37
+ - Dependencies as prose — Jira ticket links only.
38
+ - Per-claim visual specs (pixel measurements, hex inferences) inline — use single banner (rule 5).
39
+ - Logs >3 lines (>5 if SPLIT verdict).
40
+
41
+ 4. **Output language matches the user's chat language**, not the input's. Auto-detect first via rule 4a; only ask via `AskUserQuestion` if signals split.
42
+
43
+ 5. **Visual inference confidence — single banner only.** Do NOT tag every visual claim. ONE banner at the top of the Design Reference block declares source type; all claims under it inherit:
44
+ - Raster source (PNG/JPG) → `**Source: raster mockup → all visual specs are pixel-derived, not token-confirmed.**`
45
+ - Figma source → `**Source: Figma → values can be tokenized at implementation.**`
46
+ - Design-token source → `**Source: design tokens → values are authoritative.**`
47
+ Never assert hex / px / spacing from raster without the raster banner.
48
+
49
+ 6. **Sibling task IDs.** If the story references "next task / future task / another story / siblings" — check `<output-folder>/.storywright-context.json` first. If unresolved, ask via `AskUserQuestion`. If user has none yet, leave `TODO: link sibling` (unless rule F applies — invent slug per persisted naming pattern).
50
+
51
+ 7. **Mockup chrome detection — closed list.** Chrome = exactly:
52
+ - left nav rail / sidebar
53
+ - top bar (user menu, global breadcrumbs, global search)
54
+ - footer
55
+ - persistent toast/snackbar slot
56
+ - persistent modal scrim
57
+ - app-level tabs
58
+
59
+ If a companion image shows any of these AND the input does not mention them, ask via `AskUserQuestion` whether each is `in-scope`, `sibling-scope`, or `out-of-scope`. Anything not on this list (cards, section headers, in-flow buttons) is NOT chrome — do not surface as a chrome question.
60
+
61
+ 8. **Anti-PRD is part of INVEST `Small`, not a separate step.** See `[[invest-checklist]]` Small criterion — line-count ceiling (~60 lines) lives there. Single source of truth.
62
+
63
+ 9. **Cross-skill context persistence.** When any storywright skill resolves a clarification via `AskUserQuestion`, write the **answer** to `<output-folder>/.storywright-context.json`. Read only from the exact output folder of the current invocation; never search siblings or parents. Schema:
64
+
65
+ ```json
66
+ {
67
+ "version": 1,
68
+ "decided_at": "<ISO date>",
69
+ "decided_by_skill": "story-generate | story-refine | story-split | story-from-figma",
70
+ "language": "EN | ES | ...",
71
+ "chrome_scope": "in-scope | in-scope-placeholder | sibling | out-of-scope",
72
+ "siblings": "TODO | <list of IDs> | not-applicable",
73
+ "design_source": "raster | figma | tokens",
74
+ "naming_pattern": "kebab-feature-action | verb-noun | domain-action | jira-prefix",
75
+ "extra": {}
76
+ }
77
+ ```
78
+
79
+ Every skill MUST read this file BEFORE asking any question. Every skill MUST write this file when it resolves a question.
80
+
81
+ 10. **Children independence — mechanical detection (rule A).** When any skill produces multiple stories or children (story-split, story-from-figma multi-flow, story-refine recommending split):
82
+ - For each child Cj, parse its `Given:` and `and Given:` lines.
83
+ - If any Given text contains a surface noun owned by child Ci (Ci's title/scope owns "grid" and Cj's Given mentions "the grid") → mark `DEP(Cj → Ci)`.
84
+ - The dependency map IS the union of those text matches. **Do not add deps "you sense" without a Given citation.**
85
+ - Affected child's INVEST `Independent` becomes `PARTIAL · depends on <Ci>`.
86
+ - Parent epic / flow-summary file lists explicit build order (topological sort of the matrix).
87
+ - If a dep is real but no Given mentions it, rewrite the child's Given to make it explicit, then re-run the match. Intuition-based deps are forbidden.
88
+
89
+ 11. **Per-child V audit (rule C).** After any split-style output, for each candidate child run a one-line test:
90
+ "If only this child ships and no sibling exists, does a real user complete a real task?"
91
+ - If yes → V = PASS.
92
+ - If no, useless until `<other>` ships → V = `WEAK · merge-upstream-candidate`. Recommend merging into the parent surface instead of keeping standalone.
93
+ Do not let stylistic/UI-fragment children survive a split.
94
+
95
+ 12. **Passive-goal downstream prompt (rule G).** If the story's `I want to` verb is observational (`view, see, read, browse, look at, inspect, monitor`) AND the `so that` does not name a follow-up user action — ask once via `AskUserQuestion`: "What does the user do with this?". Strengthen the `so that` accordingly. Skip if `so that` already names a downstream action.
96
+
97
+ ### 4a. Language auto-detect — expanded signals (rule E)
98
+
99
+ Run cheap detection before asking. Multi-signal weighted decision:
100
+
101
+ | Signal | Where to look | Weight |
102
+ |---|---|---|
103
+ | Gherkin keywords in M ("Given/When/Then") | AC block | high |
104
+ | Persona phrasing in M ("As a user" vs "Como un usuario") | Use Case | high |
105
+ | Column / field names in M ("Phone - primary", "Teléfono - principal") | AC bullets | medium |
106
+ | Domain verbs in M ("clicking" vs "hacer clic") | AC bullets | medium |
107
+ | Figma frame names / layer text in M (when source = figma) | design source | medium |
108
+ | Title language | header | low |
109
+
110
+ **Decision:**
111
+ - All high+medium signals agree on language M → adopt M silently. Mark inline `⚠️ Assumed: output language = <M> (auto-detected from <signals>)`.
112
+ - Signals split → ask once via `AskUserQuestion`.
113
+ - User chat = L, story body = M, but high signals tie → prefer M (story body is contract).
114
+
115
+ Persist via rule 9.
116
+
117
+ ### Rule D. Surface vs styling (deterministic)
118
+
119
+ A "named UI surface" counts as a separate outcome (+1 in the pre-split counter) ONLY if it has its own user goal — a verb in the input where the user *does something with that surface* (clicks it, navigates with it, reads it, configures it).
120
+
121
+ If a noun is mentioned only in a styling context (color, padding, alignment, background) or as a sub-component of a parent surface (column inside a grid, label inside a button) → it is NOT a surface. It is styling. Count = 0.
122
+
123
+ Examples:
124
+ - "header row visually distinct (purple)" → styling of grid → 0
125
+ - "pagination control with page numbers" → surface with user goal (navigating) → +1
126
+ - "5 columns: Code, Name, Phone, ..." → sub-components of grid → 0 (grid still counts once)
127
+ - "results counter next to search button" → surface with user goal (reading count) → +1
128
+
129
+ ### Rule F. Naming pattern — ask once, persist
130
+
131
+ When any skill needs to invent a tentative ticket slug AND `.storywright-context.json` has no `naming_pattern` field, ask once via `AskUserQuestion`:
132
+
133
+ ```
134
+ Which naming pattern do you use for tickets?
135
+ - kebab-case feature-action → "customer-search-bar-wire"
136
+ - verb-noun → "wire-search-bar"
137
+ - domain-action → "search.customer.wire-input"
138
+ - Jira prefix + numeric → "CSB-001"
139
+ ```
140
+
141
+ Persist in `naming_pattern`. Use for all sibling slugs in this run AND future skills reading the same context file.
142
+
143
+ ### Deterministic pre-split test (used by all skills)
144
+
145
+ Mechanical counter. Apply the table — do NOT eyeball:
146
+
147
+ | Signal | Hit value |
148
+ |---|---|
149
+ | AC bullet starting with action verb at user level ("clicking", "submitting", "entering", "navigating") | +1 each |
150
+ | Distinct `When [event]` phrasing already implied in the story | +1 each |
151
+ | Distinct named UI surface mentioned at the AC level (rule D applies) | +1 each |
152
+
153
+ **Do NOT count:**
154
+ - sub-bullets describing the same flow
155
+ - styling of an existing surface
156
+ - preconditions or passive "rendered" statements
157
+
158
+ **Decision:**
159
+ - Count ≤1 → proceed with single-story path.
160
+ - Count ≥2 → STOP single-story path. Route to split behavior per the host skill (recommend `/story-split`, produce epic+children, or recurse).
161
+
162
+ ## Canonical output shape (this is the WHOLE story — no exceptions)
163
+
164
+ ```markdown
165
+ ### [Title]
166
+
167
+ #### Use Case
168
+ - **As a** [persona — never just "user"]
169
+ - **I want to** [action]
170
+ - **so that** [outcome with downstream action — rule G]
171
+
172
+ #### Preconditions (optional, only if user provided)
173
+ - ...
174
+
175
+ #### Out of Scope (optional, only if user provided)
176
+ - ...
177
+
178
+ #### Acceptance Criteria
179
+ - **Scenario:** [single-outcome scenario name]
180
+ - **Given:** [context — surface nouns here drive dep matrix per rule 10]
181
+ - **and Given:** [context]
182
+ - **When:** [single trigger]
183
+ - **Then:** [single observable outcome]
184
+
185
+ #### Design Reference (optional)
186
+ **Source: <raster | figma | tokens> → <banner from rule 5>**
187
+ - [link or path]
188
+ - visual notes: [...]
189
+
190
+ #### INVEST
191
+ - I — <PASS | PARTIAL · depends on <Ci>>
192
+ - N/V/E/S/T — one line each, evidence-based.
193
+ - **Verdict:** READY | READY (after <Ci> builds) | SPLIT RECOMMENDED | NEEDS REFINEMENT | NOT A STORY | WEAK·merge-upstream-candidate
194
+
195
+ #### <Generation | Refinement | Split> log (≤3 lines; ≤5 if SPLIT verdict)
196
+ - ...
197
+ ```
198
+
199
+ NOTHING else. No NFR block. No Edge Cases enumeration. No Dependencies prose. No Assumptions block (assumptions get `⚠️ Assumed` inline or are resolved via `AskUserQuestion`).
200
+
201
+ ## Application (step-by-step — every skill follows this skeleton)
202
+
203
+ 0. **Detect companion sources** (image, figma-link, accompanying text). Run conflict detection against the primary input. Run chrome detection using rule 7. Surface conflicts as BLOCKING `AskUserQuestion`.
204
+
205
+ 1. **Read prior context.** Load `<output-folder>/.storywright-context.json` if present (exact folder only). Apply resolved answers; skip the corresponding questions.
206
+
207
+ 2. **Language resolution** via rule 4 + 4a. Auto-detect using the expanded signal table; ask only if signals split. Persist via rule 9.
208
+
209
+ 3. **Persona sharpening.** If persona is "user" / "customer" / "person", ask via `AskUserQuestion` for a specific role. Generic personas hide motivation.
210
+
211
+ 4. **Passive-goal check (rule G).** If `I want to` is observational AND `so that` lacks downstream action → ask once.
212
+
213
+ 5. **Gap-check.** For each weak/missing section:
214
+ - **Blocking** (changes scope, AC outcome, or persona) → `AskUserQuestion` immediately (batched ≤4).
215
+ - **Non-blocking** (additive detail) → fill inline marked `⚠️ Assumed: <text>`. Do not ask.
216
+
217
+ 6. **Sibling reference check.** If unlinked references found → ask once. If user opts for tentative slugs, apply rule F. Persist via rule 9.
218
+
219
+ 7. **Deterministic pre-split test.** Apply the table above mechanically.
220
+ - Count ≤1 → continue to step 8 (single-story path).
221
+ - Count ≥2 → execute the **host skill's split behavior** (see Source-specific differential in each top-level skill).
222
+
223
+ 8. **Fill the canonical block** (Use Case + AC + Design Ref + INVEST). Preserve original wording where it was already good. NEVER invent NFR/edge-case/deps sections.
224
+
225
+ 9. **Run INVEST** via `[[invest-checklist]]`.
226
+ - `READY` → render.
227
+ - `SPLIT RECOMMENDED` → host-skill split behavior + rule 10 matrix + rule 11 V audit.
228
+ - `NEEDS REFINEMENT` → iterate failing dimension, max 1 cycle, then STOP.
229
+ - `NOT A STORY` → tell user it's a tech task and stop.
230
+
231
+ 10. **Render** via `[[jira-wiki-formatter]]`. Files: `story.standard.md` + `story.jira-wiki.md`. Plus `.storywright-context.json`. No other files.
232
+
233
+ 11. **Log** ≤3 bullets (≤5 if SPLIT) appended at story end. Log type label is host-specific (Generation / Refinement / Split).
234
+
235
+ ## What each top-level skill adds on top of this base
236
+
237
+ Only these three things vary:
238
+
239
+ | Skill | Source | Split behavior |
240
+ |---|---|---|
241
+ | `story-generate` | Raw prompt / ambiguous text + optional image/Figma | If pre-split count ≥2 → STOP, recommend `/story-split`. Otherwise draft 1 story. |
242
+ | `story-refine` | Existing story text + optional image/Figma | If pre-split count ≥2 → STOP, recommend `/story-split`. Otherwise fix in place. |
243
+ | `story-split` | Oversize story (any source) | Always produces epic + N children. Mechanical NxN matrix + per-child V audit MANDATORY. Recursive re-split per child if count ≥2. |
244
+ | `story-from-figma` | Figma file/page/frame URL (+ optional companion text) | One story per logical user-goal flow. Multi-flow output → mandatory `flow-summary.md` with mechanical matrix + V audit. Any flow with count ≥2 → hand off to `[[story-split]]`. |
245
+
246
+ Everything else is identical and lives in this base.
247
+
248
+ ## Common Pitfalls (all skills)
249
+
250
+ - Writing any sidecar question file (clarifications.md, questions.md, etc).
251
+ - Skipping rule 1 (terminal-only) "because the user is async".
252
+ - Eyeballing outcome counts instead of running the mechanical table.
253
+ - Renumbering ACs the team may already reference externally.
254
+ - Adding NFR/edge-cases sections "to be thorough".
255
+ - Tagging every visual claim instead of using the single Design Reference banner.
256
+ - Claiming children Independent without running the rule 10 matrix.
257
+ - Letting stylistic/UI-fragment children survive (rule 11 should have flagged them).
258
+ - Asking for a downstream action and then not strengthening the `so that`.
259
+ - Re-asking questions already answered in `.storywright-context.json`.
260
+ - Reading `.storywright-context.json` from a sibling or parent folder.
261
+
262
+ ## References
263
+
264
+ - [[invest-checklist]]
265
+ - [[acceptance-criteria]]
266
+ - [[clarification-questions]]
267
+ - [[jira-wiki-formatter]]
268
+ - [[story-generate]]
269
+ - [[story-refine]]
270
+ - [[story-split]]
271
+ - [[story-from-figma]]
272
+
273
+ <claude-specific>
274
+ - Treat every rule above as load-bearing across all top-level skills.
275
+ - Use extended thinking when applying rule 10 (parse Given lines) and rule 11 (V audit per child).
276
+ - Never call Write for any sidecar question file. Use `AskUserQuestion`.
277
+ - Read `.storywright-context.json` ONLY from the exact target output folder.
278
+ - When you find yourself about to add an NFR / edge-cases / dependencies prose section to a story body, STOP — rule 3 forbids it.
279
+ </claude-specific>
@@ -1,125 +1,146 @@
1
1
  ---
2
2
  name: story-from-figma
3
- description: Generate user stories from a Figma file or frame URL. Uses an MCP Figma server to enumerate frames, components, navigation, and states; falls back to asking for screenshots if MCP is unavailable.
3
+ description: Generate Cohn+Gherkin user stories from a Figma URL. One story per user-goal flow, not per frame. Inherits all hard rules from storywright-base.
4
4
  trigger: "/story-from-figma | story from figma | generate from figma | analizar figma | https://www.figma.com/"
5
- intent: Multimodal entrypoint skill. Inspects a Figma design, infers user flows and screens, and produces one or more stories via story-generate.
6
- version: 1.0.0
5
+ intent: Multimodal entrypoint. Behavior 100% identical to siblings except for source (Figma URL via MCP, with PNG fallback) and split-behavior (one canonical story per logical user-goal flow; flows with count ≥2 routed to /story-split).
6
+ version: 2.3.0
7
7
  inputs:
8
8
  - figma-link
9
9
  outputs:
10
- - story.jira-wiki.md (per generated story)
11
- - story.standard.md (per generated story)
12
- - clarifications.md
10
+ - story-1.standard.md
11
+ - story-1.jira-wiki.md
12
+ - flow-summary.md
13
+ - .storywright-context.json
13
14
  composes:
15
+ - _components/storywright-base
14
16
  - _components/clarification-questions
15
17
  - _components/acceptance-criteria
16
18
  - _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
19
  - _components/jira-wiki-formatter
23
20
  ---
24
21
 
25
22
  ## Purpose
26
23
 
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.
24
+ 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**.
28
25
 
29
- ## When to use
26
+ **All hard rules, canonical output shape, language detection, terminal-only Q, mechanical NxN dep matrix, per-child V audit, context persistence, and INVEST handling live in `[[storywright-base]]`. Read that first. Anything in this file is a SOURCE-SPECIFIC or SPLIT-BEHAVIOR delta only.**
30
27
 
31
- - User pastes a Figma link.
32
- - User says "generate stories from this design".
28
+ ## Source-specific differential
33
29
 
34
- ## Inputs & interpretation
30
+ - **Source:** a Figma file/page/frame URL, accessed via MCP Figma server. Falls back to PNG screenshots if MCP is unavailable.
31
+ - **What changes vs base:**
32
+ - **Design Reference banner is always Figma** (`**Source: Figma → values can be tokenized at implementation.**`) when MCP is used. Switches to the raster banner if user falls back to PNGs.
33
+ - **Persona / Goal inferred from prototype flow + frame text** (rule 4a base signal table includes Figma frame names and layer text as medium-weight signals).
34
+ - **One story per logical user-goal flow**, not per frame. Group frames by prototype-link connectivity to identify flows.
35
+ - **Companion text overrides Figma** for `User Story / Scope / Business Goal` if both are present. Figma is canonical for `Components / States / Flow structure`.
35
36
 
36
- - **figma-link** file URL, page URL, or specific frame URL. Detect the scope:
37
- - File URL → consider the whole file; ask which page or flow to focus on
38
- - Page URL → enumerate frames in that page
39
- - Frame URL → single-screen analysis (usually one story)
37
+ ## Split behavior differential
40
38
 
41
- ## Application (step-by-step)
39
+ This skill may produce **multiple stories in one invocation** (one per flow). When N>1:
40
+ - **MANDATORY: emit `flow-summary.md`** with:
41
+ - Per-story INVEST verdict
42
+ - Mechanical NxN dep matrix (base rule 10) parsed from each story's Given lines
43
+ - Per-story V audit (base rule 11) with merge-upstream flags
44
+ - Topological build order
45
+ - For any single flow whose deterministic pre-split count ≥2 → STOP that flow's draft, route to `[[story-split]]`. Mark the flow as SPLIT RECOMMENDED in `flow-summary.md`. Continue with the other flows.
42
46
 
43
- ### Phase 0 MCP availability check
47
+ If N=1 (single frame URL) standard single-story output. No `flow-summary.md`.
44
48
 
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.
49
+ ## Application (step-by-step)
49
50
 
50
- ### Phase 0.5 Detect companion inputs
51
+ Follow the **base Application** skeleton for the front-end behaviors (context load, language with Figma signal weighting, persona, passive-goal, gap-check, siblings). Figma-specific steps:
51
52
 
52
- Before extracting from Figma, check whether the user attached:
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.
53
+ ### Phase 0 MCP availability + context load
55
54
 
56
- If text + Figma both describe the same flow but disagree (e.g., text says "single page form", Figma shows multi-step wizard), **surface the conflict** in clarifications and ask before drafting. Do NOT silently pick a winner. See `[[story-generate]]` "Mixed inputs" section for source priority.
55
+ 1. Verify MCP Figma server is connected. See `mcp-figma-notes.md`.
56
+ 2. Read prior context per base rule 9.
57
+ 3. If MCP unavailable, ask via `AskUserQuestion` for fallback: (a) install MCP, (b) export PNGs, (c) paste textual flow descriptions. If user picks PNG, set `design_source = raster` in context and use the raster banner.
57
58
 
58
- ### Phase 1 — Inventory
59
+ ### Phase 1 — Inventory (MCP)
59
60
 
60
61
  1. List pages in the file (if MCP allows).
61
- 2. For the target page, list frames with:
62
- - Frame name
63
- - Frame type (entry, modal, error state, empty state, success state, loading, etc.)
64
- - Outgoing prototype links (which other frame each interactive element points to)
65
- 3. Identify the **flows** by grouping frames connected by prototype links. One flow = one candidate story (or epic if large).
62
+ 2. For the target page, list frames with: frame name, frame type (entry/modal/error/empty/success/loading), outgoing prototype links.
63
+ 3. Identify **flows** by grouping frames connected by prototype links. One flow = one candidate story (or epic if pre-split count ≥2).
64
+ 4. Apply base rule D: visual variants of the same flow do NOT count as new flows.
66
65
 
67
66
  ### Phase 2 — Per-flow inference
68
67
 
69
68
  For each flow:
69
+ 1. Identify the user goal, entry point, states (empty/loading/success/error/edge).
70
+ 2. Score confidence per inference (HIGH/MEDIUM/LOW). Below HIGH → `⚠️ Assumed` inline.
71
+ 3. Run base rule G (passive-goal check) on the inferred goal.
72
+ 4. Run base deterministic pre-split counter on the flow.
73
+ - Count ≤1 → draft the base canonical block for this flow.
74
+ - Count ≥2 → mark flow as SPLIT RECOMMENDED; skip drafting.
75
+
76
+ ### Phase 3 — Draft canonical block per flow (count ≤1 flows only)
70
77
 
71
- 1. Identify the **goal** (what user outcome does this flow achieve?).
72
- 2. Identify the **entry point** (where does the user start?).
73
- 3. Enumerate **states**: empty, loading, success, error, edge.
74
- 4. Identify **components** (forms, lists, modals) and their **inputs/outputs**.
75
- 5. Score confidence per inference: HIGH (visible in design), MEDIUM (implied), LOW (assumed). Anything below HIGH gets `> ⚠️ Assumed:` in the output.
76
- 6. Pass the structured inference to `[[story-generate]]` to produce the full story.
78
+ Use the base canonical output shape. Design Reference banner per source-specific differential above.
77
79
 
78
- ### Phase 3Splitting check
80
+ ### Phase 4Multi-flow analysis (N>1)
79
81
 
80
- If a single flow has too many states or branches, run `[[invest-checklist]]` first. If it returns `SPLIT RECOMMENDED`, hand off to `[[story-split]]` before generating.
82
+ 1. **Mechanical NxN matrix (base rule 10).** Parse each story's Given lines.
83
+ 2. **Per-story V audit (base rule 11).** Flag merge-upstream candidates.
84
+ 3. **Coherence check.** Union of stories covers the journey shown in Figma.
81
85
 
82
- ### Phase 4 — Output
86
+ ### Phase 5 — Output
83
87
 
84
- For each story:
85
- - Emit `story.jira-wiki.md` + `story.standard.md` per the formatter.
86
- - Emit a single `flow-summary.md` listing all stories produced and the frames they map to, so reviewers can audit traceability.
88
+ Per drafted flow:
89
+ - `story-<N>.standard.md` + `story-<N>.jira-wiki.md`.
87
90
 
88
- If any inference is LOW confidence, add to `clarifications.md`.
91
+ If N>1 OR any flow was routed to split:
92
+ - `flow-summary.md` with the matrix, V audit, build order, and SPLIT-RECOMMENDED markers.
93
+
94
+ Plus `.storywright-context.json` updated (`extra.figma_url`, `extra.figma_scope`, `extra.mcp_available`).
95
+
96
+ NO `clarifications.md`. NO Edge Cases sections. NO NFR blocks. NO per-claim visual tags.
89
97
 
90
98
  ## Examples
91
99
 
92
100
  ### Good
93
-
94
101
  Input: Figma file URL with 3 flows on the "Auth" page (login, signup, password reset).
95
-
96
102
  Output:
97
- - 3 stories (one per flow).
98
- - Each story references the frames it derived from: `Maps to frames: AUTH-001, AUTH-002, AUTH-003`.
99
- - Account-recovery flow flagged for `[[story-split]]` because it had 12 frames covering multiple recovery methods.
103
+ - 3 canonical stories (one per flow).
104
+ - `flow-summary.md` with mechanical matrix (#2 DEP #1; #3 independent).
105
+ - V audit: all PASS.
106
+ - Recovery flow has 12 frames → pre-split counter ≥2 → marked SPLIT RECOMMENDED; not drafted.
107
+
108
+ ### Good — PNG fallback
109
+ MCP unavailable. User exports 3 PNGs. Skill switches banner to raster, marks `design_source = raster`, generates 3 stories with single raster banner each.
110
+
111
+ ### Good — passive goal fires
112
+ Flow goal inferred as "view dashboard". Base rule G fires. Ask: "What does the user do with the dashboard data?". User: "Spot anomalies and drill in." So-that strengthened.
100
113
 
101
114
  ### Bad
115
+ One story per frame. Frames are screens; stories are user goals.
102
116
 
103
- One story per frame. Frames are screens; stories are user goals. A single goal may span 5 frames.
117
+ ### Bad
118
+ Emitting `clarifications.md` (violates base rule 1).
119
+
120
+ ### Bad
121
+ Skipping the mechanical matrix in `flow-summary.md` when N>1.
104
122
 
105
- ## Common Pitfalls
123
+ ## Common Pitfalls (figma-specific)
106
124
 
107
125
  - Treating each frame as a story.
108
- - Skipping prototype-link analysis — without flow structure, inferred user goals are guesses.
109
- - Ignoring empty/error/loading states. Designers usually include them; PMs often miss them.
110
- - Trusting MEDIUM/LOW inferences silently. Always surface them.
111
- - Generating stories without verifying that the design covers all error paths (often the design only shows the happy path).
126
+ - Skipping prototype-link analysis — without flow structure, user goals are guesses.
127
+ - Ignoring empty/error/loading states. Fold into AC failure paths, not edge-case sections.
128
+ - Trusting MEDIUM/LOW inferences silently mark `⚠️ Assumed`.
129
+ - Skipping per-story V audit when N>1 (figma flows over-split easily).
130
+ - All other pitfalls in `[[storywright-base]]` apply equally.
112
131
 
113
132
  ## References
114
133
 
134
+ - [[storywright-base]] — the rulebook
115
135
  - [[story-generate]]
136
+ - [[story-refine]]
116
137
  - [[story-split]]
117
- - [[clarification-questions]]
118
- - `./mcp-figma-notes.md` (setup of MCP server)
138
+ - `./mcp-figma-notes.md` (MCP server setup)
119
139
 
120
140
  <claude-specific>
121
- - Use Claude's native vision when MCP is unavailable and the user drops PNGs.
141
+ - Read `[[storywright-base]]` before applying. Do not duplicate its rules in your reasoning.
142
+ - Use Claude vision when MCP is unavailable and the user drops PNGs.
122
143
  - Use extended thinking for flow grouping — prototype links can be ambiguous.
123
- - Cache the Phase 2 inference checklist across calls.
124
- - When MCP Figma is available, batch frame metadata fetches into one round trip to minimize tool round-trips.
144
+ - When MCP is available, batch frame metadata fetches into one round trip.
145
+ - Build the multi-story dependency matrix from Given-text parsing (base rule 10), not intuition.
125
146
  </claude-specific>