@sun-asterisk/sungen 2.4.5 → 2.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.
Files changed (201) hide show
  1. package/dist/cli/commands/delivery.d.ts +7 -0
  2. package/dist/cli/commands/delivery.d.ts.map +1 -0
  3. package/dist/cli/commands/delivery.js +348 -0
  4. package/dist/cli/commands/delivery.js.map +1 -0
  5. package/dist/cli/commands/generate.d.ts.map +1 -1
  6. package/dist/cli/commands/generate.js +2 -0
  7. package/dist/cli/commands/generate.js.map +1 -1
  8. package/dist/cli/commands/update.d.ts.map +1 -1
  9. package/dist/cli/commands/update.js +64 -1
  10. package/dist/cli/commands/update.js.map +1 -1
  11. package/dist/cli/index.js +4 -2
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/exporters/csv-exporter.d.ts +32 -0
  14. package/dist/exporters/csv-exporter.d.ts.map +1 -0
  15. package/dist/exporters/csv-exporter.js +311 -0
  16. package/dist/exporters/csv-exporter.js.map +1 -0
  17. package/dist/exporters/feature-parser.d.ts +48 -0
  18. package/dist/exporters/feature-parser.d.ts.map +1 -0
  19. package/dist/exporters/feature-parser.js +178 -0
  20. package/dist/exporters/feature-parser.js.map +1 -0
  21. package/dist/exporters/package-info.d.ts +9 -0
  22. package/dist/exporters/package-info.d.ts.map +1 -0
  23. package/dist/exporters/package-info.js +73 -0
  24. package/dist/exporters/package-info.js.map +1 -0
  25. package/dist/exporters/playwright-report-parser.d.ts +21 -0
  26. package/dist/exporters/playwright-report-parser.d.ts.map +1 -0
  27. package/dist/exporters/playwright-report-parser.js +184 -0
  28. package/dist/exporters/playwright-report-parser.js.map +1 -0
  29. package/dist/exporters/scenario-merger.d.ts +21 -0
  30. package/dist/exporters/scenario-merger.d.ts.map +1 -0
  31. package/dist/exporters/scenario-merger.js +51 -0
  32. package/dist/exporters/scenario-merger.js.map +1 -0
  33. package/dist/exporters/spec-parser.d.ts +20 -0
  34. package/dist/exporters/spec-parser.d.ts.map +1 -0
  35. package/dist/exporters/spec-parser.js +259 -0
  36. package/dist/exporters/spec-parser.js.map +1 -0
  37. package/dist/exporters/step-formatter.d.ts +32 -0
  38. package/dist/exporters/step-formatter.d.ts.map +1 -0
  39. package/dist/exporters/step-formatter.js +76 -0
  40. package/dist/exporters/step-formatter.js.map +1 -0
  41. package/dist/exporters/test-data-resolver.d.ts +20 -0
  42. package/dist/exporters/test-data-resolver.d.ts.map +1 -0
  43. package/dist/exporters/test-data-resolver.js +96 -0
  44. package/dist/exporters/test-data-resolver.js.map +1 -0
  45. package/dist/exporters/types.d.ts +104 -0
  46. package/dist/exporters/types.d.ts.map +1 -0
  47. package/dist/exporters/types.js +6 -0
  48. package/dist/exporters/types.js.map +1 -0
  49. package/dist/exporters/xlsx-exporter.d.ts +19 -0
  50. package/dist/exporters/xlsx-exporter.d.ts.map +1 -0
  51. package/dist/exporters/xlsx-exporter.js +309 -0
  52. package/dist/exporters/xlsx-exporter.js.map +1 -0
  53. package/dist/generators/gherkin-parser/index.d.ts +1 -0
  54. package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
  55. package/dist/generators/gherkin-parser/index.js +3 -0
  56. package/dist/generators/gherkin-parser/index.js.map +1 -1
  57. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +29 -1
  58. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  59. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +21 -1
  60. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -1
  61. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js +11 -2
  62. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -1
  63. package/dist/generators/test-generator/adapters/playwright/templates/after-all.hbs +8 -0
  64. package/dist/generators/test-generator/adapters/playwright/templates/after-each.hbs +8 -0
  65. package/dist/generators/test-generator/adapters/playwright/templates/before-all.hbs +8 -0
  66. package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  67. package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +24 -0
  68. package/dist/generators/test-generator/code-generator.d.ts +2 -0
  69. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  70. package/dist/generators/test-generator/code-generator.js +109 -12
  71. package/dist/generators/test-generator/code-generator.js.map +1 -1
  72. package/dist/generators/test-generator/step-mapper.d.ts +1 -0
  73. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  74. package/dist/generators/test-generator/step-mapper.js +1 -1
  75. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  76. package/dist/generators/test-generator/template-engine.d.ts +29 -1
  77. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  78. package/dist/generators/test-generator/template-engine.js +11 -2
  79. package/dist/generators/test-generator/template-engine.js.map +1 -1
  80. package/dist/generators/test-generator/utils/data-resolver.d.ts +11 -2
  81. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
  82. package/dist/generators/test-generator/utils/data-resolver.js +36 -25
  83. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
  84. package/dist/generators/test-generator/utils/runtime-data-transformer.d.ts +7 -0
  85. package/dist/generators/test-generator/utils/runtime-data-transformer.d.ts.map +1 -0
  86. package/dist/generators/test-generator/utils/runtime-data-transformer.js +42 -0
  87. package/dist/generators/test-generator/utils/runtime-data-transformer.js.map +1 -0
  88. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  89. package/dist/generators/test-generator/utils/selector-resolver.js +26 -0
  90. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  91. package/dist/generators/types.d.ts +1 -0
  92. package/dist/generators/types.d.ts.map +1 -1
  93. package/dist/generators/types.js.map +1 -1
  94. package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
  95. package/dist/orchestrator/ai-rules-updater.js +12 -0
  96. package/dist/orchestrator/ai-rules-updater.js.map +1 -1
  97. package/dist/orchestrator/project-initializer.d.ts +21 -1
  98. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  99. package/dist/orchestrator/project-initializer.js +158 -74
  100. package/dist/orchestrator/project-initializer.js.map +1 -1
  101. package/dist/orchestrator/screen-manager.d.ts.map +1 -1
  102. package/dist/orchestrator/screen-manager.js +2 -0
  103. package/dist/orchestrator/screen-manager.js.map +1 -1
  104. package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +15 -17
  105. package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +7 -5
  106. package/dist/orchestrator/templates/ai-instructions/claude-cmd-delivery.md +71 -0
  107. package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +28 -1
  108. package/dist/orchestrator/templates/ai-instructions/claude-config.md +23 -4
  109. package/dist/orchestrator/templates/ai-instructions/claude-skill-capture-figma.md +142 -0
  110. package/dist/orchestrator/templates/ai-instructions/claude-skill-capture-live.md +100 -0
  111. package/dist/orchestrator/templates/ai-instructions/claude-skill-capture-local.md +73 -0
  112. package/dist/orchestrator/templates/ai-instructions/claude-skill-delivery.md +103 -0
  113. package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +68 -13
  114. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +22 -0
  115. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +54 -3
  116. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +13 -15
  117. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +6 -4
  118. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +71 -0
  119. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +38 -14
  120. package/dist/orchestrator/templates/ai-instructions/copilot-config.md +23 -4
  121. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-figma.md +142 -0
  122. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-live.md +100 -0
  123. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-local.md +73 -0
  124. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +103 -0
  125. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +88 -13
  126. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +22 -0
  127. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +54 -3
  128. package/dist/orchestrator/templates/playwright.config.d.ts.map +1 -1
  129. package/dist/orchestrator/templates/playwright.config.js +6 -1
  130. package/dist/orchestrator/templates/playwright.config.js.map +1 -1
  131. package/dist/orchestrator/templates/playwright.config.ts +6 -1
  132. package/dist/orchestrator/templates/specs-base.d.ts +12 -1
  133. package/dist/orchestrator/templates/specs-base.d.ts.map +1 -1
  134. package/dist/orchestrator/templates/specs-base.js +47 -5
  135. package/dist/orchestrator/templates/specs-base.js.map +1 -1
  136. package/dist/orchestrator/templates/specs-base.ts +65 -7
  137. package/dist/orchestrator/templates/specs-test-data.d.ts +14 -0
  138. package/dist/orchestrator/templates/specs-test-data.d.ts.map +1 -0
  139. package/dist/orchestrator/templates/specs-test-data.js +100 -0
  140. package/dist/orchestrator/templates/specs-test-data.js.map +1 -0
  141. package/dist/orchestrator/templates/specs-test-data.ts +66 -0
  142. package/package.json +2 -1
  143. package/src/cli/commands/delivery.ts +348 -0
  144. package/src/cli/commands/generate.ts +2 -0
  145. package/src/cli/commands/update.ts +84 -2
  146. package/src/cli/index.ts +4 -2
  147. package/src/exporters/csv-exporter.ts +304 -0
  148. package/src/exporters/feature-parser.ts +168 -0
  149. package/src/exporters/package-info.ts +35 -0
  150. package/src/exporters/playwright-report-parser.ts +168 -0
  151. package/src/exporters/scenario-merger.ts +63 -0
  152. package/src/exporters/spec-parser.ts +247 -0
  153. package/src/exporters/step-formatter.ts +80 -0
  154. package/src/exporters/test-data-resolver.ts +59 -0
  155. package/src/exporters/types.ts +112 -0
  156. package/src/exporters/xlsx-exporter.ts +301 -0
  157. package/src/generators/gherkin-parser/index.ts +4 -0
  158. package/src/generators/test-generator/adapters/adapter-interface.ts +12 -1
  159. package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +14 -2
  160. package/src/generators/test-generator/adapters/playwright/templates/after-all.hbs +8 -0
  161. package/src/generators/test-generator/adapters/playwright/templates/after-each.hbs +8 -0
  162. package/src/generators/test-generator/adapters/playwright/templates/before-all.hbs +8 -0
  163. package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  164. package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +24 -0
  165. package/src/generators/test-generator/code-generator.ts +122 -13
  166. package/src/generators/test-generator/step-mapper.ts +2 -2
  167. package/src/generators/test-generator/template-engine.ts +28 -2
  168. package/src/generators/test-generator/utils/data-resolver.ts +45 -27
  169. package/src/generators/test-generator/utils/runtime-data-transformer.ts +51 -0
  170. package/src/generators/test-generator/utils/selector-resolver.ts +26 -0
  171. package/src/generators/types.ts +1 -0
  172. package/src/orchestrator/ai-rules-updater.ts +12 -0
  173. package/src/orchestrator/project-initializer.ts +187 -80
  174. package/src/orchestrator/screen-manager.ts +2 -0
  175. package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +15 -17
  176. package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +7 -5
  177. package/src/orchestrator/templates/ai-instructions/claude-cmd-delivery.md +71 -0
  178. package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +28 -1
  179. package/src/orchestrator/templates/ai-instructions/claude-config.md +23 -4
  180. package/src/orchestrator/templates/ai-instructions/claude-skill-capture-figma.md +142 -0
  181. package/src/orchestrator/templates/ai-instructions/claude-skill-capture-live.md +100 -0
  182. package/src/orchestrator/templates/ai-instructions/claude-skill-capture-local.md +73 -0
  183. package/src/orchestrator/templates/ai-instructions/claude-skill-delivery.md +103 -0
  184. package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +68 -13
  185. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +22 -0
  186. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +54 -3
  187. package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +13 -15
  188. package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +6 -4
  189. package/src/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +71 -0
  190. package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +38 -14
  191. package/src/orchestrator/templates/ai-instructions/copilot-config.md +23 -4
  192. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-figma.md +142 -0
  193. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-live.md +100 -0
  194. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-local.md +73 -0
  195. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +103 -0
  196. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +88 -13
  197. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +22 -0
  198. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +54 -3
  199. package/src/orchestrator/templates/playwright.config.ts +6 -1
  200. package/src/orchestrator/templates/specs-base.ts +65 -7
  201. package/src/orchestrator/templates/specs-test-data.ts +66 -0
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: sungen-capture-figma
3
+ description: 'Fetch design context + PNG from a Figma frame URL via Figma Dev Mode MCP. Auto-loaded by create-test when user picks Figma as the visual source.'
4
+ user-invocable: false
5
+ ---
6
+
7
+ ## Purpose
8
+
9
+ Pull **structured design data** (layout, typography, colors, component tree, design tokens) and a **PNG screenshot** from a Figma frame URL, so `sungen-tc-generation` can author Gherkin + test-data before a live domain exists.
10
+
11
+ Use this when the project is pre-launch, or when Figma is the source of truth and the live build lags the design.
12
+
13
+ ---
14
+
15
+ ## Prerequisites
16
+
17
+ - **Figma MCP server** (`https://mcp.figma.com/mcp`, HTTP transport) connected in the user's `.mcp.json` — `sungen init` scaffolds this automatically. On first use, Claude Code opens a browser for Figma OAuth. Official tools: `get_design_context`, `get_variable_defs`, `get_screenshot`.
18
+ - Figma account signed in with access to the file. **Dev/Full seats** get per-minute rate limits; **Starter/View seats** get monthly tool-call limits.
19
+ - A Figma URL with both **fileKey** and **nodeId** in it.
20
+
21
+ If the MCP is not connected, **do not fail silently** — tell the user:
22
+ > "Figma MCP not detected. Run `sungen init` to scaffold the config, or manually add `figma` with `url: https://mcp.figma.com/mcp` to `.mcp.json`. Then sign in when Claude Code prompts."
23
+
24
+ Then stop.
25
+
26
+ ---
27
+
28
+ ## Steps
29
+
30
+ ### 1. Resolve Figma URL
31
+
32
+ Prefer in this order:
33
+
34
+ 1. `Figma URL` field in `qa/screens/<screen>/requirements/spec.md` (Overview section)
35
+ 2. If empty or missing → `AskUserQuestion`: *"Paste the Figma frame URL"* (free text)
36
+
37
+ Accept any of these URL shapes:
38
+
39
+ ```
40
+ https://www.figma.com/file/<fileKey>/<title>?node-id=<nodeId>
41
+ https://www.figma.com/design/<fileKey>/<title>?node-id=<nodeId>
42
+ https://www.figma.com/proto/<fileKey>/<title>?node-id=<nodeId>
43
+ ```
44
+
45
+ Parse:
46
+ - `fileKey` = the segment after `/file/`, `/design/`, or `/proto/`
47
+ - `nodeId` = the `node-id` query param (may use `-` or `:` — pass through as-is; MCP accepts both)
48
+
49
+ If `node-id` is missing, ask the user to select a frame in Figma and copy the **frame URL** specifically (not the file root URL).
50
+
51
+ ### 2. Fetch design context
52
+
53
+ Call **both** in parallel:
54
+
55
+ ```
56
+ get_design_context({ fileKey, nodeId })
57
+ get_variable_defs({ fileKey, nodeId })
58
+ ```
59
+
60
+ `get_design_context` returns layout, typography, color values, component structure, spacing.
61
+ `get_variable_defs` returns named design tokens (color/spacing/typography variables).
62
+
63
+ ### 3. Fetch screenshot
64
+
65
+ ```
66
+ get_screenshot({ fileKey, nodeId })
67
+ ```
68
+
69
+ Save the returned PNG to:
70
+
71
+ ```
72
+ qa/screens/<screen>/requirements/ui/figma-<sanitized-nodeId>.png
73
+ ```
74
+
75
+ Sanitize `nodeId` for filesystem: replace `:` and `-` with `_`. Example: `42-15` → `figma-42_15.png`.
76
+
77
+ ### 4. Write metadata dump
78
+
79
+ Combine the design context + variables into a Markdown summary at:
80
+
81
+ ```
82
+ qa/screens/<screen>/requirements/ui/figma-meta.md
83
+ ```
84
+
85
+ Format:
86
+
87
+ ```markdown
88
+ # Figma Capture — <nodeId>
89
+
90
+ **Source:** <full Figma URL>
91
+ **Captured:** <ISO date>
92
+
93
+ ## Components
94
+ <hierarchical list of component names + variants from get_design_context>
95
+
96
+ ## Typography
97
+ <font families, sizes, weights, line heights>
98
+
99
+ ## Colors
100
+ <color tokens + raw hex values>
101
+
102
+ ## Spacing & Layout
103
+ <spacing tokens, auto-layout specs>
104
+
105
+ ## Text Content
106
+ <visible text strings from the frame — used by tc-generation to populate test-data>
107
+ ```
108
+
109
+ This file is consumed by `sungen-tc-generation` as a secondary source alongside `spec.md`.
110
+
111
+ ### 5. Report back
112
+
113
+ Output a short summary to the user:
114
+
115
+ > Captured Figma frame `<nodeId>`:
116
+ > - Components: N
117
+ > - Text strings: M
118
+ > - Design tokens: K
119
+ > - Screenshot: `qa/screens/<screen>/requirements/ui/figma-<nodeId>.png`
120
+ > - Metadata: `requirements/ui/figma-meta.md`
121
+
122
+ Then hand back to the calling command.
123
+
124
+ ---
125
+
126
+ ## Error handling
127
+
128
+ | Error | Action |
129
+ |---|---|
130
+ | MCP tool not available | Print setup instructions, stop, do not fall back silently |
131
+ | `fileKey` missing from URL | Ask user to paste a valid frame URL |
132
+ | `nodeId` missing from URL | Ask user to right-click a frame in Figma → *Copy link to selection* |
133
+ | `get_design_context` 403 | Ask user to check Dev Mode seat on that file |
134
+ | `get_screenshot` returns no image | Continue with metadata only; warn user no PNG was captured |
135
+
136
+ ---
137
+
138
+ ## What this skill does NOT do
139
+
140
+ - Does not generate Gherkin (that's `sungen-tc-generation`)
141
+ - Does not write `selectors.yaml` (that's `/sungen:run-test`)
142
+ - Does not validate the design against live UI (future skill: `sungen-capture-live` can be run afterwards for cross-check)
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: sungen-capture-live
3
+ description: 'Capture a live running page via Playwright MCP — snapshot + screenshot for visual context. Auto-loaded by create-test when user picks Live page scan.'
4
+ user-invocable: false
5
+ ---
6
+
7
+ ## Purpose
8
+
9
+ Navigate a running application, take **one accessibility snapshot** and **one screenshot**, and save them as visual context for test generation. Use when the app is live (dev, staging, or production with read-only access) and you want the tests grounded in the actual rendered UI.
10
+
11
+ This skill handles auth gracefully: if the page redirects to login, it asks the user to sign in manually rather than injecting cookies.
12
+
13
+ ---
14
+
15
+ ## Prerequisites
16
+
17
+ - Playwright MCP connected.
18
+ - Dev/staging server reachable (or a public URL).
19
+ - `playwright.config.ts` exists at the project root (for `baseURL` fallback).
20
+
21
+ ---
22
+
23
+ ## Steps
24
+
25
+ ### 1. Resolve target URL
26
+
27
+ Resolve in this order:
28
+
29
+ 1. `Live URL` field in `qa/screens/<screen>/requirements/spec.md` (Overview section)
30
+ 2. `baseURL` from `playwright.config.ts` + `URL Path` from `spec.md`
31
+ 3. If neither works → `AskUserQuestion`: *"Paste the full URL for the page to scan"*
32
+
33
+ ### 2. Navigate
34
+
35
+ `browser_navigate` to the resolved URL.
36
+
37
+ ### 3. Handle auth redirect
38
+
39
+ If the page redirects to a login route (URL contains `/login`, `/signin`, `/auth`, or the page title/content indicates a login screen):
40
+
41
+ 1. Tell the user which login URL they landed on.
42
+ 2. `AskUserQuestion`:
43
+ - **I'll log in manually** — wait for user confirmation, then re-navigate to the target URL
44
+ - **Skip live scan** — tell caller to invoke `sungen-capture-local` instead
45
+ - **Cancel**
46
+ 3. **Never** inject cookies or localStorage via `browser_evaluate` or `browser_run_code`. Auth belongs to the user.
47
+
48
+ ### 4. Snapshot
49
+
50
+ Take **ONE** `browser_snapshot`. This accessibility tree is the primary AI context — it contains roles, names, text, and structure that the tc-generation skill uses to identify sections and fields.
51
+
52
+ ### 5. Screenshot (optional but recommended)
53
+
54
+ Take **ONE** `browser_take_screenshot` with `fullPage: true`. Save to:
55
+
56
+ ```
57
+ qa/screens/<screen>/requirements/ui/live-<timestamp>.png
58
+ ```
59
+
60
+ Where `<timestamp>` is `YYYYMMDD-HHMM` in local time (e.g. `live-20260421-1430.png`).
61
+
62
+ This gives users a visual record they can reference later without re-scanning.
63
+
64
+ ### 6. Detect discrepancies vs spec
65
+
66
+ If `spec.md` exists, briefly cross-check the snapshot against spec sections:
67
+
68
+ - Fields listed in spec but not in snapshot → flag as *missing in UI*
69
+ - Elements visible in snapshot but not in spec → flag as *missing in spec*
70
+
71
+ Report findings but **do not** auto-edit `spec.md` — let the user decide.
72
+
73
+ ### 7. Report back
74
+
75
+ > Captured live page `<URL>`:
76
+ > - Snapshot: <N> interactive elements detected
77
+ > - Screenshot: `requirements/ui/live-<timestamp>.png`
78
+ > - Discrepancies vs spec: <count, or "none">
79
+
80
+ Hand back to the calling command.
81
+
82
+ ---
83
+
84
+ ## What this skill does NOT do
85
+
86
+ - Does not run tests
87
+ - Does not generate `selectors.yaml` (that's `/sungen:run-test`)
88
+ - Does not inject auth state (user logs in manually)
89
+ - Does not crawl — scans **exactly one** page per invocation
90
+ - Does not generate Gherkin — that's `sungen-tc-generation`
91
+
92
+ ---
93
+
94
+ ## Relationship to other capture skills
95
+
96
+ - `sungen-capture-figma` — design source of truth (pre-launch)
97
+ - `sungen-capture-local` — any image the user dropped in `requirements/ui/`
98
+ - `sungen-capture-live` — this skill, verifies/supplements against the running app
99
+
100
+ All three write to `requirements/ui/` and report back to the caller. They are mutually exclusive per create-test run, but a user can run create-test multiple times with different sources to layer context.
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: sungen-capture-local
3
+ description: 'Load existing UI assets (screenshots, Figma exports, hand-drawn mockups) from requirements/ui/. Auto-loaded by create-test when user picks UI images as the visual source.'
4
+ user-invocable: false
5
+ ---
6
+
7
+ ## Purpose
8
+
9
+ Use **pre-existing images** in `qa/screens/<screen>/requirements/ui/` as visual context for test generation. No network, no MCP, no live site required — works for any design tool (Figma export, Sketch, Penpot, Zeplin, hand-drawn, screenshots of a staging env).
10
+
11
+ This is the **baseline fallback**: if live domain is down and Figma MCP isn't configured, this always works as long as the user drops images in the folder.
12
+
13
+ ---
14
+
15
+ ## Steps
16
+
17
+ ### 1. List available images
18
+
19
+ Glob `qa/screens/<screen>/requirements/ui/*.{png,jpg,jpeg,webp,gif}` and report count + filenames.
20
+
21
+ Filter out metadata files (e.g. `figma-meta.md` written by `sungen-capture-figma`) — those are read by `tc-generation` separately, not treated as images here.
22
+
23
+ ### 2. Handle empty folder
24
+
25
+ If no images found:
26
+
27
+ 1. Tell the user the folder is empty, with the full path so they can navigate there in Finder.
28
+ 2. `AskUserQuestion`:
29
+ - **I'll drop images now** — wait for user to confirm, then re-glob
30
+ - **Switch to Figma URL** — tell caller to invoke `sungen-capture-figma` instead
31
+ - **Switch to live page scan** — tell caller to invoke `sungen-capture-live` instead
32
+ - **Cancel** — abort create-test
33
+ 3. If user picks "drop images now", wait for their confirmation message (e.g. "done") then re-run step 1.
34
+
35
+ ### 3. Read images for context
36
+
37
+ Use the `Read` tool on each image file — Claude Code can read PNG/JPG/WebP directly as visual context.
38
+
39
+ For large sets (>10 images), ask the user which are primary and which are states/variants, to avoid loading too much visual context at once.
40
+
41
+ ### 4. Summarize
42
+
43
+ Output a short summary:
44
+
45
+ > Loaded N image(s) from `qa/screens/<screen>/requirements/ui/`:
46
+ > - `<filename-1>` — <one-line description of what's visible>
47
+ > - `<filename-2>` — <one-line description>
48
+ > ...
49
+
50
+ Hand back to the calling command.
51
+
52
+ ---
53
+
54
+ ## File naming hints for users
55
+
56
+ When this skill reports back, nudge users toward consistent filenames so future runs are self-documenting:
57
+
58
+ - `<section>-default.png` — baseline state of a section
59
+ - `<section>-error.png` — error state
60
+ - `<section>-loading.png` — loading state
61
+ - `<section>-empty.png` — empty state
62
+ - `full-page.png` / `viewport.png` — whole screen (auto-generated by `sungen add --capture`)
63
+
64
+ Don't enforce — just suggest if filenames are ambiguous.
65
+
66
+ ---
67
+
68
+ ## What this skill does NOT do
69
+
70
+ - Does not download images from external URLs
71
+ - Does not generate images (no AI image generation)
72
+ - Does not modify existing images (no crop/resize)
73
+ - Does not generate Gherkin — that's `sungen-tc-generation`
@@ -0,0 +1,103 @@
1
+ ---
2
+ name: sungen-delivery
3
+ description: 'Export Gherkin scenarios + Playwright results → CSV test case deliverable. Auto-loaded by delivery command.'
4
+ user-invocable: false
5
+ ---
6
+
7
+ ## Purpose
8
+
9
+ Export test cases from Sungen screens to a standardized CSV file (format BM-2-901-13) for QA delivery.
10
+
11
+ **This skill delegates all heavy work to the `sungen delivery` CLI.** The CLI is the single source of truth for parsing logic — do NOT re-parse files in AI. Your role is only to:
12
+
13
+ 1. Invoke the CLI
14
+ 2. Show its output verbatim
15
+ 3. Help the user react to pre-flight failures
16
+
17
+ ---
18
+
19
+ ## Architecture
20
+
21
+ ```
22
+ User → /sungen:delivery [screen...]
23
+
24
+
25
+ sungen delivery CLI (deterministic — no AI tokens)
26
+ ├─ Scope detection (no-arg = all screens)
27
+ ├─ Pre-flight source checks per screen
28
+ ├─ Parse .feature (metadata)
29
+ ├─ Parse .spec.ts (resolved Playwright code — source of truth)
30
+ ├─ Parse test-data.yaml (resolve {{vars}})
31
+ ├─ Parse test-results/results.json (match test titles)
32
+ ├─ Merge sources + generate CSV rows
33
+ └─ Write qa/deliverables/<screen>-testcases.csv
34
+ ```
35
+
36
+ Source modules: `src/exporters/*.ts`
37
+
38
+ ---
39
+
40
+ ## Required sources (CLI pre-flight checks these)
41
+
42
+ | # | Source | Path | Created by |
43
+ |---|--------|------|------------|
44
+ | 1 | Feature file | `qa/screens/<screen>/features/<screen>.feature` | `/sungen:add-screen` + `/sungen:create-test` |
45
+ | 2 | Test data | `qa/screens/<screen>/test-data/<screen>.yaml` | `/sungen:create-test` |
46
+ | 3 | Selectors | `qa/screens/<screen>/selectors/<screen>.yaml` | `/sungen:run-test` |
47
+ | 4 | Compiled spec | `specs/generated/<screen>/<screen>.spec.ts` | `sungen generate` (during `/sungen:run-test`) |
48
+ | 5 | Test results | `specs/generated/<screen>/<screen>-test-result.json` (per-screen) or `test-results/results.json` (global fallback) | `/sungen:run-test` |
49
+
50
+ **Sources 1-4 are blocking** — CLI aborts if any is missing.
51
+ **Source 5 is optional** — CSV is still generated but Test Result/Date/Executor/Env columns are empty (all tests show as Pending).
52
+
53
+ The CLI reads the **per-screen result file first** (co-located with `.spec.ts`), then falls back to the global `test-results/results.json`. Per-screen is preferred because the global file gets OVERWRITTEN each time Playwright runs, losing results from earlier screens.
54
+
55
+ ---
56
+
57
+ ## Column mapping (handled by CLI)
58
+
59
+ | CSV Column | Source |
60
+ |------------|--------|
61
+ | TC ID | Generated: `<SCREEN_UPPER>-<VP>-<NNN>` |
62
+ | Category 1 | Scenario name with VP prefix stripped |
63
+ | Category 2 | VP group: `VP-SEC`→Accessing, `VP-UI`→GUI, `VP-VAL`/`VP-LOGIC`→Function |
64
+ | Category 3 | Feature name (first line of `.feature`) |
65
+ | Category 4 | Screen name |
66
+ | Pre-condition | Auth tag → "Logged in as X" / "Not authenticated" + Given steps (natural language) |
67
+ | Test Data | `{{vars}}` from scenario resolved via test-data.yaml → `key: value; key2: value2` |
68
+ | Steps | `.spec.ts` code comments for interactions (numbered) |
69
+ | Expected results | `.spec.ts` `expect(...)` comments (numbered) |
70
+ | Priority | Tag: `@critical`/`@high`/`@normal`/`@low` (default: Normal) |
71
+ | Testcase type | `@manual` → Manual, else Auto. Not compiled → "Not compiled" |
72
+ | Test Result | results.json status: passed→Passed, failed/timedOut→Failed, skipped→N/A, else Pending |
73
+ | Executed Date | results.json startTime formatted as `dd/mm/yyyy` |
74
+ | Test Executor | `git config user.name` |
75
+ | Test Environment | `playwright.config.ts` baseURL + project name |
76
+ | Note | Error message + trace path (for failed tests) |
77
+
78
+ ---
79
+
80
+ ## Excluded from CSV
81
+
82
+ - `@steps:<name>` **base** scenarios — these are setup-only, inlined into `@extend:...` scenarios at compile time
83
+ - Default scaffold `Sample scenario for <screen>` — not a real test
84
+
85
+ ---
86
+
87
+ ## CLI command reference
88
+
89
+ ```bash
90
+ # Export all screens
91
+ sungen delivery
92
+
93
+ # Export specific screens
94
+ sungen delivery kudos awards
95
+
96
+ # Skip pre-flight (CI only)
97
+ sungen delivery --skip-preflight
98
+
99
+ # Skip screens with blocking misses
100
+ sungen delivery --continue-on-missing
101
+ ```
102
+
103
+ Output: `qa/deliverables/<screen>-testcases.csv` (UTF-8 with BOM)
@@ -109,6 +109,8 @@ Row scope: `see [Ref] row in [Table] table with {{v}}` enters scope. Subsequent
109
109
 
110
110
  Most elements auto-infer from `[Label] type` → `getByRole(type, { name: 'Label' })`. Only add YAML when the accessible name differs, needs `nth`, or needs `testid`. Full auto-infer table → see `sungen-selector-keys` skill.
111
111
 
112
+ **Types requiring YAML entry:** `date-picker`, `uploader`, `overlay`, `frame`, `step` - these have no standard ARIA role and need explicit selectors.
113
+
112
114
  ## YAML Keys
113
115
 
114
116
  `[Reference]` → **lowercase, keep Unicode**: `[Search Content]` → `search content:`, `[Thời gian]` → `thời gian:`
@@ -149,6 +151,14 @@ Options: `nth` `exact` `scope` `match` `variant` `frame` `contenteditable` `colu
149
151
  | `@no-auth` | Disable inherited auth |
150
152
  | `@steps:name` | Define reusable step block (base scenario) |
151
153
  | `@extend:name` | Prepend Given→When from @steps block (skip Then) |
154
+ | `@cleanup:overlay` | Auto-cleanup: dismiss dialogs/overlays after each test (base.ts fixture) |
155
+ | `@cleanup:forms` | Auto-cleanup: clear form fields after each test (base.ts fixture) |
156
+ | `@cleanup:scroll` | Auto-cleanup: scroll to top after each test (base.ts fixture) |
157
+ | `@cleanup:storage` | Auto-cleanup: clear sessionStorage after each test (base.ts fixture) |
158
+ | `@screenshot:on-failure` | Auto-capture screenshot when test fails (base.ts fixture) |
159
+ | `@beforeAll` | Hook: runs once before all tests → `test.beforeAll()` |
160
+ | `@afterEach` | Hook: runs after each test → `test.afterEach()` (custom cleanup) |
161
+ | `@afterAll` | Hook: runs once after all tests → `test.afterAll()` |
152
162
 
153
163
  ### @extend behavior
154
164
 
@@ -173,30 +183,28 @@ Options: `nth` `exact` `scope` `match` `variant` `frame` `contenteditable` `colu
173
183
  | Missing `is` for state | `with {{text}} hidden` | `with {{text}} is hidden` |
174
184
  | State as value | `with {{disabled}}` | `is disabled` |
175
185
  | Missing target type | `fill [email] with {{v}}` | `fill [email] field with {{v}}` |
176
- | Using Background | `Background: Given User is on...` | Use `@steps` + `@extend` instead |
186
+ | Background with scope | `Background: ... And User is on [X] dialog` | Use `@steps` + `@extend` for scope-dependent flows |
177
187
  | `is on` after When | `When ... And User is on [X] dialog` | `And User see [X] dialog` or separate Given |
178
188
 
179
189
  ## Background vs @steps/@extend
180
190
 
181
- **Do NOT use `Background:` block.** Use `@steps` + `@extend` instead.
191
+ Both `Background` and `@steps`/`@extend` are valid — they serve different purposes.
182
192
 
183
- **Why:**
184
- - `Background` runs before EVERY scenario but cannot set dialog/frame scope correctly
185
- - `Background` with `When` + `And User is on [X] dialog` creates keyword mismatch (`is on` = Given, not When)
186
- - `@steps` + `@extend` gives explicit control: base steps run Given→When, extending scenario starts with `Given User is on [X] dialog` (correct scope setup)
193
+ | Pattern | Use when | Generates |
194
+ |---|---|---|
195
+ | `Background` | Simple shared setup (navigate to page) | `test.beforeEach()` |
196
+ | `@steps`/`@extend` | Complex reusable flows with scope (dialog, frame) | Inline merged steps in `test()` |
187
197
 
188
- **Wrong:**
198
+ **Use `Background` for simple navigation:**
189
199
  ```gherkin
190
200
  Background:
191
- Given User is on [Kudos] page
192
- When User click [Open] button
193
- And User is on [Modal] dialog ← keyword mismatch
201
+ Given User is on [Dashboard] page
194
202
 
195
- Scenario: VP-UI-001 Title visible
196
- Then User see [Title] heading
203
+ Scenario: View stats
204
+ Then User see [Revenue Chart] section
197
205
  ```
198
206
 
199
- **Correct:**
207
+ **Use `@steps`/`@extend` when scope matters (dialog, frame):**
200
208
  ```gherkin
201
209
  @steps:open_modal
202
210
  Scenario: Open modal
@@ -209,3 +217,50 @@ Scenario: VP-UI-001 Title visible
209
217
  Given User is on [Modal] dialog
210
218
  Then User see [Title] heading
211
219
  ```
220
+
221
+ **Avoid `Background` with scope-dependent steps** — `When` + `And User is on [X] dialog` creates keyword mismatch (`is on` = Given, not When). Use `@steps`/`@extend` instead.
222
+
223
+ ## Hooks & Cleanup
224
+
225
+ Two layers for test lifecycle management. Prefer `@cleanup:*` tags (Layer 1) — they work with base.ts automatically. Use hook scenarios (Layer 2) only for custom logic.
226
+
227
+ ### Layer 1: `@cleanup:*` tags (automatic via base.ts)
228
+
229
+ Feature-level tags that activate cleanup fixtures in base.ts. No Gherkin steps needed.
230
+
231
+ ```gherkin
232
+ @auth:admin
233
+ @cleanup:overlay
234
+ @cleanup:forms
235
+ Feature: User Management
236
+ Path: /users
237
+
238
+ Background:
239
+ Given User is on [User Management] page
240
+
241
+ Scenario: Create user shows form
242
+ When User click [Add User] button
243
+ Then User see [Create User] dialog
244
+
245
+ Scenario: Search user by name
246
+ When User fill [Search] field with {{search_name}}
247
+ Then User see [User Row] row
248
+ ```
249
+
250
+ | Tag | What base.ts does after each test |
251
+ |---|---|
252
+ | `@cleanup:overlay` | Press Escape, click body, dismiss fixed overlays |
253
+ | `@cleanup:forms` | Clear all input/textarea fields, reset selects |
254
+ | `@cleanup:scroll` | Scroll to top of page |
255
+ | `@cleanup:storage` | Clear sessionStorage |
256
+
257
+ ### Layer 2: `@afterEach` scenario (custom cleanup)
258
+
259
+ Only when `@cleanup:*` tags aren't enough — feature-specific logic.
260
+
261
+ ### Layer 3: `@beforeAll` / `@afterAll` (optional)
262
+
263
+ For one-time setup/teardown.
264
+
265
+ **Rendering order in `.spec.ts`:**
266
+ `test.describe` → `test.use(storageState)` → `test.use(autoCleanup)` → `test.beforeAll` → `test.beforeEach` → `test.afterEach` → `test.afterAll` → `test()` blocks
@@ -102,5 +102,27 @@ If no YAML key exists, the resolver infers from the Gherkin element type:
102
102
  | `[X] list` | `getByRole('list', { name: 'X' })` |
103
103
  | `[X] column` | `getByRole('columnheader', { name: 'X' })` |
104
104
  | `[X] dialog` / `modal` / `drawer` | `getByRole('dialog', { name: 'X' })` |
105
+ | `[X] dropdown` / `select` | `getByRole('combobox', { name: 'X' })` |
106
+ | `[X] menuitem` | `getByRole('menuitem', { name: 'X' })` |
107
+ | `[X] progressbar` | `getByRole('progressbar', { name: 'X' })` |
108
+ | `[X] section` | `getByRole('region', { name: 'X' })` |
109
+ | `[X] card` | `getByRole('article', { name: 'X' })` |
110
+ | `[X] item` | `getByRole('listitem', { name: 'X' })` |
111
+ | `[X] cell` | `getByRole('cell', { name: 'X' })` |
112
+ | `[X] spinner` | `getByRole('status', { name: 'X' })` |
113
+ | `[X] breadcrumb` | `getByRole('navigation', { name: 'X' })` |
114
+ | `[X] badge` / `tooltip` / `tag` | `getByText('X')` |
105
115
 
106
116
  **Only add a YAML entry when** the auto-inferred locator won't work (wrong name, need testid, need nth, etc.).
117
+
118
+ ### Types requiring YAML entry (no auto-infer)
119
+
120
+ These types need explicit `selectors.yaml` entries:
121
+
122
+ | Type | Reason |
123
+ |------|--------|
124
+ | `date-picker` | Custom component, needs testid or CSS |
125
+ | `uploader` | File input, needs upload type selector |
126
+ | `overlay` | No standard ARIA role, needs CSS/testid |
127
+ | `frame` | Needs iframe selector |
128
+ | `step` | Custom stepper component, needs testid |
@@ -112,20 +112,59 @@ Given User is on [Screen] page
112
112
  And User wait for [Page Title] heading is visible
113
113
  ```
114
114
 
115
+ ## Cleanup & Hooks
116
+
117
+ ### Auto-assign `@cleanup:*` tags based on screen sections
118
+
119
+ After identifying screen sections, add appropriate `@cleanup:*` feature-level tags. These activate base.ts fixtures that auto-clean state between tests.
120
+
121
+ | Screen has | Add tag | Why |
122
+ |---|---|---|
123
+ | Modal / Dialog / Drawer | `@cleanup:overlay` | Dismiss leftover overlays between tests |
124
+ | Form & Inputs / Search / Filter | `@cleanup:forms` | Clear form fields, reset selects |
125
+ | Long scrollable content | `@cleanup:scroll` | Scroll to top for consistent assertions |
126
+ | Auth tokens / session data in tests | `@cleanup:storage` | Clear sessionStorage |
127
+ | CI/CD or debug-heavy screens | `@screenshot:on-failure` | Auto-capture screenshot on test failure |
128
+
129
+ **Always add `@cleanup:overlay`** if ANY section opens a dialog (Create/Add, Update/Edit, Delete confirmation). Most CRUD screens need it.
130
+
131
+ **Always add `@cleanup:forms`** if the screen has inline search, filter dropdowns, or editable forms that persist between tests.
132
+
133
+ ### When to add `@afterEach` hook scenario
134
+
135
+ Only when `@cleanup:*` tags aren't enough — feature-specific cleanup logic:
136
+ - Reset a dropdown filter to default value (not just clear)
137
+ - Navigate away from a sub-tab back to the main tab
138
+ - Close a specific sidebar panel
139
+
140
+ ```gherkin
141
+ @afterEach
142
+ Scenario: Reset filters to default
143
+ When User select [Status Filter] dropdown with {{default_status}}
144
+ ```
145
+
146
+ ### `@beforeAll` / `@afterAll` — optional, low priority
147
+
148
+ For one-time setup/teardown. Most screens don't need these.
149
+
115
150
  ## Output Format
116
151
 
117
152
  **Feature file** — `qa/screens/<screen>/features/<screen>.feature`
118
153
 
119
- **Never use `Background:`.** Use `@steps` + `@extend` for shared setup (see `sungen-gherkin-syntax` skill).
154
+ `Background` is valid for simple shared setup (navigate to page). Use `@steps`/`@extend` for complex flows with scope (dialog, frame).
120
155
 
121
156
  ```gherkin
122
157
  @auth:role
158
+ @cleanup:overlay
159
+ @cleanup:forms
123
160
  Feature: <Screen> Screen
124
161
 
162
+ Background:
163
+ Given User is on [Screen] page
164
+
125
165
  # Shared setup — NO priority tag on @steps
126
166
  @steps:open_form
127
167
  Scenario: Open form
128
- Given User is on [Screen] page
129
168
  When User click [Create] button
130
169
  Then User see [Form] dialog
131
170
 
@@ -165,6 +204,18 @@ Feature: <Screen> Screen
165
204
 
166
205
  **Naming**: `VP-<CATEGORY>-<NNN>` prefix. Scenario name must use the **same element type** as the steps — e.g., if the step uses `dialog`, write "dialog opens" not "modal opens".
167
206
 
168
- **Test data** — `qa/screens/<screen>/test-data/<screen>.yaml`, grouped by section.
207
+ **Test data** — `qa/screens/<screen>/test-data/<screen>.yaml`, grouped by section. Data is loaded **at runtime** — keys become runtime lookups, not hardcoded strings. The same compiled test works across environments.
208
+
209
+ **Environment-specific data**: For values that differ per environment (credentials, URLs, test users), create `<screen>.<env>.yaml` alongside the base file. Users run `SUNGEN_ENV=staging npx playwright test` to merge overrides. Structure env YAML with the same keys, only including values that change:
210
+
211
+ ```yaml
212
+ # login.yaml (base)
213
+ valid_email: admin@dev.example.com
214
+ valid_password: DevPass123
215
+
216
+ # login.staging.yaml (override for staging)
217
+ valid_email: admin@staging.example.com
218
+ valid_password: StagingPass456
219
+ ```
169
220
 
170
221
  **Do NOT generate**: `selectors.yaml` (created during run-test), Playwright code (sungen compiles).