@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
|
@@ -4,14 +4,26 @@ import * as fs from 'fs';
|
|
|
4
4
|
import { runAudit, AuditReport, catalogIdFromScreenDir } from '../../harness/audit';
|
|
5
5
|
import { reportSlug } from '../../harness/unit-paths';
|
|
6
6
|
import { acceptViewpointBaseline } from '../../harness/viewpoint-baseline';
|
|
7
|
+
import { removeDraftLineFromFile, viewpointFileIsAiDraft } from '../../harness/viewpoint-draft-header';
|
|
7
8
|
import { findUnitDir } from '../resolve-unit';
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
function bar(ratio: number, width = 20): string {
|
|
11
|
-
|
|
11
|
+
export function bar(ratio: number, width = 20): string {
|
|
12
|
+
// A display helper must not be able to take the CLI down whatever the model hands it: an
|
|
13
|
+
// out-of-range ratio made `String.repeat` throw `Invalid count value: -5`, which killed the
|
|
14
|
+
// run mid-scorecard so the gate, the findings and the next-step hint never printed (#762).
|
|
15
|
+
const n = Math.max(0, Math.min(width, Math.round((Number.isFinite(ratio) ? ratio : 0) * width)));
|
|
12
16
|
return '█'.repeat(n) + '░'.repeat(width - n);
|
|
13
17
|
}
|
|
14
18
|
|
|
19
|
+
/** The ⑥ headline. No viewpoint ID read → nothing was matched, so `0%` would read as a measured
|
|
20
|
+
* failure; say `n/a` and why instead (#832). Same with no scenario yet (#852). */
|
|
21
|
+
export function traceabilityHeadline(trace: AuditReport['trace']): string {
|
|
22
|
+
if (trace.overviewIds === 0) return ' ⑥ Traceability — n/a (no viewpoint ID found in test-viewpoint.md)';
|
|
23
|
+
if (trace.total === 0) return ' ⑥ Traceability — n/a (no scenarios yet)';
|
|
24
|
+
return ` ⑥ Traceability — ${(trace.mappedRatio * 100).toFixed(0)}% scenarios linked to viewpoint-overview`;
|
|
25
|
+
}
|
|
26
|
+
|
|
15
27
|
function render(r: AuditReport): void {
|
|
16
28
|
const L = console.log;
|
|
17
29
|
L('');
|
|
@@ -47,6 +59,11 @@ function render(r: AuditReport): void {
|
|
|
47
59
|
L(` ① Viewpoint Gate — page-type: ${r.gate.pageType ?? 'unknown'} — themes ${r.gate.themesCovered}/${r.gate.themesTotal} covered`);
|
|
48
60
|
if (r.gate.gaps.length) for (const g of r.gate.gaps) L(` ✗ ${g.status === 'shallow' ? 'SHALLOW' : 'MISSING'}: ${g.theme}`);
|
|
49
61
|
else L(' ✓ all critical themes covered (with data assertions)');
|
|
62
|
+
// Name the scenario behind each covered theme (#776). A bare count gives a reviewer nothing to
|
|
63
|
+
// check, so a keyword matching something absurd stays invisible; the evidence line makes it
|
|
64
|
+
// obvious. Second line of defence — it holds even if the matcher is wrong again.
|
|
65
|
+
for (const c of r.gate.coveredBy ?? [])
|
|
66
|
+
L(` ✓ ${c.theme} ← [${c.keyword}] ${c.by.length > 88 ? `${c.by.slice(0, 88)}…` : c.by}`);
|
|
50
67
|
L('');
|
|
51
68
|
if (r.flowQuality?.hasContract) {
|
|
52
69
|
const fq = r.flowQuality;
|
|
@@ -74,7 +91,7 @@ function render(r: AuditReport): void {
|
|
|
74
91
|
if (r.depth.shallowBusinessCritical.length > 8) L(` … +${r.depth.shallowBusinessCritical.length - 8} more`);
|
|
75
92
|
L('');
|
|
76
93
|
L(` ③ Claim-Proof — ${r.claim.proven}/${r.claim.withClaims} titled claims proven by steps [${r.claim.verdict.toUpperCase()}]`);
|
|
77
|
-
if (r.claim.unproven.length === 0) L(' ✓ every claim (all/only/single/correct/changes/hidden) is backed by an assertion');
|
|
94
|
+
if (r.claim.unproven.length === 0) L(' ✓ every claim (all/only/single/correct/changes/hidden/order/limit) is backed by an assertion');
|
|
78
95
|
for (const u of r.claim.unproven.slice(0, 8)) L(` ${u.severity === 'fail' ? '✗' : '⚠'} [${u.claim}] ${u.name} → needs ${u.need}`);
|
|
79
96
|
if (r.claim.unproven.length > 8) L(` … +${r.claim.unproven.length - 8} more`);
|
|
80
97
|
L('');
|
|
@@ -102,7 +119,7 @@ function render(r: AuditReport): void {
|
|
|
102
119
|
}
|
|
103
120
|
}
|
|
104
121
|
L('');
|
|
105
|
-
L(
|
|
122
|
+
L(traceabilityHeadline(r.trace));
|
|
106
123
|
L(` ${r.trace.note}`);
|
|
107
124
|
L('');
|
|
108
125
|
if (r.spec.hasSpec && (r.spec.frTotal > 0 || r.spec.triggerGaps.length > 0 || r.spec.verdict !== 'pass')) {
|
|
@@ -127,7 +144,7 @@ function render(r: AuditReport): void {
|
|
|
127
144
|
const held = new Set(r.score.axes.filter((x) => x.withheld).map((x) => x.key));
|
|
128
145
|
const absent = na.filter((k) => !held.has(k));
|
|
129
146
|
if (absent.length) L(` not scored (no evidence in this unit): ${absent.join(', ')}`);
|
|
130
|
-
if (held.size) L(` measured but held (viewpoint
|
|
147
|
+
if (held.size) L(` measured but held (viewpoint not accepted yet — changed, adopted after the suite, or an AI draft; review, then --accept-viewpoint): ${[...held].join(', ')}`);
|
|
131
148
|
}
|
|
132
149
|
L(` weakest: ${r.calibration.weakest.axis} ${(r.calibration.weakest.value * 100).toFixed(0)}%${r.calibration.inflated ? ' ⚠ SCORE-INFLATED-BY-BREADTH' : ''}`);
|
|
133
150
|
if (r.calibration.cappedAt !== undefined) {
|
|
@@ -157,14 +174,18 @@ export function registerAuditCommand(program: Command): void {
|
|
|
157
174
|
.option('--area <name>', 'Alias of --api — an API-first area (qa/api/<name>)')
|
|
158
175
|
.option('--json', 'Output the raw JSON report')
|
|
159
176
|
.option('--accept-viewpoint', 'Accept the current test-viewpoint.md as the baseline the suite is measured against')
|
|
177
|
+
.option('--no-baseline', 'Measure without writing .sungen/viewpoint-baseline.json (audit a drafted viewpoint before generating)')
|
|
160
178
|
.action((options) => {
|
|
161
179
|
try {
|
|
162
180
|
const name = options.screen || options.api || options.area;
|
|
163
181
|
if (!name) throw new Error('Provide --screen <name> (or --api <area>)');
|
|
182
|
+
// Commander's `--no-*`: `baseline` is true unless the flag is passed.
|
|
183
|
+
const recordBaseline = options.baseline !== false;
|
|
184
|
+
if (!recordBaseline && options.acceptViewpoint) throw new Error('--no-baseline and --accept-viewpoint cannot be combined');
|
|
164
185
|
const dir = findUnitDir(name);
|
|
165
186
|
if (!dir) throw new Error(`Not found: qa/screens/${name}, qa/flows/${name}, or qa/api/${name}`);
|
|
166
187
|
|
|
167
|
-
|
|
188
|
+
let report = runAudit(dir, name);
|
|
168
189
|
|
|
169
190
|
// The baseline is only ever written HERE, never by the measurement itself:
|
|
170
191
|
// a first sighting has nothing to compare against, and any later change is
|
|
@@ -179,18 +200,43 @@ export function registerAuditCommand(program: Command): void {
|
|
|
179
200
|
const unitId = catalogIdFromScreenDir(dir);
|
|
180
201
|
const vb = report.viewpointBaseline;
|
|
181
202
|
const postHoc = vb.status === 'new' && report.scenarioCount > 0;
|
|
203
|
+
// `drafted-by: ai` — a viewpoint the AI wrote is never accepted by the audit that measures it,
|
|
204
|
+
// with scenarios or without: only `--accept-viewpoint` does, and that removes the line.
|
|
205
|
+
const vpPath = path.join(dir, 'requirements', 'test-viewpoint.md');
|
|
206
|
+
const hasDraftMarker = viewpointFileIsAiDraft(vpPath);
|
|
207
|
+
// A draft with no VP id has nothing to accept — only VIEWPOINT-MISSING speaks for it. Fail
|
|
208
|
+
// here, before any write, so the file stays as it is and the QA is told why.
|
|
209
|
+
if (options.acceptViewpoint && vb.status === 'absent' && hasDraftMarker) {
|
|
210
|
+
throw new Error('the draft declares no VP ids — nothing to accept. Add the viewpoint ids (VP-… in the Priority Viewpoints table or checks), then run --accept-viewpoint again.');
|
|
211
|
+
}
|
|
212
|
+
const aiDraft = vb.status !== 'absent' && hasDraftMarker;
|
|
182
213
|
// A re-parsed baseline is a CACHE migration, not an acceptance: the comparison already
|
|
183
214
|
// resolved to `unchanged`, and rewriting the record only lets the NEXT real edit be
|
|
184
215
|
// detected. Left unwritten it would re-migrate — and re-announce — on every run.
|
|
185
|
-
|
|
186
|
-
|
|
216
|
+
//
|
|
217
|
+
// `--no-baseline` skips every write here, the migration included: a draft audited before its
|
|
218
|
+
// scenarios exist is `new` and not post-hoc, and a plain audit would record it as the yardstick.
|
|
219
|
+
if (recordBaseline && !aiDraft && vb.reparsed) acceptViewpointBaseline(process.cwd(), unitId, { hash: vb.hash, ids: vb.ids, fileHash: vb.fileHash });
|
|
220
|
+
if (recordBaseline && ((vb.status === 'new' && !postHoc && !aiDraft) || (options.acceptViewpoint && (vb.status === 'changed' || postHoc || aiDraft)))) {
|
|
187
221
|
acceptViewpointBaseline(process.cwd(), unitId, { hash: vb.hash, ids: vb.ids, fileHash: vb.fileHash });
|
|
188
|
-
if (options.acceptViewpoint
|
|
189
|
-
|
|
190
|
-
|
|
222
|
+
if (options.acceptViewpoint) {
|
|
223
|
+
// The baseline is recorded first: if the line cannot be removed the draft stays flagged
|
|
224
|
+
// (held, finding, decide step) and the accept can simply be run again.
|
|
225
|
+
const lineRemoved = aiDraft && removeDraftLineFromFile(vpPath);
|
|
226
|
+
// Measure again against what was just accepted: the report printed and saved below (the
|
|
227
|
+
// one `sungen next` reads) must not be the pre-accept one, still holding the axes (#867).
|
|
228
|
+
report = runAudit(dir, name);
|
|
229
|
+
if (!options.json) {
|
|
230
|
+
console.log(`\n ✓ test-viewpoint.md accepted as the baseline for ${name} (${vb.ids.length} viewpoint id(s)).`);
|
|
231
|
+
if (lineRemoved) console.log(' Removed the `drafted-by: ai` line from test-viewpoint.md — it is QA-reviewed from here on.');
|
|
232
|
+
console.log(' The report below is measured against it.\n');
|
|
233
|
+
}
|
|
191
234
|
}
|
|
192
235
|
} else if (options.acceptViewpoint && !options.json) {
|
|
193
|
-
|
|
236
|
+
// `absent` covers a file with no readable viewpoint id too — say which (#832).
|
|
237
|
+
console.log(vb.status === 'absent'
|
|
238
|
+
? `\n ○ nothing to accept for ${name} — no viewpoint ID found in requirements/test-viewpoint.md (missing file, or no section declares one).\n`
|
|
239
|
+
: `\n ○ nothing to accept for ${name} — the viewpoint baseline is ${vb.status}.\n`);
|
|
194
240
|
}
|
|
195
241
|
|
|
196
242
|
// Persist report under .sungen/reports/ (flat slug: api flow `flows/x` → `flows-x-audit.json`).
|
|
@@ -204,6 +250,7 @@ export function registerAuditCommand(program: Command): void {
|
|
|
204
250
|
} else {
|
|
205
251
|
render(report);
|
|
206
252
|
console.log(` Report: ${path.relative(process.cwd(), outPath)}`);
|
|
253
|
+
if (!recordBaseline) console.log(' ○ baseline not recorded (--no-baseline)');
|
|
207
254
|
console.log('');
|
|
208
255
|
}
|
|
209
256
|
// Non-zero exit when the gate fails — usable in CI / repair loop. Set exitCode (not
|
|
@@ -4,7 +4,8 @@ import { createRequire } from 'module';
|
|
|
4
4
|
import * as fs from 'fs';
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import {
|
|
7
|
-
readCapabilities, writeCapabilities, loadDriverCatalog, driverMeta,
|
|
7
|
+
readCapabilities, writeCapabilities, loadDriverCatalog, driverMeta, capabilitiesPath,
|
|
8
|
+
type CapabilityProfile,
|
|
8
9
|
} from '../../harness/capability';
|
|
9
10
|
import { buildPlan, MANUAL_REASONS } from '../../harness/capability-plan';
|
|
10
11
|
import { adapterRegistry } from '../../generators/test-generator/adapters';
|
|
@@ -12,26 +13,37 @@ import { emitMobileRuntime, installMobileDriver } from '../../orchestrator/mobil
|
|
|
12
13
|
import { emitAppiumEnvironment, runAppiumEnvironmentSetup } from '../../orchestrator/appium-environment-setup';
|
|
13
14
|
import { coreVersion, resolveDriverVersion } from '../../orchestrator/lockstep-version';
|
|
14
15
|
import { findUnitDir, resolveUnit } from '../resolve-unit';
|
|
16
|
+
import { readTextFile } from '../../harness/read-text';
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
|
-
* Add `test:mobile` to the project's package.json scripts (if absent).
|
|
18
|
-
*
|
|
19
|
-
*
|
|
19
|
+
* Add `test:mobile` to the project's package.json scripts (if absent). Idempotent.
|
|
20
|
+
*
|
|
21
|
+
* Four outcomes, not two. The old boolean collapsed "already present", "no package.json" and
|
|
22
|
+
* "could not parse it" into a single `false`, and the caller rendered that as
|
|
23
|
+
* `– skipped package.json scripts[test:mobile] (already exists)` — which, on a malformed
|
|
24
|
+
* package.json, states the exact opposite of the truth: the script is absent, the command promised
|
|
25
|
+
* it, and the next thing the user sees is `npm error Missing script: "test:mobile"`.
|
|
20
26
|
*/
|
|
21
|
-
|
|
27
|
+
type MobileScriptOutcome =
|
|
28
|
+
| { state: 'added' }
|
|
29
|
+
| { state: 'already-present' }
|
|
30
|
+
| { state: 'no-package-json' }
|
|
31
|
+
| { state: 'unreadable'; error: string };
|
|
32
|
+
|
|
33
|
+
function addMobileScript(cwd: string): MobileScriptOutcome {
|
|
22
34
|
const pkgPath = path.join(cwd, 'package.json');
|
|
23
|
-
if (!fs.existsSync(pkgPath)) return
|
|
35
|
+
if (!fs.existsSync(pkgPath)) return { state: 'no-package-json' };
|
|
24
36
|
let pkg: Record<string, any>;
|
|
25
37
|
try {
|
|
26
|
-
pkg = JSON.parse(
|
|
27
|
-
} catch {
|
|
28
|
-
return
|
|
38
|
+
pkg = JSON.parse(readTextFile(pkgPath)); // BOM-tolerant: npm reads such a file fine, so must we
|
|
39
|
+
} catch (e) {
|
|
40
|
+
return { state: 'unreadable', error: (e as Error).message.split('\n')[0] };
|
|
29
41
|
}
|
|
30
42
|
if (!pkg.scripts || typeof pkg.scripts !== 'object') pkg.scripts = {};
|
|
31
|
-
if (pkg.scripts['test:mobile']) return
|
|
43
|
+
if (pkg.scripts['test:mobile']) return { state: 'already-present' };
|
|
32
44
|
pkg.scripts['test:mobile'] = 'wdio run wdio.conf.ts';
|
|
33
45
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
|
|
34
|
-
return
|
|
46
|
+
return { state: 'added' };
|
|
35
47
|
}
|
|
36
48
|
|
|
37
49
|
/**
|
|
@@ -221,9 +233,13 @@ export function registerCapabilityCommand(program: Command): void {
|
|
|
221
233
|
}
|
|
222
234
|
|
|
223
235
|
const profile = readCapabilities(cwd);
|
|
236
|
+
assertProfileWritable(profile, cwd);
|
|
224
237
|
const enabled = Array.from(new Set([...profile.enabled, driver]));
|
|
225
238
|
const platform = meta.kind === 'platform' ? driver : profile.platform;
|
|
226
|
-
|
|
239
|
+
// Carry `verification` through. It is the recorded TEST TYPE, not a derived value: dropping
|
|
240
|
+
// it here silently re-derives the scope from `enabled`, handing an E2E-only project the
|
|
241
|
+
// @api/@query verification it had explicitly narrowed away.
|
|
242
|
+
writeCapabilities(cwd, { platform, enabled, verification: profile.verification });
|
|
227
243
|
console.log(`✓ capability "${driver}" enabled${meta.kind === 'platform' ? ` (platform=${driver})` : ''}.`);
|
|
228
244
|
|
|
229
245
|
// Emit the mobile runtime harness when the mobile platform driver is added.
|
|
@@ -236,11 +252,11 @@ export function registerCapabilityCommand(program: Command): void {
|
|
|
236
252
|
for (const f of result.skipped) console.log(` – skipped ${f} (already exists)`);
|
|
237
253
|
|
|
238
254
|
// Add test:mobile script to package.json (idempotent)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
255
|
+
const script = addMobileScript(cwd);
|
|
256
|
+
if (script.state === 'added') console.log(' ✓ created package.json scripts[test:mobile]');
|
|
257
|
+
else if (script.state === 'already-present') console.log(' – skipped package.json scripts[test:mobile] (already exists)');
|
|
258
|
+
else if (script.state === 'no-package-json') console.log(' ✗ NOT added package.json scripts[test:mobile] — no package.json here; run `npm init -y` first, then add: "test:mobile": "wdio run wdio.conf.ts"');
|
|
259
|
+
else console.log(` ✗ NOT added package.json scripts[test:mobile] — package.json is not valid JSON (${script.error}); fix it, then add: "test:mobile": "wdio run wdio.conf.ts"`);
|
|
244
260
|
|
|
245
261
|
// appium-environment/ provisioning bundle (idempotent per file) — emitted before the driver
|
|
246
262
|
// install, run after it so its Appium step finds the project-local CLI.
|
|
@@ -249,7 +265,9 @@ export function registerCapabilityCommand(program: Command): void {
|
|
|
249
265
|
else console.log(' – skipped appium-environment/ (already exists)');
|
|
250
266
|
|
|
251
267
|
// Best-effort driver install — non-fatal so capability add still succeeds offline.
|
|
252
|
-
|
|
268
|
+
// --skip-install promises no npm install; the driver + wdio/appium runtime is ~290 MB.
|
|
269
|
+
if (o.skipInstall) console.log(' – skipped mobile driver install (--skip-install) — later: sungen capability add mobile');
|
|
270
|
+
else installMobileDriver(cwd);
|
|
253
271
|
|
|
254
272
|
// --skip-install means "record only" — then provisioning the machine is not wanted either.
|
|
255
273
|
runAppiumEnvironmentSetup(cwd, { skip: !!(o.skipEnvSetup || o.skipInstall) });
|
|
@@ -262,6 +280,22 @@ export function registerCapabilityCommand(program: Command): void {
|
|
|
262
280
|
}
|
|
263
281
|
});
|
|
264
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Every path that WRITES qa/capabilities.yaml first reads it, edits one field, and writes the whole
|
|
285
|
+
* file back. That round-trip is only safe when the read succeeded: an unreadable profile reads as
|
|
286
|
+
* "no platform, no drivers", so the write-back would replace the user's declaration with just the
|
|
287
|
+
* one driver being added — and `remove` would replace it with nothing at all. Refuse instead.
|
|
288
|
+
*/
|
|
289
|
+
function assertProfileWritable(profile: CapabilityProfile, cwd: string): void {
|
|
290
|
+
if (profile.source !== 'unreadable') return;
|
|
291
|
+
console.error(
|
|
292
|
+
`✗ ${path.relative(cwd, capabilitiesPath(cwd))} exists but could not be parsed.\n` +
|
|
293
|
+
` Refusing to rewrite it: this command replaces the whole file, so it would discard the\n` +
|
|
294
|
+
` platform, drivers and verification scope you declared. Fix the YAML and re-run.`,
|
|
295
|
+
);
|
|
296
|
+
process.exit(1);
|
|
297
|
+
}
|
|
298
|
+
|
|
265
299
|
// ── remove ─────────────────────────────────────────────────────────────
|
|
266
300
|
cap
|
|
267
301
|
.command('remove <driver>')
|
|
@@ -271,9 +305,10 @@ export function registerCapabilityCommand(program: Command): void {
|
|
|
271
305
|
try {
|
|
272
306
|
const cwd = process.cwd();
|
|
273
307
|
const profile = readCapabilities(cwd);
|
|
308
|
+
assertProfileWritable(profile, cwd);
|
|
274
309
|
const enabled = profile.enabled.filter((d) => d !== driver);
|
|
275
310
|
const platform = profile.platform === driver ? undefined : profile.platform;
|
|
276
|
-
writeCapabilities(cwd, { platform, enabled });
|
|
311
|
+
writeCapabilities(cwd, { platform, enabled, verification: profile.verification });
|
|
277
312
|
const meta = driverMeta(driver);
|
|
278
313
|
if (o.uninstall && meta && !adapterRegistry.hasAdapter(meta.adapter || meta.id)) {
|
|
279
314
|
spawnSync('npm', ['uninstall', meta.package], { stdio: 'inherit', shell: true });
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { Command } from 'commander';
|
|
13
13
|
import { buildRunManifest, readRunManifest, writeRunManifest, selectChanged } from '../../harness/run-manifest';
|
|
14
14
|
import { findUnitDir } from '../resolve-unit';
|
|
15
|
+
import { titlesToGrep } from '../../harness/select-by-ids';
|
|
15
16
|
import { execFileSync } from 'child_process';
|
|
16
17
|
import * as path from 'path';
|
|
17
18
|
|
|
@@ -40,9 +41,6 @@ function gitChangedFiles(unitDir: string): string[] {
|
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
/** Escape a scenario title for a `-g` / `--mochaOpts.grep` regex. */
|
|
44
|
-
const toGrep = (titles: string[]): string =>
|
|
45
|
-
titles.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
|
|
46
44
|
|
|
47
45
|
export function registerChangedCommand(program: Command): void {
|
|
48
46
|
program
|
|
@@ -75,7 +73,7 @@ export function registerChangedCommand(program: Command): void {
|
|
|
75
73
|
if (options.grep) {
|
|
76
74
|
// Empty output is meaningful: nothing to run. A caller must treat "" as "skip the run",
|
|
77
75
|
// never as "match everything" — an empty grep would run the whole suite.
|
|
78
|
-
console.log(
|
|
76
|
+
console.log(titlesToGrep(selection.scenarios));
|
|
79
77
|
return;
|
|
80
78
|
}
|
|
81
79
|
if (options.json) { console.log(JSON.stringify(selection, null, 2)); return; }
|
|
@@ -11,8 +11,7 @@ import { Command } from 'commander';
|
|
|
11
11
|
import * as path from 'path';
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import { execSync } from 'child_process';
|
|
14
|
-
import {
|
|
15
|
-
import { resolveWebBaseUrl } from '../../exporters/env-qa';
|
|
14
|
+
import { getEnvironment } from '../../exporters/run-environment';
|
|
16
15
|
import {
|
|
17
16
|
buildDashboardSnapshot,
|
|
18
17
|
DashboardTarget,
|
|
@@ -37,30 +36,6 @@ const COLOR = {
|
|
|
37
36
|
|
|
38
37
|
function log(msg: string): void { console.log(msg); }
|
|
39
38
|
|
|
40
|
-
function getEnvironment(cwd: string): EnvironmentInfo {
|
|
41
|
-
let baseURL = '';
|
|
42
|
-
let projectName = 'chromium';
|
|
43
|
-
const configPath = path.join(cwd, 'playwright.config.ts');
|
|
44
|
-
if (fs.existsSync(configPath)) {
|
|
45
|
-
const c = fs.readFileSync(configPath, 'utf-8');
|
|
46
|
-
// Both config shapes: legacy literal and env-aware resolveBaseUrl('x') wrapper.
|
|
47
|
-
const baseMatch = c.match(/baseURL:\s*(?:resolveBaseUrl\(\s*)?['"]([^'"]+)['"]/);
|
|
48
|
-
if (baseMatch) baseURL = baseMatch[1];
|
|
49
|
-
const projMatch = c.match(/name:\s*['"]([^'"]+)['"]/);
|
|
50
|
-
if (projMatch) projectName = projMatch[1];
|
|
51
|
-
}
|
|
52
|
-
// Same SUNGEN_BASE_URL override as delivery — the two surfaces must agree.
|
|
53
|
-
baseURL = resolveWebBaseUrl(cwd, baseURL);
|
|
54
|
-
|
|
55
|
-
let executor = process.env.CI_USER || process.env.USER || '';
|
|
56
|
-
try {
|
|
57
|
-
const gitUser = execSync('git config user.name', { cwd, encoding: 'utf-8' }).trim();
|
|
58
|
-
if (gitUser) executor = gitUser;
|
|
59
|
-
} catch { /* ignore */ }
|
|
60
|
-
|
|
61
|
-
return { baseURL, projectName, executor };
|
|
62
|
-
}
|
|
63
|
-
|
|
64
39
|
interface DashboardOptions {
|
|
65
40
|
noHistory?: boolean;
|
|
66
41
|
open?: boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { resolveUnit } from '../resolve-unit';
|
|
3
|
+
import { draftDefects } from '../../harness/defect-draft';
|
|
4
|
+
import { readDefects } from '../../harness/defects';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `sungen defect draft|list` — defect records under qa/defects/ (see harness/defects.ts).
|
|
8
|
+
* `draft` writes one record per product-candidate row of the unit's last `sungen triage`.
|
|
9
|
+
*/
|
|
10
|
+
export function registerDefectCommand(program: Command): void {
|
|
11
|
+
const defect = program.command('defect').description('Draft and list defect records (qa/defects/DEF-NNN-*.md) from red scenarios');
|
|
12
|
+
|
|
13
|
+
defect
|
|
14
|
+
.command('draft')
|
|
15
|
+
.description('Draft a defect record for each product-candidate row of the last `sungen triage`')
|
|
16
|
+
.option('-s, --screen <name>', 'Screen or flow name')
|
|
17
|
+
.option('--api <name>', 'API-first area or api flow (qa/api/<name>)')
|
|
18
|
+
.option('--scenario <title|id>', 'Only the scenario whose title contains this text, or that carries this VP id')
|
|
19
|
+
.option('--json', 'Output raw JSON')
|
|
20
|
+
.action((o: { screen?: string; api?: string; scenario?: string; json?: boolean }) => {
|
|
21
|
+
try {
|
|
22
|
+
const name = o.screen || o.api;
|
|
23
|
+
if (!name) throw new Error('Provide --screen <name> (or --api <area>)');
|
|
24
|
+
const unit = resolveUnit(name, process.cwd());
|
|
25
|
+
if (!unit) throw new Error(`Not found: qa/screens/${name}, qa/flows/${name}, or qa/api/${name}`);
|
|
26
|
+
const r = draftDefects(process.cwd(), unit, { scenario: o.scenario });
|
|
27
|
+
if (o.json) { console.log(JSON.stringify(r, null, 2)); return; }
|
|
28
|
+
if (r.missingTriage) { console.log(`\n ${name}: no triage yet — run \`sungen triage --screen ${name}\` after the tests.\n`); return; }
|
|
29
|
+
for (const f of r.written) console.log(` ✎ ${f}`);
|
|
30
|
+
for (const s of r.skipped) console.log(` ○ already recorded as ${s.id}: ${s.scenario}`);
|
|
31
|
+
if (!r.written.length && !r.skipped.length) console.log(` ✓ ${name}: no product-candidate rows to draft.`);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error('Error:', error instanceof Error ? error.message : error);
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
defect
|
|
39
|
+
.command('list')
|
|
40
|
+
.description('List defect records (id, severity, status, units, scenario count)')
|
|
41
|
+
.option('--status <status>', 'Only records with this status (open, fixed, verified, closed, wont-fix)')
|
|
42
|
+
.option('--json', 'Output raw JSON')
|
|
43
|
+
.action((o: { status?: string; json?: boolean }) => {
|
|
44
|
+
const rows = readDefects(process.cwd()).filter((r) => !o.status || r.status === o.status);
|
|
45
|
+
if (o.json) { console.log(JSON.stringify(rows, null, 2)); return; }
|
|
46
|
+
if (!rows.length) { console.log(' (no defect records)'); return; }
|
|
47
|
+
for (const r of rows) console.log(` ${r.id} ${r.severity.padEnd(8)} ${r.status.padEnd(9)} ${r.units.join(',')} ${r.scenarios.length} scenario(s) ${r.title}`);
|
|
48
|
+
});
|
|
49
|
+
}
|