@sun-asterisk/sungen 3.2.34 → 3.3.0-alpha.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/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/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 +9 -4
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/capability.d.ts.map +1 -1
- package/dist/cli/commands/capability.js +6 -2
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/contract-derive-command.d.ts +10 -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 +87 -10
- 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 +41 -13
- 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 +64 -6
- 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/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 +30 -0
- package/dist/contract/derive-free-feature.d.ts.map +1 -0
- package/dist/contract/derive-free-feature.js +145 -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 +35 -0
- package/dist/contract/trace/trace-file-reader.d.ts.map +1 -0
- package/dist/contract/trace/trace-file-reader.js +155 -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 +27 -0
- package/dist/contract/trace/trace-run-record.d.ts.map +1 -0
- package/dist/contract/trace/trace-run-record.js +115 -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 +41 -0
- package/dist/contract/trace/trace-zip-limits.d.ts.map +1 -0
- package/dist/contract/trace/trace-zip-limits.js +48 -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 +30 -0
- package/dist/decisions/confirmed-decision-commands.d.ts.map +1 -0
- package/dist/decisions/confirmed-decision-commands.js +172 -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 +33 -0
- package/dist/decisions/human-confirmation.d.ts.map +1 -0
- package/dist/decisions/human-confirmation.js +155 -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/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 +21 -0
- package/dist/graph/evaluate-graph.d.ts.map +1 -0
- package/dist/graph/evaluate-graph.js +49 -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 +59 -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 +19 -0
- package/dist/graph/nodes/test-case-contract-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/test-case-contract-nodes.js +56 -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 +20 -0
- package/dist/graph/nodes/unit-contract-node.d.ts.map +1 -0
- package/dist/graph/nodes/unit-contract-node.js +81 -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 +90 -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 +32 -0
- package/dist/harness/gates/audit-report-verification.d.ts.map +1 -0
- package/dist/harness/gates/audit-report-verification.js +207 -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 +29 -0
- package/dist/harness/gates/delivery-decision-gate.d.ts.map +1 -0
- package/dist/harness/gates/delivery-decision-gate.js +91 -0
- package/dist/harness/gates/delivery-decision-gate.js.map +1 -0
- package/dist/harness/gates/delivery-decision-step.d.ts +16 -0
- package/dist/harness/gates/delivery-decision-step.d.ts.map +1 -0
- package/dist/harness/gates/delivery-decision-step.js +71 -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 +24 -1
- package/dist/harness/journey.d.ts.map +1 -1
- package/dist/harness/journey.js +114 -23
- 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/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 +106 -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 +37 -0
- package/dist/hooks/hand-back-core.d.ts.map +1 -0
- package/dist/hooks/hand-back-core.js +115 -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 +55 -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/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 +23 -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/registry.ts +16 -0
- package/src/cli/commands/audit.ts +9 -4
- package/src/cli/commands/capability.ts +4 -2
- package/src/cli/commands/contract-derive-command.ts +60 -0
- package/src/cli/commands/contract.ts +130 -0
- package/src/cli/commands/defect.ts +49 -0
- package/src/cli/commands/delivery.ts +85 -13
- package/src/cli/commands/generate.ts +3 -1
- package/src/cli/commands/journey.ts +39 -14
- package/src/cli/commands/next.ts +60 -8
- 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/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 +110 -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 +103 -0
- package/src/contract/trace/trace-binding.ts +56 -0
- package/src/contract/trace/trace-file-reader.ts +123 -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 +74 -0
- package/src/contract/trace/trace-steps.ts +88 -0
- package/src/contract/trace/trace-zip-limits.ts +73 -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 +128 -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 +114 -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/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 +62 -0
- package/src/graph/locate-finding.ts +93 -0
- package/src/graph/node-decl.ts +65 -0
- package/src/graph/nodes/core-node-catalog.ts +15 -0
- package/src/graph/nodes/test-case-contract-nodes.ts +69 -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 +82 -0
- package/src/graph/nodes/unit-design-nodes.ts +88 -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 +173 -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 +111 -0
- package/src/harness/gates/delivery-decision-step.ts +73 -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 +122 -27
- 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/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 +70 -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 +106 -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 +54 -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/claude-hooks-install.ts +168 -0
- package/src/orchestrator/lockstep-version.ts +28 -15
- package/src/orchestrator/project-initializer.ts +21 -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,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Waivers move from `.sungen/journey/<slug>.state.json` into the decision layer (DOS-13.5, red-team
|
|
3
|
+
* #2) — without laundering an agent-forged waiver into a hash-valid decision (review H1).
|
|
4
|
+
*
|
|
5
|
+
* The state file is agent-writable, so a legacy waiver is TRUSTED only when its record equals the
|
|
6
|
+
* one committed in git HEAD (a commit went through review; a local edit did not). Per obligation,
|
|
7
|
+
* with L = the legacy waiver and D = the decision in force:
|
|
8
|
+
* L same as D → nothing to do (same reason against the same evidence)
|
|
9
|
+
* L untrusted → not imported, not counted; needs-you says UNTRUSTED and how to confirm it
|
|
10
|
+
* L trusted, no D → import L (`where: migrated`, idempotent by content id)
|
|
11
|
+
* L trusted, newer than D → import L superseding D — an `at` in the future never counts as newer
|
|
12
|
+
* L trusted, not newer than D → D wins; the dual-write corrects the legacy file
|
|
13
|
+
* The import runs ONCE per unit: when nothing untrusted remains, a marker is written and from then on
|
|
14
|
+
* the legacy file is only a dual-write target (so the previous CLI still reads the waivers), never a source.
|
|
15
|
+
*
|
|
16
|
+
* plan is read-only, so the board is the same whether or not the writes succeed. commit writes under
|
|
17
|
+
* the write-ahead sentinel; only an unwritable checkout is tolerated silently — a conflict is raised.
|
|
18
|
+
*/
|
|
19
|
+
import * as fs from 'fs';
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import { withMigrationSentinel } from '../basis/migration-sentinel';
|
|
22
|
+
import { appendDecision, AppendResult } from './append-decision';
|
|
23
|
+
import { canonicalJson, computeDecisionId } from './decision-identity';
|
|
24
|
+
import { decisionsDirFor, unitDecisionScope } from './decision-file';
|
|
25
|
+
import { DecisionDraft } from './decision-schema';
|
|
26
|
+
import { gitUserName } from './decision-source';
|
|
27
|
+
import { committedJson } from './git-head-trust';
|
|
28
|
+
import { formatCommand } from './human-confirmation';
|
|
29
|
+
import { readDecisions } from './read-decisions';
|
|
30
|
+
import { asLegacyWaiver, effectiveWaiverEntries, isLegacyWaiver, LegacyWaiver, sameWaiver, waiverDraft } from './waiver-decisions';
|
|
31
|
+
|
|
32
|
+
export interface UntrustedWaiver { obligation: string; waiver: LegacyWaiver }
|
|
33
|
+
|
|
34
|
+
export interface WaiverSyncPlan {
|
|
35
|
+
scope: string | null;
|
|
36
|
+
/** obligation → waiver in force (legacy shape): what the board counts. */
|
|
37
|
+
waivers: Record<string, LegacyWaiver>;
|
|
38
|
+
untrusted: UntrustedWaiver[];
|
|
39
|
+
/** What the dual-write puts back in the legacy file: legacy key order, unknown records kept verbatim. */
|
|
40
|
+
stateWaivers: Record<string, unknown>;
|
|
41
|
+
imports: DecisionDraft[];
|
|
42
|
+
/** Write the import marker on commit: nothing untrusted is left to decide. */
|
|
43
|
+
markDone: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const importMarkerPath = (projectRoot: string, slug: string): string =>
|
|
47
|
+
path.join(projectRoot, '.sungen', 'migrations', `${slug}.waivers-imported.json`);
|
|
48
|
+
|
|
49
|
+
const asRecord = (v: unknown): Record<string, unknown> => (v && typeof v === 'object' && !Array.isArray(v) ? v as Record<string, unknown> : {});
|
|
50
|
+
const newer = (w: LegacyWaiver, validFrom: string): boolean => {
|
|
51
|
+
const at = Date.parse(w.at);
|
|
52
|
+
return at > Date.parse(validFrom) && at <= Date.now();
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function planWaiverSync(projectRoot: string, unit: string, slug: string, statePath: string, legacy: unknown): WaiverSyncPlan {
|
|
56
|
+
const legacyWaivers = asRecord(legacy);
|
|
57
|
+
const scope = unitDecisionScope(projectRoot, unit);
|
|
58
|
+
const inForce = scope ? effectiveWaiverEntries(readDecisions(projectRoot, scope, { kind: 'waiver' }).entries) : new Map();
|
|
59
|
+
const stateWaivers: Record<string, unknown> = { ...legacyWaivers };
|
|
60
|
+
const waivers: Record<string, LegacyWaiver> = {};
|
|
61
|
+
const untrusted: UntrustedWaiver[] = [];
|
|
62
|
+
const imports: DecisionDraft[] = [];
|
|
63
|
+
|
|
64
|
+
if (scope && fs.existsSync(importMarkerPath(projectRoot, slug))) {
|
|
65
|
+
for (const [ob, d] of inForce) stateWaivers[ob] = waivers[ob] = asLegacyWaiver(d);
|
|
66
|
+
return { scope, waivers, untrusted, stateWaivers, imports, markDone: false };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const head = asRecord(asRecord(committedJson(projectRoot, statePath)).waivers);
|
|
70
|
+
for (const [ob, w] of Object.entries(legacyWaivers)) {
|
|
71
|
+
if (!isLegacyWaiver(w)) continue; // unreadable record: kept in the file, never counted
|
|
72
|
+
const d = inForce.get(ob);
|
|
73
|
+
if (d && sameWaiver(asLegacyWaiver(d), w)) { waivers[ob] = w; continue; }
|
|
74
|
+
if (!(ob in head) || canonicalJson(head[ob]) !== canonicalJson(w)) { untrusted.push({ obligation: ob, waiver: w }); continue; }
|
|
75
|
+
if (d && !newer(w, d.valid_from)) { stateWaivers[ob] = waivers[ob] = asLegacyWaiver(d); continue; }
|
|
76
|
+
if (scope) imports.push(waiverDraft(ob, w, { by: 'unknown', where: 'migrated' }, d?.id));
|
|
77
|
+
waivers[ob] = w;
|
|
78
|
+
}
|
|
79
|
+
for (const [ob, d] of inForce) if (!(ob in waivers)) stateWaivers[ob] = waivers[ob] = asLegacyWaiver(d);
|
|
80
|
+
return { scope, waivers, untrusted, stateWaivers, imports, markDone: !!scope && untrusted.length === 0 };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** The needs-you line for a waiver that is not in git HEAD: not counted, and how a human confirms it. */
|
|
84
|
+
export function untrustedWaiverText(unit: string, slug: string, title: string, u: UntrustedWaiver): string {
|
|
85
|
+
const confirm = formatCommand(['sungen', 'journey', '--screen', unit, '--waive', u.obligation, '--reason', u.waiver.reason]);
|
|
86
|
+
return `⚠️ Waiver on "${title}" is UNTRUSTED — not counted (decision.in-run: it is in .sungen/journey/${slug}.state.json `
|
|
87
|
+
+ `but not in git HEAD). If it is yours, confirm it on a terminal: ${confirm}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const UNWRITABLE = new Set(['EACCES', 'EROFS', 'ENOSPC', 'EPERM']);
|
|
91
|
+
|
|
92
|
+
function writeFile(file: string, text: string): void {
|
|
93
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
94
|
+
fs.writeFileSync(file, text, 'utf-8');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Persist a plan: imports, the dual-written legacy file, the import marker. Returns false when the
|
|
99
|
+
* checkout cannot be written (read-only, full disk); any other failure — a decision that does not
|
|
100
|
+
* verify, a migration in progress or interrupted — is raised, never swallowed.
|
|
101
|
+
*/
|
|
102
|
+
export function commitWaiverSync(projectRoot: string, unit: string, slug: string, plan: WaiverSyncPlan, statePath: string, stateText: string): boolean {
|
|
103
|
+
const marker = importMarkerPath(projectRoot, slug);
|
|
104
|
+
const writeMarker = plan.markDone && !fs.existsSync(marker);
|
|
105
|
+
const markerText = (ids: string[]) => `${JSON.stringify({ schema: 1, unit, importedAt: new Date().toISOString(), imported: ids }, null, 2)}\n`;
|
|
106
|
+
try {
|
|
107
|
+
if (!plan.scope || plan.imports.length === 0) {
|
|
108
|
+
writeFile(statePath, stateText);
|
|
109
|
+
if (writeMarker) writeFile(marker, markerText([]));
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
const scope = plan.scope;
|
|
113
|
+
const dir = decisionsDirFor(projectRoot, scope);
|
|
114
|
+
const targets = plan.imports.map((d) => path.join(dir, `${computeDecisionId(d, scope)}.yaml`));
|
|
115
|
+
withMigrationSentinel(projectRoot, unit, slug, `import ${plan.imports.length} legacy waiver(s) into the decision layer`,
|
|
116
|
+
[statePath, ...(writeMarker ? [marker] : []), ...targets], () => {
|
|
117
|
+
const ids = plan.imports.map((d) => appendDecision(projectRoot, scope, d).entry.id);
|
|
118
|
+
writeFile(statePath, stateText);
|
|
119
|
+
if (writeMarker) writeFile(marker, markerText(ids));
|
|
120
|
+
});
|
|
121
|
+
return true;
|
|
122
|
+
} catch (err) {
|
|
123
|
+
if (UNWRITABLE.has((err as NodeJS.ErrnoException)?.code ?? '')) return false;
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Record a waiver given now on the CLI; supersedes the waiver in force for that obligation, if any. */
|
|
129
|
+
export function recordWaiver(projectRoot: string, unit: string, obligation: string, w: LegacyWaiver): AppendResult {
|
|
130
|
+
const scope = unitDecisionScope(projectRoot, unit);
|
|
131
|
+
if (!scope) throw new Error(`Cannot record a waiver: "${unit}" does not name exactly one unit under qa/screens, qa/flows or qa/api.`);
|
|
132
|
+
const current = effectiveWaiverEntries(readDecisions(projectRoot, scope, { kind: 'waiver' }).entries).get(obligation);
|
|
133
|
+
if (current && sameWaiver(asLegacyWaiver(current), w)) return { status: 'already-recorded', entry: current, path: current.path };
|
|
134
|
+
return appendDecision(projectRoot, scope, waiverDraft(obligation, w, { by: gitUserName(projectRoot), where: 'cli' }, current?.id));
|
|
135
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read the decisions of one scope (DOS-13.1 – 13.3). Best-effort by contract: a missing directory
|
|
3
|
+
* reads as empty, a bad file becomes a `problem` — a read-only or half-broken checkout never throws.
|
|
4
|
+
*
|
|
5
|
+
* Only entries that verify against themselves take effect; an entry whose content no longer matches
|
|
6
|
+
* its id, or whose entry_hash no longer matches the entry, is reported and ignored (trust nothing
|
|
7
|
+
* written). Computed on read, never stored:
|
|
8
|
+
* - `superseded_by` — the latest visible entry that names this one in `supersedes`
|
|
9
|
+
* - `stale` — with `auditHash` given: `evidence_hash ≠ auditHash` (the waiver rule, DOS-13.5)
|
|
10
|
+
* `asOf` hides entries whose `valid_from` is later, so a later superseder does not supersede yet.
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { DecisionEntry, DecisionKind } from './decision-schema';
|
|
15
|
+
import { DecisionProblem, decisionsDirFor, verifyDecisionFile } from './decision-file';
|
|
16
|
+
|
|
17
|
+
export interface ReadDecision extends DecisionEntry {
|
|
18
|
+
scope: string;
|
|
19
|
+
path: string;
|
|
20
|
+
superseded_by?: string;
|
|
21
|
+
stale?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ReadDecisionsOptions { asOf?: string; auditHash?: string; kind?: DecisionKind }
|
|
25
|
+
export interface ReadDecisionsResult { entries: ReadDecision[]; problems: DecisionProblem[] }
|
|
26
|
+
|
|
27
|
+
const byTime = (a: DecisionEntry, b: DecisionEntry): number =>
|
|
28
|
+
Date.parse(a.valid_from) - Date.parse(b.valid_from) || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
29
|
+
|
|
30
|
+
export function readDecisions(projectRoot: string, scope: string, opts: ReadDecisionsOptions = {}): ReadDecisionsResult {
|
|
31
|
+
const problems: DecisionProblem[] = [];
|
|
32
|
+
let dir: string;
|
|
33
|
+
let names: string[];
|
|
34
|
+
try {
|
|
35
|
+
dir = decisionsDirFor(projectRoot, scope);
|
|
36
|
+
names = fs.readdirSync(dir).filter((f) => f.endsWith('.yaml')).sort();
|
|
37
|
+
} catch {
|
|
38
|
+
return { entries: [], problems };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const cutoff = opts.asOf ? Date.parse(opts.asOf) : Infinity;
|
|
42
|
+
const entries: ReadDecision[] = [];
|
|
43
|
+
for (const name of names) {
|
|
44
|
+
const file = path.join(dir, name);
|
|
45
|
+
const v = verifyDecisionFile(file, scope);
|
|
46
|
+
if (v.problem) { problems.push(v.problem); continue; }
|
|
47
|
+
if (Date.parse(v.entry.valid_from) > cutoff) continue;
|
|
48
|
+
entries.push({ ...v.entry, scope, path: file });
|
|
49
|
+
}
|
|
50
|
+
entries.sort(byTime);
|
|
51
|
+
|
|
52
|
+
const byId = new Map(entries.map((e) => [e.id, e]));
|
|
53
|
+
for (const e of entries) {
|
|
54
|
+
const target = e.supersedes ? byId.get(e.supersedes) : undefined;
|
|
55
|
+
if (target) target.superseded_by = e.id; // ascending time: the latest superseder wins
|
|
56
|
+
}
|
|
57
|
+
if (opts.auditHash !== undefined) {
|
|
58
|
+
for (const e of entries) if (e.evidence_hash !== undefined) e.stale = e.evidence_hash !== opts.auditHash;
|
|
59
|
+
}
|
|
60
|
+
return { entries: opts.kind ? entries.filter((e) => e.kind === opts.kind) : entries, problems };
|
|
61
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The accepted viewpoint baseline, seen as decisions — read-only (DOS-11.4; storage moves in P1).
|
|
3
|
+
*
|
|
4
|
+
* `sungen audit --accept-viewpoint` records `.sungen/viewpoint-baseline.json` (harness/viewpoint-
|
|
5
|
+
* baseline.ts). Each unit in it is projected as one `viewpoint-acceptance` decision, without moving or
|
|
6
|
+
* rewriting anything: no file is written here, ever.
|
|
7
|
+
*
|
|
8
|
+
* The file is agent-writable, so a unit is projected only while its record equals the one committed
|
|
9
|
+
* in git HEAD (review H1) — otherwise it would turn a local edit into a hash-valid decision. Anything
|
|
10
|
+
* not projected is reported: an `untrusted` unit, an `invalid` unit record, an `unreadable` file.
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { canonicalJson, sealDecision } from './decision-identity';
|
|
15
|
+
import { DecisionProblem, PROJECT_SCOPE } from './decision-file';
|
|
16
|
+
import { committedJson } from './git-head-trust';
|
|
17
|
+
import { ReadDecision } from './read-decisions';
|
|
18
|
+
|
|
19
|
+
/** Same location harness/viewpoint-baseline.ts writes. */
|
|
20
|
+
const baselineFile = (projectRoot: string): string => path.join(projectRoot, '.sungen', 'viewpoint-baseline.json');
|
|
21
|
+
const EPOCH = '1970-01-01T00:00:00.000Z';
|
|
22
|
+
|
|
23
|
+
interface UnitRecord { hash: string; ids: string[]; recordedAt?: string; fileHash?: string }
|
|
24
|
+
|
|
25
|
+
function isUnitRecord(v: unknown): v is UnitRecord {
|
|
26
|
+
const r = v as UnitRecord;
|
|
27
|
+
return !!r && typeof r === 'object' && typeof r.hash === 'string' && Array.isArray(r.ids) && r.ids.every((i) => typeof i === 'string');
|
|
28
|
+
}
|
|
29
|
+
const unitsOf = (raw: unknown): Record<string, unknown> | null => {
|
|
30
|
+
const u = (raw as { units?: unknown } | null)?.units;
|
|
31
|
+
return u && typeof u === 'object' && !Array.isArray(u) ? u as Record<string, unknown> : null;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function project(unit: string, r: UnitRecord, file: string): ReadDecision {
|
|
35
|
+
const at = typeof r.recordedAt === 'string' && !Number.isNaN(Date.parse(r.recordedAt)) ? new Date(r.recordedAt).toISOString() : EPOCH;
|
|
36
|
+
const entry = sealDecision({
|
|
37
|
+
kind: 'viewpoint-acceptance',
|
|
38
|
+
anchors: [],
|
|
39
|
+
text: `Accept the test-viewpoint declaration of ${unit} as the baseline`,
|
|
40
|
+
reason: 'Accepted with sungen audit --accept-viewpoint (legacy .sungen/viewpoint-baseline.json)',
|
|
41
|
+
payload: { unit, hash: r.hash, ids: r.ids, ...(typeof r.fileHash === 'string' ? { fileHash: r.fileHash } : {}) },
|
|
42
|
+
source: { by: 'unknown', where: 'legacy:viewpoint-baseline' },
|
|
43
|
+
valid_from: at,
|
|
44
|
+
visibility: 'internal',
|
|
45
|
+
}, PROJECT_SCOPE);
|
|
46
|
+
return { ...entry, scope: PROJECT_SCOPE, path: file };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function viewpointAcceptanceDecisions(projectRoot: string): { entries: ReadDecision[]; problems: DecisionProblem[] } {
|
|
50
|
+
const file = baselineFile(projectRoot);
|
|
51
|
+
const entries: ReadDecision[] = [];
|
|
52
|
+
const problems: DecisionProblem[] = [];
|
|
53
|
+
if (!fs.existsSync(file)) return { entries, problems };
|
|
54
|
+
let units: Record<string, unknown> | null;
|
|
55
|
+
try {
|
|
56
|
+
units = unitsOf(JSON.parse(fs.readFileSync(file, 'utf8')));
|
|
57
|
+
} catch (err) {
|
|
58
|
+
problems.push({ path: file, code: 'unreadable', message: `viewpoint baseline cannot be read: ${err instanceof Error ? err.message : String(err)}` });
|
|
59
|
+
return { entries, problems };
|
|
60
|
+
}
|
|
61
|
+
if (!units) return { entries, problems: [{ path: file, code: 'unreadable', message: 'viewpoint baseline has no `units` mapping' }] };
|
|
62
|
+
|
|
63
|
+
const committed = unitsOf(committedJson(projectRoot, file)) ?? {};
|
|
64
|
+
for (const unit of Object.keys(units).sort()) {
|
|
65
|
+
const r = units[unit];
|
|
66
|
+
if (!isUnitRecord(r)) { problems.push({ path: file, code: 'invalid', message: `viewpoint baseline record for ${unit} is malformed; not projected` }); continue; }
|
|
67
|
+
if (!(unit in committed) || canonicalJson(committed[unit]) !== canonicalJson(r)) {
|
|
68
|
+
problems.push({ path: file, code: 'untrusted', message: `viewpoint baseline for ${unit} is not the one in git HEAD — not taken as a decision (decision.in-run); commit it through review` });
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
entries.push(project(unit, r, file));
|
|
72
|
+
}
|
|
73
|
+
return { entries, problems };
|
|
74
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Journey waivers as decisions (DOS-13.5).
|
|
3
|
+
*
|
|
4
|
+
* A waiver entry is `kind: waiver`, `payload.obligation`, `evidence_hash` = the audit hash the waiver
|
|
5
|
+
* was given against (legacy `auditHashAtWaive`). Per obligation the waiver in force is the latest
|
|
6
|
+
* (by `valid_from`) entry that nothing supersedes. Whether it COUNTS is the old rule, unchanged: only
|
|
7
|
+
* while `evidence_hash` equals the current audit hash; otherwise it is STALE and goes back to a human.
|
|
8
|
+
*/
|
|
9
|
+
import { DecisionDraft, DecisionEntry, DecisionSource } from './decision-schema';
|
|
10
|
+
import { ReadDecision } from './read-decisions';
|
|
11
|
+
|
|
12
|
+
/** The legacy shape in `.sungen/journey/<slug>.state.json` — still dual-written for one release. */
|
|
13
|
+
export interface LegacyWaiver { reason: string; at: string; auditHashAtWaive: string }
|
|
14
|
+
|
|
15
|
+
const norm = (s: string): string => s.normalize('NFC').replace(/\r\n?/g, '\n').trim();
|
|
16
|
+
|
|
17
|
+
export function isLegacyWaiver(w: unknown): w is LegacyWaiver {
|
|
18
|
+
const x = w as LegacyWaiver;
|
|
19
|
+
return !!x && typeof x === 'object' && typeof x.reason === 'string' && norm(x.reason).length > 0
|
|
20
|
+
&& typeof x.at === 'string' && !Number.isNaN(Date.parse(x.at)) && typeof x.auditHashAtWaive === 'string';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Same decision: same reason against the same evidence (the time it was recorded does not matter). */
|
|
24
|
+
export function sameWaiver(a: LegacyWaiver, b: LegacyWaiver): boolean {
|
|
25
|
+
return norm(a.reason) === norm(b.reason) && a.auditHashAtWaive === b.auditHashAtWaive;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function waiverDraft(obligation: string, w: LegacyWaiver, source: DecisionSource, supersedes?: string): DecisionDraft {
|
|
29
|
+
return {
|
|
30
|
+
kind: 'waiver',
|
|
31
|
+
anchors: [],
|
|
32
|
+
text: `Waive ${obligation}`,
|
|
33
|
+
reason: w.reason,
|
|
34
|
+
payload: { obligation },
|
|
35
|
+
source,
|
|
36
|
+
valid_from: w.at,
|
|
37
|
+
...(supersedes ? { supersedes } : {}),
|
|
38
|
+
visibility: 'internal',
|
|
39
|
+
evidence_hash: w.auditHashAtWaive,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function asLegacyWaiver(e: DecisionEntry): LegacyWaiver {
|
|
44
|
+
return { reason: e.reason, at: e.valid_from, auditHashAtWaive: e.evidence_hash ?? '' };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** obligation → the waiver entry in force. `entries` come from readDecisions (sorted by time). */
|
|
48
|
+
export function effectiveWaiverEntries(entries: ReadDecision[]): Map<string, ReadDecision> {
|
|
49
|
+
const out = new Map<string, ReadDecision>();
|
|
50
|
+
for (const e of entries) {
|
|
51
|
+
const ob = e.payload?.obligation;
|
|
52
|
+
if (e.kind !== 'waiver' || e.superseded_by || typeof ob !== 'string') continue;
|
|
53
|
+
out.set(ob, e); // ascending time: the latest wins
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
@@ -32,6 +32,10 @@ import { formatEnv } from './run-environment';
|
|
|
32
32
|
export interface BuildCsvInput {
|
|
33
33
|
screen: string;
|
|
34
34
|
featureName: string;
|
|
35
|
+
/** The exact command that regenerates this unit (`sungen generate --flow checkout`). `screen`
|
|
36
|
+
* is the deliverable label — the FEATURE basename, `flow/<x>` for a flow — so a note built from
|
|
37
|
+
* it named a command that fails (#880). */
|
|
38
|
+
generateCommand?: string;
|
|
35
39
|
/** URL path for the screen/flow entry point — concatenated onto baseURL
|
|
36
40
|
* when building the Test Environment column so QA can see the exact URL
|
|
37
41
|
* the test targets. */
|
|
@@ -207,7 +211,7 @@ export function buildTestCaseRows(input: BuildCsvInput): TestCaseRow[] {
|
|
|
207
211
|
// No execution record AND no compiled test → Manual if @manual, else genuinely not compiled.
|
|
208
212
|
testResult = testcaseType === 'Manual' ? 'Pending' : 'N/A';
|
|
209
213
|
if (testcaseType !== 'Manual') {
|
|
210
|
-
note =
|
|
214
|
+
note = `Scenario not compiled — re-run \`${input.generateCommand ?? `sungen generate --screen ${input.screen}`}\``;
|
|
211
215
|
} else {
|
|
212
216
|
// Why the case is manual — the `# MANUAL: …` comment — so the tester reading the
|
|
213
217
|
// deliverable knows what blocks automation (#810). Empty when no reason is written.
|
|
@@ -117,6 +117,7 @@ export function parseFeatureMetadata(featureFilePath: string): FeatureMetadata {
|
|
|
117
117
|
referencedVars: extractReferencedVars(sc, extractTestcaseType([...parsed.tags, ...sc.tags]) === 'Manual'),
|
|
118
118
|
orderedSteps: classifySteps(sc),
|
|
119
119
|
comments: sc.comments,
|
|
120
|
+
hookType: sc.hookType,
|
|
120
121
|
}));
|
|
121
122
|
|
|
122
123
|
return {
|
|
@@ -136,6 +137,17 @@ export function isStepsBaseScenario(sc: ScenarioMetadata): boolean {
|
|
|
136
137
|
return !!sc.stepsName;
|
|
137
138
|
}
|
|
138
139
|
|
|
140
|
+
/**
|
|
141
|
+
* A hook (`@beforeAll` / `@afterEach` / `@afterAll`) — setup or teardown around the tests, compiled
|
|
142
|
+
* to `test.beforeAll()` etc. Read from the scenario's OWN tag (the parser's `hookType`), never from
|
|
143
|
+
* the feature+scenario tag union. It is not a test case: counted as one, it blocked the matrix at
|
|
144
|
+
* Gate A (a hook carries no VP id, as the gherkin skill tells authors) and showed in the legacy
|
|
145
|
+
* workbook and the dashboard as a "Not compiled" row (#880).
|
|
146
|
+
*/
|
|
147
|
+
export function isHookScenario(sc: ScenarioMetadata): boolean {
|
|
148
|
+
return !!sc.hookType;
|
|
149
|
+
}
|
|
150
|
+
|
|
139
151
|
/**
|
|
140
152
|
* Return true if this is the default scaffold sample scenario (not real).
|
|
141
153
|
*/
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
MAX_VARIANTS_PER_ITEM,
|
|
35
35
|
} from './types';
|
|
36
36
|
import { runGates } from './gates';
|
|
37
|
+
import { CATALOG_GATE_RULES, GateRules } from '../../harness/gates/resolve-rule';
|
|
37
38
|
import { capabilityRegistry } from '../../capabilities/registry';
|
|
38
39
|
import { discoverAndRegisterCapabilities } from '../../capabilities/discover';
|
|
39
40
|
|
|
@@ -96,6 +97,7 @@ function resolveDataPairs(
|
|
|
96
97
|
vars: string[],
|
|
97
98
|
testData: Record<string, string> | null,
|
|
98
99
|
row?: Record<string, unknown>,
|
|
100
|
+
runtimeVars: Set<string> = new Set(),
|
|
99
101
|
): string[] {
|
|
100
102
|
const pairs: string[] = [];
|
|
101
103
|
if (row) {
|
|
@@ -107,7 +109,10 @@ function resolveDataPairs(
|
|
|
107
109
|
for (const v of vars) {
|
|
108
110
|
const val = row && v in row ? undefined : testData?.[v]; // row columns already listed
|
|
109
111
|
// Credential-named refs (`accounts.0.password`) render `***` — this column is read outside the run.
|
|
110
|
-
|
|
112
|
+
// A value may embed a var the scenario captures at run time (`Total ({{stat}})`) or a
|
|
113
|
+
// dataset column — expanded with the same vars as the cells, so both columns agree (#879).
|
|
114
|
+
const scope = row ? { ...(testData ?? {}), ...rowAsStrings(row) } : (testData ?? {});
|
|
115
|
+
if (val !== undefined) pairs.push(`${v}: ${displayValue(maskCredentialValue(v, expandValue(String(val), scope, runtimeVars, new Set([v]))))}`);
|
|
111
116
|
}
|
|
112
117
|
return pairs;
|
|
113
118
|
}
|
|
@@ -124,6 +129,8 @@ export interface BuildInputs {
|
|
|
124
129
|
specText?: string;
|
|
125
130
|
/** apis.yaml endpoint catalog (api units) — renders `@api:` calls as request blocks. */
|
|
126
131
|
apiCatalog?: Record<string, ApiCatalogEntry>;
|
|
132
|
+
/** The unit's gate rules (catalog + gate-overrides, OES-11.2); the catalog alone when absent. */
|
|
133
|
+
gateRules?: GateRules;
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
/**
|
|
@@ -136,6 +143,10 @@ export function deriveVariants(inputs: Pick<BuildInputs, 'feature' | 'merged' |
|
|
|
136
143
|
// Test-data values may cross-reference other keys (email_padded: " {{valid_email}} ") —
|
|
137
144
|
// resolve one level so display cells never leak a template token (review B-04).
|
|
138
145
|
const testData = resolveCrossRefs(inputs.testData);
|
|
146
|
+
// Display cells expand from the RAW values, per scenario — with its row and its runtime vars —
|
|
147
|
+
// in the runtime's order (captured var > row column > test-data key). The pre-resolved copy above
|
|
148
|
+
// only serves row discovery and result matching, which render nothing (#879).
|
|
149
|
+
const rawTestData = inputs.testData ?? {};
|
|
139
150
|
const apiCatalog = inputs.apiCatalog ?? {};
|
|
140
151
|
const variants: CoverageVariant[] = [];
|
|
141
152
|
|
|
@@ -305,14 +316,14 @@ export function deriveVariants(inputs: Pick<BuildInputs, 'feature' | 'merged' |
|
|
|
305
316
|
const resultByLabel = new Map(resultVariants.map((rv) => [rv.nameSuffix.replace(/^ — /, ''), rv.result]));
|
|
306
317
|
rows.forEach((row, i) => {
|
|
307
318
|
const label = String(row.case ?? row.name ?? row.label ?? `row ${i + 1}`);
|
|
308
|
-
const cells = renderCells({ ...
|
|
319
|
+
const cells = renderCells({ ...rawTestData, ...rowAsStrings(row) });
|
|
309
320
|
variants.push({
|
|
310
321
|
...base,
|
|
311
322
|
ref: `${vpId}#${label}`,
|
|
312
323
|
caseLabel: label,
|
|
313
324
|
title: `${category1} — ${label}`,
|
|
314
325
|
condition: label,
|
|
315
|
-
data: resolveDataPairs(m.feature.referencedVars,
|
|
326
|
+
data: resolveDataPairs(m.feature.referencedVars, rawTestData, row, runtimeVars),
|
|
316
327
|
trigger: cells.trigger,
|
|
317
328
|
oracle: cells.oracle,
|
|
318
329
|
precondition: cells.precondition,
|
|
@@ -322,13 +333,13 @@ export function deriveVariants(inputs: Pick<BuildInputs, 'feature' | 'merged' |
|
|
|
322
333
|
});
|
|
323
334
|
});
|
|
324
335
|
} else {
|
|
325
|
-
const cells = renderCells(
|
|
336
|
+
const cells = renderCells(rawTestData);
|
|
326
337
|
variants.push({
|
|
327
338
|
...base,
|
|
328
339
|
ref: vpId,
|
|
329
340
|
title: category1,
|
|
330
341
|
condition: category1,
|
|
331
|
-
data: resolveDataPairs(m.feature.referencedVars,
|
|
342
|
+
data: resolveDataPairs(m.feature.referencedVars, rawTestData, undefined, runtimeVars),
|
|
332
343
|
trigger: cells.trigger,
|
|
333
344
|
oracle: cells.oracle,
|
|
334
345
|
precondition: cells.precondition,
|
|
@@ -360,9 +371,9 @@ function substituteDisplayVars(
|
|
|
360
371
|
if (isCapture && /\bas\s+$/i.test(text.slice(0, offset))) return m;
|
|
361
372
|
// A value the test produces at run time has no static form — name it so the
|
|
362
373
|
// tester knows to compare against what the earlier step captured.
|
|
363
|
-
if (
|
|
374
|
+
if (isRuntimeVar(key, runtimeVars)) return `the captured ${key}`;
|
|
364
375
|
if (!(key in vars)) return m; // unknown stays literal → Gate D flags it
|
|
365
|
-
return displayValue(vars[key]);
|
|
376
|
+
return displayValue(expandValue(vars[key], vars, runtimeVars, new Set([key])));
|
|
366
377
|
});
|
|
367
378
|
// A dynamic token written straight into a step (`{{$uuid}}`) never reaches
|
|
368
379
|
// displayValue — name it here so the same wording covers both routes.
|
|
@@ -432,12 +443,45 @@ export function computeRequirements(
|
|
|
432
443
|
});
|
|
433
444
|
}
|
|
434
445
|
|
|
435
|
-
|
|
446
|
+
const isRuntimeVar = (key: string, runtimeVars: Set<string>): boolean =>
|
|
447
|
+
runtimeVars.has(key) || runtimeVars.has(key.split(/[.[]/)[0]);
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Expand the `{{refs}}` inside a test-data VALUE the way the runtime's `interpolate()` does
|
|
451
|
+
* (specs/generated/test-data.ts): recursively, depth-capped against reference cycles, and a var
|
|
452
|
+
* the scenario captures at run time is named, not looked up. An unknown ref (or a cycle) stays
|
|
453
|
+
* literal, so Gate D still refuses it; a nested value renders through displayValue, as it did
|
|
454
|
+
* when this resolved one level (an empty one reads `(empty)`).
|
|
455
|
+
*
|
|
456
|
+
* Delivery used to resolve ONE level, before any scenario's runtime vars were known: both
|
|
457
|
+
* `heading_expected: "Total ({{stat}})"` with `remember … as {{stat}}`, and a plain chain
|
|
458
|
+
* (`a: "{{b}}"`, `b: "x {{c}}"`), left a token that blocked the export of a suite the runtime
|
|
459
|
+
* runs fine (#879).
|
|
460
|
+
*/
|
|
461
|
+
function expandValue(
|
|
462
|
+
value: string, vars: Record<string, string>, runtimeVars: Set<string>,
|
|
463
|
+
expanding: ReadonlySet<string> = new Set(), depth = 0,
|
|
464
|
+
): string {
|
|
465
|
+
if (depth > 10 || !value.includes('{{')) return value;
|
|
466
|
+
return value.replace(/\{\{\s*([^}\s]+)\s*\}\}/g, (m, key: string) => {
|
|
467
|
+
if (isRuntimeVar(key, runtimeVars)) return `the captured ${key}`;
|
|
468
|
+
const v = vars[key];
|
|
469
|
+
// A key already being expanded is a cycle: keep the token (Gate D names it) instead of
|
|
470
|
+
// re-entering — `a: "{{a}}{{a}}"` doubled per level and exhausted the heap.
|
|
471
|
+
if (v === undefined || v === null || expanding.has(key)) return m;
|
|
472
|
+
return displayValue(expandValue(String(v), vars, runtimeVars, new Set([...expanding, key]), depth + 1));
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Pre-resolve test-data cross-references before any scenario is known — every static level.
|
|
478
|
+
* A runtime var is not known yet and stays a token here; each scenario's cells expand it.
|
|
479
|
+
*/
|
|
436
480
|
function resolveCrossRefs(testData: Record<string, string> | null): Record<string, string> | null {
|
|
437
481
|
if (!testData) return null;
|
|
438
482
|
const out: Record<string, string> = {};
|
|
439
483
|
for (const [k, v] of Object.entries(testData)) {
|
|
440
|
-
out[k] = typeof v === 'string' && v.includes('{{') ?
|
|
484
|
+
out[k] = typeof v === 'string' && v.includes('{{') ? renderDynamicTokens(expandValue(v, testData, new Set(), new Set([k]))) : v;
|
|
441
485
|
}
|
|
442
486
|
return out;
|
|
443
487
|
}
|
|
@@ -463,6 +507,7 @@ function rowAsStrings(row: Record<string, unknown>): Record<string, string> {
|
|
|
463
507
|
* as blocked), which silently skewed the derived parent result.
|
|
464
508
|
*/
|
|
465
509
|
export function variantState(v: CoverageVariant): VariantState {
|
|
510
|
+
if (v.manualState) return v.manualState; // a carried Manual result (#891)
|
|
466
511
|
const r = v.result;
|
|
467
512
|
if (!r) return 'Pending';
|
|
468
513
|
switch (r.status) {
|
|
@@ -552,7 +597,7 @@ export function buildMatrix(inputs: BuildInputs): MatrixModel {
|
|
|
552
597
|
variantsByVp.set(v.vpId, list);
|
|
553
598
|
}
|
|
554
599
|
|
|
555
|
-
const findings = runGates({ inputs, variants, variantsByVp });
|
|
600
|
+
const findings = runGates({ inputs, variants, variantsByVp, rules: inputs.gateRules });
|
|
556
601
|
const stale = new Set(findings.filter((f) => f.gate === 'E' && f.ref).map((f) => f.ref as string));
|
|
557
602
|
|
|
558
603
|
const items: DeliveryItem[] = map.groups.map((g) => {
|
|
@@ -618,22 +663,21 @@ export function buildMatrix(inputs: BuildInputs): MatrixModel {
|
|
|
618
663
|
// requirements/spec.md; @spec: traces mark `covered`; the map's `requirements:`
|
|
619
664
|
// section carries the reviewed overrides (partially_covered / not_applicable / …).
|
|
620
665
|
const requirements = computeRequirements(inputs.specText ?? '', map, items);
|
|
666
|
+
// Gate R levels come from the catalog like every other matrix gate (OES-11.2); `off` drops the finding.
|
|
667
|
+
const gateR = (rule: string, message: string): void => {
|
|
668
|
+
const { severity } = (inputs.gateRules ?? CATALOG_GATE_RULES).resolve(rule);
|
|
669
|
+
if (severity !== 'off') findings.push({ gate: 'R', severity, message });
|
|
670
|
+
};
|
|
621
671
|
const gaps = requirements.filter((r) => r.status === 'gap');
|
|
622
672
|
if (gaps.length > 0) {
|
|
623
|
-
|
|
624
|
-
gate: 'R', severity: 'warning',
|
|
625
|
-
message: `${gaps.length} requirement id(s) with no coverage or disposition: ${gaps.map((g) => g.id).join(', ')} — trace them, or record a status in the map \`requirements:\` section`,
|
|
626
|
-
});
|
|
673
|
+
gateR('matrix.gate-r.requirement-gap', `${gaps.length} requirement id(s) with no coverage or disposition: ${gaps.map((g) => g.id).join(', ')} — trace them, or record a status in the map \`requirements:\` section`);
|
|
627
674
|
}
|
|
628
675
|
// A `covered` claim with no traced variant is prose, not traceability: nothing
|
|
629
676
|
// detects it when the proving scenario is later changed or deleted. Either tag
|
|
630
677
|
// the scenario that proves it (`@spec:<id>`) or say where it IS covered.
|
|
631
678
|
const unbacked = requirements.filter((r) => r.status === 'covered' && r.items.length === 0);
|
|
632
679
|
if (unbacked.length > 0) {
|
|
633
|
-
|
|
634
|
-
gate: 'R', severity: 'warning',
|
|
635
|
-
message: `${unbacked.length} requirement id(s) declared \`covered\` with no variant tracing to them: ${unbacked.map((r) => r.id).join(', ')} — add \`@spec:<id>\` to the scenario that proves each, or use covered_elsewhere / partially_covered with a named reference`,
|
|
636
|
-
});
|
|
680
|
+
gateR('matrix.gate-r.covered-unbacked', `${unbacked.length} requirement id(s) declared \`covered\` with no variant tracing to them: ${unbacked.map((r) => r.id).join(', ')} — add \`@spec:<id>\` to the scenario that proves each, or use covered_elsewhere / partially_covered with a named reference`);
|
|
637
681
|
}
|
|
638
682
|
|
|
639
683
|
const variantCount = items.reduce((a, i) => a + i.variants.length, 0);
|