@pavp/storywright 1.6.0 → 1.6.2
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/_components/jira-wiki-formatter/SKILL.md +2 -0
- package/skills/_components/storywright-base/SKILL.md +277 -0
- package/skills/story-from-figma/SKILL.md +61 -159
- package/skills/story-generate/SKILL.md +40 -207
- package/skills/story-refine/SKILL.md +52 -262
- package/skills/story-split/SKILL.md +68 -203
package/package.json
CHANGED
|
@@ -119,6 +119,8 @@ Permitir a usuarios autenticarse mediante OAuth con Google.
|
|
|
119
119
|
- Forgetting that Jira's `{code}` block doesn't support all languages — fall back to `{noformat}` for plain text.
|
|
120
120
|
- Emoji in Jira: works in cloud, often mangled in older self-hosted. Keep emojis to non-critical decoration.
|
|
121
121
|
- Empty headings. Drop.
|
|
122
|
+
- Wrong heading levels: CommonMark output uses `#` (H1) for title, `##` (H2) for sections. Jira uses `h2.` for title, `h3.` for sections. The canonical block in `[[storywright-base]]` uses `###`/`####` as taxonomy shorthand only — do not copy those levels into the rendered artifact.
|
|
123
|
+
- Emitting INVEST as a section: INVEST is a process step. Its verdict belongs in the log line only (`INVEST Verdict: READY`), never as a standalone section in the output file.
|
|
122
124
|
|
|
123
125
|
## References
|
|
124
126
|
|
|
@@ -0,0 +1,277 @@
|
|
|
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
|
+
> **Note:** This block shows the *section taxonomy and rules* — not heading levels or exact markup. The rendered artifact must follow the `story-generate/templates/` files exactly: `#` for title, `##` for sections (CommonMark) or `h2.`/`h3.` (Jira wiki). INVEST is a **process step** — it informs the Verdict line in the log but is NOT emitted as a section in the output artifact.
|
|
165
|
+
|
|
166
|
+
```markdown
|
|
167
|
+
### [Title]
|
|
168
|
+
|
|
169
|
+
#### Use Case
|
|
170
|
+
- **As a** [persona — never just "user"]
|
|
171
|
+
- **I want to** [action]
|
|
172
|
+
- **so that** [outcome with downstream action — rule G]
|
|
173
|
+
|
|
174
|
+
#### Preconditions (optional, only if user provided)
|
|
175
|
+
- ...
|
|
176
|
+
|
|
177
|
+
#### Out of Scope (optional, only if user provided)
|
|
178
|
+
- ...
|
|
179
|
+
|
|
180
|
+
#### Acceptance Criteria
|
|
181
|
+
- **Scenario:** [single-outcome scenario name]
|
|
182
|
+
- **Given:** [context — surface nouns here drive dep matrix per rule 10]
|
|
183
|
+
- **and Given:** [context]
|
|
184
|
+
- **When:** [single trigger]
|
|
185
|
+
- **Then:** [single observable outcome]
|
|
186
|
+
|
|
187
|
+
#### Design Reference (optional)
|
|
188
|
+
**Source: <raster | figma | tokens> → <banner from rule 5>**
|
|
189
|
+
- [link or path]
|
|
190
|
+
- visual notes: [...]
|
|
191
|
+
|
|
192
|
+
#### <Generation | Refinement | Split> log (≤3 lines; ≤5 if SPLIT verdict)
|
|
193
|
+
- INVEST Verdict: <READY | SPLIT RECOMMENDED | NEEDS REFINEMENT | NOT A STORY>
|
|
194
|
+
- [other changes]
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
NOTHING else. No NFR block. No Edge Cases enumeration. No Dependencies prose. No Assumptions block (assumptions get `⚠️ Assumed` inline or are resolved via `AskUserQuestion`). No standalone INVEST section — verdict belongs in the log only.
|
|
198
|
+
|
|
199
|
+
## Application (step-by-step — every skill follows this skeleton)
|
|
200
|
+
|
|
201
|
+
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`.
|
|
202
|
+
|
|
203
|
+
1. **Read prior context.** Load `<output-folder>/.storywright-context.json` if present (exact folder only). Apply resolved answers; skip the corresponding questions.
|
|
204
|
+
|
|
205
|
+
2. **Language resolution** via rule 4 + 4a. Auto-detect using the expanded signal table; ask only if signals split. Persist via rule 9.
|
|
206
|
+
|
|
207
|
+
3. **Persona sharpening.** If persona is "user" / "customer" / "person", ask via `AskUserQuestion` for a specific role. Generic personas hide motivation.
|
|
208
|
+
|
|
209
|
+
4. **Passive-goal check (rule G).** If `I want to` is observational AND `so that` lacks downstream action → ask once.
|
|
210
|
+
|
|
211
|
+
5. **Gap-check.** For each weak/missing section:
|
|
212
|
+
- **Blocking** (changes scope, AC outcome, or persona) → `AskUserQuestion` immediately (batched ≤4).
|
|
213
|
+
- **Non-blocking** (additive detail) → fill inline marked `⚠️ Assumed: <text>`. Do not ask.
|
|
214
|
+
|
|
215
|
+
6. **Sibling reference check.** If unlinked references found → ask once. If user opts for tentative slugs, apply rule F. Persist via rule 9.
|
|
216
|
+
|
|
217
|
+
7. **Deterministic pre-split test.** Apply the table above mechanically.
|
|
218
|
+
- Count ≤1 → continue to step 8 (single-story path).
|
|
219
|
+
- Count ≥2 → execute the **host skill's split behavior** (see Source-specific differential in each top-level skill).
|
|
220
|
+
|
|
221
|
+
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.
|
|
222
|
+
|
|
223
|
+
9. **Run INVEST** via `[[invest-checklist]]`.
|
|
224
|
+
- `READY` → render.
|
|
225
|
+
- `SPLIT RECOMMENDED` → host-skill split behavior + rule 10 matrix + rule 11 V audit.
|
|
226
|
+
- `NEEDS REFINEMENT` → iterate failing dimension, max 1 cycle, then STOP.
|
|
227
|
+
- `NOT A STORY` → tell user it's a tech task and stop.
|
|
228
|
+
|
|
229
|
+
10. **Render** via `[[jira-wiki-formatter]]`. Files: `story.standard.md` + `story.jira-wiki.md`. Plus `.storywright-context.json`. No other files.
|
|
230
|
+
|
|
231
|
+
11. **Log** ≤3 bullets (≤5 if SPLIT) appended at story end. Log type label is host-specific (Generation / Refinement / Split).
|
|
232
|
+
|
|
233
|
+
## What each top-level skill adds on top of this base
|
|
234
|
+
|
|
235
|
+
Only these three things vary:
|
|
236
|
+
|
|
237
|
+
| Skill | Source | Split behavior |
|
|
238
|
+
|---|---|---|
|
|
239
|
+
| `story-generate` | Raw prompt / ambiguous text + optional image/Figma | If pre-split count ≥2 → STOP, recommend `/story-split`. Otherwise draft 1 story. |
|
|
240
|
+
| `story-refine` | Existing story text + optional image/Figma | If pre-split count ≥2 → STOP, recommend `/story-split`. Otherwise fix in place. |
|
|
241
|
+
| `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. |
|
|
242
|
+
| `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]]`. |
|
|
243
|
+
|
|
244
|
+
Everything else is identical and lives in this base.
|
|
245
|
+
|
|
246
|
+
## Common Pitfalls (all skills)
|
|
247
|
+
|
|
248
|
+
- Writing any sidecar question file (clarifications.md, questions.md, etc).
|
|
249
|
+
- Skipping rule 1 (terminal-only) "because the user is async".
|
|
250
|
+
- Eyeballing outcome counts instead of running the mechanical table.
|
|
251
|
+
- Renumbering ACs the team may already reference externally.
|
|
252
|
+
- Adding NFR/edge-cases sections "to be thorough".
|
|
253
|
+
- Tagging every visual claim instead of using the single Design Reference banner.
|
|
254
|
+
- Claiming children Independent without running the rule 10 matrix.
|
|
255
|
+
- Letting stylistic/UI-fragment children survive (rule 11 should have flagged them).
|
|
256
|
+
- Asking for a downstream action and then not strengthening the `so that`.
|
|
257
|
+
- Re-asking questions already answered in `.storywright-context.json`.
|
|
258
|
+
- Reading `.storywright-context.json` from a sibling or parent folder.
|
|
259
|
+
|
|
260
|
+
## References
|
|
261
|
+
|
|
262
|
+
- [[invest-checklist]]
|
|
263
|
+
- [[acceptance-criteria]]
|
|
264
|
+
- [[clarification-questions]]
|
|
265
|
+
- [[jira-wiki-formatter]]
|
|
266
|
+
- [[story-generate]]
|
|
267
|
+
- [[story-refine]]
|
|
268
|
+
- [[story-split]]
|
|
269
|
+
- [[story-from-figma]]
|
|
270
|
+
|
|
271
|
+
<claude-specific>
|
|
272
|
+
- Treat every rule above as load-bearing across all top-level skills.
|
|
273
|
+
- Use extended thinking when applying rule 10 (parse Given lines) and rule 11 (V audit per child).
|
|
274
|
+
- Never call Write for any sidecar question file. Use `AskUserQuestion`.
|
|
275
|
+
- Read `.storywright-context.json` ONLY from the exact target output folder.
|
|
276
|
+
- When you find yourself about to add an NFR / edge-cases / dependencies prose section to a story body, STOP — rule 3 forbids it.
|
|
277
|
+
</claude-specific>
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: story-from-figma
|
|
3
|
-
description: Generate Cohn+Gherkin user stories from a Figma URL.
|
|
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.
|
|
6
|
-
version: 2.
|
|
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
|
|
11
|
-
- story
|
|
10
|
+
- story-1.standard.md
|
|
11
|
+
- story-1.jira-wiki.md
|
|
12
12
|
- flow-summary.md
|
|
13
13
|
- .storywright-context.json
|
|
14
14
|
composes:
|
|
15
|
+
- _components/storywright-base
|
|
15
16
|
- _components/clarification-questions
|
|
16
17
|
- _components/acceptance-criteria
|
|
17
18
|
- _components/invest-checklist
|
|
@@ -20,172 +21,77 @@ composes:
|
|
|
20
21
|
|
|
21
22
|
## Purpose
|
|
22
23
|
|
|
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**.
|
|
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**.
|
|
24
25
|
|
|
25
|
-
|
|
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.**
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
## Source-specific differential
|
|
28
29
|
|
|
29
|
-
|
|
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`.
|
|
30
36
|
|
|
31
|
-
|
|
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
|
+
## Split behavior differential
|
|
37
38
|
|
|
38
|
-
|
|
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.
|
|
39
46
|
|
|
40
|
-
|
|
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.
|
|
73
|
-
|
|
74
|
-
## When to use
|
|
75
|
-
|
|
76
|
-
- User pastes a Figma link.
|
|
77
|
-
- User says "generate stories from this design".
|
|
78
|
-
|
|
79
|
-
## Inputs & interpretation
|
|
80
|
-
|
|
81
|
-
- **figma-link** — file URL, page URL, or specific frame URL. Detect the scope:
|
|
82
|
-
- File URL → consider the whole file; ask which page or flow to focus on
|
|
83
|
-
- Page URL → enumerate frames in that page
|
|
84
|
-
- Frame URL → single-screen analysis (usually one story)
|
|
47
|
+
If N=1 (single frame URL) → standard single-story output. No `flow-summary.md`.
|
|
85
48
|
|
|
86
49
|
## Application (step-by-step)
|
|
87
50
|
|
|
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:
|
|
52
|
+
|
|
88
53
|
### Phase 0 — MCP availability + context load
|
|
89
54
|
|
|
90
55
|
1. Verify MCP Figma server is connected. See `mcp-figma-notes.md`.
|
|
91
|
-
2.
|
|
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.
|
|
95
|
-
|
|
96
|
-
### Phase 0.5 — Companion inputs + language
|
|
97
|
-
|
|
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`.
|
|
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.
|
|
101
58
|
|
|
102
59
|
### Phase 1 — Inventory (MCP)
|
|
103
60
|
|
|
104
61
|
1. List pages in the file (if MCP allows).
|
|
105
|
-
2. For the target page, list frames with:
|
|
106
|
-
|
|
107
|
-
|
|
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.
|
|
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.
|
|
111
65
|
|
|
112
66
|
### Phase 2 — Per-flow inference
|
|
113
67
|
|
|
114
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.
|
|
115
75
|
|
|
116
|
-
|
|
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]
|
|
133
|
-
|
|
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]
|
|
139
|
-
|
|
140
|
-
#### Design Reference
|
|
141
|
-
**Source: Figma → values can be tokenized at implementation.**
|
|
142
|
-
- <frame URL or frame names>
|
|
143
|
-
|
|
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
|
-
```
|
|
76
|
+
### Phase 3 — Draft canonical block per flow (count ≤1 flows only)
|
|
151
77
|
|
|
152
|
-
|
|
78
|
+
Use the base canonical output shape. Design Reference banner per source-specific differential above.
|
|
153
79
|
|
|
154
|
-
|
|
80
|
+
### Phase 4 — Multi-flow analysis (N>1)
|
|
155
81
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
3. **Coherence check
|
|
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.
|
|
159
85
|
|
|
160
86
|
### Phase 5 — Output
|
|
161
87
|
|
|
162
|
-
|
|
88
|
+
Per drafted flow:
|
|
163
89
|
- `story-<N>.standard.md` + `story-<N>.jira-wiki.md`.
|
|
164
90
|
|
|
165
|
-
|
|
166
|
-
|
|
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 | | | — |
|
|
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.
|
|
182
93
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
**Design source:** Figma (or raster, if PNG fallback).
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Plus `.storywright-context.json` updated.
|
|
94
|
+
Plus `.storywright-context.json` updated (`extra.figma_url`, `extra.figma_scope`, `extra.mcp_available`).
|
|
189
95
|
|
|
190
96
|
NO `clarifications.md`. NO Edge Cases sections. NO NFR blocks. NO per-claim visual tags.
|
|
191
97
|
|
|
@@ -194,51 +100,47 @@ NO `clarifications.md`. NO Edge Cases sections. NO NFR blocks. NO per-claim visu
|
|
|
194
100
|
### Good
|
|
195
101
|
Input: Figma file URL with 3 flows on the "Auth" page (login, signup, password reset).
|
|
196
102
|
Output:
|
|
197
|
-
- 3 canonical stories.
|
|
103
|
+
- 3 canonical stories (one per flow).
|
|
198
104
|
- `flow-summary.md` with mechanical matrix (#2 DEP #1; #3 independent).
|
|
199
105
|
- V audit: all PASS.
|
|
200
|
-
- Recovery flow has 12 frames → pre-split counter ≥2 →
|
|
106
|
+
- Recovery flow has 12 frames → pre-split counter ≥2 → marked SPLIT RECOMMENDED; not drafted.
|
|
201
107
|
|
|
202
108
|
### Good — PNG fallback
|
|
203
|
-
MCP unavailable. User exports 3 PNGs. Skill switches banner to raster, marks `design_source = raster`, generates 3 stories with
|
|
109
|
+
MCP unavailable. User exports 3 PNGs. Skill switches banner to raster, marks `design_source = raster`, generates 3 stories with single raster banner each.
|
|
204
110
|
|
|
205
111
|
### Good — passive goal fires
|
|
206
|
-
Flow goal inferred as "view dashboard".
|
|
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.
|
|
207
113
|
|
|
208
114
|
### Bad
|
|
209
115
|
One story per frame. Frames are screens; stories are user goals.
|
|
210
116
|
|
|
211
117
|
### Bad
|
|
212
|
-
Emitting `clarifications.md
|
|
118
|
+
Emitting `clarifications.md` (violates base rule 1).
|
|
213
119
|
|
|
214
120
|
### Bad
|
|
215
121
|
Skipping the mechanical matrix in `flow-summary.md` when N>1.
|
|
216
122
|
|
|
217
|
-
## Common Pitfalls
|
|
123
|
+
## Common Pitfalls (figma-specific)
|
|
218
124
|
|
|
219
125
|
- Treating each frame as a story.
|
|
220
126
|
- Skipping prototype-link analysis — without flow structure, user goals are guesses.
|
|
221
|
-
- Ignoring empty/error/loading states.
|
|
127
|
+
- Ignoring empty/error/loading states. Fold into AC failure paths, not edge-case sections.
|
|
222
128
|
- Trusting MEDIUM/LOW inferences silently — mark `⚠️ Assumed`.
|
|
223
|
-
-
|
|
224
|
-
-
|
|
225
|
-
- Re-asking questions already in `.storywright-context.json`.
|
|
226
|
-
- Tagging every visual claim instead of using the single Figma banner.
|
|
129
|
+
- Skipping per-story V audit when N>1 (figma flows over-split easily).
|
|
130
|
+
- All other pitfalls in `[[storywright-base]]` apply equally.
|
|
227
131
|
|
|
228
132
|
## References
|
|
229
133
|
|
|
134
|
+
- [[storywright-base]] — the rulebook
|
|
230
135
|
- [[story-generate]]
|
|
231
|
-
- [[story-split]]
|
|
232
136
|
- [[story-refine]]
|
|
233
|
-
- [[
|
|
137
|
+
- [[story-split]]
|
|
234
138
|
- `./mcp-figma-notes.md` (MCP server setup)
|
|
235
139
|
|
|
236
140
|
<claude-specific>
|
|
141
|
+
- Read `[[storywright-base]]` before applying. Do not duplicate its rules in your reasoning.
|
|
237
142
|
- Use Claude vision when MCP is unavailable and the user drops PNGs.
|
|
238
143
|
- Use extended thinking for flow grouping — prototype links can be ambiguous.
|
|
239
|
-
-
|
|
240
|
-
-
|
|
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`.
|
|
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.
|
|
244
146
|
</claude-specific>
|