@sun-asterisk/sungen 3.2.33 → 3.2.34

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 (210) hide show
  1. package/dist/cli/commands/audit.d.ts +4 -0
  2. package/dist/cli/commands/audit.d.ts.map +1 -1
  3. package/dist/cli/commands/audit.js +16 -3
  4. package/dist/cli/commands/audit.js.map +1 -1
  5. package/dist/cli/commands/changed.d.ts.map +1 -1
  6. package/dist/cli/commands/changed.js +2 -3
  7. package/dist/cli/commands/changed.js.map +1 -1
  8. package/dist/cli/commands/dashboard.d.ts.map +1 -1
  9. package/dist/cli/commands/dashboard.js +2 -28
  10. package/dist/cli/commands/dashboard.js.map +1 -1
  11. package/dist/cli/commands/delivery.d.ts.map +1 -1
  12. package/dist/cli/commands/delivery.js +40 -35
  13. package/dist/cli/commands/delivery.js.map +1 -1
  14. package/dist/cli/commands/results-merge.d.ts +9 -0
  15. package/dist/cli/commands/results-merge.d.ts.map +1 -1
  16. package/dist/cli/commands/results-merge.js +7 -0
  17. package/dist/cli/commands/results-merge.js.map +1 -1
  18. package/dist/cli/commands/select.d.ts +12 -0
  19. package/dist/cli/commands/select.d.ts.map +1 -0
  20. package/dist/cli/commands/select.js +122 -0
  21. package/dist/cli/commands/select.js.map +1 -0
  22. package/dist/cli/commands/update.d.ts.map +1 -1
  23. package/dist/cli/commands/update.js +3 -0
  24. package/dist/cli/commands/update.js.map +1 -1
  25. package/dist/cli/index.js +7 -2
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/dashboard/templates/index.html +1 -1
  28. package/dist/dashboard/types.d.ts +1 -0
  29. package/dist/dashboard/types.d.ts.map +1 -1
  30. package/dist/exporters/csv-exporter.d.ts.map +1 -1
  31. package/dist/exporters/csv-exporter.js +11 -10
  32. package/dist/exporters/csv-exporter.js.map +1 -1
  33. package/dist/exporters/json-exporter.d.ts.map +1 -1
  34. package/dist/exporters/json-exporter.js +7 -0
  35. package/dist/exporters/json-exporter.js.map +1 -1
  36. package/dist/exporters/manual-hybrid-oracle.d.ts +54 -0
  37. package/dist/exporters/manual-hybrid-oracle.d.ts.map +1 -0
  38. package/dist/exporters/manual-hybrid-oracle.js +114 -0
  39. package/dist/exporters/manual-hybrid-oracle.js.map +1 -0
  40. package/dist/exporters/matrix/build.d.ts.map +1 -1
  41. package/dist/exporters/matrix/build.js +6 -2
  42. package/dist/exporters/matrix/build.js.map +1 -1
  43. package/dist/exporters/matrix/export.d.ts +3 -0
  44. package/dist/exporters/matrix/export.d.ts.map +1 -1
  45. package/dist/exporters/matrix/export.js +1 -0
  46. package/dist/exporters/matrix/export.js.map +1 -1
  47. package/dist/exporters/matrix/gates.js +6 -0
  48. package/dist/exporters/matrix/gates.js.map +1 -1
  49. package/dist/exporters/matrix/render-testcase-sheet.d.ts.map +1 -1
  50. package/dist/exporters/matrix/render-testcase-sheet.js +10 -4
  51. package/dist/exporters/matrix/render-testcase-sheet.js.map +1 -1
  52. package/dist/exporters/matrix/types.d.ts +8 -1
  53. package/dist/exporters/matrix/types.d.ts.map +1 -1
  54. package/dist/exporters/matrix/types.js.map +1 -1
  55. package/dist/exporters/matrix/wording.d.ts +1 -1
  56. package/dist/exporters/matrix/wording.d.ts.map +1 -1
  57. package/dist/exporters/matrix/wording.js +10 -1
  58. package/dist/exporters/matrix/wording.js.map +1 -1
  59. package/dist/exporters/run-environment.d.ts +32 -0
  60. package/dist/exporters/run-environment.d.ts.map +1 -0
  61. package/dist/exporters/run-environment.js +125 -0
  62. package/dist/exporters/run-environment.js.map +1 -0
  63. package/dist/exporters/scenario-merger.d.ts +18 -0
  64. package/dist/exporters/scenario-merger.d.ts.map +1 -1
  65. package/dist/exporters/scenario-merger.js +47 -3
  66. package/dist/exporters/scenario-merger.js.map +1 -1
  67. package/dist/exporters/test-data-resolver.d.ts +0 -4
  68. package/dist/exporters/test-data-resolver.d.ts.map +1 -1
  69. package/dist/exporters/test-data-resolver.js +0 -7
  70. package/dist/exporters/test-data-resolver.js.map +1 -1
  71. package/dist/generators/gherkin-parser/index.d.ts +11 -4
  72. package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
  73. package/dist/generators/gherkin-parser/index.js +49 -19
  74. package/dist/generators/gherkin-parser/index.js.map +1 -1
  75. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +4 -0
  76. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  77. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +1 -1
  78. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -1
  79. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/pick-option.hbs +13 -0
  80. package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +16 -0
  81. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  82. package/dist/generators/test-generator/code-generator.js +23 -2
  83. package/dist/generators/test-generator/code-generator.js.map +1 -1
  84. package/dist/generators/test-generator/diagnostics.d.ts +3 -1
  85. package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
  86. package/dist/generators/test-generator/diagnostics.js +3 -1
  87. package/dist/generators/test-generator/diagnostics.js.map +1 -1
  88. package/dist/harness/audit.d.ts +3 -0
  89. package/dist/harness/audit.d.ts.map +1 -1
  90. package/dist/harness/audit.js +17 -8
  91. package/dist/harness/audit.js.map +1 -1
  92. package/dist/harness/data-driven-lint.d.ts.map +1 -1
  93. package/dist/harness/data-driven-lint.js +69 -27
  94. package/dist/harness/data-driven-lint.js.map +1 -1
  95. package/dist/harness/next-step.d.ts.map +1 -1
  96. package/dist/harness/next-step.js +1 -0
  97. package/dist/harness/next-step.js.map +1 -1
  98. package/dist/harness/parse.d.ts +24 -0
  99. package/dist/harness/parse.d.ts.map +1 -1
  100. package/dist/harness/parse.js +117 -13
  101. package/dist/harness/parse.js.map +1 -1
  102. package/dist/harness/quality-gates.d.ts.map +1 -1
  103. package/dist/harness/quality-gates.js +6 -4
  104. package/dist/harness/quality-gates.js.map +1 -1
  105. package/dist/harness/read-text.d.ts +15 -0
  106. package/dist/harness/read-text.d.ts.map +1 -1
  107. package/dist/harness/read-text.js +25 -0
  108. package/dist/harness/read-text.js.map +1 -1
  109. package/dist/harness/select-by-ids.d.ts +31 -0
  110. package/dist/harness/select-by-ids.d.ts.map +1 -0
  111. package/dist/harness/select-by-ids.js +106 -0
  112. package/dist/harness/select-by-ids.js.map +1 -0
  113. package/dist/harness/sensors.d.ts +8 -1
  114. package/dist/harness/sensors.d.ts.map +1 -1
  115. package/dist/harness/sensors.js +61 -9
  116. package/dist/harness/sensors.js.map +1 -1
  117. package/dist/harness/spec-branches.js +1 -1
  118. package/dist/harness/spec-branches.js.map +1 -1
  119. package/dist/harness/ui-inventory.d.ts +40 -0
  120. package/dist/harness/ui-inventory.d.ts.map +1 -0
  121. package/dist/harness/ui-inventory.js +191 -0
  122. package/dist/harness/ui-inventory.js.map +1 -0
  123. package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
  124. package/dist/harness/viewpoint-ledger.js +64 -9
  125. package/dist/harness/viewpoint-ledger.js.map +1 -1
  126. package/dist/orchestrator/screen-manager.d.ts.map +1 -1
  127. package/dist/orchestrator/screen-manager.js +3 -11
  128. package/dist/orchestrator/screen-manager.js.map +1 -1
  129. package/dist/orchestrator/templates/ai-src/agents/discovery.md +11 -3
  130. package/dist/orchestrator/templates/ai-src/agents/reviewer.md +8 -0
  131. package/dist/orchestrator/templates/ai-src/commands/create-test.md +2 -2
  132. package/dist/orchestrator/templates/ai-src/commands/review.md +2 -2
  133. package/dist/orchestrator/templates/ai-src/commands/run-test.md +70 -13
  134. package/dist/orchestrator/templates/ai-src/skills/sungen-capture/mode-local.md +2 -2
  135. package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +20 -0
  136. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +17 -8
  137. package/dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +58 -14
  138. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +41 -1
  139. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -0
  140. package/dist/orchestrator/templates/playwright.config.ts +4 -2
  141. package/dist/orchestrator/templates/specs-url-assert.d.ts.map +1 -1
  142. package/dist/orchestrator/templates/specs-url-assert.js +24 -2
  143. package/dist/orchestrator/templates/specs-url-assert.js.map +1 -1
  144. package/dist/orchestrator/templates/specs-url-assert.ts +23 -2
  145. package/dist/orchestrator/trace-mode-install.d.ts +14 -0
  146. package/dist/orchestrator/trace-mode-install.d.ts.map +1 -0
  147. package/dist/orchestrator/trace-mode-install.js +132 -0
  148. package/dist/orchestrator/trace-mode-install.js.map +1 -0
  149. package/dist/orchestrator/viewpoint-pattern-catalog.d.ts +20 -0
  150. package/dist/orchestrator/viewpoint-pattern-catalog.d.ts.map +1 -0
  151. package/dist/orchestrator/viewpoint-pattern-catalog.js +45 -0
  152. package/dist/orchestrator/viewpoint-pattern-catalog.js.map +1 -0
  153. package/package.json +3 -3
  154. package/src/cli/commands/audit.ts +14 -3
  155. package/src/cli/commands/changed.ts +2 -4
  156. package/src/cli/commands/dashboard.ts +1 -26
  157. package/src/cli/commands/delivery.ts +37 -32
  158. package/src/cli/commands/results-merge.ts +7 -1
  159. package/src/cli/commands/select.ts +88 -0
  160. package/src/cli/commands/update.ts +3 -0
  161. package/src/cli/index.ts +7 -2
  162. package/src/dashboard/templates/index.html +1 -1
  163. package/src/dashboard/types.ts +1 -0
  164. package/src/exporters/csv-exporter.ts +7 -10
  165. package/src/exporters/json-exporter.ts +6 -1
  166. package/src/exporters/manual-hybrid-oracle.ts +112 -0
  167. package/src/exporters/matrix/build.ts +6 -2
  168. package/src/exporters/matrix/export.ts +4 -0
  169. package/src/exporters/matrix/gates.ts +6 -0
  170. package/src/exporters/matrix/render-testcase-sheet.ts +10 -4
  171. package/src/exporters/matrix/types.ts +8 -1
  172. package/src/exporters/matrix/wording.ts +10 -1
  173. package/src/exporters/run-environment.ts +89 -0
  174. package/src/exporters/scenario-merger.ts +49 -4
  175. package/src/exporters/test-data-resolver.ts +0 -6
  176. package/src/generators/gherkin-parser/index.ts +50 -18
  177. package/src/generators/test-generator/adapters/adapter-interface.ts +4 -0
  178. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +1 -1
  179. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -1
  180. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/pick-option.hbs +13 -0
  181. package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +16 -0
  182. package/src/generators/test-generator/code-generator.ts +23 -2
  183. package/src/generators/test-generator/diagnostics.ts +3 -1
  184. package/src/harness/audit.ts +20 -9
  185. package/src/harness/data-driven-lint.ts +82 -24
  186. package/src/harness/next-step.ts +1 -0
  187. package/src/harness/parse.ts +123 -16
  188. package/src/harness/quality-gates.ts +6 -4
  189. package/src/harness/read-text.ts +25 -0
  190. package/src/harness/select-by-ids.ts +83 -0
  191. package/src/harness/sensors.ts +59 -9
  192. package/src/harness/spec-branches.ts +1 -1
  193. package/src/harness/ui-inventory.ts +164 -0
  194. package/src/harness/viewpoint-ledger.ts +57 -11
  195. package/src/orchestrator/screen-manager.ts +3 -11
  196. package/src/orchestrator/templates/ai-src/agents/discovery.md +11 -3
  197. package/src/orchestrator/templates/ai-src/agents/reviewer.md +8 -0
  198. package/src/orchestrator/templates/ai-src/commands/create-test.md +2 -2
  199. package/src/orchestrator/templates/ai-src/commands/review.md +2 -2
  200. package/src/orchestrator/templates/ai-src/commands/run-test.md +70 -13
  201. package/src/orchestrator/templates/ai-src/skills/sungen-capture/mode-local.md +2 -2
  202. package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +20 -0
  203. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +17 -8
  204. package/src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +58 -14
  205. package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +41 -1
  206. package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -0
  207. package/src/orchestrator/templates/playwright.config.ts +4 -2
  208. package/src/orchestrator/templates/specs-url-assert.ts +23 -2
  209. package/src/orchestrator/trace-mode-install.ts +94 -0
  210. package/src/orchestrator/viewpoint-pattern-catalog.ts +58 -0
@@ -629,6 +629,7 @@ on mobile a dialog-scoped ref still resolves against the whole screen (`SG-W021`
629
629
  | Tag | Effect |
630
630
  |---|---|
631
631
  | `@spec:<id>` | **Traceability**: this scenario proves requirement `<id>` from `requirements/spec.md` (`@spec:FR-003`). Repeatable — a scenario may prove several. Read by `sungen audit` (requirement coverage) and by delivery (the Coverage sheet's requirement table). Without it the link is only inferred from wording and cannot survive an edit. |
632
+ | `@ui:<UI-NNN>` | **Design traceability**: this scenario proves design item `UI-NNN` from `requirements/ui-inventory.md` (`@ui:UI-014`). Repeatable. Read by `sungen audit` (`UI-ITEM-UNCOVERED`). An item deliberately not tested is recorded as a comment instead: `# UI-DEFERRED: UI-002..013 — <reason>`. Rules: `sungen-tc-generation` § Design Inventory. |
632
633
  | `@manual` | Skip in generation |
633
634
  | `@known-defect` | The scenario is EXPECTED to be red — it asserts a live defect. It still runs and still reports as failed (never skipped, never "fixed"), and it stays a pass-through tag so `--grep @known-defect` selects it. **`[mobile]`** Its failure does NOT escalate the next scenario's `@reset:` tier: a red that was designed in is not evidence of leftover state |
634
635
  | `@auth:role` | Use auth storage state for role |
@@ -640,7 +641,8 @@ on mobile a dialog-scoped ref still resolves against the whole screen (`SG-W021`
640
641
  | `@cleanup:scroll` | Auto-cleanup: scroll to top after each test (cleanupPage) |
641
642
  | `@cleanup:storage` | Auto-cleanup: clear sessionStorage after each test (cleanupPage) |
642
643
  | `@screenshot:on-failure` | Auto-capture screenshot when test fails (base.ts fixture) |
643
- | `@parallel` | Opt-out: fresh page per test instead of serial default (for independent scenarios). Compiles on mobile too, but a single device/emulator gets no session-isolation benefit from it |
644
+ | `@serial` | Opt-in: one shared page for an ordered, genuinely stateful sequence → `test.describe.serial()`. A failure skips the rest |
645
+ | `@parallel` | Names the default (fresh page per test) — changes nothing. Compiles on mobile too, but a single device/emulator gets no session-isolation benefit from it |
644
646
  | `@beforeAll` | Hook: runs once before all tests → `test.beforeAll()` |
645
647
  | `@afterEach` | Hook: runs after each test → `test.afterEach()` (custom cleanup) |
646
648
  | `@afterAll` | Hook: runs once after all tests → `test.afterAll()` |
@@ -774,14 +776,14 @@ npx playwright test --grep "@smoke|@high" # smoke OR high
774
776
 
775
777
  ### Serial vs Parallel (test execution mode)
776
778
 
777
- **Default: serial** — `test.describe.serial()` with shared page. Background runs once in `beforeAll`. Fail → skip remaining.
779
+ **Default: isolated** — `test.describe()` with a fresh page per test. Background runs as `beforeEach`; a failing scenario does not skip the others. Write every scenario so it stands alone — no scenario may rely on state another one left behind. `@parallel` only names this default.
778
780
 
779
- **`@parallel` opt-out** — `test.describe()` with fresh page per test. Background runs as `beforeEach`. Use when scenarios are truly independent (validation rules, permission tests).
781
+ **`@serial` opt-in** — `test.describe.serial()` with one shared page. Background runs once in `beforeAll`; a failure skips the rest. Use it only for a genuinely stateful, ordered sequence.
780
782
 
781
783
  | Mode | Generated | Page | Background | On fail |
782
784
  |---|---|---|---|---|
783
- | Serial (default) | `test.describe.serial()` | Shared | `beforeAll` (1 goto) | Skip remaining |
784
- | `@parallel` | `test.describe()` | Fresh per test | `beforeEach` (N goto) | Continue |
785
+ | Isolated (default, `@parallel`) | `test.describe()` | Fresh per test | `beforeEach` (N goto) | Continue |
786
+ | `@serial` | `test.describe.serial()` | Shared | `beforeAll` (1 goto) | Skip remaining |
785
787
 
786
788
  **Multiple auth groups need the default isolation.** A feature mixing `@auth:user` with `@no-auth` compiles as-is — features are parallel by default, and `@parallel` only names that default. What breaks it is `@serial`: one shared browser context cannot carry two different sessions, so the compiler errors and asks you to drop `@serial` or split the feature.
787
789
 
@@ -942,7 +944,13 @@ Feature: User Management
942
944
 
943
945
  ### Layer 2: `@afterEach` scenario (custom cleanup)
944
946
 
945
- Only when `@cleanup:*` tags aren't enough — feature-specific logic.
947
+ Only when `@cleanup:*` tags aren't enough — feature-specific logic. `@afterEach` gets the per-test
948
+ `page`, so UI cleanup steps work in it.
949
+
950
+ It runs after every test it applies to — and it does NOT apply to the `@no-auth` group when the
951
+ feature mixes `@no-auth` with other scenarios: an anonymous test has an empty session, so a cleanup
952
+ that needs the signed-in page would fail it although its own steps passed. The hook is emitted inside
953
+ each other group instead. A feature whose scenarios are ALL `@no-auth` keeps the hook for them.
946
954
 
947
955
  ### Layer 3: `@beforeAll` / `@afterAll` (optional)
948
956
 
@@ -967,8 +975,9 @@ Scenario: drop the seeded data after the last scenario
967
975
  recorded and the next step still runs; a failing action step (`Given`/`When`) stops the hook there.
968
976
  The hook fails ONCE with the full list (`Hook preconditions not met`), not with the first failure.
969
977
  - `@cases` and `@extend` are not supported on a hook — they are ignored with a compile warning.
970
- - A hook has no `page` fixture on a per-scenario (non-`@serial`) feature — keep its steps to `@api:`/
971
- `@query:` preconditions and `expect` assertions there.
978
+ - `@beforeAll` / `@afterAll` have no `page` fixture on an isolated (non-`@serial`) feature — keep
979
+ their steps to `@api:`/`@query:` preconditions and `expect` assertions there. `@afterEach` does get
980
+ the per-test `page`.
972
981
 
973
982
  **Rendering order in `.spec.ts`:**
974
983
  `test.describe` → `test.use(storageState)` → `test.use(autoCleanup)` → `test.beforeAll` → `test.beforeEach` → `test.afterEach` → `test.afterAll` → `test()` blocks.
@@ -225,12 +225,33 @@ Skip if `specs/.auth/<role>.json` already exists and a probe navigation reaches
225
225
 
226
226
  ---
227
227
 
228
+ ## Where each wave writes its result
229
+
230
+ `sungen delivery` reads the per-target result file (`specs/generated/<name>/<name>-test-result.json`),
231
+ which the JSON reporter in `playwright.config.ts` writes. Keep it that way in every wave:
232
+
233
+ - **Never pass `--reporter`** — it replaces the config's reporters, the JSON reporter is switched off, and the run writes no result file.
234
+ - **Subset waves (Phase 1–2) write to `test-results/sungen-wave.json`** — never to the per-target file (a subset would overwrite the unit's full result) and never to the default `test-results/results.json` (delivery falls back to that file when a per-target one is missing, so a 5-scenario smoke would read as the unit's result). `test-results/` is Playwright's output dir, wiped on every run — nothing to clean up.
235
+ - **Full waves (Phase 3–4) write the per-target file** — the Phase 4 file is the result delivery shows.
236
+ - **Scope every run to the unit** — `specs/generated/<name>/` (flow: `specs/generated/flows/<name>/`). Without a path, `--grep` runs every unit in `specs/generated/`.
237
+
238
+ ### Fix retries re-run only what the wave left red (Phase 2–3)
239
+
240
+ - **The first run of a phase is its full wave.** Each **fix retry** is the same command plus `--last-failed`, written to `test-results/sungen-wave.json` — never to the per-target file.
241
+ - **Retry immediately after the run whose failures you fixed.** `--last-failed` reads the failures of the *previous run only*: run any other test in between (a `-g` debug run) and the list now describes that run. If you did, re-run the full wave instead.
242
+ - **Nothing left red → no retry.** On an empty list Playwright prints "No tests found", exits 1 and still writes a zero-test report — that is not a failure of the unit, and it is why a retry never writes the per-target file.
243
+ - **A locale run (`SUNGEN_ENV=<env>`) writes `test-results/sungen-wave.<env>.json`** — the config inserts the env before `.json`; it is still a scratch file, nothing reads it.
244
+ - **A retry does not show whether your fix broke a test that was green.** Phase 3's full first run catches a Phase 2 fix that did; Phase 4 catches a Phase 3 one.
245
+
246
+ ---
247
+
228
248
  ## Phase 1: Smoke Check (catch fundamentals)
229
249
 
230
250
  Run **up to 5 scenarios** — pick the first `@high` scenarios in the feature file.
231
251
 
232
252
  ```bash
233
- npx playwright test --grep "VP-.*-001|VP-.*-002|VP-.*-003|VP-.*-004|VP-.*-005" --reporter=line
253
+ PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/sungen-wave.json \
254
+ npx playwright test specs/generated/<name>/ --grep "VP-.*-001|VP-.*-002|VP-.*-003|VP-.*-004|VP-.*-005"
234
255
  ```
235
256
 
236
257
  **Purpose:** Detect broken fundamentals before running 50+ tests:
@@ -248,7 +269,15 @@ npx playwright test --grep "VP-.*-001|VP-.*-002|VP-.*-003|VP-.*-004|VP-.*-005" -
248
269
  Run all `@high` scenarios:
249
270
 
250
271
  ```bash
251
- npx playwright test --grep "@high" --reporter=line
272
+ PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/sungen-wave.json \
273
+ npx playwright test specs/generated/<name>/ --grep "@high"
274
+ ```
275
+
276
+ Fix retry — only the scenarios this wave left red:
277
+
278
+ ```bash
279
+ PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/sungen-wave.json \
280
+ npx playwright test specs/generated/<name>/ --grep "@high" --last-failed
252
281
  ```
253
282
 
254
283
  If your Playwright config doesn't support tag grep, use scenario name grep from the feature file — collect VP IDs of `@high` scenarios.
@@ -261,12 +290,24 @@ Max 2 fix attempts in this phase.
261
290
 
262
291
  ## Phase 3: Full Run (@normal + @low)
263
292
 
264
- Run remaining scenarios:
293
+ Run remaining scenarios — the whole unit, into its per-target result file:
265
294
 
266
295
  ```bash
267
- npx playwright test --reporter=line
296
+ PLAYWRIGHT_JSON_OUTPUT_NAME=specs/generated/<name>/<name>-test-result.json \
297
+ npx playwright test specs/generated/<name>/<name>.spec.ts
268
298
  ```
269
299
 
300
+ A multi-feature screen (one result file per feature) or a locale run (`SUNGEN_ENV`): use the loop in `run-test` § "Playwright command guidelines".
301
+
302
+ Fix retry — the failures only, into the wave file (the per-target file keeps this phase's full run until Phase 4 rewrites it):
303
+
304
+ ```bash
305
+ PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/sungen-wave.json \
306
+ npx playwright test specs/generated/<name>/<name>.spec.ts --last-failed
307
+ ```
308
+
309
+ **Multi-feature screen — no `--last-failed` here.** Phase 3 ran one Playwright run per feature spec, so the failure list holds only the LAST spec's failures; a retry would skip every earlier feature's red tests without a word. Re-run the per-spec loop instead.
310
+
270
311
  Many selectors already fixed from Phase 2 (shared elements). Only diagnose **new** failures — selectors that only appear in lower-priority scenarios.
271
312
 
272
313
  Max 1 fix attempt. If `@low` scenarios still fail after fix → **report and move on**, don't loop.
@@ -275,12 +316,15 @@ Max 1 fix attempt. If `@low` scenarios still fail after fix → **report and mov
275
316
 
276
317
  ## Phase 4: Regression
277
318
 
278
- One final full run to confirm all phases together:
319
+ One final full run to confirm all phases together — this per-target file is the result `sungen delivery` reads:
279
320
 
280
321
  ```bash
281
- npx playwright test --reporter=line
322
+ PLAYWRIGHT_JSON_OUTPUT_NAME=specs/generated/<name>/<name>-test-result.json \
323
+ npx playwright test specs/generated/<name>/<name>.spec.ts
282
324
  ```
283
325
 
326
+ Same multi-feature / locale form as Phase 3.
327
+
284
328
  Report results. Do NOT enter another fix loop here.
285
329
 
286
330
  ---
@@ -458,13 +502,13 @@ user detail:
458
502
 
459
503
  ## Attempt Budget Summary
460
504
 
461
- | Phase | What runs | Max fix attempts | On failure after max |
462
- |---|---|---|---|
463
- | 0. Pre-gen | Playwright MCP snapshot → write selectors.yaml | 1 snapshot | Ask user — skip or retry navigation |
464
- | 0.5. Auth | Manual login in MCP browser → `browser_storage_state` → `specs/.auth/<role>.json` | 1 login | Ask user — retry login or fall back to `sungen makeauth` |
465
- | 1. Smoke | First 5 @high | 2 | Ask user — fundamentals broken |
466
- | 2. Priority | All @high | 2 | Report failures, continue to Phase 3 |
467
- | 3. Full | All tests | 1 | Report @low/@normal failures, continue |
468
- | 4. Regression | All tests | 0 | Report final results |
505
+ | Phase | What runs | Fix retry runs | Max fix attempts | On failure after max |
506
+ |---|---|---|---|---|
507
+ | 0. Pre-gen | Playwright MCP snapshot → write selectors.yaml | — | 1 snapshot | Ask user — skip or retry navigation |
508
+ | 0.5. Auth | Manual login in MCP browser → `browser_storage_state` → `specs/.auth/<role>.json` | — | 1 login | Ask user — retry login or fall back to `sungen makeauth` |
509
+ | 1. Smoke | First 5 @high | the same 5 | 2 | Ask user — fundamentals broken |
510
+ | 2. Priority | All @high | `--last-failed` | 2 | Report failures, continue to Phase 3 |
511
+ | 3. Full | All tests | `--last-failed` (multi-feature screen: the per-spec loop again) | 1 | Report @low/@normal failures, continue |
512
+ | 4. Regression | All tests | — | 0 | Report final results |
469
513
 
470
514
  **Total worst case: 5 fix attempts** (2+2+1), not unbounded loops. Phases 0 and 0.5 don't count toward fix budget.
@@ -154,7 +154,9 @@ For append: read highest `VP-<CAT>-<NNN>`, continue from next number. Never modi
154
154
  Auto-detected by `create-test` before invoking this skill:
155
155
  - `spec.md` — primary, always read if present
156
156
  - `spec_figma.md` — Figma supplement (PAT flow already done — just read the file)
157
- - `ui/*.png` — visual context
157
+ - `ui/*.{png,jpg,jpeg,webp,gif}` — design images. **Every one is read**, and turned into the Design Inventory below — not just "visual context".
158
+ - `ui/figma-meta.md` — Figma MCP capture (`sungen-capture` mode figma-mcp): `## Components` and `## Text Content` feed the Design Inventory; `## Text Content` also supplies exact labels for `test-data.yaml`.
159
+ - `ui-inventory.md` — the Design Inventory (written by create-test, see § Design Inventory). When it already exists, keep its ids and append new items; never renumber.
158
160
  - `test-viewpoint.md` — test conditions checklist; scan entirely regardless of format.
159
161
  Format varies across projects: hierarchical table (Level 1–4 columns), flat checklist,
160
162
  prose, or mixed. Regardless of format:
@@ -181,6 +183,40 @@ This means: do not test other screens' UI layout or navigation. It does NOT mean
181
183
 
182
184
  ---
183
185
 
186
+ ## Design Inventory (UI items)
187
+
188
+ **When:** the unit holds any design source — images in `requirements/ui/`, `ui/figma-meta.md`, or `spec_figma.md`. Without one, skip this section.
189
+
190
+ **Why:** a design read "for visual context" leaves no trace. An item that exists only on the design (a column `spec.md` never names) or contradicts the spec is then missed by the author AND the reviewer, and "deliberately deferred" looks exactly like "never seen". `sungen audit` checks this file (`UI-INVENTORY-MISSING`, `UI-INVENTORY-INCOMPLETE`, `UI-ITEM-UNCOVERED`).
191
+
192
+ **Reading order:** `spec.md` (authoritative) → `spec_figma.md` → `ui/figma-meta.md` (`## Components`, `## Text Content`) → **every** image in `ui/`. Many images: group them (primary screen vs states/variants) but read them all — an unread state screen is an un-inventoried one.
193
+
194
+ **Write `requirements/ui-inventory.md`** — one row per component, table column, button/link, field, state (empty/error/loading/disabled), and design annotation:
195
+
196
+ ```markdown
197
+ # UI Inventory — <screen>
198
+ images read: 3/3 · figma-meta.md: read · spec_figma.md: absent
199
+
200
+ | ID | Item | Kind | Source | Seen in |
201
+ |---|---|---|---|---|
202
+ | UI-001 | Job List table | table | spec+design | ui/list.png |
203
+ | UI-002 | Contract plan | column | spec+design | ui/list.png |
204
+ | UI-014 | Salary range | column | design-only | ui/list.png |
205
+ | UI-015 | Status badge "Closed" | column | conflict — spec says "Expired" | ui/list.png |
206
+ ```
207
+
208
+ - **Source:** `spec+design` (both name it) · `design-only` (only the design shows it) · `conflict` (they disagree — say how in the cell). `spec.md` stays authoritative; a conflict is reported, never silently resolved in either direction.
209
+ - **IDs** `UI-NNN` are append-only, like scenario ids: re-runs keep existing rows and continue numbering.
210
+ - `images read: N/N` counts the images you actually opened against the images in the folder.
211
+
212
+ **Account for every `design-only` / `conflict` item in the `.feature`** — either:
213
+ - **cover it**: tag the scenario that proves it `@ui:UI-014`, or
214
+ - **defer it with a reason** in a feature comment: `# UI-DEFERRED: UI-002..013 — per-column checks are owned by job-detail`. A deferral without a reason defers nothing.
215
+
216
+ `spec+design` items are covered through the spec (`@spec:`), and citing their ids is optional.
217
+
218
+ ---
219
+
184
220
  ## Generation Workflow
185
221
 
186
222
  ### Step 1 — Orient: patterns + risk
@@ -219,6 +255,10 @@ Viewpoint items: [TV-01 – <exact wording from test-viewpoint row 1>]
219
255
  [TV-02 – <exact wording from test-viewpoint row 2>]
220
256
  → one entry per row/bullet in test-viewpoint.md, regardless of format
221
257
  → leave empty if no test-viewpoint.md present
258
+ UI items: [UI-014 – Salary range column (design-only) → covered by VP-TAB-012]
259
+ [UI-002..013 – per-column checks → deferred: owned by job-detail]
260
+ → one entry per Design Inventory row: covered / deferred-with-reason / uncovered
261
+ → leave empty if the unit has no design source
222
262
  Spec gaps: [G1 – behavior undocumented → verify with dev]
223
263
  ```
224
264
 
@@ -152,6 +152,7 @@ Build a mapping table: for each applicable group, does the feature have a matchi
152
152
  | **Account Status** | Deleted / blocked / inactive account login | VP-LOGIC | corresponding account data → error message |
153
153
  | **Security** | SQL Injection; XSS; Data Integrity (edit dropdown/remove `disabled` via DevTools → server rejects). SQL on LIKE/search fields → 2 TCs per the `sungen-viewpoint` SQL 2-layer rule. | VP-SEC | `with {{xss_*}}`/`{{sql_*}}`; data-integrity usually `@manual` |
154
154
  | **Cross-surface outcomes** | Admin action → outcome on user-facing surface (portal, mobile, widget); spec defines display condition on another URL | VP-LOGIC-CS | `@high @manual` per surface per business rule — at minimum 1 per cross-surface rule; use `@auth:role` + `@extend` if surface reachable in same test run |
155
+ | **Design items** *(when `requirements/ui/*`, `ui/figma-meta.md` or `spec_figma.md` exist)* | Every component / column / button / state the design shows is in `ui-inventory.md`; each `design-only` / `conflict` item is covered or deferred with a reason. Read the images yourself — the inventory can be incomplete | UI-NNN | `@ui:UI-NNN` on the proving scenario, or `# UI-DEFERRED: UI-NNN — <reason>`; rules in `sungen-tc-generation` § Design Inventory |
155
156
 
156
157
  **Mobile units add four categories** (`@platform:mobile/android/ios` only). Each maps to a theme the
157
158
  `sungen audit` mobile catalog scores, so a gap here is a scored gap, not a stylistic note — the
@@ -374,6 +375,12 @@ If `selectors/<name>.yaml` exists, count lines matching `@needs-live-verify` (pr
374
375
  | Behavior Handling / Account Status | ... | ... |
375
376
  | Security (XSS/SQLi) | ... | ... |
376
377
  | Cross-surface outcomes | ... | ... |
378
+ | Design items | n/a / ✓ / ✗ | ... |
379
+
380
+ ### Design ↔ Feature (when the unit holds design sources)
381
+ - Images read: <n>/<n> · inventory items: <n> (covered <n> · deferred <n> · uncovered <n>)
382
+ - Not inventoried: <item> (<image>) …
383
+ - Mislabelled / unproven: UI-NNN …
377
384
 
378
385
  ### ✗ Must-fix
379
386
  1. [DIMENSION] VP-XXX issue description
@@ -105,8 +105,10 @@ export default defineConfig({
105
105
  /* Per-action timeout (click, fill, etc.) */
106
106
  actionTimeout: 10_000,
107
107
 
108
- /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
109
- trace: 'on-first-retry',
108
+ /* Trace for a failed test. CI: recorded on the first retry (CI retries). Local: no retries, so
109
+ 'on-first-retry' would never record one — keep the trace of every failed test instead.
110
+ See https://playwright.dev/docs/trace-viewer */
111
+ trace: process.env.CI ? 'on-first-retry' : 'retain-on-failure',
110
112
 
111
113
  /**
112
114
  * Capture screenshot after each test failure.
@@ -1 +1 @@
1
- {"version":3,"file":"specs-url-assert.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-url-assert.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAYrF;AAwBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,cAAc,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,CA6CtH;AAED,oGAAoG;AACpG,KAAK,cAAc,GAAG;IACpB,GAAG,IAAI,MAAM,CAAC;IACd,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpF,CAAC;AAEF,uDAAuD;AACvD,UAAU,UAAU;IAAG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE;AAgDlE;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,cAAc,EAC3B,IAAI,GAAE,UAAU,GAAG;IAAE,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO,GACtF,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,cAAc,GAAG;IAAE,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,EAC3G,WAAW,EAAE,cAAc,EAC3B,IAAI,GAAE,UAAU,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO,GACtG,OAAO,CAAC,IAAI,CAAC,CASf"}
1
+ {"version":3,"file":"specs-url-assert.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-url-assert.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAYrF;AAwBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,cAAc,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,CA6CtH;AAED,oGAAoG;AACpG,KAAK,cAAc,GAAG;IACpB,GAAG,IAAI,MAAM,CAAC;IACd,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpF,CAAC;AAEF,uDAAuD;AACvD,UAAU,UAAU;IAAG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE;AAqElE;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,cAAc,EAC3B,IAAI,GAAE,UAAU,GAAG;IAAE,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO,GACtF,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,cAAc,GAAG;IAAE,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,EAC3G,WAAW,EAAE,cAAc,EAC3B,IAAI,GAAE,UAAU,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO,GACtG,OAAO,CAAC,IAAI,CAAC,CASf"}
@@ -162,9 +162,31 @@ function urlMatches({ pathname, hostname, declared, dataRef, ignoreQuery }) {
162
162
  * 3000) bounds step 1. Both are runtime knobs, so a slow environment is a config change, not a
163
163
  * regenerate.
164
164
  */
165
+ /**
166
+ * A millisecond budget from the environment. `Number()` alone turned `"1s"` / `"abc"` into NaN and
167
+ * `""` into 0 (`??` keeps an empty string): the hold loop then never ran, so a late redirect passed
168
+ * unseen, and a 0 / NaN networkidle timeout means "no timeout" to Playwright — the step waited out
169
+ * the whole test (#856). Unset or empty means the default; a malformed value falls back to it and
170
+ * says so, once per variable. `allowZero` for a knob where 0 is a real choice (no hold).
171
+ */
172
+ const warnedEnv = new Set();
173
+ function msEnv(name, fallback, allowZero = false) {
174
+ const raw = process.env[name]?.trim();
175
+ if (!raw)
176
+ return fallback;
177
+ const value = Number(raw);
178
+ if (Number.isFinite(value) && (value > 0 || (allowZero && value === 0)))
179
+ return value;
180
+ if (!warnedEnv.has(name)) {
181
+ warnedEnv.add(name);
182
+ console.warn(`[sungen] ${name}=${JSON.stringify(raw)} is not a ${allowZero ? 'non-negative' : 'positive'} number of milliseconds — using the default ${fallback}.`);
183
+ }
184
+ return fallback;
185
+ }
165
186
  async function settleAndHold(page, matches, opts, label, consequence) {
166
- const settleMs = opts.settleMs ?? Number(process.env.SUNGEN_URL_SETTLE_MS ?? 1000);
167
- const networkIdleMs = opts.networkIdleMs ?? Number(process.env.SUNGEN_URL_NETWORKIDLE_MS ?? 3000);
187
+ // 0 holds nothing (the operator's call); 0 for networkidle would mean "no timeout", so it is refused.
188
+ const settleMs = opts.settleMs ?? msEnv('SUNGEN_URL_SETTLE_MS', 1000, true);
189
+ const networkIdleMs = opts.networkIdleMs ?? msEnv('SUNGEN_URL_NETWORKIDLE_MS', 3000);
168
190
  const arrivedAt = page.url();
169
191
  await page.waitForLoadState('networkidle', { timeout: networkIdleMs }).catch(() => undefined);
170
192
  const started = Date.now();
@@ -1 +1 @@
1
- {"version":3,"file":"specs-url-assert.js","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-url-assert.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"specs-url-assert.js","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-url-assert.ts"],"names":[],"mappings":"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"}
@@ -205,6 +205,26 @@ interface SettleOpts { settleMs?: number; networkIdleMs?: number }
205
205
  * 3000) bounds step 1. Both are runtime knobs, so a slow environment is a config change, not a
206
206
  * regenerate.
207
207
  */
208
+ /**
209
+ * A millisecond budget from the environment. `Number()` alone turned `"1s"` / `"abc"` into NaN and
210
+ * `""` into 0 (`??` keeps an empty string): the hold loop then never ran, so a late redirect passed
211
+ * unseen, and a 0 / NaN networkidle timeout means "no timeout" to Playwright — the step waited out
212
+ * the whole test (#856). Unset or empty means the default; a malformed value falls back to it and
213
+ * says so, once per variable. `allowZero` for a knob where 0 is a real choice (no hold).
214
+ */
215
+ const warnedEnv = new Set<string>();
216
+ function msEnv(name: string, fallback: number, allowZero = false): number {
217
+ const raw = process.env[name]?.trim();
218
+ if (!raw) return fallback;
219
+ const value = Number(raw);
220
+ if (Number.isFinite(value) && (value > 0 || (allowZero && value === 0))) return value;
221
+ if (!warnedEnv.has(name)) {
222
+ warnedEnv.add(name);
223
+ console.warn(`[sungen] ${name}=${JSON.stringify(raw)} is not a ${allowZero ? 'non-negative' : 'positive'} number of milliseconds — using the default ${fallback}.`);
224
+ }
225
+ return fallback;
226
+ }
227
+
208
228
  async function settleAndHold(
209
229
  page: SettleablePage,
210
230
  matches: (u: URL) => boolean,
@@ -212,8 +232,9 @@ async function settleAndHold(
212
232
  label: string,
213
233
  consequence: string,
214
234
  ): Promise<void> {
215
- const settleMs = opts.settleMs ?? Number(process.env.SUNGEN_URL_SETTLE_MS ?? 1000);
216
- const networkIdleMs = opts.networkIdleMs ?? Number(process.env.SUNGEN_URL_NETWORKIDLE_MS ?? 3000);
235
+ // 0 holds nothing (the operator's call); 0 for networkidle would mean "no timeout", so it is refused.
236
+ const settleMs = opts.settleMs ?? msEnv('SUNGEN_URL_SETTLE_MS', 1000, true);
237
+ const networkIdleMs = opts.networkIdleMs ?? msEnv('SUNGEN_URL_NETWORKIDLE_MS', 3000);
217
238
  const arrivedAt = page.url();
218
239
 
219
240
  await page.waitForLoadState('networkidle', { timeout: networkIdleMs }).catch(() => undefined);
@@ -0,0 +1,14 @@
1
+ /** The template's trace value: cheap on CI (retries exist there), a trace for every local failure. */
2
+ export declare const TRACE_MODE_EXPRESSION = "process.env.CI ? 'on-first-retry' : 'retain-on-failure'";
3
+ /**
4
+ * 'patched' — the old default was rewritten now
5
+ * 'present' — already the template expression (idempotent)
6
+ * 'custom' — another value, no trace line, more than one old-default line, or one inside
7
+ * `projects: [...]`; nothing written
8
+ * 'absent' — no playwright.config.ts (a mobile-only project, or not a sungen project)
9
+ */
10
+ export type TraceModeOutcome = 'patched' | 'present' | 'custom' | 'absent';
11
+ export declare function patchTraceMode(cwd: string, dryRun?: boolean): TraceModeOutcome;
12
+ /** `sungen update` step: patch the trace mode and say so when it changed. */
13
+ export declare function installTraceMode(cwd: string, dryRun?: boolean): void;
14
+ //# sourceMappingURL=trace-mode-install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-mode-install.d.ts","sourceRoot":"","sources":["../../src/orchestrator/trace-mode-install.ts"],"names":[],"mappings":"AAgBA,sGAAsG;AACtG,eAAO,MAAM,qBAAqB,4DAA4D,CAAC;AAE/F;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AA6C3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAe,GAAG,gBAAgB,CAgBrF;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAe,GAAG,IAAI,CAG3E"}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TRACE_MODE_EXPRESSION = void 0;
37
+ exports.patchTraceMode = patchTraceMode;
38
+ exports.installTraceMode = installTraceMode;
39
+ /**
40
+ * Move an existing project's `use.trace` off the old default so local runs keep a trace.
41
+ *
42
+ * The old template paired `trace: 'on-first-retry'` with `retries: process.env.CI ? 2 : 0`: off CI
43
+ * there is no retry, so there is never a "first retry" and a QA fixing a test on their machine never
44
+ * got a trace. The template now records `on-first-retry` on CI and `retain-on-failure` locally.
45
+ *
46
+ * `playwright.config.ts` is written once at `sungen init` and never re-synced (see
47
+ * report-sanitize-reporter-install.ts, the same problem for the sanitize reporter), so `sungen update`
48
+ * calls this. It rewrites the trace line ONLY while it is still the old default — any other value is
49
+ * a choice the user made, and a wrong edit to a user's config is worse than a missing trace. The same
50
+ * goes for a `trace` inside `projects: [...]`: that is a per-project override, not the template default.
51
+ */
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
54
+ /** The template's trace value: cheap on CI (retries exist there), a trace for every local failure. */
55
+ exports.TRACE_MODE_EXPRESSION = "process.env.CI ? 'on-first-retry' : 'retain-on-failure'";
56
+ const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
57
+ // Both are anchored to the start of a line, so a commented-out copy (`// trace: …`) never counts.
58
+ // OLD_DEFAULT keeps the indentation in $1 and leaves the trailing comma, comment and EOL alone.
59
+ const OLD_DEFAULT = /^([ \t]*trace:[ \t]*)(['"])on-first-retry\2/gm;
60
+ const PRESENT = new RegExp(`^[ \\t]*trace:[ \\t]*${escapeRegExp(exports.TRACE_MODE_EXPRESSION)}`, 'm');
61
+ // The old template's one-line comment, only when it sits directly above the (patched) trace line.
62
+ // A comment the user wrote is theirs and stays.
63
+ const OLD_COMMENT = new RegExp(`^([ \\t]*)/\\* Collect trace when retrying the failed test\\. See https://playwright\\.dev/docs/trace-viewer \\*/(\\r?\\n)(?=[ \\t]*trace:[ \\t]*${escapeRegExp(exports.TRACE_MODE_EXPRESSION)})`, 'm');
64
+ const newComment = (indent, eol) => `${indent}/* Trace for a failed test. CI: recorded on the first retry (CI retries). Local: no retries, so${eol}` +
65
+ `${indent} 'on-first-retry' would never record one — keep the trace of every failed test instead.${eol}` +
66
+ `${indent} See https://playwright.dev/docs/trace-viewer */${eol}`;
67
+ /**
68
+ * [start, end] offsets of each live `projects: [...]` array, matched by bracket depth. Brackets inside
69
+ * a `//` or `/* *\/` comment or a quoted string are skipped: one stray `]` in a note would otherwise
70
+ * close the span early and expose a per-project override to the patch.
71
+ */
72
+ function projectsSpans(src) {
73
+ const spans = [];
74
+ for (const m of src.matchAll(/^[ \t]*projects\s*:\s*\[/gm)) {
75
+ const open = m.index + m[0].length - 1;
76
+ let depth = 0;
77
+ for (let i = open; i < src.length; i++) {
78
+ const ch = src[i];
79
+ if (ch === '/' && src[i + 1] === '/') {
80
+ const nl = src.indexOf('\n', i);
81
+ i = nl < 0 ? src.length : nl;
82
+ continue;
83
+ }
84
+ if (ch === '/' && src[i + 1] === '*') {
85
+ const end = src.indexOf('*/', i + 2);
86
+ i = end < 0 ? src.length : end + 1;
87
+ continue;
88
+ }
89
+ if (ch === "'" || ch === '"' || ch === '`') {
90
+ for (i++; i < src.length && src[i] !== ch; i++)
91
+ if (src[i] === '\\')
92
+ i++;
93
+ continue;
94
+ }
95
+ if (ch === '[')
96
+ depth++;
97
+ else if (ch === ']' && --depth === 0) {
98
+ spans.push([open, i]);
99
+ break;
100
+ }
101
+ }
102
+ }
103
+ return spans;
104
+ }
105
+ function patchTraceMode(cwd, dryRun = false) {
106
+ const configPath = path.join(cwd, 'playwright.config.ts');
107
+ if (!fs.existsSync(configPath))
108
+ return 'absent';
109
+ const src = fs.readFileSync(configPath, 'utf8');
110
+ if (PRESENT.test(src))
111
+ return 'present';
112
+ const hits = [...src.matchAll(OLD_DEFAULT)];
113
+ if (hits.length !== 1)
114
+ return 'custom'; // none: the user's own value · several: ambiguous, don't guess
115
+ const at = hits[0].index;
116
+ if (projectsSpans(src).some(([s, e]) => at > s && at < e))
117
+ return 'custom'; // a per-project override
118
+ if (!dryRun) {
119
+ const patched = src
120
+ .replace(OLD_DEFAULT, `$1${exports.TRACE_MODE_EXPRESSION}`)
121
+ .replace(OLD_COMMENT, (_m, indent, eol) => newComment(indent, eol));
122
+ fs.writeFileSync(configPath, patched);
123
+ }
124
+ return 'patched';
125
+ }
126
+ /** `sungen update` step: patch the trace mode and say so when it changed. */
127
+ function installTraceMode(cwd, dryRun = false) {
128
+ if (patchTraceMode(cwd, dryRun) !== 'patched')
129
+ return;
130
+ console.log(`${dryRun ? '📋 would update' : '✓ updated'} playwright.config.ts: local runs now keep a trace for every failed test (trace: ${exports.TRACE_MODE_EXPRESSION})`);
131
+ }
132
+ //# sourceMappingURL=trace-mode-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-mode-install.js","sourceRoot":"","sources":["../../src/orchestrator/trace-mode-install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The sungen-viewpoint pattern catalog by number — the `## N. <Name>` headings of
3
+ * `templates/ai-src/skills/sungen-viewpoint/group-*.md` — for the "UI Patterns Identified" table
4
+ * `sungen add` scaffolds into `test-viewpoint.md` (#842).
5
+ *
6
+ * The scaffold used to hard-code its own ten rows: eight of them numbered differently from the
7
+ * catalog (Data Table 2 vs 7, Modal 9 vs 12…), plus a "Pagination" pattern the catalog does not
8
+ * have, so authors copied the wrong numbers next to a skill that cites the right ones.
9
+ * `tests/harness/viewpoint-comments-and-patterns.run.ts` pins this list to the catalog headings.
10
+ */
11
+ export interface ViewpointPattern {
12
+ n: number;
13
+ name: string;
14
+ /** Group F — native-app patterns, read IN ADDITION to 1–17 for a mobile screen. */
15
+ mobile?: boolean;
16
+ }
17
+ export declare const VIEWPOINT_PATTERNS: readonly ViewpointPattern[];
18
+ /** The scaffold's pattern-table rows: 1–17 for every screen, plus Group F on a mobile project. */
19
+ export declare function uiPatternRows(isMobile: boolean): string[];
20
+ //# sourceMappingURL=viewpoint-pattern-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewpoint-pattern-catalog.d.ts","sourceRoot":"","sources":["../../src/orchestrator/viewpoint-pattern-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,kBAAkB,EAAE,SAAS,gBAAgB,EAiCzD,CAAC;AAEF,kGAAkG;AAClG,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,CAIzD"}