@pavp/storywright 1.3.0 → 1.5.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.
@@ -1,6 +1,6 @@
1
1
  ---
2
- description: Audit an existing user story and fill gaps in place
3
- argument-hint: <paste existing story>
2
+ description: Audit an existing user story and fill gaps in place (supports text + optional image / Figma companion)
3
+ argument-hint: <paste existing story> [+ attach image or paste Figma URL for cross-source check]
4
4
  ---
5
5
 
6
6
  Invoke the `story-refine` skill from the storywright pack to audit and improve this story:
@@ -9,6 +9,7 @@ $ARGUMENTS
9
9
 
10
10
  Follow the skill's procedure:
11
11
 
12
+ 0. Detect companion sources (image, figma-link). If present, run conflict detection between the story text and the design BEFORE filling sections. Surface conflicts as BLOCKING clarifications; never silently rewrite the story to match the design.
12
13
  1. Parse the existing story into the section taxonomy. Mark each section: present / missing / weak.
13
14
  2. Gap-check weak sections via `clarification-questions`. Ask only BLOCKING questions.
14
15
  3. Detect language and preserve it in output.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Split an oversize story into an epic + child stories using INVEST + Humanizing Work patterns
3
- argument-hint: <paste oversize story>
3
+ argument-hint: <paste oversize story> [+ optional image / Figma URL for flow inventory]
4
4
  ---
5
5
 
6
6
  Invoke the `story-split` skill from the storywright pack to split this story:
@@ -9,6 +9,7 @@ $ARGUMENTS
9
9
 
10
10
  Follow the skill's procedure:
11
11
 
12
+ 0. Detect companion sources (image, figma-link). If present, use them to inventory candidate sub-flows (prototype links, frame structure). If Figma shows N flows but text mentions K (K < N), surface as BLOCKING clarification before drafting the split plan. Text is canonical for scope of the epic; design is canonical for flow structure.
12
13
  1. Run `invest-checklist` and apply the pre-split gates:
13
14
  - If Valuable FAILS → NOT A STORY. Don't split. Stop.
14
15
  - If Testable / Negotiable FAILS → fix in place, don't split. Stop.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pavp/storywright",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
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",
@@ -44,13 +44,16 @@ For each dimension, mark PASS / FAIL and write one sentence of evidence.
44
44
  FAIL if unknowns dominate (spike-shaped) or the surface is too broad.
45
45
 
46
46
  5. **S — Small**
47
- PASS if it fits one sprint and one developer-week is plausible.
48
- FAIL if it visibly mixes ≥2 distinct flows or touches ≥3 unrelated surfaces.
47
+ PASS if it fits one sprint AND has exactly one Gherkin `When`/`Then` pair AND touches ≤2 related surfaces.
48
+ FAIL if it visibly mixes ≥2 distinct flows, OR has >1 `When`/`Then` pair (multi-outcome = scope creep, Cohn anti-pattern), OR touches ≥3 unrelated surfaces.
49
49
 
50
50
  6. **T — Testable**
51
51
  PASS if every AC has an observable outcome.
52
52
  FAIL if ACs hand-wave behavior or rely on subjective judgment.
53
53
 
54
+ 7. **Anti-PRD sanity (storywright-specific)**
55
+ If the rendered story body exceeds ~60 lines excluding user-supplied Preconditions/Out-of-Scope blocks, treat as a spec, not a story. FAIL `Small`. Force `SPLIT RECOMMENDED`.
56
+
54
57
  7. Emit the report block:
55
58
  ```
56
59
  ### INVEST Check
@@ -1,102 +1,312 @@
1
1
  ---
2
2
  name: story-refine
3
- description: Audit an existing user story for gaps and fill them in place. Surfaces missing AC, DoD, edge cases, risks; asks clarifications only for blocking unknowns. Returns dual-format refined story.
3
+ description: Audit an existing user story and fix it in place. Cohn+Gherkin canonical output. Asks clarifications ONLY in terminal. Recommends split when story has multiple outcomes.
4
4
  trigger: "/story-refine | refine this story | improve this story | refinar historia | this story is incomplete"
5
- intent: Refinement skill for stories that already exist but are incomplete or weakly specified. Composes the same component skills as story-generate but skips the drafting step.
6
- version: 1.0.0
5
+ intent: Refinement skill for stories that already exist but are incomplete or weakly specified. Default philosophy = Mike Cohn (story is a conversation starter, not a spec). Splits aggressively. Never produces mini-PRDs.
6
+ version: 2.2.0
7
7
  inputs:
8
8
  - text
9
+ - image
10
+ - figma-link
9
11
  outputs:
10
- - story.jira-wiki.md
11
12
  - story.standard.md
12
- - clarifications.md
13
+ - story.jira-wiki.md
14
+ - .storywright-context.json
13
15
  composes:
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
- When the PM already has a story written but it's missing sections, has hand-wavy ACs, or never went through INVEST, this skill brings it up to standard without rewriting it from scratch.
24
+ Bring an existing user story up to standard *without* turning it into a feature spec. Output is conversation-ready, Cohn-format, Gherkin AC. If the story is too big, recommend split do not refine an oversized story into a longer one.
25
+
26
+ ## Hard rules (no exceptions)
27
+
28
+ 1. **Terminal-only clarifications.** Never write any sidecar question file. All gap questions go through `AskUserQuestion` (batch in groups of ≤4). If a gap is non-blocking, mark `⚠️ Assumed` inline in the story body — do not ask.
29
+
30
+ 2. **Cohn + Gherkin canonical.** One Use Case block. One AC scenario per story (one Given chain, one `When`, one `Then`). If the story naturally needs >1 `When`/`Then` → **STOP refining, recommend `/story-split`**.
31
+
32
+ 3. **No mini-PRDs.** The following sections are PROHIBITED in story output (they belong to DoD, design handoff, or sibling tickets):
33
+ - Non-Functional Requirements blocks (a11y/i18n/perf/tokens) — these live in the team's global Definition of Done
34
+ - Edge Cases enumerations — sibling stories or DoD
35
+ - Dependencies as prose — use Jira ticket links instead
36
+ - Visual specs derived from raster mockups (pixel measurements, hex inferences) inline with each claim
37
+ - Refinement logs >3 lines (>5 if verdict is SPLIT RECOMMENDED)
38
+
39
+ 4. **Output language matches the user's chat language**, not the story's. Auto-detect first (see rule 4a); only ask via `AskUserQuestion` if detection is ambiguous.
40
+
41
+ 5. **Visual inference confidence — single banner only.** Do NOT tag every visual claim. Instead, add ONE banner at the top of the Design Reference block declaring the source type. All claims under that block inherit the banner's confidence level.
42
+ - Raster source (PNG/JPG) → banner: `**Source: raster mockup → all visual specs are pixel-derived, not token-confirmed.**`
43
+ - Figma source → banner: `**Source: Figma → values can be tokenized at implementation.**`
44
+ - Design-token source → banner: `**Source: design tokens → values are authoritative.**`
45
+ - Never assert hex values, pixel sizes, or exact spacing from raster without the raster banner.
46
+
47
+ 6. **Sibling task IDs.** If story body references "next task", "future task", "another story", "siblings" — check `<output-folder>/.storywright-context.json` first (rule 9). If unresolved, ask via `AskUserQuestion`. If user has none yet, leave a `TODO: link sibling` placeholder, do not invent (unless rule F applies — see below).
48
+
49
+ 7. **Mockup chrome detection — closed list.** Chrome = exactly these elements:
50
+ - left nav rail / sidebar
51
+ - top bar (user menu, global breadcrumbs, global search)
52
+ - footer
53
+ - persistent toast/snackbar slot
54
+ - persistent modal scrim
55
+ - app-level tabs
56
+
57
+ If companion image shows any of the above and the story body does not mention them, ask via `AskUserQuestion` whether each one 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.
58
+
59
+ 8. **Anti-PRD is part of INVEST `Small`, not a separate step.** See `[[invest-checklist]]` step 7 — line count ceiling lives inside the `Small` criterion so there is one source of truth.
60
+
61
+ 9. **Cross-skill context persistence.** When the skill resolves any clarification via `AskUserQuestion`, write the **answers** to `<output-folder>/.storywright-context.json`. This is NOT a question file — it is a resolved-answers file. Read only from the exact output folder of the current invocation; never search siblings or parents. Schema:
62
+ ```json
63
+ {
64
+ "version": 1,
65
+ "decided_at": "<ISO date>",
66
+ "decided_by_skill": "story-refine",
67
+ "language": "EN | ES | ...",
68
+ "chrome_scope": "in-scope | in-scope-placeholder | sibling | out-of-scope",
69
+ "siblings": "TODO | <list of IDs> | not-applicable",
70
+ "design_source": "raster | figma | tokens",
71
+ "naming_pattern": "<see rule F>",
72
+ "extra": {}
73
+ }
74
+ ```
75
+ Future skills (`story-split`, `story-from-figma`, etc.) MUST read this file before re-asking the same questions.
76
+
77
+ 10. **Children independence — mechanical detection (A).** When the skill recommends or executes split, build an NxN dependency matrix MECHANICALLY, not by intuition:
78
+ - For each child Cj, parse its `Given:` and `and Given:` lines.
79
+ - If any `Given` text contains a surface noun owned by child Ci (e.g., Cj's Given mentions "the grid" and Ci's title/scope owns "grid") → mark `DEP(Cj → Ci)`.
80
+ - The dependency map IS the union of those text matches. Do not add deps "you sense" without a Given citation.
81
+ - Affected child's INVEST `Independent` becomes `PARTIAL · depends on <Ci>`; parent EPIC lists explicit build order derived from the matrix (topological).
82
+ - Independence-by-intuition is forbidden. If a dep is real but no Given mentions it, rewrite the child's Given to make it explicit, then re-run the match.
83
+
84
+ 11. **Per-child V audit (C).** After split, for each candidate child run a one-line V test: "If only this child ships and no sibling exists, does a real user complete a real task?". If the answer is "no, useless until <other child> ships" → mark V as `WEAK · merge-upstream-candidate` and recommend merging that child into its parent surface instead of keeping it standalone. Do not let stylistic/UI-fragment children survive the split.
85
+
86
+ 12. **Passive-goal downstream prompt (G).** If the story's `I want to` verb is passive/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 data?". Use the answer to strengthen the `so that` clause. This forces explicit value. Skip the prompt if `so that` already names a downstream action (e.g., "so that I can call the customer").
87
+
88
+ ### 4a. Language auto-detect — expanded signals (E)
89
+
90
+ Run cheap detection before asking. Look at multiple signals, not just Gherkin keywords:
91
+
92
+ | Signal | Where to look | Weight |
93
+ |---|---|---|
94
+ | Gherkin keywords in M ("Given/When/Then") | AC block | high |
95
+ | Persona phrasing in M ("As a user" vs "Como un usuario") | Use Case | high |
96
+ | Column / field names in M ("Phone - primary", "Teléfono - principal") | AC bullets | medium |
97
+ | Domain verbs in M ("clicking" vs "hacer clic", "submitting" vs "enviar") | AC bullets | medium |
98
+ | Title language | header | low |
99
+
100
+ **Decision:**
101
+ - All high+medium signals agree on language M → adopt M silently. No question. Mark inline `⚠️ Assumed: output language = <M> (auto-detected from <signals>)`.
102
+ - Signals split (some EN, some ES) → ask once via `AskUserQuestion`.
103
+ - User-chat language = L, story-body signals = M, but high signals tie → prefer M (story body is contract).
104
+
105
+ Persist via rule 9.
106
+
107
+ ### Rule F. Naming pattern — ask once, persist
108
+
109
+ When the skill needs to invent a tentative ticket slug (e.g., for sibling references with no IDs yet) AND `.storywright-context.json` has no `naming_pattern` field, ask once via `AskUserQuestion`:
110
+
111
+ ```
112
+ Which naming pattern do you use for tickets?
113
+ - kebab-case feature-action → "customer-search-bar-wire"
114
+ - verb-noun → "wire-search-bar"
115
+ - domain-action → "search.customer.wire-input"
116
+ - Jira prefix + numeric → "CSB-001" (assume next available)
117
+ ```
118
+
119
+ Persist the answer in `.storywright-context.json` under `naming_pattern`. Use it for all sibling slugs in the current run AND future skills reading the same context file.
28
120
 
29
121
  ## When to use
30
122
 
31
123
  - User pastes an existing story (text) and asks to make it Jira-ready.
32
- - A story has ACs but no DoD, or vice versa.
124
+ - A story has ACs but no testable outcomes.
33
125
  - INVEST gate fails on `Testable` or `Negotiable` — fixable in place (not splittable).
34
126
 
35
- For oversized stories that fail `Independent / Estimable / Small`, hand off to `[[story-split]]` instead.
127
+ For oversized stories that fail `Independent / Estimable / Small`, OR have multiple `When`/`Then` pairs, OR have >1 distinct outcome (per the deterministic counter below) → hand off to `[[story-split]]` instead.
36
128
 
37
129
  ## Inputs & interpretation
38
130
 
39
131
  - **text** — existing story. Detect which sections are present, which are missing, which are weak.
132
+ - **image (optional)** — companion screenshot/mockup. Use to validate UI claims only. NEVER as source for pixel-precise visual specs inline with each AC claim (see rule 5).
133
+ - **figma-link (optional)** — companion design. Use to enrich AC observable outcomes (states, named components).
134
+
135
+ ### Mixed inputs source-priority
136
+
137
+ - Story text canonical for `User Story / Scope / Business value`.
138
+ - Image/Figma canonical for `component names / observable states` referenced inside AC.
139
+ - Conflicts → BLOCKING `AskUserQuestion`. Never silently rewrite the story to match the design.
140
+
141
+ ## Canonical output shape (this is the WHOLE story)
142
+
143
+ ```markdown
144
+ ### [Title]
145
+
146
+ #### Use Case
147
+ - **As a** [persona]
148
+ - **I want to** [action]
149
+ - **so that** [outcome with downstream action — see rule G]
150
+
151
+ #### Preconditions (optional, only if user provided)
152
+ - ...
153
+
154
+ #### Out of Scope (optional, only if user provided)
155
+ - ...
156
+
157
+ #### Acceptance Criteria
158
+ - **Scenario:** [single-outcome scenario name]
159
+ - **Given:** [context — surface nouns here drive dep matrix per rule A]
160
+ - **and Given:** [context]
161
+ - **When:** [single trigger]
162
+ - **Then:** [single observable outcome]
163
+
164
+ #### Design Reference (optional)
165
+ **Source: <raster | figma | tokens> → <inherited-confidence banner from rule 5>**
166
+ - [link or path]
167
+ - visual notes: [...]
168
+
169
+ #### INVEST
170
+ - I/N/V/E/S/T — one line each, evidence-based.
171
+ - **Verdict:** READY | SPLIT RECOMMENDED | NEEDS REFINEMENT | NOT A STORY
172
+
173
+ #### Refinement log (≤3 lines; ≤5 if verdict=SPLIT)
174
+ - ...
175
+ ```
176
+
177
+ Nothing else. No NFR block. No Edge Cases enumeration. No Dependencies prose. No Assumptions block (assumptions get `⚠️ Assumed` inline or are resolved via `AskUserQuestion`).
40
178
 
41
179
  ## Application (step-by-step)
42
180
 
43
- 1. **Parse the existing story.** Map content into the 15-section taxonomy. Note: present / missing / weak.
44
- 2. **Gap-check the weak sections** via `[[clarification-questions]]`. If gaps are inferrable, mark `⚠️ Assumed` and proceed. Only ask BLOCKING questions.
45
- 3. **Detect language** of the existing story; preserve it in the output.
46
- 4. **Fill missing/weak sections** in dependency order:
47
- - Reglas de negocio `[[business-rules]]`
48
- - Consideraciones técnicas → inline
49
- - Edge cases `[[edge-cases]]`
50
- - Criterios de aceptación → `[[acceptance-criteria]]`
51
- - Analytics → `[[analytics-events]]`
52
- - Riesgos + dependencias → `[[risks-and-dependencies]]`
53
- - DoD `[[definition-of-done]]`
54
- 5. **Preserve original wording** where it was already good. Mark changed sections with a comment trail at the end of the story:
55
- ```
56
- ---
57
- Refinement log:
58
- - Added Edge Cases (8 cases)
59
- - Strengthened AC-2 (was untestable: "should work properly")
60
- - Added analytics block
61
- ```
62
- 6. **Run INVEST** via `[[invest-checklist]]`.
63
- - `READY` → render outputs.
64
- - `NEEDS REFINEMENT` iterate on the failing dimension.
65
- - `SPLIT RECOMMENDED` STOP. Tell the user the story should go through `[[story-split]]` instead.
66
- 7. **Render** both outputs via `[[jira-wiki-formatter]]`.
67
- 8. **Emit `clarifications.md`** if assumptions remain unresolved.
181
+ 0. **Detect companion sources** (image, figma-link). Run conflict detection against story text. Run chrome-detection using the closed list in rule 7. Surface conflicts as BLOCKING `AskUserQuestion` calls.
182
+
183
+ 1. **Parse story** into the canonical sections above. Note: present / missing / weak.
184
+
185
+ 2. **Read prior context.** If `<output-folder>/.storywright-context.json` exists (exact folder only — no sibling fallback), load it. Apply resolved answers; skip the corresponding questions.
186
+
187
+ 3. **Language resolution (rule 4 + 4a).** Auto-detect using the expanded signal table. Ask only if signals split. Persist via rule 9.
188
+
189
+ 4. **Passive-goal check (rule G).** If `I want to` verb is observational AND `so that` lacks downstream action ask once. Persist resolution into the strengthened `so that` clause.
190
+
191
+ 5. **Gap-check.** For each weak/missing section:
192
+ - **Blocking** (changes scope, AC outcome, or persona) `AskUserQuestion` immediately (batched ≤4).
193
+ - **Non-blocking** (additive detail) → fill inline marked `⚠️ Assumed: <text>`. Do not ask.
194
+
195
+ 6. **Sibling reference check (rule 6).** If found and unlinked → ask via `AskUserQuestion` once. If user opts for tentative slugs, apply rule F (naming pattern). Persist via rule 9.
196
+
197
+ 7. **Deterministic pre-split test.** Apply this counter mechanically — do not eyeball:
198
+
199
+ **Count = sum of all hits below:**
200
+ | Signal | Hit value |
201
+ |---|---|
202
+ | AC bullet starting with an action verb at the user level ("clicking", "submitting", "entering", "navigating") | +1 each |
203
+ | Distinct `When [event]` phrasing already implied in the story | +1 each |
204
+ | Distinct named UI surface mentioned at the AC level — see (D) below for what counts | +1 each |
205
+
206
+ **(D) Surface vs styling rule (deterministic).** A "named UI surface" counts as +1 ONLY if it has its own user goal — meaning there is a verb in the story body where the user *does something with that surface* (clicks it, navigates with it, reads it, configures it). If a noun is mentioned only in a styling context (color, background, padding, alignment) 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.
207
+
208
+ Examples:
209
+ - "header row visually distinct (purple background)" — styling of grid → 0
210
+ - "pagination control with page numbers and arrows" — surface with user goal (navigating) → +1
211
+ - "5 columns: Code, Customer name, Phone, Email, Address" — columns are sub-components of grid → 0 (grid still counts once)
212
+ - "results counter next to search button" — surface with user goal (reading count) → +1
213
+
214
+ **Do NOT count:**
215
+ - sub-bullets describing the same flow (column names inside one grid = the grid itself, not separate outcomes)
216
+ - styling of an existing surface (header purple = part of grid, not a new outcome)
217
+ - preconditions or "rendered" statements (passive layout assertions are not Whens)
218
+
219
+ **Decision:**
220
+ - Count ≤1 → continue to step 8.
221
+ - Count ≥2 → **STOP. Recommend `/story-split` via terminal message.** Output: list of candidate children + per-pair dependency note (rule 10) + V audit per child (rule 11).
222
+
223
+ 8. **Fill the weak sections** using `[[acceptance-criteria]]` (single Gherkin block) and `[[invest-checklist]]`. Preserve original wording where it was already good.
224
+
225
+ 9. **Run INVEST** via `[[invest-checklist]]` (which embeds the anti-PRD line-count check inside `Small` — rule 8).
226
+ - `READY` → render.
227
+ - `SPLIT RECOMMENDED` → STOP, recommend split (and run rule 10 children-independence matrix + rule 11 V audit per child).
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** both outputs via `[[jira-wiki-formatter]]`. Files: `story.standard.md` + `story.jira-wiki.md`. Plus `.storywright-context.json`. No other files.
232
+
233
+ 11. **Refinement log** ≤3 bullets (≤5 if SPLIT) appended at story end.
68
234
 
69
235
  ## Examples
70
236
 
71
- ### Good
237
+ ### Good — READY
238
+ Input: story with title + Use Case + 2 vague ACs.
239
+ Output: canonical block, ≤30 lines, AC tightened to single Given/When/Then, INVEST verdict READY, ≤3-line refinement log, `.storywright-context.json` written.
72
240
 
73
- Input: a story with title + User Story + 2 vague ACs ("It should be fast", "User can log in").
241
+ ### Good SPLIT (Spanish)
242
+ Input: historia con 7 bullets de AC (grilla + contador + paginación + link).
243
+ Output: NO refined story. Mensaje terminal:
244
+ ```
245
+ SPLIT RECOMMENDED. Conteo determinístico = 4 (grilla, contador, paginación, link).
246
+ Children candidatos:
247
+ 1. Page shell + chrome (si in-scope)
248
+ 2. Grid 5 columnas + header style
249
+ 3. Contador de resultados
250
+ 4. Control de paginación
251
+ 5. Link affordance en customer name
252
+ Matriz independencia (parse mecánico de Given):
253
+ - C4.Given menciona "the grid" → DEP(C4 → C2) → PARTIAL
254
+ - C5.Given menciona "the grid" → DEP(C5 → C2) → PARTIAL
255
+ - Orden build: C1 → C2 → {C3, C4, C5}
256
+ V audit per child:
257
+ - C1: PASS (chrome funcional = workspace context)
258
+ - C2: PASS (read records)
259
+ - C3: WEAK · merge-upstream-candidate — counter sin grid no entrega valor
260
+ - C4: PASS (navigate pages)
261
+ - C5: PASS (link affordance)
262
+ Corré /story-split para expandir; considera mergear C3 en C2.
263
+ ```
74
264
 
75
- Output:
76
- - Original title/user story preserved.
77
- - AC-1 rewritten to Given/When/Then with observable outcomes.
78
- - AC-2 split into AC-2 (happy path) and AC-3 (failure path).
79
- - Added Edge Cases section (5 cases).
80
- - Added DoD section.
81
- - Refinement log appended.
265
+ ### Good — passive-goal prompt fires
266
+ Input: "As a user, I want to view list of customers, so that I quickly find details."
267
+ Skill detects passive verb `view` + thin `so that`.
268
+ Asks: "What does the user do with the customer they find?"
269
+ User: "Call them to schedule a service."
270
+ Refined `so that`: "so that I can quickly find a customer and call them to schedule a service."
82
271
 
83
272
  ### Bad
273
+ Adding NFR / a11y / i18n / Dependencies sections "to be thorough". Violates rule 3.
84
274
 
85
- Rewriting the whole story when only 2 sections were weak. Preserve good content.
275
+ ### Bad
276
+ Writing any sidecar question file instead of asking via `AskUserQuestion`. Violates rule 1.
277
+
278
+ ### Bad
279
+ Tagging every visual claim with `[mockup-pixel-derived]` instead of using the single banner. Violates rule 5.
280
+
281
+ ### Bad
282
+ Claiming 5 children all `Independent` after split without running the mechanical matrix from rule 10.
283
+
284
+ ### Bad
285
+ Counting "header row purple" as +1 in the pre-split test. It is styling of the grid (rule D), not a separate surface. Should be 0.
86
286
 
87
287
  ## Common Pitfalls
88
288
 
89
289
  - Treating refine like generate. If the PM already wrote the user goal, don't restate it.
90
- - Renumbering ACs the team may already reference externally. Append new ACs at the end.
91
- - Skipping the refinement log. Reviewers need to see what changed.
290
+ - Renumbering ACs append new content, don't shuffle.
291
+ - Skipping the deterministic pre-split test (step 7). Refining oversized stories produces oversized refined stories.
292
+ - Eyeballing outcome counts or dep matrix instead of running the mechanical rules (D, A).
293
+ - Re-asking questions already answered in `.storywright-context.json`.
294
+ - Letting weak-V children survive the split (rule 11).
295
+ - Skipping the downstream-action prompt for passive goals (rule G).
92
296
 
93
297
  ## References
94
298
 
95
299
  - [[story-generate]]
96
300
  - [[story-split]]
97
301
  - [[invest-checklist]]
302
+ - [[acceptance-criteria]]
98
303
 
99
304
  <claude-specific>
100
305
  - Diff the original sections against the refined ones in your reasoning; only emit changes that materially improve the story.
101
- - Cache the 15-section taxonomy.
306
+ - Never call Write for any question/clarification sidecar file. Use `AskUserQuestion`.
307
+ - Treat step 7 (deterministic pre-split test) as a hard gate; do not skip even when the user explicitly asks to refine.
308
+ - Read `.storywright-context.json` ONLY from the exact target output folder. Do not search siblings or parents.
309
+ - After split, build the dependency matrix from Given-text parsing (rule 10), not intuition.
310
+ - After split, run V audit per child (rule 11) and flag merge-upstream-candidates loudly.
311
+ - For passive `I want to` verbs, fire rule G prompt before INVEST.
102
312
  </claude-specific>
@@ -6,6 +6,8 @@ intent: Splitting skill that uses the INVEST failure reasons (from invest-checkl
6
6
  version: 1.0.0
7
7
  inputs:
8
8
  - text
9
+ - image
10
+ - figma-link
9
11
  outputs:
10
12
  - split-plan.md
11
13
  - epic.md
@@ -28,6 +30,16 @@ When a story is an epic in disguise, splitting badly is worse than not splitting
28
30
  ## Inputs & interpretation
29
31
 
30
32
  - **text** — the oversize story (or a one-line goal that's clearly epic-scoped).
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.
35
+
36
+ ### Mixed inputs
37
+
38
+ When the user provides text + image / Figma alongside the story:
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.
31
43
 
32
44
  ## Application (step-by-step)
33
45