@sun-asterisk/sungen 3.2.35 → 3.3.0-alpha.10
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/case-triage-hint.d.ts +14 -0
- package/dist/cli/case-triage-hint.d.ts.map +1 -0
- package/dist/cli/case-triage-hint.js +23 -0
- package/dist/cli/case-triage-hint.js.map +1 -0
- package/dist/cli/commands/audit.js +1 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/capability.js +1 -1
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/contract-derive-command.d.ts +12 -0
- package/dist/cli/commands/contract-derive-command.d.ts.map +1 -0
- package/dist/cli/commands/contract-derive-command.js +113 -0
- package/dist/cli/commands/contract-derive-command.js.map +1 -0
- package/dist/cli/commands/contract.d.ts +20 -0
- package/dist/cli/commands/contract.d.ts.map +1 -0
- package/dist/cli/commands/contract.js +195 -0
- package/dist/cli/commands/contract.js.map +1 -0
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +109 -19
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/gate.d.ts.map +1 -1
- package/dist/cli/commands/gate.js +2 -1
- package/dist/cli/commands/gate.js.map +1 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +17 -3
- 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 +47 -17
- package/dist/cli/commands/journey.js.map +1 -1
- package/dist/cli/commands/next.d.ts +13 -0
- package/dist/cli/commands/next.d.ts.map +1 -1
- package/dist/cli/commands/next.js +98 -9
- package/dist/cli/commands/next.js.map +1 -1
- package/dist/cli/commands/triage.d.ts +2 -1
- package/dist/cli/commands/triage.d.ts.map +1 -1
- package/dist/cli/commands/triage.js +45 -3
- package/dist/cli/commands/triage.js.map +1 -1
- 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 +37 -8
- 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/json-error-on-exit.d.ts +34 -0
- package/dist/cli/json-error-on-exit.d.ts.map +1 -0
- package/dist/cli/json-error-on-exit.js +63 -0
- package/dist/cli/json-error-on-exit.js.map +1 -0
- package/dist/cli/project-sungen-invocation.d.ts +13 -0
- package/dist/cli/project-sungen-invocation.d.ts.map +1 -0
- package/dist/cli/project-sungen-invocation.js +95 -0
- package/dist/cli/project-sungen-invocation.js.map +1 -0
- package/dist/cli/run-command-hints.d.ts +9 -0
- package/dist/cli/run-command-hints.d.ts.map +1 -0
- package/dist/cli/run-command-hints.js +84 -0
- package/dist/cli/run-command-hints.js.map +1 -0
- package/dist/cli/waiting-for-you-block.d.ts +18 -0
- package/dist/cli/waiting-for-you-block.d.ts.map +1 -0
- package/dist/cli/waiting-for-you-block.js +22 -0
- package/dist/cli/waiting-for-you-block.js.map +1 -0
- package/dist/contract/accept-opaque-steps.d.ts +3 -0
- package/dist/contract/accept-opaque-steps.d.ts.map +1 -0
- package/dist/contract/accept-opaque-steps.js +114 -0
- package/dist/contract/accept-opaque-steps.js.map +1 -0
- package/dist/contract/approve-contract.d.ts +38 -0
- package/dist/contract/approve-contract.d.ts.map +1 -0
- package/dist/contract/approve-contract.js +93 -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 +22 -0
- package/dist/contract/build-trace-conformance.d.ts.map +1 -0
- package/dist/contract/build-trace-conformance.js +151 -0
- package/dist/contract/build-trace-conformance.js.map +1 -0
- package/dist/contract/classify-contract-change.d.ts +24 -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 +47 -0
- package/dist/contract/classify-trace-conformance.d.ts.map +1 -0
- package/dist/contract/classify-trace-conformance.js +164 -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 +92 -0
- package/dist/contract/contract-schema.d.ts.map +1 -0
- package/dist/contract/contract-schema.js +124 -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 +141 -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 +49 -0
- package/dist/contract/derive-free-feature.d.ts.map +1 -0
- package/dist/contract/derive-free-feature.js +183 -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 +75 -0
- package/dist/contract/project-contract-blockers.js.map +1 -0
- package/dist/contract/record-contract-approval.d.ts +36 -0
- package/dist/contract/record-contract-approval.d.ts.map +1 -0
- package/dist/contract/record-contract-approval.js +126 -0
- package/dist/contract/record-contract-approval.js.map +1 -0
- package/dist/contract/render-free-gherkin.d.ts +42 -0
- package/dist/contract/render-free-gherkin.d.ts.map +1 -0
- package/dist/contract/render-free-gherkin.js +147 -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 +20 -0
- package/dist/contract/resolve-unit-trace-identities.d.ts.map +1 -0
- package/dist/contract/resolve-unit-trace-identities.js +62 -0
- package/dist/contract/resolve-unit-trace-identities.js.map +1 -0
- package/dist/contract/trace/collect-trace-evidence.d.ts +44 -0
- package/dist/contract/trace/collect-trace-evidence.d.ts.map +1 -0
- package/dist/contract/trace/collect-trace-evidence.js +219 -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/read-file-once.d.ts +20 -0
- package/dist/contract/trace/read-file-once.d.ts.map +1 -0
- package/dist/contract/trace/read-file-once.js +135 -0
- package/dist/contract/trace/read-file-once.js.map +1 -0
- package/dist/contract/trace/scenario-id-claims.d.ts +11 -0
- package/dist/contract/trace/scenario-id-claims.d.ts.map +1 -0
- package/dist/contract/trace/scenario-id-claims.js +89 -0
- package/dist/contract/trace/scenario-id-claims.js.map +1 -0
- package/dist/contract/trace/select-final-attempt.d.ts +29 -0
- package/dist/contract/trace/select-final-attempt.d.ts.map +1 -0
- package/dist/contract/trace/select-final-attempt.js +119 -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 +22 -0
- package/dist/contract/trace/trace-binding.d.ts.map +1 -0
- package/dist/contract/trace/trace-binding.js +91 -0
- package/dist/contract/trace/trace-binding.js.map +1 -0
- package/dist/contract/trace/trace-file-reader.d.ts +47 -0
- package/dist/contract/trace/trace-file-reader.d.ts.map +1 -0
- package/dist/contract/trace/trace-file-reader.js +137 -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-freshness.d.ts +27 -0
- package/dist/contract/trace/trace-freshness.d.ts.map +1 -0
- package/dist/contract/trace/trace-freshness.js +146 -0
- package/dist/contract/trace/trace-freshness.js.map +1 -0
- package/dist/contract/trace/trace-identity-resolution.d.ts +28 -0
- package/dist/contract/trace/trace-identity-resolution.d.ts.map +1 -0
- package/dist/contract/trace/trace-identity-resolution.js +87 -0
- package/dist/contract/trace/trace-identity-resolution.js.map +1 -0
- package/dist/contract/trace/trace-run-record.d.ts +32 -0
- package/dist/contract/trace/trace-run-record.d.ts.map +1 -0
- package/dist/contract/trace/trace-run-record.js +135 -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 +109 -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 +43 -0
- package/dist/decisions/decision-schema.d.ts.map +1 -0
- package/dist/decisions/decision-schema.js +76 -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 +19 -0
- package/dist/decisions/git-head-trust.d.ts.map +1 -0
- package/dist/decisions/git-head-trust.js +128 -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 +38 -0
- package/dist/decisions/legacy-waiver-migration.d.ts.map +1 -0
- package/dist/decisions/legacy-waiver-migration.js +179 -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 +11 -2
- package/dist/exporters/csv-exporter.d.ts.map +1 -1
- package/dist/exporters/csv-exporter.js +8 -4
- package/dist/exporters/csv-exporter.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 +10 -9
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/export.d.ts +9 -1
- package/dist/exporters/matrix/export.d.ts.map +1 -1
- package/dist/exporters/matrix/export.js +13 -4
- 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 +3 -0
- 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 +3 -0
- package/dist/exporters/matrix/render-xlsx.js.map +1 -1
- package/dist/exporters/matrix/types.d.ts +4 -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/test-data-resolver.d.ts.map +1 -1
- package/dist/exporters/test-data-resolver.js +2 -12
- package/dist/exporters/test-data-resolver.js.map +1 -1
- package/dist/exporters/xlsx-exporter.d.ts +3 -2
- package/dist/exporters/xlsx-exporter.d.ts.map +1 -1
- package/dist/exporters/xlsx-exporter.js +4 -4
- package/dist/exporters/xlsx-exporter.js.map +1 -1
- package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
- package/dist/generators/gherkin-parser/index.js +0 -1
- package/dist/generators/gherkin-parser/index.js.map +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/contain-text-assertion.hbs +1 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -13
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -9
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +18 -4
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/diagnostics.d.ts +3 -9
- package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.js +3 -9
- package/dist/generators/test-generator/diagnostics.js.map +1 -1
- package/dist/generators/test-generator/patterns/types.d.ts +1 -1
- package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.d.ts +0 -8
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +8 -52
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/generators/test-generator/utils/data-resolver.d.ts +0 -16
- package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/data-resolver.js +0 -59
- package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +2 -10
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/graph/board-human-actions.d.ts +5 -0
- package/dist/graph/board-human-actions.d.ts.map +1 -0
- package/dist/graph/board-human-actions.js +83 -0
- package/dist/graph/board-human-actions.js.map +1 -0
- package/dist/graph/evaluate-graph.d.ts +41 -0
- package/dist/graph/evaluate-graph.d.ts.map +1 -0
- package/dist/graph/evaluate-graph.js +77 -0
- package/dist/graph/evaluate-graph.js.map +1 -0
- package/dist/graph/human-action.d.ts +21 -0
- package/dist/graph/human-action.d.ts.map +1 -0
- package/dist/graph/human-action.js +3 -0
- package/dist/graph/human-action.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/manual-triage-decisions.d.ts +19 -0
- package/dist/graph/manual-triage-decisions.d.ts.map +1 -0
- package/dist/graph/manual-triage-decisions.js +53 -0
- package/dist/graph/manual-triage-decisions.js.map +1 -0
- package/dist/graph/node-decl.d.ts +75 -0
- package/dist/graph/node-decl.d.ts.map +1 -0
- package/dist/graph/node-decl.js +11 -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 +72 -0
- package/dist/graph/nodes/test-case-contract-nodes.js.map +1 -0
- package/dist/graph/nodes/test-case-nodes.d.ts +29 -0
- package/dist/graph/nodes/test-case-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/test-case-nodes.js +95 -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 +96 -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 +96 -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 +12 -0
- package/dist/graph/test-case-results.d.ts.map +1 -0
- package/dist/graph/test-case-results.js +161 -0
- package/dist/graph/test-case-results.js.map +1 -0
- package/dist/graph/test-case-satisfied.d.ts +26 -0
- package/dist/graph/test-case-satisfied.d.ts.map +1 -0
- package/dist/graph/test-case-satisfied.js +55 -0
- package/dist/graph/test-case-satisfied.js.map +1 -0
- package/dist/graph/test-case-state-shape.d.ts +73 -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 +135 -0
- package/dist/graph/unit-artifact-probes.js.map +1 -0
- package/dist/graph/unit-results-freshness.d.ts +29 -0
- package/dist/graph/unit-results-freshness.d.ts.map +1 -0
- package/dist/graph/unit-results-freshness.js +213 -0
- package/dist/graph/unit-results-freshness.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 +14 -2
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +20 -21
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/catalog/gate-rules.yaml +647 -0
- package/dist/harness/defect-draft.d.ts.map +1 -1
- package/dist/harness/defect-draft.js +12 -2
- package/dist/harness/defect-draft.js.map +1 -1
- package/dist/harness/defects.d.ts +14 -0
- package/dist/harness/defects.d.ts.map +1 -1
- package/dist/harness/defects.js +14 -10
- package/dist/harness/defects.js.map +1 -1
- package/dist/harness/flow-check.d.ts +9 -0
- package/dist/harness/flow-check.d.ts.map +1 -1
- package/dist/harness/flow-check.js +11 -0
- package/dist/harness/flow-check.js.map +1 -1
- 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 +102 -0
- package/dist/harness/gates/audit-gate-verdict.js.map +1 -0
- package/dist/harness/gates/audit-input-hash.d.ts +6 -0
- package/dist/harness/gates/audit-input-hash.d.ts.map +1 -0
- package/dist/harness/gates/audit-input-hash.js +124 -0
- package/dist/harness/gates/audit-input-hash.js.map +1 -0
- package/dist/harness/gates/audit-report-verification.d.ts +43 -0
- package/dist/harness/gates/audit-report-verification.d.ts.map +1 -0
- package/dist/harness/gates/audit-report-verification.js +241 -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 +24 -0
- package/dist/harness/gates/delivery-checklist.d.ts.map +1 -0
- package/dist/harness/gates/delivery-checklist.js +161 -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 +166 -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-import-bounds.d.ts +13 -0
- package/dist/harness/gates/migrated-waiver-import-bounds.d.ts.map +1 -0
- package/dist/harness/gates/migrated-waiver-import-bounds.js +141 -0
- package/dist/harness/gates/migrated-waiver-import-bounds.js.map +1 -0
- package/dist/harness/gates/migrated-waiver-review.d.ts +16 -0
- package/dist/harness/gates/migrated-waiver-review.d.ts.map +1 -0
- package/dist/harness/gates/migrated-waiver-review.js +114 -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 +64 -1
- package/dist/harness/journey.d.ts.map +1 -1
- package/dist/harness/journey.js +258 -34
- 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 +71 -43
- package/dist/harness/manifest.js.map +1 -1
- package/dist/harness/next-step.d.ts +58 -4
- package/dist/harness/next-step.d.ts.map +1 -1
- package/dist/harness/next-step.js +55 -204
- package/dist/harness/next-step.js.map +1 -1
- package/dist/harness/parse.d.ts +7 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +18 -2
- 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 +22 -5
- 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 +41 -38
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/triage-manual-classification.d.ts +32 -0
- package/dist/harness/triage-manual-classification.d.ts.map +1 -0
- package/dist/harness/triage-manual-classification.js +56 -0
- package/dist/harness/triage-manual-classification.js.map +1 -0
- package/dist/harness/unit-paths.d.ts +8 -0
- package/dist/harness/unit-paths.d.ts.map +1 -1
- package/dist/harness/unit-paths.js +23 -1
- package/dist/harness/unit-paths.js.map +1 -1
- package/dist/hooks/bash-read-only-segment.d.ts +9 -0
- package/dist/hooks/bash-read-only-segment.d.ts.map +1 -0
- package/dist/hooks/bash-read-only-segment.js +168 -0
- package/dist/hooks/bash-read-only-segment.js.map +1 -0
- package/dist/hooks/bash-write-targets.d.ts +25 -0
- package/dist/hooks/bash-write-targets.d.ts.map +1 -0
- package/dist/hooks/bash-write-targets.js +266 -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 +13 -0
- package/dist/hooks/guard-protected-paths.d.ts.map +1 -0
- package/dist/hooks/guard-protected-paths.js +116 -0
- package/dist/hooks/guard-protected-paths.js.map +1 -0
- package/dist/hooks/guard-rules.d.ts +20 -0
- package/dist/hooks/guard-rules.d.ts.map +1 -0
- package/dist/hooks/guard-rules.js +130 -0
- package/dist/hooks/guard-rules.js.map +1 -0
- package/dist/hooks/guard-tty-spoof-rule.d.ts +17 -0
- package/dist/hooks/guard-tty-spoof-rule.d.ts.map +1 -0
- package/dist/hooks/guard-tty-spoof-rule.js +22 -0
- package/dist/hooks/guard-tty-spoof-rule.js.map +1 -0
- package/dist/hooks/hand-back-core.d.ts +42 -0
- package/dist/hooks/hand-back-core.d.ts.map +1 -0
- package/dist/hooks/hand-back-core.js +128 -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 +14 -0
- package/dist/hooks/session-start-unit-state-hook.d.ts.map +1 -0
- package/dist/hooks/session-start-unit-state-hook.js +60 -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 +43 -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/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- 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 +11 -3
- package/dist/orchestrator/ai-skills/commands.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/templates/ai-src/commands/add-api.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/add-flow.md +6 -26
- 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 +17 -16
- package/dist/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/delivery.md +4 -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 +4 -0
- package/dist/orchestrator/templates/ai-src/commands/run-test.md +6 -8
- 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/partials/waiting-for-you.claude.md +11 -0
- package/dist/orchestrator/templates/ai-src/partials/waiting-for-you.codex.md +11 -0
- package/dist/orchestrator/templates/ai-src/partials/waiting-for-you.copilot.md +11 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +1 -2
- package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +4 -5
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +8 -24
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +3 -4
- package/dist/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
- package/dist/orchestrator/templates/specs-test-data.ts +4 -22
- 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/case-triage-hint.ts +31 -0
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/capability.ts +1 -1
- package/src/cli/commands/contract-derive-command.ts +72 -0
- package/src/cli/commands/contract.ts +164 -0
- package/src/cli/commands/delivery.ts +106 -19
- package/src/cli/commands/gate.ts +2 -1
- package/src/cli/commands/generate.ts +16 -3
- package/src/cli/commands/journey.ts +45 -18
- package/src/cli/commands/next.ts +92 -11
- package/src/cli/commands/triage.ts +41 -3
- package/src/cli/commands/update.ts +41 -10
- package/src/cli/index.ts +24 -30
- package/src/cli/json-error-on-exit.ts +72 -0
- package/src/cli/project-sungen-invocation.ts +59 -0
- package/src/cli/run-command-hints.ts +47 -0
- package/src/cli/waiting-for-you-block.ts +27 -0
- package/src/contract/accept-opaque-steps.ts +114 -0
- package/src/contract/approve-contract.ts +101 -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 +103 -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 +170 -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 +166 -0
- package/src/contract/contract-units.ts +52 -0
- package/src/contract/contracts-lock-file.ts +98 -0
- package/src/contract/data-normalize.ts +66 -0
- package/src/contract/derive-free-feature.ts +153 -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 +38 -0
- package/src/contract/record-contract-approval.ts +110 -0
- package/src/contract/render-free-gherkin.ts +118 -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 +58 -0
- package/src/contract/trace/collect-trace-evidence.ts +178 -0
- package/src/contract/trace/identity-cache.ts +61 -0
- package/src/contract/trace/read-file-once.ts +95 -0
- package/src/contract/trace/scenario-id-claims.ts +60 -0
- package/src/contract/trace/select-final-attempt.ts +77 -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 +59 -0
- package/src/contract/trace/trace-file-reader.ts +144 -0
- package/src/contract/trace/trace-fingerprint.ts +68 -0
- package/src/contract/trace/trace-freshness.ts +110 -0
- package/src/contract/trace/trace-identity-resolution.ts +77 -0
- package/src/contract/trace/trace-run-record.ts +96 -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 +64 -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 +77 -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 +76 -0
- package/src/decisions/human-confirmation.ts +119 -0
- package/src/decisions/legacy-waiver-migration.ts +146 -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 +12 -4
- package/src/exporters/matrix/build.ts +11 -9
- package/src/exporters/matrix/export.ts +16 -4
- package/src/exporters/matrix/gates.ts +62 -129
- package/src/exporters/matrix/render-csv.ts +3 -0
- package/src/exporters/matrix/render-gate-overrides-sheet.ts +50 -0
- package/src/exporters/matrix/render-xlsx.ts +3 -0
- package/src/exporters/matrix/types.ts +4 -1
- package/src/exporters/matrix/xlsx-cells.ts +1 -1
- package/src/exporters/test-data-resolver.ts +2 -10
- package/src/exporters/xlsx-exporter.ts +5 -4
- package/src/generators/gherkin-parser/index.ts +0 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/contain-text-assertion.hbs +1 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -13
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -9
- package/src/generators/test-generator/code-generator.ts +17 -4
- package/src/generators/test-generator/diagnostics.ts +3 -9
- package/src/generators/test-generator/patterns/types.ts +0 -2
- package/src/generators/test-generator/step-mapper.ts +9 -56
- package/src/generators/test-generator/utils/data-resolver.ts +0 -53
- package/src/generators/test-generator/utils/selector-resolver.ts +2 -10
- package/src/graph/board-human-actions.ts +80 -0
- package/src/graph/evaluate-graph.ts +97 -0
- package/src/graph/human-action.ts +33 -0
- package/src/graph/locate-finding.ts +93 -0
- package/src/graph/manual-triage-decisions.ts +55 -0
- package/src/graph/node-decl.ts +83 -0
- package/src/graph/nodes/core-node-catalog.ts +15 -0
- package/src/graph/nodes/test-case-contract-nodes.ts +90 -0
- package/src/graph/nodes/test-case-nodes.ts +100 -0
- package/src/graph/nodes/unit-audit-nodes.ts +96 -0
- package/src/graph/nodes/unit-contract-node.ts +100 -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 +111 -0
- package/src/graph/test-case-satisfied.ts +58 -0
- package/src/graph/test-case-state-shape.ts +67 -0
- package/src/graph/test-case-states.ts +84 -0
- package/src/graph/unit-artifact-probes.ts +79 -0
- package/src/graph/unit-results-freshness.ts +165 -0
- package/src/graph/unit-state-facts.ts +112 -0
- package/src/harness/audit.ts +31 -18
- package/src/harness/catalog/gate-rules.yaml +647 -0
- package/src/harness/defect-draft.ts +13 -2
- package/src/harness/defects.ts +22 -9
- package/src/harness/flow-check.ts +11 -0
- package/src/harness/gates/audit-gate-terms.ts +80 -0
- package/src/harness/gates/audit-gate-verdict.ts +79 -0
- package/src/harness/gates/audit-input-hash.ts +79 -0
- package/src/harness/gates/audit-report-verification.ts +206 -0
- package/src/harness/gates/decisions-hash.ts +42 -0
- package/src/harness/gates/delivery-checklist.ts +152 -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 +124 -0
- package/src/harness/gates/journey-gate-inputs.ts +89 -0
- package/src/harness/gates/migrated-waiver-import-bounds.ts +103 -0
- package/src/harness/gates/migrated-waiver-review.ts +121 -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 +287 -39
- package/src/harness/manifest.ts +67 -43
- package/src/harness/next-step.ts +91 -193
- package/src/harness/parse.ts +20 -2
- package/src/harness/provenance.ts +99 -11
- package/src/harness/script-check.ts +20 -5
- package/src/harness/sensors.ts +47 -40
- package/src/harness/triage-manual-classification.ts +76 -0
- package/src/harness/unit-paths.ts +19 -0
- package/src/hooks/bash-read-only-segment.ts +130 -0
- package/src/hooks/bash-write-targets.ts +195 -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 +80 -0
- package/src/hooks/guard-rules.ts +117 -0
- package/src/hooks/guard-tty-spoof-rule.ts +34 -0
- package/src/hooks/hand-back-core.ts +118 -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 +59 -0
- package/src/hooks/stop-next-step-hook.ts +38 -0
- package/src/hooks/sungen-project-root.ts +80 -0
- package/src/index.ts +1 -2
- package/src/orchestrator/ai-skills/command-partial-includes.ts +72 -0
- package/src/orchestrator/ai-skills/commands.ts +17 -5
- 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/templates/ai-src/commands/add-api.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/add-flow.md +6 -26
- 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 +17 -16
- package/src/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/delivery.md +4 -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 +4 -0
- package/src/orchestrator/templates/ai-src/commands/run-test.md +6 -8
- 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/partials/waiting-for-you.claude.md +11 -0
- package/src/orchestrator/templates/ai-src/partials/waiting-for-you.codex.md +11 -0
- package/src/orchestrator/templates/ai-src/partials/waiting-for-you.copilot.md +11 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +1 -2
- package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +4 -5
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +8 -24
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +3 -4
- package/src/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
- package/src/orchestrator/templates/specs-test-data.ts +4 -22
- package/src/utils/safe-yaml-parse.ts +44 -0
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/expanded-assertion.hbs +0 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/date-picker-unsupported.hbs +0 -5
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/expanded-assertion.hbs +0 -12
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/expanded-assertion.hbs +0 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/date-picker-unsupported.hbs +0 -5
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/expanded-assertion.hbs +0 -12
package/src/harness/defects.ts
CHANGED
|
@@ -66,24 +66,37 @@ export function readDefects(cwd: string): DefectRecord[] {
|
|
|
66
66
|
return out;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Everything the defect-link findings of one unit read off qa/defects/ — and so what the audit's
|
|
71
|
+
* inputsHash covers there (#927): the unit's `@known-defect:<id>` tags with no record, in tag order,
|
|
72
|
+
* and the unit's OPEN records with the scenarios they name. Title, severity and prose are not read,
|
|
73
|
+
* so editing them never asks for a re-audit.
|
|
74
|
+
*/
|
|
75
|
+
export interface DefectLinkInputs { missing: string[]; open: Array<{ id: string; scenarios: string[] }> }
|
|
76
|
+
|
|
77
|
+
export function defectLinkInputs(cwd: string, unitId: string, featureText: string): DefectLinkInputs {
|
|
78
|
+
const records = readDefects(cwd);
|
|
79
|
+
const known = new Set(records.map((r) => r.id));
|
|
80
|
+
const tagged = [...new Set([...featureText.matchAll(KNOWN_DEFECT_TAG)].map((m) => m[1]))];
|
|
81
|
+
return {
|
|
82
|
+
missing: tagged.filter((id) => !known.has(id)),
|
|
83
|
+
open: records.filter((r) => r.status === 'open' && r.units.includes(unitId)).map((r) => ({ id: r.id, scenarios: r.scenarios })),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
69
87
|
/**
|
|
70
88
|
* Advisory audit findings for one unit (never scored):
|
|
71
89
|
* DEFECT-REF-MISSING a `@known-defect:DEF-NNN` tag with no record file.
|
|
72
90
|
* DEFECT-ORPHAN (info) an OPEN record of this unit names a scenario the unit no longer has.
|
|
73
91
|
*/
|
|
74
92
|
export function defectLinkFindings(cwd: string, unitId: string, featureText: string, scenarioNames: string[]): string[] {
|
|
75
|
-
const
|
|
93
|
+
const { missing, open } = defectLinkInputs(cwd, unitId, featureText);
|
|
76
94
|
const findings: string[] = [];
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
for (const id of tagged) {
|
|
80
|
-
if (!known.has(id)) {
|
|
81
|
-
findings.push(`DEFECT-REF-MISSING: \`@known-defect:${id}\` has no record in qa/defects/ — draft it with \`sungen defect draft --screen ${unitId}\`, or correct the id.`);
|
|
82
|
-
}
|
|
95
|
+
for (const id of missing) {
|
|
96
|
+
findings.push(`DEFECT-REF-MISSING: \`@known-defect:${id}\` has no record in qa/defects/ — draft it with \`sungen defect draft --screen ${unitId}\`, or correct the id.`);
|
|
83
97
|
}
|
|
84
98
|
const names = new Set(scenarioNames);
|
|
85
|
-
for (const r of
|
|
86
|
-
if (r.status !== 'open' || !r.units.includes(unitId)) continue;
|
|
99
|
+
for (const r of open) {
|
|
87
100
|
for (const s of r.scenarios) {
|
|
88
101
|
if (!names.has(s)) {
|
|
89
102
|
findings.push(`DEFECT-ORPHAN (info): ${r.id} is open and names scenario "${s}", which ${unitId} no longer has — update the record's scenarios, or close it.`);
|
|
@@ -70,6 +70,17 @@ export function loadFlowScenarios(cwd: string): FlowScenario[] {
|
|
|
70
70
|
return out;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* What a screen audit reads from its sibling flows (#927): the scenarios that can credit a gate theme
|
|
75
|
+
* — only deep ones do (flowCoveredThemes) — by flow and haystack. The screen's inputsHash covers them,
|
|
76
|
+
* sorted so the hash does not depend on directory order; a shallow scenario or prose moves nothing.
|
|
77
|
+
*/
|
|
78
|
+
export function flowCreditInputs(cwd: string): Array<{ flow: string; haystack: string }> {
|
|
79
|
+
const key = (s: { flow: string; haystack: string }): string => `${s.flow}\n${s.haystack}`;
|
|
80
|
+
return loadFlowScenarios(cwd).filter((s) => s.deep).map(({ flow, haystack }) => ({ flow, haystack }))
|
|
81
|
+
.sort((a, b) => (key(a) < key(b) ? -1 : key(a) > key(b) ? 1 : 0));
|
|
82
|
+
}
|
|
83
|
+
|
|
73
84
|
export function buildFlowCheck(cwd: string, onlyFlow?: string): FlowCheckReport {
|
|
74
85
|
const screens = listDirs(path.join(cwd, 'qa', 'screens'));
|
|
75
86
|
const flows = (onlyFlow ? [onlyFlow] : listDirs(path.join(cwd, 'qa', 'flows')));
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The audit's gateStatus conjunction, in ONE place (OES-11.2): `runAudit` evaluates it to set
|
|
3
|
+
* gateStatus, and `verifyAuditReport` re-evaluates it from the report's own fields to catch a stored
|
|
4
|
+
* PASS the report cannot reproduce (a hand-flipped gateStatus + exitCode — tester finding m1).
|
|
5
|
+
*
|
|
6
|
+
* Each term names its catalog rule; `resolveRule` decides whether a violated one blocks. The decision
|
|
7
|
+
* layer adds three hard terms: a rejected override, a decision file that does not verify (id / hash).
|
|
8
|
+
* Re-evaluating catches casual tampering only: a forger who also rewrites every finding, gap and
|
|
9
|
+
* verdict in the report is out of scope here, as for inputsHash (anti-staleness, not anti-forgery).
|
|
10
|
+
*/
|
|
11
|
+
import { evaluateGateTerms, GateTerm } from './gate-terms';
|
|
12
|
+
import { trackGateRules } from './resolve-rule';
|
|
13
|
+
import { UnitGateOverrides } from './unit-gate-overrides';
|
|
14
|
+
|
|
15
|
+
/** The report fields the conjunction reads — present in every report runAudit writes. */
|
|
16
|
+
export interface AuditTermSources {
|
|
17
|
+
gate: { gaps: unknown[] };
|
|
18
|
+
depth: { verdict: string };
|
|
19
|
+
claim: { verdict: string };
|
|
20
|
+
spec: { verdict: string };
|
|
21
|
+
taxonomyMismatch: boolean;
|
|
22
|
+
gateSensorError: boolean;
|
|
23
|
+
reusedScenarioIds: unknown[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function auditGateTerms(r: AuditTermSources): GateTerm[] {
|
|
27
|
+
return [
|
|
28
|
+
{ rule: 'audit.viewpoint-coverage', holds: r.gate.gaps.length === 0 },
|
|
29
|
+
{ rule: 'audit.assertion-depth', holds: r.depth.verdict !== 'fail' },
|
|
30
|
+
{ rule: 'audit.claim-proof', holds: r.claim.verdict !== 'fail' },
|
|
31
|
+
{ rule: 'audit.spec-coverage', holds: r.spec.verdict !== 'fail' },
|
|
32
|
+
{ rule: 'audit.taxonomy-mismatch', holds: !r.taxonomyMismatch },
|
|
33
|
+
// An 'error' finding from a capability gate sensor (api, db, …) — the driver's own verdict.
|
|
34
|
+
{ rule: 'audit.gate-sensor-error', holds: !r.gateSensorError },
|
|
35
|
+
// #694 — a reused id reaches the deliverable as two rows under one testcase id.
|
|
36
|
+
{ rule: 'audit.scenario-id-reuse', holds: r.reusedScenarioIds.length === 0 },
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function decisionTerms(o: UnitGateOverrides): GateTerm[] {
|
|
41
|
+
return [
|
|
42
|
+
{ rule: 'gate.override-rejected', holds: o.rejected.length === 0 },
|
|
43
|
+
{ rule: 'decision.id-reuse', holds: !o.problems.some((p) => p.code === 'id-mismatch') },
|
|
44
|
+
{ rule: 'decision.mutated', holds: !o.problems.some((p) => p.code !== 'id-mismatch') },
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** The gateStatus a report's own terms produce under the unit's overrides — what the audit computed. */
|
|
49
|
+
export function recomputeAuditGateStatus(sources: AuditTermSources, overrides: UnitGateOverrides): 'PASS' | 'FAIL' {
|
|
50
|
+
const outcome = evaluateGateTerms([...auditGateTerms(sources), ...decisionTerms(overrides)], trackGateRules(overrides.context));
|
|
51
|
+
return outcome.pass ? 'PASS' : 'FAIL';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const isObj = (v: unknown): v is Record<string, unknown> => !!v && typeof v === 'object' && !Array.isArray(v);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The term sources of a parsed audit.json. `strict` (a current report): every field must be there with
|
|
58
|
+
* its type, else null. Not strict (a legacy report, written before some fields): a missing field reads
|
|
59
|
+
* as "holds", so only a stored PASS that a present field contradicts can be caught.
|
|
60
|
+
*/
|
|
61
|
+
export function termSourcesOf(r: Record<string, unknown>, strict: boolean): AuditTermSources | null {
|
|
62
|
+
const verdict = (k: string): string | null | undefined => {
|
|
63
|
+
const v = r[k];
|
|
64
|
+
if (!isObj(v)) return strict ? null : undefined;
|
|
65
|
+
return typeof v.verdict === 'string' ? v.verdict : strict ? null : undefined;
|
|
66
|
+
};
|
|
67
|
+
const gaps = isObj(r.gate) && Array.isArray(r.gate.gaps) ? r.gate.gaps : strict ? null : [];
|
|
68
|
+
const depth = verdict('depth');
|
|
69
|
+
const claim = verdict('claim');
|
|
70
|
+
const spec = verdict('spec');
|
|
71
|
+
const flag = (k: string): boolean | null => (typeof r[k] === 'boolean' ? r[k] as boolean : strict ? null : false);
|
|
72
|
+
const taxonomyMismatch = flag('taxonomyMismatch');
|
|
73
|
+
const gateSensorError = flag('gateSensorError');
|
|
74
|
+
const reused = Array.isArray(r.reusedScenarioIds) ? r.reusedScenarioIds : strict ? null : [];
|
|
75
|
+
if ([gaps, depth, claim, spec, taxonomyMismatch, gateSensorError, reused].some((x) => x === null)) return null;
|
|
76
|
+
return {
|
|
77
|
+
gate: { gaps: gaps as unknown[] }, depth: { verdict: depth ?? 'pass' }, claim: { verdict: claim ?? 'pass' }, spec: { verdict: spec ?? 'pass' },
|
|
78
|
+
taxonomyMismatch: taxonomyMismatch as boolean, gateSensorError: gateSensorError as boolean, reusedScenarioIds: reused as unknown[],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The audit's side of the gate registry (OES-11.2/11.4): load the unit's gate overrides, hand the
|
|
3
|
+
* tracked rules to the sensors, evaluate the gateStatus conjunction, and produce the fields the
|
|
4
|
+
* report records so readers can verify it (takumi T3):
|
|
5
|
+
*
|
|
6
|
+
* gateOverrides[] every override touching the unit, applied / ineffective / rejected
|
|
7
|
+
* decisionsHash the overrides it was judged under (stale when they change)
|
|
8
|
+
* inputsHash .feature + spec + viewpoint + … + decisionsHash, and the defect records and
|
|
9
|
+
* crediting flows it reads (audit-input-hash.ts, #927)
|
|
10
|
+
* exitCode 0 on PASS, 2 on FAIL — what `sungen audit` exits with
|
|
11
|
+
*
|
|
12
|
+
* The decision layer adds three hard terms: a rejected override (gate.override-rejected) and a
|
|
13
|
+
* decision file in the unit's reach that does not verify (decision.id-reuse / decision.mutated).
|
|
14
|
+
* With no decision at all none of this changes an outcome.
|
|
15
|
+
*/
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { projectRootFromScreenDir } from '../intent';
|
|
18
|
+
import { auditInputsHash } from './audit-input-hash';
|
|
19
|
+
import { evaluateGateTerms, ruleVerdict, SensorVerdict } from './gate-terms';
|
|
20
|
+
import { auditGateTerms, AuditTermSources, decisionTerms } from './audit-gate-terms';
|
|
21
|
+
import { GateOverrideReport, gateOverrideReports } from './gate-override-report';
|
|
22
|
+
import { GateRules, TrackedGateRules, trackGateRules } from './resolve-rule';
|
|
23
|
+
import { loadUnitGateOverrides, unitScopeOfDir, UnitGateOverrides } from './unit-gate-overrides';
|
|
24
|
+
|
|
25
|
+
export const AUDIT_EXIT_CODE = { PASS: 0, FAIL: 2 } as const;
|
|
26
|
+
|
|
27
|
+
export interface AuditGateContext {
|
|
28
|
+
projectRoot: string;
|
|
29
|
+
overrides: UnitGateOverrides;
|
|
30
|
+
rules: TrackedGateRules;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function auditGateContext(unitDir: string): AuditGateContext {
|
|
34
|
+
const projectRoot = projectRootFromScreenDir(unitDir);
|
|
35
|
+
const overrides = loadUnitGateOverrides(projectRoot, unitScopeOfDir(projectRoot, unitDir));
|
|
36
|
+
return { projectRoot, overrides, rules: trackGateRules(overrides.context) };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** A depth verdict a capability computed with the catalog alone, re-levelled for this unit's rules. */
|
|
40
|
+
export function relevelProvidedDepth<T extends { verdict: SensorVerdict }>(depth: T, rules: GateRules): T {
|
|
41
|
+
if (depth.verdict !== 'fail') return depth;
|
|
42
|
+
const verdict = ruleVerdict(rules, 'audit.assertion-depth', true, false);
|
|
43
|
+
return verdict === 'fail' ? depth : { ...depth, verdict };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Findings for the decision layer — empty when the unit has no override and no bad decision file. */
|
|
47
|
+
export function decisionFindings(ctx: AuditGateContext): string[] {
|
|
48
|
+
const o = ctx.overrides;
|
|
49
|
+
const rel = (p: string): string => path.relative(ctx.projectRoot, p).split(path.sep).join('/');
|
|
50
|
+
return [
|
|
51
|
+
...o.rejected.map((r) => `GATE-OVERRIDE-REJECTED (gate.override-rejected): ${r.decisionId} in ${r.path} cannot apply — ${r.reason}. Record a valid override that supersedes it.`),
|
|
52
|
+
...o.ineffective.map((r) => `GATE-OVERRIDE-INEFFECTIVE: ${r.decisionId} (${r.rule ?? '?'}) in ${r.path} relaxes nothing — ${r.reason}. Record it with \`sungen journey --decide gate-override\` on a terminal.`),
|
|
53
|
+
...o.problems.map((p) => `${p.code === 'id-mismatch' ? 'DECISION-ID-REUSED (decision.id-reuse)' : 'DECISION-UNVERIFIABLE (decision.mutated)'}: ${rel(p.path)} — ${p.message}. Restore it from git; change a decision by recording a superseding one.`),
|
|
54
|
+
...o.inForce.map((x) => `GATE-OVERRIDDEN: ${x.rule} is ${x.severity} for ${x.scope} (catalog level lowered by ${x.decisionId}, recorded by ${x.by}) — ${x.reason}`),
|
|
55
|
+
// Review H1: it counts here so its author sees the effect; release refuses it until reviewed.
|
|
56
|
+
...o.inForce.filter((x) => x.committed === false).map((x) => `GATE-OVERRIDE-UNCOMMITTED: ${x.decisionId} (${x.rule}) is not in git HEAD — it counts in this audit, but \`sungen gate --phase deliver\` and \`sungen delivery\` refuse it (decision.in-run) until it is committed through review.`),
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface AuditGateVerdict {
|
|
61
|
+
gateStatus: 'PASS' | 'FAIL';
|
|
62
|
+
gateOverrides: GateOverrideReport[];
|
|
63
|
+
decisionsHash: string;
|
|
64
|
+
inputsHash: string;
|
|
65
|
+
exitCode: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Evaluate the gateStatus conjunction (audit-gate-terms.ts, shared with the reader) and the verifiable fields. */
|
|
69
|
+
export function auditGateVerdict(ctx: AuditGateContext, sources: AuditTermSources, unitDir: string, unitName: string): AuditGateVerdict {
|
|
70
|
+
const outcome = evaluateGateTerms([...auditGateTerms(sources), ...decisionTerms(ctx.overrides)], ctx.rules);
|
|
71
|
+
const gateStatus = outcome.pass ? 'PASS' : 'FAIL';
|
|
72
|
+
return {
|
|
73
|
+
gateStatus,
|
|
74
|
+
gateOverrides: gateOverrideReports(ctx.overrides, ctx.rules.triggered()),
|
|
75
|
+
decisionsHash: ctx.overrides.decisionsHash,
|
|
76
|
+
inputsHash: auditInputsHash(unitDir, unitName, ctx.overrides.decisionsHash),
|
|
77
|
+
exitCode: AUDIT_EXIT_CODE[gateStatus],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `inputsHash` of an audit (OES-11.4, takumi T3): the hash of what the audit judged plus the
|
|
3
|
+
* `decisionsHash` it was judged under. A reader recomputes it; any difference means the report no
|
|
4
|
+
* longer describes the unit, so it counts as never audited.
|
|
5
|
+
*
|
|
6
|
+
* It is ANTI-STALENESS, NOT ANTI-FORGERY: anyone who can write audit.json can also compute this hash
|
|
7
|
+
* (the function is public). It catches a report that outlived its inputs; verdicts built by code and
|
|
8
|
+
* the git-HEAD checks on decisions are what stand against a forger.
|
|
9
|
+
*
|
|
10
|
+
* Inputs — every file whose change can move a verdict:
|
|
11
|
+
* the unit's .feature files · requirements/spec.md · requirements/test-viewpoint.md ·
|
|
12
|
+
* requirements/flow-contract.yaml · requirements/spec_figma.md · requirements/ui-inventory.md ·
|
|
13
|
+
* requirements/ui/* · qa/context.md (intent focus → thresholds) · qa/capabilities.yaml (platform,
|
|
14
|
+
* enabled drivers → gate sensors)
|
|
15
|
+
* and what it reads outside the unit (#927), as the audit reads it — not the files whole, so a
|
|
16
|
+
* re-audit is asked for only when the verdict can move:
|
|
17
|
+
* defects qa/defects/: the unit's `@known-defect:<id>` tags with no record, and its OPEN records
|
|
18
|
+
* with their scenarios (defectLinkInputs — DEFECT-REF-MISSING, DEFECT-ORPHAN)
|
|
19
|
+
* flowCredit a SCREEN's sibling flows: the deep scenarios that can credit a gate theme
|
|
20
|
+
* (flowCreditInputs — TQ-4, COVERED-VIA-FLOW); a flow or api unit is never credited
|
|
21
|
+
* Each is part of the hash only when it holds something, so a project with neither keeps the hash it
|
|
22
|
+
* had; a report written before #927 in a project with either reads stale once.
|
|
23
|
+
*/
|
|
24
|
+
import { createHash } from 'crypto';
|
|
25
|
+
import * as fs from 'fs';
|
|
26
|
+
import * as path from 'path';
|
|
27
|
+
import { canonicalJson } from '../../decisions/decision-identity';
|
|
28
|
+
import { defectLinkInputs } from '../defects';
|
|
29
|
+
import { flowCreditInputs } from '../flow-check';
|
|
30
|
+
import { projectRootFromScreenDir } from '../intent';
|
|
31
|
+
import { catalogIdFromScreenDir, featureFilesFor, isScreenUnitId } from '../unit-paths';
|
|
32
|
+
|
|
33
|
+
const sha256 = (s: string | Buffer): string => createHash('sha256').update(s).digest('hex');
|
|
34
|
+
|
|
35
|
+
function fileSha(file: string): string | null {
|
|
36
|
+
try { return sha256(fs.readFileSync(file)); } catch { return null; }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function filesIn(dir: string): string[] {
|
|
40
|
+
try {
|
|
41
|
+
return fs.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => path.join(dir, e.name)).sort();
|
|
42
|
+
} catch { return []; }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The audit's input files that exist, in a stable order. */
|
|
46
|
+
export function auditInputFiles(unitDir: string, unitName: string): string[] {
|
|
47
|
+
const req = path.join(unitDir, 'requirements');
|
|
48
|
+
const qa = path.join(projectRootFromScreenDir(unitDir), 'qa');
|
|
49
|
+
const candidates = [
|
|
50
|
+
...featureFilesFor(unitDir, unitName),
|
|
51
|
+
...['spec.md', 'test-viewpoint.md', 'flow-contract.yaml', 'spec_figma.md', 'ui-inventory.md'].map((f) => path.join(req, f)),
|
|
52
|
+
...filesIn(path.join(req, 'ui')),
|
|
53
|
+
path.join(qa, 'context.md'),
|
|
54
|
+
path.join(qa, 'capabilities.yaml'),
|
|
55
|
+
];
|
|
56
|
+
return candidates.filter((f) => fs.existsSync(f));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** What the audit reads outside the unit — each key only when it holds something. */
|
|
60
|
+
function crossUnitInputs(root: string, unitDir: string, unitName: string): Record<string, unknown> {
|
|
61
|
+
const unitId = catalogIdFromScreenDir(unitDir);
|
|
62
|
+
const featureText = featureFilesFor(unitDir, unitName).map((f) => { try { return fs.readFileSync(f, 'utf8'); } catch { return ''; } }).join('\n');
|
|
63
|
+
const defects = defectLinkInputs(root, unitId, featureText);
|
|
64
|
+
const flowCredit = isScreenUnitId(unitId) ? flowCreditInputs(root) : [];
|
|
65
|
+
return { ...(defects.missing.length || defects.open.length ? { defects } : {}), ...(flowCredit.length ? { flowCredit } : {}) };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function auditInputsHash(unitDir: string, unitName: string, decisionsHash: string): string {
|
|
69
|
+
const root = projectRootFromScreenDir(unitDir);
|
|
70
|
+
const inputs = auditInputFiles(unitDir, unitName)
|
|
71
|
+
.map((f) => ({ file: path.relative(root, f).split(path.sep).join('/'), sha: fileSha(f) }));
|
|
72
|
+
return sha256(canonicalJson({ schema: 2, inputs, decisionsHash, ...crossUnitInputs(root, unitDir, unitName) }));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** The stale reason when the inputsHash moved — it names every kind of input, the ones outside the unit too. */
|
|
76
|
+
export function auditInputsChangedReason(unitDir: string): string {
|
|
77
|
+
const outside = isScreenUnitId(catalogIdFromScreenDir(unitDir)) ? 'the defect records and sibling flows it reads' : 'the defect records it reads';
|
|
78
|
+
return `an input the audit judged (.feature, spec, viewpoint, context, design, or ${outside}) changed since this audit`;
|
|
79
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading `audit.json` back without trusting it (takumi T3, DOS-14.0, OES-11.4). The report is an
|
|
3
|
+
* OUTPUT of `sungen audit`; every reader (journey/gate, delivery, and `next` via this module) checks:
|
|
4
|
+
*
|
|
5
|
+
* schema a JSON object; only the keys the audit writes; known keys have their type
|
|
6
|
+
* status `gateStatus` is PASS|FAIL and agrees with the integer `exitCode` (0 | 2)
|
|
7
|
+
* inputs `inputsHash` equals the hash of today's inputs + decisions (audit-input-hash.ts)
|
|
8
|
+
* decisions `decisionsHash` equals today's — otherwise the audit is stale: re-audit
|
|
9
|
+
* rules `provenance.catalogHash` and `provenance.rulesHash` are the running sungen's — other
|
|
10
|
+
* catalogs or another AUDIT_RULES_VERSION scored it (a 3.2 PASS can be a 3.3 FAIL on the
|
|
11
|
+
* same files): stale, re-audit. Missing → stale (fail closed). The package VERSION
|
|
12
|
+
* alone is not a reason: a newer sungen with the same rules gives the same verdict (W4)
|
|
13
|
+
* verdict gateStatus re-evaluated from the report's own terms (audit-gate-terms.ts) under the
|
|
14
|
+
* overrides in force — a flipped gateStatus + exitCode is `verdict-mismatch` (tester m1)
|
|
15
|
+
* Anything else counts as NEVER AUDITED, not as clean; only an explicit `gateStatus: PASS` passes.
|
|
16
|
+
* These checks are anti-STALENESS and anti-casual-tamper, NOT anti-forgery: a writer of audit.json can
|
|
17
|
+
* recompute the hashes, and one who rewrites every finding, gap and verdict is out of scope here.
|
|
18
|
+
*
|
|
19
|
+
* Legacy (DOS-11.4, #933): a report written before these fields existed carries none of exitCode /
|
|
20
|
+
* inputsHash / decisionsHash / gateOverrides, so nothing in it can vouch for today's inputs. It reads
|
|
21
|
+
* STALE — one `sungen audit` records a current one. (It used to count while no input file was newer:
|
|
22
|
+
* a fresh checkout gives every file the checkout's mtime, so that proved nothing and an old PASS was
|
|
23
|
+
* trusted.) A legacy report claiming a PASS its own fields contradict is invalid. A report carrying
|
|
24
|
+
* SOME of the fields is malformed.
|
|
25
|
+
*/
|
|
26
|
+
import * as fs from 'fs';
|
|
27
|
+
import * as path from 'path';
|
|
28
|
+
import { resolveUnitCandidates } from '../../cli/resolve-unit';
|
|
29
|
+
import { reportSlug } from '../unit-paths';
|
|
30
|
+
import { getProvenance } from '../provenance';
|
|
31
|
+
import { auditInputsChangedReason, auditInputsHash } from './audit-input-hash';
|
|
32
|
+
import { AUDIT_EXIT_CODE } from './audit-gate-verdict';
|
|
33
|
+
import { recomputeAuditGateStatus, termSourcesOf } from './audit-gate-terms';
|
|
34
|
+
import { EMPTY_DECISIONS_HASH } from './decisions-hash';
|
|
35
|
+
import { loadUnitGateOverrides, unitScopeOfDir, UnitGateOverrides } from './unit-gate-overrides';
|
|
36
|
+
|
|
37
|
+
export type AuditState = 'absent' | 'verified' | 'stale' | 'invalid';
|
|
38
|
+
export type AuditProblemCode = 'unreadable' | 'unknown-key' | 'bad-type' | 'partial-fields' | 'status-exit-mismatch'
|
|
39
|
+
| 'unit-unresolved' | 'decisions-changed' | 'inputs-changed' | 'rules-changed' | 'legacy-with-overrides' | 'legacy-unverified' | 'verdict-mismatch';
|
|
40
|
+
|
|
41
|
+
export interface AuditVerification {
|
|
42
|
+
state: AuditState;
|
|
43
|
+
problems: Array<{ code: AuditProblemCode; message: string }>;
|
|
44
|
+
/** Caveats on a report that counts. */
|
|
45
|
+
notes: string[];
|
|
46
|
+
/** The parsed report — only when it counts (verified). */
|
|
47
|
+
report: Record<string, unknown> | null;
|
|
48
|
+
path: string;
|
|
49
|
+
/** Today's decisionsHash for the unit (what a fresh audit would record). */
|
|
50
|
+
currentDecisionsHash: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** A string field of the report's provenance, or null when it does not say. */
|
|
54
|
+
function provenanceField(r: Record<string, unknown>, key: 'sungenVersion' | 'catalogHash' | 'rulesHash'): string | null {
|
|
55
|
+
const v = r.provenance && typeof r.provenance === 'object' ? (r.provenance as Record<string, unknown>)[key] : undefined;
|
|
56
|
+
return typeof v === 'string' && v ? v : null;
|
|
57
|
+
}
|
|
58
|
+
const writtenBy = (r: Record<string, unknown>): string | null => provenanceField(r, 'sungenVersion');
|
|
59
|
+
|
|
60
|
+
export interface RulesStamp { catalogHash: string | null; rulesHash: string | null }
|
|
61
|
+
/** rulesProblem's answer for a report that records no rules (`provenance.catalogHash` / `rulesHash`): an older sungen wrote it. */
|
|
62
|
+
export const NO_RULES_STAMP = 'audited by an older sungen, which did not record the rules it scored with';
|
|
63
|
+
/** What getProvenance writes when it could not read a catalog — never a match, on either side. */
|
|
64
|
+
const UNKNOWN = 'unknown';
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Why the rules a report was scored by (`was`) cannot be taken as this sungen's (`now`), or null when
|
|
68
|
+
* they are the same KNOWN rules. Missing or `unknown` on either side is a problem (fail closed):
|
|
69
|
+
* unknown == unknown proves nothing.
|
|
70
|
+
*/
|
|
71
|
+
export function rulesProblem(was: RulesStamp, now: RulesStamp): string | null {
|
|
72
|
+
if (!was.catalogHash || !was.rulesHash) return NO_RULES_STAMP;
|
|
73
|
+
if ([was.catalogHash, was.rulesHash].includes(UNKNOWN)) return 'the rules that scored it are unknown (provenance says "unknown")';
|
|
74
|
+
if (!now.catalogHash || !now.rulesHash || [now.catalogHash, now.rulesHash].includes(UNKNOWN)) return 'this sungen cannot read its own rules (catalog or rules hash unknown), so it trusts no report';
|
|
75
|
+
if (was.catalogHash === now.catalogHash && was.rulesHash === now.rulesHash) return null;
|
|
76
|
+
return `scored by other rules (catalog ${was.catalogHash} · rules ${was.rulesHash}) than this sungen's (catalog ${now.catalogHash} · rules ${now.rulesHash})`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Why a current-format report was judged by other rules than this sungen's, or null when the same. */
|
|
80
|
+
function otherRules(r: Record<string, unknown>): string | null {
|
|
81
|
+
return rulesProblem({ catalogHash: provenanceField(r, 'catalogHash'), rulesHash: provenanceField(r, 'rulesHash') }, getProvenance());
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
type JsonKind = 'string' | 'number' | 'boolean' | 'object' | 'array';
|
|
85
|
+
const OBJ = 'object' as const;
|
|
86
|
+
/** Every top-level key `runAudit` writes (tests/gates/audit-report-trust.run.ts keeps this in step). */
|
|
87
|
+
export const AUDIT_REPORT_KEYS: Record<string, JsonKind> = {
|
|
88
|
+
screen: 'string', scenarioCount: 'number', gate: OBJ, depth: OBJ, claim: OBJ, taxonomy: OBJ, balance: OBJ,
|
|
89
|
+
duplicates: OBJ, trace: OBJ, taxonomyMismatch: 'boolean', reusedScenarioIds: 'array', downstream: OBJ,
|
|
90
|
+
manualOracle: OBJ, automatableManual: OBJ, flowDepth: OBJ, oracle: OBJ, ledger: OBJ, viewpointBaseline: OBJ,
|
|
91
|
+
flowQuality: OBJ, flowInventory: OBJ, uiInventory: OBJ, calibration: OBJ, score: OBJ, gateStatus: 'string',
|
|
92
|
+
findings: 'array', intent: OBJ, provenance: OBJ, spec: OBJ,
|
|
93
|
+
gateOverrides: 'array', decisionsHash: 'string', inputsHash: 'string', exitCode: 'number', gateSensorError: 'boolean',
|
|
94
|
+
};
|
|
95
|
+
const P0_KEYS = ['exitCode', 'inputsHash', 'decisionsHash', 'gateOverrides', 'gateSensorError'];
|
|
96
|
+
const HASH_RE = /^[0-9a-f]{64}$/;
|
|
97
|
+
|
|
98
|
+
const kindOf = (v: unknown): JsonKind | 'null' => (v === null ? 'null' : Array.isArray(v) ? 'array' : typeof v as JsonKind);
|
|
99
|
+
|
|
100
|
+
/** Structural problems of a parsed report, independent of the unit's current inputs. */
|
|
101
|
+
function schemaProblems(r: Record<string, unknown>): AuditVerification['problems'] {
|
|
102
|
+
const out: AuditVerification['problems'] = [];
|
|
103
|
+
for (const [k, v] of Object.entries(r)) {
|
|
104
|
+
const want = AUDIT_REPORT_KEYS[k];
|
|
105
|
+
if (!want) out.push({ code: 'unknown-key', message: `unknown key "${k}" — the audit never writes it` });
|
|
106
|
+
else if (kindOf(v) !== want) out.push({ code: 'bad-type', message: `"${k}" must be ${want}, got ${kindOf(v)}` });
|
|
107
|
+
}
|
|
108
|
+
if (r.gateStatus !== 'PASS' && r.gateStatus !== 'FAIL') out.push({ code: 'bad-type', message: 'gateStatus must be PASS or FAIL' });
|
|
109
|
+
if (Array.isArray(r.findings) && !r.findings.every((f) => typeof f === 'string')) out.push({ code: 'bad-type', message: 'findings must be strings' });
|
|
110
|
+
const present = P0_KEYS.filter((k) => k in r);
|
|
111
|
+
if (present.length > 0 && present.length < P0_KEYS.length) {
|
|
112
|
+
out.push({ code: 'partial-fields', message: `carries ${present.join(', ')} but not ${P0_KEYS.filter((k) => !(k in r)).join(', ')}` });
|
|
113
|
+
}
|
|
114
|
+
if (present.length === P0_KEYS.length) {
|
|
115
|
+
if (!Number.isInteger(r.exitCode)) out.push({ code: 'bad-type', message: 'exitCode must be an integer' });
|
|
116
|
+
else if (r.gateStatus === 'PASS' || r.gateStatus === 'FAIL') {
|
|
117
|
+
if (r.exitCode !== AUDIT_EXIT_CODE[r.gateStatus]) out.push({ code: 'status-exit-mismatch', message: `gateStatus ${r.gateStatus} with exitCode ${r.exitCode} — a ${r.gateStatus} audit exits ${AUDIT_EXIT_CODE[r.gateStatus]}` });
|
|
118
|
+
}
|
|
119
|
+
for (const k of ['inputsHash', 'decisionsHash']) if (typeof r[k] !== 'string' || !HASH_RE.test(r[k] as string)) out.push({ code: 'bad-type', message: `${k} must be 64 hex characters` });
|
|
120
|
+
if (Array.isArray(r.gateOverrides) && !r.gateOverrides.every((g) => kindOf(g) === 'object')) out.push({ code: 'bad-type', message: 'gateOverrides must be objects' });
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function auditReportPath(projectRoot: string, unit: string): string {
|
|
126
|
+
return path.join(projectRoot, '.sungen', 'reports', `${reportSlug(unit)}-audit.json`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Today's decisionsHash for a unit name — what `next` compares an audit with (phase 05). */
|
|
130
|
+
export function currentDecisionsHash(projectRoot: string, unit: string): string {
|
|
131
|
+
const found = resolveUnitCandidates(unit, projectRoot);
|
|
132
|
+
const scope = found.length === 1 ? unitScopeOfDir(projectRoot, found[0].dir) : null;
|
|
133
|
+
return loadUnitGateOverrides(projectRoot, scope).decisionsHash;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function verifyAuditReport(projectRoot: string, unit: string): AuditVerification {
|
|
137
|
+
const file = auditReportPath(projectRoot, unit);
|
|
138
|
+
const found = resolveUnitCandidates(unit, projectRoot);
|
|
139
|
+
const unitDir = found.length === 1 ? found[0].dir : null;
|
|
140
|
+
const overrides = loadUnitGateOverrides(projectRoot, unitDir ? unitScopeOfDir(projectRoot, unitDir) : null);
|
|
141
|
+
const current = overrides.decisionsHash;
|
|
142
|
+
const result = (state: AuditState, problems: AuditVerification['problems'], report: Record<string, unknown> | null = null, notes: string[] = []): AuditVerification =>
|
|
143
|
+
({ state, problems, notes, report, path: file, currentDecisionsHash: current });
|
|
144
|
+
|
|
145
|
+
if (!fs.existsSync(file)) return result('absent', []);
|
|
146
|
+
let parsed: unknown;
|
|
147
|
+
try { parsed = JSON.parse(fs.readFileSync(file, 'utf8').replace(/^/, '')); } catch (err) {
|
|
148
|
+
return result('invalid', [{ code: 'unreadable', message: err instanceof Error ? err.message : String(err) }]);
|
|
149
|
+
}
|
|
150
|
+
if (kindOf(parsed) !== 'object') return result('invalid', [{ code: 'unreadable', message: 'not a JSON object' }]);
|
|
151
|
+
const r = parsed as Record<string, unknown>;
|
|
152
|
+
const schema = schemaProblems(r);
|
|
153
|
+
if (schema.length) return result('invalid', schema);
|
|
154
|
+
|
|
155
|
+
if (!P0_KEYS.some((k) => k in r)) {
|
|
156
|
+
// A legacy report predates gateSensorError, so only a stored PASS its own fields contradict is caught.
|
|
157
|
+
const sources = termSourcesOf(r, false);
|
|
158
|
+
if (r.gateStatus === 'PASS' && sources && recomputeAuditGateStatus(sources, overrides) === 'FAIL') return result('invalid', [verdictMismatch(r)]);
|
|
159
|
+
const by = `written by ${writtenBy(r) ? `sungen ${writtenBy(r)}` : 'an earlier sungen'}`;
|
|
160
|
+
if (current !== EMPTY_DECISIONS_HASH) {
|
|
161
|
+
return result('stale', [{ code: 'legacy-with-overrides', message: `${by} (no decisionsHash) and a gate-override now applies to this unit` }]);
|
|
162
|
+
}
|
|
163
|
+
return result('stale', [{ code: 'legacy-unverified', message: `${by}, before inputsHash existed — its inputs cannot be verified` }]);
|
|
164
|
+
}
|
|
165
|
+
const stale: AuditVerification['problems'] = [];
|
|
166
|
+
const rules = otherRules(r);
|
|
167
|
+
// A report from before the rules stamp reads in plain words, with the one command that clears it (#966).
|
|
168
|
+
if (rules) stale.push({ code: 'rules-changed', message: rules === NO_RULES_STAMP
|
|
169
|
+
? `audited by an older sungen${writtenBy(r) ? ` (${writtenBy(r)})` : ''} — run \`sungen audit --screen ${unit}\` once`
|
|
170
|
+
: `${writtenBy(r) ? `written by sungen ${writtenBy(r)}, ` : ''}${rules}` });
|
|
171
|
+
if (r.decisionsHash !== current) stale.push({ code: 'decisions-changed', message: 'the gate-override decisions changed since this audit' });
|
|
172
|
+
if (!unitDir) return result('invalid', [{ code: 'unit-unresolved', message: `"${unit}" does not name exactly one unit, so the audit's inputs cannot be checked` }]);
|
|
173
|
+
if (r.inputsHash !== auditInputsHash(unitDir, unit, r.decisionsHash as string)) {
|
|
174
|
+
stale.push({ code: 'inputs-changed', message: auditInputsChangedReason(unitDir) });
|
|
175
|
+
}
|
|
176
|
+
if (stale.length) return result('stale', stale);
|
|
177
|
+
const tampered = verdictProblem(r, overrides);
|
|
178
|
+
return tampered ? result('invalid', [tampered]) : result('verified', [], r);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const verdictMismatch = (r: Record<string, unknown>): AuditVerification['problems'][number] => ({
|
|
182
|
+
code: 'verdict-mismatch',
|
|
183
|
+
message: `verdict mismatch — gateStatus ${String(r.gateStatus)} is not what the report's own findings produce under today's overrides (edited by hand)`,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
/** A current report re-evaluated from its own terms (audit-gate-terms.ts): missing terms or another verdict = not trusted. */
|
|
187
|
+
function verdictProblem(r: Record<string, unknown>, overrides: UnitGateOverrides): AuditVerification['problems'][number] | null {
|
|
188
|
+
const sources = termSourcesOf(r, true);
|
|
189
|
+
if (!sources) return { code: 'bad-type', message: 'the gate terms (gate.gaps, depth/claim/spec verdicts, taxonomyMismatch, gateSensorError, reusedScenarioIds) are incomplete' };
|
|
190
|
+
return recomputeAuditGateStatus(sources, overrides) === r.gateStatus ? null : verdictMismatch(r);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Whether the report may be used at all: only a verified one. */
|
|
194
|
+
export const auditCounts = (v: AuditVerification): boolean => v.state === 'verified';
|
|
195
|
+
|
|
196
|
+
/** Only an explicit `gateStatus: PASS` on a report that counts passes; a score never does. */
|
|
197
|
+
export const auditPassed = (v: AuditVerification): boolean => auditCounts(v) && v.report?.gateStatus === 'PASS';
|
|
198
|
+
|
|
199
|
+
/** One line saying why the report does not count, for a needs-you item or a blocker. */
|
|
200
|
+
export function auditNotCountedReason(v: AuditVerification, unit: string): string {
|
|
201
|
+
const why = v.problems.map((p) => p.message).join('; ');
|
|
202
|
+
const rerun = `re-run \`sungen audit --screen ${unit}\``;
|
|
203
|
+
if (v.state === 'stale') return `Audit report is stale (${why}) — ${rerun}.`;
|
|
204
|
+
if (v.state === 'invalid') return `Audit report is not trusted (${why}) — treated as never audited; ${rerun}.`;
|
|
205
|
+
return `No audit report yet — ${rerun}.`;
|
|
206
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `decisionsHash` (OES-11.4, red-team #12): a fingerprint of the decisions that can change a unit's
|
|
3
|
+
* gate outcome. The audit records it; `next`, `gate` and `delivery` recompute it — a mismatch means
|
|
4
|
+
* the audit was measured under other decisions: stale, re-audit.
|
|
5
|
+
*
|
|
6
|
+
* What it covers, for one unit — the project's `qa/decisions/` plus the unit's own directory:
|
|
7
|
+
* - every `gate-override` entry that can apply to the unit (accepted, ineffective, rejected,
|
|
8
|
+
* superseded alike), by path and entry_hash
|
|
9
|
+
* - every file there that does not verify (unreadable, invalid, id or hash mismatch), by path,
|
|
10
|
+
* problem and content — it may be an override nobody can read
|
|
11
|
+
* What it does NOT cover: waivers. A waiver is bound to the audit by `evidence_hash = hash of the
|
|
12
|
+
* audit report`; folding it in here would make every waiver stale the audit that it waives.
|
|
13
|
+
*/
|
|
14
|
+
import { createHash } from 'crypto';
|
|
15
|
+
import * as fs from 'fs';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { canonicalJson } from '../../decisions/decision-identity';
|
|
18
|
+
import { DecisionProblem } from '../../decisions/decision-file';
|
|
19
|
+
|
|
20
|
+
export interface DecisionsHashItem {
|
|
21
|
+
path: string;
|
|
22
|
+
entryHash?: string;
|
|
23
|
+
problem?: string;
|
|
24
|
+
contentSha?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const sha256 = (s: string | Buffer): string => createHash('sha256').update(s).digest('hex');
|
|
28
|
+
|
|
29
|
+
export function computeDecisionsHash(items: DecisionsHashItem[]): string {
|
|
30
|
+
const sorted = [...items].sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
31
|
+
return sha256(canonicalJson({ schema: 1, decisions: sorted }));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** The hash of a unit with no decision that can touch its gates. */
|
|
35
|
+
export const EMPTY_DECISIONS_HASH = computeDecisionsHash([]);
|
|
36
|
+
|
|
37
|
+
/** A problem file as a hash item: its content counts, so editing it re-stales the audit. */
|
|
38
|
+
export function problemHashItem(projectRoot: string, p: DecisionProblem): DecisionsHashItem {
|
|
39
|
+
let contentSha = 'unreadable';
|
|
40
|
+
try { contentSha = sha256(fs.readFileSync(p.path)); } catch { /* gone or unreadable: the marker stands */ }
|
|
41
|
+
return { path: path.relative(projectRoot, p.path).split(path.sep).join('/'), problem: p.code, contentSha };
|
|
42
|
+
}
|