@sun-asterisk/sungen 2.5.0 → 2.5.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/README.md +88 -7
- package/dist/cli/commands/add.d.ts.map +1 -1
- package/dist/cli/commands/add.js +109 -9
- package/dist/cli/commands/add.js.map +1 -1
- package/dist/cli/commands/figma.d.ts +11 -0
- package/dist/cli/commands/figma.d.ts.map +1 -0
- package/dist/cli/commands/figma.js +178 -0
- package/dist/cli/commands/figma.js.map +1 -0
- package/dist/cli/index.js +4 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
- package/dist/orchestrator/ai-rules-updater.js +2 -0
- package/dist/orchestrator/ai-rules-updater.js.map +1 -1
- package/dist/orchestrator/figma/figma-scaffolder-helpers.d.ts +33 -0
- package/dist/orchestrator/figma/figma-scaffolder-helpers.d.ts.map +1 -0
- package/dist/orchestrator/figma/figma-scaffolder-helpers.js +135 -0
- package/dist/orchestrator/figma/figma-scaffolder-helpers.js.map +1 -0
- package/dist/orchestrator/figma/figma-scaffolder-types.d.ts +25 -0
- package/dist/orchestrator/figma/figma-scaffolder-types.d.ts.map +1 -0
- package/dist/orchestrator/figma/figma-scaffolder-types.js +7 -0
- package/dist/orchestrator/figma/figma-scaffolder-types.js.map +1 -0
- package/dist/orchestrator/figma/figma-scaffolder.d.ts +23 -0
- package/dist/orchestrator/figma/figma-scaffolder.d.ts.map +1 -0
- package/dist/orchestrator/figma/figma-scaffolder.js +212 -0
- package/dist/orchestrator/figma/figma-scaffolder.js.map +1 -0
- package/dist/orchestrator/figma/node-path-collapser.d.ts +16 -0
- package/dist/orchestrator/figma/node-path-collapser.d.ts.map +1 -0
- package/dist/orchestrator/figma/node-path-collapser.js +37 -0
- package/dist/orchestrator/figma/node-path-collapser.js.map +1 -0
- package/dist/orchestrator/figma/spec-figma-renderer.d.ts +44 -0
- package/dist/orchestrator/figma/spec-figma-renderer.d.ts.map +1 -0
- package/dist/orchestrator/figma/spec-figma-renderer.js +45 -0
- package/dist/orchestrator/figma/spec-figma-renderer.js.map +1 -0
- package/dist/orchestrator/figma/spec-figma-section-renderers.d.ts +23 -0
- package/dist/orchestrator/figma/spec-figma-section-renderers.d.ts.map +1 -0
- package/dist/orchestrator/figma/spec-figma-section-renderers.js +47 -0
- package/dist/orchestrator/figma/spec-figma-section-renderers.js.map +1 -0
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +56 -11
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +30 -17
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-review.md +4 -3
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +33 -1
- package/dist/orchestrator/templates/ai-instructions/claude-config.md +1 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-figma-source.md +151 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +39 -20
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +2 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +53 -9
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +21 -16
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +2 -2
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-review.md +4 -3
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +36 -4
- package/dist/orchestrator/templates/ai-instructions/copilot-config.md +1 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-skill-figma-source.md +151 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-figma-source.md +151 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +61 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +51 -25
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +20 -0
- package/dist/tools/figma/figma-auth.d.ts +36 -0
- package/dist/tools/figma/figma-auth.d.ts.map +1 -0
- package/dist/tools/figma/figma-auth.js +182 -0
- package/dist/tools/figma/figma-auth.js.map +1 -0
- package/dist/tools/figma/figma-cache.d.ts +45 -0
- package/dist/tools/figma/figma-cache.d.ts.map +1 -0
- package/dist/tools/figma/figma-cache.js +191 -0
- package/dist/tools/figma/figma-cache.js.map +1 -0
- package/dist/tools/figma/figma-client-types.d.ts +112 -0
- package/dist/tools/figma/figma-client-types.d.ts.map +1 -0
- package/dist/tools/figma/figma-client-types.js +7 -0
- package/dist/tools/figma/figma-client-types.js.map +1 -0
- package/dist/tools/figma/figma-errors.d.ts +49 -0
- package/dist/tools/figma/figma-errors.d.ts.map +1 -0
- package/dist/tools/figma/figma-errors.js +105 -0
- package/dist/tools/figma/figma-errors.js.map +1 -0
- package/dist/tools/figma/figma-image-downloader.d.ts +25 -0
- package/dist/tools/figma/figma-image-downloader.d.ts.map +1 -0
- package/dist/tools/figma/figma-image-downloader.js +128 -0
- package/dist/tools/figma/figma-image-downloader.js.map +1 -0
- package/dist/tools/figma/figma-node-filter.d.ts +26 -0
- package/dist/tools/figma/figma-node-filter.d.ts.map +1 -0
- package/dist/tools/figma/figma-node-filter.js +164 -0
- package/dist/tools/figma/figma-node-filter.js.map +1 -0
- package/dist/tools/figma/figma-rest-client.d.ts +24 -0
- package/dist/tools/figma/figma-rest-client.d.ts.map +1 -0
- package/dist/tools/figma/figma-rest-client.js +154 -0
- package/dist/tools/figma/figma-rest-client.js.map +1 -0
- package/dist/tools/figma/figma-url-parser.d.ts +18 -0
- package/dist/tools/figma/figma-url-parser.d.ts.map +1 -0
- package/dist/tools/figma/figma-url-parser.js +51 -0
- package/dist/tools/figma/figma-url-parser.js.map +1 -0
- package/dist/utils/exec-file-no-throw.d.ts +20 -0
- package/dist/utils/exec-file-no-throw.d.ts.map +1 -0
- package/dist/utils/exec-file-no-throw.js +36 -0
- package/dist/utils/exec-file-no-throw.js.map +1 -0
- package/package.json +1 -1
- package/src/cli/commands/add.ts +80 -9
- package/src/cli/commands/figma.ts +162 -0
- package/src/cli/index.ts +4 -2
- package/src/orchestrator/ai-rules-updater.ts +2 -0
- package/src/orchestrator/figma/figma-scaffolder-helpers.ts +126 -0
- package/src/orchestrator/figma/figma-scaffolder-types.ts +26 -0
- package/src/orchestrator/figma/figma-scaffolder.ts +209 -0
- package/src/orchestrator/figma/node-path-collapser.ts +38 -0
- package/src/orchestrator/figma/spec-figma-renderer.ts +80 -0
- package/src/orchestrator/figma/spec-figma-section-renderers.ts +46 -0
- package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +56 -11
- package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +30 -17
- package/src/orchestrator/templates/ai-instructions/claude-cmd-review.md +4 -3
- package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +33 -1
- package/src/orchestrator/templates/ai-instructions/claude-config.md +1 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-figma-source.md +151 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +39 -20
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +2 -0
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +53 -9
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +21 -16
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +2 -2
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-review.md +4 -3
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +36 -4
- package/src/orchestrator/templates/ai-instructions/copilot-config.md +1 -0
- package/src/orchestrator/templates/ai-instructions/copilot-skill-figma-source.md +151 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-figma-source.md +151 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +61 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +51 -25
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +20 -0
- package/src/tools/figma/figma-auth.ts +161 -0
- package/src/tools/figma/figma-cache.ts +184 -0
- package/src/tools/figma/figma-client-types.ts +125 -0
- package/src/tools/figma/figma-errors.ts +127 -0
- package/src/tools/figma/figma-image-downloader.ts +112 -0
- package/src/tools/figma/figma-node-filter.ts +198 -0
- package/src/tools/figma/figma-rest-client.ts +183 -0
- package/src/tools/figma/figma-url-parser.ts +55 -0
- package/src/utils/exec-file-no-throw.ts +45 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: run-test
|
|
2
|
+
name: sungen-run-test
|
|
3
3
|
description: 'Generate selectors + auth state via Playwright MCP, compile, and run Playwright tests — auto-fixes selectors on failure'
|
|
4
|
-
argument-hint: [screen-name]
|
|
5
|
-
|
|
4
|
+
argument-hint: '[screen-name]'
|
|
5
|
+
tools: [read, execute, edit, vscode/askQuestions, playwright/*]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
## Role
|
|
@@ -16,7 +16,39 @@ Parse **screen** from `$ARGUMENTS`. If missing, ask the user.
|
|
|
16
16
|
## Pre-run (phased — per `sungen-selector-fix` skill)
|
|
17
17
|
|
|
18
18
|
1. Verify `qa/screens/<screen>/` has `.feature` + `test-data.yaml`.
|
|
19
|
-
2. **Phase 0 — Selector Pre-gen**: if `selectors.yaml` is missing/empty or doesn't cover the feature file's `[Reference]`s,
|
|
19
|
+
2. **Phase 0 — Selector Pre-gen**: if `selectors.yaml` is missing/empty or doesn't cover the feature file's `[Reference]`s, apply the following decision tree before running Phase 0 from `sungen-selector-fix`:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Phase 0 — Selector Generation decision tree
|
|
23
|
+
|
|
24
|
+
Live page reachable? (URL provided and loads without error)
|
|
25
|
+
YES → existing flow: browser_navigate → one browser_snapshot → generate selectors.yaml (verified entries)
|
|
26
|
+
NO → spec_figma.md exists in requirements/?
|
|
27
|
+
YES → provisional flow (sungen-figma-source + sungen-selector-fix skills):
|
|
28
|
+
1. Read filtered Figma node data from spec_figma.md (## Components + ## Text Inventory)
|
|
29
|
+
2. Apply selector heuristics from sungen-figma-source skill (testid > role+name > placeholder > label > locator > text)
|
|
30
|
+
3. Write selectors.yaml — every provisional entry gets this comment on the line above:
|
|
31
|
+
# @needs-live-verify source=figma node_id=<id>
|
|
32
|
+
4. Compile: sungen generate --screen <screen> — must succeed
|
|
33
|
+
5. Phase 1 smoke check runs; tests using unverified selectors may fail
|
|
34
|
+
→ auto-fix triggers on next run-test invocation when a live page is available
|
|
35
|
+
NO → hard stop: print the following message and stop:
|
|
36
|
+
"Cannot generate selectors: no live page URL and no spec_figma.md found.
|
|
37
|
+
Options:
|
|
38
|
+
• Provide the live URL so Playwright MCP can snapshot the page, OR
|
|
39
|
+
• Run: sungen add --screen <screen> --figma <figma-url> to generate spec_figma.md first"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Auto-fix on subsequent runs**: when `run-test` is invoked again with a reachable live page, Phase 0 compares the DOM snapshot against existing `selectors.yaml` entries. Entries tagged `# @needs-live-verify` are treated as candidates — if the actual selector differs, the entry is replaced and the comment removed (entry becomes verified). Entries that already match are also promoted to verified (comment removed).
|
|
43
|
+
|
|
44
|
+
**`@needs-live-verify` comment format** (one comment line, directly above the YAML key):
|
|
45
|
+
```yaml
|
|
46
|
+
# @needs-live-verify source=figma node_id=<figma-node-id>
|
|
47
|
+
submit-button:
|
|
48
|
+
type: role
|
|
49
|
+
value: button
|
|
50
|
+
name: "Submit"
|
|
51
|
+
```
|
|
20
52
|
3. **Phase 0.5 — Auth Persistence**: if the feature has `@auth:<role>` tags and `specs/.auth/<role>.json` is missing/expired, run Phase 0.5 from `sungen-selector-fix` — user logs in manually in MCP browser → `browser_storage_state` → `specs/.auth/<role>.json`. Offer `sungen makeauth <role>` as CLI fallback only if `browser_storage_state` isn't available in this MCP version.
|
|
21
53
|
4. Compile: `sungen generate --screen <screen>` (default: runtime data loading from YAML). Use `--inline-data` only if user requests compile-time hardcoded values.
|
|
22
54
|
|
|
@@ -19,6 +19,7 @@ You generate 3 files for sungen — a Gherkin compiler that produces Playwright
|
|
|
19
19
|
| `sungen-capture-figma` | Fetch design context + PNG from a Figma frame URL via Figma Dev Mode MCP |
|
|
20
20
|
| `sungen-capture-local` | Load existing UI assets (screenshots, mockups, Figma exports) from `requirements/ui/` |
|
|
21
21
|
| `sungen-capture-live` | Capture a live running page via Playwright MCP (snapshot + screenshot) |
|
|
22
|
+
| `sungen-figma-source` | Figma URL → spec_figma.md + ui/*.png + provisional selectors |
|
|
22
23
|
|
|
23
24
|
## Workflow (5 AI commands)
|
|
24
25
|
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sungen-figma-source
|
|
3
|
+
description: 'Figma URL → spec_figma.md envelope + LLM-synthesized narrative from cached raw node JSON. Auto-loaded when --figma flag present or spec_figma.md exists.'
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## When This Skill Loads
|
|
8
|
+
|
|
9
|
+
Auto-load triggers (any one is sufficient):
|
|
10
|
+
|
|
11
|
+
- Any sungen AI command invoked with `--figma` flag
|
|
12
|
+
- `requirements/spec_figma.md` exists in the screen directory
|
|
13
|
+
- User mentions a Figma URL or says "generate from Figma"
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- [ ] `sungen figma auth check` succeeds — PAT is stored and valid
|
|
20
|
+
- [ ] Figma file URL is available (shared file or frame link)
|
|
21
|
+
- [ ] If auth missing → run `sungen figma auth set` and follow the walkthrough
|
|
22
|
+
|
|
23
|
+
**Never paste the PAT into any transcript, spec file, or commit.**
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Two-Layer Architecture
|
|
28
|
+
|
|
29
|
+
`spec_figma.md` has two layers separated by the `<!-- SYNTHESIS-BELOW -->` marker:
|
|
30
|
+
|
|
31
|
+
| Layer | Producer | Overwrite Rule |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| **Envelope** (above marker) | sungen CLI | Regenerated each `sungen figma` run — deterministic |
|
|
34
|
+
| **Narrative** (below marker) | This skill (LLM) | Replaced on re-synthesis — everything from marker to EOF |
|
|
35
|
+
|
|
36
|
+
The envelope contains: YAML frontmatter, Frame metadata, Screenshots. The narrative is synthesized by YOU from the cached raw Figma node JSON.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Inputs You Read
|
|
41
|
+
|
|
42
|
+
The scaffolder persists a raw (unfiltered) Figma node tree to:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
.sungen/figma-cache/<fileKey>/<versionId>/<nodeId>-raw.json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Read this file + the envelope frontmatter of `requirements/spec_figma.md` + any PNGs under `requirements/ui/`. You MUST NOT call the Figma REST API directly — the PAT is not available to you.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Synthesis Task
|
|
53
|
+
|
|
54
|
+
Append 7 narrative sections below `<!-- SYNTHESIS-BELOW -->`. Each section is inferred from the raw node tree (names, types, `characters`, layout bounds, auto-layout direction, componentProperties):
|
|
55
|
+
|
|
56
|
+
### 1. Purpose
|
|
57
|
+
One paragraph. What screen is this? Primary user goal? Infer from frame name + top-level text + dominant CTA.
|
|
58
|
+
|
|
59
|
+
### 2. ASCII Layout
|
|
60
|
+
Rough spatial sketch using box characters. Reflect top-bottom / left-right ordering from absoluteBoundingBox. Keep under ~20 lines. Example:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
┌──────────────────────────────────────┐
|
|
64
|
+
│ [Logo] [Sign In] │
|
|
65
|
+
├──────────────────────────────────────┤
|
|
66
|
+
│ Welcome back │
|
|
67
|
+
│ ┌────────────────────────────────┐ │
|
|
68
|
+
│ │ email@example.com │ │
|
|
69
|
+
│ └────────────────────────────────┘ │
|
|
70
|
+
│ [ Continue ] │
|
|
71
|
+
└──────────────────────────────────────┘
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 3. Regions
|
|
75
|
+
Bulleted list of the major layout regions (header, sidebar, main, footer, modal, etc.) with a one-line purpose each. Use auto-layout frames as region hints.
|
|
76
|
+
|
|
77
|
+
### 4. Actions
|
|
78
|
+
Every interactive element the user can trigger. Derive from nodes whose name/type suggests a button, link, icon-button, menu-item, toggle, etc. Format:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
- **<Action name>** — <what it does> (source: <node name>)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 5. Form Fields
|
|
85
|
+
Every input the user can fill. Include label, type (text/email/password/select/checkbox/radio/textarea/date), required hint if inferable, and placeholder.
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
| Label | Type | Required | Placeholder |
|
|
89
|
+
|---|---|---|---|
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Omit entirely (write `_none_`) if no inputs exist.
|
|
93
|
+
|
|
94
|
+
### 6. Data Columns
|
|
95
|
+
If the screen shows a table, list, or card grid — enumerate the columns/fields displayed per row. Otherwise write `_none_`.
|
|
96
|
+
|
|
97
|
+
### 7. Navigation
|
|
98
|
+
Outgoing links, tab bars, breadcrumbs, back buttons — anything that moves the user to another screen. Include both explicit navigation components and implicit CTAs that navigate.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Synthesis Workflow
|
|
103
|
+
|
|
104
|
+
1. Read `requirements/spec_figma.md` — note `file_key`, `node_id`, `figma_version_id` from frontmatter
|
|
105
|
+
2. Read `.sungen/figma-cache/<file_key>/<figma_version_id>/<safe_node_id>-raw.json` (colons in node_id become underscores)
|
|
106
|
+
3. Traverse the tree. Collect: names, types, `characters`, `componentProperties`, `absoluteBoundingBox`
|
|
107
|
+
4. Produce the 7 sections above
|
|
108
|
+
5. **Locate the insertion point** in `spec_figma.md`:
|
|
109
|
+
- **If `<!-- SYNTHESIS-BELOW -->` is present** → replace everything from the marker (inclusive) to EOF with: the marker line, a blank line, then the 7 sections.
|
|
110
|
+
- **If the marker is NOT present** (older `spec_figma.md` pre-envelope-refactor, or hand-edited file) → locate the last non-empty line of the envelope (usually the end of `## Screenshots`), append a blank line, then write the marker, another blank line, then the 7 sections. Do NOT delete any existing envelope content.
|
|
111
|
+
- **If the file is missing entirely** → advise the user to re-run `sungen add --screen <screen> --figma <url> --refresh` to regenerate the envelope first. Do not fabricate one.
|
|
112
|
+
6. Preserve the envelope (frontmatter + Frame + Screenshots) byte-for-byte. Never touch content above the marker.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Re-synthesis
|
|
117
|
+
|
|
118
|
+
- If the envelope's `figma_version_id` changed → envelope is fresh; re-run synthesis
|
|
119
|
+
- If only the narrative is stale (user wants a rewrite) → truncate from marker to EOF and regenerate
|
|
120
|
+
- Never edit content ABOVE the marker — that is the scaffolder's territory
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Selector Heuristics (for downstream `run-test`)
|
|
125
|
+
|
|
126
|
+
During `run-test` Phase 0, provisional selectors can be seeded from the raw JSON:
|
|
127
|
+
|
|
128
|
+
| Figma Signal | Provisional YAML Entry |
|
|
129
|
+
|---|---|
|
|
130
|
+
| Node name ends `Button`, has text | `role: button` + `name: "<text>"` |
|
|
131
|
+
| Node name ends `Input`/`Field` | `placeholder: "<placeholder text>"` |
|
|
132
|
+
| Node name ends `Link`, has text | `role: link` + `name: "<text>"` |
|
|
133
|
+
| componentProperties has `data-testid` | `testid: <value>` |
|
|
134
|
+
| Plain text leaf (outside interactive) | `text: "<content>"` |
|
|
135
|
+
| Node name ends `Icon` | `role: img` + `name: "<accessible name>"` |
|
|
136
|
+
|
|
137
|
+
Every provisional entry MUST carry:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
# @needs-live-verify source=figma node_id=<id>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Provisional selectors feed `selectors.yaml` as candidates. `run-test` Phase 0 verifies them against the live page and overwrites incorrect entries.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Security
|
|
148
|
+
|
|
149
|
+
- Never include the PAT in `spec_figma.md`, selectors, test data, or any committed file
|
|
150
|
+
- Never log or echo the PAT in terminal output
|
|
151
|
+
- Read only from `.sungen/figma-cache/` and screen directories — never from `.env`
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sungen-figma-source
|
|
3
|
+
description: 'Figma URL → spec_figma.md envelope + LLM-synthesized narrative from cached raw node JSON. Auto-loaded when --figma flag present or spec_figma.md exists.'
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## When This Skill Loads
|
|
8
|
+
|
|
9
|
+
Auto-load triggers (any one is sufficient):
|
|
10
|
+
|
|
11
|
+
- Any sungen AI command invoked with `--figma` flag
|
|
12
|
+
- `requirements/spec_figma.md` exists in the screen directory
|
|
13
|
+
- User mentions a Figma URL or says "generate from Figma"
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- [ ] `sungen figma auth check` succeeds — PAT is stored and valid
|
|
20
|
+
- [ ] Figma file URL is available (shared file or frame link)
|
|
21
|
+
- [ ] If auth missing → run `sungen figma auth set` and follow the walkthrough
|
|
22
|
+
|
|
23
|
+
**Never paste the PAT into any transcript, spec file, or commit.**
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Two-Layer Architecture
|
|
28
|
+
|
|
29
|
+
`spec_figma.md` has two layers separated by the `<!-- SYNTHESIS-BELOW -->` marker:
|
|
30
|
+
|
|
31
|
+
| Layer | Producer | Overwrite Rule |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| **Envelope** (above marker) | sungen CLI | Regenerated each `sungen figma` run — deterministic |
|
|
34
|
+
| **Narrative** (below marker) | This skill (LLM) | Replaced on re-synthesis — everything from marker to EOF |
|
|
35
|
+
|
|
36
|
+
The envelope contains: YAML frontmatter, Frame metadata, Screenshots. The narrative is synthesized by YOU from the cached raw Figma node JSON.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Inputs You Read
|
|
41
|
+
|
|
42
|
+
The scaffolder persists a raw (unfiltered) Figma node tree to:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
.sungen/figma-cache/<fileKey>/<versionId>/<nodeId>-raw.json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Read this file + the envelope frontmatter of `requirements/spec_figma.md` + any PNGs under `requirements/ui/`. You MUST NOT call the Figma REST API directly — the PAT is not available to you.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Synthesis Task
|
|
53
|
+
|
|
54
|
+
Append 7 narrative sections below `<!-- SYNTHESIS-BELOW -->`. Each section is inferred from the raw node tree (names, types, `characters`, layout bounds, auto-layout direction, componentProperties):
|
|
55
|
+
|
|
56
|
+
### 1. Purpose
|
|
57
|
+
One paragraph. What screen is this? Primary user goal? Infer from frame name + top-level text + dominant CTA.
|
|
58
|
+
|
|
59
|
+
### 2. ASCII Layout
|
|
60
|
+
Rough spatial sketch using box characters. Reflect top-bottom / left-right ordering from absoluteBoundingBox. Keep under ~20 lines. Example:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
┌──────────────────────────────────────┐
|
|
64
|
+
│ [Logo] [Sign In] │
|
|
65
|
+
├──────────────────────────────────────┤
|
|
66
|
+
│ Welcome back │
|
|
67
|
+
│ ┌────────────────────────────────┐ │
|
|
68
|
+
│ │ email@example.com │ │
|
|
69
|
+
│ └────────────────────────────────┘ │
|
|
70
|
+
│ [ Continue ] │
|
|
71
|
+
└──────────────────────────────────────┘
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 3. Regions
|
|
75
|
+
Bulleted list of the major layout regions (header, sidebar, main, footer, modal, etc.) with a one-line purpose each. Use auto-layout frames as region hints.
|
|
76
|
+
|
|
77
|
+
### 4. Actions
|
|
78
|
+
Every interactive element the user can trigger. Derive from nodes whose name/type suggests a button, link, icon-button, menu-item, toggle, etc. Format:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
- **<Action name>** — <what it does> (source: <node name>)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 5. Form Fields
|
|
85
|
+
Every input the user can fill. Include label, type (text/email/password/select/checkbox/radio/textarea/date), required hint if inferable, and placeholder.
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
| Label | Type | Required | Placeholder |
|
|
89
|
+
|---|---|---|---|
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Omit entirely (write `_none_`) if no inputs exist.
|
|
93
|
+
|
|
94
|
+
### 6. Data Columns
|
|
95
|
+
If the screen shows a table, list, or card grid — enumerate the columns/fields displayed per row. Otherwise write `_none_`.
|
|
96
|
+
|
|
97
|
+
### 7. Navigation
|
|
98
|
+
Outgoing links, tab bars, breadcrumbs, back buttons — anything that moves the user to another screen. Include both explicit navigation components and implicit CTAs that navigate.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Synthesis Workflow
|
|
103
|
+
|
|
104
|
+
1. Read `requirements/spec_figma.md` — note `file_key`, `node_id`, `figma_version_id` from frontmatter
|
|
105
|
+
2. Read `.sungen/figma-cache/<file_key>/<figma_version_id>/<safe_node_id>-raw.json` (colons in node_id become underscores)
|
|
106
|
+
3. Traverse the tree. Collect: names, types, `characters`, `componentProperties`, `absoluteBoundingBox`
|
|
107
|
+
4. Produce the 7 sections above
|
|
108
|
+
5. **Locate the insertion point** in `spec_figma.md`:
|
|
109
|
+
- **If `<!-- SYNTHESIS-BELOW -->` is present** → replace everything from the marker (inclusive) to EOF with: the marker line, a blank line, then the 7 sections.
|
|
110
|
+
- **If the marker is NOT present** (older `spec_figma.md` pre-envelope-refactor, or hand-edited file) → locate the last non-empty line of the envelope (usually the end of `## Screenshots`), append a blank line, then write the marker, another blank line, then the 7 sections. Do NOT delete any existing envelope content.
|
|
111
|
+
- **If the file is missing entirely** → advise the user to re-run `sungen add --screen <screen> --figma <url> --refresh` to regenerate the envelope first. Do not fabricate one.
|
|
112
|
+
6. Preserve the envelope (frontmatter + Frame + Screenshots) byte-for-byte. Never touch content above the marker.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Re-synthesis
|
|
117
|
+
|
|
118
|
+
- If the envelope's `figma_version_id` changed → envelope is fresh; re-run synthesis
|
|
119
|
+
- If only the narrative is stale (user wants a rewrite) → truncate from marker to EOF and regenerate
|
|
120
|
+
- Never edit content ABOVE the marker — that is the scaffolder's territory
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Selector Heuristics (for downstream `run-test`)
|
|
125
|
+
|
|
126
|
+
During `run-test` Phase 0, provisional selectors can be seeded from the raw JSON:
|
|
127
|
+
|
|
128
|
+
| Figma Signal | Provisional YAML Entry |
|
|
129
|
+
|---|---|
|
|
130
|
+
| Node name ends `Button`, has text | `role: button` + `name: "<text>"` |
|
|
131
|
+
| Node name ends `Input`/`Field` | `placeholder: "<placeholder text>"` |
|
|
132
|
+
| Node name ends `Link`, has text | `role: link` + `name: "<text>"` |
|
|
133
|
+
| componentProperties has `data-testid` | `testid: <value>` |
|
|
134
|
+
| Plain text leaf (outside interactive) | `text: "<content>"` |
|
|
135
|
+
| Node name ends `Icon` | `role: img` + `name: "<accessible name>"` |
|
|
136
|
+
|
|
137
|
+
Every provisional entry MUST carry:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
# @needs-live-verify source=figma node_id=<id>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Provisional selectors feed `selectors.yaml` as candidates. `run-test` Phase 0 verifies them against the live page and overwrites incorrect entries.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Security
|
|
148
|
+
|
|
149
|
+
- Never include the PAT in `spec_figma.md`, selectors, test data, or any committed file
|
|
150
|
+
- Never log or echo the PAT in terminal output
|
|
151
|
+
- Read only from `.sungen/figma-cache/` and screen directories — never from `.env`
|
|
@@ -52,6 +52,67 @@ If existing selectors already cover the feature file, **skip Phase 0** and go st
|
|
|
52
52
|
|
|
53
53
|
---
|
|
54
54
|
|
|
55
|
+
## Phase 0 (Provisional): Figma-Only Selector Generation (no live page)
|
|
56
|
+
|
|
57
|
+
**Trigger**: Phase 0 decision tree (in `run-test` command) determined the live page is not reachable AND `requirements/spec_figma.md` exists.
|
|
58
|
+
|
|
59
|
+
**Goal**: produce a compilable `selectors.yaml` seeded from Figma node data so that `sungen generate` succeeds and the test suite can run. Every entry is provisional — it must be verified against a real DOM when the page becomes available.
|
|
60
|
+
|
|
61
|
+
### Inputs
|
|
62
|
+
|
|
63
|
+
- `requirements/spec_figma.md` — specifically:
|
|
64
|
+
- `## Components` table (Name, Type, Role, Text, Variants columns)
|
|
65
|
+
- `## Text Inventory` list (node_id → label text pairs)
|
|
66
|
+
|
|
67
|
+
### Steps
|
|
68
|
+
|
|
69
|
+
1. **Parse references**: collect every `[Reference]` element from the `.feature` file (same as live Phase 0 step 2).
|
|
70
|
+
2. **Match to Figma nodes**: for each `[Reference]`, find the best matching entry in `spec_figma.md` by comparing the reference name against component names and text labels (case-insensitive, partial match allowed).
|
|
71
|
+
3. **Apply heuristic priority** (same order as live Phase 0 — use first applicable):
|
|
72
|
+
|
|
73
|
+
| Priority | Type | Figma Signal |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| 1 | `testid` | Dev annotation `data-testid=X` in component metadata |
|
|
76
|
+
| 2 | `role` + name | Component type is Button/Link + has text label |
|
|
77
|
+
| 3 | `placeholder` | Component type is Input/Field + has placeholder text |
|
|
78
|
+
| 4 | `label` | Component has associated label text (not placeholder) |
|
|
79
|
+
| 5 | `locator` (CSS) | No accessible name derivable from Figma data |
|
|
80
|
+
| 6 | `text` | Plain text node (not inside interactive component) |
|
|
81
|
+
|
|
82
|
+
See `sungen-figma-source` skill for the authoritative heuristics table mapping Figma signals to YAML entry types.
|
|
83
|
+
|
|
84
|
+
4. **Write entries**: add each entry to `selectors.yaml`, prefixed with the required comment:
|
|
85
|
+
```yaml
|
|
86
|
+
# @needs-live-verify source=figma node_id=<figma-node-id>
|
|
87
|
+
submit-button:
|
|
88
|
+
type: role
|
|
89
|
+
value: button
|
|
90
|
+
name: "Submit"
|
|
91
|
+
```
|
|
92
|
+
- Key naming follows `sungen-selector-keys` conventions (lowercase, Unicode preserved, `--type` / `--N` suffixes).
|
|
93
|
+
- Copy text character-for-character from `## Text Inventory`. Never infer from the Gherkin label.
|
|
94
|
+
- Merge, don't overwrite — preserve the page selector and any user-authored entries.
|
|
95
|
+
|
|
96
|
+
5. **Compile**: `sungen generate --screen <screen>` — must succeed before Phase 1.
|
|
97
|
+
|
|
98
|
+
### Auto-fix on live page (subsequent run-test invocations)
|
|
99
|
+
|
|
100
|
+
When `run-test` is called again and the live page is now reachable:
|
|
101
|
+
- Phase 0 takes ONE `browser_snapshot`.
|
|
102
|
+
- For each entry tagged `# @needs-live-verify` in `selectors.yaml`:
|
|
103
|
+
- Compare the provisional selector against the actual DOM element found in the snapshot.
|
|
104
|
+
- If match → remove the comment line (entry promoted to verified).
|
|
105
|
+
- If mismatch → replace the YAML value with the snapshot-derived selector, then remove the comment (entry corrected and verified).
|
|
106
|
+
- Entries with no corresponding DOM element → log as unresolved, leave comment in place for manual inspection.
|
|
107
|
+
|
|
108
|
+
### Pitfalls
|
|
109
|
+
|
|
110
|
+
- Inferring selector names from Gherkin labels instead of Figma `## Text Inventory` → mismatch on live verification.
|
|
111
|
+
- Omitting `# @needs-live-verify` comment → reviewer has no way to count unverified selectors.
|
|
112
|
+
- Overwriting user-authored selectors during merge → always check for existing keys before adding.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
55
116
|
## Phase 0.5: Auth Persistence (MCP alternative to `sungen makeauth`)
|
|
56
117
|
|
|
57
118
|
Capture an authenticated session from the MCP browser into `specs/.auth/<role>.json` — the same path `sungen makeauth` writes to, which compiled tests already reference via `test.use({ storageState })` based on `@auth:<role>` tags. No `playwright.config.ts` edits needed. Run once per auth lifetime, not on every selector fix.
|
|
@@ -6,14 +6,25 @@ user-invocable: false
|
|
|
6
6
|
|
|
7
7
|
## Goal
|
|
8
8
|
|
|
9
|
-
Generate **focused test cases per screen section**
|
|
9
|
+
Generate **focused test cases per screen section** using a **tier-based approach** for faster results. Output `.feature` + `test-data.yaml` only — selectors are deferred to `/sungen:run-test`.
|
|
10
|
+
|
|
11
|
+
### Tier System
|
|
12
|
+
|
|
13
|
+
| Tier | Priority | What to generate | When |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| **Tier 1** (default) | `@critical` + `@high` | Happy paths, required validation, core business rules, security basics | First run of `create-test` |
|
|
16
|
+
| **Tier 2** (expand) | `@normal` + `@low` | UI presence, optional validation, edge cases, cosmetic checks | User runs `create-test` again with "Add viewpoints" mode |
|
|
17
|
+
|
|
18
|
+
**Round 1 (Tier 1)** targets **~10-15 scenarios per section** — enough to cover critical flows and catch real bugs. This is the default behavior.
|
|
19
|
+
|
|
20
|
+
**Round 2 (Tier 2)** expands to full coverage when the user explicitly chooses "Add viewpoints" or "Add new sections" update mode. Only then generate `@normal` + `@low` scenarios to fill coverage gaps.
|
|
10
21
|
|
|
11
22
|
## Update Mode
|
|
12
23
|
|
|
13
24
|
When `.feature` already has scenarios, summarize and ask:
|
|
14
|
-
1. **Add new sections** — append, continue numbering
|
|
15
|
-
2. **Add viewpoints** —
|
|
16
|
-
3. **Replace all** — overwrite
|
|
25
|
+
1. **Add new sections** — append new sections with Tier 2 (`@normal` + `@low`) scenarios, continue numbering
|
|
26
|
+
2. **Add viewpoints** — expand existing sections with Tier 2 (`@normal` + `@low`) scenarios
|
|
27
|
+
3. **Replace all** — overwrite with fresh Tier 1 (`@critical` + `@high`) generation
|
|
17
28
|
|
|
18
29
|
For append: read highest `VP-<CAT>-<NNN>`, continue from next number. Never modify existing scenarios.
|
|
19
30
|
|
|
@@ -28,14 +39,28 @@ Requirements improve every viewpoint: exact error messages for VAL, business rul
|
|
|
28
39
|
|
|
29
40
|
If also exploring live page: verify spec vs actual, flag mismatches, capture exact text.
|
|
30
41
|
|
|
42
|
+
### Figma supplement (`spec_figma.md`)
|
|
43
|
+
|
|
44
|
+
When `requirements/spec_figma.md` is present alongside `spec.md`, treat it as a **secondary input** with these rules:
|
|
45
|
+
|
|
46
|
+
- **Never override `spec.md`**: `spec.md` is authoritative for all business rules, field constraints, and behavior. `spec_figma.md` only supplements with visual/text data that `spec.md` may lack.
|
|
47
|
+
- **`## Text Inventory` → literal strings**: use text label values from this section verbatim in `test-data.yaml` (button labels, input placeholders, error messages shown in Figma). Do not paraphrase or invent alternatives.
|
|
48
|
+
- **`## Interaction States` → state coverage checkpoints**: use the listed variants (e.g., empty, loading, error, success) as a checklist for state-coverage scenarios. Only generate scenarios for states that are either (a) confirmed in both `spec.md` and `spec_figma.md`, or (b) explicitly documented in one source without contradiction from the other.
|
|
49
|
+
- **Flag disagreements**: if a field name, label, or behavior in `spec_figma.md` contradicts `spec.md`, insert an HTML comment at the top of the `.feature` file:
|
|
50
|
+
```gherkin
|
|
51
|
+
<!-- FIGMA-SPEC CONFLICT: <brief description> — using spec.md value -->
|
|
52
|
+
```
|
|
53
|
+
Then proceed using the `spec.md` value.
|
|
54
|
+
|
|
31
55
|
## Screen Input Sources
|
|
32
56
|
|
|
33
|
-
**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
57
|
+
**Auto-detect** — the parent command (`create-test`) resolves visual sources before invoking this skill. By the time generation starts, the available sources are already determined:
|
|
58
|
+
- `spec.md` — primary, always read if present
|
|
59
|
+
- `spec_figma.md` — Figma supplement, read if present (PAT flow already completed)
|
|
60
|
+
- `ui/*.png` — visual context, read if present
|
|
61
|
+
- `test-viewpoint.md` — edge cases and known issues, read if present
|
|
37
62
|
|
|
38
|
-
**
|
|
63
|
+
**IMPORTANT:** If `spec_figma.md` exists, do NOT call any `mcp__figma__*` tool. The PAT flow is complete — just read the file.
|
|
39
64
|
|
|
40
65
|
**Single screen focus**: one URL = one screen. Don't explore sibling paths. Modals on same page = part of this screen.
|
|
41
66
|
|
|
@@ -76,7 +101,9 @@ Apply `sungen-test-design-techniques` to spec-extracted conditions:
|
|
|
76
101
|
|
|
77
102
|
Use `sungen-viewpoint` skill for per-pattern checklists across 4 viewpoints: UI/UX, Data & Validate, Logic, Security.
|
|
78
103
|
|
|
79
|
-
|
|
104
|
+
**Tier-aware gap filling:**
|
|
105
|
+
- **Tier 1 (first run)**: only add `@critical` and `@high` items from the checklists — core security checks (VP-SEC), required field validation (VP-VAL), key state transitions (VP-LOGIC). Skip `@normal`/`@low` items like hover states, empty states, tooltips.
|
|
106
|
+
- **Tier 2 (expand run)**: add `@normal` + `@low` scenarios — UI presence, optional validation, edge cases, cosmetic checks, keyboard nav, hover effects.
|
|
80
107
|
|
|
81
108
|
**Validation rule**: capture actual error messages from live page or spec.md. Use `User see {{error_var}}` — never assert just "is visible".
|
|
82
109
|
|
|
@@ -168,13 +195,14 @@ Feature: <Screen> Screen
|
|
|
168
195
|
When User click [Create] button
|
|
169
196
|
Then User see [Form] dialog
|
|
170
197
|
|
|
171
|
-
# --- Section: Create User Form ---
|
|
198
|
+
# --- Section: Create User Form (Tier 1: @critical + @high) ---
|
|
172
199
|
|
|
173
|
-
@
|
|
174
|
-
Scenario: VP-
|
|
200
|
+
@critical @extend:open_form
|
|
201
|
+
Scenario: VP-LOGIC-001 Submit form with valid data creates record
|
|
175
202
|
Given User is on [Form] dialog
|
|
176
|
-
|
|
177
|
-
And User
|
|
203
|
+
When User fill [Name] field with {{valid_name}}
|
|
204
|
+
And User click [Submit] button
|
|
205
|
+
Then User see {{success_message}} message
|
|
178
206
|
|
|
179
207
|
@high @extend:open_form
|
|
180
208
|
Scenario: VP-VAL-001 Submit with all empty fields shows errors
|
|
@@ -182,11 +210,7 @@ Feature: <Screen> Screen
|
|
|
182
210
|
When User click [Submit] button
|
|
183
211
|
Then User see [Name error] message with {{name_required_error}}
|
|
184
212
|
|
|
185
|
-
# --- Section: User Table ---
|
|
186
|
-
|
|
187
|
-
@normal
|
|
188
|
-
Scenario: VP-UI-010 Table displays all columns
|
|
189
|
-
Then User see [Name] column in [Users] table
|
|
213
|
+
# --- Section: User Table (Tier 1: @critical + @high) ---
|
|
190
214
|
|
|
191
215
|
@high
|
|
192
216
|
Scenario: VP-VAL-010 Table displays correct data
|
|
@@ -194,13 +218,15 @@ Feature: <Screen> Screen
|
|
|
194
218
|
| Name | Email |
|
|
195
219
|
| {{name_1}} | {{email_1}} |
|
|
196
220
|
|
|
197
|
-
@
|
|
198
|
-
Scenario: VP-
|
|
199
|
-
Given User
|
|
200
|
-
When User
|
|
201
|
-
Then User
|
|
221
|
+
@critical
|
|
222
|
+
Scenario: VP-SEC-010 Unauthorized user cannot access page
|
|
223
|
+
Given User is not logged in
|
|
224
|
+
When User navigate to [Screen] page
|
|
225
|
+
Then User is on [Login] page
|
|
202
226
|
```
|
|
203
227
|
|
|
228
|
+
**Tier 2 (expand run)** adds `@normal` + `@low` scenarios like UI field presence, hover states, tooltips, empty states.
|
|
229
|
+
|
|
204
230
|
### When to use DataTable vs Row Scope
|
|
205
231
|
|
|
206
232
|
| Pattern | Use when |
|
|
@@ -43,6 +43,8 @@ Score: `(dimensions_covered / 6) * 40`. Validate technique application with `sun
|
|
|
43
43
|
|
|
44
44
|
**Classification**: UI = static/always-same appearance. VAL = input validation/errors. LOGIC = behavior/state changes (includes persisted state without When). SEC = auth/permissions.
|
|
45
45
|
|
|
46
|
+
**Tier-aware scoring**: If the feature file only contains `@critical` + `@high` scenarios (Tier 1), do NOT penalize for missing VP-UI viewpoint — UI scenarios are intentionally deferred to Tier 2. Score "All applicable VP present" based on Tier 1-relevant viewpoints only (VAL, LOGIC, SEC). Note in the review output: *"VP-UI deferred to Tier 2 — run create-test with 'Add viewpoints' to expand."*
|
|
47
|
+
|
|
46
48
|
---
|
|
47
49
|
|
|
48
50
|
## Quality Rules
|
|
@@ -87,6 +89,21 @@ Do NOT mark `@manual` when data is visible in snapshot or documented in spec —
|
|
|
87
89
|
|
|
88
90
|
---
|
|
89
91
|
|
|
92
|
+
## Unverified Selectors metric
|
|
93
|
+
|
|
94
|
+
**When to check**: if `qa/screens/<screen>/selectors/<screen>.yaml` exists, count lines matching the pattern `@needs-live-verify`.
|
|
95
|
+
|
|
96
|
+
| Metric | Source | Scoring impact |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| Unverified Selectors | Count of `@needs-live-verify` comment lines in `selectors.yaml` | None — non-blocking |
|
|
99
|
+
|
|
100
|
+
- If count > 0: include the following line in the review report summary (after the score table, before Issues):
|
|
101
|
+
`⚠ <N> selectors flagged @needs-live-verify — run run-test against live URL when available.`
|
|
102
|
+
- Does NOT reduce the score or block the 60% threshold. The suite can PASS with unverified selectors.
|
|
103
|
+
- If `selectors.yaml` does not exist yet (not yet generated): omit this metric entirely.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
90
107
|
## Output Format
|
|
91
108
|
|
|
92
109
|
```markdown
|
|
@@ -99,6 +116,9 @@ Do NOT mark `@manual` when data is visible in snapshot or documented in spec —
|
|
|
99
116
|
| Viewpoint | <n> | 30 |
|
|
100
117
|
| **Total** | **<n>%** | **100** |
|
|
101
118
|
|
|
119
|
+
⚠ <N> selectors flagged @needs-live-verify — run run-test against live URL when available.
|
|
120
|
+
<!-- omit this line if selectors.yaml doesn't exist or @needs-live-verify count = 0 -->
|
|
121
|
+
|
|
102
122
|
### Issues
|
|
103
123
|
1. [SYNTAX] ...
|
|
104
124
|
2. [COVERAGE] ...
|