@sun-asterisk/sungen 3.2.32 → 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.
- 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 +26 -4
- 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 +35 -17
- 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/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +79 -53
- 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/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/index.js +7 -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.map +1 -1
- package/dist/exporters/csv-exporter.js +11 -10
- package/dist/exporters/csv-exporter.js.map +1 -1
- package/dist/exporters/feature-parser.d.ts +21 -0
- package/dist/exporters/feature-parser.d.ts.map +1 -1
- package/dist/exporters/feature-parser.js +32 -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 +19 -9
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/carry-manual-results.d.ts +70 -0
- package/dist/exporters/matrix/carry-manual-results.d.ts.map +1 -0
- package/dist/exporters/matrix/carry-manual-results.js +232 -0
- package/dist/exporters/matrix/carry-manual-results.js.map +1 -0
- package/dist/exporters/matrix/export.d.ts +5 -0
- package/dist/exporters/matrix/export.d.ts.map +1 -1
- package/dist/exporters/matrix/export.js +8 -1
- 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-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/types.d.ts +8 -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/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 +47 -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/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 +29 -12
- 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/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/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/next-step.d.ts.map +1 -1
- package/dist/harness/next-step.js +1 -0
- package/dist/harness/next-step.js.map +1 -1
- package/dist/harness/parse.d.ts +24 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +117 -13
- 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/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 +102 -27
- 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/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-ledger.d.ts.map +1 -1
- package/dist/harness/viewpoint-ledger.js +66 -10
- package/dist/harness/viewpoint-ledger.js.map +1 -1
- 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/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 +3 -11
- 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 +2 -2
- package/dist/orchestrator/templates/ai-src/commands/review.md +2 -2
- package/dist/orchestrator/templates/ai-src/commands/run-test.md +70 -13
- 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 +23 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +26 -8
- 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 +41 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -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 +20 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.d.ts.map +1 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.js +45 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.js.map +1 -0
- package/package.json +3 -3
- package/src/cli/commands/audit.ts +24 -5
- package/src/cli/commands/capability.ts +51 -18
- package/src/cli/commands/changed.ts +2 -4
- package/src/cli/commands/dashboard.ts +1 -26
- package/src/cli/commands/delivery.ts +75 -48
- 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/update.ts +3 -0
- package/src/cli/index.ts +7 -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 +7 -10
- package/src/exporters/feature-parser.ts +32 -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 +20 -10
- package/src/exporters/matrix/carry-manual-results.ts +229 -0
- package/src/exporters/matrix/export.ts +14 -4
- package/src/exporters/matrix/gates.ts +6 -0
- package/src/exporters/matrix/render-testcase-sheet.ts +10 -4
- package/src/exporters/matrix/types.ts +8 -1
- package/src/exporters/matrix/wording.ts +36 -2
- package/src/exporters/run-environment.ts +89 -0
- package/src/exporters/scenario-merger.ts +49 -4
- package/src/exporters/test-data-resolver.ts +0 -6
- 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 +37 -16
- 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/data-driven-lint.ts +82 -24
- 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/next-step.ts +1 -0
- package/src/harness/parse.ts +123 -16
- 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/secret-scan.ts +60 -4
- package/src/harness/select-by-ids.ts +83 -0
- package/src/harness/sensors.ts +109 -28
- package/src/harness/spec-branches.ts +6 -3
- package/src/harness/spec-coverage.ts +14 -4
- package/src/harness/ui-inventory.ts +164 -0
- package/src/harness/viewpoint-ledger.ts +59 -12
- 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/project-deps-sync.ts +23 -1
- package/src/orchestrator/project-initializer.ts +54 -6
- package/src/orchestrator/screen-manager.ts +3 -11
- 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 +2 -2
- package/src/orchestrator/templates/ai-src/commands/review.md +2 -2
- package/src/orchestrator/templates/ai-src/commands/run-test.md +70 -13
- 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 +23 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +26 -8
- 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 +41 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -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 +58 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* npm `overrides` a sungen project needs in order to pass `npm audit`.
|
|
4
|
+
*
|
|
5
|
+
* Why this lives in the CLI instead of in `packages/core/package.json`: npm honours `overrides`
|
|
6
|
+
* ONLY in the root `package.json` of the project doing the installing. A block declared by a
|
|
7
|
+
* DEPENDENCY is inert — it is not read, not merged, and not carried in the published tarball. So
|
|
8
|
+
* the monorepo root can (and does) pin these for itself while every consumer of the published
|
|
9
|
+
* packages still resolves the vulnerable versions. Repo green, install red, and nobody working in
|
|
10
|
+
* the repo ever sees what a consumer sees. Issue #764.
|
|
11
|
+
*
|
|
12
|
+
* Sungen already writes to the consuming project's `package.json` (standard scripts on `init`,
|
|
13
|
+
* family version pinning on `update`), so the overrides go in on the same two passes. That makes
|
|
14
|
+
* the fix reachable the ordinary way: a new project is clean from its first install, an existing
|
|
15
|
+
* one becomes clean on the next `sungen update`.
|
|
16
|
+
*
|
|
17
|
+
* Every entry below is here because NOTHING ELSE CLEARS IT — the offending package is either at its
|
|
18
|
+
* latest published version already, or is hard-pinned by an unmaintained parent. Bumping sungen's
|
|
19
|
+
* own declared ranges does not move any of them: `@sungen/driver-mobile` is already on the newest
|
|
20
|
+
* appium (3.x) and webdriverio (9.x), and npm's own `fix available` for that chain is a DOWNGRADE
|
|
21
|
+
* to appium 1.22.3 / webdriverio 8.14.6, not a fix.
|
|
22
|
+
*
|
|
23
|
+
* Measured on a clean-room install of the published 3.2.32 family (2026-09-23): 25 findings
|
|
24
|
+
* (12 moderate, 13 high) without this block, 0 with it.
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.SECURITY_OVERRIDES = void 0;
|
|
28
|
+
/**
|
|
29
|
+
* The pinned set. Keep it MINIMAL: an entry earns its place only while a clean install is red
|
|
30
|
+
* without it. When an upstream finally ships a fix inside its own declared range, delete the entry
|
|
31
|
+
* rather than raising it — a stale override silently holds a whole subtree back.
|
|
32
|
+
*/
|
|
33
|
+
exports.SECURITY_OVERRIDES = [
|
|
34
|
+
{
|
|
35
|
+
pkg: 'uuid',
|
|
36
|
+
range: '^11.1.1',
|
|
37
|
+
// exceljs 4.4.0 IS the latest (published 2024-12-20) and hard-declares "uuid": "^8.3.0".
|
|
38
|
+
// There is no newer exceljs to bump to, which is why npm reports fixAvailable: false.
|
|
39
|
+
why: 'GHSA-w5hq-g745-h8pq (moderate) — uuid@8.3.2 via exceljs@4.4.0, which is unmaintained and pins ^8.3.0',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
pkg: 'morgan',
|
|
43
|
+
range: '^1.12.1',
|
|
44
|
+
// @appium/base-driver pins the exact version "1.11.0", so no resolution reaches 1.12.x on its own.
|
|
45
|
+
why: 'GHSA-jxfw-x594-9x9m (moderate) — morgan@1.11.0 exact-pinned by @appium/base-driver',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
pkg: 'serialize-javascript',
|
|
49
|
+
range: '^7.1.2',
|
|
50
|
+
why: 'GHSA-5c6j-r48x-rmvq (high) + GHSA-qj8w-gfj5-8c6v (moderate) — serialize-javascript@6.0.2 via mocha (^6.0.2)',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
pkg: '@puppeteer/browsers',
|
|
54
|
+
range: '^3.2.3',
|
|
55
|
+
// The vulnerable package is extract-zip, whose latest (2.0.1) IS the flagged version — there is
|
|
56
|
+
// nothing to pin it to. @puppeteer/browsers 3.x dropped extract-zip for modern-tar, so the pin
|
|
57
|
+
// goes on the parent instead. @wdio/utils asks for ^2.2.0 but imports only install, canDownload,
|
|
58
|
+
// resolveBuildId, detectBrowserPlatform, Browser, ChromeReleaseChannel and computeExecutablePath
|
|
59
|
+
// — all seven still exported by 3.2.3, verified against @wdio/utils@9.32.0.
|
|
60
|
+
why: 'GHSA-jmr9-qjv8-65gv + GHSA-7pqw-9j4j-h8q3 (high) — extract-zip@2.0.1 via @puppeteer/browsers@2.x ← @wdio/utils; extract-zip has no fixed release, 3.x replaced it with modern-tar',
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
//# sourceMappingURL=security-overrides-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-overrides-catalog.js","sourceRoot":"","sources":["../../src/orchestrator/security-overrides-catalog.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;;AAWH;;;;GAIG;AACU,QAAA,kBAAkB,GAAuB;IACpD;QACE,GAAG,EAAE,MAAM;QACX,KAAK,EAAE,SAAS;QAChB,yFAAyF;QACzF,sFAAsF;QACtF,GAAG,EAAE,sGAAsG;KAC5G;IACD;QACE,GAAG,EAAE,QAAQ;QACb,KAAK,EAAE,SAAS;QAChB,mGAAmG;QACnG,GAAG,EAAE,oFAAoF;KAC1F;IACD;QACE,GAAG,EAAE,sBAAsB;QAC3B,KAAK,EAAE,QAAQ;QACf,GAAG,EAAE,6GAA6G;KACnH;IACD;QACE,GAAG,EAAE,qBAAqB;QAC1B,KAAK,EAAE,QAAQ;QACf,gGAAgG;QAChG,+FAA+F;QAC/F,iGAAiG;QACjG,iGAAiG;QACjG,4EAA4E;QAC5E,GAAG,EAAE,mLAAmL;KACzL;CACF,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { SecurityOverride } from './security-overrides-catalog';
|
|
2
|
+
/**
|
|
3
|
+
* Merge the security-override catalog into a consuming project's `package.json`.
|
|
4
|
+
*
|
|
5
|
+
* The catalog itself — which packages, which ranges, and why each one cannot be cleared any other
|
|
6
|
+
* way — lives in `security-overrides-catalog.ts`. That is the file to edit when an advisory moves;
|
|
7
|
+
* this one holds only the merge, the write and the reporting, which do not change when it does.
|
|
8
|
+
*/
|
|
9
|
+
export { SECURITY_OVERRIDES } from './security-overrides-catalog';
|
|
10
|
+
export type { SecurityOverride } from './security-overrides-catalog';
|
|
11
|
+
export interface OverridePlan {
|
|
12
|
+
/** Entries missing from the project, to be written. */
|
|
13
|
+
add: SecurityOverride[];
|
|
14
|
+
/** Entries the project already pins itself — left untouched, reported so the user can judge. */
|
|
15
|
+
existing: Array<{
|
|
16
|
+
pkg: string;
|
|
17
|
+
declared: string;
|
|
18
|
+
wanted: string;
|
|
19
|
+
}>;
|
|
20
|
+
/** Set when the pins were needed but the write failed — `add` is then empty, nothing was applied. */
|
|
21
|
+
writeFailed?: boolean;
|
|
22
|
+
/** Lockfile of a package manager that ignores `overrides`, when the project has one. */
|
|
23
|
+
foreignLockfile?: 'yarn' | 'pnpm';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Decide what a project's `overrides` block is missing. Pure — no I/O, so the tests and `--dry-run`
|
|
27
|
+
* can plan without touching anything.
|
|
28
|
+
*
|
|
29
|
+
* A pin the project already declares is NEVER rewritten, even when it differs from ours. Someone who
|
|
30
|
+
* typed a range into their own `package.json` had a reason (a private mirror, a pinned fork, a
|
|
31
|
+
* downgrade forced by another tool), and silently overwriting it would be the more surprising bug.
|
|
32
|
+
* It is reported instead, so a still-vulnerable pin is visible rather than swallowed.
|
|
33
|
+
*/
|
|
34
|
+
export declare function planSecurityOverrides(pkgJson: Record<string, any>): OverridePlan;
|
|
35
|
+
/**
|
|
36
|
+
* Write the missing overrides into a project's `package.json`.
|
|
37
|
+
*
|
|
38
|
+
* Best-effort by design, exactly like the rest of the project-file touching in `init` / `update`: an
|
|
39
|
+
* unreadable or malformed `package.json` means we skip silently rather than fail the command the
|
|
40
|
+
* user actually ran. The audit gate is not worth losing a scaffold over.
|
|
41
|
+
*
|
|
42
|
+
* Must run BEFORE the project's `npm install`, or the first resolution pass writes a lockfile that
|
|
43
|
+
* already pins the vulnerable versions.
|
|
44
|
+
*
|
|
45
|
+
* @param dryRun plan only — report what would change and write nothing
|
|
46
|
+
* @returns the plan that was applied, or null when there was no `package.json` to apply it to
|
|
47
|
+
*/
|
|
48
|
+
export declare function ensureSecurityOverrides(packageJsonPath: string, dryRun?: boolean): OverridePlan | null;
|
|
49
|
+
/** Print what `ensureSecurityOverrides` did, in the voice the surrounding commands already use. */
|
|
50
|
+
export declare function reportSecurityOverrides(plan: OverridePlan | null, dryRun?: boolean): void;
|
|
51
|
+
//# sourceMappingURL=security-overrides.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-overrides.d.ts","sourceRoot":"","sources":["../../src/orchestrator/security-overrides.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsB,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEpF;;;;;;GAMG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,GAAG,EAAE,gBAAgB,EAAE,CAAC;IACxB,gGAAgG;IAChG,QAAQ,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,qGAAqG;IACrG,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,wFAAwF;IACxF,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,YAAY,CAuBhF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,YAAY,GAAG,IAAI,CA2BpG;AAeD,mGAAmG;AACnG,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,EAAE,MAAM,UAAQ,GAAG,IAAI,CAgCvF"}
|
|
@@ -0,0 +1,165 @@
|
|
|
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.SECURITY_OVERRIDES = void 0;
|
|
37
|
+
exports.planSecurityOverrides = planSecurityOverrides;
|
|
38
|
+
exports.ensureSecurityOverrides = ensureSecurityOverrides;
|
|
39
|
+
exports.reportSecurityOverrides = reportSecurityOverrides;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const security_overrides_catalog_1 = require("./security-overrides-catalog");
|
|
43
|
+
/**
|
|
44
|
+
* Merge the security-override catalog into a consuming project's `package.json`.
|
|
45
|
+
*
|
|
46
|
+
* The catalog itself — which packages, which ranges, and why each one cannot be cleared any other
|
|
47
|
+
* way — lives in `security-overrides-catalog.ts`. That is the file to edit when an advisory moves;
|
|
48
|
+
* this one holds only the merge, the write and the reporting, which do not change when it does.
|
|
49
|
+
*/
|
|
50
|
+
var security_overrides_catalog_2 = require("./security-overrides-catalog");
|
|
51
|
+
Object.defineProperty(exports, "SECURITY_OVERRIDES", { enumerable: true, get: function () { return security_overrides_catalog_2.SECURITY_OVERRIDES; } });
|
|
52
|
+
/**
|
|
53
|
+
* Decide what a project's `overrides` block is missing. Pure — no I/O, so the tests and `--dry-run`
|
|
54
|
+
* can plan without touching anything.
|
|
55
|
+
*
|
|
56
|
+
* A pin the project already declares is NEVER rewritten, even when it differs from ours. Someone who
|
|
57
|
+
* typed a range into their own `package.json` had a reason (a private mirror, a pinned fork, a
|
|
58
|
+
* downgrade forced by another tool), and silently overwriting it would be the more surprising bug.
|
|
59
|
+
* It is reported instead, so a still-vulnerable pin is visible rather than swallowed.
|
|
60
|
+
*/
|
|
61
|
+
function planSecurityOverrides(pkgJson) {
|
|
62
|
+
const current = pkgJson.overrides && typeof pkgJson.overrides === 'object' ? pkgJson.overrides : {};
|
|
63
|
+
const add = [];
|
|
64
|
+
const existing = [];
|
|
65
|
+
for (const entry of security_overrides_catalog_1.SECURITY_OVERRIDES) {
|
|
66
|
+
const declared = current[entry.pkg];
|
|
67
|
+
if (typeof declared === 'string') {
|
|
68
|
+
if (declared !== entry.range)
|
|
69
|
+
existing.push({ pkg: entry.pkg, declared, wanted: entry.range });
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
// A nested override object ({ "uuid": { ".": "^11" } }) is a deliberate, more specific shape —
|
|
73
|
+
// treat it as the project's own decision and leave it alone.
|
|
74
|
+
if (declared !== undefined) {
|
|
75
|
+
existing.push({ pkg: entry.pkg, declared: JSON.stringify(declared), wanted: entry.range });
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
add.push(entry);
|
|
79
|
+
}
|
|
80
|
+
return { add, existing };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Write the missing overrides into a project's `package.json`.
|
|
84
|
+
*
|
|
85
|
+
* Best-effort by design, exactly like the rest of the project-file touching in `init` / `update`: an
|
|
86
|
+
* unreadable or malformed `package.json` means we skip silently rather than fail the command the
|
|
87
|
+
* user actually ran. The audit gate is not worth losing a scaffold over.
|
|
88
|
+
*
|
|
89
|
+
* Must run BEFORE the project's `npm install`, or the first resolution pass writes a lockfile that
|
|
90
|
+
* already pins the vulnerable versions.
|
|
91
|
+
*
|
|
92
|
+
* @param dryRun plan only — report what would change and write nothing
|
|
93
|
+
* @returns the plan that was applied, or null when there was no `package.json` to apply it to
|
|
94
|
+
*/
|
|
95
|
+
function ensureSecurityOverrides(packageJsonPath, dryRun = false) {
|
|
96
|
+
let pkgJson;
|
|
97
|
+
try {
|
|
98
|
+
pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const plan = planSecurityOverrides(pkgJson);
|
|
104
|
+
plan.foreignLockfile = detectForeignLockfile(path.dirname(packageJsonPath));
|
|
105
|
+
if (plan.add.length && !dryRun) {
|
|
106
|
+
const overrides = pkgJson.overrides && typeof pkgJson.overrides === 'object' ? pkgJson.overrides : {};
|
|
107
|
+
for (const entry of plan.add)
|
|
108
|
+
overrides[entry.pkg] = entry.range;
|
|
109
|
+
pkgJson.overrides = overrides;
|
|
110
|
+
try {
|
|
111
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(pkgJson, null, 2) + '\n', 'utf-8');
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Read-only checkout, root-owned file, read-only container mount. `sungen update` in
|
|
115
|
+
// particular has ALREADY reinstalled globally by the time it gets here, so throwing would
|
|
116
|
+
// abandon the AI-rules refresh and the family sync over a hardening step. Report and move on.
|
|
117
|
+
return { add: [], existing: plan.existing, foreignLockfile: plan.foreignLockfile, writeFailed: true };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return plan;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* npm is the only package manager that reads a top-level `overrides` block. Yarn wants
|
|
124
|
+
* `resolutions`, pnpm wants `pnpm.overrides` — so on those projects the block we write is inert and
|
|
125
|
+
* the install stays vulnerable. We do NOT guess at the equivalent field (getting a resolutions
|
|
126
|
+
* pattern subtly wrong is worse than not writing one), but silence would be the same class of bug
|
|
127
|
+
* as #764 itself: a fix that looks applied and is not. So: say so.
|
|
128
|
+
*/
|
|
129
|
+
function detectForeignLockfile(dir) {
|
|
130
|
+
if (fs.existsSync(path.join(dir, 'pnpm-lock.yaml')))
|
|
131
|
+
return 'pnpm';
|
|
132
|
+
if (fs.existsSync(path.join(dir, 'yarn.lock')))
|
|
133
|
+
return 'yarn';
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
/** Print what `ensureSecurityOverrides` did, in the voice the surrounding commands already use. */
|
|
137
|
+
function reportSecurityOverrides(plan, dryRun = false) {
|
|
138
|
+
if (!plan)
|
|
139
|
+
return;
|
|
140
|
+
if (plan.writeFailed) {
|
|
141
|
+
console.warn('⚠️ Could not write the security overrides into package.json (read-only file?). Nothing else\n' +
|
|
142
|
+
' failed. Add this block by hand to keep `npm audit` clean:\n' +
|
|
143
|
+
` "overrides": ${JSON.stringify(Object.fromEntries(security_overrides_catalog_1.SECURITY_OVERRIDES.map((o) => [o.pkg, o.range])), null, 2).replace(/\n/g, '\n ')}\n`);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (plan.add.length) {
|
|
147
|
+
const verb = dryRun ? '[dry-run] would add' : 'Added';
|
|
148
|
+
console.log(`🔒 ${verb} ${plan.add.length} security override(s) to package.json — npm honours these only here, not from sungen's own manifest:`);
|
|
149
|
+
for (const entry of plan.add)
|
|
150
|
+
console.log(` • ${entry.pkg}@${entry.range} — ${entry.why}`);
|
|
151
|
+
console.log('');
|
|
152
|
+
}
|
|
153
|
+
if (plan.existing.length) {
|
|
154
|
+
console.log('🔒 Left your own overrides alone (sungen never rewrites a pin you declared):');
|
|
155
|
+
for (const e of plan.existing)
|
|
156
|
+
console.log(` – ${e.pkg}: ${e.declared} (sungen would use ${e.wanted})`);
|
|
157
|
+
console.log(' If `npm audit` still flags one of these, raise it by hand.\n');
|
|
158
|
+
}
|
|
159
|
+
if (plan.foreignLockfile && (plan.add.length || plan.existing.length)) {
|
|
160
|
+
const field = plan.foreignLockfile === 'pnpm' ? '"pnpm": { "overrides": … }' : '"resolutions"';
|
|
161
|
+
console.warn(`⚠️ This project has a ${plan.foreignLockfile} lockfile. ${plan.foreignLockfile} ignores npm's "overrides" —\n` +
|
|
162
|
+
` mirror the block into ${field} as well, or the pins do nothing here.\n`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=security-overrides.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-overrides.js","sourceRoot":"","sources":["../../src/orchestrator/security-overrides.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,9 @@ You are a **test-design context explorer**. You run in an **isolated context** s
|
|
|
9
9
|
## Explore (do NOT ask the user to pick a source — read all that exist)
|
|
10
10
|
- `requirements/spec.md` — primary behavior source.
|
|
11
11
|
- `requirements/spec_figma.md` — Figma supplement (if present; do NOT call Figma MCP when this exists).
|
|
12
|
-
- `requirements/ui/*` images —
|
|
12
|
+
- `requirements/ui/*` images — read **every** image (group primary vs states/variants when there are many, but open them all).
|
|
13
|
+
- `requirements/ui/figma-meta.md` — Figma MCP capture: `## Components`, `## Text Content`.
|
|
14
|
+
- `requirements/ui-inventory.md` — an existing Design Inventory: keep its `UI-NNN` ids.
|
|
13
15
|
- Live page — only if a base URL is configured and reachable: `browser_navigate` + `browser_snapshot` for real element roles/names. Fall back gracefully if it requires login / fails.
|
|
14
16
|
|
|
15
17
|
## Cross-check
|
|
@@ -20,7 +22,13 @@ Flag any **conflicts** between sources (field names, labels, behavior, states th
|
|
|
20
22
|
SOURCES: spec=<yes/no, completeness high|med|low> | figma=<...> | ui=<n images> | live=<reached|offline>
|
|
21
23
|
PAGE TYPE: <e.g. ecommerce-list / form / auth / ...>
|
|
22
24
|
RECOMMENDED ROUTE: <spec-first | source-first | ...> — authoritative source: <which>
|
|
23
|
-
CONFLICTS: <list, or "none">
|
|
25
|
+
CONFLICTS: <list, or "none"> — each conflict on a design item also appears in UI INVENTORY with source `conflict`
|
|
26
|
+
UI INVENTORY: images read: <read>/<total> · figma-meta.md: <read|absent> · spec_figma.md: <read|absent>
|
|
27
|
+
| UI-001 | <item> | <component|column|button|field|state|annotation> | spec+design | <image> |
|
|
28
|
+
| UI-014 | <item> | column | design-only | <image> |
|
|
29
|
+
| UI-015 | <item> | column | conflict — <how spec and design disagree> | <image> |
|
|
30
|
+
→ one row per item the design shows (format and id rules: `sungen-tc-generation` § Design Inventory);
|
|
31
|
+
omit the block only when the unit has no design source
|
|
24
32
|
KEY FACTS (condensed):
|
|
25
33
|
- Sections: <list>
|
|
26
34
|
- Fields/validation: <key constraints + exact error messages>
|
|
@@ -29,4 +37,4 @@ KEY FACTS (condensed):
|
|
|
29
37
|
ASSUMPTIONS / MISSING INFO: <what's unknown — to be marked in output>
|
|
30
38
|
```
|
|
31
39
|
|
|
32
|
-
Keep it tight. Do not generate test cases — that is the orchestrator's job. Do not write files.
|
|
40
|
+
Keep it tight — except UI INVENTORY, which is listed in full: it is the checklist the orchestrator writes to `ui-inventory.md`. Do not generate test cases — that is the orchestrator's job. Do not write files.
|
|
@@ -10,6 +10,8 @@ You are an **independent Senior QA Reviewer**. You did **not** write these tests
|
|
|
10
10
|
- `qa/<screens|flows>/<name>/features/<name>.feature` — the scenarios under review.
|
|
11
11
|
- `qa/<screens|flows>/<name>/requirements/test-viewpoint.md` — the viewpoint overview (priority).
|
|
12
12
|
- `qa/<screens|flows>/<name>/requirements/spec.md` — source of truth for behavior.
|
|
13
|
+
- `qa/<screens|flows>/<name>/requirements/ui/*` images, `ui/figma-meta.md`, `spec_figma.md` — the design, when present. Open **every** image.
|
|
14
|
+
- `qa/<screens|flows>/<name>/requirements/ui-inventory.md` — the Design Inventory create-test wrote (`UI-NNN` rows).
|
|
13
15
|
- `.sungen/reports/<name>-audit.json` — the deterministic findings (don't repeat them; go deeper).
|
|
14
16
|
|
|
15
17
|
## What to judge (semantic — the gate misses these)
|
|
@@ -25,6 +27,7 @@ You are an **independent Senior QA Reviewer**. You did **not** write these tests
|
|
|
25
27
|
- **Flows self-clean.** A CRUD/auth chain deletes what it created (final `@api:delete_*`) or is `@cleanup`-tagged.
|
|
26
28
|
- **Idempotency uses the DB oracle.** A "no double-charge / exactly once" claim is proven by `@concurrent` + a `@query` count, not HTTP status alone (status can lie under a race).
|
|
27
29
|
- **Auth negatives** exist for protected mutations (401/403), not just the happy path.
|
|
30
|
+
7. **Design ↔ Feature** (only when the unit holds design sources). Read the design yourself — do not trust the inventory to be complete. Report: items the design shows that are **missing from `ui-inventory.md`**; inventory items **mislabelled** `spec+design` that `spec.md` never names (design-only) or names differently (conflict); and `design-only`/`conflict` items whose `@ui:` scenario does not actually prove them, or whose `# UI-DEFERRED:` reason does not hold. The audit only sees what the inventory lists — you are the check on the inventory itself.
|
|
28
31
|
|
|
29
32
|
## Output (do NOT edit any file)
|
|
30
33
|
Return a concise verdict:
|
|
@@ -38,6 +41,11 @@ ISSUES (most important first):
|
|
|
38
41
|
FIX: <the exact Gherkin step(s) to add/change>
|
|
39
42
|
2. ...
|
|
40
43
|
|
|
44
|
+
DESIGN DIFF (omit when the unit has no design source):
|
|
45
|
+
- not inventoried: <item> (<image>)
|
|
46
|
+
- mislabelled: UI-NNN <item> — is <design-only|conflict>, not spec+design
|
|
47
|
+
- unproven: UI-NNN <item> — <why the @ui scenario / deferral does not hold>
|
|
48
|
+
|
|
41
49
|
STRENGTHS: <1-2 lines, what is genuinely good>
|
|
42
50
|
```
|
|
43
51
|
|
|
@@ -224,7 +224,7 @@ If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the d
|
|
|
224
224
|
|
|
225
225
|
**Auto-detect visual source** — do NOT ask the user to pick a source. Instead, check what already exists and use it:
|
|
226
226
|
1. If `spec_figma.md` exists → read it as Figma supplement (PAT flow already completed during `add-screen`). Do NOT call any `mcp__figma__*` tool.
|
|
227
|
-
2. If `ui/` has images (`.png`, `.jpg`, etc.) → read them
|
|
227
|
+
2. If `ui/` has images (`.png`, `.jpg`, etc.) or `ui/figma-meta.md` → read **all** of them; they feed the Design Inventory (below), not just visual context.
|
|
228
228
|
{{#cap parallel-subagents}}
|
|
229
229
|
3. If neither exists → use `AskUserQuestion` to ask: *"No visual source found. Pick one:"* — then invoke the **`sungen-capture`** skill with the matching **mode** (read only that mode's file):
|
|
230
230
|
- **Figma PAT** — ask for URL, run `sungen add --screen <screen> --figma '<url>'` via Bash, then `sungen-capture` **mode figma-pat**
|
|
@@ -242,7 +242,7 @@ If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the d
|
|
|
242
242
|
|
|
243
243
|
(When `spec_figma.md` exists, that is also `sungen-capture` **mode figma-pat**; when `ui/` images exist, that is **mode local**.)
|
|
244
244
|
|
|
245
|
-
**Cross-check**:
|
|
245
|
+
**Cross-check + Design Inventory**: when the unit holds any design source (`ui/` images, `ui/figma-meta.md`, `spec_figma.md`), follow `sungen-tc-generation` § **Design Inventory** (reading order, one `UI-NNN` row per item, `spec+design` / `design-only` / `conflict`) and **write `requirements/ui-inventory.md`** before generating — from the discovery report's UI INVENTORY block when a sub-agent read the sources. Every `design-only` / `conflict` item must then be covered (`@ui:UI-NNN`) or deferred with a reason (`# UI-DEFERRED: UI-NNN — <reason>`) in the `.feature`; `sungen audit` reports `UI-ITEM-UNCOVERED` otherwise. Show the user the conflicts and design-only items — they are decisions, not details.
|
|
246
246
|
|
|
247
247
|
Summarize what you found in requirements and present to the user.
|
|
248
248
|
|
|
@@ -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/*]"
|
|
@@ -85,6 +85,13 @@ Stop here for mobile — do not continue to the web path.
|
|
|
85
85
|
> QA finding → report it, let it FAIL** (it may be a real bug). The live page is NOT the oracle;
|
|
86
86
|
> never hand-edit the generated `.spec.ts` either. See `sungen-error-mapping` § "HARD RULE".
|
|
87
87
|
> (A `password > 8` test that fails on 6 chars is a bug to report, not a `>= 6` edit.)
|
|
88
|
+
>
|
|
89
|
+
> **Blocked by missing seed data / capability** (the run cannot create the state the scenario
|
|
90
|
+
> needs)? Keep every Given/When/Then; add only a tag — `@requires:<cap>` when a driver exists,
|
|
91
|
+
> else `@manual:M1` with a `# MANUAL (<date>, run-test): <reason>` comment inside the scenario —
|
|
92
|
+
> and list each downgrade in the run summary for QA. Never replace the assertion with a presence
|
|
93
|
+
> placeholder and park the oracle in a comment (`SG-W008`). See `sungen-error-mapping` § "Fails
|
|
94
|
+
> because the environment lacks the DATA or CAPABILITY".
|
|
88
95
|
|
|
89
96
|
## Parameters
|
|
90
97
|
|
|
@@ -95,7 +102,9 @@ Parse from `$ARGUMENTS`:
|
|
|
95
102
|
the result over the previous run's file instead of replacing it. Passing it also **skips the scope gate**:
|
|
96
103
|
the flag IS the answer, so asking again would be noise. Without the flag the gate asks — but only when the
|
|
97
104
|
selection is narrower than the whole unit (see the table). Either way a subset run must follow the merge
|
|
98
|
-
|
|
105
|
+
flow below — web writes the subset to a temp report, mobile backs the fixed-name file up BEFORE the run.
|
|
106
|
+
- **`--ids <ID,…>`** — run exactly these test-case IDs (`VP-UI-001,VP-UI-002`) and merge the result
|
|
107
|
+
over the previous run's file — see the `--ids` section below. Skips the scope gate, like `--change-only`.
|
|
99
108
|
- **`--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
109
|
|
|
101
110
|
If `--env` is passed but no value follows, ask the user which locale to use.
|
|
@@ -172,6 +181,7 @@ Read `summary.selected`, `summary.total`, `all`, and `reasons`, then follow this
|
|
|
172
181
|
| Situation | What to do |
|
|
173
182
|
|---|---|
|
|
174
183
|
| `--change-only` was passed | **Do NOT ask.** Run the changed set, print the list + reasons for the record, follow the merge flow below. |
|
|
184
|
+
| `--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
185
|
| `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
186
|
| `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
187
|
| `0 < selected < total` | **ASK** — this is the only case with two honest answers. |
|
|
@@ -187,6 +197,10 @@ recorded` and runs everything again — the narrowing never starts. Record it af
|
|
|
187
197
|
results you accept (a full run, or a subset once merged), and NOT after a run you are about to
|
|
188
198
|
redo: leaving the baseline where it is keeps the same scenarios selected on the next attempt.
|
|
189
199
|
|
|
200
|
+
**Never record after an `--ids` run.** The user's IDs need not cover what an edit changed;
|
|
201
|
+
recording would mark every changed scenario as re-run, and the next `--change-only` would skip the
|
|
202
|
+
ones this run never touched.
|
|
203
|
+
|
|
190
204
|
When you ask, first PRINT the selection so the choice is informed — one line per scenario with its
|
|
191
205
|
reason, exactly as `sungen changed` renders it — then `AskUserQuestion` with two options:
|
|
192
206
|
|
|
@@ -257,7 +271,7 @@ question already.
|
|
|
257
271
|
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
272
|
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
273
|
8. **Phase 4 — Regression**: One final full run. Report results. No more fix loops.
|
|
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.
|
|
274
|
+
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
275
|
{{#cap parallel-subagents}}
|
|
262
276
|
9. **Integrity check & trace (always run after the final run).**
|
|
263
277
|
- `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 +339,7 @@ sungen results merge --screen <name> specs/generated/<name>/subset-tmp.json
|
|
|
325
339
|
rm specs/generated/<name>/subset-tmp.json
|
|
326
340
|
```
|
|
327
341
|
|
|
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`
|
|
342
|
+
`--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
343
|
|
|
330
344
|
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
345
|
|
|
@@ -360,29 +374,33 @@ If you want to filter scenarios, use `-g "<pattern>"` instead of a reporter over
|
|
|
360
374
|
|
|
361
375
|
## `--change-only` — re-run just what an edit obliges, without losing the rest
|
|
362
376
|
|
|
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:
|
|
377
|
+
A per-target result file holds the whole unit, so a subset run must never replace it: re-running 3
|
|
378
|
+
cases of a 100-case screen used to throw away the 97 that still passed. The subset is MERGED in
|
|
379
|
+
instead — on web via a temp report, on mobile via a backup taken BEFORE the run (the WDIO reporter
|
|
380
|
+
always writes the fixed-name file, so by the time the run finishes the old one is gone):
|
|
369
381
|
|
|
370
382
|
```bash
|
|
371
383
|
# 1. what does the edit oblige? (empty output = nothing to run, do NOT fall through to a full run)
|
|
372
384
|
npx sungen changed --screen <name> # human-readable, with the reason per scenario
|
|
373
385
|
GREP=$(npx sungen changed --screen <name> --grep)
|
|
374
386
|
|
|
387
|
+
# MOBILE — the WDIO reporter always writes the canonical per-OS file, so back it up first:
|
|
375
388
|
# 2. keep the previous results BEFORE the runner overwrites them
|
|
376
389
|
cp specs/generated/<name>/<name>-test-result.<os>.json /tmp/<name>.prev.json
|
|
377
|
-
|
|
378
390
|
# 3. run only the selected scenarios
|
|
379
391
|
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
392
|
# 4. merge the subset back over the kept results (same title → new wins, others kept)
|
|
383
393
|
npx sungen results merge /tmp/<name>.prev.json specs/generated/<name>/<name>-test-result.<os>.json \
|
|
384
394
|
-o specs/generated/<name>/<name>-test-result.<os>.json
|
|
385
395
|
|
|
396
|
+
# WEB — Playwright writes its report to PLAYWRIGHT_JSON_OUTPUT_NAME (else test-results/results.json),
|
|
397
|
+
# never to the per-target file by itself: write the subset to a temp report and merge THAT in (#837).
|
|
398
|
+
# With --env <x>: prefix BOTH commands with SUNGEN_ENV=<x>; the config then writes subset-tmp.<x>.json.
|
|
399
|
+
PLAYWRIGHT_JSON_OUTPUT_NAME=specs/generated/<name>/subset-tmp.json \
|
|
400
|
+
npx playwright test specs/generated/<name>/<name>.spec.ts -g "$GREP"
|
|
401
|
+
npx sungen results merge --screen <name> specs/generated/<name>/subset-tmp.json # --env x → subset-tmp.x.json
|
|
402
|
+
rm specs/generated/<name>/subset-tmp*.json
|
|
403
|
+
|
|
386
404
|
# 5. record the new baseline — ONLY after a run you accept
|
|
387
405
|
npx sungen changed --screen <name> --record
|
|
388
406
|
```
|
|
@@ -398,6 +416,45 @@ change that broke it.
|
|
|
398
416
|
**Without `--change-only`** the full run still writes the file wholesale, which is correct — a full
|
|
399
417
|
run IS the complete picture. Merging only matters for subsets.
|
|
400
418
|
|
|
419
|
+
## `--ids` — run a chosen list of test-case IDs
|
|
420
|
+
|
|
421
|
+
The user names the cases (`--ids VP-UI-001,VP-UI-002`). `sungen select` resolves them —
|
|
422
|
+
deterministic, exact ID match, grouped per feature — and refuses anything it cannot run:
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
npx sungen select --screen <name> --ids <ID,…> # human-readable
|
|
426
|
+
npx sungen select --screen <name> --ids <ID,…> --json # what you act on
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Exit 1 = do not run.** Report every entry of `unknown` (with its `didYouMean`), `notRunnable`
|
|
430
|
+
(manual / owned by a flow — with the reason) and `notCompiled` (→ `sungen generate` first), then
|
|
431
|
+
use `AskUserQuestion` to offer: run the valid IDs only / correct the list. Never fall back to a
|
|
432
|
+
full run, and never run with an empty grep.
|
|
433
|
+
|
|
434
|
+
Then, **for each entry of `features`** (a multi-feature screen has one spec and one result file per
|
|
435
|
+
feature), with `<spec>` = its `spec`, `<f>` = its `feature`, `<dir>` = the spec's directory and
|
|
436
|
+
`GREP` = its `grep`:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
# WEB — write the subset to a temp report, then merge it into <f>'s per-target file.
|
|
440
|
+
# With --env <x>: prefix BOTH commands with SUNGEN_ENV=<x>; the config then writes subset-tmp.<x>.json.
|
|
441
|
+
PLAYWRIGHT_JSON_OUTPUT_NAME=<dir>/subset-tmp.json npx playwright test <spec> -g "$GREP"
|
|
442
|
+
npx sungen results merge --screen <f> <dir>/subset-tmp.json # --env x → <dir>/subset-tmp.x.json
|
|
443
|
+
rm <dir>/subset-tmp*.json
|
|
444
|
+
|
|
445
|
+
# MOBILE — the reporter always writes <dir>/<f>-test-result.<android|ios>[.<env>].json: back it up first
|
|
446
|
+
# (with --env <x> every <f>-test-result.<os>.json below is <f>-test-result.<os>.<x>.json)
|
|
447
|
+
cp <dir>/<f>-test-result.<os>.json /tmp/<f>.prev.json
|
|
448
|
+
SUNGEN_SPECS='./<spec>' npm run test:mobile -- --mochaOpts.grep "$GREP"
|
|
449
|
+
npx sungen results merge /tmp/<f>.prev.json <dir>/<f>-test-result.<os>.json -o <dir>/<f>-test-result.<os>.json
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
With no previous result file (first run of the unit, or of this `--env`) there is nothing to merge
|
|
453
|
+
into — `results merge --screen` says so and exits 1: on web run with
|
|
454
|
+
`PLAYWRIGHT_JSON_OUTPUT_NAME=<dir>/<f>-test-result.json`, on mobile skip the backup and the merge.
|
|
455
|
+
With `--both`, back up and merge each OS's file. **Do NOT run `sungen changed --record`** (see the
|
|
456
|
+
scope gate). Report the per-ID outcome, plus the IDs that were refused.
|
|
457
|
+
|
|
401
458
|
## Next steps
|
|
402
459
|
|
|
403
460
|
After showing results, use `AskUserQuestion` to offer next steps:
|
|
@@ -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.
|