@sun-asterisk/sungen 3.2.34 → 3.3.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/basis/anchor-grammar.d.ts +32 -0
- package/dist/basis/anchor-grammar.d.ts.map +1 -0
- package/dist/basis/anchor-grammar.js +82 -0
- package/dist/basis/anchor-grammar.js.map +1 -0
- package/dist/basis/anchor-hash.d.ts +6 -0
- package/dist/basis/anchor-hash.d.ts.map +1 -0
- package/dist/basis/anchor-hash.js +28 -0
- package/dist/basis/anchor-hash.js.map +1 -0
- package/dist/basis/bm51-tables.d.ts +20 -0
- package/dist/basis/bm51-tables.d.ts.map +1 -0
- package/dist/basis/bm51-tables.js +71 -0
- package/dist/basis/bm51-tables.js.map +1 -0
- package/dist/basis/extract-spec-anchors.d.ts +39 -0
- package/dist/basis/extract-spec-anchors.d.ts.map +1 -0
- package/dist/basis/extract-spec-anchors.js +81 -0
- package/dist/basis/extract-spec-anchors.js.map +1 -0
- package/dist/basis/migration-sentinel.d.ts +47 -0
- package/dist/basis/migration-sentinel.d.ts.map +1 -0
- package/dist/basis/migration-sentinel.js +219 -0
- package/dist/basis/migration-sentinel.js.map +1 -0
- package/dist/basis/spec-frontmatter.d.ts +18 -0
- package/dist/basis/spec-frontmatter.d.ts.map +1 -0
- package/dist/basis/spec-frontmatter.js +55 -0
- package/dist/basis/spec-frontmatter.js.map +1 -0
- package/dist/basis/spec-sections.d.ts +18 -0
- package/dist/basis/spec-sections.d.ts.map +1 -0
- package/dist/basis/spec-sections.js +27 -0
- package/dist/basis/spec-sections.js.map +1 -0
- package/dist/basis/test-basis-schema.d.ts +28 -0
- package/dist/basis/test-basis-schema.d.ts.map +1 -0
- package/dist/basis/test-basis-schema.js +141 -0
- package/dist/basis/test-basis-schema.js.map +1 -0
- package/dist/capabilities/discover.d.ts +4 -0
- package/dist/capabilities/discover.d.ts.map +1 -1
- package/dist/capabilities/discover.js +16 -2
- package/dist/capabilities/discover.js.map +1 -1
- package/dist/capabilities/registry.d.ts +15 -0
- package/dist/capabilities/registry.d.ts.map +1 -1
- package/dist/capabilities/registry.js.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +10 -5
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/capability.d.ts.map +1 -1
- package/dist/cli/commands/capability.js +6 -2
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/contract-derive-command.d.ts +11 -0
- package/dist/cli/commands/contract-derive-command.d.ts.map +1 -0
- package/dist/cli/commands/contract-derive-command.js +99 -0
- package/dist/cli/commands/contract-derive-command.js.map +1 -0
- package/dist/cli/commands/contract.d.ts +17 -0
- package/dist/cli/commands/contract.d.ts.map +1 -0
- package/dist/cli/commands/contract.js +162 -0
- package/dist/cli/commands/contract.js.map +1 -0
- package/dist/cli/commands/defect.d.ts +7 -0
- package/dist/cli/commands/defect.d.ts.map +1 -0
- package/dist/cli/commands/defect.js +68 -0
- package/dist/cli/commands/defect.js.map +1 -0
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +96 -12
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +3 -1
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/journey.d.ts.map +1 -1
- package/dist/cli/commands/journey.js +43 -15
- package/dist/cli/commands/journey.js.map +1 -1
- package/dist/cli/commands/next.d.ts +8 -0
- package/dist/cli/commands/next.d.ts.map +1 -1
- package/dist/cli/commands/next.js +68 -8
- package/dist/cli/commands/next.js.map +1 -1
- package/dist/cli/commands/triage.d.ts +7 -0
- package/dist/cli/commands/triage.d.ts.map +1 -0
- package/dist/cli/commands/triage.js +98 -0
- package/dist/cli/commands/triage.js.map +1 -0
- package/dist/cli/commands/update.d.ts +11 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +31 -6
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/index.js +24 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/project-sungen-invocation.d.ts +7 -0
- package/dist/cli/project-sungen-invocation.d.ts.map +1 -0
- package/dist/cli/project-sungen-invocation.js +76 -0
- package/dist/cli/project-sungen-invocation.js.map +1 -0
- package/dist/contract/approve-contract.d.ts +31 -0
- package/dist/contract/approve-contract.d.ts.map +1 -0
- package/dist/contract/approve-contract.js +87 -0
- package/dist/contract/approve-contract.js.map +1 -0
- package/dist/contract/assertion-matcher-vocabulary.d.ts +24 -0
- package/dist/contract/assertion-matcher-vocabulary.d.ts.map +1 -0
- package/dist/contract/assertion-matcher-vocabulary.js +100 -0
- package/dist/contract/assertion-matcher-vocabulary.js.map +1 -0
- package/dist/contract/build-contract-verdict.d.ts +32 -0
- package/dist/contract/build-contract-verdict.d.ts.map +1 -0
- package/dist/contract/build-contract-verdict.js +123 -0
- package/dist/contract/build-contract-verdict.js.map +1 -0
- package/dist/contract/build-trace-conformance.d.ts +18 -0
- package/dist/contract/build-trace-conformance.d.ts.map +1 -0
- package/dist/contract/build-trace-conformance.js +153 -0
- package/dist/contract/build-trace-conformance.js.map +1 -0
- package/dist/contract/classify-contract-change.d.ts +23 -0
- package/dist/contract/classify-contract-change.d.ts.map +1 -0
- package/dist/contract/classify-contract-change.js +98 -0
- package/dist/contract/classify-contract-change.js.map +1 -0
- package/dist/contract/classify-contract-unit.d.ts +18 -0
- package/dist/contract/classify-contract-unit.d.ts.map +1 -0
- package/dist/contract/classify-contract-unit.js +49 -0
- package/dist/contract/classify-contract-unit.js.map +1 -0
- package/dist/contract/classify-trace-conformance.d.ts +32 -0
- package/dist/contract/classify-trace-conformance.d.ts.map +1 -0
- package/dist/contract/classify-trace-conformance.js +117 -0
- package/dist/contract/classify-trace-conformance.js.map +1 -0
- package/dist/contract/contract-git.d.ts +24 -0
- package/dist/contract/contract-git.d.ts.map +1 -0
- package/dist/contract/contract-git.js +144 -0
- package/dist/contract/contract-git.js.map +1 -0
- package/dist/contract/contract-hash.d.ts +7 -0
- package/dist/contract/contract-hash.d.ts.map +1 -0
- package/dist/contract/contract-hash.js +38 -0
- package/dist/contract/contract-hash.js.map +1 -0
- package/dist/contract/contract-report-file.d.ts +4 -0
- package/dist/contract/contract-report-file.d.ts.map +1 -0
- package/dist/contract/contract-report-file.js +60 -0
- package/dist/contract/contract-report-file.js.map +1 -0
- package/dist/contract/contract-schema.d.ts +71 -0
- package/dist/contract/contract-schema.d.ts.map +1 -0
- package/dist/contract/contract-schema.js +102 -0
- package/dist/contract/contract-schema.js.map +1 -0
- package/dist/contract/contract-units.d.ts +12 -0
- package/dist/contract/contract-units.d.ts.map +1 -0
- package/dist/contract/contract-units.js +96 -0
- package/dist/contract/contract-units.js.map +1 -0
- package/dist/contract/contracts-lock-file.d.ts +24 -0
- package/dist/contract/contracts-lock-file.d.ts.map +1 -0
- package/dist/contract/contracts-lock-file.js +140 -0
- package/dist/contract/contracts-lock-file.js.map +1 -0
- package/dist/contract/data-normalize.d.ts +10 -0
- package/dist/contract/data-normalize.d.ts.map +1 -0
- package/dist/contract/data-normalize.js +110 -0
- package/dist/contract/data-normalize.js.map +1 -0
- package/dist/contract/derive-free-feature.d.ts +38 -0
- package/dist/contract/derive-free-feature.d.ts.map +1 -0
- package/dist/contract/derive-free-feature.js +154 -0
- package/dist/contract/derive-free-feature.js.map +1 -0
- package/dist/contract/field-semantic-redaction.d.ts +21 -0
- package/dist/contract/field-semantic-redaction.d.ts.map +1 -0
- package/dist/contract/field-semantic-redaction.js +118 -0
- package/dist/contract/field-semantic-redaction.js.map +1 -0
- package/dist/contract/free-feature-blocks.d.ts +10 -0
- package/dist/contract/free-feature-blocks.d.ts.map +1 -0
- package/dist/contract/free-feature-blocks.js +94 -0
- package/dist/contract/free-feature-blocks.js.map +1 -0
- package/dist/contract/lock-secret-guard.d.ts +22 -0
- package/dist/contract/lock-secret-guard.d.ts.map +1 -0
- package/dist/contract/lock-secret-guard.js +134 -0
- package/dist/contract/lock-secret-guard.js.map +1 -0
- package/dist/contract/lock-vs-git-head.d.ts +26 -0
- package/dist/contract/lock-vs-git-head.d.ts.map +1 -0
- package/dist/contract/lock-vs-git-head.js +28 -0
- package/dist/contract/lock-vs-git-head.js.map +1 -0
- package/dist/contract/normalize-contract-step.d.ts +21 -0
- package/dist/contract/normalize-contract-step.d.ts.map +1 -0
- package/dist/contract/normalize-contract-step.js +70 -0
- package/dist/contract/normalize-contract-step.js.map +1 -0
- package/dist/contract/normalize-feature-steps.d.ts +7 -0
- package/dist/contract/normalize-feature-steps.d.ts.map +1 -0
- package/dist/contract/normalize-feature-steps.js +127 -0
- package/dist/contract/normalize-feature-steps.js.map +1 -0
- package/dist/contract/oracle-strength.d.ts +12 -0
- package/dist/contract/oracle-strength.d.ts.map +1 -0
- package/dist/contract/oracle-strength.js +88 -0
- package/dist/contract/oracle-strength.js.map +1 -0
- package/dist/contract/project-contract-blockers.d.ts +10 -0
- package/dist/contract/project-contract-blockers.d.ts.map +1 -0
- package/dist/contract/project-contract-blockers.js +73 -0
- package/dist/contract/project-contract-blockers.js.map +1 -0
- package/dist/contract/record-contract-approval.d.ts +21 -0
- package/dist/contract/record-contract-approval.d.ts.map +1 -0
- package/dist/contract/record-contract-approval.js +98 -0
- package/dist/contract/record-contract-approval.js.map +1 -0
- package/dist/contract/render-free-gherkin.d.ts +40 -0
- package/dist/contract/render-free-gherkin.d.ts.map +1 -0
- package/dist/contract/render-free-gherkin.js +141 -0
- package/dist/contract/render-free-gherkin.js.map +1 -0
- package/dist/contract/render-trace-sentence.d.ts +20 -0
- package/dist/contract/render-trace-sentence.d.ts.map +1 -0
- package/dist/contract/render-trace-sentence.js +109 -0
- package/dist/contract/render-trace-sentence.js.map +1 -0
- package/dist/contract/render-trace-target.d.ts +14 -0
- package/dist/contract/render-trace-target.d.ts.map +1 -0
- package/dist/contract/render-trace-target.js +70 -0
- package/dist/contract/render-trace-target.js.map +1 -0
- package/dist/contract/resolve-unit-trace-identities.d.ts +8 -0
- package/dist/contract/resolve-unit-trace-identities.d.ts.map +1 -0
- package/dist/contract/resolve-unit-trace-identities.js +78 -0
- package/dist/contract/resolve-unit-trace-identities.js.map +1 -0
- package/dist/contract/trace/collect-trace-evidence.d.ts +33 -0
- package/dist/contract/trace/collect-trace-evidence.d.ts.map +1 -0
- package/dist/contract/trace/collect-trace-evidence.js +161 -0
- package/dist/contract/trace/collect-trace-evidence.js.map +1 -0
- package/dist/contract/trace/identity-cache.d.ts +19 -0
- package/dist/contract/trace/identity-cache.d.ts.map +1 -0
- package/dist/contract/trace/identity-cache.js +104 -0
- package/dist/contract/trace/identity-cache.js.map +1 -0
- package/dist/contract/trace/select-final-attempt.d.ts +27 -0
- package/dist/contract/trace/select-final-attempt.d.ts.map +1 -0
- package/dist/contract/trace/select-final-attempt.js +116 -0
- package/dist/contract/trace/select-final-attempt.js.map +1 -0
- package/dist/contract/trace/snapshot-html-renderer.d.ts +31 -0
- package/dist/contract/trace/snapshot-html-renderer.d.ts.map +1 -0
- package/dist/contract/trace/snapshot-html-renderer.js +172 -0
- package/dist/contract/trace/snapshot-html-renderer.js.map +1 -0
- package/dist/contract/trace/snapshot-resolver.d.ts +21 -0
- package/dist/contract/trace/snapshot-resolver.d.ts.map +1 -0
- package/dist/contract/trace/snapshot-resolver.js +65 -0
- package/dist/contract/trace/snapshot-resolver.js.map +1 -0
- package/dist/contract/trace/snapshot-store.d.ts +66 -0
- package/dist/contract/trace/snapshot-store.d.ts.map +1 -0
- package/dist/contract/trace/snapshot-store.js +173 -0
- package/dist/contract/trace/snapshot-store.js.map +1 -0
- package/dist/contract/trace/target-identity.d.ts +74 -0
- package/dist/contract/trace/target-identity.d.ts.map +1 -0
- package/dist/contract/trace/target-identity.js +68 -0
- package/dist/contract/trace/target-identity.js.map +1 -0
- package/dist/contract/trace/test-step-join.d.ts +65 -0
- package/dist/contract/trace/test-step-join.d.ts.map +1 -0
- package/dist/contract/trace/test-step-join.js +80 -0
- package/dist/contract/trace/test-step-join.js.map +1 -0
- package/dist/contract/trace/trace-binding.d.ts +21 -0
- package/dist/contract/trace/trace-binding.d.ts.map +1 -0
- package/dist/contract/trace/trace-binding.js +88 -0
- package/dist/contract/trace/trace-binding.js.map +1 -0
- package/dist/contract/trace/trace-file-reader.d.ts +41 -0
- package/dist/contract/trace/trace-file-reader.d.ts.map +1 -0
- package/dist/contract/trace/trace-file-reader.js +161 -0
- package/dist/contract/trace/trace-file-reader.js.map +1 -0
- package/dist/contract/trace/trace-fingerprint.d.ts +22 -0
- package/dist/contract/trace/trace-fingerprint.d.ts.map +1 -0
- package/dist/contract/trace/trace-fingerprint.js +96 -0
- package/dist/contract/trace/trace-fingerprint.js.map +1 -0
- package/dist/contract/trace/trace-identity-resolution.d.ts +26 -0
- package/dist/contract/trace/trace-identity-resolution.d.ts.map +1 -0
- package/dist/contract/trace/trace-identity-resolution.js +84 -0
- package/dist/contract/trace/trace-identity-resolution.js.map +1 -0
- package/dist/contract/trace/trace-run-record.d.ts +30 -0
- package/dist/contract/trace/trace-run-record.d.ts.map +1 -0
- package/dist/contract/trace/trace-run-record.js +121 -0
- package/dist/contract/trace/trace-run-record.js.map +1 -0
- package/dist/contract/trace/trace-steps.d.ts +19 -0
- package/dist/contract/trace/trace-steps.d.ts.map +1 -0
- package/dist/contract/trace/trace-steps.js +79 -0
- package/dist/contract/trace/trace-steps.js.map +1 -0
- package/dist/contract/trace/trace-zip-limits.d.ts +45 -0
- package/dist/contract/trace/trace-zip-limits.d.ts.map +1 -0
- package/dist/contract/trace/trace-zip-limits.js +52 -0
- package/dist/contract/trace/trace-zip-limits.js.map +1 -0
- package/dist/contract/trace/trace-zip-reader.d.ts +10 -0
- package/dist/contract/trace/trace-zip-reader.d.ts.map +1 -0
- package/dist/contract/trace/trace-zip-reader.js +186 -0
- package/dist/contract/trace/trace-zip-reader.js.map +1 -0
- package/dist/contract/verify-approval-decisions.d.ts +5 -0
- package/dist/contract/verify-approval-decisions.d.ts.map +1 -0
- package/dist/contract/verify-approval-decisions.js +104 -0
- package/dist/contract/verify-approval-decisions.js.map +1 -0
- package/dist/decisions/append-decision.d.ts +12 -0
- package/dist/decisions/append-decision.d.ts.map +1 -0
- package/dist/decisions/append-decision.js +73 -0
- package/dist/decisions/append-decision.js.map +1 -0
- package/dist/decisions/confirmed-decision-commands.d.ts +41 -0
- package/dist/decisions/confirmed-decision-commands.d.ts.map +1 -0
- package/dist/decisions/confirmed-decision-commands.js +190 -0
- package/dist/decisions/confirmed-decision-commands.js.map +1 -0
- package/dist/decisions/decision-file.d.ts +31 -0
- package/dist/decisions/decision-file.d.ts.map +1 -0
- package/dist/decisions/decision-file.js +139 -0
- package/dist/decisions/decision-file.js.map +1 -0
- package/dist/decisions/decision-identity.d.ts +12 -0
- package/dist/decisions/decision-identity.d.ts.map +1 -0
- package/dist/decisions/decision-identity.js +78 -0
- package/dist/decisions/decision-identity.js.map +1 -0
- package/dist/decisions/decision-integrity-check.d.ts +12 -0
- package/dist/decisions/decision-integrity-check.d.ts.map +1 -0
- package/dist/decisions/decision-integrity-check.js +102 -0
- package/dist/decisions/decision-integrity-check.js.map +1 -0
- package/dist/decisions/decision-schema.d.ts +42 -0
- package/dist/decisions/decision-schema.d.ts.map +1 -0
- package/dist/decisions/decision-schema.js +75 -0
- package/dist/decisions/decision-schema.js.map +1 -0
- package/dist/decisions/decision-source.d.ts +2 -0
- package/dist/decisions/decision-source.d.ts.map +1 -0
- package/dist/decisions/decision-source.js +18 -0
- package/dist/decisions/decision-source.js.map +1 -0
- package/dist/decisions/exclusive-file-create.d.ts +3 -0
- package/dist/decisions/exclusive-file-create.d.ts.map +1 -0
- package/dist/decisions/exclusive-file-create.js +84 -0
- package/dist/decisions/exclusive-file-create.js.map +1 -0
- package/dist/decisions/git-head-trust.d.ts +7 -0
- package/dist/decisions/git-head-trust.d.ts.map +1 -0
- package/dist/decisions/git-head-trust.js +76 -0
- package/dist/decisions/git-head-trust.js.map +1 -0
- package/dist/decisions/human-confirmation.d.ts +35 -0
- package/dist/decisions/human-confirmation.d.ts.map +1 -0
- package/dist/decisions/human-confirmation.js +161 -0
- package/dist/decisions/human-confirmation.js.map +1 -0
- package/dist/decisions/legacy-waiver-migration.d.ts +31 -0
- package/dist/decisions/legacy-waiver-migration.d.ts.map +1 -0
- package/dist/decisions/legacy-waiver-migration.js +170 -0
- package/dist/decisions/legacy-waiver-migration.js.map +1 -0
- package/dist/decisions/read-decisions.d.ts +19 -0
- package/dist/decisions/read-decisions.d.ts.map +1 -0
- package/dist/decisions/read-decisions.js +90 -0
- package/dist/decisions/read-decisions.js.map +1 -0
- package/dist/decisions/viewpoint-baseline-adapter.d.ts +7 -0
- package/dist/decisions/viewpoint-baseline-adapter.d.ts.map +1 -0
- package/dist/decisions/viewpoint-baseline-adapter.js +109 -0
- package/dist/decisions/viewpoint-baseline-adapter.js.map +1 -0
- package/dist/decisions/waiver-decisions.d.ts +24 -0
- package/dist/decisions/waiver-decisions.d.ts.map +1 -0
- package/dist/decisions/waiver-decisions.js +46 -0
- package/dist/decisions/waiver-decisions.js.map +1 -0
- package/dist/exporters/csv-exporter.d.ts +4 -0
- package/dist/exporters/csv-exporter.d.ts.map +1 -1
- package/dist/exporters/csv-exporter.js +1 -1
- package/dist/exporters/csv-exporter.js.map +1 -1
- package/dist/exporters/feature-parser.d.ts +8 -0
- package/dist/exporters/feature-parser.d.ts.map +1 -1
- package/dist/exporters/feature-parser.js +12 -0
- package/dist/exporters/feature-parser.js.map +1 -1
- package/dist/exporters/matrix/build.d.ts +3 -0
- package/dist/exporters/matrix/build.d.ts.map +1 -1
- package/dist/exporters/matrix/build.js +59 -19
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/carry-manual-results.d.ts +19 -0
- package/dist/exporters/matrix/carry-manual-results.d.ts.map +1 -1
- package/dist/exporters/matrix/carry-manual-results.js +76 -6
- package/dist/exporters/matrix/carry-manual-results.js.map +1 -1
- package/dist/exporters/matrix/export.d.ts +8 -2
- package/dist/exporters/matrix/export.d.ts.map +1 -1
- package/dist/exporters/matrix/export.js +16 -3
- package/dist/exporters/matrix/export.js.map +1 -1
- package/dist/exporters/matrix/gates.d.ts +6 -1
- package/dist/exporters/matrix/gates.d.ts.map +1 -1
- package/dist/exporters/matrix/gates.js +57 -128
- package/dist/exporters/matrix/gates.js.map +1 -1
- package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
- package/dist/exporters/matrix/render-csv.js +4 -1
- package/dist/exporters/matrix/render-csv.js.map +1 -1
- package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts +13 -0
- package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts.map +1 -0
- package/dist/exporters/matrix/render-gate-overrides-sheet.js +44 -0
- package/dist/exporters/matrix/render-gate-overrides-sheet.js.map +1 -0
- package/dist/exporters/matrix/render-xlsx.d.ts +1 -0
- package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
- package/dist/exporters/matrix/render-xlsx.js +6 -0
- package/dist/exporters/matrix/render-xlsx.js.map +1 -1
- package/dist/exporters/matrix/types.d.ts +9 -1
- package/dist/exporters/matrix/types.d.ts.map +1 -1
- package/dist/exporters/matrix/types.js.map +1 -1
- package/dist/exporters/matrix/xlsx-cells.js +1 -1
- package/dist/exporters/matrix/xlsx-cells.js.map +1 -1
- package/dist/exporters/playwright-report-parser.d.ts.map +1 -1
- package/dist/exporters/playwright-report-parser.js +1 -0
- package/dist/exporters/playwright-report-parser.js.map +1 -1
- package/dist/exporters/scenario-merger.d.ts.map +1 -1
- package/dist/exporters/scenario-merger.js +2 -0
- package/dist/exporters/scenario-merger.js.map +1 -1
- package/dist/exporters/types.d.ts +5 -0
- package/dist/exporters/types.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +13 -0
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/graph/evaluate-graph.d.ts +23 -0
- package/dist/graph/evaluate-graph.d.ts.map +1 -0
- package/dist/graph/evaluate-graph.js +52 -0
- package/dist/graph/evaluate-graph.js.map +1 -0
- package/dist/graph/locate-finding.d.ts +20 -0
- package/dist/graph/locate-finding.d.ts.map +1 -0
- package/dist/graph/locate-finding.js +137 -0
- package/dist/graph/locate-finding.js.map +1 -0
- package/dist/graph/node-decl.d.ts +66 -0
- package/dist/graph/node-decl.d.ts.map +1 -0
- package/dist/graph/node-decl.js +8 -0
- package/dist/graph/node-decl.js.map +1 -0
- package/dist/graph/nodes/core-node-catalog.d.ts +7 -0
- package/dist/graph/nodes/core-node-catalog.d.ts.map +1 -0
- package/dist/graph/nodes/core-node-catalog.js +13 -0
- package/dist/graph/nodes/core-node-catalog.js.map +1 -0
- package/dist/graph/nodes/test-case-contract-nodes.d.ts +21 -0
- package/dist/graph/nodes/test-case-contract-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/test-case-contract-nodes.js +59 -0
- package/dist/graph/nodes/test-case-contract-nodes.js.map +1 -0
- package/dist/graph/nodes/test-case-nodes.d.ts +26 -0
- package/dist/graph/nodes/test-case-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/test-case-nodes.js +66 -0
- package/dist/graph/nodes/test-case-nodes.js.map +1 -0
- package/dist/graph/nodes/unit-audit-nodes.d.ts +18 -0
- package/dist/graph/nodes/unit-audit-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/unit-audit-nodes.js +95 -0
- package/dist/graph/nodes/unit-audit-nodes.js.map +1 -0
- package/dist/graph/nodes/unit-contract-node.d.ts +21 -0
- package/dist/graph/nodes/unit-contract-node.d.ts.map +1 -0
- package/dist/graph/nodes/unit-contract-node.js +88 -0
- package/dist/graph/nodes/unit-contract-node.js.map +1 -0
- package/dist/graph/nodes/unit-design-nodes.d.ts +14 -0
- package/dist/graph/nodes/unit-design-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/unit-design-nodes.js +91 -0
- package/dist/graph/nodes/unit-design-nodes.js.map +1 -0
- package/dist/graph/nodes/unit-execution-nodes.d.ts +16 -0
- package/dist/graph/nodes/unit-execution-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/unit-execution-nodes.js +79 -0
- package/dist/graph/nodes/unit-execution-nodes.js.map +1 -0
- package/dist/graph/test-case-identity.d.ts +13 -0
- package/dist/graph/test-case-identity.d.ts.map +1 -0
- package/dist/graph/test-case-identity.js +106 -0
- package/dist/graph/test-case-identity.js.map +1 -0
- package/dist/graph/test-case-results.d.ts +11 -0
- package/dist/graph/test-case-results.d.ts.map +1 -0
- package/dist/graph/test-case-results.js +137 -0
- package/dist/graph/test-case-results.js.map +1 -0
- package/dist/graph/test-case-satisfied.d.ts +25 -0
- package/dist/graph/test-case-satisfied.d.ts.map +1 -0
- package/dist/graph/test-case-satisfied.js +51 -0
- package/dist/graph/test-case-satisfied.js.map +1 -0
- package/dist/graph/test-case-state-shape.d.ts +67 -0
- package/dist/graph/test-case-state-shape.d.ts.map +1 -0
- package/dist/graph/test-case-state-shape.js +3 -0
- package/dist/graph/test-case-state-shape.js.map +1 -0
- package/dist/graph/test-case-states.d.ts +9 -0
- package/dist/graph/test-case-states.d.ts.map +1 -0
- package/dist/graph/test-case-states.js +116 -0
- package/dist/graph/test-case-states.js.map +1 -0
- package/dist/graph/unit-artifact-probes.d.ts +19 -0
- package/dist/graph/unit-artifact-probes.d.ts.map +1 -0
- package/dist/graph/unit-artifact-probes.js +133 -0
- package/dist/graph/unit-artifact-probes.js.map +1 -0
- package/dist/graph/unit-state-facts.d.ts +43 -0
- package/dist/graph/unit-state-facts.d.ts.map +1 -0
- package/dist/graph/unit-state-facts.js +87 -0
- package/dist/graph/unit-state-facts.js.map +1 -0
- package/dist/harness/audit.d.ts +11 -0
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +34 -9
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/catalog/gate-rules.yaml +647 -0
- package/dist/harness/counted-assertions.d.ts +2 -0
- package/dist/harness/counted-assertions.d.ts.map +1 -0
- package/dist/harness/counted-assertions.js +38 -0
- package/dist/harness/counted-assertions.js.map +1 -0
- package/dist/harness/defect-draft.d.ts +14 -0
- package/dist/harness/defect-draft.d.ts.map +1 -0
- package/dist/harness/defect-draft.js +143 -0
- package/dist/harness/defect-draft.js.map +1 -0
- package/dist/harness/defects.d.ts +24 -0
- package/dist/harness/defects.d.ts.map +1 -0
- package/dist/harness/defects.js +118 -0
- package/dist/harness/defects.js.map +1 -0
- package/dist/harness/gates/audit-gate-terms.d.ts +41 -0
- package/dist/harness/gates/audit-gate-terms.d.ts.map +1 -0
- package/dist/harness/gates/audit-gate-terms.js +72 -0
- package/dist/harness/gates/audit-gate-terms.js.map +1 -0
- package/dist/harness/gates/audit-gate-verdict.d.ts +31 -0
- package/dist/harness/gates/audit-gate-verdict.d.ts.map +1 -0
- package/dist/harness/gates/audit-gate-verdict.js +101 -0
- package/dist/harness/gates/audit-gate-verdict.js.map +1 -0
- package/dist/harness/gates/audit-input-hash.d.ts +4 -0
- package/dist/harness/gates/audit-input-hash.d.ts.map +1 -0
- package/dist/harness/gates/audit-input-hash.js +96 -0
- package/dist/harness/gates/audit-input-hash.js.map +1 -0
- package/dist/harness/gates/audit-report-verification.d.ts +41 -0
- package/dist/harness/gates/audit-report-verification.d.ts.map +1 -0
- package/dist/harness/gates/audit-report-verification.js +236 -0
- package/dist/harness/gates/audit-report-verification.js.map +1 -0
- package/dist/harness/gates/decisions-hash.d.ts +13 -0
- package/dist/harness/gates/decisions-hash.d.ts.map +1 -0
- package/dist/harness/gates/decisions-hash.js +72 -0
- package/dist/harness/gates/decisions-hash.js.map +1 -0
- package/dist/harness/gates/delivery-checklist.d.ts +21 -0
- package/dist/harness/gates/delivery-checklist.d.ts.map +1 -0
- package/dist/harness/gates/delivery-checklist.js +128 -0
- package/dist/harness/gates/delivery-checklist.js.map +1 -0
- package/dist/harness/gates/delivery-decision-gate.d.ts +33 -0
- package/dist/harness/gates/delivery-decision-gate.d.ts.map +1 -0
- package/dist/harness/gates/delivery-decision-gate.js +116 -0
- package/dist/harness/gates/delivery-decision-gate.js.map +1 -0
- package/dist/harness/gates/delivery-decision-step.d.ts +19 -0
- package/dist/harness/gates/delivery-decision-step.d.ts.map +1 -0
- package/dist/harness/gates/delivery-decision-step.js +86 -0
- package/dist/harness/gates/delivery-decision-step.js.map +1 -0
- package/dist/harness/gates/gate-override-report.d.ts +59 -0
- package/dist/harness/gates/gate-override-report.d.ts.map +1 -0
- package/dist/harness/gates/gate-override-report.js +86 -0
- package/dist/harness/gates/gate-override-report.js.map +1 -0
- package/dist/harness/gates/gate-override-scope.d.ts +18 -0
- package/dist/harness/gates/gate-override-scope.d.ts.map +1 -0
- package/dist/harness/gates/gate-override-scope.js +98 -0
- package/dist/harness/gates/gate-override-scope.js.map +1 -0
- package/dist/harness/gates/gate-override-validation.d.ts +25 -0
- package/dist/harness/gates/gate-override-validation.d.ts.map +1 -0
- package/dist/harness/gates/gate-override-validation.js +81 -0
- package/dist/harness/gates/gate-override-validation.js.map +1 -0
- package/dist/harness/gates/gate-rule-catalog.d.ts +24 -0
- package/dist/harness/gates/gate-rule-catalog.d.ts.map +1 -0
- package/dist/harness/gates/gate-rule-catalog.js +112 -0
- package/dist/harness/gates/gate-rule-catalog.js.map +1 -0
- package/dist/harness/gates/gate-terms.d.ts +33 -0
- package/dist/harness/gates/gate-terms.d.ts.map +1 -0
- package/dist/harness/gates/gate-terms.js +41 -0
- package/dist/harness/gates/gate-terms.js.map +1 -0
- package/dist/harness/gates/in-run-decision-check.d.ts +21 -0
- package/dist/harness/gates/in-run-decision-check.d.ts.map +1 -0
- package/dist/harness/gates/in-run-decision-check.js +138 -0
- package/dist/harness/gates/in-run-decision-check.js.map +1 -0
- package/dist/harness/gates/journey-gate-inputs.d.ts +37 -0
- package/dist/harness/gates/journey-gate-inputs.d.ts.map +1 -0
- package/dist/harness/gates/journey-gate-inputs.js +81 -0
- package/dist/harness/gates/journey-gate-inputs.js.map +1 -0
- package/dist/harness/gates/migrated-waiver-review.d.ts +6 -0
- package/dist/harness/gates/migrated-waiver-review.d.ts.map +1 -0
- package/dist/harness/gates/migrated-waiver-review.js +116 -0
- package/dist/harness/gates/migrated-waiver-review.js.map +1 -0
- package/dist/harness/gates/resolve-rule.d.ts +59 -0
- package/dist/harness/gates/resolve-rule.d.ts.map +1 -0
- package/dist/harness/gates/resolve-rule.js +41 -0
- package/dist/harness/gates/resolve-rule.js.map +1 -0
- package/dist/harness/gates/unit-gate-overrides.d.ts +25 -0
- package/dist/harness/gates/unit-gate-overrides.d.ts.map +1 -0
- package/dist/harness/gates/unit-gate-overrides.js +122 -0
- package/dist/harness/gates/unit-gate-overrides.js.map +1 -0
- package/dist/harness/journey.d.ts +43 -1
- package/dist/harness/journey.d.ts.map +1 -1
- package/dist/harness/journey.js +207 -33
- package/dist/harness/journey.js.map +1 -1
- package/dist/harness/manifest.d.ts +12 -0
- package/dist/harness/manifest.d.ts.map +1 -1
- package/dist/harness/manifest.js +73 -45
- package/dist/harness/manifest.js.map +1 -1
- package/dist/harness/next-step.d.ts +37 -6
- package/dist/harness/next-step.d.ts.map +1 -1
- package/dist/harness/next-step.js +34 -174
- package/dist/harness/next-step.js.map +1 -1
- package/dist/harness/parse.d.ts +25 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +38 -13
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/provenance.d.ts +29 -0
- package/dist/harness/provenance.d.ts.map +1 -1
- package/dist/harness/provenance.js +109 -9
- package/dist/harness/provenance.js.map +1 -1
- package/dist/harness/script-check.d.ts.map +1 -1
- package/dist/harness/script-check.js +29 -6
- package/dist/harness/script-check.js.map +1 -1
- package/dist/harness/sensors.d.ts +14 -3
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +64 -44
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/triage-signals.d.ts +20 -0
- package/dist/harness/triage-signals.d.ts.map +1 -0
- package/dist/harness/triage-signals.js +30 -0
- package/dist/harness/triage-signals.js.map +1 -0
- package/dist/harness/triage-unit.d.ts +23 -0
- package/dist/harness/triage-unit.d.ts.map +1 -0
- package/dist/harness/triage-unit.js +142 -0
- package/dist/harness/triage-unit.js.map +1 -0
- package/dist/harness/triage.d.ts +28 -0
- package/dist/harness/triage.d.ts.map +1 -0
- package/dist/harness/triage.js +99 -0
- package/dist/harness/triage.js.map +1 -0
- package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
- package/dist/harness/viewpoint-ledger.js +2 -1
- package/dist/harness/viewpoint-ledger.js.map +1 -1
- package/dist/hooks/bash-write-targets.d.ts +15 -0
- package/dist/hooks/bash-write-targets.d.ts.map +1 -0
- package/dist/hooks/bash-write-targets.js +173 -0
- package/dist/hooks/bash-write-targets.js.map +1 -0
- package/dist/hooks/claude-hook-entry.d.ts +11 -0
- package/dist/hooks/claude-hook-entry.d.ts.map +1 -0
- package/dist/hooks/claude-hook-entry.js +137 -0
- package/dist/hooks/claude-hook-entry.js.map +1 -0
- package/dist/hooks/claude-transcript-turn.d.ts +11 -0
- package/dist/hooks/claude-transcript-turn.d.ts.map +1 -0
- package/dist/hooks/claude-transcript-turn.js +143 -0
- package/dist/hooks/claude-transcript-turn.js.map +1 -0
- package/dist/hooks/guard-delivery-contract-rule.d.ts +10 -0
- package/dist/hooks/guard-delivery-contract-rule.d.ts.map +1 -0
- package/dist/hooks/guard-delivery-contract-rule.js +152 -0
- package/dist/hooks/guard-delivery-contract-rule.js.map +1 -0
- package/dist/hooks/guard-protected-paths.d.ts +9 -0
- package/dist/hooks/guard-protected-paths.d.ts.map +1 -0
- package/dist/hooks/guard-protected-paths.js +107 -0
- package/dist/hooks/guard-protected-paths.js.map +1 -0
- package/dist/hooks/guard-rules.d.ts +37 -0
- package/dist/hooks/guard-rules.d.ts.map +1 -0
- package/dist/hooks/guard-rules.js +61 -0
- package/dist/hooks/guard-rules.js.map +1 -0
- package/dist/hooks/guard-tty-spoof-rule.d.ts +15 -0
- package/dist/hooks/guard-tty-spoof-rule.d.ts.map +1 -0
- package/dist/hooks/guard-tty-spoof-rule.js +21 -0
- package/dist/hooks/guard-tty-spoof-rule.js.map +1 -0
- package/dist/hooks/hand-back-core.d.ts +39 -0
- package/dist/hooks/hand-back-core.d.ts.map +1 -0
- package/dist/hooks/hand-back-core.js +122 -0
- package/dist/hooks/hand-back-core.js.map +1 -0
- package/dist/hooks/hook-cli-command.d.ts +9 -0
- package/dist/hooks/hook-cli-command.d.ts.map +1 -0
- package/dist/hooks/hook-cli-command.js +46 -0
- package/dist/hooks/hook-cli-command.js.map +1 -0
- package/dist/hooks/hook-registry.d.ts +10 -0
- package/dist/hooks/hook-registry.d.ts.map +1 -0
- package/dist/hooks/hook-registry.js +24 -0
- package/dist/hooks/hook-registry.js.map +1 -0
- package/dist/hooks/hook-result-contract.d.ts +50 -0
- package/dist/hooks/hook-result-contract.d.ts.map +1 -0
- package/dist/hooks/hook-result-contract.js +80 -0
- package/dist/hooks/hook-result-contract.js.map +1 -0
- package/dist/hooks/hook-toggles.d.ts +10 -0
- package/dist/hooks/hook-toggles.d.ts.map +1 -0
- package/dist/hooks/hook-toggles.js +107 -0
- package/dist/hooks/hook-toggles.js.map +1 -0
- package/dist/hooks/pre-tool-guard-hook.d.ts +10 -0
- package/dist/hooks/pre-tool-guard-hook.d.ts.map +1 -0
- package/dist/hooks/pre-tool-guard-hook.js +105 -0
- package/dist/hooks/pre-tool-guard-hook.js.map +1 -0
- package/dist/hooks/session-start-unit-state-hook.d.ts +13 -0
- package/dist/hooks/session-start-unit-state-hook.d.ts.map +1 -0
- package/dist/hooks/session-start-unit-state-hook.js +57 -0
- package/dist/hooks/session-start-unit-state-hook.js.map +1 -0
- package/dist/hooks/stop-next-step-hook.d.ts +16 -0
- package/dist/hooks/stop-next-step-hook.d.ts.map +1 -0
- package/dist/hooks/stop-next-step-hook.js +42 -0
- package/dist/hooks/stop-next-step-hook.js.map +1 -0
- package/dist/hooks/sungen-project-root.d.ts +19 -0
- package/dist/hooks/sungen-project-root.d.ts.map +1 -0
- package/dist/hooks/sungen-project-root.js +130 -0
- package/dist/hooks/sungen-project-root.js.map +1 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.d.ts +15 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.js +106 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.js.map +1 -0
- package/dist/orchestrator/ai-skills/commands.d.ts +5 -1
- package/dist/orchestrator/ai-skills/commands.d.ts.map +1 -1
- package/dist/orchestrator/ai-skills/commands.js +16 -6
- package/dist/orchestrator/ai-skills/commands.js.map +1 -1
- package/dist/orchestrator/ai-skills/golden-skills.test.js +29 -0
- package/dist/orchestrator/ai-skills/golden-skills.test.js.map +1 -1
- package/dist/orchestrator/assets-drift.d.ts +5 -0
- package/dist/orchestrator/assets-drift.d.ts.map +1 -1
- package/dist/orchestrator/assets-drift.js +12 -3
- package/dist/orchestrator/assets-drift.js.map +1 -1
- package/dist/orchestrator/claude-hooks-install.d.ts +27 -0
- package/dist/orchestrator/claude-hooks-install.d.ts.map +1 -0
- package/dist/orchestrator/claude-hooks-install.js +203 -0
- package/dist/orchestrator/claude-hooks-install.js.map +1 -0
- package/dist/orchestrator/lockstep-version.d.ts +15 -5
- package/dist/orchestrator/lockstep-version.d.ts.map +1 -1
- package/dist/orchestrator/lockstep-version.js +30 -17
- package/dist/orchestrator/lockstep-version.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts +6 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +24 -0
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/screen-manager.d.ts.map +1 -1
- package/dist/orchestrator/screen-manager.js +4 -2
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/orchestrator/templates/ai-src/commands/add-api.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
- package/dist/orchestrator/templates/ai-src/commands/create-test.md +14 -16
- package/dist/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/delivery.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/design.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/feedback.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/locale.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/review.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/run-test.md +14 -10
- package/dist/orchestrator/templates/ai-src/config/claude.md +20 -7
- package/dist/orchestrator/templates/ai-src/config/copilot.md +20 -7
- package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
- package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
- package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
- package/dist/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
- package/dist/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
- package/dist/utils/safe-yaml-parse.d.ts +8 -0
- package/dist/utils/safe-yaml-parse.d.ts.map +1 -0
- package/dist/utils/safe-yaml-parse.js +51 -0
- package/dist/utils/safe-yaml-parse.js.map +1 -0
- package/package.json +3 -3
- package/src/basis/anchor-grammar.ts +83 -0
- package/src/basis/anchor-hash.ts +27 -0
- package/src/basis/bm51-tables.ts +65 -0
- package/src/basis/extract-spec-anchors.ts +95 -0
- package/src/basis/migration-sentinel.ts +175 -0
- package/src/basis/spec-frontmatter.ts +68 -0
- package/src/basis/spec-sections.ts +35 -0
- package/src/basis/test-basis-schema.ts +81 -0
- package/src/capabilities/discover.ts +15 -2
- package/src/capabilities/registry.ts +16 -0
- package/src/cli/commands/audit.ts +10 -5
- package/src/cli/commands/capability.ts +4 -2
- package/src/cli/commands/contract-derive-command.ts +61 -0
- package/src/cli/commands/contract.ts +130 -0
- package/src/cli/commands/defect.ts +49 -0
- package/src/cli/commands/delivery.ts +92 -15
- package/src/cli/commands/generate.ts +3 -1
- package/src/cli/commands/journey.ts +41 -16
- package/src/cli/commands/next.ts +64 -10
- package/src/cli/commands/triage.ts +57 -0
- package/src/cli/commands/update.ts +35 -8
- package/src/cli/index.ts +24 -30
- package/src/cli/project-sungen-invocation.ts +39 -0
- package/src/contract/approve-contract.ts +94 -0
- package/src/contract/assertion-matcher-vocabulary.ts +93 -0
- package/src/contract/build-contract-verdict.ts +108 -0
- package/src/contract/build-trace-conformance.ts +100 -0
- package/src/contract/classify-contract-change.ts +92 -0
- package/src/contract/classify-contract-unit.ts +47 -0
- package/src/contract/classify-trace-conformance.ts +116 -0
- package/src/contract/contract-git.ts +106 -0
- package/src/contract/contract-hash.ts +34 -0
- package/src/contract/contract-report-file.ts +25 -0
- package/src/contract/contract-schema.ts +137 -0
- package/src/contract/contract-units.ts +52 -0
- package/src/contract/contracts-lock-file.ts +97 -0
- package/src/contract/data-normalize.ts +66 -0
- package/src/contract/derive-free-feature.ts +120 -0
- package/src/contract/field-semantic-redaction.ts +80 -0
- package/src/contract/free-feature-blocks.ts +56 -0
- package/src/contract/lock-secret-guard.ts +95 -0
- package/src/contract/lock-vs-git-head.ts +38 -0
- package/src/contract/normalize-contract-step.ts +74 -0
- package/src/contract/normalize-feature-steps.ts +93 -0
- package/src/contract/oracle-strength.ts +80 -0
- package/src/contract/project-contract-blockers.ts +36 -0
- package/src/contract/record-contract-approval.ts +70 -0
- package/src/contract/render-free-gherkin.ts +113 -0
- package/src/contract/render-trace-sentence.ts +98 -0
- package/src/contract/render-trace-target.ts +68 -0
- package/src/contract/resolve-unit-trace-identities.ts +35 -0
- package/src/contract/trace/collect-trace-evidence.ts +109 -0
- package/src/contract/trace/identity-cache.ts +61 -0
- package/src/contract/trace/select-final-attempt.ts +70 -0
- package/src/contract/trace/snapshot-html-renderer.ts +136 -0
- package/src/contract/trace/snapshot-resolver.ts +66 -0
- package/src/contract/trace/snapshot-store.ts +151 -0
- package/src/contract/trace/target-identity.ts +104 -0
- package/src/contract/trace/test-step-join.ts +104 -0
- package/src/contract/trace/trace-binding.ts +56 -0
- package/src/contract/trace/trace-file-reader.ts +133 -0
- package/src/contract/trace/trace-fingerprint.ts +68 -0
- package/src/contract/trace/trace-identity-resolution.ts +74 -0
- package/src/contract/trace/trace-run-record.ts +80 -0
- package/src/contract/trace/trace-steps.ts +88 -0
- package/src/contract/trace/trace-zip-limits.ts +77 -0
- package/src/contract/trace/trace-zip-reader.ts +127 -0
- package/src/contract/verify-approval-decisions.ts +60 -0
- package/src/decisions/append-decision.ts +35 -0
- package/src/decisions/confirmed-decision-commands.ts +149 -0
- package/src/decisions/decision-file.ts +93 -0
- package/src/decisions/decision-identity.ts +73 -0
- package/src/decisions/decision-integrity-check.ts +61 -0
- package/src/decisions/decision-schema.ts +76 -0
- package/src/decisions/decision-source.ts +14 -0
- package/src/decisions/exclusive-file-create.ts +42 -0
- package/src/decisions/git-head-trust.ts +32 -0
- package/src/decisions/human-confirmation.ts +119 -0
- package/src/decisions/legacy-waiver-migration.ts +135 -0
- package/src/decisions/read-decisions.ts +61 -0
- package/src/decisions/viewpoint-baseline-adapter.ts +74 -0
- package/src/decisions/waiver-decisions.ts +56 -0
- package/src/exporters/csv-exporter.ts +5 -1
- package/src/exporters/feature-parser.ts +12 -0
- package/src/exporters/matrix/build.ts +62 -18
- package/src/exporters/matrix/carry-manual-results.ts +70 -7
- package/src/exporters/matrix/export.ts +17 -2
- package/src/exporters/matrix/gates.ts +62 -129
- package/src/exporters/matrix/render-csv.ts +4 -1
- package/src/exporters/matrix/render-gate-overrides-sheet.ts +50 -0
- package/src/exporters/matrix/render-xlsx.ts +6 -0
- package/src/exporters/matrix/types.ts +9 -1
- package/src/exporters/matrix/xlsx-cells.ts +1 -1
- package/src/exporters/playwright-report-parser.ts +1 -0
- package/src/exporters/scenario-merger.ts +2 -1
- package/src/exporters/types.ts +5 -0
- package/src/generators/test-generator/code-generator.ts +13 -0
- package/src/graph/evaluate-graph.ts +66 -0
- package/src/graph/locate-finding.ts +93 -0
- package/src/graph/node-decl.ts +72 -0
- package/src/graph/nodes/core-node-catalog.ts +15 -0
- package/src/graph/nodes/test-case-contract-nodes.ts +74 -0
- package/src/graph/nodes/test-case-nodes.ts +68 -0
- package/src/graph/nodes/unit-audit-nodes.ts +95 -0
- package/src/graph/nodes/unit-contract-node.ts +89 -0
- package/src/graph/nodes/unit-design-nodes.ts +89 -0
- package/src/graph/nodes/unit-execution-nodes.ts +77 -0
- package/src/graph/test-case-identity.ts +75 -0
- package/src/graph/test-case-results.ts +90 -0
- package/src/graph/test-case-satisfied.ts +55 -0
- package/src/graph/test-case-state-shape.ts +62 -0
- package/src/graph/test-case-states.ts +84 -0
- package/src/graph/unit-artifact-probes.ts +77 -0
- package/src/graph/unit-state-facts.ts +112 -0
- package/src/harness/audit.ts +46 -11
- package/src/harness/catalog/gate-rules.yaml +647 -0
- package/src/harness/counted-assertions.ts +33 -0
- package/src/harness/defect-draft.ts +115 -0
- package/src/harness/defects.ts +94 -0
- package/src/harness/gates/audit-gate-terms.ts +80 -0
- package/src/harness/gates/audit-gate-verdict.ts +78 -0
- package/src/harness/gates/audit-input-hash.ts +55 -0
- package/src/harness/gates/audit-report-verification.ts +201 -0
- package/src/harness/gates/decisions-hash.ts +42 -0
- package/src/harness/gates/delivery-checklist.ts +120 -0
- package/src/harness/gates/delivery-decision-gate.ts +139 -0
- package/src/harness/gates/delivery-decision-step.ts +89 -0
- package/src/harness/gates/gate-override-report.ts +114 -0
- package/src/harness/gates/gate-override-scope.ts +66 -0
- package/src/harness/gates/gate-override-validation.ts +75 -0
- package/src/harness/gates/gate-rule-catalog.ts +82 -0
- package/src/harness/gates/gate-terms.ts +59 -0
- package/src/harness/gates/in-run-decision-check.ts +99 -0
- package/src/harness/gates/journey-gate-inputs.ts +89 -0
- package/src/harness/gates/migrated-waiver-review.ts +68 -0
- package/src/harness/gates/resolve-rule.ts +94 -0
- package/src/harness/gates/unit-gate-overrides.ts +99 -0
- package/src/harness/journey.ts +215 -38
- package/src/harness/manifest.ts +69 -45
- package/src/harness/next-step.ts +60 -170
- package/src/harness/parse.ts +40 -13
- package/src/harness/provenance.ts +99 -11
- package/src/harness/script-check.ts +27 -6
- package/src/harness/sensors.ts +73 -47
- package/src/harness/triage-signals.ts +46 -0
- package/src/harness/triage-unit.ts +113 -0
- package/src/harness/triage.ts +127 -0
- package/src/harness/viewpoint-ledger.ts +2 -2
- package/src/hooks/bash-write-targets.ts +109 -0
- package/src/hooks/claude-hook-entry.ts +85 -0
- package/src/hooks/claude-transcript-turn.ts +96 -0
- package/src/hooks/guard-delivery-contract-rule.ts +110 -0
- package/src/hooks/guard-protected-paths.ts +71 -0
- package/src/hooks/guard-rules.ts +98 -0
- package/src/hooks/guard-tty-spoof-rule.ts +31 -0
- package/src/hooks/hand-back-core.ts +112 -0
- package/src/hooks/hook-cli-command.ts +17 -0
- package/src/hooks/hook-registry.ts +24 -0
- package/src/hooks/hook-result-contract.ts +114 -0
- package/src/hooks/hook-toggles.ts +66 -0
- package/src/hooks/pre-tool-guard-hook.ts +67 -0
- package/src/hooks/session-start-unit-state-hook.ts +56 -0
- package/src/hooks/stop-next-step-hook.ts +37 -0
- package/src/hooks/sungen-project-root.ts +80 -0
- package/src/orchestrator/ai-skills/command-partial-includes.ts +72 -0
- package/src/orchestrator/ai-skills/commands.ts +22 -8
- package/src/orchestrator/ai-skills/golden-skills.test.ts +23 -0
- package/src/orchestrator/assets-drift.ts +12 -5
- package/src/orchestrator/claude-hooks-install.ts +168 -0
- package/src/orchestrator/lockstep-version.ts +28 -15
- package/src/orchestrator/project-initializer.ts +22 -0
- package/src/orchestrator/screen-manager.ts +3 -1
- package/src/orchestrator/templates/ai-src/commands/add-api.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
- package/src/orchestrator/templates/ai-src/commands/create-test.md +14 -16
- package/src/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/delivery.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/design.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/feedback.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/locale.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/review.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/run-test.md +14 -10
- package/src/orchestrator/templates/ai-src/config/claude.md +20 -7
- package/src/orchestrator/templates/ai-src/config/copilot.md +20 -7
- package/src/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
- package/src/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
- package/src/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
- package/src/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
- package/src/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
- package/src/utils/safe-yaml-parse.ts +44 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gate-rule catalog (OES-11.1): `harness/catalog/gate-rules.yaml`, shipped next to the code
|
|
3
|
+
* (`copy-templates` copies it into `dist/harness/catalog/`).
|
|
4
|
+
*
|
|
5
|
+
* The catalog is code-owned data — a malformed one is a build defect, so loading it throws rather
|
|
6
|
+
* than degrading to "no rules" (which would silently stop every gate from blocking).
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import { parse } from 'yaml';
|
|
11
|
+
|
|
12
|
+
export const GATE_SEVERITIES = ['error', 'review', 'warning', 'info'] as const;
|
|
13
|
+
export type GateSeverity = typeof GATE_SEVERITIES[number];
|
|
14
|
+
export type GateKind = 'hard' | 'soft';
|
|
15
|
+
export const GATE_STAGES = ['spec', 'create', 'generate', 'run', 'deliver'] as const;
|
|
16
|
+
export type GateStage = typeof GATE_STAGES[number];
|
|
17
|
+
|
|
18
|
+
export interface GateRule {
|
|
19
|
+
id: string;
|
|
20
|
+
stage: GateStage;
|
|
21
|
+
severity: GateSeverity;
|
|
22
|
+
kind: GateKind;
|
|
23
|
+
rationale: string;
|
|
24
|
+
fix: string;
|
|
25
|
+
since: string;
|
|
26
|
+
offAllowed: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const CATALOG_FILE = path.join(__dirname, '..', 'catalog', 'gate-rules.yaml');
|
|
30
|
+
const ID_RE = /^[a-z0-9]+(\.[a-z0-9]+(-[a-z0-9]+)*)+$/;
|
|
31
|
+
|
|
32
|
+
/** Parse and validate catalog text. Throws on the first structural defect. */
|
|
33
|
+
export function parseGateRuleCatalog(text: string): Map<string, GateRule> {
|
|
34
|
+
const doc = parse(text) as { rules?: unknown } | null;
|
|
35
|
+
if (!doc || !Array.isArray(doc.rules)) throw new Error('gate-rules.yaml: no `rules:` list');
|
|
36
|
+
const out = new Map<string, GateRule>();
|
|
37
|
+
for (const raw of doc.rules as Array<Record<string, unknown>>) {
|
|
38
|
+
const id = String(raw?.id ?? '');
|
|
39
|
+
const bad = (why: string): never => { throw new Error(`gate-rules.yaml: rule "${id}" ${why}`); };
|
|
40
|
+
if (!ID_RE.test(id)) bad('has no dotted kebab-case id');
|
|
41
|
+
if (out.has(id)) bad('is declared twice');
|
|
42
|
+
if (!GATE_STAGES.includes(raw.stage as GateStage)) bad(`has an unknown stage "${raw.stage}"`);
|
|
43
|
+
if (!GATE_SEVERITIES.includes(raw.severity as GateSeverity)) bad(`has an unknown severity "${raw.severity}"`);
|
|
44
|
+
if (raw.kind !== 'hard' && raw.kind !== 'soft') bad('kind must be hard|soft');
|
|
45
|
+
if (typeof raw.offAllowed !== 'boolean') bad('offAllowed must be a boolean');
|
|
46
|
+
if (raw.kind === 'hard' && raw.offAllowed) bad('is hard, so it can never be switched off');
|
|
47
|
+
out.set(id, {
|
|
48
|
+
id,
|
|
49
|
+
stage: raw.stage as GateStage,
|
|
50
|
+
severity: raw.severity as GateSeverity,
|
|
51
|
+
kind: raw.kind as GateKind,
|
|
52
|
+
rationale: String(raw.rationale ?? ''),
|
|
53
|
+
fix: String(raw.fix ?? ''),
|
|
54
|
+
since: String(raw.since ?? ''),
|
|
55
|
+
offAllowed: raw.offAllowed as boolean,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let cached: ReadonlyMap<string, GateRule> | null = null;
|
|
62
|
+
|
|
63
|
+
/** Every rule, keyed by id (loaded once per process). */
|
|
64
|
+
export function gateRuleCatalog(): ReadonlyMap<string, GateRule> {
|
|
65
|
+
if (!cached) cached = parseGateRuleCatalog(fs.readFileSync(CATALOG_FILE, 'utf8'));
|
|
66
|
+
return cached;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function findGateRule(id: string): GateRule | undefined {
|
|
70
|
+
return gateRuleCatalog().get(id);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** A rule the CODE names. An unknown id is a programming error, never user input — so it throws. */
|
|
74
|
+
export function gateRule(id: string): GateRule {
|
|
75
|
+
const rule = findGateRule(id);
|
|
76
|
+
if (!rule) throw new Error(`gate rule "${id}" is not in harness/catalog/gate-rules.yaml`);
|
|
77
|
+
return rule;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function listRules(): GateRule[] {
|
|
81
|
+
return [...gateRuleCatalog().values()];
|
|
82
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turning a gate CONDITION into an outcome through `resolveRule` — the only shapes a gate site uses,
|
|
3
|
+
* so no site writes a severity literal of its own (OES-11.2).
|
|
4
|
+
*
|
|
5
|
+
* evaluateGateTerms a conjunction (audit gateStatus, script-check status): each term names its
|
|
6
|
+
* rule and whether its condition holds; a violated term blocks only when its
|
|
7
|
+
* resolved severity blocks
|
|
8
|
+
* ruleVerdict a sensor verdict (pass | warn | fail) for one rule
|
|
9
|
+
* sensorSeverityOf a per-finding sensor severity (fail | warn | info), or null when switched off
|
|
10
|
+
*/
|
|
11
|
+
import { GateRules, ResolvedRule } from './resolve-rule';
|
|
12
|
+
|
|
13
|
+
export interface GateTerm {
|
|
14
|
+
rule: string;
|
|
15
|
+
/** The condition the rule wants to see — `true` means the term passes. */
|
|
16
|
+
holds: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface GateTermsOutcome {
|
|
20
|
+
pass: boolean;
|
|
21
|
+
/** Violated rules whose resolved severity blocks. */
|
|
22
|
+
blocking: string[];
|
|
23
|
+
/** Violated rules an override lowered to advisory. */
|
|
24
|
+
relaxed: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function evaluateGateTerms(terms: GateTerm[], rules: GateRules): GateTermsOutcome {
|
|
28
|
+
const blocking: string[] = [];
|
|
29
|
+
const relaxed: string[] = [];
|
|
30
|
+
for (const t of terms) {
|
|
31
|
+
if (t.holds) continue;
|
|
32
|
+
const r = rules.resolve(t.rule);
|
|
33
|
+
if (r.blocking) blocking.push(t.rule);
|
|
34
|
+
else if (r.overriddenBy) relaxed.push(t.rule);
|
|
35
|
+
}
|
|
36
|
+
return { pass: blocking.length === 0, blocking, relaxed };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type SensorVerdict = 'pass' | 'warn' | 'fail';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A sensor verdict for one rule. `advisoryAnyway` is a reason the miss can never block that is not
|
|
43
|
+
* a severity (the `smoke` focus, or no failing row) — the rule is then not consulted at all.
|
|
44
|
+
*/
|
|
45
|
+
export function ruleVerdict(rules: GateRules, id: string, conditionMet: boolean, advisoryAnyway: boolean): SensorVerdict {
|
|
46
|
+
if (!conditionMet) return 'pass';
|
|
47
|
+
if (advisoryAnyway) return 'warn';
|
|
48
|
+
const r = rules.resolve(id);
|
|
49
|
+
if (r.severity === 'off') return 'pass';
|
|
50
|
+
return r.blocking ? 'fail' : 'warn';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type SensorSeverity = 'fail' | 'warn' | 'info';
|
|
54
|
+
|
|
55
|
+
export function sensorSeverityOf(r: ResolvedRule): SensorSeverity | null {
|
|
56
|
+
if (r.severity === 'off') return null;
|
|
57
|
+
if (r.blocking) return 'fail';
|
|
58
|
+
return r.severity === 'info' ? 'info' : 'warn';
|
|
59
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `decision.in-run` (OES-11.5, red-team #3/#15) — a hard rule: a decision that relaxes or approves
|
|
3
|
+
* something (`gate-override`, `waiver`, `contract-approval`) must have been reviewed BEFORE the run
|
|
4
|
+
* being delivered. It is in-run when
|
|
5
|
+
* - it is not in `git show HEAD:` (never committed, so never reviewed), or
|
|
6
|
+
* - it was committed after the start of that run — judged by its git COMMIT time, not by the
|
|
7
|
+
* `valid_from` it carries, which its author writes and can backdate (review H1).
|
|
8
|
+
* Without git only the second test is possible, on `valid_from`; the caller says so (lower confidence).
|
|
9
|
+
* Without git AND without a run, nothing can be judged — reported, not guessed. A commit time can be
|
|
10
|
+
* forged too (GIT_COMMITTER_DATE); it raises the bar, it is not a signature.
|
|
11
|
+
*
|
|
12
|
+
* A MIGRATED waiver (DOS-13.5) was reviewed when its legacy record was committed — the only record the
|
|
13
|
+
* import trusts — so it is judged by THAT commit (migrated-waiver-review.ts), never by its own decision
|
|
14
|
+
* file: in-run when the record was committed after the run started, or, with no run to compare,
|
|
15
|
+
* after the decision file appeared. Holding it to its decision file's commit would make every legacy
|
|
16
|
+
* project's waivers in-run the day they are imported (phase 09). An entry HEAD's legacy file does not
|
|
17
|
+
* vouch for — absent, uncommitted, different — is judged as any other.
|
|
18
|
+
*/
|
|
19
|
+
import * as fs from 'fs';
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import { DECISION_FILE_PATH } from '../../decisions/decision-file';
|
|
22
|
+
import { DecisionVisibility } from '../../decisions/decision-schema';
|
|
23
|
+
import { gitOutput } from '../../decisions/git-head-trust';
|
|
24
|
+
import { readDecisions } from '../../decisions/read-decisions';
|
|
25
|
+
import { decisionFirstSeenMs, migratedWaiverReviewedAt } from './migrated-waiver-review';
|
|
26
|
+
|
|
27
|
+
export const IN_RUN_KINDS = ['gate-override', 'waiver', 'contract-approval'] as const;
|
|
28
|
+
export const IN_RUN_RULE = 'decision.in-run';
|
|
29
|
+
|
|
30
|
+
export interface InRunDecision { id: string; kind: string; path: string; visibility: DecisionVisibility; why: string[] }
|
|
31
|
+
|
|
32
|
+
/** Paths (relative to the project, `/`-separated) of decision files in git HEAD; null outside git. */
|
|
33
|
+
export function committedDecisionPaths(projectRoot: string): Set<string> | null {
|
|
34
|
+
if (gitOutput(projectRoot, ['rev-parse', '--is-inside-work-tree'])?.trim() !== 'true') return null;
|
|
35
|
+
const listed = gitOutput(projectRoot, ['ls-tree', '-r', '-z', '--name-only', 'HEAD', '--', 'qa']) ?? ''; // no HEAD yet → nothing committed
|
|
36
|
+
return new Set(listed.split('\0').filter((p) => DECISION_FILE_PATH.test(p)));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** When a committed file was last committed (ISO), or null when git cannot say. */
|
|
40
|
+
function commitTimeOf(projectRoot: string, rel: string): string | null {
|
|
41
|
+
const t = gitOutput(projectRoot, ['log', '-1', '--format=%cI', '--', rel])?.trim();
|
|
42
|
+
return t && !Number.isNaN(Date.parse(t)) ? t : null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** When the delivered run started: Playwright's `stats.startTime`; null when there is no readable run. */
|
|
46
|
+
export function runStartOf(resultsPath: string | null): string | null {
|
|
47
|
+
if (!resultsPath) return null;
|
|
48
|
+
try {
|
|
49
|
+
const json = JSON.parse(fs.readFileSync(resultsPath, 'utf8')) as { stats?: { startTime?: unknown } };
|
|
50
|
+
const t = json?.stats?.startTime;
|
|
51
|
+
return typeof t === 'string' && !Number.isNaN(Date.parse(t)) ? t : null;
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const isInRunKind = (kind: string): boolean => (IN_RUN_KINDS as readonly string[]).includes(kind);
|
|
58
|
+
|
|
59
|
+
/** In-run decisions among `scopes`, judged against one run start (null: HEAD membership only) and the committed set. */
|
|
60
|
+
export function inRunDecisions(projectRoot: string, scopes: string[], runStart: string | null, committed: Set<string> | null): InRunDecision[] {
|
|
61
|
+
const out: InRunDecision[] = [];
|
|
62
|
+
const after = (t: string): boolean => !!runStart && Date.parse(t) > Date.parse(runStart);
|
|
63
|
+
for (const scope of scopes) {
|
|
64
|
+
for (const e of readDecisions(projectRoot, scope).entries) {
|
|
65
|
+
if (!isInRunKind(e.kind)) continue;
|
|
66
|
+
const rel = path.relative(projectRoot, e.path).split(path.sep).join('/');
|
|
67
|
+
const why: string[] = [];
|
|
68
|
+
const legacyAt = committed ? migratedWaiverReviewedAt(projectRoot, scope, e) : null;
|
|
69
|
+
if (legacyAt) {
|
|
70
|
+
if (runStart ? after(legacyAt) : Date.parse(legacyAt) > decisionFirstSeenMs(projectRoot, rel, e.path)) {
|
|
71
|
+
why.push(runStart
|
|
72
|
+
? `migrated: its legacy record was committed at ${legacyAt}, after the run started ${runStart}`
|
|
73
|
+
: `migrated: its legacy record was committed at ${legacyAt}, after this decision first appeared`);
|
|
74
|
+
}
|
|
75
|
+
} else if (committed && !committed.has(rel)) {
|
|
76
|
+
why.push('not in git HEAD (never committed through review)');
|
|
77
|
+
} else if (committed && runStart) {
|
|
78
|
+
const at = commitTimeOf(projectRoot, rel);
|
|
79
|
+
if (at ? after(at) : after(e.valid_from)) {
|
|
80
|
+
why.push(at ? `committed at ${at}, after the run started ${runStart}` : `recorded ${e.valid_from} (commit time unavailable), after the run started ${runStart}`);
|
|
81
|
+
}
|
|
82
|
+
} else if (!committed && after(e.valid_from)) {
|
|
83
|
+
why.push(`recorded ${e.valid_from}, after the run started ${runStart}`);
|
|
84
|
+
}
|
|
85
|
+
if (why.length) out.push({ id: e.id, kind: e.kind, path: rel, visibility: e.visibility, why });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Release decisions (override / waiver / approval) in reach that git HEAD does not hold — what `gate deliver` refuses. */
|
|
92
|
+
export function uncommittedReleaseDecisions(projectRoot: string, scopes: string[]): InRunDecision[] {
|
|
93
|
+
return inRunDecisions(projectRoot, scopes, null, committedDecisionPaths(projectRoot));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Whether any decision of an in-run kind is in reach at all — the no-git notes are printed only then. */
|
|
97
|
+
export function hasInRunKindDecisions(projectRoot: string, scopes: string[]): boolean {
|
|
98
|
+
return scopes.some((s) => readDecisions(projectRoot, s).entries.some((e) => isInRunKind(e.kind)));
|
|
99
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the journey board and `runGate` take from the gate registry (OES-11.2/11.4, phase-03 review).
|
|
3
|
+
*
|
|
4
|
+
* readJourneyAudit the audit report, read through the T3 checks — a stale or untrusted one
|
|
5
|
+
* counts as never audited
|
|
6
|
+
* applyAuditOverrides an OB-* whose rule the AUDIT recorded as overridden is accepted
|
|
7
|
+
* (`overridden`); journey never re-applies an override itself (red-team #12)
|
|
8
|
+
* journeyDecisionFindings the decision files in the unit's reach that do not verify, edits/deletes
|
|
9
|
+
* of committed entries (checkDecisionIntegrity), and rejected overrides — each
|
|
10
|
+
* a finding the board shows and the gate blocks on, never a crash
|
|
11
|
+
*/
|
|
12
|
+
import { checkDecisionIntegrity } from '../../decisions/decision-integrity-check';
|
|
13
|
+
import { resolveUnitCandidates } from '../../cli/resolve-unit';
|
|
14
|
+
import { auditCounts, auditNotCountedReason, AuditVerification, verifyAuditReport } from './audit-report-verification';
|
|
15
|
+
import { GateOverrideReport } from './gate-override-report';
|
|
16
|
+
import { ActiveOverride } from './resolve-rule';
|
|
17
|
+
import { loadUnitGateOverrides, unitScopeOfDir, UnitGateOverrides } from './unit-gate-overrides';
|
|
18
|
+
|
|
19
|
+
export interface JourneyAuditInput {
|
|
20
|
+
audit: Record<string, unknown> | null;
|
|
21
|
+
verification: AuditVerification;
|
|
22
|
+
/** Set when a report exists but does not count (stale / invalid). */
|
|
23
|
+
notCountedReason?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function readJourneyAudit(projectRoot: string, unit: string): JourneyAuditInput {
|
|
27
|
+
const verification = verifyAuditReport(projectRoot, unit);
|
|
28
|
+
if (auditCounts(verification)) return { audit: verification.report, verification };
|
|
29
|
+
return {
|
|
30
|
+
audit: null,
|
|
31
|
+
verification,
|
|
32
|
+
...(verification.state !== 'absent' ? { notCountedReason: auditNotCountedReason(verification, unit) } : {}),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The audit rule each design obligation stands for. */
|
|
37
|
+
export const OBLIGATION_RULE: Readonly<Record<string, string>> = {
|
|
38
|
+
'OB-spec': 'audit.spec-coverage',
|
|
39
|
+
'OB-coverage': 'audit.viewpoint-coverage',
|
|
40
|
+
'OB-depth': 'audit.assertion-depth',
|
|
41
|
+
'OB-trace': 'audit.taxonomy-mismatch',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
interface OverridableObligation { id: string; status: string; detail: string; overriddenBy?: string }
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Mark needs-work obligations whose rule the audit recorded as overridden (applied). audit.json is
|
|
48
|
+
* output too: an `applied` entry counts only when the same override (decision id AND rule) is in
|
|
49
|
+
* force for the unit today (review M3); the others are ignored and returned for the board.
|
|
50
|
+
*/
|
|
51
|
+
export function applyAuditOverrides<T extends OverridableObligation>(obligations: T[], audit: Record<string, unknown>, inForce: ActiveOverride[]): GateOverrideReport[] {
|
|
52
|
+
const recorded = (Array.isArray(audit.gateOverrides) ? audit.gateOverrides as GateOverrideReport[] : [])
|
|
53
|
+
.filter((g) => g && g.status === 'applied');
|
|
54
|
+
const real = (g: GateOverrideReport): boolean => inForce.some((o) => o.decisionId === g.decisionId && o.rule === g.rule);
|
|
55
|
+
const applied = recorded.filter(real);
|
|
56
|
+
for (const ob of obligations) {
|
|
57
|
+
const o = applied.find((g) => g.rule === OBLIGATION_RULE[ob.id]);
|
|
58
|
+
if (!o || ob.status !== 'needs-work') continue;
|
|
59
|
+
ob.status = 'overridden';
|
|
60
|
+
ob.overriddenBy = o.decisionId;
|
|
61
|
+
ob.detail = `overridden by ${o.decisionId} (${o.rule} → ${o.severity}) — ${o.reason}. Was: ${ob.detail}`;
|
|
62
|
+
}
|
|
63
|
+
return recorded.filter((g) => !real(g));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function ignoredOverrideText(g: GateOverrideReport): string {
|
|
67
|
+
return `⚠️ audit.json says override ${String(g.decisionId)} (${String(g.rule)}) applied, but it is not in force for this unit — ignored. Re-run the audit; never edit its report.`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface DecisionGateFinding { rule: 'decision.id-reuse' | 'decision.mutated' | 'gate.override-rejected'; path: string; message: string }
|
|
71
|
+
|
|
72
|
+
export function unitOverrides(projectRoot: string, unit: string): UnitGateOverrides {
|
|
73
|
+
const found = resolveUnitCandidates(unit, projectRoot);
|
|
74
|
+
return loadUnitGateOverrides(projectRoot, found.length === 1 ? unitScopeOfDir(projectRoot, found[0].dir) : null);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Integrity of every decision in the unit's reach (project + unit dirs) plus its rejected overrides. */
|
|
78
|
+
export function journeyDecisionFindings(projectRoot: string, overrides: UnitGateOverrides): DecisionGateFinding[] {
|
|
79
|
+
const reach = ['qa/decisions/', ...(overrides.unitScope ? [`qa/${overrides.unitScope}/decisions/`] : [])];
|
|
80
|
+
const integrity: DecisionGateFinding[] = checkDecisionIntegrity(projectRoot)
|
|
81
|
+
.filter((f) => reach.some((r) => f.path.startsWith(r)))
|
|
82
|
+
.map((f) => ({ rule: f.rule, path: f.path, message: f.message }));
|
|
83
|
+
const rejected: DecisionGateFinding[] = overrides.rejected.map((r) => ({ rule: 'gate.override-rejected', path: r.path, message: `${r.decisionId}: ${r.reason}` }));
|
|
84
|
+
return [...integrity, ...rejected];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function decisionFindingText(f: DecisionGateFinding): string {
|
|
88
|
+
return `⛔ ${f.rule}: ${f.path} — ${f.message}. Hard rule: restore the file from git, or record a superseding decision on a terminal.`;
|
|
89
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When a MIGRATED waiver was reviewed (DOS-13.5, phase 09) — for `decision.in-run`.
|
|
3
|
+
*
|
|
4
|
+
* The import (legacy-waiver-migration.ts) trusts a legacy waiver only when git HEAD's
|
|
5
|
+
* `.sungen/journey/<slug>.state.json` holds that exact record; its review was the commit that put the
|
|
6
|
+
* record there. So a migrated decision is judged by THAT commit, not by its own file:
|
|
7
|
+
*
|
|
8
|
+
* vouched HEAD's state file holds the record (same reason, `at`, auditHashAtWaive) — reviewedAt is
|
|
9
|
+
* the commit time of the oldest commit in the unbroken run, back from HEAD, that holds it
|
|
10
|
+
* with a run start in-run when reviewedAt is after it (the same test as any committed decision)
|
|
11
|
+
* without one in-run when reviewedAt is after the decision file first appeared (its first
|
|
12
|
+
* commit, else its creation time): a genuine import always follows the commit it read
|
|
13
|
+
* Anything else — no git, no such record in HEAD, a record that differs — is not vouched for: the
|
|
14
|
+
* decision is judged as any other (`not in git HEAD`, or its own commit time).
|
|
15
|
+
*/
|
|
16
|
+
import * as fs from 'fs';
|
|
17
|
+
import * as path from 'path';
|
|
18
|
+
import { committedText, gitOutput } from '../../decisions/git-head-trust';
|
|
19
|
+
import type { ReadDecision } from '../../decisions/read-decisions';
|
|
20
|
+
import { asLegacyWaiver, isLegacyWaiver, sameWaiver } from '../../decisions/waiver-decisions';
|
|
21
|
+
import { reportSlug } from '../unit-paths';
|
|
22
|
+
|
|
23
|
+
/** Commits of one state file the walk reads at most (each is one `git show`). */
|
|
24
|
+
const MAX_COMMITS = 200;
|
|
25
|
+
|
|
26
|
+
const parse = (text: string | null): { waivers?: Record<string, unknown> } | null => {
|
|
27
|
+
if (text === null) return null;
|
|
28
|
+
try { return JSON.parse(text.replace(/^/, '')); } catch { return null; }
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function holds(state: { waivers?: Record<string, unknown> } | null, e: ReadDecision, ob: string): boolean {
|
|
32
|
+
const w = state?.waivers?.[ob];
|
|
33
|
+
return isLegacyWaiver(w) && w.at === e.valid_from && sameWaiver(w, asLegacyWaiver(e));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The commit time of the oldest commit, in the unbroken run back from HEAD, whose state file holds the record. */
|
|
37
|
+
function introducedAt(projectRoot: string, rel: string, e: ReadDecision, ob: string): string | null {
|
|
38
|
+
const log = gitOutput(projectRoot, ['log', `--max-count=${MAX_COMMITS}`, '--format=%H %cI', '--', rel]) ?? '';
|
|
39
|
+
let oldest: string | null = null;
|
|
40
|
+
for (const line of log.split('\n').filter(Boolean)) {
|
|
41
|
+
const [sha, at] = line.split(' ');
|
|
42
|
+
if (!holds(parse(gitOutput(projectRoot, ['show', `${sha}:./${rel}`])), e, ob)) break;
|
|
43
|
+
oldest = at;
|
|
44
|
+
}
|
|
45
|
+
return oldest && !Number.isNaN(Date.parse(oldest)) ? oldest : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** When a migrated waiver's legacy record was committed, or null when nothing in git HEAD vouches for it. */
|
|
49
|
+
export function migratedWaiverReviewedAt(projectRoot: string, scope: string, e: ReadDecision): string | null {
|
|
50
|
+
const ob = e.payload?.obligation;
|
|
51
|
+
if (e.kind !== 'waiver' || e.source?.where !== 'migrated' || typeof ob !== 'string') return null;
|
|
52
|
+
// The journey keys its state by the unit name it was given: `<name>`, or the catalog id for api units.
|
|
53
|
+
const slugs = new Set([scope.split('/').pop() ?? '', reportSlug(scope.replace(/^(screens|flows)\//, ''))]);
|
|
54
|
+
for (const slug of slugs) {
|
|
55
|
+
const file = path.join(projectRoot, '.sungen', 'journey', `${slug}.state.json`);
|
|
56
|
+
if (!holds(parse(committedText(projectRoot, file)), e, ob)) continue;
|
|
57
|
+
const at = introducedAt(projectRoot, path.relative(projectRoot, file).split(path.sep).join('/'), e, ob);
|
|
58
|
+
if (at) return at;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** When a decision file first appeared: its first commit, else its creation (or last change) on disk. */
|
|
64
|
+
export function decisionFirstSeenMs(projectRoot: string, rel: string, abs: string): number {
|
|
65
|
+
const added = gitOutput(projectRoot, ['log', '--diff-filter=A', '--format=%cI', '--', rel])?.trim().split('\n').filter(Boolean).pop();
|
|
66
|
+
if (added && !Number.isNaN(Date.parse(added))) return Date.parse(added);
|
|
67
|
+
try { const s = fs.statSync(abs); return s.birthtimeMs || s.mtimeMs; } catch { return Number.NEGATIVE_INFINITY; }
|
|
68
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One `resolveRule` (OES-11.2). Code keeps computing a gate's CONDITION; what the condition costs —
|
|
3
|
+
* its severity, and whether that blocks — comes from here and nowhere else, so audit, sensors,
|
|
4
|
+
* script-check, matrix gates and journey cannot disagree about a rule (red-team #12).
|
|
5
|
+
*
|
|
6
|
+
* Two axes, never merged (takumi T5):
|
|
7
|
+
* block vs advisory follows severity — error|review block; warning|info|off never block
|
|
8
|
+
* overridable or not follows kind — a hard rule ignores every override
|
|
9
|
+
* With no override in force the result IS the catalog row, which equals today's behavior.
|
|
10
|
+
*/
|
|
11
|
+
import { DecisionVisibility } from '../../decisions/decision-schema';
|
|
12
|
+
import { GateKind, GateSeverity, gateRule, listRules, GateRule } from './gate-rule-catalog';
|
|
13
|
+
|
|
14
|
+
export type OverrideSeverity = 'warning' | 'info' | 'off';
|
|
15
|
+
export type ResolvedSeverity = GateSeverity | 'off';
|
|
16
|
+
|
|
17
|
+
/** A gate-override decision that passed validation and is in force for one unit. */
|
|
18
|
+
export interface ActiveOverride {
|
|
19
|
+
decisionId: string;
|
|
20
|
+
rule: string;
|
|
21
|
+
severity: OverrideSeverity;
|
|
22
|
+
scope: string;
|
|
23
|
+
reason: string;
|
|
24
|
+
visibility: DecisionVisibility;
|
|
25
|
+
by: string;
|
|
26
|
+
validFrom: string;
|
|
27
|
+
path: string;
|
|
28
|
+
/** In git HEAD? null outside git. An uncommitted override still counts here, but release refuses it (decision.in-run). */
|
|
29
|
+
committed: boolean | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface GateRuleContext {
|
|
33
|
+
/** rule id → the override in force for the unit being judged. */
|
|
34
|
+
overrides: ReadonlyMap<string, ActiveOverride>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const NO_OVERRIDES: GateRuleContext = Object.freeze({ overrides: new Map<string, ActiveOverride>() });
|
|
38
|
+
|
|
39
|
+
export interface ResolvedRule {
|
|
40
|
+
id: string;
|
|
41
|
+
severity: ResolvedSeverity;
|
|
42
|
+
catalogSeverity: GateSeverity;
|
|
43
|
+
kind: GateKind;
|
|
44
|
+
blocking: boolean;
|
|
45
|
+
/** The decision id of the override that set `severity`, when one did. */
|
|
46
|
+
overriddenBy?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const isBlockingSeverity = (s: ResolvedSeverity): boolean => s === 'error' || s === 'review';
|
|
50
|
+
|
|
51
|
+
/** Whether an override may apply to this rule at all (defense in depth behind validation). */
|
|
52
|
+
function admissible(rule: GateRule, o: ActiveOverride | undefined): o is ActiveOverride {
|
|
53
|
+
if (!o || rule.kind === 'hard') return false;
|
|
54
|
+
return o.severity !== 'off' || rule.offAllowed;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function resolveRule(id: string, ctx: GateRuleContext = NO_OVERRIDES): ResolvedRule {
|
|
58
|
+
const rule = gateRule(id);
|
|
59
|
+
const o = ctx.overrides.get(id);
|
|
60
|
+
if (!admissible(rule, o)) {
|
|
61
|
+
return { id, severity: rule.severity, catalogSeverity: rule.severity, kind: rule.kind, blocking: isBlockingSeverity(rule.severity) };
|
|
62
|
+
}
|
|
63
|
+
return { id, severity: o.severity, catalogSeverity: rule.severity, kind: rule.kind, blocking: isBlockingSeverity(o.severity), overriddenBy: o.decisionId };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { listRules };
|
|
67
|
+
|
|
68
|
+
/** What a gate site holds: resolve a rule whose condition it found met. */
|
|
69
|
+
export interface GateRules {
|
|
70
|
+
resolve(id: string): ResolvedRule;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** The catalog alone — today's behavior; the default wherever no unit context is known. */
|
|
74
|
+
export const CATALOG_GATE_RULES: GateRules = Object.freeze({ resolve: (id: string) => resolveRule(id, NO_OVERRIDES) });
|
|
75
|
+
|
|
76
|
+
export interface TrackedGateRules extends GateRules {
|
|
77
|
+
readonly context: GateRuleContext;
|
|
78
|
+
/** Rules whose override changed an outcome during this evaluation. */
|
|
79
|
+
triggered(): ReadonlySet<string>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Resolve against one unit's overrides and remember which of them actually changed something. */
|
|
83
|
+
export function trackGateRules(context: GateRuleContext): TrackedGateRules {
|
|
84
|
+
const fired = new Set<string>();
|
|
85
|
+
return {
|
|
86
|
+
context,
|
|
87
|
+
resolve(id: string): ResolvedRule {
|
|
88
|
+
const r = resolveRule(id, context);
|
|
89
|
+
if (r.overriddenBy) fired.add(id);
|
|
90
|
+
return r;
|
|
91
|
+
},
|
|
92
|
+
triggered: () => fired,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gate overrides in force for ONE unit, read from the decision layer (OES-11.2/11.3, DOS-13).
|
|
3
|
+
*
|
|
4
|
+
* Sources: `qa/decisions/` (project) and `qa/<kind>/<unit>/decisions/` (the unit). Only entries that
|
|
5
|
+
* verify against themselves are considered (readDecisions); superseded ones are out of force. Per
|
|
6
|
+
* rule the override in force is the most specific — an exact unit beats a glob — then the latest, then
|
|
7
|
+
* the higher decision id (deterministic). Each carries whether git HEAD holds it: an uncommitted one
|
|
8
|
+
* still counts (the author sees its effect), release refuses it (decision.in-run, review H1).
|
|
9
|
+
* Never throws: a bad file is a `problem`, a bad override is `rejected`.
|
|
10
|
+
*/
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { isValidScope, PROJECT_SCOPE, DecisionProblem } from '../../decisions/decision-file';
|
|
13
|
+
import { readDecisions, ReadDecision } from '../../decisions/read-decisions';
|
|
14
|
+
import { judgeOverride } from './gate-override-validation';
|
|
15
|
+
import { ActiveOverride, GateRuleContext } from './resolve-rule';
|
|
16
|
+
import { computeDecisionsHash, DecisionsHashItem, problemHashItem } from './decisions-hash';
|
|
17
|
+
import { committedDecisionPaths } from './in-run-decision-check';
|
|
18
|
+
|
|
19
|
+
export interface OverrideIssue {
|
|
20
|
+
decisionId: string;
|
|
21
|
+
path: string;
|
|
22
|
+
rule?: string;
|
|
23
|
+
reason: string;
|
|
24
|
+
entry: ReadDecision;
|
|
25
|
+
committed: boolean | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface UnitGateOverrides {
|
|
29
|
+
unitScope: string | null;
|
|
30
|
+
context: GateRuleContext;
|
|
31
|
+
inForce: ActiveOverride[];
|
|
32
|
+
rejected: OverrideIssue[];
|
|
33
|
+
ineffective: OverrideIssue[];
|
|
34
|
+
/** Files in the two directories that do not verify (DOS-13.3) — reported, never skipped. */
|
|
35
|
+
problems: DecisionProblem[];
|
|
36
|
+
decisionsHash: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** The decision scope of a unit directory (`screens/login`, `api/flows/signup`), or null. */
|
|
40
|
+
export function unitScopeOfDir(projectRoot: string, unitDir: string): string | null {
|
|
41
|
+
const rel = path.relative(path.join(projectRoot, 'qa'), unitDir).split(path.sep).join('/');
|
|
42
|
+
return rel && !rel.startsWith('..') && isValidScope(rel) && rel !== PROJECT_SCOPE ? rel : null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const specificity = (o: ActiveOverride, unitScope: string | null): number => (o.scope === unitScope ? 1 : 0);
|
|
46
|
+
|
|
47
|
+
/** Does `a` take precedence over `b` for the same rule? valid_from is schema-checked ISO; NaN never orders. */
|
|
48
|
+
function wins(a: ActiveOverride, b: ActiveOverride, unitScope: string | null): boolean {
|
|
49
|
+
const s = specificity(a, unitScope) - specificity(b, unitScope);
|
|
50
|
+
if (s !== 0) return s > 0;
|
|
51
|
+
const t = (Date.parse(a.validFrom) || 0) - (Date.parse(b.validFrom) || 0);
|
|
52
|
+
return t !== 0 ? t > 0 : a.decisionId > b.decisionId;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function loadUnitGateOverrides(projectRoot: string, unitScope: string | null): UnitGateOverrides {
|
|
56
|
+
const scopes = unitScope ? [PROJECT_SCOPE, unitScope] : [PROJECT_SCOPE];
|
|
57
|
+
const entries: ReadDecision[] = [];
|
|
58
|
+
const problems: DecisionProblem[] = [];
|
|
59
|
+
for (const s of scopes) {
|
|
60
|
+
const r = readDecisions(projectRoot, s);
|
|
61
|
+
entries.push(...r.entries);
|
|
62
|
+
problems.push(...r.problems);
|
|
63
|
+
}
|
|
64
|
+
const rel = (p: string): string => path.relative(projectRoot, p).split(path.sep).join('/');
|
|
65
|
+
const hashItems: DecisionsHashItem[] = problems.map((p) => problemHashItem(projectRoot, p));
|
|
66
|
+
const byRule = new Map<string, ActiveOverride>();
|
|
67
|
+
const rejected: OverrideIssue[] = [];
|
|
68
|
+
const ineffective: OverrideIssue[] = [];
|
|
69
|
+
// HEAD membership is read once, and only when an override is in reach (two git calls).
|
|
70
|
+
let head: Set<string> | null | undefined;
|
|
71
|
+
const inHead = (p: string): boolean | null => {
|
|
72
|
+
if (head === undefined) head = committedDecisionPaths(projectRoot);
|
|
73
|
+
return head ? head.has(p) : null;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
for (const e of entries.filter((x) => x.kind === 'gate-override')) {
|
|
77
|
+
const j = judgeOverride(e, unitScope);
|
|
78
|
+
if (j.status === 'irrelevant') continue;
|
|
79
|
+
const p = rel(e.path);
|
|
80
|
+
hashItems.push({ path: p, entryHash: e.entry_hash });
|
|
81
|
+
if (e.superseded_by) continue;
|
|
82
|
+
const rule = typeof e.payload?.rule === 'string' ? e.payload.rule : undefined;
|
|
83
|
+
const issue = { decisionId: e.id, path: p, rule, entry: e, committed: inHead(p) };
|
|
84
|
+
if (j.status === 'rejected') { rejected.push({ ...issue, reason: j.reason }); continue; }
|
|
85
|
+
if (j.status === 'ineffective') { ineffective.push({ ...issue, reason: j.reason }); continue; }
|
|
86
|
+
const o: ActiveOverride = { ...j.override, committed: issue.committed };
|
|
87
|
+
const current = byRule.get(o.rule);
|
|
88
|
+
if (!current || wins(o, current, unitScope)) byRule.set(o.rule, o);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
unitScope,
|
|
92
|
+
context: { overrides: byRule },
|
|
93
|
+
inForce: [...byRule.values()].sort((a, b) => a.rule.localeCompare(b.rule, 'en')),
|
|
94
|
+
rejected,
|
|
95
|
+
ineffective,
|
|
96
|
+
problems,
|
|
97
|
+
decisionsHash: computeDecisionsHash(hashItems),
|
|
98
|
+
};
|
|
99
|
+
}
|