@sun-asterisk/sungen 3.2.34 → 3.3.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/basis/anchor-grammar.d.ts +32 -0
- package/dist/basis/anchor-grammar.d.ts.map +1 -0
- package/dist/basis/anchor-grammar.js +82 -0
- package/dist/basis/anchor-grammar.js.map +1 -0
- package/dist/basis/anchor-hash.d.ts +6 -0
- package/dist/basis/anchor-hash.d.ts.map +1 -0
- package/dist/basis/anchor-hash.js +28 -0
- package/dist/basis/anchor-hash.js.map +1 -0
- package/dist/basis/bm51-tables.d.ts +20 -0
- package/dist/basis/bm51-tables.d.ts.map +1 -0
- package/dist/basis/bm51-tables.js +71 -0
- package/dist/basis/bm51-tables.js.map +1 -0
- package/dist/basis/extract-spec-anchors.d.ts +39 -0
- package/dist/basis/extract-spec-anchors.d.ts.map +1 -0
- package/dist/basis/extract-spec-anchors.js +81 -0
- package/dist/basis/extract-spec-anchors.js.map +1 -0
- package/dist/basis/migration-sentinel.d.ts +47 -0
- package/dist/basis/migration-sentinel.d.ts.map +1 -0
- package/dist/basis/migration-sentinel.js +219 -0
- package/dist/basis/migration-sentinel.js.map +1 -0
- package/dist/basis/spec-frontmatter.d.ts +18 -0
- package/dist/basis/spec-frontmatter.d.ts.map +1 -0
- package/dist/basis/spec-frontmatter.js +55 -0
- package/dist/basis/spec-frontmatter.js.map +1 -0
- package/dist/basis/spec-sections.d.ts +18 -0
- package/dist/basis/spec-sections.d.ts.map +1 -0
- package/dist/basis/spec-sections.js +27 -0
- package/dist/basis/spec-sections.js.map +1 -0
- package/dist/basis/test-basis-schema.d.ts +28 -0
- package/dist/basis/test-basis-schema.d.ts.map +1 -0
- package/dist/basis/test-basis-schema.js +141 -0
- package/dist/basis/test-basis-schema.js.map +1 -0
- package/dist/capabilities/discover.d.ts +4 -0
- package/dist/capabilities/discover.d.ts.map +1 -1
- package/dist/capabilities/discover.js +16 -2
- package/dist/capabilities/discover.js.map +1 -1
- package/dist/capabilities/registry.d.ts +15 -0
- package/dist/capabilities/registry.d.ts.map +1 -1
- package/dist/capabilities/registry.js.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +10 -5
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/capability.d.ts.map +1 -1
- package/dist/cli/commands/capability.js +6 -2
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/contract-derive-command.d.ts +11 -0
- package/dist/cli/commands/contract-derive-command.d.ts.map +1 -0
- package/dist/cli/commands/contract-derive-command.js +99 -0
- package/dist/cli/commands/contract-derive-command.js.map +1 -0
- package/dist/cli/commands/contract.d.ts +17 -0
- package/dist/cli/commands/contract.d.ts.map +1 -0
- package/dist/cli/commands/contract.js +162 -0
- package/dist/cli/commands/contract.js.map +1 -0
- package/dist/cli/commands/defect.d.ts +7 -0
- package/dist/cli/commands/defect.d.ts.map +1 -0
- package/dist/cli/commands/defect.js +68 -0
- package/dist/cli/commands/defect.js.map +1 -0
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +96 -12
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +3 -1
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/journey.d.ts.map +1 -1
- package/dist/cli/commands/journey.js +43 -15
- package/dist/cli/commands/journey.js.map +1 -1
- package/dist/cli/commands/next.d.ts +8 -0
- package/dist/cli/commands/next.d.ts.map +1 -1
- package/dist/cli/commands/next.js +68 -8
- package/dist/cli/commands/next.js.map +1 -1
- package/dist/cli/commands/triage.d.ts +7 -0
- package/dist/cli/commands/triage.d.ts.map +1 -0
- package/dist/cli/commands/triage.js +98 -0
- package/dist/cli/commands/triage.js.map +1 -0
- package/dist/cli/commands/update.d.ts +11 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +31 -6
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/index.js +24 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/project-sungen-invocation.d.ts +7 -0
- package/dist/cli/project-sungen-invocation.d.ts.map +1 -0
- package/dist/cli/project-sungen-invocation.js +76 -0
- package/dist/cli/project-sungen-invocation.js.map +1 -0
- package/dist/contract/approve-contract.d.ts +31 -0
- package/dist/contract/approve-contract.d.ts.map +1 -0
- package/dist/contract/approve-contract.js +87 -0
- package/dist/contract/approve-contract.js.map +1 -0
- package/dist/contract/assertion-matcher-vocabulary.d.ts +24 -0
- package/dist/contract/assertion-matcher-vocabulary.d.ts.map +1 -0
- package/dist/contract/assertion-matcher-vocabulary.js +100 -0
- package/dist/contract/assertion-matcher-vocabulary.js.map +1 -0
- package/dist/contract/build-contract-verdict.d.ts +32 -0
- package/dist/contract/build-contract-verdict.d.ts.map +1 -0
- package/dist/contract/build-contract-verdict.js +123 -0
- package/dist/contract/build-contract-verdict.js.map +1 -0
- package/dist/contract/build-trace-conformance.d.ts +18 -0
- package/dist/contract/build-trace-conformance.d.ts.map +1 -0
- package/dist/contract/build-trace-conformance.js +153 -0
- package/dist/contract/build-trace-conformance.js.map +1 -0
- package/dist/contract/classify-contract-change.d.ts +23 -0
- package/dist/contract/classify-contract-change.d.ts.map +1 -0
- package/dist/contract/classify-contract-change.js +98 -0
- package/dist/contract/classify-contract-change.js.map +1 -0
- package/dist/contract/classify-contract-unit.d.ts +18 -0
- package/dist/contract/classify-contract-unit.d.ts.map +1 -0
- package/dist/contract/classify-contract-unit.js +49 -0
- package/dist/contract/classify-contract-unit.js.map +1 -0
- package/dist/contract/classify-trace-conformance.d.ts +32 -0
- package/dist/contract/classify-trace-conformance.d.ts.map +1 -0
- package/dist/contract/classify-trace-conformance.js +117 -0
- package/dist/contract/classify-trace-conformance.js.map +1 -0
- package/dist/contract/contract-git.d.ts +24 -0
- package/dist/contract/contract-git.d.ts.map +1 -0
- package/dist/contract/contract-git.js +144 -0
- package/dist/contract/contract-git.js.map +1 -0
- package/dist/contract/contract-hash.d.ts +7 -0
- package/dist/contract/contract-hash.d.ts.map +1 -0
- package/dist/contract/contract-hash.js +38 -0
- package/dist/contract/contract-hash.js.map +1 -0
- package/dist/contract/contract-report-file.d.ts +4 -0
- package/dist/contract/contract-report-file.d.ts.map +1 -0
- package/dist/contract/contract-report-file.js +60 -0
- package/dist/contract/contract-report-file.js.map +1 -0
- package/dist/contract/contract-schema.d.ts +71 -0
- package/dist/contract/contract-schema.d.ts.map +1 -0
- package/dist/contract/contract-schema.js +102 -0
- package/dist/contract/contract-schema.js.map +1 -0
- package/dist/contract/contract-units.d.ts +12 -0
- package/dist/contract/contract-units.d.ts.map +1 -0
- package/dist/contract/contract-units.js +96 -0
- package/dist/contract/contract-units.js.map +1 -0
- package/dist/contract/contracts-lock-file.d.ts +24 -0
- package/dist/contract/contracts-lock-file.d.ts.map +1 -0
- package/dist/contract/contracts-lock-file.js +140 -0
- package/dist/contract/contracts-lock-file.js.map +1 -0
- package/dist/contract/data-normalize.d.ts +10 -0
- package/dist/contract/data-normalize.d.ts.map +1 -0
- package/dist/contract/data-normalize.js +110 -0
- package/dist/contract/data-normalize.js.map +1 -0
- package/dist/contract/derive-free-feature.d.ts +38 -0
- package/dist/contract/derive-free-feature.d.ts.map +1 -0
- package/dist/contract/derive-free-feature.js +154 -0
- package/dist/contract/derive-free-feature.js.map +1 -0
- package/dist/contract/field-semantic-redaction.d.ts +21 -0
- package/dist/contract/field-semantic-redaction.d.ts.map +1 -0
- package/dist/contract/field-semantic-redaction.js +118 -0
- package/dist/contract/field-semantic-redaction.js.map +1 -0
- package/dist/contract/free-feature-blocks.d.ts +10 -0
- package/dist/contract/free-feature-blocks.d.ts.map +1 -0
- package/dist/contract/free-feature-blocks.js +94 -0
- package/dist/contract/free-feature-blocks.js.map +1 -0
- package/dist/contract/lock-secret-guard.d.ts +22 -0
- package/dist/contract/lock-secret-guard.d.ts.map +1 -0
- package/dist/contract/lock-secret-guard.js +134 -0
- package/dist/contract/lock-secret-guard.js.map +1 -0
- package/dist/contract/lock-vs-git-head.d.ts +26 -0
- package/dist/contract/lock-vs-git-head.d.ts.map +1 -0
- package/dist/contract/lock-vs-git-head.js +28 -0
- package/dist/contract/lock-vs-git-head.js.map +1 -0
- package/dist/contract/normalize-contract-step.d.ts +21 -0
- package/dist/contract/normalize-contract-step.d.ts.map +1 -0
- package/dist/contract/normalize-contract-step.js +70 -0
- package/dist/contract/normalize-contract-step.js.map +1 -0
- package/dist/contract/normalize-feature-steps.d.ts +7 -0
- package/dist/contract/normalize-feature-steps.d.ts.map +1 -0
- package/dist/contract/normalize-feature-steps.js +127 -0
- package/dist/contract/normalize-feature-steps.js.map +1 -0
- package/dist/contract/oracle-strength.d.ts +12 -0
- package/dist/contract/oracle-strength.d.ts.map +1 -0
- package/dist/contract/oracle-strength.js +88 -0
- package/dist/contract/oracle-strength.js.map +1 -0
- package/dist/contract/project-contract-blockers.d.ts +10 -0
- package/dist/contract/project-contract-blockers.d.ts.map +1 -0
- package/dist/contract/project-contract-blockers.js +73 -0
- package/dist/contract/project-contract-blockers.js.map +1 -0
- package/dist/contract/record-contract-approval.d.ts +21 -0
- package/dist/contract/record-contract-approval.d.ts.map +1 -0
- package/dist/contract/record-contract-approval.js +98 -0
- package/dist/contract/record-contract-approval.js.map +1 -0
- package/dist/contract/render-free-gherkin.d.ts +40 -0
- package/dist/contract/render-free-gherkin.d.ts.map +1 -0
- package/dist/contract/render-free-gherkin.js +141 -0
- package/dist/contract/render-free-gherkin.js.map +1 -0
- package/dist/contract/render-trace-sentence.d.ts +20 -0
- package/dist/contract/render-trace-sentence.d.ts.map +1 -0
- package/dist/contract/render-trace-sentence.js +109 -0
- package/dist/contract/render-trace-sentence.js.map +1 -0
- package/dist/contract/render-trace-target.d.ts +14 -0
- package/dist/contract/render-trace-target.d.ts.map +1 -0
- package/dist/contract/render-trace-target.js +70 -0
- package/dist/contract/render-trace-target.js.map +1 -0
- package/dist/contract/resolve-unit-trace-identities.d.ts +8 -0
- package/dist/contract/resolve-unit-trace-identities.d.ts.map +1 -0
- package/dist/contract/resolve-unit-trace-identities.js +78 -0
- package/dist/contract/resolve-unit-trace-identities.js.map +1 -0
- package/dist/contract/trace/collect-trace-evidence.d.ts +33 -0
- package/dist/contract/trace/collect-trace-evidence.d.ts.map +1 -0
- package/dist/contract/trace/collect-trace-evidence.js +161 -0
- package/dist/contract/trace/collect-trace-evidence.js.map +1 -0
- package/dist/contract/trace/identity-cache.d.ts +19 -0
- package/dist/contract/trace/identity-cache.d.ts.map +1 -0
- package/dist/contract/trace/identity-cache.js +104 -0
- package/dist/contract/trace/identity-cache.js.map +1 -0
- package/dist/contract/trace/select-final-attempt.d.ts +27 -0
- package/dist/contract/trace/select-final-attempt.d.ts.map +1 -0
- package/dist/contract/trace/select-final-attempt.js +116 -0
- package/dist/contract/trace/select-final-attempt.js.map +1 -0
- package/dist/contract/trace/snapshot-html-renderer.d.ts +31 -0
- package/dist/contract/trace/snapshot-html-renderer.d.ts.map +1 -0
- package/dist/contract/trace/snapshot-html-renderer.js +172 -0
- package/dist/contract/trace/snapshot-html-renderer.js.map +1 -0
- package/dist/contract/trace/snapshot-resolver.d.ts +21 -0
- package/dist/contract/trace/snapshot-resolver.d.ts.map +1 -0
- package/dist/contract/trace/snapshot-resolver.js +65 -0
- package/dist/contract/trace/snapshot-resolver.js.map +1 -0
- package/dist/contract/trace/snapshot-store.d.ts +66 -0
- package/dist/contract/trace/snapshot-store.d.ts.map +1 -0
- package/dist/contract/trace/snapshot-store.js +173 -0
- package/dist/contract/trace/snapshot-store.js.map +1 -0
- package/dist/contract/trace/target-identity.d.ts +74 -0
- package/dist/contract/trace/target-identity.d.ts.map +1 -0
- package/dist/contract/trace/target-identity.js +68 -0
- package/dist/contract/trace/target-identity.js.map +1 -0
- package/dist/contract/trace/test-step-join.d.ts +65 -0
- package/dist/contract/trace/test-step-join.d.ts.map +1 -0
- package/dist/contract/trace/test-step-join.js +80 -0
- package/dist/contract/trace/test-step-join.js.map +1 -0
- package/dist/contract/trace/trace-binding.d.ts +21 -0
- package/dist/contract/trace/trace-binding.d.ts.map +1 -0
- package/dist/contract/trace/trace-binding.js +88 -0
- package/dist/contract/trace/trace-binding.js.map +1 -0
- package/dist/contract/trace/trace-file-reader.d.ts +41 -0
- package/dist/contract/trace/trace-file-reader.d.ts.map +1 -0
- package/dist/contract/trace/trace-file-reader.js +161 -0
- package/dist/contract/trace/trace-file-reader.js.map +1 -0
- package/dist/contract/trace/trace-fingerprint.d.ts +22 -0
- package/dist/contract/trace/trace-fingerprint.d.ts.map +1 -0
- package/dist/contract/trace/trace-fingerprint.js +96 -0
- package/dist/contract/trace/trace-fingerprint.js.map +1 -0
- package/dist/contract/trace/trace-identity-resolution.d.ts +26 -0
- package/dist/contract/trace/trace-identity-resolution.d.ts.map +1 -0
- package/dist/contract/trace/trace-identity-resolution.js +84 -0
- package/dist/contract/trace/trace-identity-resolution.js.map +1 -0
- package/dist/contract/trace/trace-run-record.d.ts +30 -0
- package/dist/contract/trace/trace-run-record.d.ts.map +1 -0
- package/dist/contract/trace/trace-run-record.js +121 -0
- package/dist/contract/trace/trace-run-record.js.map +1 -0
- package/dist/contract/trace/trace-steps.d.ts +19 -0
- package/dist/contract/trace/trace-steps.d.ts.map +1 -0
- package/dist/contract/trace/trace-steps.js +79 -0
- package/dist/contract/trace/trace-steps.js.map +1 -0
- package/dist/contract/trace/trace-zip-limits.d.ts +45 -0
- package/dist/contract/trace/trace-zip-limits.d.ts.map +1 -0
- package/dist/contract/trace/trace-zip-limits.js +52 -0
- package/dist/contract/trace/trace-zip-limits.js.map +1 -0
- package/dist/contract/trace/trace-zip-reader.d.ts +10 -0
- package/dist/contract/trace/trace-zip-reader.d.ts.map +1 -0
- package/dist/contract/trace/trace-zip-reader.js +186 -0
- package/dist/contract/trace/trace-zip-reader.js.map +1 -0
- package/dist/contract/verify-approval-decisions.d.ts +5 -0
- package/dist/contract/verify-approval-decisions.d.ts.map +1 -0
- package/dist/contract/verify-approval-decisions.js +104 -0
- package/dist/contract/verify-approval-decisions.js.map +1 -0
- package/dist/decisions/append-decision.d.ts +12 -0
- package/dist/decisions/append-decision.d.ts.map +1 -0
- package/dist/decisions/append-decision.js +73 -0
- package/dist/decisions/append-decision.js.map +1 -0
- package/dist/decisions/confirmed-decision-commands.d.ts +41 -0
- package/dist/decisions/confirmed-decision-commands.d.ts.map +1 -0
- package/dist/decisions/confirmed-decision-commands.js +190 -0
- package/dist/decisions/confirmed-decision-commands.js.map +1 -0
- package/dist/decisions/decision-file.d.ts +31 -0
- package/dist/decisions/decision-file.d.ts.map +1 -0
- package/dist/decisions/decision-file.js +139 -0
- package/dist/decisions/decision-file.js.map +1 -0
- package/dist/decisions/decision-identity.d.ts +12 -0
- package/dist/decisions/decision-identity.d.ts.map +1 -0
- package/dist/decisions/decision-identity.js +78 -0
- package/dist/decisions/decision-identity.js.map +1 -0
- package/dist/decisions/decision-integrity-check.d.ts +12 -0
- package/dist/decisions/decision-integrity-check.d.ts.map +1 -0
- package/dist/decisions/decision-integrity-check.js +102 -0
- package/dist/decisions/decision-integrity-check.js.map +1 -0
- package/dist/decisions/decision-schema.d.ts +42 -0
- package/dist/decisions/decision-schema.d.ts.map +1 -0
- package/dist/decisions/decision-schema.js +75 -0
- package/dist/decisions/decision-schema.js.map +1 -0
- package/dist/decisions/decision-source.d.ts +2 -0
- package/dist/decisions/decision-source.d.ts.map +1 -0
- package/dist/decisions/decision-source.js +18 -0
- package/dist/decisions/decision-source.js.map +1 -0
- package/dist/decisions/exclusive-file-create.d.ts +3 -0
- package/dist/decisions/exclusive-file-create.d.ts.map +1 -0
- package/dist/decisions/exclusive-file-create.js +84 -0
- package/dist/decisions/exclusive-file-create.js.map +1 -0
- package/dist/decisions/git-head-trust.d.ts +7 -0
- package/dist/decisions/git-head-trust.d.ts.map +1 -0
- package/dist/decisions/git-head-trust.js +76 -0
- package/dist/decisions/git-head-trust.js.map +1 -0
- package/dist/decisions/human-confirmation.d.ts +35 -0
- package/dist/decisions/human-confirmation.d.ts.map +1 -0
- package/dist/decisions/human-confirmation.js +161 -0
- package/dist/decisions/human-confirmation.js.map +1 -0
- package/dist/decisions/legacy-waiver-migration.d.ts +31 -0
- package/dist/decisions/legacy-waiver-migration.d.ts.map +1 -0
- package/dist/decisions/legacy-waiver-migration.js +170 -0
- package/dist/decisions/legacy-waiver-migration.js.map +1 -0
- package/dist/decisions/read-decisions.d.ts +19 -0
- package/dist/decisions/read-decisions.d.ts.map +1 -0
- package/dist/decisions/read-decisions.js +90 -0
- package/dist/decisions/read-decisions.js.map +1 -0
- package/dist/decisions/viewpoint-baseline-adapter.d.ts +7 -0
- package/dist/decisions/viewpoint-baseline-adapter.d.ts.map +1 -0
- package/dist/decisions/viewpoint-baseline-adapter.js +109 -0
- package/dist/decisions/viewpoint-baseline-adapter.js.map +1 -0
- package/dist/decisions/waiver-decisions.d.ts +24 -0
- package/dist/decisions/waiver-decisions.d.ts.map +1 -0
- package/dist/decisions/waiver-decisions.js +46 -0
- package/dist/decisions/waiver-decisions.js.map +1 -0
- package/dist/exporters/csv-exporter.d.ts +4 -0
- package/dist/exporters/csv-exporter.d.ts.map +1 -1
- package/dist/exporters/csv-exporter.js +1 -1
- package/dist/exporters/csv-exporter.js.map +1 -1
- package/dist/exporters/feature-parser.d.ts +8 -0
- package/dist/exporters/feature-parser.d.ts.map +1 -1
- package/dist/exporters/feature-parser.js +12 -0
- package/dist/exporters/feature-parser.js.map +1 -1
- package/dist/exporters/matrix/build.d.ts +3 -0
- package/dist/exporters/matrix/build.d.ts.map +1 -1
- package/dist/exporters/matrix/build.js +59 -19
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/carry-manual-results.d.ts +19 -0
- package/dist/exporters/matrix/carry-manual-results.d.ts.map +1 -1
- package/dist/exporters/matrix/carry-manual-results.js +76 -6
- package/dist/exporters/matrix/carry-manual-results.js.map +1 -1
- package/dist/exporters/matrix/export.d.ts +8 -2
- package/dist/exporters/matrix/export.d.ts.map +1 -1
- package/dist/exporters/matrix/export.js +16 -3
- package/dist/exporters/matrix/export.js.map +1 -1
- package/dist/exporters/matrix/gates.d.ts +6 -1
- package/dist/exporters/matrix/gates.d.ts.map +1 -1
- package/dist/exporters/matrix/gates.js +57 -128
- package/dist/exporters/matrix/gates.js.map +1 -1
- package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
- package/dist/exporters/matrix/render-csv.js +4 -1
- package/dist/exporters/matrix/render-csv.js.map +1 -1
- package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts +13 -0
- package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts.map +1 -0
- package/dist/exporters/matrix/render-gate-overrides-sheet.js +44 -0
- package/dist/exporters/matrix/render-gate-overrides-sheet.js.map +1 -0
- package/dist/exporters/matrix/render-xlsx.d.ts +1 -0
- package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
- package/dist/exporters/matrix/render-xlsx.js +6 -0
- package/dist/exporters/matrix/render-xlsx.js.map +1 -1
- package/dist/exporters/matrix/types.d.ts +9 -1
- package/dist/exporters/matrix/types.d.ts.map +1 -1
- package/dist/exporters/matrix/types.js.map +1 -1
- package/dist/exporters/matrix/xlsx-cells.js +1 -1
- package/dist/exporters/matrix/xlsx-cells.js.map +1 -1
- package/dist/exporters/playwright-report-parser.d.ts.map +1 -1
- package/dist/exporters/playwright-report-parser.js +1 -0
- package/dist/exporters/playwright-report-parser.js.map +1 -1
- package/dist/exporters/scenario-merger.d.ts.map +1 -1
- package/dist/exporters/scenario-merger.js +2 -0
- package/dist/exporters/scenario-merger.js.map +1 -1
- package/dist/exporters/types.d.ts +5 -0
- package/dist/exporters/types.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +13 -0
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/graph/evaluate-graph.d.ts +23 -0
- package/dist/graph/evaluate-graph.d.ts.map +1 -0
- package/dist/graph/evaluate-graph.js +52 -0
- package/dist/graph/evaluate-graph.js.map +1 -0
- package/dist/graph/locate-finding.d.ts +20 -0
- package/dist/graph/locate-finding.d.ts.map +1 -0
- package/dist/graph/locate-finding.js +137 -0
- package/dist/graph/locate-finding.js.map +1 -0
- package/dist/graph/node-decl.d.ts +66 -0
- package/dist/graph/node-decl.d.ts.map +1 -0
- package/dist/graph/node-decl.js +8 -0
- package/dist/graph/node-decl.js.map +1 -0
- package/dist/graph/nodes/core-node-catalog.d.ts +7 -0
- package/dist/graph/nodes/core-node-catalog.d.ts.map +1 -0
- package/dist/graph/nodes/core-node-catalog.js +13 -0
- package/dist/graph/nodes/core-node-catalog.js.map +1 -0
- package/dist/graph/nodes/test-case-contract-nodes.d.ts +21 -0
- package/dist/graph/nodes/test-case-contract-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/test-case-contract-nodes.js +59 -0
- package/dist/graph/nodes/test-case-contract-nodes.js.map +1 -0
- package/dist/graph/nodes/test-case-nodes.d.ts +26 -0
- package/dist/graph/nodes/test-case-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/test-case-nodes.js +66 -0
- package/dist/graph/nodes/test-case-nodes.js.map +1 -0
- package/dist/graph/nodes/unit-audit-nodes.d.ts +18 -0
- package/dist/graph/nodes/unit-audit-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/unit-audit-nodes.js +95 -0
- package/dist/graph/nodes/unit-audit-nodes.js.map +1 -0
- package/dist/graph/nodes/unit-contract-node.d.ts +21 -0
- package/dist/graph/nodes/unit-contract-node.d.ts.map +1 -0
- package/dist/graph/nodes/unit-contract-node.js +88 -0
- package/dist/graph/nodes/unit-contract-node.js.map +1 -0
- package/dist/graph/nodes/unit-design-nodes.d.ts +14 -0
- package/dist/graph/nodes/unit-design-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/unit-design-nodes.js +91 -0
- package/dist/graph/nodes/unit-design-nodes.js.map +1 -0
- package/dist/graph/nodes/unit-execution-nodes.d.ts +16 -0
- package/dist/graph/nodes/unit-execution-nodes.d.ts.map +1 -0
- package/dist/graph/nodes/unit-execution-nodes.js +79 -0
- package/dist/graph/nodes/unit-execution-nodes.js.map +1 -0
- package/dist/graph/test-case-identity.d.ts +13 -0
- package/dist/graph/test-case-identity.d.ts.map +1 -0
- package/dist/graph/test-case-identity.js +106 -0
- package/dist/graph/test-case-identity.js.map +1 -0
- package/dist/graph/test-case-results.d.ts +11 -0
- package/dist/graph/test-case-results.d.ts.map +1 -0
- package/dist/graph/test-case-results.js +137 -0
- package/dist/graph/test-case-results.js.map +1 -0
- package/dist/graph/test-case-satisfied.d.ts +25 -0
- package/dist/graph/test-case-satisfied.d.ts.map +1 -0
- package/dist/graph/test-case-satisfied.js +51 -0
- package/dist/graph/test-case-satisfied.js.map +1 -0
- package/dist/graph/test-case-state-shape.d.ts +67 -0
- package/dist/graph/test-case-state-shape.d.ts.map +1 -0
- package/dist/graph/test-case-state-shape.js +3 -0
- package/dist/graph/test-case-state-shape.js.map +1 -0
- package/dist/graph/test-case-states.d.ts +9 -0
- package/dist/graph/test-case-states.d.ts.map +1 -0
- package/dist/graph/test-case-states.js +116 -0
- package/dist/graph/test-case-states.js.map +1 -0
- package/dist/graph/unit-artifact-probes.d.ts +19 -0
- package/dist/graph/unit-artifact-probes.d.ts.map +1 -0
- package/dist/graph/unit-artifact-probes.js +133 -0
- package/dist/graph/unit-artifact-probes.js.map +1 -0
- package/dist/graph/unit-state-facts.d.ts +43 -0
- package/dist/graph/unit-state-facts.d.ts.map +1 -0
- package/dist/graph/unit-state-facts.js +87 -0
- package/dist/graph/unit-state-facts.js.map +1 -0
- package/dist/harness/audit.d.ts +11 -0
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +34 -9
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/catalog/gate-rules.yaml +647 -0
- package/dist/harness/counted-assertions.d.ts +2 -0
- package/dist/harness/counted-assertions.d.ts.map +1 -0
- package/dist/harness/counted-assertions.js +38 -0
- package/dist/harness/counted-assertions.js.map +1 -0
- package/dist/harness/defect-draft.d.ts +14 -0
- package/dist/harness/defect-draft.d.ts.map +1 -0
- package/dist/harness/defect-draft.js +143 -0
- package/dist/harness/defect-draft.js.map +1 -0
- package/dist/harness/defects.d.ts +24 -0
- package/dist/harness/defects.d.ts.map +1 -0
- package/dist/harness/defects.js +118 -0
- package/dist/harness/defects.js.map +1 -0
- package/dist/harness/gates/audit-gate-terms.d.ts +41 -0
- package/dist/harness/gates/audit-gate-terms.d.ts.map +1 -0
- package/dist/harness/gates/audit-gate-terms.js +72 -0
- package/dist/harness/gates/audit-gate-terms.js.map +1 -0
- package/dist/harness/gates/audit-gate-verdict.d.ts +31 -0
- package/dist/harness/gates/audit-gate-verdict.d.ts.map +1 -0
- package/dist/harness/gates/audit-gate-verdict.js +101 -0
- package/dist/harness/gates/audit-gate-verdict.js.map +1 -0
- package/dist/harness/gates/audit-input-hash.d.ts +4 -0
- package/dist/harness/gates/audit-input-hash.d.ts.map +1 -0
- package/dist/harness/gates/audit-input-hash.js +96 -0
- package/dist/harness/gates/audit-input-hash.js.map +1 -0
- package/dist/harness/gates/audit-report-verification.d.ts +41 -0
- package/dist/harness/gates/audit-report-verification.d.ts.map +1 -0
- package/dist/harness/gates/audit-report-verification.js +236 -0
- package/dist/harness/gates/audit-report-verification.js.map +1 -0
- package/dist/harness/gates/decisions-hash.d.ts +13 -0
- package/dist/harness/gates/decisions-hash.d.ts.map +1 -0
- package/dist/harness/gates/decisions-hash.js +72 -0
- package/dist/harness/gates/decisions-hash.js.map +1 -0
- package/dist/harness/gates/delivery-checklist.d.ts +21 -0
- package/dist/harness/gates/delivery-checklist.d.ts.map +1 -0
- package/dist/harness/gates/delivery-checklist.js +128 -0
- package/dist/harness/gates/delivery-checklist.js.map +1 -0
- package/dist/harness/gates/delivery-decision-gate.d.ts +33 -0
- package/dist/harness/gates/delivery-decision-gate.d.ts.map +1 -0
- package/dist/harness/gates/delivery-decision-gate.js +116 -0
- package/dist/harness/gates/delivery-decision-gate.js.map +1 -0
- package/dist/harness/gates/delivery-decision-step.d.ts +19 -0
- package/dist/harness/gates/delivery-decision-step.d.ts.map +1 -0
- package/dist/harness/gates/delivery-decision-step.js +86 -0
- package/dist/harness/gates/delivery-decision-step.js.map +1 -0
- package/dist/harness/gates/gate-override-report.d.ts +59 -0
- package/dist/harness/gates/gate-override-report.d.ts.map +1 -0
- package/dist/harness/gates/gate-override-report.js +86 -0
- package/dist/harness/gates/gate-override-report.js.map +1 -0
- package/dist/harness/gates/gate-override-scope.d.ts +18 -0
- package/dist/harness/gates/gate-override-scope.d.ts.map +1 -0
- package/dist/harness/gates/gate-override-scope.js +98 -0
- package/dist/harness/gates/gate-override-scope.js.map +1 -0
- package/dist/harness/gates/gate-override-validation.d.ts +25 -0
- package/dist/harness/gates/gate-override-validation.d.ts.map +1 -0
- package/dist/harness/gates/gate-override-validation.js +81 -0
- package/dist/harness/gates/gate-override-validation.js.map +1 -0
- package/dist/harness/gates/gate-rule-catalog.d.ts +24 -0
- package/dist/harness/gates/gate-rule-catalog.d.ts.map +1 -0
- package/dist/harness/gates/gate-rule-catalog.js +112 -0
- package/dist/harness/gates/gate-rule-catalog.js.map +1 -0
- package/dist/harness/gates/gate-terms.d.ts +33 -0
- package/dist/harness/gates/gate-terms.d.ts.map +1 -0
- package/dist/harness/gates/gate-terms.js +41 -0
- package/dist/harness/gates/gate-terms.js.map +1 -0
- package/dist/harness/gates/in-run-decision-check.d.ts +21 -0
- package/dist/harness/gates/in-run-decision-check.d.ts.map +1 -0
- package/dist/harness/gates/in-run-decision-check.js +138 -0
- package/dist/harness/gates/in-run-decision-check.js.map +1 -0
- package/dist/harness/gates/journey-gate-inputs.d.ts +37 -0
- package/dist/harness/gates/journey-gate-inputs.d.ts.map +1 -0
- package/dist/harness/gates/journey-gate-inputs.js +81 -0
- package/dist/harness/gates/journey-gate-inputs.js.map +1 -0
- package/dist/harness/gates/migrated-waiver-review.d.ts +6 -0
- package/dist/harness/gates/migrated-waiver-review.d.ts.map +1 -0
- package/dist/harness/gates/migrated-waiver-review.js +116 -0
- package/dist/harness/gates/migrated-waiver-review.js.map +1 -0
- package/dist/harness/gates/resolve-rule.d.ts +59 -0
- package/dist/harness/gates/resolve-rule.d.ts.map +1 -0
- package/dist/harness/gates/resolve-rule.js +41 -0
- package/dist/harness/gates/resolve-rule.js.map +1 -0
- package/dist/harness/gates/unit-gate-overrides.d.ts +25 -0
- package/dist/harness/gates/unit-gate-overrides.d.ts.map +1 -0
- package/dist/harness/gates/unit-gate-overrides.js +122 -0
- package/dist/harness/gates/unit-gate-overrides.js.map +1 -0
- package/dist/harness/journey.d.ts +43 -1
- package/dist/harness/journey.d.ts.map +1 -1
- package/dist/harness/journey.js +207 -33
- package/dist/harness/journey.js.map +1 -1
- package/dist/harness/manifest.d.ts +12 -0
- package/dist/harness/manifest.d.ts.map +1 -1
- package/dist/harness/manifest.js +73 -45
- package/dist/harness/manifest.js.map +1 -1
- package/dist/harness/next-step.d.ts +37 -6
- package/dist/harness/next-step.d.ts.map +1 -1
- package/dist/harness/next-step.js +34 -174
- package/dist/harness/next-step.js.map +1 -1
- package/dist/harness/parse.d.ts +25 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +38 -13
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/provenance.d.ts +29 -0
- package/dist/harness/provenance.d.ts.map +1 -1
- package/dist/harness/provenance.js +109 -9
- package/dist/harness/provenance.js.map +1 -1
- package/dist/harness/script-check.d.ts.map +1 -1
- package/dist/harness/script-check.js +29 -6
- package/dist/harness/script-check.js.map +1 -1
- package/dist/harness/sensors.d.ts +14 -3
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +64 -44
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/triage-signals.d.ts +20 -0
- package/dist/harness/triage-signals.d.ts.map +1 -0
- package/dist/harness/triage-signals.js +30 -0
- package/dist/harness/triage-signals.js.map +1 -0
- package/dist/harness/triage-unit.d.ts +23 -0
- package/dist/harness/triage-unit.d.ts.map +1 -0
- package/dist/harness/triage-unit.js +142 -0
- package/dist/harness/triage-unit.js.map +1 -0
- package/dist/harness/triage.d.ts +28 -0
- package/dist/harness/triage.d.ts.map +1 -0
- package/dist/harness/triage.js +99 -0
- package/dist/harness/triage.js.map +1 -0
- package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
- package/dist/harness/viewpoint-ledger.js +2 -1
- package/dist/harness/viewpoint-ledger.js.map +1 -1
- package/dist/hooks/bash-write-targets.d.ts +15 -0
- package/dist/hooks/bash-write-targets.d.ts.map +1 -0
- package/dist/hooks/bash-write-targets.js +173 -0
- package/dist/hooks/bash-write-targets.js.map +1 -0
- package/dist/hooks/claude-hook-entry.d.ts +11 -0
- package/dist/hooks/claude-hook-entry.d.ts.map +1 -0
- package/dist/hooks/claude-hook-entry.js +137 -0
- package/dist/hooks/claude-hook-entry.js.map +1 -0
- package/dist/hooks/claude-transcript-turn.d.ts +11 -0
- package/dist/hooks/claude-transcript-turn.d.ts.map +1 -0
- package/dist/hooks/claude-transcript-turn.js +143 -0
- package/dist/hooks/claude-transcript-turn.js.map +1 -0
- package/dist/hooks/guard-delivery-contract-rule.d.ts +10 -0
- package/dist/hooks/guard-delivery-contract-rule.d.ts.map +1 -0
- package/dist/hooks/guard-delivery-contract-rule.js +152 -0
- package/dist/hooks/guard-delivery-contract-rule.js.map +1 -0
- package/dist/hooks/guard-protected-paths.d.ts +9 -0
- package/dist/hooks/guard-protected-paths.d.ts.map +1 -0
- package/dist/hooks/guard-protected-paths.js +107 -0
- package/dist/hooks/guard-protected-paths.js.map +1 -0
- package/dist/hooks/guard-rules.d.ts +37 -0
- package/dist/hooks/guard-rules.d.ts.map +1 -0
- package/dist/hooks/guard-rules.js +61 -0
- package/dist/hooks/guard-rules.js.map +1 -0
- package/dist/hooks/guard-tty-spoof-rule.d.ts +15 -0
- package/dist/hooks/guard-tty-spoof-rule.d.ts.map +1 -0
- package/dist/hooks/guard-tty-spoof-rule.js +21 -0
- package/dist/hooks/guard-tty-spoof-rule.js.map +1 -0
- package/dist/hooks/hand-back-core.d.ts +39 -0
- package/dist/hooks/hand-back-core.d.ts.map +1 -0
- package/dist/hooks/hand-back-core.js +122 -0
- package/dist/hooks/hand-back-core.js.map +1 -0
- package/dist/hooks/hook-cli-command.d.ts +9 -0
- package/dist/hooks/hook-cli-command.d.ts.map +1 -0
- package/dist/hooks/hook-cli-command.js +46 -0
- package/dist/hooks/hook-cli-command.js.map +1 -0
- package/dist/hooks/hook-registry.d.ts +10 -0
- package/dist/hooks/hook-registry.d.ts.map +1 -0
- package/dist/hooks/hook-registry.js +24 -0
- package/dist/hooks/hook-registry.js.map +1 -0
- package/dist/hooks/hook-result-contract.d.ts +50 -0
- package/dist/hooks/hook-result-contract.d.ts.map +1 -0
- package/dist/hooks/hook-result-contract.js +80 -0
- package/dist/hooks/hook-result-contract.js.map +1 -0
- package/dist/hooks/hook-toggles.d.ts +10 -0
- package/dist/hooks/hook-toggles.d.ts.map +1 -0
- package/dist/hooks/hook-toggles.js +107 -0
- package/dist/hooks/hook-toggles.js.map +1 -0
- package/dist/hooks/pre-tool-guard-hook.d.ts +10 -0
- package/dist/hooks/pre-tool-guard-hook.d.ts.map +1 -0
- package/dist/hooks/pre-tool-guard-hook.js +105 -0
- package/dist/hooks/pre-tool-guard-hook.js.map +1 -0
- package/dist/hooks/session-start-unit-state-hook.d.ts +13 -0
- package/dist/hooks/session-start-unit-state-hook.d.ts.map +1 -0
- package/dist/hooks/session-start-unit-state-hook.js +57 -0
- package/dist/hooks/session-start-unit-state-hook.js.map +1 -0
- package/dist/hooks/stop-next-step-hook.d.ts +16 -0
- package/dist/hooks/stop-next-step-hook.d.ts.map +1 -0
- package/dist/hooks/stop-next-step-hook.js +42 -0
- package/dist/hooks/stop-next-step-hook.js.map +1 -0
- package/dist/hooks/sungen-project-root.d.ts +19 -0
- package/dist/hooks/sungen-project-root.d.ts.map +1 -0
- package/dist/hooks/sungen-project-root.js +130 -0
- package/dist/hooks/sungen-project-root.js.map +1 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.d.ts +15 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.js +106 -0
- package/dist/orchestrator/ai-skills/command-partial-includes.js.map +1 -0
- package/dist/orchestrator/ai-skills/commands.d.ts +5 -1
- package/dist/orchestrator/ai-skills/commands.d.ts.map +1 -1
- package/dist/orchestrator/ai-skills/commands.js +16 -6
- package/dist/orchestrator/ai-skills/commands.js.map +1 -1
- package/dist/orchestrator/ai-skills/golden-skills.test.js +29 -0
- package/dist/orchestrator/ai-skills/golden-skills.test.js.map +1 -1
- package/dist/orchestrator/assets-drift.d.ts +5 -0
- package/dist/orchestrator/assets-drift.d.ts.map +1 -1
- package/dist/orchestrator/assets-drift.js +12 -3
- package/dist/orchestrator/assets-drift.js.map +1 -1
- package/dist/orchestrator/claude-hooks-install.d.ts +27 -0
- package/dist/orchestrator/claude-hooks-install.d.ts.map +1 -0
- package/dist/orchestrator/claude-hooks-install.js +203 -0
- package/dist/orchestrator/claude-hooks-install.js.map +1 -0
- package/dist/orchestrator/lockstep-version.d.ts +15 -5
- package/dist/orchestrator/lockstep-version.d.ts.map +1 -1
- package/dist/orchestrator/lockstep-version.js +30 -17
- package/dist/orchestrator/lockstep-version.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts +6 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +24 -0
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/screen-manager.d.ts.map +1 -1
- package/dist/orchestrator/screen-manager.js +4 -2
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/orchestrator/templates/ai-src/commands/add-api.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
- package/dist/orchestrator/templates/ai-src/commands/create-test.md +14 -16
- package/dist/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/delivery.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/design.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/feedback.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/locale.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/review.md +2 -0
- package/dist/orchestrator/templates/ai-src/commands/run-test.md +14 -10
- package/dist/orchestrator/templates/ai-src/config/claude.md +20 -7
- package/dist/orchestrator/templates/ai-src/config/copilot.md +20 -7
- package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
- package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
- package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
- package/dist/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
- package/dist/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
- package/dist/utils/safe-yaml-parse.d.ts +8 -0
- package/dist/utils/safe-yaml-parse.d.ts.map +1 -0
- package/dist/utils/safe-yaml-parse.js +51 -0
- package/dist/utils/safe-yaml-parse.js.map +1 -0
- package/package.json +3 -3
- package/src/basis/anchor-grammar.ts +83 -0
- package/src/basis/anchor-hash.ts +27 -0
- package/src/basis/bm51-tables.ts +65 -0
- package/src/basis/extract-spec-anchors.ts +95 -0
- package/src/basis/migration-sentinel.ts +175 -0
- package/src/basis/spec-frontmatter.ts +68 -0
- package/src/basis/spec-sections.ts +35 -0
- package/src/basis/test-basis-schema.ts +81 -0
- package/src/capabilities/discover.ts +15 -2
- package/src/capabilities/registry.ts +16 -0
- package/src/cli/commands/audit.ts +10 -5
- package/src/cli/commands/capability.ts +4 -2
- package/src/cli/commands/contract-derive-command.ts +61 -0
- package/src/cli/commands/contract.ts +130 -0
- package/src/cli/commands/defect.ts +49 -0
- package/src/cli/commands/delivery.ts +92 -15
- package/src/cli/commands/generate.ts +3 -1
- package/src/cli/commands/journey.ts +41 -16
- package/src/cli/commands/next.ts +64 -10
- package/src/cli/commands/triage.ts +57 -0
- package/src/cli/commands/update.ts +35 -8
- package/src/cli/index.ts +24 -30
- package/src/cli/project-sungen-invocation.ts +39 -0
- package/src/contract/approve-contract.ts +94 -0
- package/src/contract/assertion-matcher-vocabulary.ts +93 -0
- package/src/contract/build-contract-verdict.ts +108 -0
- package/src/contract/build-trace-conformance.ts +100 -0
- package/src/contract/classify-contract-change.ts +92 -0
- package/src/contract/classify-contract-unit.ts +47 -0
- package/src/contract/classify-trace-conformance.ts +116 -0
- package/src/contract/contract-git.ts +106 -0
- package/src/contract/contract-hash.ts +34 -0
- package/src/contract/contract-report-file.ts +25 -0
- package/src/contract/contract-schema.ts +137 -0
- package/src/contract/contract-units.ts +52 -0
- package/src/contract/contracts-lock-file.ts +97 -0
- package/src/contract/data-normalize.ts +66 -0
- package/src/contract/derive-free-feature.ts +120 -0
- package/src/contract/field-semantic-redaction.ts +80 -0
- package/src/contract/free-feature-blocks.ts +56 -0
- package/src/contract/lock-secret-guard.ts +95 -0
- package/src/contract/lock-vs-git-head.ts +38 -0
- package/src/contract/normalize-contract-step.ts +74 -0
- package/src/contract/normalize-feature-steps.ts +93 -0
- package/src/contract/oracle-strength.ts +80 -0
- package/src/contract/project-contract-blockers.ts +36 -0
- package/src/contract/record-contract-approval.ts +70 -0
- package/src/contract/render-free-gherkin.ts +113 -0
- package/src/contract/render-trace-sentence.ts +98 -0
- package/src/contract/render-trace-target.ts +68 -0
- package/src/contract/resolve-unit-trace-identities.ts +35 -0
- package/src/contract/trace/collect-trace-evidence.ts +109 -0
- package/src/contract/trace/identity-cache.ts +61 -0
- package/src/contract/trace/select-final-attempt.ts +70 -0
- package/src/contract/trace/snapshot-html-renderer.ts +136 -0
- package/src/contract/trace/snapshot-resolver.ts +66 -0
- package/src/contract/trace/snapshot-store.ts +151 -0
- package/src/contract/trace/target-identity.ts +104 -0
- package/src/contract/trace/test-step-join.ts +104 -0
- package/src/contract/trace/trace-binding.ts +56 -0
- package/src/contract/trace/trace-file-reader.ts +133 -0
- package/src/contract/trace/trace-fingerprint.ts +68 -0
- package/src/contract/trace/trace-identity-resolution.ts +74 -0
- package/src/contract/trace/trace-run-record.ts +80 -0
- package/src/contract/trace/trace-steps.ts +88 -0
- package/src/contract/trace/trace-zip-limits.ts +77 -0
- package/src/contract/trace/trace-zip-reader.ts +127 -0
- package/src/contract/verify-approval-decisions.ts +60 -0
- package/src/decisions/append-decision.ts +35 -0
- package/src/decisions/confirmed-decision-commands.ts +149 -0
- package/src/decisions/decision-file.ts +93 -0
- package/src/decisions/decision-identity.ts +73 -0
- package/src/decisions/decision-integrity-check.ts +61 -0
- package/src/decisions/decision-schema.ts +76 -0
- package/src/decisions/decision-source.ts +14 -0
- package/src/decisions/exclusive-file-create.ts +42 -0
- package/src/decisions/git-head-trust.ts +32 -0
- package/src/decisions/human-confirmation.ts +119 -0
- package/src/decisions/legacy-waiver-migration.ts +135 -0
- package/src/decisions/read-decisions.ts +61 -0
- package/src/decisions/viewpoint-baseline-adapter.ts +74 -0
- package/src/decisions/waiver-decisions.ts +56 -0
- package/src/exporters/csv-exporter.ts +5 -1
- package/src/exporters/feature-parser.ts +12 -0
- package/src/exporters/matrix/build.ts +62 -18
- package/src/exporters/matrix/carry-manual-results.ts +70 -7
- package/src/exporters/matrix/export.ts +17 -2
- package/src/exporters/matrix/gates.ts +62 -129
- package/src/exporters/matrix/render-csv.ts +4 -1
- package/src/exporters/matrix/render-gate-overrides-sheet.ts +50 -0
- package/src/exporters/matrix/render-xlsx.ts +6 -0
- package/src/exporters/matrix/types.ts +9 -1
- package/src/exporters/matrix/xlsx-cells.ts +1 -1
- package/src/exporters/playwright-report-parser.ts +1 -0
- package/src/exporters/scenario-merger.ts +2 -1
- package/src/exporters/types.ts +5 -0
- package/src/generators/test-generator/code-generator.ts +13 -0
- package/src/graph/evaluate-graph.ts +66 -0
- package/src/graph/locate-finding.ts +93 -0
- package/src/graph/node-decl.ts +72 -0
- package/src/graph/nodes/core-node-catalog.ts +15 -0
- package/src/graph/nodes/test-case-contract-nodes.ts +74 -0
- package/src/graph/nodes/test-case-nodes.ts +68 -0
- package/src/graph/nodes/unit-audit-nodes.ts +95 -0
- package/src/graph/nodes/unit-contract-node.ts +89 -0
- package/src/graph/nodes/unit-design-nodes.ts +89 -0
- package/src/graph/nodes/unit-execution-nodes.ts +77 -0
- package/src/graph/test-case-identity.ts +75 -0
- package/src/graph/test-case-results.ts +90 -0
- package/src/graph/test-case-satisfied.ts +55 -0
- package/src/graph/test-case-state-shape.ts +62 -0
- package/src/graph/test-case-states.ts +84 -0
- package/src/graph/unit-artifact-probes.ts +77 -0
- package/src/graph/unit-state-facts.ts +112 -0
- package/src/harness/audit.ts +46 -11
- package/src/harness/catalog/gate-rules.yaml +647 -0
- package/src/harness/counted-assertions.ts +33 -0
- package/src/harness/defect-draft.ts +115 -0
- package/src/harness/defects.ts +94 -0
- package/src/harness/gates/audit-gate-terms.ts +80 -0
- package/src/harness/gates/audit-gate-verdict.ts +78 -0
- package/src/harness/gates/audit-input-hash.ts +55 -0
- package/src/harness/gates/audit-report-verification.ts +201 -0
- package/src/harness/gates/decisions-hash.ts +42 -0
- package/src/harness/gates/delivery-checklist.ts +120 -0
- package/src/harness/gates/delivery-decision-gate.ts +139 -0
- package/src/harness/gates/delivery-decision-step.ts +89 -0
- package/src/harness/gates/gate-override-report.ts +114 -0
- package/src/harness/gates/gate-override-scope.ts +66 -0
- package/src/harness/gates/gate-override-validation.ts +75 -0
- package/src/harness/gates/gate-rule-catalog.ts +82 -0
- package/src/harness/gates/gate-terms.ts +59 -0
- package/src/harness/gates/in-run-decision-check.ts +99 -0
- package/src/harness/gates/journey-gate-inputs.ts +89 -0
- package/src/harness/gates/migrated-waiver-review.ts +68 -0
- package/src/harness/gates/resolve-rule.ts +94 -0
- package/src/harness/gates/unit-gate-overrides.ts +99 -0
- package/src/harness/journey.ts +215 -38
- package/src/harness/manifest.ts +69 -45
- package/src/harness/next-step.ts +60 -170
- package/src/harness/parse.ts +40 -13
- package/src/harness/provenance.ts +99 -11
- package/src/harness/script-check.ts +27 -6
- package/src/harness/sensors.ts +73 -47
- package/src/harness/triage-signals.ts +46 -0
- package/src/harness/triage-unit.ts +113 -0
- package/src/harness/triage.ts +127 -0
- package/src/harness/viewpoint-ledger.ts +2 -2
- package/src/hooks/bash-write-targets.ts +109 -0
- package/src/hooks/claude-hook-entry.ts +85 -0
- package/src/hooks/claude-transcript-turn.ts +96 -0
- package/src/hooks/guard-delivery-contract-rule.ts +110 -0
- package/src/hooks/guard-protected-paths.ts +71 -0
- package/src/hooks/guard-rules.ts +98 -0
- package/src/hooks/guard-tty-spoof-rule.ts +31 -0
- package/src/hooks/hand-back-core.ts +112 -0
- package/src/hooks/hook-cli-command.ts +17 -0
- package/src/hooks/hook-registry.ts +24 -0
- package/src/hooks/hook-result-contract.ts +114 -0
- package/src/hooks/hook-toggles.ts +66 -0
- package/src/hooks/pre-tool-guard-hook.ts +67 -0
- package/src/hooks/session-start-unit-state-hook.ts +56 -0
- package/src/hooks/stop-next-step-hook.ts +37 -0
- package/src/hooks/sungen-project-root.ts +80 -0
- package/src/orchestrator/ai-skills/command-partial-includes.ts +72 -0
- package/src/orchestrator/ai-skills/commands.ts +22 -8
- package/src/orchestrator/ai-skills/golden-skills.test.ts +23 -0
- package/src/orchestrator/assets-drift.ts +12 -5
- package/src/orchestrator/claude-hooks-install.ts +168 -0
- package/src/orchestrator/lockstep-version.ts +28 -15
- package/src/orchestrator/project-initializer.ts +22 -0
- package/src/orchestrator/screen-manager.ts +3 -1
- package/src/orchestrator/templates/ai-src/commands/add-api.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
- package/src/orchestrator/templates/ai-src/commands/create-test.md +14 -16
- package/src/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/delivery.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/design.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/feedback.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/locale.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/review.md +2 -0
- package/src/orchestrator/templates/ai-src/commands/run-test.md +14 -10
- package/src/orchestrator/templates/ai-src/config/claude.md +20 -7
- package/src/orchestrator/templates/ai-src/config/copilot.md +20 -7
- package/src/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
- package/src/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
- package/src/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
- package/src/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
- package/src/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
- package/src/utils/safe-yaml-parse.ts +44 -0
package/src/harness/next-step.ts
CHANGED
|
@@ -16,9 +16,17 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import * as fs from 'fs';
|
|
18
18
|
import * as path from 'path';
|
|
19
|
-
import { reportSlug
|
|
20
|
-
import { readTextFile } from './read-text';
|
|
19
|
+
import { reportSlug } from './unit-paths';
|
|
21
20
|
import { checkAssetsDrift } from '../orchestrator/assets-drift';
|
|
21
|
+
import type { HeadSnapshot } from '../contract/contract-git';
|
|
22
|
+
import { evaluateGraph, EvaluateOptions } from '../graph/evaluate-graph';
|
|
23
|
+
import { CORE_NODES } from '../graph/nodes/core-node-catalog';
|
|
24
|
+
import type { TestCaseState } from '../graph/test-case-state-shape';
|
|
25
|
+
import { testCaseStates } from '../graph/test-case-states';
|
|
26
|
+
import {
|
|
27
|
+
countFailedResults, countScenarios, hasDeliverableFor, hasResolvedSelector, isCompiled, readIfExists, unitResultFiles,
|
|
28
|
+
} from '../graph/unit-artifact-probes';
|
|
29
|
+
import { AuditNotCounted, ContractFacts, ContractSummary, readContractFacts, readTrustedAudit } from '../graph/unit-state-facts';
|
|
22
30
|
|
|
23
31
|
export interface NextStep {
|
|
24
32
|
/** The command to run, as the operator would type it. */
|
|
@@ -33,6 +41,13 @@ export interface NextStep {
|
|
|
33
41
|
* in the same session (#660).
|
|
34
42
|
*/
|
|
35
43
|
kind: 'do' | 'blocked' | 'optional' | 'decide';
|
|
44
|
+
/** The graph node that produced the step (OES-10.1). `--json` detail; the text never shows it. */
|
|
45
|
+
nodeId?: string;
|
|
46
|
+
granularity?: 'unit' | 'test-case';
|
|
47
|
+
/** The one test case the step is about (`sungen next <unit> --case <id>`). */
|
|
48
|
+
testCase?: string;
|
|
49
|
+
/** Catalog rule ids (gate-rules.yaml) the step answers to. */
|
|
50
|
+
gates?: string[];
|
|
36
51
|
}
|
|
37
52
|
|
|
38
53
|
export interface UnitState {
|
|
@@ -47,6 +62,13 @@ export interface UnitState {
|
|
|
47
62
|
selectorsArePlaceholder: boolean;
|
|
48
63
|
compiled: boolean;
|
|
49
64
|
hasResults: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Scenarios whose FINAL attempt failed (failed · timedOut · interrupted) across the unit's result
|
|
67
|
+
* files — a retried pass is not a failure. Any failure puts `sungen triage` in the path: with only
|
|
68
|
+
* "optional" left after a deliverable, a red run read as done and its reds reached the export
|
|
69
|
+
* unclassified. Absent when the state was not read from disk.
|
|
70
|
+
*/
|
|
71
|
+
failedCount?: number;
|
|
50
72
|
hasDeliverable: boolean;
|
|
51
73
|
audit?: {
|
|
52
74
|
overall: number;
|
|
@@ -61,69 +83,42 @@ export interface UnitState {
|
|
|
61
83
|
* warning is one grey stderr line at the top of every command (#620).
|
|
62
84
|
*/
|
|
63
85
|
assetsDrift?: { recordedVersion: string; runningVersion: string };
|
|
86
|
+
/** An audit report exists but does not count (stale, untrusted) — gate and delivery block on it too. */
|
|
87
|
+
auditNotCounted?: AuditNotCounted;
|
|
88
|
+
/** The rebuilt Test Contract verdict (DOS-14.4); absent when not read from disk or no scenario exists. */
|
|
89
|
+
contract?: ContractSummary;
|
|
90
|
+
/** Per-test-case state (DOS-11.1); absent when not read from disk or unreadable. */
|
|
91
|
+
testCases?: TestCaseState[];
|
|
64
92
|
steps: NextStep[];
|
|
65
93
|
}
|
|
66
94
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
return JSON.parse(readTextFile(p)) as Record<string, unknown>;
|
|
72
|
-
} catch {
|
|
73
|
-
return null; // absent or unreadable — treated as "not run"
|
|
74
|
-
}
|
|
95
|
+
export interface ReadUnitStateOptions {
|
|
96
|
+
/** git HEAD read once for many units (`sungen next` with no unit). */
|
|
97
|
+
gitSnapshot?: HeadSnapshot;
|
|
75
98
|
}
|
|
76
99
|
|
|
77
|
-
|
|
78
|
-
let n = 0;
|
|
79
|
-
for (const f of featureFilesFor(unitDir, unit)) {
|
|
80
|
-
const text = fs.existsSync(f) ? readTextFile(f) : '';
|
|
81
|
-
n += (text.match(/^\s*Scenario(?: Outline)?:/gm) ?? []).length;
|
|
82
|
-
}
|
|
83
|
-
return n;
|
|
84
|
-
}
|
|
100
|
+
const exists = (p: string): boolean => fs.existsSync(p);
|
|
85
101
|
|
|
86
102
|
/**
|
|
87
|
-
* Everything the resolver needs, read from disk. `
|
|
88
|
-
* (`<screen>` · `flows/<f>` · `api/<a>`); `unitDir` is its directory.
|
|
103
|
+
* Everything the resolver needs, read from disk. `unit` is the catalog id
|
|
104
|
+
* (`<screen>` · `flows/<f>` · `api/<a>`); `unitDir` is its directory. The audit report is read
|
|
105
|
+
* through verifyAuditReport, as `sungen gate` and `sungen delivery` read it: a stale or untrusted
|
|
106
|
+
* report counts as never audited (OES-11.4) and is named in `auditNotCounted`.
|
|
89
107
|
*/
|
|
90
108
|
export function readUnitState(
|
|
91
|
-
projectRoot: string, unitDir: string, unit: string, kind: UnitState['kind'],
|
|
109
|
+
projectRoot: string, unitDir: string, unit: string, kind: UnitState['kind'], opts: ReadUnitStateOptions = {},
|
|
92
110
|
): UnitState {
|
|
93
111
|
const req = path.join(unitDir, 'requirements');
|
|
94
112
|
const slug = reportSlug(unit);
|
|
95
|
-
const audit =
|
|
113
|
+
const { report: audit, notCounted } = readTrustedAudit(projectRoot, unit);
|
|
96
114
|
const selectorsDir = path.join(unitDir, 'selectors');
|
|
97
115
|
let selectorFiles: string[] = [];
|
|
98
116
|
try {
|
|
99
117
|
selectorFiles = fs.readdirSync(selectorsDir).filter((f) => f.endsWith('.yaml'));
|
|
100
118
|
} catch { /* api units carry no selectors */ }
|
|
101
|
-
|
|
102
|
-
// point in a unit's life — the resolver exists to report exactly that, so it must not crash on it.
|
|
103
|
-
const read = (p: string): string => (fs.existsSync(p) ? readTextFile(p) : '');
|
|
104
|
-
const selectorText = selectorFiles.map((f) => read(path.join(selectorsDir, f))).join('\n');
|
|
119
|
+
const selectorTexts = selectorFiles.map((f) => readIfExists(path.join(selectorsDir, f)));
|
|
105
120
|
const contractPath = path.join(req, 'flow-contract.yaml');
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
const specDirs = [
|
|
109
|
-
path.join(projectRoot, 'specs', 'generated', 'flows', unit),
|
|
110
|
-
path.join(projectRoot, 'specs', 'generated', unit),
|
|
111
|
-
];
|
|
112
|
-
const compiled = specDirs.some((d) => {
|
|
113
|
-
try {
|
|
114
|
-
return fs.readdirSync(d).some((f) => f.endsWith('.spec.ts'));
|
|
115
|
-
} catch { return false; }
|
|
116
|
-
});
|
|
117
|
-
const hasResults = specDirs.some((d) => {
|
|
118
|
-
try {
|
|
119
|
-
return fs.readdirSync(d).some((f) => f.endsWith('-test-result.json'));
|
|
120
|
-
} catch { return false; }
|
|
121
|
-
});
|
|
122
|
-
let hasDeliverable = false;
|
|
123
|
-
try {
|
|
124
|
-
hasDeliverable = fs.readdirSync(path.join(projectRoot, 'qa', 'deliverables'))
|
|
125
|
-
.some((f) => f.startsWith(`${slug}-`));
|
|
126
|
-
} catch { /* nothing exported yet */ }
|
|
121
|
+
const resultFiles = unitResultFiles(projectRoot, unit);
|
|
127
122
|
|
|
128
123
|
const score = (audit?.score ?? {}) as { overall?: number };
|
|
129
124
|
const baseline = (audit?.viewpointBaseline ?? {}) as { status?: string };
|
|
@@ -134,14 +129,16 @@ export function readUnitState(
|
|
|
134
129
|
hasContract: exists(contractPath),
|
|
135
130
|
// A contract WITHOUT `flows:` can only be scored per phase, which is a materially weaker
|
|
136
131
|
// claim — so it is part of the state, not a detail.
|
|
137
|
-
hasFlowInventory: /^\s*flows:\s*$/m.test(
|
|
132
|
+
hasFlowInventory: /^\s*flows:\s*$/m.test(readIfExists(contractPath)),
|
|
138
133
|
scenarioCount: countScenarios(unitDir, unit),
|
|
139
134
|
hasSelectors: selectorFiles.length > 0,
|
|
140
135
|
// A scaffolded selector file exists but resolves nothing; treating it as "done" is what
|
|
141
136
|
// makes a run look further along than it is.
|
|
142
|
-
selectorsArePlaceholder: selectorFiles.length > 0
|
|
143
|
-
|
|
144
|
-
|
|
137
|
+
selectorsArePlaceholder: selectorFiles.length > 0 && !selectorTexts.some(hasResolvedSelector),
|
|
138
|
+
compiled: isCompiled(projectRoot, unit),
|
|
139
|
+
hasResults: resultFiles.length > 0,
|
|
140
|
+
failedCount: countFailedResults(resultFiles),
|
|
141
|
+
hasDeliverable: hasDeliverableFor(projectRoot, slug),
|
|
145
142
|
assetsDrift: (() => {
|
|
146
143
|
const d = checkAssetsDrift(projectRoot);
|
|
147
144
|
return d && d.recordedVersion !== d.runningVersion
|
|
@@ -156,131 +153,24 @@ export function readUnitState(
|
|
|
156
153
|
viewpointBaselineStatus: baseline.status,
|
|
157
154
|
}
|
|
158
155
|
: undefined,
|
|
156
|
+
...(notCounted ? { auditNotCounted: notCounted } : {}),
|
|
159
157
|
steps: [],
|
|
160
158
|
};
|
|
159
|
+
let contract: ContractFacts | undefined;
|
|
160
|
+
if (state.scenarioCount > 0) state.contract = (contract = readContractFacts(projectRoot, unit, unitDir, opts.gitSnapshot)).summary;
|
|
161
|
+
try {
|
|
162
|
+
state.testCases = testCaseStates(projectRoot, unit, { unitDir, auditFindings: state.audit?.findings ?? [] })
|
|
163
|
+
.map((tc) => (contract?.cases.has(tc.id) ? { ...tc, contract: contract.cases.get(tc.id) } : tc));
|
|
164
|
+
} catch { /* an unparseable .feature — the unit-level nodes still answer, as before test-case state */ }
|
|
161
165
|
state.steps = deriveSteps(state);
|
|
162
166
|
return state;
|
|
163
167
|
}
|
|
164
168
|
|
|
165
|
-
/** The finding codes worth naming in a next step — each maps to a specific repair. */
|
|
166
|
-
const REPAIRABLE = [
|
|
167
|
-
'FLOW-CONTRACT-MISSING', 'FLOW-INVENTORY-MISSING', 'FLOW-UNCOVERED', 'FLOW-UNDECLARED',
|
|
168
|
-
'FLOW-PHASE-MISFILED', 'FLOW-GUARANTEE-MISSING', 'FLOW-OUTCOME-UNPROVEN', 'CONTINUITY-ONE-SIDED',
|
|
169
|
-
'ORACLE-URL-ONLY',
|
|
170
|
-
'SPEC-RESTATED-UNVERIFIED', 'VIEWPOINT-GESTURE-SUBSTITUTED', 'SPEC-UNCOVERED', 'SPEC-CLAUSE-UNCOVERED',
|
|
171
|
-
'TRIGGER-UNCOVERED', 'PERMISSION-PAIR-MISSING', 'VISIBILITY-PAIR-MISSING',
|
|
172
|
-
'VIEWPOINT-ITEM-MISSING', 'MANUAL-CODE-MISSING', 'MANUAL-AUTOMATABLE', 'DEPTH-DEFERRED',
|
|
173
|
-
'UI-INVENTORY-MISSING', 'UI-INVENTORY-INCOMPLETE', 'UI-ITEM-UNCOVERED',
|
|
174
|
-
];
|
|
175
|
-
|
|
176
169
|
/**
|
|
177
|
-
* The ordered answer
|
|
178
|
-
*
|
|
170
|
+
* The ordered answer — earliest unmet precondition first, so the list reads as a path rather than a
|
|
171
|
+
* menu. Evaluated over the internal node graph (src/graph, OES-10.1): each former if/return branch
|
|
172
|
+
* is one node, and an open blocking node cuts everything after it, exactly as the `return`s did.
|
|
179
173
|
*/
|
|
180
|
-
export function deriveSteps(s: UnitState): NextStep[] {
|
|
181
|
-
|
|
182
|
-
const design = s.kind === 'api' ? `/sungen:create-test ${s.unit}` : `/sungen:create-test ${s.unit}`;
|
|
183
|
-
|
|
184
|
-
if (!s.hasSpec && !s.hasViewpoint) {
|
|
185
|
-
out.push({
|
|
186
|
-
kind: 'blocked',
|
|
187
|
-
command: `write qa/${s.kind === 'screen' ? 'screens' : s.kind === 'flow' ? 'flows' : 'api'}/${s.unit}/requirements/spec.md`,
|
|
188
|
-
because: 'the unit has neither a spec nor a test-viewpoint, so there is nothing to generate FROM — generation without a source invents behaviour',
|
|
189
|
-
});
|
|
190
|
-
return out;
|
|
191
|
-
}
|
|
192
|
-
// Stale AI assets come FIRST, because they invalidate the advice below: a HARD RULE added to
|
|
193
|
-
// `create-test` reaches nobody until `sungen update` runs, so the run that follows will repeat
|
|
194
|
-
// whatever the old instructions said. Upgrading the package alone does not refresh them, and the
|
|
195
|
-
// existing warning is one grey stderr line among a command's whole output (#620).
|
|
196
|
-
if (s.assetsDrift) {
|
|
197
|
-
out.push({
|
|
198
|
-
kind: 'do',
|
|
199
|
-
command: 'sungen update',
|
|
200
|
-
because: `this project's AI commands/skills were written by sungen ${s.assetsDrift.recordedVersion} and you are running ${s.assetsDrift.runningVersion} — upgrading the package does NOT refresh them, so any rule added since ${s.assetsDrift.recordedVersion} is not in effect for the next run`,
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
// The yardstick. `atomicLedger` and `traceability` are measured against test-viewpoint.md and
|
|
204
|
-
// four sensors read it, so its absence is not cosmetic — and it can go missing from a unit that
|
|
205
|
-
// already HAS a spec (a run deleted it), which the "no source at all" branch above never sees.
|
|
206
|
-
if (!s.hasViewpoint) {
|
|
207
|
-
out.push({
|
|
208
|
-
kind: 'blocked',
|
|
209
|
-
command: s.kind === 'flow'
|
|
210
|
-
? `sungen add-flow --flow ${s.unit} --path <start-url> # repairs the missing scaffold; never overwrites`
|
|
211
|
-
: `write qa/screens/${s.unit}/requirements/test-viewpoint.md`,
|
|
212
|
-
because: 'requirements/test-viewpoint.md is missing — it is the yardstick `atomicLedger` and `traceability` are measured against, and four sensors read it, so the audit reports VIEWPOINT-MISSING and those axes are excluded. A flow contract does not substitute: it declares the use case, the viewpoint declares the claims',
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
if (s.kind === 'flow' && !s.hasContract) {
|
|
216
|
-
out.push({
|
|
217
|
-
kind: 'blocked',
|
|
218
|
-
command: `author requirements/flow-contract.yaml, then ${design}`,
|
|
219
|
-
because: 'a flow with no contract is scored as a generic screen against page-type themes a journey cannot have (FLOW-CONTRACT-MISSING)',
|
|
220
|
-
});
|
|
221
|
-
return out;
|
|
222
|
-
}
|
|
223
|
-
if (s.scenarioCount === 0) {
|
|
224
|
-
out.push({ kind: 'do', command: design, because: 'no scenarios exist yet' });
|
|
225
|
-
return out;
|
|
226
|
-
}
|
|
227
|
-
if (s.kind === 'flow' && !s.hasFlowInventory) {
|
|
228
|
-
out.push({
|
|
229
|
-
kind: 'do',
|
|
230
|
-
command: `add \`flows:\` to requirements/flow-contract.yaml, then sungen audit --screen ${s.unit}`,
|
|
231
|
-
because: 'without the inventory, coverage is measured per PHASE — and a phase counts as covered as soon as one scenario carries it, so the number cannot tell you a flow is missing',
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
if (!s.audit) {
|
|
235
|
-
out.push({ kind: 'do', command: `sungen audit --screen ${s.unit}`, because: 'the suite has never been measured' });
|
|
236
|
-
return out;
|
|
237
|
-
}
|
|
238
|
-
if (s.audit.viewpointBaselineStatus === 'changed') {
|
|
239
|
-
out.push({
|
|
240
|
-
kind: 'decide',
|
|
241
|
-
command: `sungen audit --screen ${s.unit} --accept-viewpoint`,
|
|
242
|
-
because: 'test-viewpoint.md changed since the accepted baseline, so the ledger and traceability axes are not evidence until a QA confirms the new declaration. A decision, not a step: an agent presents it and does not run it — accepting the yardstick you just wrote makes both axes read 100% by construction',
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
const repair = s.audit.findings
|
|
246
|
-
.map((f) => f.split(':')[0].trim())
|
|
247
|
-
.filter((code) => REPAIRABLE.includes(code));
|
|
248
|
-
if (repair.length > 0) {
|
|
249
|
-
out.push({
|
|
250
|
-
kind: 'do',
|
|
251
|
-
command: `repair, then sungen audit --screen ${s.unit}`,
|
|
252
|
-
because: `${repair.length} finding(s) name a specific repair: ${[...new Set(repair)].slice(0, 4).join(', ')}`,
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
if (s.audit.gateStatus === 'FAIL') {
|
|
256
|
-
out.push({
|
|
257
|
-
kind: 'blocked',
|
|
258
|
-
command: `repair the gate, then sungen audit --screen ${s.unit}`,
|
|
259
|
-
because: `the viewpoint gate is FAIL at ${s.audit.overall}/10 — running tests against a design that fails its own gate measures the wrong thing`,
|
|
260
|
-
});
|
|
261
|
-
return out;
|
|
262
|
-
}
|
|
263
|
-
if (s.kind !== 'api' && (!s.hasSelectors || s.selectorsArePlaceholder)) {
|
|
264
|
-
out.push({
|
|
265
|
-
kind: 'do',
|
|
266
|
-
command: `/sungen:run-test ${s.unit}`,
|
|
267
|
-
because: s.hasSelectors
|
|
268
|
-
? 'the selector file is still a placeholder, so nothing resolves against a live page'
|
|
269
|
-
: 'no selectors exist yet — run-test generates them from the live page, compiles and auto-fixes',
|
|
270
|
-
});
|
|
271
|
-
return out;
|
|
272
|
-
}
|
|
273
|
-
if (!s.compiled) {
|
|
274
|
-
out.push({ kind: 'do', command: `sungen generate --${s.kind === 'flow' ? 'flow' : 'screen'} ${s.unit}`, because: 'the suite has not been compiled to a spec yet' });
|
|
275
|
-
return out;
|
|
276
|
-
}
|
|
277
|
-
if (!s.hasResults) {
|
|
278
|
-
out.push({ kind: 'do', command: `/sungen:run-test ${s.unit}`, because: 'the compiled spec has never been run, so every case is Pending' });
|
|
279
|
-
return out;
|
|
280
|
-
}
|
|
281
|
-
if (!s.hasDeliverable) {
|
|
282
|
-
out.push({ kind: 'do', command: `/sungen:delivery ${s.unit}`, because: 'results exist but have not been exported to the Test Case & Coverage Matrix' });
|
|
283
|
-
}
|
|
284
|
-
out.push({ kind: 'optional', command: `/sungen:create-test ${s.unit}`, because: 'extend coverage — the next tier, or the flows the inventory still lists as pending' });
|
|
285
|
-
return out;
|
|
174
|
+
export function deriveSteps(s: UnitState, opts: EvaluateOptions = {}): NextStep[] {
|
|
175
|
+
return evaluateGraph(CORE_NODES, s, s.testCases, opts);
|
|
286
176
|
}
|
package/src/harness/parse.ts
CHANGED
|
@@ -79,6 +79,7 @@ export interface ScenarioInfo {
|
|
|
79
79
|
deferredToFlow?: boolean; // @deferred:flow — owned by a flow, not automated on this screen (H6)
|
|
80
80
|
ownedByFlow?: string; // @owned-by:<flow> — the flow that owns this deferred scenario (H6)
|
|
81
81
|
featureManual?: boolean; // its Feature is tagged @manual — codegen skips the whole file (#835)
|
|
82
|
+
handWritten?: boolean; // @free / @impl:code — counted, never compiled (isHandWritten, DOS-14.8)
|
|
82
83
|
/** Ordered steps with their resolved bucket (And/But inherit) — flow handoff analysis (#569). */
|
|
83
84
|
/** `arg` = the step's data table, normalised (#817) — absent when the step has none. */
|
|
84
85
|
steps?: Array<{ bucket: 'given' | 'when' | 'then'; text: string; arg?: string }>;
|
|
@@ -285,6 +286,25 @@ function withBackground(sc: ParsedScenario, background?: ParsedScenario): Parsed
|
|
|
285
286
|
return { ...sc, steps: [...bg, ...((sc.steps as ParsedStep[]) || [])] } as ParsedScenario;
|
|
286
287
|
}
|
|
287
288
|
|
|
289
|
+
/**
|
|
290
|
+
* The `VP-<CATEGORY>-<n>` / `FL-<PHASE>-<n>` code in a scenario title, and its category — the ONE
|
|
291
|
+
* reading of it; the manifest kept an older copy of this regex and recorded no code for
|
|
292
|
+
* VP-I18N-001, VP-LIST-DISPLAY-01, VP-AF02-01 or any FL- id (#889).
|
|
293
|
+
*
|
|
294
|
+
* Category is everything between `VP-` and the final `-<sequence>` — INCLUDING hyphens, so
|
|
295
|
+
* compound categories (VP-LIST-DISPLAY-01, VP-ADD-TO-CART-03, VP-PRODUCT-DISCOVERY-02) parse,
|
|
296
|
+
* not just single-word ones. A single-word category (VP-CART-001) still works. (H1)
|
|
297
|
+
* Flows use journey-phase ids (FL-HP-001 / FL-ER-002) — the VP- anchor rejected them, so every
|
|
298
|
+
* flow scenario had NO category and the whole suite bucketed `other` (taxonomy=0%, #569).
|
|
299
|
+
* Segments may carry digits: the use-case framework numbers its flows (VP-AF02-01,
|
|
300
|
+
* VP-EF11-01 — one id per Alternate/Exception Flow), and `[A-Z]+` also silently truncated
|
|
301
|
+
* VP-I18N-001 to no category at all (the `18` broke the class mid-segment).
|
|
302
|
+
*/
|
|
303
|
+
export function vpCodeOf(title: string): { vpCode?: string; category?: string } {
|
|
304
|
+
const m = title.match(/\b(?:VP|FL)-([A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*)-\d+/i);
|
|
305
|
+
return m ? { vpCode: m[0].toUpperCase(), category: m[1].toUpperCase() } : {};
|
|
306
|
+
}
|
|
307
|
+
|
|
288
308
|
function classifyScenario(sc: ParsedScenario): ScenarioInfo {
|
|
289
309
|
const tags = sc.tags || [];
|
|
290
310
|
const deferredToFlow = tags.includes('@deferred:flow');
|
|
@@ -310,17 +330,7 @@ function classifyScenario(sc: ParsedScenario): ScenarioInfo {
|
|
|
310
330
|
let priority: Priority = 'unknown';
|
|
311
331
|
for (const t of tags) if (PRIORITY_TAGS[t]) priority = PRIORITY_TAGS[t];
|
|
312
332
|
|
|
313
|
-
|
|
314
|
-
// compound categories (VP-LIST-DISPLAY-01, VP-ADD-TO-CART-03, VP-PRODUCT-DISCOVERY-02) parse,
|
|
315
|
-
// not just single-word ones. A single-word category (VP-CART-001) still works. (H1)
|
|
316
|
-
// Flows use journey-phase ids (FL-HP-001 / FL-ER-002) — the VP- anchor rejected them, so every
|
|
317
|
-
// flow scenario had NO category and the whole suite bucketed `other` (taxonomy=0%, #569).
|
|
318
|
-
// Segments may carry digits: the use-case framework numbers its flows (VP-AF02-01,
|
|
319
|
-
// VP-EF11-01 — one id per Alternate/Exception Flow), and `[A-Z]+` also silently truncated
|
|
320
|
-
// VP-I18N-001 to no category at all (the `18` broke the class mid-segment).
|
|
321
|
-
const codeMatch = sc.name.match(/\b(?:VP|FL)-([A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*)-\d+/i);
|
|
322
|
-
const vpCode = codeMatch ? codeMatch[0].toUpperCase() : undefined;
|
|
323
|
-
const category = codeMatch ? codeMatch[1].toUpperCase() : undefined;
|
|
333
|
+
const { vpCode, category } = vpCodeOf(sc.name);
|
|
324
334
|
// Project-scheme ID: the leading token of the title (VP0-001 / MS-HP-001 / VP-LIST-001).
|
|
325
335
|
const leadMatch = sc.name.match(/^\s*([A-Za-z][A-Za-z0-9.-]*)/);
|
|
326
336
|
const vpId = leadMatch && isIdLike(leadMatch[1]) ? leadMatch[1].toUpperCase() : undefined;
|
|
@@ -395,9 +405,26 @@ export function loadScenarios(featurePath: string): ScenarioInfo[] {
|
|
|
395
405
|
const feature = parser.parseFeatureFile(featurePath);
|
|
396
406
|
// Kept apart from `manual` so the audit's accounting is unchanged; only `select` reads it.
|
|
397
407
|
const featureManual = (feature.tags || []).some((t: string) => /^@manual\b/i.test(t)) || undefined;
|
|
408
|
+
// A derived `@proposed` scenario (sungen contract derive, DOS-14.8) is not counted until QA approves it;
|
|
409
|
+
// an approved `@free` / `@impl:code` one IS counted, but never compiled (`handWritten`).
|
|
410
|
+
const tagsOf = (s: { tags?: string[] }): string[] => [...(feature.tags || []), ...(s.tags || [])];
|
|
398
411
|
return (feature.scenarios || [])
|
|
399
|
-
.filter((s) => !s.stepsName && !s.hookType) // skip @steps/@hook blocks
|
|
400
|
-
.map((s) => ({
|
|
412
|
+
.filter((s) => !s.stepsName && !s.hookType && !tagsOf(s).some((t) => PROPOSED_TAG.test(t))) // skip @steps/@hook blocks and unapproved proposals
|
|
413
|
+
.map((s) => ({
|
|
414
|
+
...classifyScenario(withBackground(s, feature.background)), sourceFile: featurePath, featureManual,
|
|
415
|
+
handWritten: isHandWritten(tagsOf(s), featurePath) || undefined,
|
|
416
|
+
}));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const PROPOSED_TAG = /^@proposed$/i;
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Is a scenario implemented by HAND-WRITTEN code rather than compiled (DOS-14.2, 14.8)? `@free`,
|
|
423
|
+
* `@impl:code`, a derived `@proposed`, or anything in a derived `*.free.feature`. The one predicate
|
|
424
|
+
* codegen (never compiles these), script-check (never expects a compiled twin) and the harness share.
|
|
425
|
+
*/
|
|
426
|
+
export function isHandWritten(tags: readonly string[], featureFile?: string): boolean {
|
|
427
|
+
return (!!featureFile && featureFile.endsWith('.free.feature')) || tags.some((t) => /^@(?:free|impl:code|proposed)$/i.test(t));
|
|
401
428
|
}
|
|
402
429
|
|
|
403
430
|
/**
|
|
@@ -1,22 +1,110 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Provenance stamp for deterministic reports (score-determinism D1)
|
|
2
|
+
* Provenance stamp for deterministic reports (score-determinism D1), and the RULES the audit's
|
|
3
|
+
* verdict was judged by (#933, owner decision W4).
|
|
3
4
|
*
|
|
4
|
-
* The audit score is a pure function of the project files + the bundled
|
|
5
|
-
* Stamping
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* The audit score is a pure function of the project files + the bundled catalogs + the scoring
|
|
6
|
+
* code. Stamping them into the report lets two users who get different scores see IMMEDIATELY
|
|
7
|
+
* whether the cause is a rules mismatch rather than a real difference in their test design — and
|
|
8
|
+
* lets `verifyAuditReport` tell a report judged by today's rules from one judged by other rules:
|
|
9
|
+
*
|
|
10
|
+
* sungenVersion which package wrote it — informational: a newer sungen with the same rules
|
|
11
|
+
* gives the same verdict, so the version alone never makes a report stale
|
|
12
|
+
* catalogHash sha256(universal-viewpoints.yaml), first 12 hex — the viewpoint catalog
|
|
13
|
+
* rulesHash sha256(AUDIT_RULES_VERSION + every catalog file under harness/catalog/ + each
|
|
14
|
+
* bundled driver's sources/catalogs), first 12 hex — everything the verdict
|
|
15
|
+
* depends on that is not the project's own files. No package VERSION is hashed:
|
|
16
|
+
* packages are lockstep-versioned, so a release would stale every report
|
|
9
17
|
*/
|
|
10
18
|
import * as fs from 'fs';
|
|
11
19
|
import * as path from 'path';
|
|
12
20
|
import * as crypto from 'crypto';
|
|
13
21
|
|
|
22
|
+
/**
|
|
23
|
+
* The version of the audit's SCORING CODE. Bump it (by one) in the same change whenever what
|
|
24
|
+
* `runAudit` computes for the same project can change: a sensor, a threshold, a gate term
|
|
25
|
+
* (audit-gate-terms.ts), the score model or weights, a finding that feeds the verdict, or the
|
|
26
|
+
* audit sensor of a bundled driver. Every report scored before the bump then reads stale and asks
|
|
27
|
+
* for one `sungen audit`. Catalog edits (harness/catalog/*.yaml) and bundled-driver changes (their
|
|
28
|
+
* sources and catalogs are hashed) need no bump.
|
|
29
|
+
* A release that changes none of these keeps every report trusted across the upgrade.
|
|
30
|
+
* Enforced by tests/audit/run.ts: its rules lock (tests/audit/audit-rules.lock.json) fails when the
|
|
31
|
+
* fixtures' audit output changes under an unchanged rules hash. After the bump, re-record it:
|
|
32
|
+
* npx tsx tests/audit/run.ts --record-rules-lock
|
|
33
|
+
*/
|
|
34
|
+
export const AUDIT_RULES_VERSION = 1;
|
|
35
|
+
|
|
14
36
|
export interface Provenance {
|
|
15
37
|
sungenVersion: string;
|
|
16
38
|
catalogHash: string; // sha256(universal-viewpoints.yaml), first 12 hex — the catalog that drives the score
|
|
39
|
+
rulesHash: string; // sha256(AUDIT_RULES_VERSION + harness/catalog/*.yaml + bundled drivers), first 12 hex — the verdict's rules
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** A bundled driver as an input of the rules: its package dir, or null when it is not installed. */
|
|
43
|
+
export interface DriverRulesInput { name: string; version?: string; dir: string | null }
|
|
44
|
+
|
|
45
|
+
/** What is not a driver's rule: dependencies, build output, tests, docs, editor and lock files. */
|
|
46
|
+
const SKIP_DIR = new Set(['node_modules', 'dist', 'tests', 'test', 'coverage']);
|
|
47
|
+
const SKIP_FILE = /^(?:\.|package(?:-lock)?\.json$|tsconfig.*\.json$|.*\.(?:md|tsbuildinfo)$)/;
|
|
48
|
+
|
|
49
|
+
function driverFiles(root: string, rel = ''): string[] {
|
|
50
|
+
const out: string[] = [];
|
|
51
|
+
for (const e of fs.readdirSync(path.join(root, rel), { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name, 'en'))) {
|
|
52
|
+
if (e.name.startsWith('.')) continue;
|
|
53
|
+
const r = rel ? `${rel}/${e.name}` : e.name;
|
|
54
|
+
if (e.isDirectory()) { if (!SKIP_DIR.has(e.name)) out.push(...driverFiles(root, r)); }
|
|
55
|
+
else if (e.isFile() && !SKIP_FILE.test(e.name)) out.push(r);
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** The package root above a driver's resolved entry file (the dir whose package.json names it). */
|
|
61
|
+
function packageRootOf(entry: string, name: string): string | null {
|
|
62
|
+
let dir = path.dirname(entry);
|
|
63
|
+
for (let i = 0; i < 8; i++) {
|
|
64
|
+
try { if (JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'))?.name === name) return dir; } catch { /* keep walking */ }
|
|
65
|
+
const parent = path.dirname(dir);
|
|
66
|
+
if (parent === dir) break;
|
|
67
|
+
dir = parent;
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
17
70
|
}
|
|
18
71
|
|
|
72
|
+
/** Each bundled driver as discovery would load it (project anchor, then core's), or `absent`. */
|
|
73
|
+
export function bundledDriverRulesInputs(): DriverRulesInput[] {
|
|
74
|
+
// Lazy: discovery pulls the capability registry, which nothing else here needs.
|
|
75
|
+
const { bundledDriverNames, resolveDriverCopy } = require('../capabilities/discover') as typeof import('../capabilities/discover');
|
|
76
|
+
return bundledDriverNames().map((name) => {
|
|
77
|
+
const copy = resolveDriverCopy(name);
|
|
78
|
+
const dir = copy ? packageRootOf(copy.resolved, name) : null;
|
|
79
|
+
return { name, version: copy?.version, dir };
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const CATALOG_DIR = path.join(__dirname, 'catalog');
|
|
84
|
+
const sha12 = (s: string | Buffer): string => crypto.createHash('sha256').update(s).digest('hex').slice(0, 12);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The rules hash: the scoring version, every *.yaml of the catalog dir (by name), and each bundled
|
|
88
|
+
* driver — every source / catalog file of its package (by relative path; build output, tests and
|
|
89
|
+
* dependencies excluded), or a stable `absent` marker when it is not installed. A driver's version is
|
|
90
|
+
* deliberately left out: releases bump every package in lockstep, and only content changes the rules.
|
|
91
|
+
*/
|
|
92
|
+
export function rulesHashOf(rulesVersion: number, catalogDir: string = CATALOG_DIR, drivers: DriverRulesInput[] = bundledDriverRulesInputs()): string {
|
|
93
|
+
const files = fs.readdirSync(catalogDir).filter((f) => f.endsWith('.yaml')).sort();
|
|
94
|
+
const h = crypto.createHash('sha256').update(`audit-rules:${rulesVersion}\n`);
|
|
95
|
+
for (const f of files) h.update(`${f}\n`).update(fs.readFileSync(path.join(catalogDir, f))).update('\n');
|
|
96
|
+
for (const d of [...drivers].sort((a, b) => a.name.localeCompare(b.name, 'en'))) {
|
|
97
|
+
h.update(`driver:${d.name}\n`);
|
|
98
|
+
if (!d.dir) { h.update('absent\n'); continue; }
|
|
99
|
+
for (const f of driverFiles(d.dir)) h.update(`${f}\n`).update(fs.readFileSync(path.join(d.dir, f))).update('\n');
|
|
100
|
+
}
|
|
101
|
+
return h.digest('hex').slice(0, 12);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let cached: Provenance | null = null;
|
|
105
|
+
|
|
19
106
|
export function getProvenance(): Provenance {
|
|
107
|
+
if (cached) return cached;
|
|
20
108
|
let sungenVersion = 'unknown';
|
|
21
109
|
try {
|
|
22
110
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'package.json'), 'utf-8'));
|
|
@@ -24,10 +112,10 @@ export function getProvenance(): Provenance {
|
|
|
24
112
|
} catch { /* version stays 'unknown' */ }
|
|
25
113
|
|
|
26
114
|
let catalogHash = 'unknown';
|
|
27
|
-
try {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
} catch { /* hash stays 'unknown' */ }
|
|
115
|
+
try { catalogHash = sha12(fs.readFileSync(path.join(CATALOG_DIR, 'universal-viewpoints.yaml'), 'utf-8')); } catch { /* hash stays 'unknown' */ }
|
|
116
|
+
let rulesHash = 'unknown';
|
|
117
|
+
try { rulesHash = rulesHashOf(AUDIT_RULES_VERSION); } catch { /* hash stays 'unknown' */ }
|
|
31
118
|
|
|
32
|
-
|
|
119
|
+
cached = { sungenVersion, catalogHash, rulesHash };
|
|
120
|
+
return cached;
|
|
33
121
|
}
|
|
@@ -18,6 +18,8 @@ import * as os from 'os';
|
|
|
18
18
|
import { loadUnitScenarios, ScenarioInfo } from './parse';
|
|
19
19
|
import { featureFilesFor } from './unit-paths';
|
|
20
20
|
import { readTextFile } from './read-text';
|
|
21
|
+
import { CATALOG_GATE_RULES } from './gates/resolve-rule';
|
|
22
|
+
import { evaluateGateTerms } from './gates/gate-terms';
|
|
21
23
|
|
|
22
24
|
export interface ScriptCheckResult {
|
|
23
25
|
screen: string;
|
|
@@ -107,6 +109,12 @@ const ASSERTION_STEP_COMMENT = /^\s*\/\/\s*Assert\b/;
|
|
|
107
109
|
// but as a bare substring it would also exempt a genuinely hollow step whose test-data or step
|
|
108
110
|
// text happened to contain it.
|
|
109
111
|
const NOOP_STEP_MARKER = /^\s*\/\/\s*App launched via wdio capabilities/;
|
|
112
|
+
// The same kind of step on the web adapter, where the explanation IS the step comment: the
|
|
113
|
+
// step-mapper compiles `Given User is on [Edit] dialog` (and its exit) to `// Enter dialog scope:
|
|
114
|
+
// Edit` and no code, because it only re-roots the steps after it — the next assertion runs as
|
|
115
|
+
// `page.getByRole('dialog', …).getByRole(…)`. A field unit reported 13 BYPASS, every one of them
|
|
116
|
+
// this comment, and exited 2 on a correct suite (#881). Anchored to the whole marker line.
|
|
117
|
+
const SCOPE_STEP_MARKER = /^\s*\/\/\s*(?:Enter|Exit) dialog scope(?::\s*.*)?$/;
|
|
110
118
|
|
|
111
119
|
/** A spec comment line reduced to its text, for comparison against a compiler step comment. */
|
|
112
120
|
const commentText = (line: string): string => line.trim().replace(/^\/\/\s?/, '').trim();
|
|
@@ -241,7 +249,7 @@ export function analyzeFaithfulness(
|
|
|
241
249
|
const hasCode = region.some((l) => !isComment(l) && CODE_LINE.test(l));
|
|
242
250
|
// A documented no-op emits its explanation INTO the step's region, so read the region
|
|
243
251
|
// (not just the marker line) for it — see NOOP_STEP_MARKER.
|
|
244
|
-
if (hasCode || region.some((l) => NOOP_STEP_MARKER.test(l))) continue;
|
|
252
|
+
if (hasCode || region.some((l) => NOOP_STEP_MARKER.test(l)) || SCOPE_STEP_MARKER.test(body[markers[s]])) continue;
|
|
245
253
|
if (tailAmbiguous && s === markers.length - 1) continue;
|
|
246
254
|
hollowSteps.push({ test: title, step: body[markers[s]].trim().slice(0, 70) });
|
|
247
255
|
}
|
|
@@ -334,7 +342,8 @@ function findSpecs(dir: string, name: string, kind: UnitKind): string[] {
|
|
|
334
342
|
export async function runScriptCheck(screenDir: string, screenName: string, kind: UnitKind): Promise<ScriptCheckResult> {
|
|
335
343
|
const featureFiles = featureFilesFor(screenDir, screenName);
|
|
336
344
|
const scenarios = loadUnitScenarios(screenDir, screenName);
|
|
337
|
-
|
|
345
|
+
// Hand-written (@free / @impl:code) scenarios are proven by their traces, not compiled — no twin expected.
|
|
346
|
+
const automated = scenarios.filter((s) => !s.manual && !s.handWritten);
|
|
338
347
|
const manual = scenarios.filter((s) => s.manual);
|
|
339
348
|
|
|
340
349
|
const committedSpecs = findSpecs(path.join(process.cwd(), 'specs', 'generated'), screenName, kind);
|
|
@@ -382,9 +391,10 @@ export async function runScriptCheck(screenDir: string, screenName: string, kind
|
|
|
382
391
|
// failed regenerate degrades check C to its heuristic instead of crashing it.
|
|
383
392
|
let stepTrace: Map<string, string[]> | undefined;
|
|
384
393
|
if (committedSpec) {
|
|
394
|
+
let tmp: string | undefined;
|
|
385
395
|
try {
|
|
386
396
|
const { CodeGenerator } = require('../generators/test-generator/code-generator');
|
|
387
|
-
|
|
397
|
+
tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'sungen-scriptcheck-'));
|
|
388
398
|
const qaSourceDir = path.join(process.cwd(), 'qa', kind === 'flow' ? 'flows' : kind === 'api' ? 'api' : 'screens');
|
|
389
399
|
// api units derive their unit id (api/<area>) from the feature path — like `generate --api`;
|
|
390
400
|
// screen/flow pass screenName + flowMode explicitly (unchanged → byte-identical regenerate).
|
|
@@ -422,9 +432,11 @@ export async function runScriptCheck(screenDir: string, screenName: string, kind
|
|
|
422
432
|
if (drift === 'drift') {
|
|
423
433
|
findings.push('DRIFT: committed spec differs from a fresh regenerate → spec was hand-edited or the .feature changed without `sungen generate`. The test code no longer reflects the Gherkin.');
|
|
424
434
|
}
|
|
425
|
-
fs.rmSync(tmp, { recursive: true, force: true });
|
|
426
435
|
} catch (e) {
|
|
427
436
|
findings.push(`Drift check skipped (regenerate failed): ${e instanceof Error ? e.message : e}`);
|
|
437
|
+
} finally {
|
|
438
|
+
// Removed on every path: a throwing regenerate used to leave one sungen-scriptcheck-* dir per call.
|
|
439
|
+
if (tmp) fs.rmSync(tmp, { recursive: true, force: true });
|
|
428
440
|
}
|
|
429
441
|
}
|
|
430
442
|
|
|
@@ -440,7 +452,16 @@ export async function runScriptCheck(screenDir: string, screenName: string, kind
|
|
|
440
452
|
}
|
|
441
453
|
const bypass = assertionlessTests.length > 0 || hollowSteps.length > 0;
|
|
442
454
|
|
|
443
|
-
|
|
455
|
+
// Every term is a hard rule (the #387 drift family): no gate-override can lower one, so the
|
|
456
|
+
// catalog alone decides (OES-11.3).
|
|
457
|
+
const faithful = evaluateGateTerms([
|
|
458
|
+
{ rule: 'script.no-spec', holds: !!committedSpec },
|
|
459
|
+
{ rule: 'script.count-mismatch', holds: countMatch },
|
|
460
|
+
{ rule: 'script.missing-in-spec', holds: missingInSpec.length === 0 },
|
|
461
|
+
{ rule: 'script.extra-in-spec', holds: extraInSpec.length === 0 },
|
|
462
|
+
{ rule: 'script.drift', holds: drift === 'in-sync' },
|
|
463
|
+
{ rule: 'script.bypass', holds: !bypass },
|
|
464
|
+
], CATALOG_GATE_RULES);
|
|
444
465
|
|
|
445
466
|
return {
|
|
446
467
|
screen: screenName,
|
|
@@ -456,7 +477,7 @@ export async function runScriptCheck(screenDir: string, screenName: string, kind
|
|
|
456
477
|
assertionlessTests,
|
|
457
478
|
hollowSteps,
|
|
458
479
|
bypass,
|
|
459
|
-
status:
|
|
480
|
+
status: faithful.pass ? 'OK' : 'FAIL',
|
|
460
481
|
findings,
|
|
461
482
|
};
|
|
462
483
|
}
|