@sun-asterisk/sungen 3.2.34 → 3.3.0-alpha.2
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/basis/anchor-grammar.d.ts +32 -0
- package/dist/basis/anchor-grammar.d.ts.map +1 -0
- package/dist/basis/anchor-grammar.js +82 -0
- package/dist/basis/anchor-grammar.js.map +1 -0
- package/dist/basis/anchor-hash.d.ts +6 -0
- package/dist/basis/anchor-hash.d.ts.map +1 -0
- package/dist/basis/anchor-hash.js +28 -0
- package/dist/basis/anchor-hash.js.map +1 -0
- package/dist/basis/bm51-tables.d.ts +20 -0
- package/dist/basis/bm51-tables.d.ts.map +1 -0
- package/dist/basis/bm51-tables.js +71 -0
- package/dist/basis/bm51-tables.js.map +1 -0
- package/dist/basis/extract-spec-anchors.d.ts +39 -0
- package/dist/basis/extract-spec-anchors.d.ts.map +1 -0
- package/dist/basis/extract-spec-anchors.js +81 -0
- package/dist/basis/extract-spec-anchors.js.map +1 -0
- package/dist/basis/migration-sentinel.d.ts +47 -0
- package/dist/basis/migration-sentinel.d.ts.map +1 -0
- package/dist/basis/migration-sentinel.js +219 -0
- package/dist/basis/migration-sentinel.js.map +1 -0
- package/dist/basis/spec-frontmatter.d.ts +18 -0
- package/dist/basis/spec-frontmatter.d.ts.map +1 -0
- package/dist/basis/spec-frontmatter.js +55 -0
- package/dist/basis/spec-frontmatter.js.map +1 -0
- package/dist/basis/spec-sections.d.ts +18 -0
- package/dist/basis/spec-sections.d.ts.map +1 -0
- package/dist/basis/spec-sections.js +27 -0
- package/dist/basis/spec-sections.js.map +1 -0
- package/dist/basis/test-basis-schema.d.ts +28 -0
- package/dist/basis/test-basis-schema.d.ts.map +1 -0
- package/dist/basis/test-basis-schema.js +141 -0
- package/dist/basis/test-basis-schema.js.map +1 -0
- package/dist/capabilities/discover.d.ts +4 -0
- package/dist/capabilities/discover.d.ts.map +1 -1
- package/dist/capabilities/discover.js +16 -2
- package/dist/capabilities/discover.js.map +1 -1
- package/dist/capabilities/registry.d.ts +15 -0
- package/dist/capabilities/registry.d.ts.map +1 -1
- package/dist/capabilities/registry.js.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +10 -5
- 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 +6 -2
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/contract-derive-command.d.ts +11 -0
- package/dist/cli/commands/contract-derive-command.d.ts.map +1 -0
- package/dist/cli/commands/contract-derive-command.js +99 -0
- package/dist/cli/commands/contract-derive-command.js.map +1 -0
- package/dist/cli/commands/contract.d.ts +17 -0
- package/dist/cli/commands/contract.d.ts.map +1 -0
- package/dist/cli/commands/contract.js +162 -0
- package/dist/cli/commands/contract.js.map +1 -0
- 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 +96 -12
- 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 +3 -1
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/journey.d.ts.map +1 -1
- package/dist/cli/commands/journey.js +43 -15
- package/dist/cli/commands/journey.js.map +1 -1
- package/dist/cli/commands/next.d.ts +8 -0
- package/dist/cli/commands/next.d.ts.map +1 -1
- package/dist/cli/commands/next.js +68 -8
- package/dist/cli/commands/next.js.map +1 -1
- 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 +11 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +31 -6
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/index.js +24 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/project-sungen-invocation.d.ts +7 -0
- package/dist/cli/project-sungen-invocation.d.ts.map +1 -0
- package/dist/cli/project-sungen-invocation.js +76 -0
- package/dist/cli/project-sungen-invocation.js.map +1 -0
- package/dist/contract/approve-contract.d.ts +31 -0
- package/dist/contract/approve-contract.d.ts.map +1 -0
- package/dist/contract/approve-contract.js +87 -0
- package/dist/contract/approve-contract.js.map +1 -0
- package/dist/contract/assertion-matcher-vocabulary.d.ts +24 -0
- package/dist/contract/assertion-matcher-vocabulary.d.ts.map +1 -0
- package/dist/contract/assertion-matcher-vocabulary.js +100 -0
- package/dist/contract/assertion-matcher-vocabulary.js.map +1 -0
- package/dist/contract/build-contract-verdict.d.ts +32 -0
- package/dist/contract/build-contract-verdict.d.ts.map +1 -0
- package/dist/contract/build-contract-verdict.js +123 -0
- package/dist/contract/build-contract-verdict.js.map +1 -0
- package/dist/contract/build-trace-conformance.d.ts +18 -0
- package/dist/contract/build-trace-conformance.d.ts.map +1 -0
- package/dist/contract/build-trace-conformance.js +153 -0
- package/dist/contract/build-trace-conformance.js.map +1 -0
- package/dist/contract/classify-contract-change.d.ts +23 -0
- package/dist/contract/classify-contract-change.d.ts.map +1 -0
- package/dist/contract/classify-contract-change.js +98 -0
- package/dist/contract/classify-contract-change.js.map +1 -0
- package/dist/contract/classify-contract-unit.d.ts +18 -0
- package/dist/contract/classify-contract-unit.d.ts.map +1 -0
- package/dist/contract/classify-contract-unit.js +49 -0
- package/dist/contract/classify-contract-unit.js.map +1 -0
- package/dist/contract/classify-trace-conformance.d.ts +32 -0
- package/dist/contract/classify-trace-conformance.d.ts.map +1 -0
- package/dist/contract/classify-trace-conformance.js +117 -0
- package/dist/contract/classify-trace-conformance.js.map +1 -0
- package/dist/contract/contract-git.d.ts +24 -0
- package/dist/contract/contract-git.d.ts.map +1 -0
- package/dist/contract/contract-git.js +144 -0
- package/dist/contract/contract-git.js.map +1 -0
- package/dist/contract/contract-hash.d.ts +7 -0
- package/dist/contract/contract-hash.d.ts.map +1 -0
- package/dist/contract/contract-hash.js +38 -0
- package/dist/contract/contract-hash.js.map +1 -0
- package/dist/contract/contract-report-file.d.ts +4 -0
- package/dist/contract/contract-report-file.d.ts.map +1 -0
- package/dist/contract/contract-report-file.js +60 -0
- package/dist/contract/contract-report-file.js.map +1 -0
- package/dist/contract/contract-schema.d.ts +71 -0
- package/dist/contract/contract-schema.d.ts.map +1 -0
- package/dist/contract/contract-schema.js +102 -0
- package/dist/contract/contract-schema.js.map +1 -0
- package/dist/contract/contract-units.d.ts +12 -0
- package/dist/contract/contract-units.d.ts.map +1 -0
- package/dist/contract/contract-units.js +96 -0
- package/dist/contract/contract-units.js.map +1 -0
- package/dist/contract/contracts-lock-file.d.ts +24 -0
- package/dist/contract/contracts-lock-file.d.ts.map +1 -0
- package/dist/contract/contracts-lock-file.js +140 -0
- package/dist/contract/contracts-lock-file.js.map +1 -0
- package/dist/contract/data-normalize.d.ts +10 -0
- package/dist/contract/data-normalize.d.ts.map +1 -0
- package/dist/contract/data-normalize.js +110 -0
- package/dist/contract/data-normalize.js.map +1 -0
- package/dist/contract/derive-free-feature.d.ts +38 -0
- package/dist/contract/derive-free-feature.d.ts.map +1 -0
- package/dist/contract/derive-free-feature.js +154 -0
- package/dist/contract/derive-free-feature.js.map +1 -0
- package/dist/contract/field-semantic-redaction.d.ts +21 -0
- package/dist/contract/field-semantic-redaction.d.ts.map +1 -0
- package/dist/contract/field-semantic-redaction.js +118 -0
- package/dist/contract/field-semantic-redaction.js.map +1 -0
- package/dist/contract/free-feature-blocks.d.ts +10 -0
- package/dist/contract/free-feature-blocks.d.ts.map +1 -0
- package/dist/contract/free-feature-blocks.js +94 -0
- package/dist/contract/free-feature-blocks.js.map +1 -0
- package/dist/contract/lock-secret-guard.d.ts +22 -0
- package/dist/contract/lock-secret-guard.d.ts.map +1 -0
- package/dist/contract/lock-secret-guard.js +134 -0
- package/dist/contract/lock-secret-guard.js.map +1 -0
- package/dist/contract/lock-vs-git-head.d.ts +26 -0
- package/dist/contract/lock-vs-git-head.d.ts.map +1 -0
- package/dist/contract/lock-vs-git-head.js +28 -0
- package/dist/contract/lock-vs-git-head.js.map +1 -0
- package/dist/contract/normalize-contract-step.d.ts +21 -0
- package/dist/contract/normalize-contract-step.d.ts.map +1 -0
- package/dist/contract/normalize-contract-step.js +70 -0
- package/dist/contract/normalize-contract-step.js.map +1 -0
- package/dist/contract/normalize-feature-steps.d.ts +7 -0
- package/dist/contract/normalize-feature-steps.d.ts.map +1 -0
- package/dist/contract/normalize-feature-steps.js +127 -0
- package/dist/contract/normalize-feature-steps.js.map +1 -0
- package/dist/contract/oracle-strength.d.ts +12 -0
- package/dist/contract/oracle-strength.d.ts.map +1 -0
- package/dist/contract/oracle-strength.js +88 -0
- package/dist/contract/oracle-strength.js.map +1 -0
- package/dist/contract/project-contract-blockers.d.ts +10 -0
- package/dist/contract/project-contract-blockers.d.ts.map +1 -0
- package/dist/contract/project-contract-blockers.js +73 -0
- package/dist/contract/project-contract-blockers.js.map +1 -0
- package/dist/contract/record-contract-approval.d.ts +21 -0
- package/dist/contract/record-contract-approval.d.ts.map +1 -0
- package/dist/contract/record-contract-approval.js +98 -0
- package/dist/contract/record-contract-approval.js.map +1 -0
- package/dist/contract/render-free-gherkin.d.ts +40 -0
- package/dist/contract/render-free-gherkin.d.ts.map +1 -0
- package/dist/contract/render-free-gherkin.js +141 -0
- package/dist/contract/render-free-gherkin.js.map +1 -0
- package/dist/contract/render-trace-sentence.d.ts +20 -0
- package/dist/contract/render-trace-sentence.d.ts.map +1 -0
- package/dist/contract/render-trace-sentence.js +109 -0
- package/dist/contract/render-trace-sentence.js.map +1 -0
- package/dist/contract/render-trace-target.d.ts +14 -0
- package/dist/contract/render-trace-target.d.ts.map +1 -0
- package/dist/contract/render-trace-target.js +70 -0
- package/dist/contract/render-trace-target.js.map +1 -0
- package/dist/contract/resolve-unit-trace-identities.d.ts +8 -0
- package/dist/contract/resolve-unit-trace-identities.d.ts.map +1 -0
- package/dist/contract/resolve-unit-trace-identities.js +78 -0
- package/dist/contract/resolve-unit-trace-identities.js.map +1 -0
- package/dist/contract/trace/collect-trace-evidence.d.ts +33 -0
- package/dist/contract/trace/collect-trace-evidence.d.ts.map +1 -0
- package/dist/contract/trace/collect-trace-evidence.js +161 -0
- package/dist/contract/trace/collect-trace-evidence.js.map +1 -0
- package/dist/contract/trace/identity-cache.d.ts +19 -0
- package/dist/contract/trace/identity-cache.d.ts.map +1 -0
- package/dist/contract/trace/identity-cache.js +104 -0
- package/dist/contract/trace/identity-cache.js.map +1 -0
- package/dist/contract/trace/select-final-attempt.d.ts +27 -0
- package/dist/contract/trace/select-final-attempt.d.ts.map +1 -0
- package/dist/contract/trace/select-final-attempt.js +116 -0
- package/dist/contract/trace/select-final-attempt.js.map +1 -0
- package/dist/contract/trace/snapshot-html-renderer.d.ts +31 -0
- package/dist/contract/trace/snapshot-html-renderer.d.ts.map +1 -0
- package/dist/contract/trace/snapshot-html-renderer.js +172 -0
- package/dist/contract/trace/snapshot-html-renderer.js.map +1 -0
- package/dist/contract/trace/snapshot-resolver.d.ts +21 -0
- package/dist/contract/trace/snapshot-resolver.d.ts.map +1 -0
- package/dist/contract/trace/snapshot-resolver.js +65 -0
- package/dist/contract/trace/snapshot-resolver.js.map +1 -0
- package/dist/contract/trace/snapshot-store.d.ts +66 -0
- package/dist/contract/trace/snapshot-store.d.ts.map +1 -0
- package/dist/contract/trace/snapshot-store.js +173 -0
- package/dist/contract/trace/snapshot-store.js.map +1 -0
- package/dist/contract/trace/target-identity.d.ts +74 -0
- package/dist/contract/trace/target-identity.d.ts.map +1 -0
- package/dist/contract/trace/target-identity.js +68 -0
- package/dist/contract/trace/target-identity.js.map +1 -0
- package/dist/contract/trace/test-step-join.d.ts +65 -0
- package/dist/contract/trace/test-step-join.d.ts.map +1 -0
- package/dist/contract/trace/test-step-join.js +80 -0
- package/dist/contract/trace/test-step-join.js.map +1 -0
- package/dist/contract/trace/trace-binding.d.ts +21 -0
- package/dist/contract/trace/trace-binding.d.ts.map +1 -0
- package/dist/contract/trace/trace-binding.js +88 -0
- package/dist/contract/trace/trace-binding.js.map +1 -0
- package/dist/contract/trace/trace-file-reader.d.ts +41 -0
- package/dist/contract/trace/trace-file-reader.d.ts.map +1 -0
- package/dist/contract/trace/trace-file-reader.js +161 -0
- package/dist/contract/trace/trace-file-reader.js.map +1 -0
- package/dist/contract/trace/trace-fingerprint.d.ts +22 -0
- package/dist/contract/trace/trace-fingerprint.d.ts.map +1 -0
- package/dist/contract/trace/trace-fingerprint.js +96 -0
- package/dist/contract/trace/trace-fingerprint.js.map +1 -0
- package/dist/contract/trace/trace-identity-resolution.d.ts +26 -0
- package/dist/contract/trace/trace-identity-resolution.d.ts.map +1 -0
- package/dist/contract/trace/trace-identity-resolution.js +84 -0
- package/dist/contract/trace/trace-identity-resolution.js.map +1 -0
- package/dist/contract/trace/trace-run-record.d.ts +30 -0
- package/dist/contract/trace/trace-run-record.d.ts.map +1 -0
- package/dist/contract/trace/trace-run-record.js +121 -0
- package/dist/contract/trace/trace-run-record.js.map +1 -0
- package/dist/contract/trace/trace-steps.d.ts +19 -0
- package/dist/contract/trace/trace-steps.d.ts.map +1 -0
- package/dist/contract/trace/trace-steps.js +79 -0
- package/dist/contract/trace/trace-steps.js.map +1 -0
- package/dist/contract/trace/trace-zip-limits.d.ts +45 -0
- package/dist/contract/trace/trace-zip-limits.d.ts.map +1 -0
- package/dist/contract/trace/trace-zip-limits.js +52 -0
- package/dist/contract/trace/trace-zip-limits.js.map +1 -0
- package/dist/contract/trace/trace-zip-reader.d.ts +10 -0
- package/dist/contract/trace/trace-zip-reader.d.ts.map +1 -0
- package/dist/contract/trace/trace-zip-reader.js +186 -0
- package/dist/contract/trace/trace-zip-reader.js.map +1 -0
- package/dist/contract/verify-approval-decisions.d.ts +5 -0
- package/dist/contract/verify-approval-decisions.d.ts.map +1 -0
- package/dist/contract/verify-approval-decisions.js +104 -0
- package/dist/contract/verify-approval-decisions.js.map +1 -0
- package/dist/decisions/append-decision.d.ts +12 -0
- package/dist/decisions/append-decision.d.ts.map +1 -0
- package/dist/decisions/append-decision.js +73 -0
- package/dist/decisions/append-decision.js.map +1 -0
- package/dist/decisions/confirmed-decision-commands.d.ts +41 -0
- package/dist/decisions/confirmed-decision-commands.d.ts.map +1 -0
- package/dist/decisions/confirmed-decision-commands.js +190 -0
- package/dist/decisions/confirmed-decision-commands.js.map +1 -0
- package/dist/decisions/decision-file.d.ts +31 -0
- package/dist/decisions/decision-file.d.ts.map +1 -0
- package/dist/decisions/decision-file.js +139 -0
- package/dist/decisions/decision-file.js.map +1 -0
- package/dist/decisions/decision-identity.d.ts +12 -0
- package/dist/decisions/decision-identity.d.ts.map +1 -0
- package/dist/decisions/decision-identity.js +78 -0
- package/dist/decisions/decision-identity.js.map +1 -0
- package/dist/decisions/decision-integrity-check.d.ts +12 -0
- package/dist/decisions/decision-integrity-check.d.ts.map +1 -0
- package/dist/decisions/decision-integrity-check.js +102 -0
- package/dist/decisions/decision-integrity-check.js.map +1 -0
- package/dist/decisions/decision-schema.d.ts +42 -0
- package/dist/decisions/decision-schema.d.ts.map +1 -0
- package/dist/decisions/decision-schema.js +75 -0
- package/dist/decisions/decision-schema.js.map +1 -0
- package/dist/decisions/decision-source.d.ts +2 -0
- package/dist/decisions/decision-source.d.ts.map +1 -0
- package/dist/decisions/decision-source.js +18 -0
- package/dist/decisions/decision-source.js.map +1 -0
- package/dist/decisions/exclusive-file-create.d.ts +3 -0
- package/dist/decisions/exclusive-file-create.d.ts.map +1 -0
- package/dist/decisions/exclusive-file-create.js +84 -0
- package/dist/decisions/exclusive-file-create.js.map +1 -0
- package/dist/decisions/git-head-trust.d.ts +7 -0
- package/dist/decisions/git-head-trust.d.ts.map +1 -0
- package/dist/decisions/git-head-trust.js +76 -0
- package/dist/decisions/git-head-trust.js.map +1 -0
- package/dist/decisions/human-confirmation.d.ts +35 -0
- package/dist/decisions/human-confirmation.d.ts.map +1 -0
- package/dist/decisions/human-confirmation.js +161 -0
- package/dist/decisions/human-confirmation.js.map +1 -0
- package/dist/decisions/legacy-waiver-migration.d.ts +31 -0
- package/dist/decisions/legacy-waiver-migration.d.ts.map +1 -0
- package/dist/decisions/legacy-waiver-migration.js +170 -0
- package/dist/decisions/legacy-waiver-migration.js.map +1 -0
- package/dist/decisions/read-decisions.d.ts +19 -0
- package/dist/decisions/read-decisions.d.ts.map +1 -0
- package/dist/decisions/read-decisions.js +90 -0
- package/dist/decisions/read-decisions.js.map +1 -0
- package/dist/decisions/viewpoint-baseline-adapter.d.ts +7 -0
- package/dist/decisions/viewpoint-baseline-adapter.d.ts.map +1 -0
- package/dist/decisions/viewpoint-baseline-adapter.js +109 -0
- package/dist/decisions/viewpoint-baseline-adapter.js.map +1 -0
- package/dist/decisions/waiver-decisions.d.ts +24 -0
- package/dist/decisions/waiver-decisions.d.ts.map +1 -0
- package/dist/decisions/waiver-decisions.js +46 -0
- package/dist/decisions/waiver-decisions.js.map +1 -0
- 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 +1 -1
- package/dist/exporters/csv-exporter.js.map +1 -1
- package/dist/exporters/feature-parser.d.ts +8 -0
- package/dist/exporters/feature-parser.d.ts.map +1 -1
- package/dist/exporters/feature-parser.js +12 -0
- package/dist/exporters/feature-parser.js.map +1 -1
- package/dist/exporters/matrix/build.d.ts +3 -0
- package/dist/exporters/matrix/build.d.ts.map +1 -1
- package/dist/exporters/matrix/build.js +59 -19
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/carry-manual-results.d.ts +19 -0
- package/dist/exporters/matrix/carry-manual-results.d.ts.map +1 -1
- package/dist/exporters/matrix/carry-manual-results.js +76 -6
- package/dist/exporters/matrix/carry-manual-results.js.map +1 -1
- package/dist/exporters/matrix/export.d.ts +8 -2
- package/dist/exporters/matrix/export.d.ts.map +1 -1
- package/dist/exporters/matrix/export.js +16 -3
- package/dist/exporters/matrix/export.js.map +1 -1
- package/dist/exporters/matrix/gates.d.ts +6 -1
- package/dist/exporters/matrix/gates.d.ts.map +1 -1
- package/dist/exporters/matrix/gates.js +57 -128
- package/dist/exporters/matrix/gates.js.map +1 -1
- package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
- package/dist/exporters/matrix/render-csv.js +4 -1
- package/dist/exporters/matrix/render-csv.js.map +1 -1
- package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts +13 -0
- package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts.map +1 -0
- package/dist/exporters/matrix/render-gate-overrides-sheet.js +44 -0
- package/dist/exporters/matrix/render-gate-overrides-sheet.js.map +1 -0
- package/dist/exporters/matrix/render-xlsx.d.ts +1 -0
- package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
- package/dist/exporters/matrix/render-xlsx.js +6 -0
- package/dist/exporters/matrix/render-xlsx.js.map +1 -1
- package/dist/exporters/matrix/types.d.ts +9 -1
- package/dist/exporters/matrix/types.d.ts.map +1 -1
- package/dist/exporters/matrix/types.js.map +1 -1
- package/dist/exporters/matrix/xlsx-cells.js +1 -1
- package/dist/exporters/matrix/xlsx-cells.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/scenario-merger.d.ts.map +1 -1
- package/dist/exporters/scenario-merger.js +2 -0
- package/dist/exporters/scenario-merger.js.map +1 -1
- package/dist/exporters/types.d.ts +5 -0
- package/dist/exporters/types.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +13 -0
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/graph/evaluate-graph.d.ts +23 -0
- package/dist/graph/evaluate-graph.d.ts.map +1 -0
- package/dist/graph/evaluate-graph.js +52 -0
- package/dist/graph/evaluate-graph.js.map +1 -0
- package/dist/graph/locate-finding.d.ts +20 -0
- package/dist/graph/locate-finding.d.ts.map +1 -0
- package/dist/graph/locate-finding.js +137 -0
- package/dist/graph/locate-finding.js.map +1 -0
- package/dist/graph/node-decl.d.ts +66 -0
- package/dist/graph/node-decl.d.ts.map +1 -0
- package/dist/graph/node-decl.js +8 -0
- package/dist/graph/node-decl.js.map +1 -0
- package/dist/graph/nodes/core-node-catalog.d.ts +7 -0
- package/dist/graph/nodes/core-node-catalog.d.ts.map +1 -0
- package/dist/graph/nodes/core-node-catalog.js +13 -0
- package/dist/graph/nodes/core-node-catalog.js.map +1 -0
- package/dist/graph/nodes/test-case-contract-nodes.d.ts +21 -0
- package/dist/graph/nodes/test-case-contract-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/test-case-contract-nodes.js +59 -0
- package/dist/graph/nodes/test-case-contract-nodes.js.map +1 -0
- package/dist/graph/nodes/test-case-nodes.d.ts +26 -0
- package/dist/graph/nodes/test-case-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/test-case-nodes.js +66 -0
- package/dist/graph/nodes/test-case-nodes.js.map +1 -0
- package/dist/graph/nodes/unit-audit-nodes.d.ts +18 -0
- package/dist/graph/nodes/unit-audit-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/unit-audit-nodes.js +95 -0
- package/dist/graph/nodes/unit-audit-nodes.js.map +1 -0
- package/dist/graph/nodes/unit-contract-node.d.ts +21 -0
- package/dist/graph/nodes/unit-contract-node.d.ts.map +1 -0
- package/dist/graph/nodes/unit-contract-node.js +88 -0
- package/dist/graph/nodes/unit-contract-node.js.map +1 -0
- package/dist/graph/nodes/unit-design-nodes.d.ts +14 -0
- package/dist/graph/nodes/unit-design-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/unit-design-nodes.js +91 -0
- package/dist/graph/nodes/unit-design-nodes.js.map +1 -0
- package/dist/graph/nodes/unit-execution-nodes.d.ts +16 -0
- package/dist/graph/nodes/unit-execution-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/unit-execution-nodes.js +79 -0
- package/dist/graph/nodes/unit-execution-nodes.js.map +1 -0
- package/dist/graph/test-case-identity.d.ts +13 -0
- package/dist/graph/test-case-identity.d.ts.map +1 -0
- package/dist/graph/test-case-identity.js +106 -0
- package/dist/graph/test-case-identity.js.map +1 -0
- package/dist/graph/test-case-results.d.ts +11 -0
- package/dist/graph/test-case-results.d.ts.map +1 -0
- package/dist/graph/test-case-results.js +137 -0
- package/dist/graph/test-case-results.js.map +1 -0
- package/dist/graph/test-case-satisfied.d.ts +25 -0
- package/dist/graph/test-case-satisfied.d.ts.map +1 -0
- package/dist/graph/test-case-satisfied.js +51 -0
- package/dist/graph/test-case-satisfied.js.map +1 -0
- package/dist/graph/test-case-state-shape.d.ts +67 -0
- package/dist/graph/test-case-state-shape.d.ts.map +1 -0
- package/dist/graph/test-case-state-shape.js +3 -0
- package/dist/graph/test-case-state-shape.js.map +1 -0
- package/dist/graph/test-case-states.d.ts +9 -0
- package/dist/graph/test-case-states.d.ts.map +1 -0
- package/dist/graph/test-case-states.js +116 -0
- package/dist/graph/test-case-states.js.map +1 -0
- package/dist/graph/unit-artifact-probes.d.ts +19 -0
- package/dist/graph/unit-artifact-probes.d.ts.map +1 -0
- package/dist/graph/unit-artifact-probes.js +133 -0
- package/dist/graph/unit-artifact-probes.js.map +1 -0
- package/dist/graph/unit-state-facts.d.ts +43 -0
- package/dist/graph/unit-state-facts.d.ts.map +1 -0
- package/dist/graph/unit-state-facts.js +87 -0
- package/dist/graph/unit-state-facts.js.map +1 -0
- package/dist/harness/audit.d.ts +11 -0
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +34 -9
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/catalog/gate-rules.yaml +647 -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/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/gates/audit-gate-terms.d.ts +41 -0
- package/dist/harness/gates/audit-gate-terms.d.ts.map +1 -0
- package/dist/harness/gates/audit-gate-terms.js +72 -0
- package/dist/harness/gates/audit-gate-terms.js.map +1 -0
- package/dist/harness/gates/audit-gate-verdict.d.ts +31 -0
- package/dist/harness/gates/audit-gate-verdict.d.ts.map +1 -0
- package/dist/harness/gates/audit-gate-verdict.js +101 -0
- package/dist/harness/gates/audit-gate-verdict.js.map +1 -0
- package/dist/harness/gates/audit-input-hash.d.ts +4 -0
- package/dist/harness/gates/audit-input-hash.d.ts.map +1 -0
- package/dist/harness/gates/audit-input-hash.js +96 -0
- package/dist/harness/gates/audit-input-hash.js.map +1 -0
- package/dist/harness/gates/audit-report-verification.d.ts +41 -0
- package/dist/harness/gates/audit-report-verification.d.ts.map +1 -0
- package/dist/harness/gates/audit-report-verification.js +236 -0
- package/dist/harness/gates/audit-report-verification.js.map +1 -0
- package/dist/harness/gates/decisions-hash.d.ts +13 -0
- package/dist/harness/gates/decisions-hash.d.ts.map +1 -0
- package/dist/harness/gates/decisions-hash.js +72 -0
- package/dist/harness/gates/decisions-hash.js.map +1 -0
- package/dist/harness/gates/delivery-checklist.d.ts +21 -0
- package/dist/harness/gates/delivery-checklist.d.ts.map +1 -0
- package/dist/harness/gates/delivery-checklist.js +128 -0
- package/dist/harness/gates/delivery-checklist.js.map +1 -0
- package/dist/harness/gates/delivery-decision-gate.d.ts +33 -0
- package/dist/harness/gates/delivery-decision-gate.d.ts.map +1 -0
- package/dist/harness/gates/delivery-decision-gate.js +116 -0
- package/dist/harness/gates/delivery-decision-gate.js.map +1 -0
- package/dist/harness/gates/delivery-decision-step.d.ts +19 -0
- package/dist/harness/gates/delivery-decision-step.d.ts.map +1 -0
- package/dist/harness/gates/delivery-decision-step.js +86 -0
- package/dist/harness/gates/delivery-decision-step.js.map +1 -0
- package/dist/harness/gates/gate-override-report.d.ts +59 -0
- package/dist/harness/gates/gate-override-report.d.ts.map +1 -0
- package/dist/harness/gates/gate-override-report.js +86 -0
- package/dist/harness/gates/gate-override-report.js.map +1 -0
- package/dist/harness/gates/gate-override-scope.d.ts +18 -0
- package/dist/harness/gates/gate-override-scope.d.ts.map +1 -0
- package/dist/harness/gates/gate-override-scope.js +98 -0
- package/dist/harness/gates/gate-override-scope.js.map +1 -0
- package/dist/harness/gates/gate-override-validation.d.ts +25 -0
- package/dist/harness/gates/gate-override-validation.d.ts.map +1 -0
- package/dist/harness/gates/gate-override-validation.js +81 -0
- package/dist/harness/gates/gate-override-validation.js.map +1 -0
- package/dist/harness/gates/gate-rule-catalog.d.ts +24 -0
- package/dist/harness/gates/gate-rule-catalog.d.ts.map +1 -0
- package/dist/harness/gates/gate-rule-catalog.js +112 -0
- package/dist/harness/gates/gate-rule-catalog.js.map +1 -0
- package/dist/harness/gates/gate-terms.d.ts +33 -0
- package/dist/harness/gates/gate-terms.d.ts.map +1 -0
- package/dist/harness/gates/gate-terms.js +41 -0
- package/dist/harness/gates/gate-terms.js.map +1 -0
- package/dist/harness/gates/in-run-decision-check.d.ts +21 -0
- package/dist/harness/gates/in-run-decision-check.d.ts.map +1 -0
- package/dist/harness/gates/in-run-decision-check.js +138 -0
- package/dist/harness/gates/in-run-decision-check.js.map +1 -0
- package/dist/harness/gates/journey-gate-inputs.d.ts +37 -0
- package/dist/harness/gates/journey-gate-inputs.d.ts.map +1 -0
- package/dist/harness/gates/journey-gate-inputs.js +81 -0
- package/dist/harness/gates/journey-gate-inputs.js.map +1 -0
- package/dist/harness/gates/migrated-waiver-review.d.ts +6 -0
- package/dist/harness/gates/migrated-waiver-review.d.ts.map +1 -0
- package/dist/harness/gates/migrated-waiver-review.js +116 -0
- package/dist/harness/gates/migrated-waiver-review.js.map +1 -0
- package/dist/harness/gates/resolve-rule.d.ts +59 -0
- package/dist/harness/gates/resolve-rule.d.ts.map +1 -0
- package/dist/harness/gates/resolve-rule.js +41 -0
- package/dist/harness/gates/resolve-rule.js.map +1 -0
- package/dist/harness/gates/unit-gate-overrides.d.ts +25 -0
- package/dist/harness/gates/unit-gate-overrides.d.ts.map +1 -0
- package/dist/harness/gates/unit-gate-overrides.js +122 -0
- package/dist/harness/gates/unit-gate-overrides.js.map +1 -0
- package/dist/harness/journey.d.ts +43 -1
- package/dist/harness/journey.d.ts.map +1 -1
- package/dist/harness/journey.js +207 -33
- package/dist/harness/journey.js.map +1 -1
- package/dist/harness/manifest.d.ts +12 -0
- package/dist/harness/manifest.d.ts.map +1 -1
- package/dist/harness/manifest.js +73 -45
- package/dist/harness/manifest.js.map +1 -1
- package/dist/harness/next-step.d.ts +37 -6
- package/dist/harness/next-step.d.ts.map +1 -1
- package/dist/harness/next-step.js +34 -174
- package/dist/harness/next-step.js.map +1 -1
- package/dist/harness/parse.d.ts +25 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +38 -13
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/provenance.d.ts +29 -0
- package/dist/harness/provenance.d.ts.map +1 -1
- package/dist/harness/provenance.js +109 -9
- package/dist/harness/provenance.js.map +1 -1
- package/dist/harness/script-check.d.ts.map +1 -1
- package/dist/harness/script-check.js +29 -6
- package/dist/harness/script-check.js.map +1 -1
- package/dist/harness/sensors.d.ts +14 -3
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +64 -44
- package/dist/harness/sensors.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/viewpoint-ledger.d.ts.map +1 -1
- package/dist/harness/viewpoint-ledger.js +2 -1
- package/dist/harness/viewpoint-ledger.js.map +1 -1
- package/dist/hooks/bash-write-targets.d.ts +15 -0
- package/dist/hooks/bash-write-targets.d.ts.map +1 -0
- package/dist/hooks/bash-write-targets.js +173 -0
- package/dist/hooks/bash-write-targets.js.map +1 -0
- package/dist/hooks/claude-hook-entry.d.ts +11 -0
- package/dist/hooks/claude-hook-entry.d.ts.map +1 -0
- package/dist/hooks/claude-hook-entry.js +137 -0
- package/dist/hooks/claude-hook-entry.js.map +1 -0
- package/dist/hooks/claude-transcript-turn.d.ts +11 -0
- package/dist/hooks/claude-transcript-turn.d.ts.map +1 -0
- package/dist/hooks/claude-transcript-turn.js +143 -0
- package/dist/hooks/claude-transcript-turn.js.map +1 -0
- package/dist/hooks/guard-delivery-contract-rule.d.ts +10 -0
- package/dist/hooks/guard-delivery-contract-rule.d.ts.map +1 -0
- package/dist/hooks/guard-delivery-contract-rule.js +152 -0
- package/dist/hooks/guard-delivery-contract-rule.js.map +1 -0
- package/dist/hooks/guard-protected-paths.d.ts +9 -0
- package/dist/hooks/guard-protected-paths.d.ts.map +1 -0
- package/dist/hooks/guard-protected-paths.js +107 -0
- package/dist/hooks/guard-protected-paths.js.map +1 -0
- package/dist/hooks/guard-rules.d.ts +37 -0
- package/dist/hooks/guard-rules.d.ts.map +1 -0
- package/dist/hooks/guard-rules.js +61 -0
- package/dist/hooks/guard-rules.js.map +1 -0
- package/dist/hooks/guard-tty-spoof-rule.d.ts +15 -0
- package/dist/hooks/guard-tty-spoof-rule.d.ts.map +1 -0
- package/dist/hooks/guard-tty-spoof-rule.js +21 -0
- package/dist/hooks/guard-tty-spoof-rule.js.map +1 -0
- package/dist/hooks/hand-back-core.d.ts +39 -0
- package/dist/hooks/hand-back-core.d.ts.map +1 -0
- package/dist/hooks/hand-back-core.js +122 -0
- package/dist/hooks/hand-back-core.js.map +1 -0
- package/dist/hooks/hook-cli-command.d.ts +9 -0
- package/dist/hooks/hook-cli-command.d.ts.map +1 -0
- package/dist/hooks/hook-cli-command.js +46 -0
- package/dist/hooks/hook-cli-command.js.map +1 -0
- package/dist/hooks/hook-registry.d.ts +10 -0
- package/dist/hooks/hook-registry.d.ts.map +1 -0
- package/dist/hooks/hook-registry.js +24 -0
- package/dist/hooks/hook-registry.js.map +1 -0
- package/dist/hooks/hook-result-contract.d.ts +50 -0
- package/dist/hooks/hook-result-contract.d.ts.map +1 -0
- package/dist/hooks/hook-result-contract.js +80 -0
- package/dist/hooks/hook-result-contract.js.map +1 -0
- package/dist/hooks/hook-toggles.d.ts +10 -0
- package/dist/hooks/hook-toggles.d.ts.map +1 -0
- package/dist/hooks/hook-toggles.js +107 -0
- package/dist/hooks/hook-toggles.js.map +1 -0
- package/dist/hooks/pre-tool-guard-hook.d.ts +10 -0
- package/dist/hooks/pre-tool-guard-hook.d.ts.map +1 -0
- package/dist/hooks/pre-tool-guard-hook.js +105 -0
- package/dist/hooks/pre-tool-guard-hook.js.map +1 -0
- package/dist/hooks/session-start-unit-state-hook.d.ts +13 -0
- package/dist/hooks/session-start-unit-state-hook.d.ts.map +1 -0
- package/dist/hooks/session-start-unit-state-hook.js +57 -0
- package/dist/hooks/session-start-unit-state-hook.js.map +1 -0
- package/dist/hooks/stop-next-step-hook.d.ts +16 -0
- package/dist/hooks/stop-next-step-hook.d.ts.map +1 -0
- package/dist/hooks/stop-next-step-hook.js +42 -0
- package/dist/hooks/stop-next-step-hook.js.map +1 -0
- package/dist/hooks/sungen-project-root.d.ts +19 -0
- package/dist/hooks/sungen-project-root.d.ts.map +1 -0
- package/dist/hooks/sungen-project-root.js +130 -0
- package/dist/hooks/sungen-project-root.js.map +1 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.d.ts +15 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.js +106 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.js.map +1 -0
- package/dist/orchestrator/ai-skills/commands.d.ts +5 -1
- package/dist/orchestrator/ai-skills/commands.d.ts.map +1 -1
- package/dist/orchestrator/ai-skills/commands.js +16 -6
- package/dist/orchestrator/ai-skills/commands.js.map +1 -1
- package/dist/orchestrator/ai-skills/golden-skills.test.js +29 -0
- package/dist/orchestrator/ai-skills/golden-skills.test.js.map +1 -1
- package/dist/orchestrator/assets-drift.d.ts +5 -0
- package/dist/orchestrator/assets-drift.d.ts.map +1 -1
- package/dist/orchestrator/assets-drift.js +12 -3
- package/dist/orchestrator/assets-drift.js.map +1 -1
- package/dist/orchestrator/claude-hooks-install.d.ts +27 -0
- package/dist/orchestrator/claude-hooks-install.d.ts.map +1 -0
- package/dist/orchestrator/claude-hooks-install.js +203 -0
- package/dist/orchestrator/claude-hooks-install.js.map +1 -0
- package/dist/orchestrator/lockstep-version.d.ts +15 -5
- package/dist/orchestrator/lockstep-version.d.ts.map +1 -1
- package/dist/orchestrator/lockstep-version.js +30 -17
- package/dist/orchestrator/lockstep-version.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts +6 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +24 -0
- 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 +4 -2
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/orchestrator/templates/ai-src/commands/add-api.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
- package/dist/orchestrator/templates/ai-src/commands/create-test.md +14 -16
- package/dist/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/delivery.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/design.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/feedback.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/locale.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/review.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/run-test.md +14 -10
- package/dist/orchestrator/templates/ai-src/config/claude.md +20 -7
- package/dist/orchestrator/templates/ai-src/config/copilot.md +20 -7
- package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
- package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
- package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
- package/dist/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
- package/dist/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
- package/dist/utils/safe-yaml-parse.d.ts +8 -0
- package/dist/utils/safe-yaml-parse.d.ts.map +1 -0
- package/dist/utils/safe-yaml-parse.js +51 -0
- package/dist/utils/safe-yaml-parse.js.map +1 -0
- package/package.json +3 -3
- package/src/basis/anchor-grammar.ts +83 -0
- package/src/basis/anchor-hash.ts +27 -0
- package/src/basis/bm51-tables.ts +65 -0
- package/src/basis/extract-spec-anchors.ts +95 -0
- package/src/basis/migration-sentinel.ts +175 -0
- package/src/basis/spec-frontmatter.ts +68 -0
- package/src/basis/spec-sections.ts +35 -0
- package/src/basis/test-basis-schema.ts +81 -0
- package/src/capabilities/discover.ts +15 -2
- package/src/capabilities/registry.ts +16 -0
- package/src/cli/commands/audit.ts +10 -5
- package/src/cli/commands/capability.ts +4 -2
- package/src/cli/commands/contract-derive-command.ts +61 -0
- package/src/cli/commands/contract.ts +130 -0
- package/src/cli/commands/defect.ts +49 -0
- package/src/cli/commands/delivery.ts +92 -15
- package/src/cli/commands/generate.ts +3 -1
- package/src/cli/commands/journey.ts +41 -16
- package/src/cli/commands/next.ts +64 -10
- package/src/cli/commands/triage.ts +57 -0
- package/src/cli/commands/update.ts +35 -8
- package/src/cli/index.ts +24 -30
- package/src/cli/project-sungen-invocation.ts +39 -0
- package/src/contract/approve-contract.ts +94 -0
- package/src/contract/assertion-matcher-vocabulary.ts +93 -0
- package/src/contract/build-contract-verdict.ts +108 -0
- package/src/contract/build-trace-conformance.ts +100 -0
- package/src/contract/classify-contract-change.ts +92 -0
- package/src/contract/classify-contract-unit.ts +47 -0
- package/src/contract/classify-trace-conformance.ts +116 -0
- package/src/contract/contract-git.ts +106 -0
- package/src/contract/contract-hash.ts +34 -0
- package/src/contract/contract-report-file.ts +25 -0
- package/src/contract/contract-schema.ts +137 -0
- package/src/contract/contract-units.ts +52 -0
- package/src/contract/contracts-lock-file.ts +97 -0
- package/src/contract/data-normalize.ts +66 -0
- package/src/contract/derive-free-feature.ts +120 -0
- package/src/contract/field-semantic-redaction.ts +80 -0
- package/src/contract/free-feature-blocks.ts +56 -0
- package/src/contract/lock-secret-guard.ts +95 -0
- package/src/contract/lock-vs-git-head.ts +38 -0
- package/src/contract/normalize-contract-step.ts +74 -0
- package/src/contract/normalize-feature-steps.ts +93 -0
- package/src/contract/oracle-strength.ts +80 -0
- package/src/contract/project-contract-blockers.ts +36 -0
- package/src/contract/record-contract-approval.ts +70 -0
- package/src/contract/render-free-gherkin.ts +113 -0
- package/src/contract/render-trace-sentence.ts +98 -0
- package/src/contract/render-trace-target.ts +68 -0
- package/src/contract/resolve-unit-trace-identities.ts +35 -0
- package/src/contract/trace/collect-trace-evidence.ts +109 -0
- package/src/contract/trace/identity-cache.ts +61 -0
- package/src/contract/trace/select-final-attempt.ts +70 -0
- package/src/contract/trace/snapshot-html-renderer.ts +136 -0
- package/src/contract/trace/snapshot-resolver.ts +66 -0
- package/src/contract/trace/snapshot-store.ts +151 -0
- package/src/contract/trace/target-identity.ts +104 -0
- package/src/contract/trace/test-step-join.ts +104 -0
- package/src/contract/trace/trace-binding.ts +56 -0
- package/src/contract/trace/trace-file-reader.ts +133 -0
- package/src/contract/trace/trace-fingerprint.ts +68 -0
- package/src/contract/trace/trace-identity-resolution.ts +74 -0
- package/src/contract/trace/trace-run-record.ts +80 -0
- package/src/contract/trace/trace-steps.ts +88 -0
- package/src/contract/trace/trace-zip-limits.ts +77 -0
- package/src/contract/trace/trace-zip-reader.ts +127 -0
- package/src/contract/verify-approval-decisions.ts +60 -0
- package/src/decisions/append-decision.ts +35 -0
- package/src/decisions/confirmed-decision-commands.ts +149 -0
- package/src/decisions/decision-file.ts +93 -0
- package/src/decisions/decision-identity.ts +73 -0
- package/src/decisions/decision-integrity-check.ts +61 -0
- package/src/decisions/decision-schema.ts +76 -0
- package/src/decisions/decision-source.ts +14 -0
- package/src/decisions/exclusive-file-create.ts +42 -0
- package/src/decisions/git-head-trust.ts +32 -0
- package/src/decisions/human-confirmation.ts +119 -0
- package/src/decisions/legacy-waiver-migration.ts +135 -0
- package/src/decisions/read-decisions.ts +61 -0
- package/src/decisions/viewpoint-baseline-adapter.ts +74 -0
- package/src/decisions/waiver-decisions.ts +56 -0
- package/src/exporters/csv-exporter.ts +5 -1
- package/src/exporters/feature-parser.ts +12 -0
- package/src/exporters/matrix/build.ts +62 -18
- package/src/exporters/matrix/carry-manual-results.ts +70 -7
- package/src/exporters/matrix/export.ts +17 -2
- package/src/exporters/matrix/gates.ts +62 -129
- package/src/exporters/matrix/render-csv.ts +4 -1
- package/src/exporters/matrix/render-gate-overrides-sheet.ts +50 -0
- package/src/exporters/matrix/render-xlsx.ts +6 -0
- package/src/exporters/matrix/types.ts +9 -1
- package/src/exporters/matrix/xlsx-cells.ts +1 -1
- package/src/exporters/playwright-report-parser.ts +1 -0
- package/src/exporters/scenario-merger.ts +2 -1
- package/src/exporters/types.ts +5 -0
- package/src/generators/test-generator/code-generator.ts +13 -0
- package/src/graph/evaluate-graph.ts +66 -0
- package/src/graph/locate-finding.ts +93 -0
- package/src/graph/node-decl.ts +72 -0
- package/src/graph/nodes/core-node-catalog.ts +15 -0
- package/src/graph/nodes/test-case-contract-nodes.ts +74 -0
- package/src/graph/nodes/test-case-nodes.ts +68 -0
- package/src/graph/nodes/unit-audit-nodes.ts +95 -0
- package/src/graph/nodes/unit-contract-node.ts +89 -0
- package/src/graph/nodes/unit-design-nodes.ts +89 -0
- package/src/graph/nodes/unit-execution-nodes.ts +77 -0
- package/src/graph/test-case-identity.ts +75 -0
- package/src/graph/test-case-results.ts +90 -0
- package/src/graph/test-case-satisfied.ts +55 -0
- package/src/graph/test-case-state-shape.ts +62 -0
- package/src/graph/test-case-states.ts +84 -0
- package/src/graph/unit-artifact-probes.ts +77 -0
- package/src/graph/unit-state-facts.ts +112 -0
- package/src/harness/audit.ts +46 -11
- package/src/harness/catalog/gate-rules.yaml +647 -0
- package/src/harness/counted-assertions.ts +33 -0
- package/src/harness/defect-draft.ts +115 -0
- package/src/harness/defects.ts +94 -0
- package/src/harness/gates/audit-gate-terms.ts +80 -0
- package/src/harness/gates/audit-gate-verdict.ts +78 -0
- package/src/harness/gates/audit-input-hash.ts +55 -0
- package/src/harness/gates/audit-report-verification.ts +201 -0
- package/src/harness/gates/decisions-hash.ts +42 -0
- package/src/harness/gates/delivery-checklist.ts +120 -0
- package/src/harness/gates/delivery-decision-gate.ts +139 -0
- package/src/harness/gates/delivery-decision-step.ts +89 -0
- package/src/harness/gates/gate-override-report.ts +114 -0
- package/src/harness/gates/gate-override-scope.ts +66 -0
- package/src/harness/gates/gate-override-validation.ts +75 -0
- package/src/harness/gates/gate-rule-catalog.ts +82 -0
- package/src/harness/gates/gate-terms.ts +59 -0
- package/src/harness/gates/in-run-decision-check.ts +99 -0
- package/src/harness/gates/journey-gate-inputs.ts +89 -0
- package/src/harness/gates/migrated-waiver-review.ts +68 -0
- package/src/harness/gates/resolve-rule.ts +94 -0
- package/src/harness/gates/unit-gate-overrides.ts +99 -0
- package/src/harness/journey.ts +215 -38
- package/src/harness/manifest.ts +69 -45
- package/src/harness/next-step.ts +60 -170
- package/src/harness/parse.ts +40 -13
- package/src/harness/provenance.ts +99 -11
- package/src/harness/script-check.ts +27 -6
- package/src/harness/sensors.ts +73 -47
- 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/viewpoint-ledger.ts +2 -2
- package/src/hooks/bash-write-targets.ts +109 -0
- package/src/hooks/claude-hook-entry.ts +85 -0
- package/src/hooks/claude-transcript-turn.ts +96 -0
- package/src/hooks/guard-delivery-contract-rule.ts +110 -0
- package/src/hooks/guard-protected-paths.ts +71 -0
- package/src/hooks/guard-rules.ts +98 -0
- package/src/hooks/guard-tty-spoof-rule.ts +31 -0
- package/src/hooks/hand-back-core.ts +112 -0
- package/src/hooks/hook-cli-command.ts +17 -0
- package/src/hooks/hook-registry.ts +24 -0
- package/src/hooks/hook-result-contract.ts +114 -0
- package/src/hooks/hook-toggles.ts +66 -0
- package/src/hooks/pre-tool-guard-hook.ts +67 -0
- package/src/hooks/session-start-unit-state-hook.ts +56 -0
- package/src/hooks/stop-next-step-hook.ts +37 -0
- package/src/hooks/sungen-project-root.ts +80 -0
- package/src/orchestrator/ai-skills/command-partial-includes.ts +72 -0
- package/src/orchestrator/ai-skills/commands.ts +22 -8
- package/src/orchestrator/ai-skills/golden-skills.test.ts +23 -0
- package/src/orchestrator/assets-drift.ts +12 -5
- package/src/orchestrator/claude-hooks-install.ts +168 -0
- package/src/orchestrator/lockstep-version.ts +28 -15
- package/src/orchestrator/project-initializer.ts +22 -0
- package/src/orchestrator/screen-manager.ts +3 -1
- package/src/orchestrator/templates/ai-src/commands/add-api.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
- package/src/orchestrator/templates/ai-src/commands/create-test.md +14 -16
- package/src/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/delivery.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/design.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/feedback.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/locale.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/review.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/run-test.md +14 -10
- package/src/orchestrator/templates/ai-src/config/claude.md +20 -7
- package/src/orchestrator/templates/ai-src/config/copilot.md +20 -7
- package/src/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
- package/src/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
- package/src/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
- package/src/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
- package/src/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
- package/src/utils/safe-yaml-parse.ts +44 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design-stage unit nodes — rows 1–6 of the OES-10.2 parity table, in the order and with the exact
|
|
3
|
+
* words `deriveSteps` used (frozen in tests/graph/fixtures/legacy-derive-steps.ts).
|
|
4
|
+
*
|
|
5
|
+
* 1 unit.no-source no spec and no viewpoint → blocked; cuts BEFORE even `sungen update`
|
|
6
|
+
* 2 unit.assets-drift AI assets from another build → `sungen update` (first, it voids the rest)
|
|
7
|
+
* 3 unit.viewpoint-missing no test-viewpoint.md → blocked, does not cut
|
|
8
|
+
* 4 unit.flow-contract a flow without flow-contract.yaml → blocked, cuts
|
|
9
|
+
* 5 unit.no-scenarios zero scenarios → create-test, cuts
|
|
10
|
+
* 6 unit.flow-inventory a flow contract without `flows:` → add it, re-audit
|
|
11
|
+
*/
|
|
12
|
+
import { ALL_KINDS, UnitNodeDecl, unitKindDir } from '../node-decl';
|
|
13
|
+
import { updateChannelFlag } from '../../cli/project-sungen-invocation';
|
|
14
|
+
|
|
15
|
+
const design = (unit: string): string => `/sungen:create-test ${unit}`;
|
|
16
|
+
|
|
17
|
+
export const UNIT_DESIGN_NODES: readonly UnitNodeDecl[] = [
|
|
18
|
+
{
|
|
19
|
+
id: 'unit.no-source', title: 'Write a source to generate from', actor: 'human', granularity: 'unit',
|
|
20
|
+
appliesTo: ALL_KINDS, requires: [], blocking: true, rank: 10, gates: [], produces: ['requirements/spec.md'],
|
|
21
|
+
active: () => true,
|
|
22
|
+
satisfied: (s) => s.hasSpec || s.hasViewpoint,
|
|
23
|
+
step: (s) => ({
|
|
24
|
+
kind: 'blocked',
|
|
25
|
+
command: `write qa/${unitKindDir(s.kind)}/${s.unit}/requirements/spec.md`,
|
|
26
|
+
because: 'the unit has neither a spec nor a test-viewpoint, so there is nothing to generate FROM — generation without a source invents behaviour',
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
// Stale AI assets come FIRST: a HARD RULE added to `create-test` reaches nobody until `sungen update`
|
|
31
|
+
// runs, and upgrading the package alone does not refresh them (#620).
|
|
32
|
+
id: 'unit.assets-drift', title: 'Refresh the AI commands and skills', actor: 'ai', granularity: 'unit',
|
|
33
|
+
appliesTo: ALL_KINDS, requires: ['unit.no-source'], blocking: false, rank: 20, gates: [], produces: ['.claude/', '.github/', '.agents/'],
|
|
34
|
+
active: () => true,
|
|
35
|
+
satisfied: (s) => !s.assetsDrift,
|
|
36
|
+
step: (s) => ({
|
|
37
|
+
kind: 'do',
|
|
38
|
+
command: `sungen update${updateChannelFlag(s.assetsDrift!.runningVersion)}`, // keep the channel (#939)
|
|
39
|
+
because: `this project's AI commands/skills were written by sungen ${s.assetsDrift!.recordedVersion} and you are running ${s.assetsDrift!.runningVersion} — upgrading the package does NOT refresh them, so any rule added since ${s.assetsDrift!.recordedVersion} is not in effect for the next run`,
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
// The yardstick `atomicLedger` and `traceability` are measured against; it can go missing from a
|
|
44
|
+
// unit that already HAS a spec, which unit.no-source never sees.
|
|
45
|
+
id: 'unit.viewpoint-missing', title: 'Restore the test viewpoint', actor: 'human', granularity: 'unit',
|
|
46
|
+
appliesTo: ALL_KINDS, requires: ['unit.no-source'], blocking: false, rank: 30, gates: [], produces: ['requirements/test-viewpoint.md'],
|
|
47
|
+
active: () => true,
|
|
48
|
+
satisfied: (s) => s.hasViewpoint,
|
|
49
|
+
step: (s) => ({
|
|
50
|
+
kind: 'blocked',
|
|
51
|
+
command: s.kind === 'flow'
|
|
52
|
+
? `sungen add-flow --flow ${s.unit} --path <start-url> # repairs the missing scaffold; never overwrites`
|
|
53
|
+
: `write qa/screens/${s.unit}/requirements/test-viewpoint.md`,
|
|
54
|
+
because: 'requirements/test-viewpoint.md is missing — it is the yardstick `atomicLedger` and `traceability` are measured against, and four sensors read it, so the audit reports VIEWPOINT-MISSING and those axes are excluded. A flow contract does not substitute: it declares the use case, the viewpoint declares the claims',
|
|
55
|
+
}),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'unit.flow-contract', title: 'Author the flow contract', actor: 'human', granularity: 'unit',
|
|
59
|
+
appliesTo: ['flow'], requires: ['unit.no-source'], blocking: true, rank: 40, gates: [], produces: ['requirements/flow-contract.yaml'],
|
|
60
|
+
active: () => true,
|
|
61
|
+
satisfied: (s) => s.hasContract,
|
|
62
|
+
step: (s) => ({
|
|
63
|
+
kind: 'blocked',
|
|
64
|
+
command: `author requirements/flow-contract.yaml, then ${design(s.unit)}`,
|
|
65
|
+
because: 'a flow with no contract is scored as a generic screen against page-type themes a journey cannot have (FLOW-CONTRACT-MISSING)',
|
|
66
|
+
}),
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'unit.no-scenarios', title: 'Generate the scenarios', actor: 'ai', granularity: 'unit',
|
|
70
|
+
appliesTo: ALL_KINDS, requires: ['unit.no-source', 'unit.flow-contract'], blocking: true, rank: 50,
|
|
71
|
+
gates: ['journey.phase-create'], produces: ['features/<unit>.feature'],
|
|
72
|
+
active: () => true,
|
|
73
|
+
satisfied: (s) => s.scenarioCount !== 0,
|
|
74
|
+
step: (s) => ({ kind: 'do', command: design(s.unit), because: 'no scenarios exist yet' }),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
// Without the inventory, coverage is per PHASE, and a phase counts as covered once one scenario
|
|
78
|
+
// carries it — so the number cannot show a missing flow.
|
|
79
|
+
id: 'unit.flow-inventory', title: 'Declare the flow inventory', actor: 'ai', granularity: 'unit',
|
|
80
|
+
appliesTo: ['flow'], requires: ['unit.no-scenarios'], blocking: false, rank: 60, gates: [], produces: ['requirements/flow-contract.yaml'],
|
|
81
|
+
active: () => true,
|
|
82
|
+
satisfied: (s) => s.hasFlowInventory,
|
|
83
|
+
step: (s) => ({
|
|
84
|
+
kind: 'do',
|
|
85
|
+
command: `add \`flows:\` to requirements/flow-contract.yaml, then sungen audit --screen ${s.unit}`,
|
|
86
|
+
because: 'without the inventory, coverage is measured per PHASE — and a phase counts as covered as soon as one scenario carries it, so the number cannot tell you a flow is missing',
|
|
87
|
+
}),
|
|
88
|
+
},
|
|
89
|
+
];
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution-stage unit nodes — rows 11–15 (+13b from phase 01) of the OES-10.2 parity table, with the
|
|
3
|
+
* exact words of the frozen oracle.
|
|
4
|
+
*
|
|
5
|
+
* 11 unit.selectors non-api, no selectors or a placeholder file → run-test, cuts
|
|
6
|
+
* 12 unit.compile not compiled → `sungen generate`, cuts
|
|
7
|
+
* 13 unit.run never run → run-test, cuts
|
|
8
|
+
* 13b unit.triage results with failures → `sungen triage`, before delivery, does not cut —
|
|
9
|
+
* with test-case states it keeps only the reds no case accounts for; tc.triage
|
|
10
|
+
* takes the rest (phase 05)
|
|
11
|
+
* 14 unit.deliver no deliverable → delivery
|
|
12
|
+
* 15 unit.extend always → optional create-test (the end of the path)
|
|
13
|
+
*/
|
|
14
|
+
import { ALL_KINDS, UnitNodeDecl } from '../node-decl';
|
|
15
|
+
import { attributedReds, unattributedReds } from './test-case-nodes';
|
|
16
|
+
|
|
17
|
+
const TRIAGE_TAIL = 'classify each (known defect, test defect, environment, product candidate) before exporting or extending: an unexplained red in the deliverable is a finding nobody has judged';
|
|
18
|
+
|
|
19
|
+
export const UNIT_EXECUTION_NODES: readonly UnitNodeDecl[] = [
|
|
20
|
+
{
|
|
21
|
+
// A scaffolded selector file exists but resolves nothing; treating it as done makes a run look further along.
|
|
22
|
+
id: 'unit.selectors', title: 'Generate selectors from the live page', actor: 'ai', granularity: 'unit',
|
|
23
|
+
appliesTo: ['screen', 'flow'], requires: ['unit.gate-fail'], blocking: true, rank: 110, gates: [], produces: ['selectors/<unit>.yaml'],
|
|
24
|
+
active: () => true,
|
|
25
|
+
satisfied: (s) => s.hasSelectors && !s.selectorsArePlaceholder,
|
|
26
|
+
step: (s) => ({
|
|
27
|
+
kind: 'do',
|
|
28
|
+
command: `/sungen:run-test ${s.unit}`,
|
|
29
|
+
because: s.hasSelectors
|
|
30
|
+
? 'the selector file is still a placeholder, so nothing resolves against a live page'
|
|
31
|
+
: 'no selectors exist yet — run-test generates them from the live page, compiles and auto-fixes',
|
|
32
|
+
}),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'unit.compile', title: 'Compile the suite', actor: 'deterministic', granularity: 'unit',
|
|
36
|
+
appliesTo: ALL_KINDS, requires: ['unit.gate-fail', 'unit.selectors'], blocking: true, rank: 120, gates: [], produces: ['specs/generated/<unit>/'],
|
|
37
|
+
active: () => true,
|
|
38
|
+
satisfied: (s) => s.compiled,
|
|
39
|
+
step: (s) => ({ kind: 'do', command: `sungen generate --${s.kind === 'flow' ? 'flow' : 'screen'} ${s.unit}`, because: 'the suite has not been compiled to a spec yet' }),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'unit.run', title: 'Run the compiled suite', actor: 'ai', granularity: 'unit',
|
|
43
|
+
appliesTo: ALL_KINDS, requires: ['unit.compile'], blocking: true, rank: 130, gates: ['journey.phase-run'], produces: ['specs/generated/<unit>/<unit>-test-result.json'],
|
|
44
|
+
active: () => true,
|
|
45
|
+
satisfied: (s) => s.hasResults,
|
|
46
|
+
step: (s) => ({ kind: 'do', command: `/sungen:run-test ${s.unit}`, because: 'the compiled spec has never been run, so every case is Pending' }),
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
// Reds are classified before they are exported or built on; the steps after it still follow.
|
|
50
|
+
id: 'unit.triage', title: 'Classify the failed scenarios', actor: 'deterministic', granularity: 'unit',
|
|
51
|
+
appliesTo: ALL_KINDS, requires: ['unit.run'], blocking: false, rank: 135, gates: [], produces: ['.sungen/triage/<unit>.json'],
|
|
52
|
+
active: () => true,
|
|
53
|
+
satisfied: (s) => !(unattributedReds(s) > 0),
|
|
54
|
+
step: (s) => ({
|
|
55
|
+
kind: 'do',
|
|
56
|
+
command: `sungen triage --${s.kind === 'api' ? 'api' : 'screen'} ${s.unit}`,
|
|
57
|
+
because: attributedReds(s) > 0
|
|
58
|
+
? `${unattributedReds(s)} failed result(s) in the latest run match no test case of the .feature (a renamed scenario, an @cases row or a title the .feature does not show) — ${TRIAGE_TAIL}`
|
|
59
|
+
: `${s.failedCount} scenario(s) failed in the latest run — ${TRIAGE_TAIL}`,
|
|
60
|
+
}),
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 'unit.deliver', title: 'Export the deliverable', actor: 'ai', granularity: 'unit',
|
|
64
|
+
appliesTo: ALL_KINDS, requires: ['unit.run'], blocking: false, rank: 140, gates: ['journey.phase-deliver', 'decision.in-run'],
|
|
65
|
+
produces: ['qa/deliverables/<unit>-testcases.xlsx'],
|
|
66
|
+
active: () => true,
|
|
67
|
+
satisfied: (s) => s.hasDeliverable,
|
|
68
|
+
step: (s) => ({ kind: 'do', command: `/sungen:delivery ${s.unit}`, because: 'results exist but have not been exported to the Test Case & Coverage Matrix' }),
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'unit.extend', title: 'Extend coverage', actor: 'ai', granularity: 'unit',
|
|
72
|
+
appliesTo: ALL_KINDS, requires: ['unit.run'], blocking: false, rank: 150, gates: [], produces: ['features/<unit>.feature'],
|
|
73
|
+
active: () => true,
|
|
74
|
+
satisfied: () => false,
|
|
75
|
+
step: (s) => ({ kind: 'optional', command: `/sungen:create-test ${s.unit}`, because: 'extend coverage — the next tier, or the flows the inventory still lists as pending' }),
|
|
76
|
+
},
|
|
77
|
+
];
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which test cases a unit holds, read off its `.feature` files (DOS-11.1): one per runnable scenario
|
|
3
|
+
* — `@steps` bases, hooks and the scaffold sample are not test cases (as in delivery).
|
|
4
|
+
*
|
|
5
|
+
* id the scenario's VP-id (the exporters' format-tolerant SCENARIO_ID); without one,
|
|
6
|
+
* `T-<hash8>` of file + title, flagged `unstableId` (a rename changes it)
|
|
7
|
+
* lines the scenario block, its tag lines included, up to the line before the next block
|
|
8
|
+
* mocked verified against a declared mock (`@mock` / `@network`, or a mock step) — Pass (Mocked)
|
|
9
|
+
*/
|
|
10
|
+
import { createHash } from 'crypto';
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import { isHookScenario, isSampleScaffoldScenario, isStepsBaseScenario, parseFeatureMetadata, splitVpAndName } from '../exporters/feature-parser';
|
|
14
|
+
import { featureFilesFor } from '../harness/unit-paths';
|
|
15
|
+
|
|
16
|
+
export interface FeatureCase {
|
|
17
|
+
id: string;
|
|
18
|
+
unstableId?: true;
|
|
19
|
+
title: string;
|
|
20
|
+
absFile: string;
|
|
21
|
+
/** The feature's basename — result files are named after it. */
|
|
22
|
+
featureBase: string;
|
|
23
|
+
lines: [number, number];
|
|
24
|
+
tags: string[];
|
|
25
|
+
mocked: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const SCENARIO_LINE = /^\s*Scenario(?: Outline)?:\s*(.*?)\s*$/;
|
|
29
|
+
const ENDS_BLOCK = /^\s*(?:Rule|Background):/;
|
|
30
|
+
/** Blank lines and the next block's section marker are not part of a scenario. */
|
|
31
|
+
const TRAILER = /^\s*(?:#\s*-{2,}\s*Section:.*)?$/i;
|
|
32
|
+
/** Literal twin of the mock grammar (exporters/matrix/build.ts detectMocked), without loading drivers. */
|
|
33
|
+
const MOCK_TAGS = ['@mock', '@network'];
|
|
34
|
+
const MOCK_STEP = /\[[^\]]+\]\s+mock\s+(?:is\s+active|called\s+(?:\{\{[^}]+\}\}|\d+)\s+times?)\b/i;
|
|
35
|
+
|
|
36
|
+
/** 1-based [first, last] line of every Scenario block, in file order. */
|
|
37
|
+
function scenarioBlocks(lines: string[]): Array<{ title: string; range: [number, number] }> {
|
|
38
|
+
const starts: Array<{ title: string; first: number; at: number }> = [];
|
|
39
|
+
lines.forEach((line, i) => {
|
|
40
|
+
const m = line.match(SCENARIO_LINE);
|
|
41
|
+
if (!m) return;
|
|
42
|
+
let first = i;
|
|
43
|
+
while (first > 0 && /^\s*@/.test(lines[first - 1])) first--;
|
|
44
|
+
starts.push({ title: m[1], first, at: i });
|
|
45
|
+
});
|
|
46
|
+
return starts.map((b, k) => {
|
|
47
|
+
let end = k + 1 < starts.length ? starts[k + 1].first : lines.length; // exclusive
|
|
48
|
+
for (let j = b.at + 1; j < end; j++) if (ENDS_BLOCK.test(lines[j])) { end = j; break; }
|
|
49
|
+
while (end - 1 > b.at && TRAILER.test(lines[end - 1])) end--;
|
|
50
|
+
return { title: b.title, range: [b.first + 1, end] as [number, number] };
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function featureCases(unitDir: string, unit: string): FeatureCase[] {
|
|
55
|
+
const out: FeatureCase[] = [];
|
|
56
|
+
for (const absFile of featureFilesFor(unitDir, unit).filter((f) => fs.existsSync(f))) {
|
|
57
|
+
const meta = parseFeatureMetadata(absFile);
|
|
58
|
+
const blocks = scenarioBlocks(fs.readFileSync(absFile, 'utf8').split(/\r?\n/));
|
|
59
|
+
const used = new Set<number>();
|
|
60
|
+
for (const sc of meta.scenarios) {
|
|
61
|
+
const at = blocks.findIndex((b, i) => !used.has(i) && b.title === sc.name);
|
|
62
|
+
if (at >= 0) used.add(at);
|
|
63
|
+
if (isStepsBaseScenario(sc) || isHookScenario(sc) || isSampleScaffoldScenario(sc)) continue;
|
|
64
|
+
const vpId = splitVpAndName(sc.name).vpId;
|
|
65
|
+
const rel = path.basename(absFile);
|
|
66
|
+
const id = vpId ?? `T-${createHash('sha1').update(`${rel}\n${sc.name}`).digest('hex').slice(0, 8)}`;
|
|
67
|
+
out.push({
|
|
68
|
+
id, ...(vpId ? {} : { unstableId: true as const }), title: sc.name, absFile, featureBase: path.basename(absFile, '.feature'),
|
|
69
|
+
lines: at >= 0 ? blocks[at].range : [1, 1], tags: sc.tags,
|
|
70
|
+
mocked: sc.tags.some((t) => MOCK_TAGS.some((m) => t === m || t.startsWith(`${m}:`))) || sc.orderedSteps.some((s) => MOCK_STEP.test(s.text)),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What has happened to each test case: its result, whether that result still describes the
|
|
3
|
+
* scenario, and the triage verdict on it — all read off files that already exist (DOS-11.1).
|
|
4
|
+
*
|
|
5
|
+
* result final attempt across every result file of its feature (`<base>-test-result[.<os>][.<env>].json`)
|
|
6
|
+
* and every `@cases` row (`<title> — <label>`): any red → failed; else any pass → passed
|
|
7
|
+
* stale the run manifest (`sungen changed`) selects the scenario: its steps/tags, a selector or a
|
|
8
|
+
* test-data key it uses, or a project input changed since the recorded run
|
|
9
|
+
* triage the rows of `.sungen/triage/<unit>.json` for the case, only when that triage is not
|
|
10
|
+
* older than the case's result files (a re-run voids it)
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { loadPlaywrightReport } from '../exporters/playwright-report-parser';
|
|
15
|
+
import type { PlaywrightResult } from '../exporters/types';
|
|
16
|
+
import { buildRunManifest, readRunManifest, selectChanged } from '../harness/run-manifest';
|
|
17
|
+
import { readTriageReport } from '../harness/triage-unit';
|
|
18
|
+
import type { TriageClass } from '../harness/triage';
|
|
19
|
+
import type { FeatureCase } from './test-case-identity';
|
|
20
|
+
import type { TestCaseResult, TestCaseState } from './test-case-state-shape';
|
|
21
|
+
import { generatedDirs, RESULT_FILE } from './unit-artifact-probes';
|
|
22
|
+
|
|
23
|
+
const RED = new Set<PlaywrightResult['status']>(['failed', 'timedOut', 'interrupted']);
|
|
24
|
+
/** The class a case shows when its rows disagree: what needs a human first. */
|
|
25
|
+
const TRIAGE_PRECEDENCE: TriageClass[] = ['product-candidate', 'unclassified', 'test-defect', 'environment', 'known-defect', 'blocked-capability', 'flaky'];
|
|
26
|
+
|
|
27
|
+
export interface CaseOutcome { result: TestCaseResult; failedResults: number; resultFiles: string[]; stale?: string; triage?: TestCaseState['triage'] }
|
|
28
|
+
|
|
29
|
+
const ownsTitle = (key: string, title: string): boolean => key === title || key.endsWith(` > ${title}`)
|
|
30
|
+
|| key.startsWith(`${title} — `) || key.includes(` > ${title} — `);
|
|
31
|
+
const rowOwns = (scenario: string, title: string): boolean => scenario === title || scenario.startsWith(`${title} — `);
|
|
32
|
+
const mtime = (f: string): number => { try { return fs.statSync(f).mtimeMs; } catch { return 0; } };
|
|
33
|
+
|
|
34
|
+
/** Every result file of each feature, with its parsed report (read once per file). */
|
|
35
|
+
function resultsByFeature(projectRoot: string, unit: string, unitId: string): Map<string, Array<{ file: string; report: Map<string, PlaywrightResult> }>> {
|
|
36
|
+
const dirs = [...new Set([...generatedDirs(projectRoot, unit), path.join(projectRoot, 'specs', 'generated', unitId)])];
|
|
37
|
+
const out = new Map<string, Array<{ file: string; report: Map<string, PlaywrightResult> }>>();
|
|
38
|
+
for (const d of dirs) {
|
|
39
|
+
let names: string[] = [];
|
|
40
|
+
try { names = fs.readdirSync(d).filter((f) => RESULT_FILE.test(f)).sort(); } catch { continue; }
|
|
41
|
+
for (const name of names) {
|
|
42
|
+
const report = loadPlaywrightReport(path.join(d, name));
|
|
43
|
+
if (!report) continue; // unreadable = unknown, never red
|
|
44
|
+
const base = name.replace(RESULT_FILE, '');
|
|
45
|
+
out.set(base, [...(out.get(base) ?? []), { file: path.join(d, name), report }]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Scenarios `sungen changed` would re-run. No baseline, or one that cannot be read, claims nothing. */
|
|
52
|
+
function staleReasons(projectRoot: string, unitDir: string, unit: string): Record<string, string> {
|
|
53
|
+
const before = readRunManifest(projectRoot, unit);
|
|
54
|
+
if (!before || typeof before.scenarios !== 'object' || !before.selectorKeys || !before.dataKeys) return {};
|
|
55
|
+
try { return selectChanged(before, buildRunManifest(projectRoot, unitDir, unit)).reasons; } catch { return {}; }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The triage rows, shape-checked: the report is a file anyone can edit. */
|
|
59
|
+
function triageRows(projectRoot: string, unitId: string): { at: number; rows: Array<{ scenario: string; class: TriageClass; ruleId: string }> } {
|
|
60
|
+
const report = readTriageReport(projectRoot, unitId);
|
|
61
|
+
const rows = Array.isArray(report?.rows)
|
|
62
|
+
? report!.rows.filter((r) => r && typeof r.scenario === 'string' && TRIAGE_PRECEDENCE.includes(r.class)) : [];
|
|
63
|
+
return { at: report && typeof report.generatedAt === 'string' ? Date.parse(report.generatedAt) : NaN, rows };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function caseOutcomes(projectRoot: string, unitDir: string, unit: string, unitId: string, cases: FeatureCase[]): CaseOutcome[] {
|
|
67
|
+
const byFeature = resultsByFeature(projectRoot, unit, unitId);
|
|
68
|
+
const stale = staleReasons(projectRoot, unitDir, unit);
|
|
69
|
+
const triage = triageRows(projectRoot, unitId);
|
|
70
|
+
return cases.map((c) => {
|
|
71
|
+
const statuses: PlaywrightResult['status'][] = [];
|
|
72
|
+
const files: string[] = [];
|
|
73
|
+
for (const { file, report } of byFeature.get(c.featureBase) ?? []) {
|
|
74
|
+
const mine = [...report.entries()].filter(([key]) => ownsTitle(key, c.title)).map(([, r]) => r.status);
|
|
75
|
+
if (mine.length) { statuses.push(...mine); files.push(file); }
|
|
76
|
+
}
|
|
77
|
+
const result: TestCaseResult = statuses.some((s) => RED.has(s)) ? 'failed'
|
|
78
|
+
: statuses.includes('passed') ? 'passed' : statuses.includes('skipped') ? 'skipped' : 'never-run';
|
|
79
|
+
const out: CaseOutcome = {
|
|
80
|
+
result, failedResults: statuses.filter((st) => RED.has(st)).length,
|
|
81
|
+
resultFiles: files.map((f) => path.relative(projectRoot, f).split(path.sep).join('/')),
|
|
82
|
+
};
|
|
83
|
+
if (result !== 'never-run' && stale[c.title]) out.stale = stale[c.title];
|
|
84
|
+
const current = !Number.isNaN(triage.at) && files.every((f) => mtime(f) <= triage.at);
|
|
85
|
+
const rows = current ? triage.rows.filter((r) => rowOwns(r.scenario, c.title)) : [];
|
|
86
|
+
const worst = TRIAGE_PRECEDENCE.find((cls) => rows.some((r) => r.class === cls));
|
|
87
|
+
if (worst) out.triage = { class: worst, ruleId: rows.find((r) => r.class === worst)!.ruleId };
|
|
88
|
+
return out;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When a test case generates work, and which (DOS-11.2).
|
|
3
|
+
*
|
|
4
|
+
* exempt — satisfied, no work: `@manual` (a human executes it), `@requires:<cap>` (waits on a
|
|
5
|
+
* capability the QA has not enabled), `@known-defect` (a recorded product defect),
|
|
6
|
+
* `@deferred:flow` (owned and automated by its flow — the contract excludes it too),
|
|
7
|
+
* triage `blocked-capability`. Any other `@deferred:*` is NOT exempt.
|
|
8
|
+
* trigger — what the case needs otherwise, first match wins:
|
|
9
|
+
* never run → run · result older than the scenario (run manifest) → rerun-stale ·
|
|
10
|
+
* red with no current triage, or left `unclassified` by it → triage (a classification
|
|
11
|
+
* is still owed) · triaged product-candidate → a QA decision
|
|
12
|
+
* A pass — Pass (Mocked) included — needs nothing. A red triaged test-defect / environment has been
|
|
13
|
+
* judged; the triage report and the deliverable carry it (no P0 node — a P1 follow-up).
|
|
14
|
+
*/
|
|
15
|
+
import type { TestCaseState } from './test-case-state-shape';
|
|
16
|
+
|
|
17
|
+
export type TestCaseExemption = 'manual' | 'requires' | 'known-defect' | 'deferred' | 'blocked-capability';
|
|
18
|
+
export type TestCaseNeed = 'run' | 'rerun-stale' | 'triage' | 'product-candidate';
|
|
19
|
+
|
|
20
|
+
const tagged = (tc: TestCaseState, tag: string): boolean => tc.tags.some((t) => t === tag || t.startsWith(`${tag}:`));
|
|
21
|
+
|
|
22
|
+
/** Why the case is satisfied regardless of its result, or null when it is not exempt. */
|
|
23
|
+
export function exemptionOf(tc: TestCaseState): TestCaseExemption | null {
|
|
24
|
+
if (tagged(tc, '@manual')) return 'manual';
|
|
25
|
+
if (tc.tags.some((t) => t.startsWith('@requires:'))) return 'requires';
|
|
26
|
+
if (tagged(tc, '@known-defect')) return 'known-defect';
|
|
27
|
+
if (tc.tags.some((t) => /^@deferred:flow$/i.test(t))) return 'deferred';
|
|
28
|
+
if (tc.triage?.class === 'blocked-capability') return 'blocked-capability';
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** What the case would need if it were not exempt. */
|
|
33
|
+
export function triggerOf(tc: TestCaseState): TestCaseNeed | null {
|
|
34
|
+
if (tc.result === 'never-run') return 'run';
|
|
35
|
+
if (tc.stale) return 'rerun-stale';
|
|
36
|
+
if (tc.result === 'failed') {
|
|
37
|
+
if (!tc.triage || tc.triage.class === 'unclassified') return 'triage';
|
|
38
|
+
if (tc.triage.class === 'product-candidate') return 'product-candidate';
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function testCaseNeed(tc: TestCaseState): TestCaseNeed | null {
|
|
44
|
+
return exemptionOf(tc) ? null : triggerOf(tc);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** One word for `--case`: why the case asks for nothing, or what it needs. */
|
|
48
|
+
export function testCaseStatusLabel(tc: TestCaseState): string {
|
|
49
|
+
const exempt = exemptionOf(tc);
|
|
50
|
+
if (exempt) return `satisfied (${exempt})`;
|
|
51
|
+
const need = triggerOf(tc);
|
|
52
|
+
if (need) return `needs ${need}`;
|
|
53
|
+
if (tc.result === 'passed') return tc.mocked ? 'satisfied (Pass (Mocked))' : 'satisfied (passed)';
|
|
54
|
+
return tc.triage ? `satisfied (triaged ${tc.triage.class})` : `satisfied (${tc.result})`;
|
|
55
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shape of one test case's state (DOS-11.1) — facts read off files that already exist, never a
|
|
3
|
+
* stored record. `testCaseStates()` (test-case-states.ts) builds it; `test-case-satisfied.ts` decides
|
|
4
|
+
* whether it generates work; the test-case nodes turn the unsatisfied ones into steps.
|
|
5
|
+
*/
|
|
6
|
+
import type { ScenarioClass } from '../contract/contract-schema';
|
|
7
|
+
import type { TriageClass } from '../harness/triage';
|
|
8
|
+
|
|
9
|
+
/** DOS-12.1 confidence labels: EXTRACTED 0.9–1.0 · INFERRED 0.5–0.89 · AMBIGUOUS < 0.5. */
|
|
10
|
+
export type ConfidenceLabel = 'EXTRACTED' | 'INFERRED' | 'AMBIGUOUS';
|
|
11
|
+
|
|
12
|
+
/** An audit finding pinned to the scenario it names, in the shared trace vocabulary (DOS-12.1). */
|
|
13
|
+
export interface LocatedFinding {
|
|
14
|
+
code: string;
|
|
15
|
+
text: string;
|
|
16
|
+
/** `repo@SHA:path#Lx-Ly` — SHA is `worktree` when git is absent or the file differs from HEAD. */
|
|
17
|
+
citation: string;
|
|
18
|
+
confidence: { label: ConfidenceLabel; score: number };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type TestCaseResult = 'passed' | 'failed' | 'skipped' | 'never-run';
|
|
22
|
+
|
|
23
|
+
/** The case in the contract verdict `sungen contract check` rebuilds (DOS-14.4–14.6) — attached on read. */
|
|
24
|
+
export interface TestCaseContract {
|
|
25
|
+
class: ScenarioClass;
|
|
26
|
+
/** Its first finding, as the check prints it. */
|
|
27
|
+
detail?: string;
|
|
28
|
+
/** A trace step acts on a target whose identity is only `low` — `contract check --trace` can resolve it. */
|
|
29
|
+
lowIdentity?: true;
|
|
30
|
+
/** Its lock entry is not what QA approved and committed (contract.lock-uncommitted). */
|
|
31
|
+
uncommitted?: true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface TestCaseState {
|
|
35
|
+
/** The scenario's VP-id; `T-<hash8>` of file + title when it carries none (`unstableId`). */
|
|
36
|
+
id: string;
|
|
37
|
+
unstableId?: true;
|
|
38
|
+
title: string;
|
|
39
|
+
/** Project-relative, `/`-separated path of the `.feature`. */
|
|
40
|
+
file: string;
|
|
41
|
+
/** 1-based first and last line of the scenario block (its tags included). */
|
|
42
|
+
lines: [number, number];
|
|
43
|
+
/** Feature and scenario tags. */
|
|
44
|
+
tags: string[];
|
|
45
|
+
/** Final-attempt outcome across every result file and variant: any red is `failed`. */
|
|
46
|
+
result: TestCaseResult;
|
|
47
|
+
/** Red final attempts this case accounts for — one per result file, variant and `@cases` row. */
|
|
48
|
+
failedResults?: number;
|
|
49
|
+
/** Verified against a declared mock — a pass is Pass (Mocked), not Pass (Real). */
|
|
50
|
+
mocked: boolean;
|
|
51
|
+
/** Result files that carry this case, project-relative. */
|
|
52
|
+
resultFiles: string[];
|
|
53
|
+
/** Set when the scenario changed after the run that produced its result (run manifest). */
|
|
54
|
+
stale?: string;
|
|
55
|
+
/** The current `sungen triage` row for a red case — absent when triage has not judged this result. */
|
|
56
|
+
triage?: { class: TriageClass; ruleId: string };
|
|
57
|
+
/** Spec anchors the case was generated from (manifest), and whether they moved since. */
|
|
58
|
+
anchors: Array<{ anchor: string; change: 'keep' | 'regenerate' | 'retire' | 'unknown' }>;
|
|
59
|
+
findings: LocatedFinding[];
|
|
60
|
+
/** Its class in the rebuilt contract verdict; absent outside the contract (@manual, no scenario id) or unread. */
|
|
61
|
+
contract?: TestCaseContract;
|
|
62
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `testCaseStates(projectRoot, unit)` — the state of every test case of a unit, a PURE function of
|
|
3
|
+
* files that already exist, evaluated whenever it is read (DOS-11.1, red-team #9): no state file, no
|
|
4
|
+
* facet registry, nothing written. A step interrupted yesterday is recomputed today, not remembered.
|
|
5
|
+
*
|
|
6
|
+
* identity .feature test-case-identity.ts
|
|
7
|
+
* outcome results · run manifest · triage test-case-results.ts
|
|
8
|
+
* anchors .sungen/manifest/<unit>.json — the spec anchors each scenario came from, and their drift
|
|
9
|
+
* findings the audit's findings, located on the case they name (locate-finding.ts, DOS-12.1)
|
|
10
|
+
*
|
|
11
|
+
* The audit's findings are taken only from a report that counts (verifyAuditReport): a stale or
|
|
12
|
+
* untrusted report locates nothing. A caller that already verified the report passes its findings.
|
|
13
|
+
*/
|
|
14
|
+
import * as fs from 'fs';
|
|
15
|
+
import * as path from 'path';
|
|
16
|
+
import { resolveUnitCandidates } from '../cli/resolve-unit';
|
|
17
|
+
import { auditCounts, verifyAuditReport } from '../harness/gates/audit-report-verification';
|
|
18
|
+
import { diffManifest, Manifest } from '../harness/manifest';
|
|
19
|
+
import { reportSlug } from '../harness/unit-paths';
|
|
20
|
+
import { gitCitationContext, locateFindings } from './locate-finding';
|
|
21
|
+
import { caseOutcomes } from './test-case-results';
|
|
22
|
+
import { featureCases } from './test-case-identity';
|
|
23
|
+
import type { TestCaseState } from './test-case-state-shape';
|
|
24
|
+
|
|
25
|
+
export interface TestCaseStateOptions {
|
|
26
|
+
/** The unit's directory, when the caller has resolved it already. */
|
|
27
|
+
unitDir?: string;
|
|
28
|
+
/** The findings of an audit report the caller verified; read through verifyAuditReport otherwise. */
|
|
29
|
+
auditFindings?: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type Anchor = TestCaseState['anchors'][number];
|
|
33
|
+
|
|
34
|
+
/** scenario title → its anchors, with the change `diffManifest` reports (unknown when it cannot say). */
|
|
35
|
+
function anchorsByScenario(projectRoot: string, unitDir: string, unit: string): Map<string, Anchor[]> {
|
|
36
|
+
const out = new Map<string, Anchor[]>();
|
|
37
|
+
let manifest: Manifest;
|
|
38
|
+
try {
|
|
39
|
+
manifest = JSON.parse(fs.readFileSync(path.join(projectRoot, '.sungen', 'manifest', `${reportSlug(unit)}.json`), 'utf8'));
|
|
40
|
+
} catch { return out; }
|
|
41
|
+
if (!manifest || !Array.isArray(manifest.entries)) return out;
|
|
42
|
+
let changes: Map<string, Anchor['change']> = new Map();
|
|
43
|
+
try {
|
|
44
|
+
changes = new Map(diffManifest(unitDir, unit, manifest).scenarios.map((s) => [`${s.scenario}\n${s.section}`, s.change]));
|
|
45
|
+
} catch { /* a pending migration or an unreadable spec — the drift is unknown */ }
|
|
46
|
+
for (const e of manifest.entries) {
|
|
47
|
+
if (!e || typeof e.scenario !== 'string' || typeof e.section !== 'string') continue;
|
|
48
|
+
out.set(e.scenario, [...(out.get(e.scenario) ?? []), { anchor: e.section, change: changes.get(`${e.scenario}\n${e.section}`) ?? 'unknown' }]);
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function verifiedFindings(projectRoot: string, unit: string): string[] {
|
|
54
|
+
const v = verifyAuditReport(projectRoot, unit);
|
|
55
|
+
const findings = auditCounts(v) ? v.report?.findings : undefined;
|
|
56
|
+
return Array.isArray(findings) ? findings.filter((f): f is string => typeof f === 'string') : [];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function testCaseStates(projectRoot: string, unit: string, opts: TestCaseStateOptions = {}): TestCaseState[] {
|
|
60
|
+
const found = resolveUnitCandidates(unit, projectRoot);
|
|
61
|
+
const unitDir = opts.unitDir ?? (found.length === 1 ? found[0].dir : undefined);
|
|
62
|
+
if (!unitDir || !fs.existsSync(unitDir)) return [];
|
|
63
|
+
const unitId = found.find((f) => f.dir === unitDir)?.unitId ?? unit;
|
|
64
|
+
const cases = featureCases(unitDir, unit);
|
|
65
|
+
if (!cases.length) return [];
|
|
66
|
+
const outcomes = caseOutcomes(projectRoot, unitDir, unit, unitId, cases);
|
|
67
|
+
const anchors = anchorsByScenario(projectRoot, unitDir, unit);
|
|
68
|
+
const findings = opts.auditFindings ?? verifiedFindings(projectRoot, unit);
|
|
69
|
+
const located = findings.length
|
|
70
|
+
? locateFindings(findings, cases, gitCitationContext(projectRoot, [...new Set(cases.map((c) => c.absFile))]))
|
|
71
|
+
: new Map();
|
|
72
|
+
return cases.map((c, i) => ({
|
|
73
|
+
id: c.id,
|
|
74
|
+
...(c.unstableId ? { unstableId: true as const } : {}),
|
|
75
|
+
title: c.title,
|
|
76
|
+
file: path.relative(projectRoot, c.absFile).split(path.sep).join('/'),
|
|
77
|
+
lines: c.lines,
|
|
78
|
+
tags: c.tags,
|
|
79
|
+
mocked: c.mocked,
|
|
80
|
+
...outcomes[i],
|
|
81
|
+
anchors: anchors.get(c.title) ?? [],
|
|
82
|
+
findings: located.get(i) ?? [],
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a unit holds on disk, probed cheaply for `readUnitState` and `testCaseStates` (moved out of
|
|
3
|
+
* harness/next-step.ts unchanged). Every path here is legitimately absent at some point in a unit's
|
|
4
|
+
* life — the resolver exists to report exactly that — so nothing throws on a missing file.
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { parse as parseYaml } from 'yaml';
|
|
9
|
+
import { featureFilesFor } from '../harness/unit-paths';
|
|
10
|
+
import { readTextFile } from '../harness/read-text';
|
|
11
|
+
import { loadPlaywrightReport } from '../exporters/playwright-report-parser';
|
|
12
|
+
|
|
13
|
+
/** `<f>-test-result[.<os>][.<env>].json` — a mobile run writes the OS into the name, an env run the env (#868). */
|
|
14
|
+
export const RESULT_FILE = /-test-result(?:\.[^.]+)*\.json$/;
|
|
15
|
+
|
|
16
|
+
export const readIfExists = (p: string): string => (fs.existsSync(p) ? readTextFile(p) : '');
|
|
17
|
+
|
|
18
|
+
export function countScenarios(unitDir: string, unit: string): number {
|
|
19
|
+
let n = 0;
|
|
20
|
+
for (const f of featureFilesFor(unitDir, unit)) {
|
|
21
|
+
n += (readIfExists(f).match(/^\s*Scenario(?: Outline)?:/gm) ?? []).length;
|
|
22
|
+
}
|
|
23
|
+
return n;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Does the selector text resolve at least one element? A scaffold resolves none: the web one holds
|
|
28
|
+
* only the `page` route, the mobile one only header comments. Matching the WORD "placeholder" was
|
|
29
|
+
* wrong both ways (#868): it flagged a real file whose key names an input's placeholder text, and
|
|
30
|
+
* missed both scaffolds, which never contain it.
|
|
31
|
+
*/
|
|
32
|
+
export function hasResolvedSelector(selectorText: string): boolean {
|
|
33
|
+
let doc: unknown;
|
|
34
|
+
try { doc = parseYaml(selectorText); } catch { return selectorText.trim().length >= 40; }
|
|
35
|
+
if (!doc || typeof doc !== 'object') return false;
|
|
36
|
+
// A real cell, not a marker left to be filled in. Numbers count (an id or index can be numeric).
|
|
37
|
+
const real = (v: unknown): boolean => (typeof v === 'string' || typeof v === 'number')
|
|
38
|
+
&& String(v).trim() !== '' && !/^(?:todo|tbd|placeholder|replace me)$/i.test(String(v).trim());
|
|
39
|
+
return Object.values(doc as Record<string, unknown>).some((e) => {
|
|
40
|
+
if (!e || typeof e !== 'object') return false;
|
|
41
|
+
const { type, value, name, locator } = e as { type?: unknown; value?: unknown; name?: unknown; locator?: unknown };
|
|
42
|
+
// Every SelectorEntry shape: a CSS `locator`, or a non-page `type` with a value or a role name.
|
|
43
|
+
return real(locator) || (typeof type === 'string' && type !== 'page' && (real(value) || real(name)));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Where a unit's compiled spec and result files live. */
|
|
48
|
+
export function generatedDirs(projectRoot: string, unit: string): string[] {
|
|
49
|
+
return [
|
|
50
|
+
path.join(projectRoot, 'specs', 'generated', 'flows', unit),
|
|
51
|
+
path.join(projectRoot, 'specs', 'generated', unit),
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function isCompiled(projectRoot: string, unit: string): boolean {
|
|
56
|
+
return generatedDirs(projectRoot, unit).some((d) => {
|
|
57
|
+
try { return fs.readdirSync(d).some((f) => f.endsWith('.spec.ts')); } catch { return false; }
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function unitResultFiles(projectRoot: string, unit: string): string[] {
|
|
62
|
+
return generatedDirs(projectRoot, unit).flatMap((d) => {
|
|
63
|
+
try { return fs.readdirSync(d).filter((f) => RESULT_FILE.test(f)).map((f) => path.join(d, f)); } catch { return []; }
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Final attempts that failed across the result files. An unreadable report counts nothing: "unknown" is never red. */
|
|
68
|
+
export function countFailedResults(resultFiles: string[]): number {
|
|
69
|
+
return resultFiles.reduce((n, f) => n + [...(loadPlaywrightReport(f)?.values() ?? [])]
|
|
70
|
+
.filter((r) => r.status === 'failed' || r.status === 'timedOut' || r.status === 'interrupted').length, 0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function hasDeliverableFor(projectRoot: string, slug: string): boolean {
|
|
74
|
+
try {
|
|
75
|
+
return fs.readdirSync(path.join(projectRoot, 'qa', 'deliverables')).some((f) => f.startsWith(`${slug}-`));
|
|
76
|
+
} catch { return false; } // nothing exported yet
|
|
77
|
+
}
|