@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
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
|
|
20
20
|
import * as fs from 'fs';
|
|
21
21
|
import * as ExcelJS from 'exceljs';
|
|
22
|
-
import { MatrixModel } from './types';
|
|
22
|
+
import { MatrixModel, VariantState } from './types';
|
|
23
|
+
import { rollUp } from './build';
|
|
23
24
|
import { HEADER_ROW, RESULT_COL } from './render-testcase-sheet';
|
|
24
25
|
|
|
25
26
|
const MANUAL_SHEET = 'Manual';
|
|
@@ -169,6 +170,70 @@ function resetNote(prior: CarriedCell[]): ExcelJS.CellValue {
|
|
|
169
170
|
return own ? `${header}\n${own}` : header;
|
|
170
171
|
}
|
|
171
172
|
|
|
173
|
+
/**
|
|
174
|
+
* What happens to each Manual variant's prior row: `carry` its cells, or `reset` it to Pending
|
|
175
|
+
* because the procedure changed since the result was recorded. A row with nothing recorded has
|
|
176
|
+
* no entry. The ONE decision both the model (totals, #891) and the workbook cells read.
|
|
177
|
+
*/
|
|
178
|
+
export function planManualCarry(model: MatrixModel, prior: PriorManualResults | null): Map<string, 'carry' | 'reset'> {
|
|
179
|
+
const plan = new Map<string, 'carry' | 'reset'>();
|
|
180
|
+
if (!prior) return plan;
|
|
181
|
+
for (const v of model.items.flatMap((i) => i.variants)) {
|
|
182
|
+
if (v.mode !== 'manual') continue;
|
|
183
|
+
const before = prior.rows.get(v.ref);
|
|
184
|
+
if (!before || isUntouched(before.cells)) continue;
|
|
185
|
+
const stamped = prior.stamps?.get(v.ref);
|
|
186
|
+
// Only a recorded result is a claim about the procedure. A row with no result (a
|
|
187
|
+
// blocker note, or one already reset) is carried as-is, so a second procedure
|
|
188
|
+
// change does not stack a second marker on it.
|
|
189
|
+
const hasResult = !['', 'Pending'].includes(cellText(before.cells[0].value));
|
|
190
|
+
plan.set(v.ref, stamped !== undefined && stamped !== v.fingerprint && hasResult ? 'reset' : 'carry');
|
|
191
|
+
}
|
|
192
|
+
return plan;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** A typed Result → its state word, case-insensitively (Excel's COUNTIF ignores case too). */
|
|
196
|
+
const STATE_BY_LOWER = new Map<string, VariantState>(
|
|
197
|
+
(['Passed', 'Failed', 'Blocked', 'Pending', 'N/A'] as VariantState[]).map((s) => [s.toLowerCase(), s]),
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Put the carried Manual results into the MODEL, before anything is rendered or counted.
|
|
202
|
+
*
|
|
203
|
+
* The workbook's totals, Overview and group roll-ups are formulas with a cached result computed
|
|
204
|
+
* from the model, and the CSV and the CLI summary read the model too. Carrying only the cells
|
|
205
|
+
* after rendering left all of them counting the recorded Manual results as Pending: a preview
|
|
206
|
+
* of the file, and the CLI, reported "5 Pending" for cases the tester had run (#891).
|
|
207
|
+
* A reset row counts as Pending, as its cell reads. A Result that is not a state word (a tester's
|
|
208
|
+
* "OK") counts as Pending too; the cell keeps the text, and its date still reaches the CSV.
|
|
209
|
+
* Idempotent: every Manual variant's carried fields are cleared first, so the result depends only
|
|
210
|
+
* on `prior`.
|
|
211
|
+
*/
|
|
212
|
+
export function applyManualCarry(model: MatrixModel, prior: PriorManualResults | null): void {
|
|
213
|
+
const plan = planManualCarry(model, prior);
|
|
214
|
+
for (const item of model.items) {
|
|
215
|
+
let touched = false;
|
|
216
|
+
for (const v of item.variants) {
|
|
217
|
+
if (v.mode !== 'manual') continue;
|
|
218
|
+
if (v.manualState !== undefined || v.manualDate !== undefined) touched = true;
|
|
219
|
+
delete v.manualState;
|
|
220
|
+
delete v.manualDate;
|
|
221
|
+
const decision = plan.get(v.ref);
|
|
222
|
+
if (!decision) continue;
|
|
223
|
+
touched = true;
|
|
224
|
+
if (decision === 'reset') { v.manualState = 'Pending'; continue; }
|
|
225
|
+
const [result, date] = prior!.rows.get(v.ref)!.cells.map((c) => cellText(c.value));
|
|
226
|
+
if (date) v.manualDate = date;
|
|
227
|
+
v.manualState = STATE_BY_LOWER.get(result.toLowerCase()) ?? 'Pending';
|
|
228
|
+
}
|
|
229
|
+
if (touched) {
|
|
230
|
+
const { result, counts } = rollUp(item.variants);
|
|
231
|
+
item.result = result;
|
|
232
|
+
item.resultCounts = counts;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
172
237
|
/**
|
|
173
238
|
* Carry `prior` into the freshly rendered `wb`, then stamp every manual variant's fingerprint.
|
|
174
239
|
* Only the Manual sheet's variant sub-rows are touched.
|
|
@@ -178,6 +243,7 @@ export function carryManualResults(
|
|
|
178
243
|
model: MatrixModel,
|
|
179
244
|
prior: PriorManualResults | null,
|
|
180
245
|
): ManualCarryReport {
|
|
246
|
+
const plan = planManualCarry(model, prior);
|
|
181
247
|
const report: ManualCarryReport = { carried: 0, unchecked: 0, reset: [], notPlaced: [], duplicates: prior?.duplicates ?? [] };
|
|
182
248
|
const fingerprints = new Map(
|
|
183
249
|
model.items.flatMap((i) => i.variants).filter((v) => v.mode === 'manual').map((v) => [v.ref, v.fingerprint]),
|
|
@@ -190,14 +256,11 @@ export function carryManualResults(
|
|
|
190
256
|
const before = prior.rows.get(ref);
|
|
191
257
|
if (!before) continue;
|
|
192
258
|
placed.add(ref);
|
|
193
|
-
|
|
259
|
+
const decision = plan.get(ref);
|
|
260
|
+
if (!decision) continue;
|
|
194
261
|
|
|
195
262
|
const stamped = prior.stamps?.get(ref);
|
|
196
|
-
|
|
197
|
-
// blocker note, or one already reset) is carried as-is, so a second procedure
|
|
198
|
-
// change does not stack a second marker on it.
|
|
199
|
-
const hasResult = !['', 'Pending'].includes(cellText(before.cells[0].value));
|
|
200
|
-
if (stamped !== undefined && stamped !== fingerprints.get(ref) && hasResult) {
|
|
263
|
+
if (decision === 'reset') {
|
|
201
264
|
row.getCell(RESULT_COL).value = 'Pending';
|
|
202
265
|
row.getCell(CARRIED_COLS[NOTE_INDEX]).value = resetNote(before.cells);
|
|
203
266
|
report.reset.push(ref);
|
|
@@ -17,7 +17,8 @@ import { mergeFeatureAndSpec } from '../scenario-merger';
|
|
|
17
17
|
import { getPackageVersion } from '../package-info';
|
|
18
18
|
import { writeCsv } from '../csv-exporter';
|
|
19
19
|
import { deliverableXlsxPath, writeXlsx } from '../xlsx-exporter';
|
|
20
|
-
import { carryManualResults, ManualCarryReport, readPriorManualResults } from './carry-manual-results';
|
|
20
|
+
import { applyManualCarry, carryManualResults, ManualCarryReport, PriorManualResults, readPriorManualResults } from './carry-manual-results';
|
|
21
|
+
export { readPriorManualResults } from './carry-manual-results';
|
|
21
22
|
import { loadPerfConfig, perfVerdict } from '../../harness/perf';
|
|
22
23
|
import { loadDeliveryMap, writeDeliveryMap } from './map-loader';
|
|
23
24
|
import { mapContentFingerprint } from './fingerprint';
|
|
@@ -27,6 +28,7 @@ import { renderMatrixCsv } from './render-csv';
|
|
|
27
28
|
import { DeliveryMap, MatrixFinding, MatrixModel } from './types';
|
|
28
29
|
import { ApiCatalogEntry } from '../types';
|
|
29
30
|
import { RunEnvironment } from '../run-environment';
|
|
31
|
+
import { GateRules } from '../../harness/gates/resolve-rule';
|
|
30
32
|
|
|
31
33
|
export interface MatrixTargetPaths {
|
|
32
34
|
cwd: string;
|
|
@@ -49,6 +51,8 @@ export interface MatrixTargetPaths {
|
|
|
49
51
|
mapFile: string;
|
|
50
52
|
/** Executor + environment of the run (#850) — absent for gates-only callers (inspect, approve). */
|
|
51
53
|
runEnv?: RunEnvironment;
|
|
54
|
+
/** The unit's gate rules (catalog + gate-overrides) — absent means the catalog alone. */
|
|
55
|
+
gateRules?: GateRules;
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
function readSpecText(paths: MatrixTargetPaths): string {
|
|
@@ -93,6 +97,7 @@ export function loadMatrixModel(paths: MatrixTargetPaths): MatrixLoadResult {
|
|
|
93
97
|
transformerVersion: getPackageVersion(),
|
|
94
98
|
specText: readSpecText(paths),
|
|
95
99
|
apiCatalog: catalogFor(paths),
|
|
100
|
+
gateRules: paths.gateRules,
|
|
96
101
|
});
|
|
97
102
|
model.runEnv = paths.runEnv;
|
|
98
103
|
// Perf verdict (#569): budgets are config (qa/perf.yaml), samples are the run's
|
|
@@ -131,6 +136,7 @@ export function approveMatrix(paths: MatrixTargetPaths, groupIds?: string[]): {
|
|
|
131
136
|
transformerVersion: getPackageVersion(),
|
|
132
137
|
specText: readSpecText(paths),
|
|
133
138
|
apiCatalog,
|
|
139
|
+
gateRules: paths.gateRules,
|
|
134
140
|
});
|
|
135
141
|
const blocking = model.findings.filter((f) => f.severity === 'error');
|
|
136
142
|
if (blocking.length > 0) return { findings: blocking, approved: [] };
|
|
@@ -168,12 +174,21 @@ export async function writeMatrixDeliverables(
|
|
|
168
174
|
paths: MatrixTargetPaths,
|
|
169
175
|
model: MatrixModel,
|
|
170
176
|
format: MatrixFormat = 'xlsx',
|
|
177
|
+
/** The prior workbook's Manual results, when the caller already read them; read here if absent. */
|
|
178
|
+
priorRead?: PriorManualResults | null,
|
|
171
179
|
): Promise<{ csvPath?: string; xlsxPath?: string; manualCarry?: ManualCarryReport }> {
|
|
172
180
|
const out: { csvPath?: string; xlsxPath?: string; manualCarry?: ManualCarryReport } = {};
|
|
173
181
|
const xlsx = format === 'xlsx' || format === 'both';
|
|
174
182
|
// Read the workbook about to be overwritten BEFORE writing anything, so the tester's Manual
|
|
175
183
|
// results survive (#756) and a refusal leaves no half-written target behind.
|
|
176
|
-
|
|
184
|
+
// A CSV-only export overwrites no workbook, so an unreadable one is no reason to refuse it — but a
|
|
185
|
+
// readable one still holds the Manual results the CSV should show.
|
|
186
|
+
const prior = priorRead !== undefined ? priorRead
|
|
187
|
+
: xlsx ? await readPriorManualResults(deliverableXlsxPath(paths.cwd, paths.unit))
|
|
188
|
+
: await readPriorManualResults(deliverableXlsxPath(paths.cwd, paths.unit)).catch(() => null);
|
|
189
|
+
// Into the model first: the CSV, every cached total and roll-up, and the caller's summary
|
|
190
|
+
// all read it (#891).
|
|
191
|
+
applyManualCarry(model, prior);
|
|
177
192
|
if (format === 'csv' || format === 'both') {
|
|
178
193
|
out.csvPath = writeCsv(paths.cwd, paths.unit, renderMatrixCsv(model));
|
|
179
194
|
}
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
* Deterministic quality gates for the Test Case & Coverage Matrix
|
|
3
3
|
* (docs/spec/delivery-coverage-matrix-spec.md §6).
|
|
4
4
|
*
|
|
5
|
-
* Severity behavior
|
|
5
|
+
* Severity behavior (the level of each finding comes from the gate-rule catalog through
|
|
6
|
+
* `resolveRule`, never from this file — OES-11.2):
|
|
6
7
|
* error → blocks any render
|
|
7
8
|
* review → blocks the official render; `--preview` renders with a DRAFT watermark
|
|
8
9
|
* warning → prints + renders
|
|
10
|
+
* info → prints (only when a gate-override lowered a soft rule); `off` drops the finding
|
|
9
11
|
*
|
|
10
12
|
* The gates recompute every signature part from the .feature — the map is never
|
|
11
13
|
* trusted for derivable facts, only for the semantic fields (target/intent/oracle).
|
|
@@ -14,25 +16,37 @@
|
|
|
14
16
|
import { splitVpAndName, extractTestcaseType } from '../feature-parser';
|
|
15
17
|
import { mapContentFingerprint } from './fingerprint';
|
|
16
18
|
import { bucketTexts } from './step-buckets';
|
|
17
|
-
import { CoverageVariant, MatrixFinding, MAX_VARIANTS_PER_ITEM } from './types';
|
|
19
|
+
import { CoverageVariant, GateId, MatrixFinding, MAX_VARIANTS_PER_ITEM } from './types';
|
|
18
20
|
import { expandMapRef, BuildInputs } from './build';
|
|
21
|
+
import { CATALOG_GATE_RULES, GateRules } from '../../harness/gates/resolve-rule';
|
|
19
22
|
|
|
20
23
|
export interface GateContext {
|
|
21
24
|
inputs: BuildInputs;
|
|
22
25
|
variants: CoverageVariant[];
|
|
23
26
|
variantsByVp: Map<string, CoverageVariant[]>;
|
|
27
|
+
/** The unit's gate rules (catalog + its gate-overrides); the catalog alone when absent. */
|
|
28
|
+
rules?: GateRules;
|
|
24
29
|
}
|
|
25
30
|
|
|
31
|
+
/** A gate site found its condition: the rule decides the finding's severity, or drops it. */
|
|
32
|
+
type ReportFinding = (rule: string, gate: GateId, message: string, ref?: string) => void;
|
|
33
|
+
|
|
26
34
|
export function runGates(ctx: GateContext): MatrixFinding[] {
|
|
27
35
|
const findings: MatrixFinding[] = [];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
const rules = ctx.rules ?? CATALOG_GATE_RULES;
|
|
37
|
+
const report: ReportFinding = (rule, gate, message, ref) => {
|
|
38
|
+
const { severity } = rules.resolve(rule);
|
|
39
|
+
if (severity === 'off') return;
|
|
40
|
+
findings.push({ gate, severity, ...(ref !== undefined ? { ref } : {}), message });
|
|
41
|
+
};
|
|
42
|
+
gateASource(ctx, report);
|
|
43
|
+
gateBMapping(ctx, report);
|
|
44
|
+
gateCAggregation(ctx, report);
|
|
45
|
+
gateDExecutability(ctx, report);
|
|
46
|
+
gateEDrift(ctx, report);
|
|
47
|
+
gateGReviewState(ctx, report);
|
|
48
|
+
gateWWording(ctx, report);
|
|
49
|
+
gateKCategory(ctx, report);
|
|
36
50
|
return findings;
|
|
37
51
|
}
|
|
38
52
|
|
|
@@ -54,16 +68,13 @@ const VP_CATEGORY_RULE: Array<[RegExp, string, string]> = [
|
|
|
54
68
|
* have while hiding the security work it does have. Same for `VP-NFR-*`.
|
|
55
69
|
* (normal vs abnormal stays a judgement call and is never checked.)
|
|
56
70
|
*/
|
|
57
|
-
function gateKCategory(ctx: GateContext,
|
|
71
|
+
function gateKCategory(ctx: GateContext, report: ReportFinding): void {
|
|
58
72
|
for (const g of ctx.inputs.map.groups) {
|
|
59
73
|
const vs = g.variants.flatMap((ref) => expandMapRef(ref, ctx.variantsByVp));
|
|
60
74
|
for (const [re, expected, label] of VP_CATEGORY_RULE) {
|
|
61
75
|
const hits = vs.filter((v) => re.test(v.vpCategory));
|
|
62
76
|
if (hits.length > 0 && g.category !== expected) {
|
|
63
|
-
|
|
64
|
-
gate: 'K', severity: 'warning', ref: g.id,
|
|
65
|
-
message: `group ${g.id} is \`category: ${g.category}\` but ${hits.length}/${vs.length} of its variants are ${label} scenarios (${hits.slice(0, 3).map((v) => v.vpId).join(', ')}) — use \`category: ${expected}\` or the Coverage grid's ${expected} column stays empty`,
|
|
66
|
-
});
|
|
77
|
+
report('matrix.gate-k.category-mismatch', 'K', `group ${g.id} is \`category: ${g.category}\` but ${hits.length}/${vs.length} of its variants are ${label} scenarios (${hits.slice(0, 3).map((v) => v.vpId).join(', ')}) — use \`category: ${expected}\` or the Coverage grid's ${expected} column stays empty`, g.id);
|
|
67
78
|
}
|
|
68
79
|
}
|
|
69
80
|
}
|
|
@@ -71,52 +82,40 @@ function gateKCategory(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
71
82
|
|
|
72
83
|
// --- Gate A — source quality ------------------------------------------------
|
|
73
84
|
|
|
74
|
-
function gateASource(ctx: GateContext,
|
|
85
|
+
function gateASource(ctx: GateContext, report: ReportFinding): void {
|
|
75
86
|
const { feature, merged } = ctx.inputs;
|
|
76
87
|
|
|
77
88
|
if (bucketTexts(feature.backgroundOrderedSteps, 'when').length > 0 || bucketTexts(feature.backgroundOrderedSteps, 'then').length > 0) {
|
|
78
|
-
|
|
79
|
-
gate: 'A', severity: 'error',
|
|
80
|
-
message: 'Background contains When/Then steps — setup only; move the action/oracle into scenarios',
|
|
81
|
-
});
|
|
89
|
+
report('matrix.gate-a.background-when-then', 'A', 'Background contains When/Then steps — setup only; move the action/oracle into scenarios');
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
const seen = new Map<string, number>();
|
|
85
93
|
for (const m of merged) {
|
|
86
94
|
const { vpId } = splitVpAndName(m.feature.name);
|
|
87
95
|
if (!vpId) {
|
|
88
|
-
|
|
89
|
-
gate: 'A', severity: 'error', ref: m.feature.name,
|
|
90
|
-
message: `scenario "${m.feature.name}" has no VP-id prefix — matrix variants must be addressable`,
|
|
91
|
-
});
|
|
96
|
+
report('matrix.gate-a.no-vp-id', 'A', `scenario "${m.feature.name}" has no VP-id prefix — matrix variants must be addressable`, m.feature.name);
|
|
92
97
|
continue;
|
|
93
98
|
}
|
|
94
99
|
seen.set(vpId, (seen.get(vpId) ?? 0) + 1);
|
|
95
100
|
|
|
96
101
|
const isManual = extractTestcaseType(m.feature.tags) === 'Manual';
|
|
97
102
|
if (m.resolvedExpected.length === 0) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
? `manual scenario ${vpId} has no observable oracle (no Then steps and no Observable/Oracle comment lines)`
|
|
102
|
-
: `scenario ${vpId} has no Then step — a variant without an observable oracle cannot be delivered`,
|
|
103
|
-
});
|
|
103
|
+
report('matrix.gate-a.no-oracle', 'A', isManual
|
|
104
|
+
? `manual scenario ${vpId} has no observable oracle (no Then steps and no Observable/Oracle comment lines)`
|
|
105
|
+
: `scenario ${vpId} has no Then step — a variant without an observable oracle cannot be delivered`, vpId);
|
|
104
106
|
}
|
|
105
107
|
if (m.unlabeledManualOracle) {
|
|
106
|
-
|
|
107
|
-
gate: 'A', severity: 'warning', ref: vpId,
|
|
108
|
-
message: `manual oracle found only in an unlabeled comment — exported verbatim into Expected; write the \`# Tester verifies:\` block as numbered "N. Observable: …" lines`,
|
|
109
|
-
});
|
|
108
|
+
report('matrix.gate-a.unlabeled-manual-oracle', 'A', `manual oracle found only in an unlabeled comment — exported verbatim into Expected; write the \`# Tester verifies:\` block as numbered "N. Observable: …" lines`, vpId);
|
|
110
109
|
}
|
|
111
110
|
}
|
|
112
111
|
for (const [vpId, n] of seen) {
|
|
113
|
-
if (n > 1)
|
|
112
|
+
if (n > 1) report('matrix.gate-a.duplicate-vp-id', 'A', `duplicate VP-id ${vpId} (${n} scenarios)`, vpId);
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
|
|
117
116
|
// --- Gate B — mapping completeness -------------------------------------------
|
|
118
117
|
|
|
119
|
-
function gateBMapping(ctx: GateContext,
|
|
118
|
+
function gateBMapping(ctx: GateContext, report: ReportFinding): void {
|
|
120
119
|
const { map } = ctx.inputs;
|
|
121
120
|
const { variants, variantsByVp } = ctx;
|
|
122
121
|
|
|
@@ -126,10 +125,7 @@ function gateBMapping(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
126
125
|
for (const ref of g.variants) {
|
|
127
126
|
const expanded = expandMapRef(ref, variantsByVp);
|
|
128
127
|
if (expanded.length === 0) {
|
|
129
|
-
|
|
130
|
-
gate: 'B', severity: 'error', ref: g.id,
|
|
131
|
-
message: `group ${g.id} references ${ref} which matches no scenario/@cases row in the .feature`,
|
|
132
|
-
});
|
|
128
|
+
report('matrix.gate-b.ref-matches-nothing', 'B', `group ${g.id} references ${ref} which matches no scenario/@cases row in the .feature`, g.id);
|
|
133
129
|
continue;
|
|
134
130
|
}
|
|
135
131
|
for (const v of expanded) {
|
|
@@ -142,10 +138,7 @@ function gateBMapping(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
142
138
|
|
|
143
139
|
for (const [ref, groups] of owners) {
|
|
144
140
|
if (groups.length > 1) {
|
|
145
|
-
|
|
146
|
-
gate: 'B', severity: 'error', ref,
|
|
147
|
-
message: `variant ${ref} belongs to ${groups.length} groups (${groups.join(', ')}) — exactly one required`,
|
|
148
|
-
});
|
|
141
|
+
report('matrix.gate-b.double-mapped', 'B', `variant ${ref} belongs to ${groups.length} groups (${groups.join(', ')}) — exactly one required`, ref);
|
|
149
142
|
}
|
|
150
143
|
}
|
|
151
144
|
|
|
@@ -153,32 +146,23 @@ function gateBMapping(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
153
146
|
const grouped = owners.has(v.ref);
|
|
154
147
|
const disposed = v.vpId in map.dispositions;
|
|
155
148
|
if (!grouped && !disposed) {
|
|
156
|
-
|
|
157
|
-
gate: 'B', severity: 'error', ref: v.ref,
|
|
158
|
-
message: `variant ${v.ref} is in no group and has no disposition — 100% source disposition is required`,
|
|
159
|
-
});
|
|
149
|
+
report('matrix.gate-b.unmapped', 'B', `variant ${v.ref} is in no group and has no disposition — 100% source disposition is required`, v.ref);
|
|
160
150
|
}
|
|
161
151
|
if (grouped && disposed) {
|
|
162
|
-
|
|
163
|
-
gate: 'B', severity: 'error', ref: v.ref,
|
|
164
|
-
message: `variant ${v.ref} is grouped AND disposed (${map.dispositions[v.vpId].as}) — pick one`,
|
|
165
|
-
});
|
|
152
|
+
report('matrix.gate-b.grouped-and-disposed', 'B', `variant ${v.ref} is grouped AND disposed (${map.dispositions[v.vpId].as}) — pick one`, v.ref);
|
|
166
153
|
}
|
|
167
154
|
}
|
|
168
155
|
|
|
169
156
|
for (const vpId of Object.keys(map.dispositions)) {
|
|
170
157
|
if (!variantsByVp.has(vpId)) {
|
|
171
|
-
|
|
172
|
-
gate: 'B', severity: 'warning', ref: vpId,
|
|
173
|
-
message: `disposition for ${vpId} matches no scenario (stale entry?)`,
|
|
174
|
-
});
|
|
158
|
+
report('matrix.gate-b.stale-disposition', 'B', `disposition for ${vpId} matches no scenario (stale entry?)`, vpId);
|
|
175
159
|
}
|
|
176
160
|
}
|
|
177
161
|
}
|
|
178
162
|
|
|
179
163
|
// --- Gate C — aggregation safety ---------------------------------------------
|
|
180
164
|
|
|
181
|
-
function gateCAggregation(ctx: GateContext,
|
|
165
|
+
function gateCAggregation(ctx: GateContext, report: ReportFinding): void {
|
|
182
166
|
const { map } = ctx.inputs;
|
|
183
167
|
const { variantsByVp } = ctx;
|
|
184
168
|
|
|
@@ -207,47 +191,32 @@ function gateCAggregation(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
207
191
|
for (const [label, keyOf] of hard) {
|
|
208
192
|
const distinct = new Set(vs.map(keyOf));
|
|
209
193
|
if (distinct.size > 1) {
|
|
210
|
-
|
|
211
|
-
gate: 'C', severity: 'error', ref: g.id,
|
|
212
|
-
message: `group ${g.id} mixes ${label}s (${[...distinct].join(' vs ')}) — mandatory split`,
|
|
213
|
-
});
|
|
194
|
+
report('matrix.gate-c.mixed-layers', 'C', `group ${g.id} mixes ${label}s (${[...distinct].join(' vs ')}) — mandatory split`, g.id);
|
|
214
195
|
}
|
|
215
196
|
}
|
|
216
197
|
|
|
217
198
|
// Heuristic signature parts — REVIEW_REQUIRED (equivalence was inferred, not declared).
|
|
218
199
|
const preProfiles = new Set(vs.map((v) => v.preconditionProfile));
|
|
219
200
|
if (!heuristicsConfirmed && preProfiles.size > 1) {
|
|
220
|
-
|
|
221
|
-
gate: 'C', severity: 'review', ref: g.id,
|
|
222
|
-
message: `group ${g.id} variants have different precondition profiles — confirm the grouping is safe or split`,
|
|
223
|
-
});
|
|
201
|
+
report('matrix.gate-c.precondition-profiles', 'C', `group ${g.id} variants have different precondition profiles — confirm the grouping is safe or split`, g.id);
|
|
224
202
|
}
|
|
225
203
|
const oracleShapes = new Set(vs.map((v) => v.oracleShape.join(' ; ')));
|
|
226
204
|
if (!heuristicsConfirmed && oracleShapes.size > 1) {
|
|
227
|
-
|
|
228
|
-
gate: 'C', severity: 'review', ref: g.id,
|
|
229
|
-
message: `group ${g.id} variants assert different oracle shapes (${oracleShapes.size} shapes) — confirm they are one oracle family`,
|
|
230
|
-
});
|
|
205
|
+
report('matrix.gate-c.oracle-shapes', 'C', `group ${g.id} variants assert different oracle shapes (${oracleShapes.size} shapes) — confirm they are one oracle family`, g.id);
|
|
231
206
|
}
|
|
232
207
|
if (!heuristicsConfirmed && vs.some((v) => v.procedureProfile === 'sequence')) {
|
|
233
|
-
|
|
234
|
-
gate: 'C', severity: 'review', ref: g.id,
|
|
235
|
-
message: `group ${g.id} contains a sequence-sensitive scenario — ordered flows stay solo items unless QA confirms`,
|
|
236
|
-
});
|
|
208
|
+
report('matrix.gate-c.sequence-sensitive', 'C', `group ${g.id} contains a sequence-sensitive scenario — ordered flows stay solo items unless QA confirms`, g.id);
|
|
237
209
|
}
|
|
238
210
|
|
|
239
211
|
if (vs.length > MAX_VARIANTS_PER_ITEM) {
|
|
240
|
-
|
|
241
|
-
gate: 'C', severity: 'warning', ref: g.id,
|
|
242
|
-
message: `group ${g.id} has ${vs.length} variants (> ${MAX_VARIANTS_PER_ITEM}) — consider splitting for reviewability`,
|
|
243
|
-
});
|
|
212
|
+
report('matrix.gate-c.too-many-variants', 'C', `group ${g.id} has ${vs.length} variants (> ${MAX_VARIANTS_PER_ITEM}) — consider splitting for reviewability`, g.id);
|
|
244
213
|
}
|
|
245
214
|
}
|
|
246
215
|
}
|
|
247
216
|
|
|
248
217
|
// --- Gate D — manual executability -------------------------------------------
|
|
249
218
|
|
|
250
|
-
function gateDExecutability(ctx: GateContext,
|
|
219
|
+
function gateDExecutability(ctx: GateContext, report: ReportFinding): void {
|
|
251
220
|
const { map, testData, feature } = ctx.inputs;
|
|
252
221
|
const { variantsByVp } = ctx;
|
|
253
222
|
|
|
@@ -262,16 +231,10 @@ function gateDExecutability(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
262
231
|
|| bucketTexts(feature.backgroundOrderedSteps, 'given').length > 0
|
|
263
232
|
|| v.apiCalls > 0;
|
|
264
233
|
if (!hasPrecondition) {
|
|
265
|
-
|
|
266
|
-
gate: 'D', severity: 'error', ref: v.ref,
|
|
267
|
-
message: `${v.ref}: no precondition (no Background, auth tag, or Given) — a tester cannot establish the start state`,
|
|
268
|
-
});
|
|
234
|
+
report('matrix.gate-d.no-precondition', 'D', `${v.ref}: no precondition (no Background, auth tag, or Given) — a tester cannot establish the start state`, v.ref);
|
|
269
235
|
}
|
|
270
236
|
if (v.trigger.length === 0) {
|
|
271
|
-
|
|
272
|
-
gate: 'D', severity: 'error', ref: v.ref,
|
|
273
|
-
message: `${v.ref}: no action/trigger (no When steps${v.mode === 'manual' ? ' and no Setup/Action comment lines' : ''})`,
|
|
274
|
-
});
|
|
237
|
+
report('matrix.gate-d.no-trigger', 'D', `${v.ref}: no action/trigger (no When steps${v.mode === 'manual' ? ' and no Setup/Action comment lines' : ''})`, v.ref);
|
|
275
238
|
}
|
|
276
239
|
// Oracle emptiness is Gate A (source) — not repeated here.
|
|
277
240
|
}
|
|
@@ -289,10 +252,7 @@ function gateDExecutability(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
289
252
|
const inRows = vs.some((v) => v.caseLabel !== undefined); // dataset rows carry their own columns
|
|
290
253
|
const atRuntime = runtime.has(varName) || runtime.has(varName.split(/[.[]/)[0]);
|
|
291
254
|
if (!inRows && !atRuntime && (!testData || !(varName in testData))) {
|
|
292
|
-
|
|
293
|
-
gate: 'D', severity: 'error', ref: vpId,
|
|
294
|
-
message: `${vpId}: {{${varName}}} does not resolve in test-data — the variant is not reproducible`,
|
|
295
|
-
});
|
|
255
|
+
report('matrix.gate-d.unresolved-var', 'D', `${vpId}: {{${varName}}} does not resolve in test-data — the variant is not reproducible`, vpId);
|
|
296
256
|
}
|
|
297
257
|
}
|
|
298
258
|
}
|
|
@@ -304,10 +264,7 @@ function gateDExecutability(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
304
264
|
const rendered = [...v.precondition, ...v.trigger, ...v.oracle, ...v.verification, ...v.data];
|
|
305
265
|
const token = rendered.map((t) => t.match(/\{\{[^}]*\}\}/)).find(Boolean);
|
|
306
266
|
if (token) {
|
|
307
|
-
|
|
308
|
-
gate: 'D', severity: 'error', ref: v.ref,
|
|
309
|
-
message: `${v.ref}: unresolved template token ${token[0]} remains in the rendered output — the export is not deterministic for a tester`,
|
|
310
|
-
});
|
|
267
|
+
report('matrix.gate-d.template-token-remains', 'D', `${v.ref}: unresolved template token ${token[0]} remains in the rendered output — the export is not deterministic for a tester`, v.ref);
|
|
311
268
|
}
|
|
312
269
|
}
|
|
313
270
|
}
|
|
@@ -315,7 +272,7 @@ function gateDExecutability(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
315
272
|
|
|
316
273
|
// --- Gate E — drift (stale approval) ------------------------------------------
|
|
317
274
|
|
|
318
|
-
function gateEDrift(ctx: GateContext,
|
|
275
|
+
function gateEDrift(ctx: GateContext, report: ReportFinding): void {
|
|
319
276
|
const { map } = ctx.inputs;
|
|
320
277
|
const { variantsByVp } = ctx;
|
|
321
278
|
|
|
@@ -326,15 +283,9 @@ function gateEDrift(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
326
283
|
const liveMap = mapContentFingerprint(map.groups, map.dispositions);
|
|
327
284
|
if (map.groups.some((g) => g.review === 'approved')) {
|
|
328
285
|
if (!stampedMap) {
|
|
329
|
-
|
|
330
|
-
gate: 'E', severity: 'review',
|
|
331
|
-
message: 'the delivery map has no stamped content fingerprint — run `sungen delivery --approve` to record the reviewed wording',
|
|
332
|
-
});
|
|
286
|
+
report('matrix.gate-e.map-unstamped', 'E', 'the delivery map has no stamped content fingerprint — run `sungen delivery --approve` to record the reviewed wording');
|
|
333
287
|
} else if (stampedMap !== liveMap) {
|
|
334
|
-
|
|
335
|
-
gate: 'E', severity: 'review',
|
|
336
|
-
message: 'the delivery map wording/grouping changed since approval — re-review, then `sungen delivery --approve`',
|
|
337
|
-
});
|
|
288
|
+
report('matrix.gate-e.map-drift', 'E', 'the delivery map wording/grouping changed since approval — re-review, then `sungen delivery --approve`');
|
|
338
289
|
}
|
|
339
290
|
}
|
|
340
291
|
|
|
@@ -345,15 +296,9 @@ function gateEDrift(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
345
296
|
for (const v of vs) {
|
|
346
297
|
const stamped = map.fingerprints[v.ref] ?? map.fingerprints[v.vpId];
|
|
347
298
|
if (!stamped) {
|
|
348
|
-
|
|
349
|
-
gate: 'E', severity: 'review', ref: g.id,
|
|
350
|
-
message: `group ${g.id}: ${v.ref} has no stamped fingerprint — run \`sungen delivery --approve\` after review`,
|
|
351
|
-
});
|
|
299
|
+
report('matrix.gate-e.variant-unstamped', 'E', `group ${g.id}: ${v.ref} has no stamped fingerprint — run \`sungen delivery --approve\` after review`, g.id);
|
|
352
300
|
} else if (stamped !== v.fingerprint) {
|
|
353
|
-
|
|
354
|
-
gate: 'E', severity: 'review', ref: g.id,
|
|
355
|
-
message: `group ${g.id}: ${v.ref} changed since approval (fingerprint drift) — re-review the grouping`,
|
|
356
|
-
});
|
|
301
|
+
report('matrix.gate-e.variant-drift', 'E', `group ${g.id}: ${v.ref} changed since approval (fingerprint drift) — re-review the grouping`, g.id);
|
|
357
302
|
}
|
|
358
303
|
}
|
|
359
304
|
}
|
|
@@ -370,30 +315,21 @@ const WORDING_SMELLS: Array<[RegExp, string]> = [
|
|
|
370
315
|
[/\[[^\]]+\]/, 'a [selector-style] reference — use the visible UI label'],
|
|
371
316
|
];
|
|
372
317
|
|
|
373
|
-
function gateWWording(ctx: GateContext,
|
|
318
|
+
function gateWWording(ctx: GateContext, report: ReportFinding): void {
|
|
374
319
|
for (const g of ctx.inputs.map.groups) {
|
|
375
320
|
const variantCount = g.variants.flatMap((ref) => expandMapRef(ref, ctx.variantsByVp)).length;
|
|
376
321
|
// Without a digest the parent row can only list variant refs — a reviewer
|
|
377
322
|
// then has to expand the item to learn which dimensions it covers.
|
|
378
323
|
if (variantCount > 3 && !g.dimensions) {
|
|
379
|
-
|
|
380
|
-
gate: 'W', severity: 'warning', ref: g.id,
|
|
381
|
-
message: `group ${g.id} has ${variantCount} variants and no \`dimensions:\` digest — add a short one (e.g. "required ×3 · format ×9") so the collapsed view stays informative`,
|
|
382
|
-
});
|
|
324
|
+
report('matrix.gate-w.dimensions-missing', 'W', `group ${g.id} has ${variantCount} variants and no \`dimensions:\` digest — add a short one (e.g. "required ×3 · format ×9") so the collapsed view stays informative`, g.id);
|
|
383
325
|
}
|
|
384
326
|
if (g.dimensions && g.dimensions.length > 120) {
|
|
385
|
-
|
|
386
|
-
gate: 'W', severity: 'warning', ref: g.id,
|
|
387
|
-
message: `group ${g.id} \`dimensions:\` is ${g.dimensions.length} chars — keep the digest short (≤120)`,
|
|
388
|
-
});
|
|
327
|
+
report('matrix.gate-w.dimensions-long', 'W', `group ${g.id} \`dimensions:\` is ${g.dimensions.length} chars — keep the digest short (≤120)`, g.id);
|
|
389
328
|
}
|
|
390
329
|
for (const [field, text] of ([['intent', g.intent], ['oracle', g.oracle], ...(g.dimensions ? [['dimensions', g.dimensions] as const] : [])] as const)) {
|
|
391
330
|
for (const [re, what] of WORDING_SMELLS) {
|
|
392
331
|
if (re.test(text)) {
|
|
393
|
-
|
|
394
|
-
gate: 'W', severity: 'warning', ref: g.id,
|
|
395
|
-
message: `group ${g.id} ${field} contains ${what}`,
|
|
396
|
-
});
|
|
332
|
+
report('matrix.gate-w.wording-smell', 'W', `group ${g.id} ${field} contains ${what}`, g.id);
|
|
397
333
|
}
|
|
398
334
|
}
|
|
399
335
|
}
|
|
@@ -402,12 +338,9 @@ function gateWWording(ctx: GateContext, findings: MatrixFinding[]): void {
|
|
|
402
338
|
|
|
403
339
|
// --- Gate G — review state -----------------------------------------------------
|
|
404
340
|
|
|
405
|
-
function gateGReviewState(ctx: GateContext,
|
|
341
|
+
function gateGReviewState(ctx: GateContext, report: ReportFinding): void {
|
|
406
342
|
const proposed = ctx.inputs.map.groups.filter((g) => g.review !== 'approved');
|
|
407
343
|
if (proposed.length > 0) {
|
|
408
|
-
|
|
409
|
-
gate: 'G', severity: 'review',
|
|
410
|
-
message: `${proposed.length} group(s) still \`proposed\` (${proposed.slice(0, 5).map((g) => g.id).join(', ')}${proposed.length > 5 ? ', …' : ''}) — approve them or render with --preview`,
|
|
411
|
-
});
|
|
344
|
+
report('matrix.gate-g.groups-proposed', 'G', `${proposed.length} group(s) still \`proposed\` (${proposed.slice(0, 5).map((g) => g.id).join(', ')}${proposed.length > 5 ? ', …' : ''}) — approve them or render with --preview`);
|
|
412
345
|
}
|
|
413
346
|
}
|
|
@@ -11,6 +11,7 @@ import { variantState } from './build';
|
|
|
11
11
|
import { coverageSummary, itemModeLabel, itemResultLabel } from './render-xlsx';
|
|
12
12
|
import { MatrixModel } from './types';
|
|
13
13
|
import { formatTestOutcome, resultTotals } from './result-totals';
|
|
14
|
+
import { overrideManifestLines } from '../../harness/gates/gate-override-report';
|
|
14
15
|
|
|
15
16
|
const HEADERS = [
|
|
16
17
|
'Level', 'ID', 'Target', 'Test Intent / Condition', 'Category', 'Priority',
|
|
@@ -36,6 +37,8 @@ export function renderMatrixCsv(model: MatrixModel): string {
|
|
|
36
37
|
lines.push(`# Test Case & Coverage Matrix — ${model.unit}`);
|
|
37
38
|
// Two different facts, two different words: the map's design REVIEW state, and the runs' OUTCOME.
|
|
38
39
|
lines.push(`# delivery items: ${model.manifest.itemCount} · coverage variants: ${model.manifest.variantCount} · review: ${model.manifest.approvalState} (design) · test outcome: ${formatTestOutcome(resultTotals(model.items))}`);
|
|
40
|
+
// OES-11.6: a CSV-only reader still learns which client-visible gate overrides the delivery leaned on.
|
|
41
|
+
lines.push(...overrideManifestLines(model.gateOverrides));
|
|
39
42
|
lines.push(HEADERS.map(esc).join(','));
|
|
40
43
|
|
|
41
44
|
for (const item of model.items) {
|
|
@@ -78,7 +81,7 @@ export function renderMatrixCsv(model: MatrixModel): string {
|
|
|
78
81
|
v.mode === 'manual' ? 'Manual' : 'Auto',
|
|
79
82
|
v.traces.join(' '),
|
|
80
83
|
variantState(v),
|
|
81
|
-
isoDate(v.result?.startTime),
|
|
84
|
+
v.manualDate ?? isoDate(v.result?.startTime),
|
|
82
85
|
// Redact BEFORE clipping — a clip boundary must never split a secret in
|
|
83
86
|
// a way that lets its prefix through. Same denylist as the Note column.
|
|
84
87
|
v.result?.error ? clipNoteField(redactSecrets(String(v.result.error), model.secretValues)) : '',
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sheet 5 — "Gate overrides" (OES-11.6): which quality gate a human relaxed for this unit, why, and
|
|
3
|
+
* whether the delivery leaned on it (`PASS (overridden)`). Present only when a gate-override touches
|
|
4
|
+
* the unit, so a workbook without overrides is unchanged.
|
|
5
|
+
*
|
|
6
|
+
* `visibility: internal` decisions never reach this sheet — the model carries only client-visible
|
|
7
|
+
* rows plus a count of the withheld ones (red-team #14).
|
|
8
|
+
*/
|
|
9
|
+
import * as ExcelJS from 'exceljs';
|
|
10
|
+
import { MatrixModel } from './types';
|
|
11
|
+
import { dataCell, headerCell } from './xlsx-cells';
|
|
12
|
+
|
|
13
|
+
export const GATE_OVERRIDES_SHEET = 'Gate overrides';
|
|
14
|
+
|
|
15
|
+
const COLUMNS: Array<{ label: string; width: number }> = [
|
|
16
|
+
{ label: 'Rule', width: 34 }, { label: 'Catalog level', width: 13 }, { label: 'Override level', width: 14 },
|
|
17
|
+
{ label: 'Scope', width: 22 }, { label: 'Status', width: 12 }, { label: 'Changed an outcome', width: 12 },
|
|
18
|
+
{ label: 'Reason', width: 60 }, { label: 'Decision', width: 20 }, { label: 'Recorded by', width: 18 }, { label: 'Recorded at', width: 24 },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
export function addGateOverridesSheet(wb: ExcelJS.Workbook, model: MatrixModel): void {
|
|
22
|
+
const o = model.gateOverrides;
|
|
23
|
+
if (!o) return;
|
|
24
|
+
const ws = wb.addWorksheet(GATE_OVERRIDES_SHEET);
|
|
25
|
+
COLUMNS.forEach((c, i) => { ws.getColumn(i + 1).width = c.width; });
|
|
26
|
+
ws.getCell('A1').value = 'Gate status';
|
|
27
|
+
ws.getCell('A1').font = { bold: true };
|
|
28
|
+
ws.getCell('B1').value = o.status;
|
|
29
|
+
ws.getCell('B1').font = { bold: true };
|
|
30
|
+
ws.getCell('A2').value = 'Internal decisions (counted, not listed)';
|
|
31
|
+
ws.getCell('B2').value = o.internalCount;
|
|
32
|
+
const header = ws.getRow(4);
|
|
33
|
+
COLUMNS.forEach((c, i) => headerCell(header.getCell(i + 1), c.label));
|
|
34
|
+
o.rows.forEach((r, n) => {
|
|
35
|
+
const row = ws.getRow(5 + n);
|
|
36
|
+
[r.rule, r.catalogSeverity ?? '', r.severity, r.scope, r.status, r.triggered ? 'yes' : 'no', r.reason, r.decisionId, r.by, r.validFrom]
|
|
37
|
+
.forEach((v, i) => dataCell(row.getCell(i + 1), v));
|
|
38
|
+
});
|
|
39
|
+
let next = 5 + o.rows.length;
|
|
40
|
+
if (o.rows.length === 0) ws.getCell(`A${next++}`).value = 'No client-visible gate override.';
|
|
41
|
+
const a = o.acceptedInRun;
|
|
42
|
+
if (a) {
|
|
43
|
+
// L5: who accepted decisions recorded during the run, on a terminal, for this delivery.
|
|
44
|
+
ws.getCell(`A${next + 1}`).value = 'In-run decisions accepted';
|
|
45
|
+
ws.getCell(`A${next + 1}`).font = { bold: true };
|
|
46
|
+
ws.getCell(`B${next + 1}`).value = `by ${a.by} at ${a.at}`;
|
|
47
|
+
ws.getCell(`A${next + 2}`).value = 'Decisions';
|
|
48
|
+
ws.getCell(`B${next + 2}`).value = [a.ids.join(', '), a.internalCount ? `${a.internalCount} internal (ids withheld)` : ''].filter(Boolean).join(' · ') || '—';
|
|
49
|
+
}
|
|
50
|
+
}
|