@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
|
@@ -0,0 +1,106 @@
|
|
|
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.titlesToGrep = titlesToGrep;
|
|
37
|
+
exports.parseIdList = parseIdList;
|
|
38
|
+
exports.selectByIds = selectByIds;
|
|
39
|
+
/**
|
|
40
|
+
* Select scenarios by test-case ID — backs `sungen select` and `run-test --ids` (#835).
|
|
41
|
+
*
|
|
42
|
+
* An ID means what it means everywhere else in the harness: `vpId`, the leading ID token of the
|
|
43
|
+
* scenario title (`VP-UI-001`, `MS-HP-001`, `VP0-001`). Matching is exact and case-insensitive —
|
|
44
|
+
* `VP-UI-001` never selects `VP-UI-0010` or `VP-UI-001-B` — and every ID that selects nothing
|
|
45
|
+
* runnable is reported, because the alternative is a 0-test run that reports green.
|
|
46
|
+
*/
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
/**
|
|
49
|
+
* Escape scenario titles into one `-g` / `--mochaOpts.grep` regex. Full titles, not bare IDs:
|
|
50
|
+
* a title starts with its own ID, so it can only appear inside its own test's title — and a
|
|
51
|
+
* `@cases` row test (`<title> — <row label>`) still contains it.
|
|
52
|
+
*/
|
|
53
|
+
function titlesToGrep(titles) {
|
|
54
|
+
return titles.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
|
|
55
|
+
}
|
|
56
|
+
/** `"VP-UI-001, vp-ui-002 VP-UI-001"` → `['VP-UI-001', 'VP-UI-002']`. */
|
|
57
|
+
function parseIdList(raw) {
|
|
58
|
+
return [...new Set(raw.split(/[\s,]+/).map((s) => s.trim().toUpperCase()).filter(Boolean))];
|
|
59
|
+
}
|
|
60
|
+
/** `VP-C-002.` → `VP-C-002`: the title token may carry trailing punctuation the user never types. */
|
|
61
|
+
const idOf = (s) => s.vpId?.replace(/[.-]+$/, '') || undefined;
|
|
62
|
+
function notRunnableReason(s, enabledCaps) {
|
|
63
|
+
if (s.deferredToFlow)
|
|
64
|
+
return `owned by a flow${s.ownedByFlow ? ` (${s.ownedByFlow})` : ''} — run it there`;
|
|
65
|
+
if (s.featureManual)
|
|
66
|
+
return 'its Feature is @manual — no spec is generated for it';
|
|
67
|
+
if (s.manual)
|
|
68
|
+
return 'manual — no automated test exists';
|
|
69
|
+
// Compiled as `test.skip` while the capability is off: the run would report a skip, not a result.
|
|
70
|
+
const missing = (s.requiresCaps ?? []).filter((c) => !enabledCaps.has(c));
|
|
71
|
+
if (missing.length)
|
|
72
|
+
return `needs capability ${missing.join(', ')} — compiled as a skip until \`sungen capability add ${missing.join(' ')}\``;
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
function selectByIds(scenarios, ids, unit, enabledCaps = new Set()) {
|
|
76
|
+
const out = { features: [], unknown: [], notRunnable: [] };
|
|
77
|
+
const groups = new Map();
|
|
78
|
+
const allIds = [...new Set(scenarios.map(idOf).filter((v) => !!v))];
|
|
79
|
+
for (const id of ids) {
|
|
80
|
+
const hits = scenarios.filter((s) => idOf(s) === id);
|
|
81
|
+
if (hits.length === 0) {
|
|
82
|
+
const didYouMean = allIds.filter((v) => v.startsWith(`${id}-`) || id.startsWith(`${v}-`)).slice(0, 5);
|
|
83
|
+
out.unknown.push({ id, didYouMean });
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const runnable = hits.filter((s) => !notRunnableReason(s, enabledCaps));
|
|
87
|
+
if (runnable.length === 0) {
|
|
88
|
+
out.notRunnable.push({ id, reason: notRunnableReason(hits[0], enabledCaps) });
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
for (const s of runnable) {
|
|
92
|
+
const feature = s.sourceFile ? path.basename(s.sourceFile, '.feature') : unit;
|
|
93
|
+
const g = groups.get(feature) ?? { feature, ids: [], titles: [], grep: '' };
|
|
94
|
+
if (!g.ids.includes(id))
|
|
95
|
+
g.ids.push(id);
|
|
96
|
+
if (!g.titles.includes(s.name))
|
|
97
|
+
g.titles.push(s.name);
|
|
98
|
+
groups.set(feature, g);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
for (const g of groups.values())
|
|
102
|
+
g.grep = titlesToGrep(g.titles);
|
|
103
|
+
out.features = [...groups.values()];
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=select-by-ids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-by-ids.js","sourceRoot":"","sources":["../../src/harness/select-by-ids.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,6 +41,17 @@ export interface GateResult {
|
|
|
41
41
|
status: 'missing' | 'shallow';
|
|
42
42
|
}[];
|
|
43
43
|
universalGaps: string[];
|
|
44
|
+
/**
|
|
45
|
+
* WHICH scenario covered each satisfied theme, and on which keyword — the audit's second line of
|
|
46
|
+
* defence against a bogus coverage claim (#776). A bare count ("themes 3/3") gives a reviewer
|
|
47
|
+
* nothing to check, so a nonsense match survives; naming the evidence makes it obvious on sight.
|
|
48
|
+
* Mirrors how the Claim-Proof section already names the scenario behind each claim.
|
|
49
|
+
*/
|
|
50
|
+
coveredBy: {
|
|
51
|
+
theme: string;
|
|
52
|
+
by: string;
|
|
53
|
+
keyword: string;
|
|
54
|
+
}[];
|
|
44
55
|
}
|
|
45
56
|
/**
|
|
46
57
|
* An explicit `page-type: <id>` line in test-viewpoint.md — the project stating what
|
|
@@ -134,6 +145,7 @@ export interface OracleStrengthResult {
|
|
|
134
145
|
code?: string;
|
|
135
146
|
}[];
|
|
136
147
|
facetClaims: number;
|
|
148
|
+
weakFacet: number;
|
|
137
149
|
ratio: number;
|
|
138
150
|
}
|
|
139
151
|
export declare function oracleStrength(scenarios: ScenarioInfo[]): OracleStrengthResult;
|
|
@@ -210,6 +222,9 @@ export interface TraceResult {
|
|
|
210
222
|
mappedToOverview: number;
|
|
211
223
|
withVpCodeRatio: number;
|
|
212
224
|
mappedRatio: number;
|
|
225
|
+
/** Viewpoint IDs read from test-viewpoint.md. 0 = nothing to map to, so `mappedRatio` is not a
|
|
226
|
+
* measurement — the scenario IDs were never checked (#832). */
|
|
227
|
+
overviewIds: number;
|
|
213
228
|
note: string;
|
|
214
229
|
}
|
|
215
230
|
export declare function traceability(scenarios: ScenarioInfo[], viewpoints: ViewpointEntry[]): TraceResult;
|
|
@@ -267,8 +282,12 @@ export declare function numericClaimGaps(scenarios: ScenarioInfo[]): Array<{
|
|
|
267
282
|
* The Priority-Viewpoints table is where release selection is supposed to come from. When the
|
|
268
283
|
* table says a flow is `Low` and its scenario is tagged `@high`, a smoke run picks up work the QA
|
|
269
284
|
* deliberately deprioritised — and nobody can tell which of the two was the decision (#622).
|
|
285
|
+
*
|
|
286
|
+
* Reads the SAME parse traceability does (`parseViewpointOverview`). It used to scan the raw text
|
|
287
|
+
* for any `| VP-… | high |` row, so one audit run "saw" an id for this check and not for
|
|
288
|
+
* traceability (#833), and a row in a Known Issues table could raise a contradiction.
|
|
270
289
|
*/
|
|
271
|
-
export declare function priorityMismatches(
|
|
290
|
+
export declare function priorityMismatches(viewpoints: ViewpointEntry[], scenarios: ScenarioInfo[]): Array<{
|
|
272
291
|
id: string;
|
|
273
292
|
declared: string;
|
|
274
293
|
tagged: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sensors.d.ts","sourceRoot":"","sources":["../../src/harness/sensors.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAY,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"sensors.d.ts","sourceRoot":"","sources":["../../src/harness/sensors.ts"],"names":[],"mappings":"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"}
|
package/dist/harness/sensors.js
CHANGED
|
@@ -57,6 +57,9 @@ const path = __importStar(require("path"));
|
|
|
57
57
|
const yaml_1 = require("yaml");
|
|
58
58
|
const parse_1 = require("./parse");
|
|
59
59
|
const read_text_1 = require("./read-text");
|
|
60
|
+
const keyword_match_1 = require("./keyword-match");
|
|
61
|
+
const viewpoint_priority_1 = require("./viewpoint-priority");
|
|
62
|
+
const counted_assertions_1 = require("./counted-assertions");
|
|
60
63
|
// Business-critical category keywords (matched by CONTAINMENT against the VP category, so a
|
|
61
64
|
// compound category like LIST-DISPLAY / ADD-TO-CART / PRODUCT-DISCOVERY classifies correctly).
|
|
62
65
|
const BUSINESS_CRITICAL_CATS = [
|
|
@@ -114,18 +117,11 @@ function loadCatalog() {
|
|
|
114
117
|
const p = path.join(__dirname, 'catalog', 'universal-viewpoints.yaml');
|
|
115
118
|
return (0, yaml_1.parse)((0, read_text_1.readTextFile)(p));
|
|
116
119
|
}
|
|
117
|
-
// Word-aware keyword match
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
const
|
|
122
|
-
const esc = kw.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
123
|
-
return new RegExp(`\\b${esc}(?:s|es|ed|ing)?\\b`);
|
|
124
|
-
};
|
|
125
|
-
const has = (haystacks, kw) => {
|
|
126
|
-
const re = wordRe(kw);
|
|
127
|
-
return haystacks.some((h) => re.test(h));
|
|
128
|
-
};
|
|
120
|
+
// Word-aware keyword match — one rule for every sensor, in ./keyword-match (#776). A keyword
|
|
121
|
+
// matches at a word START but may carry any suffix, so `form` does not match inside `Format` or
|
|
122
|
+
// `@platform` while `submit` still matches `submitted`. The old local copy anchored BOTH ends,
|
|
123
|
+
// which silently dropped every inflected true positive; see that module for the measurements.
|
|
124
|
+
const has = keyword_match_1.hasKeyword;
|
|
129
125
|
/**
|
|
130
126
|
* An explicit `page-type: <id>` line in test-viewpoint.md — the project stating what
|
|
131
127
|
* kind of screen this is. A declaration always beats keyword detection.
|
|
@@ -188,13 +184,15 @@ function viewpointGate(scenarios, viewpoints, catalog, isMobile = false, viewpoi
|
|
|
188
184
|
}
|
|
189
185
|
const evidence = { hits: best, runnerUp };
|
|
190
186
|
const gaps = [];
|
|
187
|
+
const coveredBy = [];
|
|
191
188
|
let total = 0, covered = 0;
|
|
192
189
|
if (pageType) {
|
|
193
190
|
for (const t of catalog.page_types[pageType].must_cover) {
|
|
194
191
|
total++;
|
|
195
192
|
// Scenarios that cover this theme by keyword (include @manual — a manual
|
|
196
193
|
// scenario with a real assertion still covers the viewpoint for design).
|
|
197
|
-
|
|
194
|
+
// Word-aware since #776: a substring match let `information` satisfy `format-boundary`.
|
|
195
|
+
const coverers = scenarios.filter((s) => t.keywords.some((k) => (0, keyword_match_1.keywordHit)(s.haystack, k)));
|
|
198
196
|
if (coverers.length === 0) {
|
|
199
197
|
gaps.push({ theme: t.theme, keywords: t.keywords, status: 'missing' });
|
|
200
198
|
continue;
|
|
@@ -203,12 +201,26 @@ function viewpointGate(scenarios, viewpoints, catalog, isMobile = false, viewpoi
|
|
|
203
201
|
// assertion, so mere presence covers it. Only DATA-correctness themes (depth.requires:
|
|
204
202
|
// data-assertion) need a data assertion to count as deeply covered.
|
|
205
203
|
const needsDepth = t.depth?.requires === 'data-assertion';
|
|
206
|
-
|
|
204
|
+
// Name the evidence for whichever scenario actually carries the theme — the one with the
|
|
205
|
+
// data assertion when depth is required, since that is the scenario the credit rests on.
|
|
206
|
+
const proof = (needsDepth ? coverers.find((s) => s.hasDataAssertion) : undefined) ?? coverers[0];
|
|
207
|
+
const credit = () => {
|
|
207
208
|
covered++;
|
|
209
|
+
coveredBy.push({
|
|
210
|
+
theme: t.theme,
|
|
211
|
+
by: proof.haystack,
|
|
212
|
+
// `proof` came out of `coverers`, which was filtered on this same predicate, so the find
|
|
213
|
+
// always lands — the `!` states that rather than inventing a fallback keyword that would
|
|
214
|
+
// misattribute the credit if the invariant ever broke.
|
|
215
|
+
keyword: t.keywords.find((k) => (0, keyword_match_1.keywordHit)(proof.haystack, k)),
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
if (!needsDepth) {
|
|
219
|
+
credit();
|
|
208
220
|
continue;
|
|
209
221
|
}
|
|
210
222
|
if (coverers.some((s) => s.hasDataAssertion))
|
|
211
|
-
|
|
223
|
+
credit();
|
|
212
224
|
else
|
|
213
225
|
gaps.push({ theme: t.theme, keywords: t.keywords, status: 'shallow' });
|
|
214
226
|
}
|
|
@@ -231,6 +243,7 @@ function viewpointGate(scenarios, viewpoints, catalog, isMobile = false, viewpoi
|
|
|
231
243
|
coverageRatio: total ? covered / total : 1,
|
|
232
244
|
gaps,
|
|
233
245
|
universalGaps,
|
|
246
|
+
coveredBy,
|
|
234
247
|
};
|
|
235
248
|
}
|
|
236
249
|
// Intent → required depth ratio + whether a miss WARNs (smoke) or FAILs the gate.
|
|
@@ -264,7 +277,7 @@ function assertionDepth(scenarios, dataThemes = [], focus = 'functional') {
|
|
|
264
277
|
// dialog") assert a HIDDEN state — that IS the correct, data-light assertion for the
|
|
265
278
|
// behavior. They only match a data keyword incidentally (e.g. "added"), so exclude them.
|
|
266
279
|
const isDismissBehavior = (s) => /\bis hidden\b|\bare hidden\b|\bdismiss|\bdisappear|\bno longer (visible|shown|present|displayed)\b|\bcloses? the (modal|dialog|popup|overlay|panel|menu)\b/.test(s.haystack);
|
|
267
|
-
const isDepthRequired = (s) => s.category !== 'NAV' && !isDismissBehavior(s) && depthKeywords.some((k) => s.haystack
|
|
280
|
+
const isDepthRequired = (s) => s.category !== 'NAV' && !isDismissBehavior(s) && depthKeywords.some((k) => (0, keyword_match_1.keywordHit)(s.haystack, k));
|
|
268
281
|
const required = nonManual.filter(isDepthRequired);
|
|
269
282
|
const reqShallow = required.filter((s) => s.shallow);
|
|
270
283
|
// Business-critical scenarios deferred to @manual (match a data-theme but excluded above).
|
|
@@ -324,7 +337,7 @@ function automatableManual(scenarios) {
|
|
|
324
337
|
function flowCoveredThemes(gaps, flowScenarios) {
|
|
325
338
|
const out = [];
|
|
326
339
|
for (const g of gaps) {
|
|
327
|
-
const hit = flowScenarios.find((s) => s.deep && g.keywords.some((k) => s.haystack
|
|
340
|
+
const hit = flowScenarios.find((s) => s.deep && g.keywords.some((k) => (0, keyword_match_1.keywordHit)(s.haystack, k)));
|
|
328
341
|
if (hit)
|
|
329
342
|
out.push({ theme: g.theme, flow: hit.flow });
|
|
330
343
|
}
|
|
@@ -386,10 +399,12 @@ function oracleStrength(scenarios) {
|
|
|
386
399
|
hint: `every \`Then\` is a URL assertion${guardLike ? ' on a permission / guard scenario' : ''} — it proves the router pushed a path, not that the page rendered for this user${guardLike ? ', and this is exactly the scenario a late 403 redirect turns falsely green' : ''}. Give the page selector an \`anchor:\` (a heading/landmark only the rendered page has) — one line per screen, and every \`see [X] page\` on it becomes a content oracle — or add a content assertion after it.`,
|
|
387
400
|
});
|
|
388
401
|
}
|
|
402
|
+
let weakFacet = 0;
|
|
389
403
|
for (const s of scenarios) {
|
|
390
404
|
if (s.manual)
|
|
391
405
|
continue; // a @manual facet check is a deliberate deferral, not a weak automated oracle
|
|
392
406
|
if (WEAK_FACET_ORACLE.test(s.stepsText)) {
|
|
407
|
+
weakFacet++;
|
|
393
408
|
weak.push({
|
|
394
409
|
name: s.name.slice(0, 80),
|
|
395
410
|
hint: 'asserting every item NAME contains a category/brand term does not prove facet membership — assert the results-page TITLE/header carries the facet, a detail-page facet field, or an API/DB oracle; or defer the exhaustive check to @manual:M2.',
|
|
@@ -397,7 +412,17 @@ function oracleStrength(scenarios) {
|
|
|
397
412
|
}
|
|
398
413
|
}
|
|
399
414
|
const facetClaims = scenarios.filter((s) => FACET_REF.test(s.stepsText) || FACET_REF.test(s.name)).length;
|
|
400
|
-
|
|
415
|
+
// Only the FACET class is denominated by `facetClaims`. `weak` also carries ORACLE-URL-ONLY
|
|
416
|
+
// findings (#662), which make no category/brand claim at all — averaging them into this axis
|
|
417
|
+
// drove `ratio` negative (5 URL-only over 2 facet claims → 1 - 5/2 = -1.5), which walked through
|
|
418
|
+
// the businessDepth floor and took the CLI's bar renderer down with it (#762). A URL-only oracle
|
|
419
|
+
// is NAMED as a finding and holds the score out of the senior band (`seniorBandedOverall`);
|
|
420
|
+
// it is not averaged into the facet axis — the invariant `url-only-oracle.run.ts` asserts.
|
|
421
|
+
// The clamp is not belt-and-braces: a weak-facet scenario need not itself satisfy FACET_REF
|
|
422
|
+
// (`see all [name] contains {{price.term}}` is weak but claims no facet), so `weakFacet` can
|
|
423
|
+
// still outrun `facetClaims`. This axis is declared 0..1; it leaves here inside 0..1.
|
|
424
|
+
const ratio = facetClaims ? Math.max(0, Math.min(1, 1 - weakFacet / facetClaims)) : 1;
|
|
425
|
+
return { weak, facetClaims, weakFacet, ratio };
|
|
401
426
|
}
|
|
402
427
|
/** Collect data-correctness themes (depth.requires) for a page-type + universal. */
|
|
403
428
|
function dataThemesFor(catalog, pageType) {
|
|
@@ -490,6 +515,27 @@ function scenarioIdReuse(scenarios) {
|
|
|
490
515
|
* a correctly-traced flow suite read as 15% traceable (#592).
|
|
491
516
|
*/
|
|
492
517
|
const unprefixed = (id) => id.replace(/^(?:VP|FL)-/i, '').toUpperCase();
|
|
518
|
+
/**
|
|
519
|
+
* The traceability note, worded from the SAME ratio the audit's TRACE finding fires on —
|
|
520
|
+
* mapped / ALL scenarios (#852). It used to compare mapped against scenarios WITH an id, so 0 of
|
|
521
|
+
* 0 (no scenario yet, or none tagged) and 2 of 2 tagged out of 10 all read "Traceable." while
|
|
522
|
+
* the audit reported `TRACE: Traceable.` for a 0–20% mapping.
|
|
523
|
+
*/
|
|
524
|
+
function traceNote(total, withCode, mapped, declared, exampleId) {
|
|
525
|
+
if (declared === 0) {
|
|
526
|
+
return 'No viewpoint ID found in test-viewpoint.md — the file is missing, or none of its sections declares one — so the scenario IDs were not checked. Declarations are read from a `## Priority Viewpoints` table, `### Required / Recommended / Optional` lists, and tables whose first column is a `VP-`/`FL-` ID or an ID of a family declared there (Known Issues / Traceability / References sections are skipped).';
|
|
527
|
+
}
|
|
528
|
+
if (total === 0)
|
|
529
|
+
return 'No scenarios yet — traceability is measured once the feature has scenarios.';
|
|
530
|
+
if (mapped >= total * 0.5)
|
|
531
|
+
return 'Traceable.';
|
|
532
|
+
const example = exampleId ? ` (e.g. \`${exampleId}-001 …\`)` : '';
|
|
533
|
+
if (withCode === 0)
|
|
534
|
+
return `No scenario carries a viewpoint ID — start each title with one of the IDs declared in test-viewpoint.md${example}.`;
|
|
535
|
+
if (mapped < withCode * 0.5)
|
|
536
|
+
return 'Scenario IDs do not match the viewpoint-overview ids (weak traceability — re-tag to the project viewpoint IDs).';
|
|
537
|
+
return `Only ${mapped} of ${total} scenarios carry a declared viewpoint ID — ${total - withCode} have no ID at all; tag them with the project's IDs${example}.`;
|
|
538
|
+
}
|
|
493
539
|
function traceability(scenarios, viewpoints) {
|
|
494
540
|
const overviewIds = new Set(viewpoints.map((v) => v.id.toUpperCase()));
|
|
495
541
|
const overviewBare = new Set(viewpoints.map((v) => unprefixed(v.id)));
|
|
@@ -517,9 +563,10 @@ function traceability(scenarios, viewpoints) {
|
|
|
517
563
|
mappedToOverview: mapped.length,
|
|
518
564
|
withVpCodeRatio: scenarios.length ? withCode.length / scenarios.length : 0,
|
|
519
565
|
mappedRatio: scenarios.length ? mapped.length / scenarios.length : 0,
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
566
|
+
overviewIds: overviewIds.size,
|
|
567
|
+
// With no ID read there is nothing to match against: telling the author to re-tag sends them
|
|
568
|
+
// to change scenarios that may be right (#832). Name the file and the sections read instead.
|
|
569
|
+
note: traceNote(scenarios.length, withCode.length, mapped.length, overviewIds.size, viewpoints[0]?.id),
|
|
523
570
|
};
|
|
524
571
|
}
|
|
525
572
|
// Ordered by specificity; the first matching rule per scenario wins.
|
|
@@ -537,6 +584,31 @@ const CLAIM_RULES = [
|
|
|
537
584
|
hint: 'swap `contains {{v}}` for `with {{v}}` on the continuity rows. A substring match cannot distinguish "unchanged" from "changed by adding a prefix" — and if the screen genuinely renders extra text around the value, say so in the title instead of claiming exactness.',
|
|
538
585
|
severity: 'warn',
|
|
539
586
|
},
|
|
587
|
+
{
|
|
588
|
+
// An ORDER claim ("sorted by date descending", "ties broken by last-updated") is invisible to
|
|
589
|
+
// a presence check: `see [List] table` passes whatever order the rows are in. It sits ahead of
|
|
590
|
+
// the generic rules so "all results sorted …" is judged as an ordering claim, not an all-claim.
|
|
591
|
+
// A tiebreaker is a Tier-1 guard in the tc-generation skill, yet no rule recognised it (#810).
|
|
592
|
+
claim: 'ordering/sort',
|
|
593
|
+
title: /\b(ascending|descending|sorted|sorts|sort order|ordered by|order by|in (?:chronological|alphabetical|reverse|numeric) order|(?:newest|oldest|latest|earliest|highest|lowest) first|tie-?break(?:s|er|ers)?|ties?)\b|降順|昇順|並び順|giảm dần|tăng dần|sắp xếp/,
|
|
594
|
+
proof: /match data|is sorted|sorted (?:ascending|descending)|\brow \d+\b|\.first\.|\.last\.|\[\d+\]\.|order by/,
|
|
595
|
+
need: 'an order-sensitive assertion (`table match data:` rows in the expected order, `is sorted ascending|descending`, or positional `row N` checks)',
|
|
596
|
+
hint: 'a presence check passes in any order — assert the rows in their expected sequence (`User see [T] table match data:`), or the column sort state; a tiebreak needs two rows sharing the primary key.',
|
|
597
|
+
severity: 'fail',
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
// A LIMIT claim ("never exceeds 10", "at most 5 files") is a count claim in disguise.
|
|
601
|
+
// Ahead of 'no-side-effect', whose negation+effect pattern would otherwise swallow
|
|
602
|
+
// "never exceeds 10 records" and ask for a duplicate-count proof.
|
|
603
|
+
claim: 'limit/cap',
|
|
604
|
+
// The quantity must be ≥2 ("at most ONE order" is a no-duplicate claim — left to the rules
|
|
605
|
+
// below) and not a duration ("up to 30 seconds" is a timing claim, not a cap).
|
|
606
|
+
title: /\b(?:never exceeds?|(?:does not|doesn['’]t|not) exceed|at most|no more than|up to|capped at|caps? at|maximum of|max(?:imum)?)\s+(?:\d{2,}|[2-9]|two|three|four|five|six|seven|eight|nine|ten)\b(?!\s*(?:ms|milliseconds?|s|secs?|seconds?|mins?|minutes?|hours?|days?)\b)|\b(?:never exceeds?|(?:does not|doesn['’]t) exceed) (?:the )?(?:limit|cap|quota|maximum)\b|以内|上限|tối đa/,
|
|
607
|
+
proof: /\bcount\b|tohavecount|table with|row with \{\{|match data|is at most|\bexactly\b|field with \{\{|\berror\b|invalid|is disabled/,
|
|
608
|
+
need: 'a count/boundary assertion (count is N, `is at most`, the N+1th input rejected or truncated)',
|
|
609
|
+
hint: 'assert the boundary itself — the count at the cap, or the value/error when one more is attempted — not just that the list or field is present.',
|
|
610
|
+
severity: 'fail',
|
|
611
|
+
},
|
|
540
612
|
{
|
|
541
613
|
claim: 'all/every/each',
|
|
542
614
|
title: /\b(all|every|each)\b/,
|
|
@@ -681,6 +753,12 @@ const CLAIM_RULES = [
|
|
|
681
753
|
},
|
|
682
754
|
];
|
|
683
755
|
const TAXONOMY_KNOWN = new Set(['LIST', 'PRODUCT', 'CART', 'FILTER', 'NAV', 'VAL', 'SEC']);
|
|
756
|
+
/**
|
|
757
|
+
* Words of ACCESS — a title about who may reach something. They make the robustness/routing words
|
|
758
|
+
* below security evidence ("deep link without authentication"); alone those words describe routing.
|
|
759
|
+
*/
|
|
760
|
+
const ACCESS_CONTEXT = /\b(xss|sql|injection|without authentication|unauthenticated|unauthori[sz]ed|without an? (?:authenticated|valid|active) \w+|without (?:permission|login|logging in|signing in|an? account|access)|not (?:logged|signed) in|logged[- ]out|direct(?:ly)? access\w*|auth[- ]?guard|forbidden|\b403\b|(?:no|insufficient|missing) permissions?|permission required|session expired|expired session|tamper\w*)\b/;
|
|
761
|
+
/** `requires`: the signal counts only when the title ALSO matches it (#888). */
|
|
684
762
|
const CATEGORY_SIGNALS = [
|
|
685
763
|
{ cat: 'FILTER', re: /\b(categor(y|ies)|sub-?categor\w*|expand\w*|collaps\w*|\bfacet\b|filter\w*|belongs? to)\b/ },
|
|
686
764
|
{ cat: 'CART', re: /\b(add(ed|ing)? to cart|added (dialog|modal|message|confirmation)|cart (page|table|line|item)|view cart|continue shopping|quantit)\b/ },
|
|
@@ -693,8 +771,13 @@ const CATEGORY_SIGNALS = [
|
|
|
693
771
|
// SEC, so the linter told QA to re-tag genuine auth-gate tests as navigation — diluting the
|
|
694
772
|
// visibility of the security suite (QA field report, 3.2.23). The guard vocabulary below is
|
|
695
773
|
// what makes the INTENT matchable, and GUARD_INTENT then wins over a mere observable.
|
|
696
|
-
{ cat: 'SEC', re: /\b(xss|sql|injection|payload|without authentication|unauthenticated|without an? (?:authenticated|valid|active) \w+|direct(?:ly)? access\w*|
|
|
774
|
+
{ cat: 'SEC', re: /\b(xss|sql|injection|payload|without authentication|unauthenticated|without an? (?:authenticated|valid|active) \w+|direct(?:ly)? access\w*|auth[- ]?guard|not skippable|without having (?:completed|submitted|logged)|remains? unauthenticated|\binert\b|tamper\w*|malformed|special character|abuse)\b/ },
|
|
775
|
+
// Robustness and routing words are SEC evidence only beside an ACCESS word. Alone they describe
|
|
776
|
+
// routing — "Unknown route shows the 404 page", "Deep link opens the item", "the tab from the url
|
|
777
|
+
// parameter" — and the linter told QA to re-tag those navigation tests as VP-SEC (#888).
|
|
778
|
+
{ cat: 'SEC', re: /\b(deep[- ]link\w*|url parameter|query param\w*|falls? back|gracefull?y|without a crash|not[- ]found|\b404\b)\b/, requires: ACCESS_CONTEXT },
|
|
697
779
|
];
|
|
780
|
+
const signalMatches = (c, title) => c.re.test(title) && (!c.requires || c.requires.test(title));
|
|
698
781
|
/**
|
|
699
782
|
* Categories whose signal describes the test's INTENT/risk rather than the observable action.
|
|
700
783
|
* When one of these matches, a competing observable-only category (NAV: "redirects", "navigates")
|
|
@@ -712,15 +795,21 @@ function taxonomyLint(scenarios) {
|
|
|
712
795
|
continue;
|
|
713
796
|
checked++;
|
|
714
797
|
const title = s.name.toLowerCase();
|
|
715
|
-
const matched = [...new Set(CATEGORY_SIGNALS.filter((c) => c
|
|
798
|
+
const matched = [...new Set(CATEGORY_SIGNALS.filter((c) => signalMatches(c, title)).map((c) => c.cat))];
|
|
716
799
|
if (matched.includes(cat))
|
|
717
800
|
continue; // title supports its own category → fine
|
|
801
|
+
// A gate (`requires`) only stops a word from SUGGESTING its category. An author who already
|
|
802
|
+
// chose that category is supported by the word alone: a VP-SEC "Deep link to the filtered
|
|
803
|
+
// list …" stays SEC instead of being pushed toward FILTER (#888 review).
|
|
804
|
+
if (CATEGORY_SIGNALS.some((c) => c.cat === cat && c.requires && c.re.test(title)))
|
|
805
|
+
continue;
|
|
718
806
|
// The declared category may be an INTENT category whose signal this title spells
|
|
719
807
|
// differently; never "correct" it toward a category that only names the observable.
|
|
720
808
|
const suppressed = INTENT_OVER_OBSERVABLE[cat];
|
|
721
809
|
const others = matched.filter((c) => c !== cat && !(suppressed && suppressed.has(c)));
|
|
722
810
|
if (others.length === 1) { // unambiguous mismatch
|
|
723
|
-
|
|
811
|
+
// The entry that MATCHED — a category can have several (SEC: guard words, gated robustness words).
|
|
812
|
+
const sig = CATEGORY_SIGNALS.find((c) => c.cat === others[0] && signalMatches(c, title));
|
|
724
813
|
const m = title.match(sig.re);
|
|
725
814
|
mislabeled.push({ name: s.name, current: cat, suggested: others[0], signal: m ? m[0] : others[0] });
|
|
726
815
|
}
|
|
@@ -790,9 +879,8 @@ function numericClaimGaps(scenarios) {
|
|
|
790
879
|
const claimed = NUMBER_WORDS[m[1]] ?? Number(m[1]);
|
|
791
880
|
if (!Number.isFinite(claimed) || claimed < 2)
|
|
792
881
|
continue;
|
|
793
|
-
//
|
|
794
|
-
|
|
795
|
-
const asserted = (s.stepsText.match(/\bsee \[[^\]]+\][^|]*?\b(?:with|contains) \{\{/g) ?? []).length;
|
|
882
|
+
// Values, positive states and indicator presence count; plain text visibility does not (#866).
|
|
883
|
+
const asserted = (0, counted_assertions_1.countedAssertions)(s.stepsText);
|
|
796
884
|
if (asserted > 0 && asserted < claimed)
|
|
797
885
|
out.push({ name: s.name, claimed, asserted, noun: m[2] });
|
|
798
886
|
}
|
|
@@ -804,16 +892,18 @@ function numericClaimGaps(scenarios) {
|
|
|
804
892
|
* The Priority-Viewpoints table is where release selection is supposed to come from. When the
|
|
805
893
|
* table says a flow is `Low` and its scenario is tagged `@high`, a smoke run picks up work the QA
|
|
806
894
|
* deliberately deprioritised — and nobody can tell which of the two was the decision (#622).
|
|
895
|
+
*
|
|
896
|
+
* Reads the SAME parse traceability does (`parseViewpointOverview`). It used to scan the raw text
|
|
897
|
+
* for any `| VP-… | high |` row, so one audit run "saw" an id for this check and not for
|
|
898
|
+
* traceability (#833), and a row in a Known Issues table could raise a contradiction.
|
|
807
899
|
*/
|
|
808
|
-
function priorityMismatches(
|
|
900
|
+
function priorityMismatches(viewpoints, scenarios) {
|
|
809
901
|
const declared = new Map();
|
|
810
|
-
for (const
|
|
811
|
-
|
|
812
|
-
|
|
902
|
+
for (const v of viewpoints)
|
|
903
|
+
if (v.priorityWord)
|
|
904
|
+
declared.set(v.id.toUpperCase(), v.priorityWord);
|
|
813
905
|
if (declared.size === 0)
|
|
814
906
|
return [];
|
|
815
|
-
// `medium` and `normal` are the same rank under different names in real documents.
|
|
816
|
-
const rank = (p) => (p === 'medium' ? 'normal' : p);
|
|
817
907
|
const out = [];
|
|
818
908
|
for (const s of scenarios) {
|
|
819
909
|
const id = (s.vpId ?? '').toUpperCase();
|
|
@@ -823,13 +913,17 @@ function priorityMismatches(viewpointText, scenarios) {
|
|
|
823
913
|
const key = [...declared.keys()].filter((k) => id.startsWith(k)).sort((a, b) => b.length - a.length)[0];
|
|
824
914
|
if (!key)
|
|
825
915
|
continue;
|
|
826
|
-
|
|
827
|
-
const
|
|
828
|
-
// `
|
|
829
|
-
if (want === '
|
|
916
|
+
// Both sides fold through the one priority reading (`critical` ≡ high, `medium`/`med` ≡ normal).
|
|
917
|
+
const want = (0, viewpoint_priority_1.parsePriority)(declared.get(key));
|
|
918
|
+
// `deferred` and `skip` (declared not applicable, #853) have no tag equivalent — nothing to contradict.
|
|
919
|
+
if (want === 'deferred' || want === 'skip')
|
|
920
|
+
continue;
|
|
921
|
+
// An untagged scenario states no priority, so it cannot contradict one (#861).
|
|
922
|
+
const tagged = s.priorityTag ?? (s.priority === 'unknown' ? undefined : String(s.priority));
|
|
923
|
+
if (!tagged)
|
|
830
924
|
continue;
|
|
831
|
-
if (want !==
|
|
832
|
-
out.push({ id: key, declared: declared.get(key), tagged
|
|
925
|
+
if (want !== (0, viewpoint_priority_1.parsePriority)(tagged))
|
|
926
|
+
out.push({ id: key, declared: declared.get(key), tagged, scenario: s.name });
|
|
833
927
|
}
|
|
834
928
|
return out;
|
|
835
929
|
}
|