@sun-asterisk/sungen 3.2.32 → 3.2.34-beta.1
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/dist/cli/commands/audit.d.ts +5 -0
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +64 -11
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/capability.d.ts.map +1 -1
- package/dist/cli/commands/capability.js +40 -18
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/changed.d.ts.map +1 -1
- package/dist/cli/commands/changed.js +2 -3
- package/dist/cli/commands/changed.js.map +1 -1
- package/dist/cli/commands/dashboard.d.ts.map +1 -1
- package/dist/cli/commands/dashboard.js +2 -28
- package/dist/cli/commands/dashboard.js.map +1 -1
- package/dist/cli/commands/defect.d.ts +7 -0
- package/dist/cli/commands/defect.d.ts.map +1 -0
- package/dist/cli/commands/defect.js +68 -0
- package/dist/cli/commands/defect.js.map +1 -0
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +113 -59
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +14 -7
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/results-merge.d.ts +9 -0
- package/dist/cli/commands/results-merge.d.ts.map +1 -1
- package/dist/cli/commands/results-merge.js +9 -12
- package/dist/cli/commands/results-merge.js.map +1 -1
- package/dist/cli/commands/results-sanitize.d.ts.map +1 -1
- package/dist/cli/commands/results-sanitize.js +2 -13
- package/dist/cli/commands/results-sanitize.js.map +1 -1
- package/dist/cli/commands/select.d.ts +12 -0
- package/dist/cli/commands/select.d.ts.map +1 -0
- package/dist/cli/commands/select.js +122 -0
- package/dist/cli/commands/select.js.map +1 -0
- package/dist/cli/commands/triage.d.ts +7 -0
- package/dist/cli/commands/triage.d.ts.map +1 -0
- package/dist/cli/commands/triage.js +98 -0
- package/dist/cli/commands/triage.js.map +1 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +3 -0
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/viewpoint.d.ts +7 -0
- package/dist/cli/commands/viewpoint.d.ts.map +1 -0
- package/dist/cli/commands/viewpoint.js +70 -0
- package/dist/cli/commands/viewpoint.js.map +1 -0
- package/dist/cli/index.js +13 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/snapshot-builder.d.ts.map +1 -1
- package/dist/dashboard/snapshot-builder.js +6 -10
- package/dist/dashboard/snapshot-builder.js.map +1 -1
- package/dist/dashboard/templates/index.html +1 -1
- package/dist/dashboard/types.d.ts +1 -0
- package/dist/dashboard/types.d.ts.map +1 -1
- package/dist/exporters/csv-exporter.d.ts +4 -0
- package/dist/exporters/csv-exporter.d.ts.map +1 -1
- package/dist/exporters/csv-exporter.js +12 -11
- package/dist/exporters/csv-exporter.js.map +1 -1
- package/dist/exporters/feature-parser.d.ts +29 -0
- package/dist/exporters/feature-parser.d.ts.map +1 -1
- package/dist/exporters/feature-parser.js +44 -1
- package/dist/exporters/feature-parser.js.map +1 -1
- package/dist/exporters/json-exporter.d.ts.map +1 -1
- package/dist/exporters/json-exporter.js +7 -0
- package/dist/exporters/json-exporter.js.map +1 -1
- package/dist/exporters/locale-variants.d.ts +7 -1
- package/dist/exporters/locale-variants.d.ts.map +1 -1
- package/dist/exporters/locale-variants.js +23 -16
- package/dist/exporters/locale-variants.js.map +1 -1
- package/dist/exporters/manual-hybrid-oracle.d.ts +54 -0
- package/dist/exporters/manual-hybrid-oracle.d.ts.map +1 -0
- package/dist/exporters/manual-hybrid-oracle.js +114 -0
- package/dist/exporters/manual-hybrid-oracle.js.map +1 -0
- package/dist/exporters/matrix/build.d.ts.map +1 -1
- package/dist/exporters/matrix/build.js +68 -19
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/carry-manual-results.d.ts +89 -0
- package/dist/exporters/matrix/carry-manual-results.d.ts.map +1 -0
- package/dist/exporters/matrix/carry-manual-results.js +302 -0
- package/dist/exporters/matrix/carry-manual-results.js.map +1 -0
- package/dist/exporters/matrix/export.d.ts +9 -1
- package/dist/exporters/matrix/export.d.ts.map +1 -1
- package/dist/exporters/matrix/export.js +21 -3
- package/dist/exporters/matrix/export.js.map +1 -1
- package/dist/exporters/matrix/gates.js +6 -0
- package/dist/exporters/matrix/gates.js.map +1 -1
- package/dist/exporters/matrix/render-csv.js +1 -1
- package/dist/exporters/matrix/render-csv.js.map +1 -1
- package/dist/exporters/matrix/render-testcase-sheet.d.ts.map +1 -1
- package/dist/exporters/matrix/render-testcase-sheet.js +10 -4
- package/dist/exporters/matrix/render-testcase-sheet.js.map +1 -1
- package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
- package/dist/exporters/matrix/render-xlsx.js +3 -0
- package/dist/exporters/matrix/render-xlsx.js.map +1 -1
- package/dist/exporters/matrix/types.d.ts +13 -1
- package/dist/exporters/matrix/types.d.ts.map +1 -1
- package/dist/exporters/matrix/types.js.map +1 -1
- package/dist/exporters/matrix/wording.d.ts +8 -1
- package/dist/exporters/matrix/wording.d.ts.map +1 -1
- package/dist/exporters/matrix/wording.js +37 -2
- package/dist/exporters/matrix/wording.js.map +1 -1
- package/dist/exporters/playwright-report-parser.d.ts.map +1 -1
- package/dist/exporters/playwright-report-parser.js +1 -0
- package/dist/exporters/playwright-report-parser.js.map +1 -1
- package/dist/exporters/run-environment.d.ts +32 -0
- package/dist/exporters/run-environment.d.ts.map +1 -0
- package/dist/exporters/run-environment.js +125 -0
- package/dist/exporters/run-environment.js.map +1 -0
- package/dist/exporters/scenario-merger.d.ts +18 -0
- package/dist/exporters/scenario-merger.d.ts.map +1 -1
- package/dist/exporters/scenario-merger.js +49 -3
- package/dist/exporters/scenario-merger.js.map +1 -1
- package/dist/exporters/test-data-resolver.d.ts +0 -4
- package/dist/exporters/test-data-resolver.d.ts.map +1 -1
- package/dist/exporters/test-data-resolver.js +0 -7
- package/dist/exporters/test-data-resolver.js.map +1 -1
- package/dist/exporters/types.d.ts +5 -0
- package/dist/exporters/types.d.ts.map +1 -1
- package/dist/exporters/xlsx-exporter.d.ts +2 -0
- package/dist/exporters/xlsx-exporter.d.ts.map +1 -1
- package/dist/exporters/xlsx-exporter.js +7 -2
- package/dist/exporters/xlsx-exporter.js.map +1 -1
- package/dist/generators/gherkin-parser/index.d.ts +11 -4
- package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
- package/dist/generators/gherkin-parser/index.js +49 -19
- package/dist/generators/gherkin-parser/index.js.map +1 -1
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts +4 -0
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/reinstall-app-action.hbs +2 -2
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +8 -2
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/visible-with-role-variable-assertion.hbs +7 -3
- package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +68 -4
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +7 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +8 -4
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/pick-option.hbs +13 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/url-assertion.hbs +5 -1
- package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +16 -0
- package/dist/generators/test-generator/code-generator.d.ts +2 -1
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +90 -5
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/diagnostics.d.ts +36 -5
- package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.js +35 -4
- package/dist/generators/test-generator/diagnostics.js.map +1 -1
- package/dist/generators/test-generator/patterns/index.d.ts +12 -2
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +15 -9
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/patterns/types.d.ts +15 -0
- package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/with-parent-scope.d.ts +5 -0
- package/dist/generators/test-generator/patterns/with-parent-scope.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/with-parent-scope.js +6 -0
- package/dist/generators/test-generator/patterns/with-parent-scope.js.map +1 -1
- package/dist/generators/test-generator/step-mapper.d.ts +46 -0
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +84 -9
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/generators/test-generator/utils/data-resolver.d.ts +25 -0
- package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/data-resolver.js +39 -8
- package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-entry-fields.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-entry-fields.js +1 -0
- package/dist/generators/test-generator/utils/selector-entry-fields.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts +37 -4
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +212 -79
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/harness/audit.d.ts +3 -0
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +60 -19
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/capability.d.ts +7 -1
- package/dist/harness/capability.d.ts.map +1 -1
- package/dist/harness/capability.js +15 -12
- package/dist/harness/capability.js.map +1 -1
- package/dist/harness/catalog/universal-viewpoints.yaml +5 -5
- package/dist/harness/config-file.d.ts +17 -0
- package/dist/harness/config-file.d.ts.map +1 -0
- package/dist/harness/config-file.js +100 -0
- package/dist/harness/config-file.js.map +1 -0
- package/dist/harness/counted-assertions.d.ts +2 -0
- package/dist/harness/counted-assertions.d.ts.map +1 -0
- package/dist/harness/counted-assertions.js +38 -0
- package/dist/harness/counted-assertions.js.map +1 -0
- package/dist/harness/data-driven-lint.d.ts.map +1 -1
- package/dist/harness/data-driven-lint.js +69 -27
- package/dist/harness/data-driven-lint.js.map +1 -1
- package/dist/harness/defect-draft.d.ts +14 -0
- package/dist/harness/defect-draft.d.ts.map +1 -0
- package/dist/harness/defect-draft.js +143 -0
- package/dist/harness/defect-draft.js.map +1 -0
- package/dist/harness/defects.d.ts +24 -0
- package/dist/harness/defects.d.ts.map +1 -0
- package/dist/harness/defects.js +118 -0
- package/dist/harness/defects.js.map +1 -0
- package/dist/harness/depth-lint.d.ts.map +1 -1
- package/dist/harness/depth-lint.js +2 -1
- package/dist/harness/depth-lint.js.map +1 -1
- package/dist/harness/flow-check.d.ts.map +1 -1
- package/dist/harness/flow-check.js +6 -2
- package/dist/harness/flow-check.js.map +1 -1
- package/dist/harness/keyword-match.d.ts +59 -0
- package/dist/harness/keyword-match.d.ts.map +1 -0
- package/dist/harness/keyword-match.js +86 -0
- package/dist/harness/keyword-match.js.map +1 -0
- package/dist/harness/manifest.d.ts.map +1 -1
- package/dist/harness/manifest.js +2 -2
- package/dist/harness/manifest.js.map +1 -1
- package/dist/harness/next-step.d.ts +2 -4
- package/dist/harness/next-step.d.ts.map +1 -1
- package/dist/harness/next-step.js +50 -5
- package/dist/harness/next-step.js.map +1 -1
- package/dist/harness/parse.d.ts +45 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +142 -24
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/perf.d.ts +7 -1
- package/dist/harness/perf.d.ts.map +1 -1
- package/dist/harness/perf.js +13 -10
- package/dist/harness/perf.js.map +1 -1
- package/dist/harness/quality-gates.d.ts +9 -2
- package/dist/harness/quality-gates.d.ts.map +1 -1
- package/dist/harness/quality-gates.js +22 -8
- package/dist/harness/quality-gates.js.map +1 -1
- package/dist/harness/query-catalog.js +0 -0
- package/dist/harness/query-catalog.js.map +1 -1
- package/dist/harness/read-text.d.ts +21 -0
- package/dist/harness/read-text.d.ts.map +1 -1
- package/dist/harness/read-text.js +32 -1
- package/dist/harness/read-text.js.map +1 -1
- package/dist/harness/script-check.d.ts.map +1 -1
- package/dist/harness/script-check.js +7 -1
- package/dist/harness/script-check.js.map +1 -1
- package/dist/harness/secret-scan.d.ts +27 -1
- package/dist/harness/secret-scan.d.ts.map +1 -1
- package/dist/harness/secret-scan.js +57 -4
- package/dist/harness/secret-scan.js.map +1 -1
- package/dist/harness/select-by-ids.d.ts +31 -0
- package/dist/harness/select-by-ids.d.ts.map +1 -0
- package/dist/harness/select-by-ids.js +106 -0
- package/dist/harness/select-by-ids.js.map +1 -0
- package/dist/harness/sensors.d.ts +20 -1
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +133 -39
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/spec-branches.d.ts +0 -18
- package/dist/harness/spec-branches.d.ts.map +1 -1
- package/dist/harness/spec-branches.js +24 -3
- package/dist/harness/spec-branches.js.map +1 -1
- package/dist/harness/spec-coverage.d.ts.map +1 -1
- package/dist/harness/spec-coverage.js +14 -4
- package/dist/harness/spec-coverage.js.map +1 -1
- package/dist/harness/triage-signals.d.ts +20 -0
- package/dist/harness/triage-signals.d.ts.map +1 -0
- package/dist/harness/triage-signals.js +30 -0
- package/dist/harness/triage-signals.js.map +1 -0
- package/dist/harness/triage-unit.d.ts +23 -0
- package/dist/harness/triage-unit.d.ts.map +1 -0
- package/dist/harness/triage-unit.js +142 -0
- package/dist/harness/triage-unit.js.map +1 -0
- package/dist/harness/triage.d.ts +28 -0
- package/dist/harness/triage.d.ts.map +1 -0
- package/dist/harness/triage.js +99 -0
- package/dist/harness/triage.js.map +1 -0
- package/dist/harness/ui-inventory.d.ts +40 -0
- package/dist/harness/ui-inventory.d.ts.map +1 -0
- package/dist/harness/ui-inventory.js +191 -0
- package/dist/harness/ui-inventory.js.map +1 -0
- package/dist/harness/viewpoint-baseline.d.ts.map +1 -1
- package/dist/harness/viewpoint-baseline.js +7 -1
- package/dist/harness/viewpoint-baseline.js.map +1 -1
- package/dist/harness/viewpoint-draft-header.d.ts +7 -0
- package/dist/harness/viewpoint-draft-header.d.ts.map +1 -0
- package/dist/harness/viewpoint-draft-header.js +100 -0
- package/dist/harness/viewpoint-draft-header.js.map +1 -0
- package/dist/harness/viewpoint-ledger.d.ts +13 -3
- package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
- package/dist/harness/viewpoint-ledger.js +106 -19
- package/dist/harness/viewpoint-ledger.js.map +1 -1
- package/dist/harness/viewpoint-mode.d.ts +9 -0
- package/dist/harness/viewpoint-mode.d.ts.map +1 -0
- package/dist/harness/viewpoint-mode.js +52 -0
- package/dist/harness/viewpoint-mode.js.map +1 -0
- package/dist/harness/viewpoint-priority.d.ts +19 -0
- package/dist/harness/viewpoint-priority.d.ts.map +1 -0
- package/dist/harness/viewpoint-priority.js +36 -0
- package/dist/harness/viewpoint-priority.js.map +1 -0
- package/dist/harness/viewpoint-review-open.d.ts +6 -0
- package/dist/harness/viewpoint-review-open.d.ts.map +1 -0
- package/dist/harness/viewpoint-review-open.js +90 -0
- package/dist/harness/viewpoint-review-open.js.map +1 -0
- package/dist/harness/viewpoint-scan-refs.d.ts +50 -0
- package/dist/harness/viewpoint-scan-refs.d.ts.map +1 -0
- package/dist/harness/viewpoint-scan-refs.js +200 -0
- package/dist/harness/viewpoint-scan-refs.js.map +1 -0
- package/dist/harness/viewpoint-scan.d.ts +41 -0
- package/dist/harness/viewpoint-scan.d.ts.map +1 -0
- package/dist/harness/viewpoint-scan.js +118 -0
- package/dist/harness/viewpoint-scan.js.map +1 -0
- package/dist/harness/write-atomic.d.ts +2 -0
- package/dist/harness/write-atomic.d.ts.map +1 -0
- package/dist/harness/write-atomic.js +62 -0
- package/dist/harness/write-atomic.js.map +1 -0
- package/dist/orchestrator/ai-skills/writer.d.ts.map +1 -1
- package/dist/orchestrator/ai-skills/writer.js +15 -7
- package/dist/orchestrator/ai-skills/writer.js.map +1 -1
- package/dist/orchestrator/assets-drift.d.ts.map +1 -1
- package/dist/orchestrator/assets-drift.js +11 -6
- package/dist/orchestrator/assets-drift.js.map +1 -1
- package/dist/orchestrator/flow-manager.d.ts +0 -1
- package/dist/orchestrator/flow-manager.d.ts.map +1 -1
- package/dist/orchestrator/flow-manager.js +3 -52
- package/dist/orchestrator/flow-manager.js.map +1 -1
- package/dist/orchestrator/project-deps-sync.d.ts.map +1 -1
- package/dist/orchestrator/project-deps-sync.js +22 -1
- package/dist/orchestrator/project-deps-sync.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts +8 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +49 -7
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/screen-manager.d.ts.map +1 -1
- package/dist/orchestrator/screen-manager.js +8 -62
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/orchestrator/security-overrides-catalog.d.ts +39 -0
- package/dist/orchestrator/security-overrides-catalog.d.ts.map +1 -0
- package/dist/orchestrator/security-overrides-catalog.js +63 -0
- package/dist/orchestrator/security-overrides-catalog.js.map +1 -0
- package/dist/orchestrator/security-overrides.d.ts +51 -0
- package/dist/orchestrator/security-overrides.d.ts.map +1 -0
- package/dist/orchestrator/security-overrides.js +165 -0
- package/dist/orchestrator/security-overrides.js.map +1 -0
- package/dist/orchestrator/templates/ai-src/agents/discovery.md +11 -3
- package/dist/orchestrator/templates/ai-src/agents/reviewer.md +8 -0
- package/dist/orchestrator/templates/ai-src/commands/create-test.md +32 -24
- package/dist/orchestrator/templates/ai-src/commands/review.md +2 -2
- package/dist/orchestrator/templates/ai-src/commands/run-test.md +78 -15
- package/dist/orchestrator/templates/ai-src/skills/sungen-capture/mode-local.md +2 -2
- package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +25 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +26 -8
- package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +5 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +58 -14
- package/dist/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +13 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +42 -2
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +18 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/review-checklist.md +63 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/viewpoint-template.md +158 -0
- package/dist/orchestrator/templates/playwright.config.ts +4 -2
- package/dist/orchestrator/templates/specs-locale-fixture.ts +21 -9
- package/dist/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
- package/dist/orchestrator/templates/specs-url-assert.d.ts +17 -1
- package/dist/orchestrator/templates/specs-url-assert.d.ts.map +1 -1
- package/dist/orchestrator/templates/specs-url-assert.js +38 -4
- package/dist/orchestrator/templates/specs-url-assert.js.map +1 -1
- package/dist/orchestrator/templates/specs-url-assert.ts +47 -4
- package/dist/orchestrator/templates/wdio.conf.ts +24 -1
- package/dist/orchestrator/trace-mode-install.d.ts +14 -0
- package/dist/orchestrator/trace-mode-install.d.ts.map +1 -0
- package/dist/orchestrator/trace-mode-install.js +132 -0
- package/dist/orchestrator/trace-mode-install.js.map +1 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.d.ts +23 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.d.ts.map +1 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.js +48 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.js.map +1 -0
- package/dist/orchestrator/viewpoint-scaffold.d.ts +3 -0
- package/dist/orchestrator/viewpoint-scaffold.d.ts.map +1 -0
- package/dist/orchestrator/viewpoint-scaffold.js +70 -0
- package/dist/orchestrator/viewpoint-scaffold.js.map +1 -0
- package/package.json +3 -3
- package/src/cli/commands/audit.ts +59 -12
- package/src/cli/commands/capability.ts +54 -19
- package/src/cli/commands/changed.ts +2 -4
- package/src/cli/commands/dashboard.ts +1 -26
- package/src/cli/commands/defect.ts +49 -0
- package/src/cli/commands/delivery.ts +106 -56
- package/src/cli/commands/generate.ts +15 -7
- package/src/cli/commands/results-merge.ts +9 -9
- package/src/cli/commands/results-sanitize.ts +2 -9
- package/src/cli/commands/select.ts +88 -0
- package/src/cli/commands/triage.ts +57 -0
- package/src/cli/commands/update.ts +3 -0
- package/src/cli/commands/viewpoint.ts +58 -0
- package/src/cli/index.ts +13 -2
- package/src/dashboard/snapshot-builder.ts +6 -8
- package/src/dashboard/templates/index.html +1 -1
- package/src/dashboard/types.ts +1 -0
- package/src/exporters/csv-exporter.ts +12 -11
- package/src/exporters/feature-parser.ts +44 -2
- package/src/exporters/json-exporter.ts +6 -1
- package/src/exporters/locale-variants.ts +23 -17
- package/src/exporters/manual-hybrid-oracle.ts +112 -0
- package/src/exporters/matrix/build.ts +71 -19
- package/src/exporters/matrix/carry-manual-results.ts +292 -0
- package/src/exporters/matrix/export.ts +24 -4
- package/src/exporters/matrix/gates.ts +6 -0
- package/src/exporters/matrix/render-csv.ts +1 -1
- package/src/exporters/matrix/render-testcase-sheet.ts +10 -4
- package/src/exporters/matrix/render-xlsx.ts +3 -0
- package/src/exporters/matrix/types.ts +13 -1
- package/src/exporters/matrix/wording.ts +36 -2
- package/src/exporters/playwright-report-parser.ts +1 -0
- package/src/exporters/run-environment.ts +89 -0
- package/src/exporters/scenario-merger.ts +51 -5
- package/src/exporters/test-data-resolver.ts +0 -6
- package/src/exporters/types.ts +5 -0
- package/src/exporters/xlsx-exporter.ts +7 -2
- package/src/generators/gherkin-parser/index.ts +50 -18
- package/src/generators/test-generator/adapters/adapter-interface.ts +6 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/reinstall-app-action.hbs +2 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +8 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/visible-with-role-variable-assertion.hbs +7 -3
- package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +68 -4
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +7 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +8 -4
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/pick-option.hbs +13 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/url-assertion.hbs +5 -1
- package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +16 -0
- package/src/generators/test-generator/code-generator.ts +77 -5
- package/src/generators/test-generator/diagnostics.ts +36 -5
- package/src/generators/test-generator/patterns/index.ts +15 -8
- package/src/generators/test-generator/patterns/types.ts +15 -0
- package/src/generators/test-generator/patterns/with-parent-scope.ts +6 -0
- package/src/generators/test-generator/step-mapper.ts +90 -8
- package/src/generators/test-generator/utils/data-resolver.ts +41 -12
- package/src/generators/test-generator/utils/selector-entry-fields.ts +1 -0
- package/src/generators/test-generator/utils/selector-resolver.ts +238 -82
- package/src/harness/audit.ts +69 -24
- package/src/harness/capability.ts +23 -12
- package/src/harness/catalog/universal-viewpoints.yaml +5 -5
- package/src/harness/config-file.ts +66 -0
- package/src/harness/counted-assertions.ts +33 -0
- package/src/harness/data-driven-lint.ts +82 -24
- package/src/harness/defect-draft.ts +115 -0
- package/src/harness/defects.ts +94 -0
- package/src/harness/depth-lint.ts +2 -1
- package/src/harness/flow-check.ts +6 -2
- package/src/harness/keyword-match.ts +85 -0
- package/src/harness/manifest.ts +2 -2
- package/src/harness/next-step.ts +47 -5
- package/src/harness/parse.ts +151 -27
- package/src/harness/perf.ts +15 -7
- package/src/harness/quality-gates.ts +22 -8
- package/src/harness/query-catalog.ts +0 -0
- package/src/harness/read-text.ts +32 -1
- package/src/harness/script-check.ts +7 -1
- package/src/harness/secret-scan.ts +60 -4
- package/src/harness/select-by-ids.ts +83 -0
- package/src/harness/sensors.ts +141 -40
- package/src/harness/spec-branches.ts +6 -3
- package/src/harness/spec-coverage.ts +14 -4
- package/src/harness/triage-signals.ts +46 -0
- package/src/harness/triage-unit.ts +113 -0
- package/src/harness/triage.ts +127 -0
- package/src/harness/ui-inventory.ts +164 -0
- package/src/harness/viewpoint-baseline.ts +7 -1
- package/src/harness/viewpoint-draft-header.ts +55 -0
- package/src/harness/viewpoint-ledger.ts +113 -25
- package/src/harness/viewpoint-mode.ts +49 -0
- package/src/harness/viewpoint-priority.ts +38 -0
- package/src/harness/viewpoint-review-open.ts +51 -0
- package/src/harness/viewpoint-scan-refs.ts +154 -0
- package/src/harness/viewpoint-scan.ts +111 -0
- package/src/harness/write-atomic.ts +22 -0
- package/src/orchestrator/ai-skills/writer.ts +18 -3
- package/src/orchestrator/assets-drift.ts +10 -5
- package/src/orchestrator/flow-manager.ts +3 -53
- package/src/orchestrator/project-deps-sync.ts +23 -1
- package/src/orchestrator/project-initializer.ts +54 -6
- package/src/orchestrator/screen-manager.ts +7 -61
- package/src/orchestrator/security-overrides-catalog.ts +69 -0
- package/src/orchestrator/security-overrides.ts +149 -0
- package/src/orchestrator/templates/ai-src/agents/discovery.md +11 -3
- package/src/orchestrator/templates/ai-src/agents/reviewer.md +8 -0
- package/src/orchestrator/templates/ai-src/commands/create-test.md +32 -24
- package/src/orchestrator/templates/ai-src/commands/review.md +2 -2
- package/src/orchestrator/templates/ai-src/commands/run-test.md +78 -15
- package/src/orchestrator/templates/ai-src/skills/sungen-capture/mode-local.md +2 -2
- package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +25 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +26 -8
- package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +5 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +58 -14
- package/src/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +13 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +42 -2
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +18 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/review-checklist.md +63 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/viewpoint-template.md +158 -0
- package/src/orchestrator/templates/playwright.config.ts +4 -2
- package/src/orchestrator/templates/specs-locale-fixture.ts +21 -9
- package/src/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
- package/src/orchestrator/templates/specs-url-assert.ts +47 -4
- package/src/orchestrator/templates/wdio.conf.ts +24 -1
- package/src/orchestrator/trace-mode-install.ts +94 -0
- package/src/orchestrator/viewpoint-pattern-catalog.ts +61 -0
- package/src/orchestrator/viewpoint-scaffold.ts +36 -0
|
@@ -51,7 +51,7 @@ You are an **independent QA Reviewer** — you did not author these tests. You d
|
|
|
51
51
|
1. **Enumerate feature files** — glob `<base>/<name>/features/*.feature` (main + any sub-features). If none → `/sungen:create-test` first.
|
|
52
52
|
2. **Run the harness (source of truth) — do NOT re-score with a separate rubric:**
|
|
53
53
|
- `sungen audit --screen <name>` (Bash) → gate status, business-weighted score, findings, gaps (coverage / assertion-depth / balance / duplicate / traceability).
|
|
54
|
-
- **`sungen-reviewer`** sub-agent (Task tool, `subagent_type: sungen-reviewer`) → semantic verdict the gate can't see (do steps prove the title, observable Then, @manual justified). Copilot/no-sub-agents: apply the `sungen-reviewer` criteria inline.
|
|
54
|
+
- **`sungen-reviewer`** sub-agent (Task tool, `subagent_type: sungen-reviewer`) → semantic verdict the gate can't see (do steps prove the title, observable Then, @manual justified) and, when the unit holds design sources (`requirements/ui/*`, `ui/figma-meta.md`, `spec_figma.md`), the **Design ↔ Feature diff** against `ui-inventory.md`. Copilot/no-sub-agents: apply the `sungen-reviewer` criteria inline.
|
|
55
55
|
- `sungen script-check --screen <name>` (Bash) → is the generated spec a 1:1 of the Gherkin (only if a spec exists; flags hand-edit / stale drift).
|
|
56
56
|
3. **Unified scorecard** — present ONE report per feature, anchored on the harness signals (the `sungen-tc-review` 7 dimensions are a *presentation layer* over these, not a competing score):
|
|
57
57
|
{{/cap}}
|
|
@@ -63,7 +63,7 @@ You are an **independent QA Reviewer** — you did not author these tests. You d
|
|
|
63
63
|
1. **Enumerate** `<base>/${input:name}/features/*.feature`. If none → `/sungen-create-test` first.
|
|
64
64
|
2. **Run the harness (source of truth) — no separate rubric:**
|
|
65
65
|
- `sungen audit --screen ${input:name}` → gate, business-weighted score, findings, gaps.
|
|
66
|
-
- Apply the **`sungen-reviewer` criteria inline** → semantic verdict (do steps prove the title? observable Then? business-critical depth? @manual justified?).
|
|
66
|
+
- Apply the **`sungen-reviewer` criteria inline** → semantic verdict (do steps prove the title? observable Then? business-critical depth? @manual justified?) and, when `requirements/ui/*` / `ui/figma-meta.md` / `spec_figma.md` exist, read them and diff the design against `ui-inventory.md` and the `.feature` (criterion 7).
|
|
67
67
|
- `sungen script-check --screen ${input:name}` → spec is 1:1 with the Gherkin (flags hand-edit / stale drift; only if a spec exists).
|
|
68
68
|
3. **Unified scorecard** per feature, anchored on harness signals (the `sungen-tc-review` 7 dimensions are a presentation layer, not a competing score):
|
|
69
69
|
{{/cap}}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: run-test
|
|
3
3
|
description: "Generate selectors + auth state (Playwright MCP for web / Appium MCP for mobile), compile, and run tests — auto-fixes selectors on failure"
|
|
4
|
-
argument-hint: "[screen-name] [--env <locale>] [--ios|--android|--both]"
|
|
4
|
+
argument-hint: "[screen-name] [--ids <ID,…>] [--env <locale>] [--ios|--android|--both]"
|
|
5
5
|
order: 40
|
|
6
6
|
claude-tools: "Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwright__browser_navigate, mcp__playwright__browser_snapshot, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_wait_for, mcp__playwright__browser_evaluate, mcp__playwright__browser_run_code, mcp__playwright__browser_storage_state, mcp__playwright__browser_set_storage_state, mcp__appium-mcp__select_device, mcp__appium-mcp__appium_session_management, mcp__appium-mcp__generate_locators, mcp__appium-mcp__appium_get_page_source, mcp__appium-mcp__appium_find_element, mcp__appium-mcp__appium_gesture, mcp__appium-mcp__appium_screenshot, mcp__appium-mcp__appium_set_value"
|
|
7
7
|
copilot-tools: "[read, execute, edit, vscode/askQuestions, playwright/*, appium/*]"
|
|
@@ -79,12 +79,21 @@ Stop here for mobile — do not continue to the web path.
|
|
|
79
79
|
> ⛔ **The `.feature` Gherkin is QA-approved and FROZEN.** During auto-fix you may write
|
|
80
80
|
> **only** `selectors.yaml`, `test-data.yaml` (and other `*.yaml` data), plus the **one narrow
|
|
81
81
|
> `.feature` edit** allowed: the **element-type token** on a `[Reference]` (e.g. `field`→`textbox`,
|
|
82
|
-
> `button`→`link` — selector resolution, not test logic).
|
|
82
|
+
> `button`→`link` — selector resolution, not test logic). A second, equally narrow exception:
|
|
83
|
+
> adding **`@known-defect:DEF-NNN`** to a scenario's tag line once its defect record exists (step 8)
|
|
84
|
+
> — that tag only, the tag line only. You must **NOT** change the Gherkin's
|
|
83
85
|
> content or logic: no rewriting/adding/removing steps, no `wait for` steps, no changed expected
|
|
84
86
|
> values, no weakened assertions. A failure that would need any of those is a **CANDIDATE BUG /
|
|
85
87
|
> QA finding → report it, let it FAIL** (it may be a real bug). The live page is NOT the oracle;
|
|
86
88
|
> never hand-edit the generated `.spec.ts` either. See `sungen-error-mapping` § "HARD RULE".
|
|
87
89
|
> (A `password > 8` test that fails on 6 chars is a bug to report, not a `>= 6` edit.)
|
|
90
|
+
>
|
|
91
|
+
> **Blocked by missing seed data / capability** (the run cannot create the state the scenario
|
|
92
|
+
> needs)? Keep every Given/When/Then; add only a tag — `@requires:<cap>` when a driver exists,
|
|
93
|
+
> else `@manual:M1` with a `# MANUAL (<date>, run-test): <reason>` comment inside the scenario —
|
|
94
|
+
> and list each downgrade in the run summary for QA. Never replace the assertion with a presence
|
|
95
|
+
> placeholder and park the oracle in a comment (`SG-W008`). See `sungen-error-mapping` § "Fails
|
|
96
|
+
> because the environment lacks the DATA or CAPABILITY".
|
|
88
97
|
|
|
89
98
|
## Parameters
|
|
90
99
|
|
|
@@ -95,7 +104,9 @@ Parse from `$ARGUMENTS`:
|
|
|
95
104
|
the result over the previous run's file instead of replacing it. Passing it also **skips the scope gate**:
|
|
96
105
|
the flag IS the answer, so asking again would be noise. Without the flag the gate asks — but only when the
|
|
97
106
|
selection is narrower than the whole unit (see the table). Either way a subset run must follow the merge
|
|
98
|
-
|
|
107
|
+
flow below — web writes the subset to a temp report, mobile backs the fixed-name file up BEFORE the run.
|
|
108
|
+
- **`--ids <ID,…>`** — run exactly these test-case IDs (`VP-UI-001,VP-UI-002`) and merge the result
|
|
109
|
+
over the previous run's file — see the `--ids` section below. Skips the scope gate, like `--change-only`.
|
|
99
110
|
- **`--ios`**, **`--android`**, **`--both`** (mobile only) — optional. Sets `MOBILE_PLATFORM` for the test run. Default: `android` if not specified. Parsed into `MOBILE_PLATFORM=<value>` and used in WebdriverIO test runs.
|
|
100
111
|
|
|
101
112
|
If `--env` is passed but no value follows, ask the user which locale to use.
|
|
@@ -172,6 +183,7 @@ Read `summary.selected`, `summary.total`, `all`, and `reasons`, then follow this
|
|
|
172
183
|
| Situation | What to do |
|
|
173
184
|
|---|---|
|
|
174
185
|
| `--change-only` was passed | **Do NOT ask.** Run the changed set, print the list + reasons for the record, follow the merge flow below. |
|
|
186
|
+
| `--ids` was passed | **Do NOT ask, and do not run `sungen changed` at all.** The user named the cases — follow the `--ids` section below. |
|
|
175
187
|
| `all: true` | **Do NOT ask** — there is nothing to choose. Print the reason (`no previous run recorded`, `the Background changed`, `project config changed`, `git reports …`) and run the FULL suite. |
|
|
176
188
|
| `selected == 0` | **Do NOT ask.** Say plainly that nothing changed since the last recorded run, and use `AskUserQuestion` to offer: re-run the full suite anyway / stop here. |
|
|
177
189
|
| `0 < selected < total` | **ASK** — this is the only case with two honest answers. |
|
|
@@ -187,6 +199,10 @@ recorded` and runs everything again — the narrowing never starts. Record it af
|
|
|
187
199
|
results you accept (a full run, or a subset once merged), and NOT after a run you are about to
|
|
188
200
|
redo: leaving the baseline where it is keeps the same scenarios selected on the next attempt.
|
|
189
201
|
|
|
202
|
+
**Never record after an `--ids` run.** The user's IDs need not cover what an edit changed;
|
|
203
|
+
recording would mark every changed scenario as re-run, and the next `--change-only` would skip the
|
|
204
|
+
ones this run never touched.
|
|
205
|
+
|
|
190
206
|
When you ask, first PRINT the selection so the choice is informed — one line per scenario with its
|
|
191
207
|
reason, exactly as `sungen changed` renders it — then `AskUserQuestion` with two options:
|
|
192
208
|
|
|
@@ -256,8 +272,8 @@ question already.
|
|
|
256
272
|
5. **Phase 1 — Smoke Check**: Run first 5 `@high` scenarios only. If failures → diagnose, fix fundamentals (page selector, auth, base @steps), re-run. Max 2 attempts. If still broken → ask user.
|
|
257
273
|
6. **Phase 2 — Priority Wave**: Run all `@high` scenarios. Fix only failures from this wave. Max 2 attempts. Shared selectors fixed here cascade to later phases.
|
|
258
274
|
7. **Phase 3 — Full Run**: Run all tests. Fix only **new** failures (elements unique to `@normal`/`@low`). Max 1 attempt. Don't loop on low-priority failures.
|
|
259
|
-
8. **Phase 4 — Regression**: One final full run.
|
|
260
|
-
9. **Phase 8 — Serial-cascade risk check** (#414): If any scenario has many steps, a skipped test may cause downstream steps to be incorrectly skipped due to the serial-cascade sensor detecting false "not reached" conditions. When you see "test skipped" messages during Phase 3–4 runs, check if the skipped scenario is a **blockers-exist** dependency in the test ledger (`sungen ledger query --screen <name>`). If the scenario had high step count and cascade fired, offer: *"Scenarios with deep steps can trigger serial-cascade skipping. Consider parallelizing this spec with `@concurrent` tags or breaking into smaller scenarios.
|
|
275
|
+
8. **Phase 4 — Regression**: One final full run. No more fix loops. Then run `sungen triage --screen <name>` and render its table as the results summary: every red or flaky scenario already sits in one class (`product-candidate`, `unclassified`, `test-defect`, `environment`, `blocked-capability`, `known-defect`, `flaky`) with the rule and one evidence line. You may move an `unclassified` row into a class only with a written evidence line of your own. You may never turn a `product-candidate` into a `test-defect` by editing the `.feature` or the expected value — the Gherkin is frozen; report it as a candidate bug. For each `product-candidate` you judge to be a product bug, run `sungen defect draft --screen <name> --scenario "<title>"`, fill the record's Summary, check its Expected against `spec.md`, then add `@known-defect:DEF-NNN` to that scenario's tag line (the tag-only exception above). The severity in the draft is `proposed` — confirm it with QA (`AskUserQuestion`) before the hand-back and set `severity_source: qa`. A row you judge is not a product bug stays in the summary with your reason, and gets no record. A `bare-timeout` row (`unclassified`) is never re-run inside this command — Phase 4 was the final run; offer the re-run in Next steps.
|
|
276
|
+
9. **Phase 8 — Serial-cascade risk check** (#414): If any scenario has many steps, a skipped test may cause downstream steps to be incorrectly skipped due to the serial-cascade sensor detecting false "not reached" conditions. When you see "test skipped" messages during Phase 3–4 runs, check if the skipped scenario is a **blockers-exist** dependency in the test ledger (`sungen ledger query --screen <name>`). If the scenario had high step count and cascade fired, offer: *"Scenarios with deep steps can trigger serial-cascade skipping. Consider parallelizing this spec with `@concurrent` tags or breaking into smaller scenarios."* Let the user decide whether to refactor (do not auto-apply parallelization).
|
|
261
277
|
{{#cap parallel-subagents}}
|
|
262
278
|
9. **Integrity check & trace (always run after the final run).**
|
|
263
279
|
- `sungen script-check --screen <name>` — verify the generated spec is a **1:1** of the Gherkin (every non-@manual scenario ↔ one `test()`, no drift). If it reports **DRIFT** (spec hand-edited or stale), re-run `sungen generate --screen <name>` so the spec matches the feature, then re-run — **never hand-edit the generated spec** (auto-fix must edit `selectors.yaml`, not the `.spec.ts`).
|
|
@@ -325,7 +341,7 @@ sungen results merge --screen <name> specs/generated/<name>/subset-tmp.json
|
|
|
325
341
|
rm specs/generated/<name>/subset-tmp.json
|
|
326
342
|
```
|
|
327
343
|
|
|
328
|
-
`--screen` takes the FEATURE basename — for a multi-feature screen (`home.spec.ts` + `home-modal.spec.ts`), each feature has its own result file: merge `home-modal`'s subset with `--screen home-modal`. If the previous run had zero failures, `--last-failed`
|
|
344
|
+
`--screen` takes the FEATURE basename — for a multi-feature screen (`home.spec.ts` + `home-modal.spec.ts`), each feature has its own result file: merge `home-modal`'s subset with `--screen home-modal`. If the previous run had zero failures, `--last-failed` finds no tests: Playwright prints "No tests found", exits 1, and still writes a zero-test report — don't merge it; use `-g "<scenario title>"` to pick the cases instead. `--last-failed` reads the failures of the *previous run only*, so any run in between replaces the list.
|
|
329
345
|
|
|
330
346
|
For a locale run (`SUNGEN_ENV=vi`), the config appends `.vi` before `.json` to WHATEVER `PLAYWRIGHT_JSON_OUTPUT_NAME` says — the temp report lands at `subset-tmp.vi.json`; merge that file into the matching `<name>-test-result.vi.json` explicitly: `sungen results merge specs/generated/<name>/<name>-test-result.vi.json specs/generated/<name>/subset-tmp.vi.json`. A scenario RENAMED by a spec edit leaves its old-title result in the file — the merge warns and keeps it (delivery builds rows from the feature, so it never renders).
|
|
331
347
|
|
|
@@ -360,29 +376,33 @@ If you want to filter scenarios, use `-g "<pattern>"` instead of a reporter over
|
|
|
360
376
|
|
|
361
377
|
## `--change-only` — re-run just what an edit obliges, without losing the rest
|
|
362
378
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
Two commands close that, and the order matters — the backup must exist BEFORE the run, because by
|
|
368
|
-
the time the run finishes the old file is already gone:
|
|
379
|
+
A per-target result file holds the whole unit, so a subset run must never replace it: re-running 3
|
|
380
|
+
cases of a 100-case screen used to throw away the 97 that still passed. The subset is MERGED in
|
|
381
|
+
instead — on web via a temp report, on mobile via a backup taken BEFORE the run (the WDIO reporter
|
|
382
|
+
always writes the fixed-name file, so by the time the run finishes the old one is gone):
|
|
369
383
|
|
|
370
384
|
```bash
|
|
371
385
|
# 1. what does the edit oblige? (empty output = nothing to run, do NOT fall through to a full run)
|
|
372
386
|
npx sungen changed --screen <name> # human-readable, with the reason per scenario
|
|
373
387
|
GREP=$(npx sungen changed --screen <name> --grep)
|
|
374
388
|
|
|
389
|
+
# MOBILE — the WDIO reporter always writes the canonical per-OS file, so back it up first:
|
|
375
390
|
# 2. keep the previous results BEFORE the runner overwrites them
|
|
376
391
|
cp specs/generated/<name>/<name>-test-result.<os>.json /tmp/<name>.prev.json
|
|
377
|
-
|
|
378
392
|
# 3. run only the selected scenarios
|
|
379
393
|
SUNGEN_SPECS='./specs/generated/<name>/<name>.spec.ts' npm run test:mobile -- --mochaOpts.grep "$GREP"
|
|
380
|
-
# web: npx playwright test specs/generated/<name>/<name>.spec.ts -g "$GREP"
|
|
381
|
-
|
|
382
394
|
# 4. merge the subset back over the kept results (same title → new wins, others kept)
|
|
383
395
|
npx sungen results merge /tmp/<name>.prev.json specs/generated/<name>/<name>-test-result.<os>.json \
|
|
384
396
|
-o specs/generated/<name>/<name>-test-result.<os>.json
|
|
385
397
|
|
|
398
|
+
# WEB — Playwright writes its report to PLAYWRIGHT_JSON_OUTPUT_NAME (else test-results/results.json),
|
|
399
|
+
# never to the per-target file by itself: write the subset to a temp report and merge THAT in (#837).
|
|
400
|
+
# With --env <x>: prefix BOTH commands with SUNGEN_ENV=<x>; the config then writes subset-tmp.<x>.json.
|
|
401
|
+
PLAYWRIGHT_JSON_OUTPUT_NAME=specs/generated/<name>/subset-tmp.json \
|
|
402
|
+
npx playwright test specs/generated/<name>/<name>.spec.ts -g "$GREP"
|
|
403
|
+
npx sungen results merge --screen <name> specs/generated/<name>/subset-tmp.json # --env x → subset-tmp.x.json
|
|
404
|
+
rm specs/generated/<name>/subset-tmp*.json
|
|
405
|
+
|
|
386
406
|
# 5. record the new baseline — ONLY after a run you accept
|
|
387
407
|
npx sungen changed --screen <name> --record
|
|
388
408
|
```
|
|
@@ -398,6 +418,45 @@ change that broke it.
|
|
|
398
418
|
**Without `--change-only`** the full run still writes the file wholesale, which is correct — a full
|
|
399
419
|
run IS the complete picture. Merging only matters for subsets.
|
|
400
420
|
|
|
421
|
+
## `--ids` — run a chosen list of test-case IDs
|
|
422
|
+
|
|
423
|
+
The user names the cases (`--ids VP-UI-001,VP-UI-002`). `sungen select` resolves them —
|
|
424
|
+
deterministic, exact ID match, grouped per feature — and refuses anything it cannot run:
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
npx sungen select --screen <name> --ids <ID,…> # human-readable
|
|
428
|
+
npx sungen select --screen <name> --ids <ID,…> --json # what you act on
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**Exit 1 = do not run.** Report every entry of `unknown` (with its `didYouMean`), `notRunnable`
|
|
432
|
+
(manual / owned by a flow — with the reason) and `notCompiled` (→ `sungen generate` first), then
|
|
433
|
+
use `AskUserQuestion` to offer: run the valid IDs only / correct the list. Never fall back to a
|
|
434
|
+
full run, and never run with an empty grep.
|
|
435
|
+
|
|
436
|
+
Then, **for each entry of `features`** (a multi-feature screen has one spec and one result file per
|
|
437
|
+
feature), with `<spec>` = its `spec`, `<f>` = its `feature`, `<dir>` = the spec's directory and
|
|
438
|
+
`GREP` = its `grep`:
|
|
439
|
+
|
|
440
|
+
```bash
|
|
441
|
+
# WEB — write the subset to a temp report, then merge it into <f>'s per-target file.
|
|
442
|
+
# With --env <x>: prefix BOTH commands with SUNGEN_ENV=<x>; the config then writes subset-tmp.<x>.json.
|
|
443
|
+
PLAYWRIGHT_JSON_OUTPUT_NAME=<dir>/subset-tmp.json npx playwright test <spec> -g "$GREP"
|
|
444
|
+
npx sungen results merge --screen <f> <dir>/subset-tmp.json # --env x → <dir>/subset-tmp.x.json
|
|
445
|
+
rm <dir>/subset-tmp*.json
|
|
446
|
+
|
|
447
|
+
# MOBILE — the reporter always writes <dir>/<f>-test-result.<android|ios>[.<env>].json: back it up first
|
|
448
|
+
# (with --env <x> every <f>-test-result.<os>.json below is <f>-test-result.<os>.<x>.json)
|
|
449
|
+
cp <dir>/<f>-test-result.<os>.json /tmp/<f>.prev.json
|
|
450
|
+
SUNGEN_SPECS='./<spec>' npm run test:mobile -- --mochaOpts.grep "$GREP"
|
|
451
|
+
npx sungen results merge /tmp/<f>.prev.json <dir>/<f>-test-result.<os>.json -o <dir>/<f>-test-result.<os>.json
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
With no previous result file (first run of the unit, or of this `--env`) there is nothing to merge
|
|
455
|
+
into — `results merge --screen` says so and exits 1: on web run with
|
|
456
|
+
`PLAYWRIGHT_JSON_OUTPUT_NAME=<dir>/<f>-test-result.json`, on mobile skip the backup and the merge.
|
|
457
|
+
With `--both`, back up and merge each OS's file. **Do NOT run `sungen changed --record`** (see the
|
|
458
|
+
scope gate). Report the per-ID outcome, plus the IDs that were refused.
|
|
459
|
+
|
|
401
460
|
## Next steps
|
|
402
461
|
|
|
403
462
|
After showing results, use `AskUserQuestion` to offer next steps:
|
|
@@ -421,3 +480,7 @@ If tests **failed** (after retries):
|
|
|
421
480
|
- **`/sungen-create-test <name>`** — Revise test cases
|
|
422
481
|
{{/cap}}
|
|
423
482
|
- **Done for now** — I'll fix manually later
|
|
483
|
+
|
|
484
|
+
If the triage table has `bare-timeout` rows, put this option FIRST and mark it Recommended: **Re-run the N timed-out scenario(s) once** — it tells a slow environment from a hanging page (name them). Ask; never re-run them on your own: a scenario may create data or spend an OTP/rate limit on a shared environment. On a yes, re-run only those scenarios with the subset-merge flow (§ Playwright command guidelines — never overwrite the result file), then `sungen triage` again:
|
|
485
|
+
- green now → move the row to `flaky` (or `environment`) with that as the evidence line;
|
|
486
|
+
- the same timeout again → read the trace's last action: stuck after a submit or a navigation → candidate bug, handled as in Phase 4 step 8 (`sungen defect draft`, QA confirms the severity); stuck in a wait the test itself defines → `test-defect`.
|
|
@@ -6,7 +6,7 @@ Use **pre-existing images** in `requirements/ui/` as visual context. No network,
|
|
|
6
6
|
|
|
7
7
|
### 1. List available images
|
|
8
8
|
|
|
9
|
-
Glob `requirements/ui/*.{png,jpg,jpeg,webp,gif}` and report count + filenames. Filter out metadata files (e.g. `figma-meta.md` written by mode figma-mcp) — those are read by `tc-generation` separately, not treated as images here.
|
|
9
|
+
Glob `requirements/ui/*.{png,jpg,jpeg,webp,gif}` and report count + filenames. Filter out metadata files (e.g. `figma-meta.md` written by mode figma-mcp) — those are read by `tc-generation` (§ Design Inventory) separately, not treated as images here.
|
|
10
10
|
|
|
11
11
|
### 2. Handle empty folder
|
|
12
12
|
|
|
@@ -21,7 +21,7 @@ If no images found:
|
|
|
21
21
|
|
|
22
22
|
### 3. Read images for context
|
|
23
23
|
|
|
24
|
-
Use the `Read` tool on each image — Claude Code reads PNG/JPG/WebP directly
|
|
24
|
+
Use the `Read` tool on **each** image — Claude Code reads PNG/JPG/WebP directly. For large sets (>10 images), ask which are primary and which are states/variants so they can be grouped — but still read them all: every image feeds the Design Inventory (`sungen-tc-generation` § Design Inventory), and the inventory records `images read: N/N`.
|
|
25
25
|
|
|
26
26
|
### 4. Summarize
|
|
27
27
|
|
|
@@ -93,6 +93,20 @@ every variant is N/A) and never a bare state word. **`N/A` leaves the denominato
|
|
|
93
93
|
and actual result share one column `P`; the header row is frozen; ISO dates; landscape print with
|
|
94
94
|
repeated header rows.
|
|
95
95
|
|
|
96
|
+
**Re-running delivery keeps the tester's Manual results** (#756, since 3.2.33). Before overwriting,
|
|
97
|
+
the CLI reads the existing workbook's **Manual** sheet and carries each variant's `L`–`P` cells into
|
|
98
|
+
the new one by `VP-…` ref, verbatim. A hidden `_sungen_manual` sheet stamps each case's fingerprint,
|
|
99
|
+
so a result recorded against an older procedure is reset to `Pending` with the previous result
|
|
100
|
+
moved into Note. Relay the CLI's `Manual results:` lines to the user: `reset to Pending` means those
|
|
101
|
+
cases must be run again by hand; `not carried` names results whose case left the feature. The
|
|
102
|
+
**Auto** sheet is not carried (the run report owns its Result), and rows a tester added by hand
|
|
103
|
+
have no ref and are not carried. Never tell the user to copy or rename the file to protect manual
|
|
104
|
+
results. A second `not carried` line names a duplicated row (only the first copy is kept) — tell
|
|
105
|
+
the user to merge it by hand. If the CLI prints `not written: cannot read …` (locked or damaged) or
|
|
106
|
+
`not written: … has no "Manual" sheet` (renamed), the unit was deliberately NOT written to protect
|
|
107
|
+
the results: ask the user to close the file or rename the sheet back to `Manual`, or move the file
|
|
108
|
+
aside. Never delete, rename or move it yourself.
|
|
109
|
+
|
|
96
110
|
`Coverage` sheet — requirement coverage table (every FR/TR/NFR id with an explicit status),
|
|
97
111
|
target × category grid with explicit `—` gaps, dispositions, manifest. CSV mirrors the same model
|
|
98
112
|
flat with a `Level` column (`item`/`variant`) + a requirement-coverage appendix.
|
|
@@ -39,6 +39,26 @@ weakening assertions, "fixing" an unknown step pattern, adding table-scope steps
|
|
|
39
39
|
needs any of these, it is a **finding for QA** — surface it in the run summary and let the test
|
|
40
40
|
**FAIL**. A failing test may be a **real bug**; do not edit the QA-approved Gherkin to make it pass.
|
|
41
41
|
|
|
42
|
+
### Fails because the environment lacks the DATA or CAPABILITY (not the app, not the locator)
|
|
43
|
+
|
|
44
|
+
Sometimes the scenario is right and the app may be right, but the run cannot set up the state —
|
|
45
|
+
the dev seed has no tie-break pair, no locked account, no second tenant. That is **neither** a
|
|
46
|
+
selector fix **nor** a reason to rewrite. The only allowed `.feature` edit is a **tag** (plus a
|
|
47
|
+
reason comment); the Given/When/Then stay **exactly** as QA approved them:
|
|
48
|
+
|
|
49
|
+
1. The capability exists as a driver (`db`, `api`, data-factory) → tag `@requires:<cap>` (e.g.
|
|
50
|
+
`@requires:db`) — it compiles to a skip stub (`AUTOMATION-READY-PENDING`) and runs, unchanged,
|
|
51
|
+
once `sungen capability add <cap>` is done.
|
|
52
|
+
2. Otherwise → tag `@manual:M1` and put the reason as a comment **inside** the scenario (below the
|
|
53
|
+
`Scenario:` line — a comment above the tags is attached to the previous scenario):
|
|
54
|
+
`# MANUAL (<date>, run-test): no seeded pair with equal plan + distinct last-updated`.
|
|
55
|
+
3. **Never** swap the real assertion (`table match data:`, `with {{v}}`, `count is …`) for a
|
|
56
|
+
presence placeholder (`see [X] table`) and move the oracle into a `# Tester verifies:` comment —
|
|
57
|
+
that hybrid exports an Expected cell that says nothing about what is checked, and `sungen
|
|
58
|
+
generate` flags it `SG-W008`.
|
|
59
|
+
4. List **every** downgrade of the run (scenario, tag added, reason) in the run summary so QA
|
|
60
|
+
reviews it — a downgrade is a coverage decision, not an auto-fix.
|
|
61
|
+
|
|
42
62
|
## ⛔ Source of truth — classify EVERY failure before you "fix" it
|
|
43
63
|
|
|
44
64
|
`.feature` + `test-data.yaml` + `spec.md` are the **oracle**. The **live page is NOT** — it may be the thing that's broken. A failing test is not automatically a test to "make pass". Classify first:
|
|
@@ -53,6 +73,8 @@ needs any of these, it is a **finding for QA** — surface it in the run summary
|
|
|
53
73
|
|
|
54
74
|
> **Cardinal sin (do NOT do this):** a `password > 8 chars` rule fails on a 6-char input → "fix" it to `>= 6` so the test passes. The logic is now meaningless. A failing assertion is a **finding**, not a chore.
|
|
55
75
|
|
|
76
|
+
**`sungen triage` makes the first pass for you.** Its classes are this section's split: `test-defect` = selector-resolution / test-data failure (auto-fix scope), `product-candidate` = assertion-value failure with an Expected and a Received (apply the spec question above), `environment` = the run itself (fix the setup, not the test), `unclassified` = yours to judge — an assertion on an element that never appeared lands here, because a wrong selector and a missing message look the same.
|
|
77
|
+
|
|
56
78
|
**Auto-fix loop scope:** the run-test auto-fix loop engages ONLY on **selector-resolution** failures. On an assertion-value failure where the app contradicts the spec → **HALT and report**, do not loop it into passing.
|
|
57
79
|
|
|
58
80
|
**Never hand-edit the generated `.spec.ts`** (e.g. inserting `page.evaluate`/`fetch` to bypass a broken control). `sungen script-check` regenerates the spec from `.feature` and flags any edit as DRIFT — regenerate, don't patch.
|
|
@@ -128,8 +150,10 @@ needs any of these, it is a **finding for QA** — surface it in the run summary
|
|
|
128
150
|
| `SG-W034` | A `see [X] column with {{v}}` step runs inside a table whose rows are declared with a **`rows:` shape**, so the row is not an ARIA row and holds no ARIA cells — but the assertion's only other way to reach a cell is `getByRole('cell')`, which matches nothing there. `columns.<col>.index` cannot rescue it: it indexes that same empty set. Before this the step failed as a timeout blaming the app. Not reported on a real `<table>`, where the role fallback is correct | Name the cell on the column: `columns: { title: { index: 0, header: 'Title', elements: { cell: { type: locator, value: '.job-title' } } } }`. This is a selectors.yaml-only fix — allowed inside the run-test auto-fix loop |
|
|
129
151
|
| `SG-E035` | **`table match data:` on a table declared with a `rows:` shape** and no matching `columns:` entries. The assertion reads its header row from `thead tr` and addresses cells as `td, th`; a <div> list has neither — forever, not as a render race — so the step could only wait out every timeout and fail on an empty header row. Refused at compile time, naming the columns it needs | Declare each DataTable column on the table entry with the selector that matches its cell inside a row: `columns: { title: { index: 0, header: 'Title', elements: { cell: { type: locator, value: '.job-title' } } } }`. Declaring columns also removes the runtime header read on a real `<table>`. This is a selectors.yaml-only fix — allowed inside the run-test auto-fix loop |
|
|
130
152
|
| `SG-W036` | A **`remember [X] … as {{v}}` capture through a `locator`/`css` selector with no `nth:`**. A capture reads ONE element and the step takes the FIRST match — the right default, and what the documented `nth: 0` workaround asked for after Playwright's strict mode turned a list-shaped selector into a hard failure naming the count. But the first of many is a decision: if the selector describes every item in a list, the captured value is the first row's. Not reported for testid/label/placeholder/role+name/text entries, which name a particular thing | Declare the index (`nth: 0`) to say the first one is meant, or narrow the selector to the single element. This is a selectors.yaml-only fix — allowed inside the run-test auto-fix loop |
|
|
153
|
+
| `SG-W037` | A **`type: page` entry saying something about the QUERY that the compiler cannot use**. Two causes: the entry's `value` carries a `?`/`#`, which is DROPPED (a page value is the path only — the pattern is matched against `u.pathname`, which never holds a query), or `query:` declares something other than `any`, which is ignored rather than read as permissive so a typo cannot quietly switch off the bare-page assertion. Both used to be silent, and the first is the trap: an author who hit "a bare `see [X] page` requires NO query" reaches for the query in the value, gets byte-identical output, and no hint why | To assert the query, declare it on the STEP (`see [X] page with {{v}}`). If the query is generated at run time — `/admins/detail?id=<the row just clicked>`, which no literal can express — add `query: any` to the entry: the query is then not part of that page's identity. selectors.yaml-only fix — allowed inside the run-test auto-fix loop |
|
|
154
|
+
| `SG-E038` | A **`{{var}}` the compiler cannot resolve** — the feature has no test-data file of its own, the key is absent, or it holds a list/map where a value was needed. This used to emit the PLACEHOLDER TEXT as the value: `fill [Partner Customer ID] field with {{valid_partner_id}}` compiled to `fill('${valid_partner_id}')`, typing those 20 literal characters into the app with `generate` exiting 0. A field with no format validation accepts the string, the server sees an unknown user, and the scenario fails at the assertion it was written to fail at — a suite that looks correct while feeding the system garbage. Every run also shares the SAME literal, so a scenario needing a fresh user silently reuses one. The step now compiles to a `throw` naming the ref and the file | Add the key to the file the message names. Note a feature resolves `{{var}}` against a data file named after **itself** — `qa/screens/<screen>/test-data/<feature>.yaml` — so the second `.feature` in a screen directory needs its own data file, not the screen-named one. `sungen data crosscheck` reports the same gap before you compile |
|
|
131
155
|
|
|
132
|
-
A diagnostic never changes generation's own exit code — `sungen generate --strict` turns any collected diagnostic into a non-zero exit for CI gates. They are not all inert, though: **`SG-W001`, `SG-W011`, `SG-E020`, `SG-E021`, `SG-W020`, `SG-E023`, `SG-E024`, `SG-E025`, `SG-E026`, `SG-E027` and `SG-
|
|
156
|
+
A diagnostic never changes generation's own exit code — `sungen generate --strict` turns any collected diagnostic into a non-zero exit for CI gates. They are not all inert, though: **`SG-W001`, `SG-W011`, `SG-E020`, `SG-E021`, `SG-W020`, `SG-E023`, `SG-E024`, `SG-E025`, `SG-E026`, `SG-E027`, `SG-E035` and `SG-E038` additionally compile the offending step to a runtime `throw`, and `SG-E031` refuses the whole file** — a step that reads as a check and silently checks nothing is worse than one that fails loudly. Generation always COMPLETES: the rest of the scenario and the rest of the file still compile. `SG-E022` is the odd one out — it blames the compiler, not your `.feature`, and throws nothing (the file is written so you can inspect it).
|
|
133
157
|
|
|
134
158
|
### Runtime error → `Test data "<key>" references ${QA_*} but the environment variable is not set`
|
|
135
159
|
|
|
@@ -629,7 +629,9 @@ 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 |
|
|
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. `@known-defect:DEF-NNN` names the record in `qa/defects/DEF-NNN-*.md` (`sungen defect draft` writes it); `sungen audit` reports `DEFECT-REF-MISSING` when that file does not exist. **`[mobile]`** Its failure does NOT escalate the next scenario's `@reset:` tier: a red that was designed in is not evidence of leftover state |
|
|
633
635
|
| `@auth:role` | Use auth storage state for role |
|
|
634
636
|
| `@no-auth` | Disable inherited auth |
|
|
635
637
|
| `@steps:name` | Define reusable step block (base scenario) |
|
|
@@ -639,7 +641,8 @@ on mobile a dialog-scoped ref still resolves against the whole screen (`SG-W021`
|
|
|
639
641
|
| `@cleanup:scroll` | Auto-cleanup: scroll to top after each test (cleanupPage) |
|
|
640
642
|
| `@cleanup:storage` | Auto-cleanup: clear sessionStorage after each test (cleanupPage) |
|
|
641
643
|
| `@screenshot:on-failure` | Auto-capture screenshot when test fails (base.ts fixture) |
|
|
642
|
-
| `@
|
|
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 |
|
|
643
646
|
| `@beforeAll` | Hook: runs once before all tests → `test.beforeAll()` |
|
|
644
647
|
| `@afterEach` | Hook: runs after each test → `test.afterEach()` (custom cleanup) |
|
|
645
648
|
| `@afterAll` | Hook: runs once after all tests → `test.afterAll()` |
|
|
@@ -695,6 +698,14 @@ Rules that matter when generating:
|
|
|
695
698
|
relaunch does not undo a half-written local DB. One rung, one scenario, and never from `none`.
|
|
696
699
|
A **retry** of the failed scenario is NOT escalated — it re-runs at its declared tier, so a
|
|
697
700
|
state-dependent failure fails both attempts and is reported honestly instead of passing on attempt 2.
|
|
701
|
+
A scenario tagged **`@known-defect`** escalates nothing either: its red was designed in, so making
|
|
702
|
+
the next scenario pay a harder reset for it buys nothing, on every run, forever.
|
|
703
|
+
- **Escalation never picks a tier this session cannot perform.** Reinstalling needs the app's build
|
|
704
|
+
file, so when the app is attached by package the ladder caps at `data` (Android) / `soft` (iOS) and
|
|
705
|
+
says it capped, instead of throwing. Nothing asked for the escalated tier, and the throw would land
|
|
706
|
+
in `beforeEach` — a hook failure, which skips every remaining scenario in the FILE. The cap never
|
|
707
|
+
goes BELOW the declared tier: a tier you asked for that the session cannot do still throws by name,
|
|
708
|
+
because that one is an unmet contract rather than a recovery the runner chose.
|
|
698
709
|
- **`SUNGEN_RESET_TIER=data` raises the floor for a whole run** without regenerating specs — CI can run
|
|
699
710
|
stricter than local dev. It never lowers a declared tier.
|
|
700
711
|
- **`data`/`full` on iOS reinstall the app**, because `mobile: clearApp` is Android-only (UiAutomator2).
|
|
@@ -765,14 +776,14 @@ npx playwright test --grep "@smoke|@high" # smoke OR high
|
|
|
765
776
|
|
|
766
777
|
### Serial vs Parallel (test execution mode)
|
|
767
778
|
|
|
768
|
-
**Default:
|
|
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.
|
|
769
780
|
|
|
770
|
-
**`@
|
|
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.
|
|
771
782
|
|
|
772
783
|
| Mode | Generated | Page | Background | On fail |
|
|
773
784
|
|---|---|---|---|---|
|
|
774
|
-
|
|
|
775
|
-
| `@
|
|
785
|
+
| Isolated (default, `@parallel`) | `test.describe()` | Fresh per test | `beforeEach` (N goto) | Continue |
|
|
786
|
+
| `@serial` | `test.describe.serial()` | Shared | `beforeAll` (1 goto) | Skip remaining |
|
|
776
787
|
|
|
777
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.
|
|
778
789
|
|
|
@@ -933,7 +944,13 @@ Feature: User Management
|
|
|
933
944
|
|
|
934
945
|
### Layer 2: `@afterEach` scenario (custom cleanup)
|
|
935
946
|
|
|
936
|
-
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.
|
|
937
954
|
|
|
938
955
|
### Layer 3: `@beforeAll` / `@afterAll` (optional)
|
|
939
956
|
|
|
@@ -958,8 +975,9 @@ Scenario: drop the seeded data after the last scenario
|
|
|
958
975
|
recorded and the next step still runs; a failing action step (`Given`/`When`) stops the hook there.
|
|
959
976
|
The hook fails ONCE with the full list (`Hook preconditions not met`), not with the first failure.
|
|
960
977
|
- `@cases` and `@extend` are not supported on a hook — they are ignored with a compile warning.
|
|
961
|
-
-
|
|
962
|
-
`@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`.
|
|
963
981
|
|
|
964
982
|
**Rendering order in `.spec.ts`:**
|
|
965
983
|
`test.describe` → `test.use(storageState)` → `test.use(autoCleanup)` → `test.beforeAll` → `test.beforeEach` → `test.afterEach` → `test.afterAll` → `test()` blocks.
|
|
@@ -35,7 +35,11 @@ user-invocable: false
|
|
|
35
35
|
| **BALANCE** | secondary viewpoints (UI/validation/security) outweigh business-core | **Stop expanding** secondary viewpoints; generate the missing business-core scenarios first. Do not add more subscription/UI variants while core is thin. |
|
|
36
36
|
| **TRACE** | scenarios use ad-hoc `VP-<CAT>-NNN` codes not linked to the viewpoint-overview | Make each scenario map to a viewpoint-overview id (align category codes, or add a mapping comment). |
|
|
37
37
|
| **ORACLE-URL-ONLY** | every `Then` in the scenario is a page/URL assertion — it proves a path was pushed, not that the page rendered; on a permission/guard scenario a late 403 redirect turns it falsely green | Add `anchor:` to the page selector (one line per screen; every `see [X] page` on it becomes a content oracle) or a content assertion after the page step. Never delete the page step to silence it. |
|
|
38
|
+
| **DEFECT-REF-MISSING** | a `@known-defect:DEF-NNN` tag names no file in `qa/defects/` | Draft the record (`sungen defect draft --screen <name> --scenario "<title>"`) or correct the id. Never drop the tag to silence it — the scenario still asserts a live defect. |
|
|
39
|
+
| **DEFECT-ORPHAN** (info) | an open defect record names a scenario this unit no longer has | Update the record's `scenarios:` to the renamed title, or close the record if the scenario was removed on purpose. Nothing in the suite to repair. |
|
|
38
40
|
| **UNIVERSAL** | a universal theme (error/empty-state, accessibility) is absent | Low priority — add if in scope; otherwise note as out-of-scope with reason. |
|
|
41
|
+
| **VIEWPOINT-DRAFT-UNREVIEWED** | `test-viewpoint.md` carries `drafted-by: ai`: no baseline, `atomicLedger` + `traceability` held | A QA action, not a repair. Keep generating; list the decision `sungen audit --screen <name> --accept-viewpoint` in the hand-back for the QA to run after reviewing the draft. Never run it, never delete the line yourself. |
|
|
42
|
+
| **VIEWPOINT-REVIEW-OPEN** (info) | `requirements/viewpoint-review.md` still has `[ ]` rows | A QA action. Report the count in the hand-back with the option to open the file; never tick rows or edit a QA-written viewpoint to clear it. Not scored. |
|
|
39
43
|
|
|
40
44
|
## P5 steps for deep cross-screen / list coverage
|
|
41
45
|
|
|
@@ -64,7 +68,7 @@ Use these when repairing GATE/DEPTH findings for the hard viewpoints (cart/detai
|
|
|
64
68
|
## Repair loop rules
|
|
65
69
|
|
|
66
70
|
1. **Budget = 3 rounds.** Re-run `sungen audit` after each repair; track score delta.
|
|
67
|
-
2. **Stop when** `gateStatus == PASS` AND `findings` empty — or budget exhausted.
|
|
71
|
+
2. **Stop when** `gateStatus == PASS` AND `findings` empty — or budget exhausted. QA-action findings (`VIEWPOINT-DRAFT-UNREVIEWED`, `VIEWPOINT-REVIEW-OPEN`) do not count: no repair clears them.
|
|
68
72
|
3. **Never fake a pass.** A shallow `see [Cart] page` does not satisfy `cart-correctness`. If a gap is genuinely cross-screen or needs capabilities the DSL lacks (e.g. capture an element value to compare elsewhere), **report it as a residual gap / flow item** instead of forcing a green gate.
|
|
69
73
|
4. **EP/data families are OK.** A `duplicates` cluster with `sameDataLikely=false` is an intentional equivalence-partition family (e.g. many invalid-email cases) — keep it; only collapse `sameDataLikely=true` exact duplicates.
|
|
70
74
|
5. **Advisory findings — surface, don't gate.** `MANUAL-REASON-MISMATCH` → fix the scenario's `@manual:Mx` code (so the planner recommends the right driver) during repair. `CAPABILITY-SUGGESTION` → **present it to the user as a next-step option** (e.g. "N @manual could be automated — `sungen capability add api db`?"), **recommend-only — never auto-install**. `VERIFICATION-OUT-OF-SCOPE (api|db)` → the unit uses `@api`/`@query`/`@requires:api|db` verification the project's recorded **test type** never opted into (E2E/UI-only per `capabilities.yaml`, and the viewpoint doesn't ask for it). During repair: **rewrite the oracle to be UI-observable** (or downgrade the deep check to an `(optional deep check: …)` note); only keep the API/DB verification if the project genuinely tests that layer — then record it (`verification: [ui, api]` / `sungen capability add`). Keep API/DB-in-E2E to the ≤20% band. Neither of these fails the gate.
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
@@ -128,7 +128,10 @@ back to the feature's own path (or `/<ref>/`) and warns `SG-W013`: a test that r
|
|
|
128
128
|
|
|
129
129
|
If the label is used by only ONE type, the base key (no suffix) is fine — suffix only on collision.
|
|
130
130
|
|
|
131
|
-
Type aliases (normalized automatically)
|
|
131
|
+
Type aliases (normalized automatically). The suffix and the step may use **different spellings of
|
|
132
|
+
the same type** — `confirm--modal` resolves for `[Confirm] dialog` and `confirm--dialog` resolves
|
|
133
|
+
for `[Confirm] modal`. Prefer the normalized suffix for consistency; either is found.
|
|
134
|
+
|
|
132
135
|
| Gherkin type | Normalized suffix |
|
|
133
136
|
|---|---|
|
|
134
137
|
| title, label, caption, message | `text` |
|
|
@@ -143,6 +146,15 @@ Type aliases (normalized automatically):
|
|
|
143
146
|
| column | `columnheader` |
|
|
144
147
|
| list-item | `listitem` |
|
|
145
148
|
|
|
149
|
+
When the step names a type from this table, only a key whose suffix is a spelling of that type is
|
|
150
|
+
used — `[Confirm] dialog` will not fall back to an unrelated `confirm--popup` entry. It reports the
|
|
151
|
+
keys it looked for, so the fix is to add one of them.
|
|
152
|
+
|
|
153
|
+
A bare `[Confirm]` keeps the older, looser fallback and matches any `confirm--*` entry, because with
|
|
154
|
+
no type there is nothing to match a suffix against. So does a `[Ref]` followed by a word that is not
|
|
155
|
+
an element type at all — `Then User see [Quick Panel] is hidden` reads `is` as that word. This is
|
|
156
|
+
what keeps state-clause steps working on a label whose keys are all suffixed.
|
|
157
|
+
|
|
146
158
|
## Nth-Suffixed Keys
|
|
147
159
|
|
|
148
160
|
When targeting a specific occurrence by index, add `--N` suffix:
|