@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/cli/commands/next.ts
CHANGED
|
@@ -3,12 +3,24 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The next step is derived from what the project HOLDS, not from which command just ran, so a
|
|
5
5
|
* session cannot lose the thread by finishing somewhere that has no footer of its own (#597).
|
|
6
|
+
*
|
|
7
|
+
* sungen next [unit] every unit (or one), unit-level steps; test-case work folds
|
|
8
|
+
* into one line per node ("N test case(s) …")
|
|
9
|
+
* sungen next <unit> --case <id> one test case: its state, and its steps after the blocking
|
|
10
|
+
* unit steps before them (OES-10.3)
|
|
11
|
+
* --json the same, machine-readable; steps add nodeId, granularity,
|
|
12
|
+
* testCase?, gates?; every older field is kept. stdout is the
|
|
13
|
+
* payload alone (#660, #836)
|
|
6
14
|
*/
|
|
7
15
|
import { Command } from 'commander';
|
|
8
16
|
import * as fs from 'fs';
|
|
9
17
|
import * as path from 'path';
|
|
10
|
-
import {
|
|
18
|
+
import { CLI_GIT_TIMEOUT_MS, headSnapshot } from '../../contract/contract-git';
|
|
19
|
+
import { testCaseStatusLabel } from '../../graph/test-case-satisfied';
|
|
20
|
+
import { testCaseStates } from '../../graph/test-case-states';
|
|
21
|
+
import { deriveSteps, NextStep, readUnitState, UnitState } from '../../harness/next-step';
|
|
11
22
|
import { resolveUnit, resolveUnitCandidates, AmbiguousUnitError } from '../resolve-unit';
|
|
23
|
+
import { withProjectInvocation } from '../project-sungen-invocation';
|
|
12
24
|
|
|
13
25
|
/** Every unit the project holds, so `sungen next` with no argument still answers. */
|
|
14
26
|
function allUnits(cwd: string): Array<{ name: string; kind: UnitState['kind']; dir: string }> {
|
|
@@ -24,7 +36,16 @@ function allUnits(cwd: string): Array<{ name: string; kind: UnitState['kind']; d
|
|
|
24
36
|
return out;
|
|
25
37
|
}
|
|
26
38
|
|
|
27
|
-
|
|
39
|
+
/** Steps as text, each `sungen …` command as this project runs it (#939); `--json` keeps them canonical. */
|
|
40
|
+
function renderSteps(steps: NextStep[], cwd: string): void {
|
|
41
|
+
for (const st of steps) {
|
|
42
|
+
const mark = st.kind === 'blocked' ? '⛔' : st.kind === 'optional' ? '○' : st.kind === 'decide' ? '⚖' : '→';
|
|
43
|
+
console.log(` ${mark} ${withProjectInvocation(st.command, cwd)}${st.kind === 'decide' ? ' (a QA decision — ask, do not run)' : ''}`);
|
|
44
|
+
console.log(` ${st.because}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function render(s: UnitState, cwd: string): void {
|
|
28
49
|
const L = console.log;
|
|
29
50
|
L('');
|
|
30
51
|
L(`━━━ Next steps: ${s.unit} (${s.kind}) ━━━`);
|
|
@@ -38,12 +59,40 @@ function render(s: UnitState): void {
|
|
|
38
59
|
].filter(Boolean);
|
|
39
60
|
L(` state: ${held.length ? held.join(' · ') : '(nothing yet)'}`);
|
|
40
61
|
if (s.audit) L(` audit: ${s.audit.overall}/10 [${s.audit.gateStatus}] · ${s.audit.findings.length} finding(s)`);
|
|
62
|
+
else if (s.auditNotCounted) L(` audit: ${s.auditNotCounted.state === 'stale' ? 'stale' : 'not trusted'} — ${s.auditNotCounted.reason}`);
|
|
41
63
|
L('');
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
64
|
+
renderSteps(s.steps, cwd);
|
|
65
|
+
L('');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** `--case <id>`: the case's state and its frontier. Exits 1 when the case cannot be found. */
|
|
69
|
+
function caseView(s: UnitState, cwd: string, unitDir: string, id: string, json: boolean): void {
|
|
70
|
+
let cases = s.testCases;
|
|
71
|
+
if (!cases) {
|
|
72
|
+
try { cases = testCaseStates(cwd, s.unit, { unitDir }); } catch (e) {
|
|
73
|
+
throw new Error(`the test cases of ${s.unit} could not be read: ${e instanceof Error ? e.message : e}`);
|
|
74
|
+
}
|
|
46
75
|
}
|
|
76
|
+
const tc = cases.find((c) => c.id === id);
|
|
77
|
+
if (!tc) {
|
|
78
|
+
const known = cases.slice(0, 8).map((c) => c.id).join(', ');
|
|
79
|
+
throw new Error(`no test case "${id}" in ${s.unit}${known ? ` — known: ${known}${cases.length > 8 ? ', …' : ''}` : ' (it holds no scenario)'}`);
|
|
80
|
+
}
|
|
81
|
+
const steps = deriveSteps({ ...s, testCases: cases }, { testCase: id });
|
|
82
|
+
if (json) { console.log(JSON.stringify({ unit: s.unit, kind: s.kind, testCase: tc, steps }, null, 2)); return; }
|
|
83
|
+
const L = console.log;
|
|
84
|
+
L('');
|
|
85
|
+
L(`━━━ Next steps: ${s.unit} › ${tc.id} (${s.kind}) ━━━`);
|
|
86
|
+
L('');
|
|
87
|
+
L(` test case: ${tc.title}${tc.unstableId ? ' (no VP-id — this id changes when the title does)' : ''}`);
|
|
88
|
+
L(` where: ${tc.file}#L${tc.lines[0]}-L${tc.lines[1]}`);
|
|
89
|
+
L(` status: ${testCaseStatusLabel(tc)} · result ${tc.result}${tc.mocked && tc.result === 'passed' ? ' (mocked)' : ''}${tc.stale ? ` · stale: ${tc.stale}` : ''}${tc.triage ? ` · triage ${tc.triage.class}` : ''}`);
|
|
90
|
+
if (tc.contract) L(` contract: ${tc.contract.class}${tc.contract.uncommitted ? ' · lock entry not committed' : ''}${tc.contract.lowIdentity ? ' · low target identity' : ''}`);
|
|
91
|
+
if (tc.anchors.length) L(` anchors: ${tc.anchors.map((a) => `${a.anchor} (${a.change})`).join(', ')}`);
|
|
92
|
+
for (const f of tc.findings) L(` finding: ${f.code} [${f.confidence.label} ${f.confidence.score}] ${f.citation}`);
|
|
93
|
+
L('');
|
|
94
|
+
if (steps.length) renderSteps(steps, cwd);
|
|
95
|
+
else L(` ✓ nothing to do for this test case — ${testCaseStatusLabel(tc)}`);
|
|
47
96
|
L('');
|
|
48
97
|
}
|
|
49
98
|
|
|
@@ -51,10 +100,13 @@ export function registerNextCommand(program: Command): void {
|
|
|
51
100
|
program
|
|
52
101
|
.command('next [unit]')
|
|
53
102
|
.description('What to do next for a unit (or every unit), derived from the project state')
|
|
103
|
+
.option('--case <id>', 'One test case of the unit (its VP-id): its state and its next steps')
|
|
54
104
|
.option('--json', 'Machine-readable output')
|
|
55
|
-
.action((unit: string | undefined, o: { json?: boolean }) => {
|
|
105
|
+
.action((unit: string | undefined, o: { json?: boolean; case?: string }) => {
|
|
56
106
|
try {
|
|
57
107
|
const cwd = process.cwd();
|
|
108
|
+
if (o.case && !unit) throw new Error('--case needs a unit: sungen next <unit> --case <id>');
|
|
109
|
+
const gitSnapshot = headSnapshot(cwd, CLI_GIT_TIMEOUT_MS);
|
|
58
110
|
let states: UnitState[];
|
|
59
111
|
if (unit) {
|
|
60
112
|
const resolved = resolveUnit(unit, cwd);
|
|
@@ -62,7 +114,9 @@ export function registerNextCommand(program: Command): void {
|
|
|
62
114
|
console.error(`Error: no unit named "${unit}" under qa/screens, qa/flows or qa/api.`);
|
|
63
115
|
process.exit(1);
|
|
64
116
|
}
|
|
65
|
-
|
|
117
|
+
const state = readUnitState(cwd, resolved.dir, unit, resolved.kind, { gitSnapshot });
|
|
118
|
+
if (o.case) { caseView(state, cwd, resolved.dir, o.case, Boolean(o.json)); return; }
|
|
119
|
+
states = [state];
|
|
66
120
|
} else {
|
|
67
121
|
const units = allUnits(cwd);
|
|
68
122
|
if (units.length === 0) {
|
|
@@ -72,14 +126,14 @@ export function registerNextCommand(program: Command): void {
|
|
|
72
126
|
// A name in two places is ambiguous; report it rather than answering for one of them.
|
|
73
127
|
states = units.map((u) => {
|
|
74
128
|
if (resolveUnitCandidates(u.name, cwd).length > 1) throw new AmbiguousUnitError(u.name, resolveUnitCandidates(u.name, cwd));
|
|
75
|
-
return readUnitState(cwd, u.dir, u.name, u.kind);
|
|
129
|
+
return readUnitState(cwd, u.dir, u.name, u.kind, { gitSnapshot });
|
|
76
130
|
});
|
|
77
131
|
}
|
|
78
132
|
if (o.json) {
|
|
79
133
|
console.log(JSON.stringify(states.length === 1 ? states[0] : states, null, 2));
|
|
80
134
|
return;
|
|
81
135
|
}
|
|
82
|
-
for (const s of states) render(s);
|
|
136
|
+
for (const s of states) render(s, cwd);
|
|
83
137
|
} catch (e) {
|
|
84
138
|
console.error(`Error: ${e instanceof Error ? e.message : e}`);
|
|
85
139
|
process.exit(1);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { resolveUnit } from '../resolve-unit';
|
|
4
|
+
import { triageUnit, writeTriageReport } from '../../harness/triage-unit';
|
|
5
|
+
import type { TriageClass } from '../../harness/triage';
|
|
6
|
+
|
|
7
|
+
/** Display order: what needs a decision first, green last. */
|
|
8
|
+
const ORDER: TriageClass[] = ['product-candidate', 'unclassified', 'test-defect', 'environment', 'blocked-capability', 'known-defect', 'flaky'];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `sungen triage` — classify every red or flaky scenario of the latest run (see harness/triage.ts).
|
|
12
|
+
* Reports, never gates: always exits 0 once the unit is found.
|
|
13
|
+
*/
|
|
14
|
+
export function registerTriageCommand(program: Command): void {
|
|
15
|
+
program
|
|
16
|
+
.command('triage')
|
|
17
|
+
.description('Classify each red or flaky scenario of the latest run: known-defect, blocked, environment, test-defect, product-candidate, unclassified')
|
|
18
|
+
.option('-s, --screen <name>', 'Screen or flow name')
|
|
19
|
+
.option('--api <name>', 'API-first area or api flow (qa/api/<name>)')
|
|
20
|
+
.option('--area <name>', 'Alias of --api')
|
|
21
|
+
.option('--json', 'Output the raw JSON report')
|
|
22
|
+
.action((o: { screen?: string; api?: string; area?: string; json?: boolean }) => {
|
|
23
|
+
try {
|
|
24
|
+
const name = o.screen || o.api || o.area;
|
|
25
|
+
if (!name) throw new Error('Provide --screen <name> (or --api <area>)');
|
|
26
|
+
const cwd = process.cwd();
|
|
27
|
+
const unit = resolveUnit(name, cwd);
|
|
28
|
+
if (!unit) throw new Error(`Not found: qa/screens/${name}, qa/flows/${name}, or qa/api/${name}`);
|
|
29
|
+
|
|
30
|
+
const report = triageUnit(cwd, unit);
|
|
31
|
+
if (report.resultFiles.length === 0) {
|
|
32
|
+
if (o.json) console.log(JSON.stringify(report, null, 2));
|
|
33
|
+
else console.log(`\n ${name}: no results — run the tests first.\n`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const saved = writeTriageReport(cwd, report);
|
|
37
|
+
if (o.json) { console.log(JSON.stringify(report, null, 2)); return; }
|
|
38
|
+
|
|
39
|
+
const L = console.log;
|
|
40
|
+
L(`\n━━━ Triage: ${name} ━━━`);
|
|
41
|
+
if (report.rows.length === 0) L(' ✓ every scenario passed on its first attempt');
|
|
42
|
+
for (const cls of ORDER) {
|
|
43
|
+
const rows = report.rows.filter((r) => r.class === cls);
|
|
44
|
+
if (rows.length === 0) continue;
|
|
45
|
+
L(`\n ${cls} (${rows.length})`);
|
|
46
|
+
for (const r of rows) {
|
|
47
|
+
L(` • ${r.scenario}${r.variant ? ` [${r.variant}]` : ''}${r.defectId ? ` → ${r.defectId}` : ''}`);
|
|
48
|
+
L(` ${r.ruleId}: ${r.evidence}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
L(`\n Report: ${path.relative(cwd, saved)}\n`);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error('Error:', error instanceof Error ? error.message : error);
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
1
|
+
import { Command, Option } from 'commander';
|
|
2
2
|
import { spawnSync } from 'child_process';
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import * as path from 'path';
|
|
@@ -41,7 +41,7 @@ export function registerUpdateCommand(program: Command): void {
|
|
|
41
41
|
program
|
|
42
42
|
.command('update')
|
|
43
43
|
.description(
|
|
44
|
-
'Reinstall @sun-asterisk/sungen (stable by default, --beta for prerelease) + refresh AI rules, commands, skills',
|
|
44
|
+
'Reinstall @sun-asterisk/sungen (stable by default, --beta / --alpha for prerelease) + refresh AI rules, commands, skills',
|
|
45
45
|
)
|
|
46
46
|
.option('--dry-run', 'Show what would be updated without making changes')
|
|
47
47
|
.option(
|
|
@@ -56,9 +56,19 @@ export function registerUpdateCommand(program: Command): void {
|
|
|
56
56
|
'Switch to the BETA channel (installs @beta — prerelease builds for testing)',
|
|
57
57
|
false,
|
|
58
58
|
)
|
|
59
|
+
// `--beta --alpha` is ambiguous: commander refuses it while parsing — one usage-error line, exit 1,
|
|
60
|
+
// before the action (and any npm install) runs — rather than settling it by flag order.
|
|
61
|
+
.addOption(
|
|
62
|
+
new Option(
|
|
63
|
+
'--alpha',
|
|
64
|
+
'Switch to the ALPHA channel (installs @alpha — early builds of the next big update, ahead of beta)',
|
|
65
|
+
)
|
|
66
|
+
.default(false)
|
|
67
|
+
.conflicts('beta'),
|
|
68
|
+
)
|
|
59
69
|
.option(
|
|
60
70
|
'--tag <dist-tag>',
|
|
61
|
-
'Install a specific npm dist-tag (e.g. latest, beta, next). Overrides --beta.',
|
|
71
|
+
'Install a specific npm dist-tag (e.g. latest, beta, alpha, next). Overrides --beta / --alpha.',
|
|
62
72
|
)
|
|
63
73
|
.option(
|
|
64
74
|
'--skip-npm-install',
|
|
@@ -70,16 +80,14 @@ export function registerUpdateCommand(program: Command): void {
|
|
|
70
80
|
'Skip reinstalling the project-local sungen packages (AI assets only — leaves node_modules stale)',
|
|
71
81
|
false,
|
|
72
82
|
)
|
|
73
|
-
.action(async (options: { dryRun?: boolean; beta?: boolean; tag?: string; skipNpmInstall?: boolean; skipProject?: boolean; assistant?: string[]; force?: boolean }) => {
|
|
83
|
+
.action(async (options: { dryRun?: boolean; beta?: boolean; alpha?: boolean; tag?: string; skipNpmInstall?: boolean; skipProject?: boolean; assistant?: string[]; force?: boolean }) => {
|
|
74
84
|
try {
|
|
75
85
|
const skipNpm =
|
|
76
86
|
Boolean(options.skipNpmInstall) || process.env[SKIP_NPM_ENV] === '1';
|
|
77
87
|
const skipProject =
|
|
78
88
|
Boolean(options.skipProject) || process.env[SKIP_PROJECT_ENV] === '1';
|
|
79
89
|
|
|
80
|
-
|
|
81
|
-
// `--beta` → beta channel; running plain `sungen update` later switches back to stable.
|
|
82
|
-
const channel = options.tag || (options.beta ? 'beta' : 'latest');
|
|
90
|
+
const channel = resolveUpdateChannel(options);
|
|
83
91
|
|
|
84
92
|
if (!skipNpm) {
|
|
85
93
|
reinstallSungen(channel);
|
|
@@ -106,6 +114,13 @@ export function registerUpdateCommand(program: Command): void {
|
|
|
106
114
|
// …and move the old `trace: 'on-first-retry'` default, which never records a trace off CI.
|
|
107
115
|
const { installTraceMode } = require('../../orchestrator/trace-mode-install');
|
|
108
116
|
installTraceMode(process.cwd(), options.dryRun ?? false);
|
|
117
|
+
// Claude Code hooks: re-merged into .claude/settings.json (user hooks kept); sungen entries a
|
|
118
|
+
// newer version dropped, or qa/sungen.config.yaml turned off, are removed.
|
|
119
|
+
if (resolveAssistants(options.assistant).includes('claude')) {
|
|
120
|
+
const { installClaudeHooks, describeHooksInstall } = require('../../orchestrator/claude-hooks-install');
|
|
121
|
+
const hooks = installClaudeHooks(process.cwd(), { dryRun: options.dryRun ?? false });
|
|
122
|
+
console.log(`${hooks.settings === 'unreadable' ? '⚠️ ' : '🪝'} ${options.dryRun ? '[dry-run] ' : ''}${describeHooksInstall(hooks)}\n`);
|
|
123
|
+
}
|
|
109
124
|
} catch (error) {
|
|
110
125
|
console.error('❌ Update failed:', error);
|
|
111
126
|
process.exit(1);
|
|
@@ -113,6 +128,18 @@ export function registerUpdateCommand(program: Command): void {
|
|
|
113
128
|
});
|
|
114
129
|
}
|
|
115
130
|
|
|
131
|
+
/**
|
|
132
|
+
* The npm dist-tag `sungen update` installs. `latest` = official/stable (the default, and how a
|
|
133
|
+
* plain `sungen update` switches back); `--beta` / `--alpha` pick a prerelease channel (each branch
|
|
134
|
+
* auto-publishes to the dist-tag of its name); `--tag` names any dist-tag and wins over both.
|
|
135
|
+
* `--beta` with `--alpha` never reaches here — the option definition refuses the pair.
|
|
136
|
+
*/
|
|
137
|
+
export function resolveUpdateChannel(o: { tag?: string; beta?: boolean; alpha?: boolean }): string {
|
|
138
|
+
if (o.tag) return o.tag;
|
|
139
|
+
if (o.alpha) return 'alpha';
|
|
140
|
+
return o.beta ? 'beta' : 'latest';
|
|
141
|
+
}
|
|
142
|
+
|
|
116
143
|
function reinstallSungen(channel: string): void {
|
|
117
144
|
const spec = `@sun-asterisk/sungen@${channel}`;
|
|
118
145
|
const label = channel === 'latest' ? 'stable (latest)' : `${channel} channel`;
|
|
@@ -139,7 +166,7 @@ function printCurrentVersion(channel: string): void {
|
|
|
139
166
|
spawnSync('sungen', ['--version'], { stdio: 'inherit', shell: true });
|
|
140
167
|
}
|
|
141
168
|
if (channel === 'latest') {
|
|
142
|
-
console.log(' Channel: stable. To try prereleases: sungen update --beta');
|
|
169
|
+
console.log(' Channel: stable. To try prereleases: sungen update --beta (or --alpha for the next big update)');
|
|
143
170
|
} else {
|
|
144
171
|
console.log(` Channel: ${channel} (prerelease). To return to stable: sungen update`);
|
|
145
172
|
}
|
package/src/cli/index.ts
CHANGED
|
@@ -37,16 +37,28 @@ import { registerCapabilityCommand } from './commands/capability';
|
|
|
37
37
|
import { registerFlowCheckCommand } from './commands/flow-check';
|
|
38
38
|
import { registerContextCommand } from './commands/context';
|
|
39
39
|
import { registerRepairCommand } from './commands/repair';
|
|
40
|
+
import { registerTriageCommand } from './commands/triage';
|
|
41
|
+
import { registerDefectCommand } from './commands/defect';
|
|
40
42
|
import { registerResultsCommand } from './commands/results-merge';
|
|
41
43
|
import { registerLoginCommand } from './commands/login';
|
|
42
44
|
import { capabilityRegistry } from '../capabilities/registry';
|
|
43
45
|
import { discoverAndRegisterCapabilities } from '../capabilities/discover';
|
|
44
46
|
import { warnAssetsDrift } from '../orchestrator/assets-drift';
|
|
47
|
+
import { attachCliHandBack } from '../hooks/hand-back-core';
|
|
48
|
+
import { registerHookCommand } from '../hooks/hook-cli-command';
|
|
45
49
|
|
|
46
50
|
// Read version from package.json so `--version` never drifts from the released version.
|
|
47
51
|
const { version } = require('../../package.json') as { version: string };
|
|
48
52
|
|
|
49
53
|
async function main() {
|
|
54
|
+
// #597 + P0.1 — the hand-back, once, for EVERY command, and from the moment parsing starts: a
|
|
55
|
+
// usage error never reaches an action, and `main().catch` exits from outside one. It hangs off
|
|
56
|
+
// process exit (not postAction) because several commands exit with a MEANINGFUL code that skips
|
|
57
|
+
// commander's hooks (`depth-lint` → 2). It points at `sungen next` instead of restating a step,
|
|
58
|
+
// so it cannot drift from the project state. A failure prints it on stderr after the error;
|
|
59
|
+
// `--json`/`--grep` keep it off stdout (#836); `hook` never prints one, `next` only when it fails (#937). The line and
|
|
60
|
+
// those rules live in the hook core (src/hooks/hand-back-core.ts) — this file only wires it.
|
|
61
|
+
const handBack = attachCliHandBack(process.argv, process.cwd());
|
|
50
62
|
const program = new Command();
|
|
51
63
|
|
|
52
64
|
program
|
|
@@ -89,10 +101,16 @@ registerSetupMobileEnvCommand(program);
|
|
|
89
101
|
registerFlowCheckCommand(program);
|
|
90
102
|
registerContextCommand(program);
|
|
91
103
|
registerRepairCommand(program);
|
|
104
|
+
registerTriageCommand(program);
|
|
105
|
+
registerDefectCommand(program);
|
|
92
106
|
registerResultsCommand(program);
|
|
93
107
|
registerIngestCommand(program);
|
|
94
108
|
registerEvalCommand(program);
|
|
95
109
|
registerLoginCommand(program);
|
|
110
|
+
// Test Contract (DOS-14). Registered inline (typed require, still loaded eagerly like every command)
|
|
111
|
+
// so the phase that added it touches ONE line of this file — no import-block edit to merge-conflict.
|
|
112
|
+
(require('./commands/contract') as typeof import('./commands/contract')).registerContractCommand(program);
|
|
113
|
+
registerHookCommand(program); // hidden: Claude Code hooks, JSON on stdout
|
|
96
114
|
|
|
97
115
|
// Capability-contributed CLI commands (Capability SPI): drivers own their authoring commands
|
|
98
116
|
// (e.g. @sungen/driver-api → `sungen api import`). Discover, then register each.
|
|
@@ -104,38 +122,14 @@ registerSetupMobileEnvCommand(program);
|
|
|
104
122
|
// Every command warns once when the project's AI assets came from a different
|
|
105
123
|
// build — `update` is the only thing that refreshes them, and nothing used to
|
|
106
124
|
// say so (stderr, so `--json` output stays parseable).
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// #597 — the hand-back, once, for EVERY command. It used to be hardcoded per command and only
|
|
110
|
-
// two of twenty-nine printed one, so a run that finished anywhere else finished in silence:
|
|
111
|
-
// `capability add` ended with a blank line and the session stopped mid-workflow. Adding a
|
|
112
|
-
// footer to the other twenty-seven would repeat the mistake in bulk.
|
|
113
|
-
//
|
|
114
|
-
// It hangs off `process.on('exit')` rather than a postAction hook because several commands
|
|
115
|
-
// exit with a MEANINGFUL code (`depth-lint` returns 2 when there are deepen candidates) and
|
|
116
|
-
// `process.exit` skips commander's hooks entirely — a postAction version printed for `audit`
|
|
117
|
-
// and silently not for `depth-lint`, which is the same class of gap all over again.
|
|
118
|
-
//
|
|
119
|
-
// It points at `sungen next` instead of restating a step, so it can never drift from the real
|
|
120
|
-
// project state. Skipped on a hard error (code 1): there the error message is the actionable
|
|
121
|
-
// thing, and burying it under a footer helps nobody. `--json` keeps stdout parseable.
|
|
122
|
-
let handBack: { unit?: string; json: boolean } | null = null;
|
|
125
|
+
// `hook` speaks only JSON to Claude Code — no drift warning there.
|
|
123
126
|
program.hook('preAction', (_thisCommand, actionCommand) => {
|
|
124
|
-
if (actionCommand.name()
|
|
125
|
-
const opts = actionCommand.opts() as Record<string, unknown>;
|
|
126
|
-
const unit = [opts.screen, opts.flow, opts.area].find((v) => typeof v === 'string' && v)
|
|
127
|
-
?? (typeof actionCommand.args?.[0] === 'string' ? actionCommand.args[0] : undefined);
|
|
128
|
-
// `--grep` is machine output too: callers capture it with `$(…)`, and a footer on stdout
|
|
129
|
-
// became part of the regex — the last alternative of `changed --grep` silently matched
|
|
130
|
-
// nothing, so `--change-only` skipped its last scenario (#836).
|
|
131
|
-
handBack = { unit: unit as string | undefined, json: opts.json === true || opts.grep === true };
|
|
127
|
+
if (actionCommand.name() !== 'hook') warnAssetsDrift(process.cwd());
|
|
132
128
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (handBack.json) process.stderr.write(`${line}\n`);
|
|
138
|
-
else process.stdout.write(`${line}\n`);
|
|
129
|
+
|
|
130
|
+
// The action knows its unit and output mode; the hand-back default above is refined here.
|
|
131
|
+
program.hook('preAction', (_thisCommand, actionCommand) => {
|
|
132
|
+
handBack.onAction(actionCommand.name(), actionCommand.opts() as Record<string, unknown>, actionCommand.args);
|
|
139
133
|
});
|
|
140
134
|
|
|
141
135
|
await program.parseAsync(process.argv);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a hint names sungen inside a project (#939, items 1–2).
|
|
3
|
+
*
|
|
4
|
+
* A project that installs its own sungen (`npm i -D @sun-asterisk/sungen`) runs it with `npx sungen`;
|
|
5
|
+
* a bare `sungen` is whatever global install the machine has — in the field test an older 3.2.24-beta
|
|
6
|
+
* beside the project's 3.3.0-alpha. And `sungen update` without a flag switches to the stable
|
|
7
|
+
* channel, so on an alpha or beta install the update hint must keep the channel it runs on.
|
|
8
|
+
*
|
|
9
|
+
* sungenInvocation(root) 'npx sungen' when <root>/node_modules/@sun-asterisk/sungen exists, else 'sungen'
|
|
10
|
+
* withProjectInvocation(cmd, root) a canonical `sungen …` command as this project runs it
|
|
11
|
+
* updateCommand(root, version?) `<invocation> update` plus `--alpha` / `--beta` (`--tag <id>` for another prerelease)
|
|
12
|
+
*
|
|
13
|
+
* Only the project root itself is looked at — where `npm i` puts a QA project's install — so a
|
|
14
|
+
* monorepo checkout above a fixture does not turn its hints into `npx`.
|
|
15
|
+
*/
|
|
16
|
+
import * as fs from 'fs';
|
|
17
|
+
import * as path from 'path';
|
|
18
|
+
import { getPackageVersion } from '../exporters/package-info';
|
|
19
|
+
|
|
20
|
+
export function sungenInvocation(projectRoot: string): string {
|
|
21
|
+
return fs.existsSync(path.join(projectRoot, 'node_modules', '@sun-asterisk', 'sungen', 'package.json')) ? 'npx sungen' : 'sungen';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** `sungen audit --screen x` → `npx sungen audit --screen x` in a project with its own install; anything else unchanged. */
|
|
25
|
+
export function withProjectInvocation(command: string, projectRoot: string): string {
|
|
26
|
+
const inv = sungenInvocation(projectRoot);
|
|
27
|
+
return inv !== 'sungen' && /^sungen\b/.test(command) ? `${inv}${command.slice('sungen'.length)}` : command;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The `sungen update` flag that keeps the channel of `version` (its prerelease id); '' for stable. */
|
|
31
|
+
export function updateChannelFlag(version: string = getPackageVersion()): string {
|
|
32
|
+
const id = version.match(/^\d+\.\d+\.\d+-([0-9A-Za-z-]+)/)?.[1];
|
|
33
|
+
if (!id) return '';
|
|
34
|
+
return id === 'alpha' || id === 'beta' ? ` --${id}` : ` --tag ${id}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function updateCommand(projectRoot: string, version: string = getPackageVersion()): string {
|
|
38
|
+
return `${sungenInvocation(projectRoot)} update${updateChannelFlag(version)}`;
|
|
39
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sungen contract approve --screen <u> [--scenario <id>]` — the human act that locks a contract
|
|
3
|
+
* (DOS-14.4, DOS-13.4, takumi T5). In order, so a human never confirms something then rejected:
|
|
4
|
+
*
|
|
5
|
+
* 1. resolve the unit, read the current scenarios and the lock (an unreadable lock refuses)
|
|
6
|
+
* 2. pick what changes: new, changed or tampered scenarios, and — when approving the whole unit —
|
|
7
|
+
* the entries of scenarios that left the feature; nothing changed → nothing to approve, no prompt
|
|
8
|
+
* 3. refuse a duplicated id or a Scenario Outline, and run the secret guard
|
|
9
|
+
* 4. show each change with its ladder class (a weakening is named before it is confirmed) and
|
|
10
|
+
* require the typed phrase on a TTY — without one: refuse and print the exact command
|
|
11
|
+
* 5. read everything AGAIN: if the feature or the lock moved while the human was reading, what
|
|
12
|
+
* they confirmed is not what would be written — refuse (L5)
|
|
13
|
+
* 6. record the decision and the lock (record-contract-approval.ts)
|
|
14
|
+
*/
|
|
15
|
+
import { ConfirmationIO, formatCommand, requireTypedConfirmation } from '../decisions/human-confirmation';
|
|
16
|
+
import { gitUserName } from '../decisions/decision-source';
|
|
17
|
+
import { classifyScenario } from './classify-contract-change';
|
|
18
|
+
import { canonicalJson } from './contract-hash';
|
|
19
|
+
import { ContractScenario, isHumanApproved } from './contract-schema';
|
|
20
|
+
import { resolveContractUnit } from './contract-units';
|
|
21
|
+
import { lockPathFor, ReadLock, readLockFile } from './contracts-lock-file';
|
|
22
|
+
import { dropProposedTags } from './free-feature-blocks';
|
|
23
|
+
import { contractFeatureFiles, loadContractScenarios } from './normalize-feature-steps';
|
|
24
|
+
import { ApprovalWrite, checkApprovalSecrets, recordContractApproval } from './record-contract-approval';
|
|
25
|
+
|
|
26
|
+
export interface ApproveInput { projectRoot: string; unit: string; scenario?: string; reason?: string; io: ConfirmationIO }
|
|
27
|
+
export interface ApproveResult {
|
|
28
|
+
status: 'approved' | 'nothing-to-approve';
|
|
29
|
+
lockPath: string;
|
|
30
|
+
decisionId?: string;
|
|
31
|
+
approved: string[];
|
|
32
|
+
removed: string[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface Plan { write: ApprovalWrite; lock: ReadLock | null; fingerprint: string }
|
|
36
|
+
|
|
37
|
+
function plan(i: ApproveInput): Plan {
|
|
38
|
+
const unit = resolveContractUnit(i.projectRoot, i.unit);
|
|
39
|
+
const lock = readLockFile(lockPathFor(unit.dir));
|
|
40
|
+
const current = loadContractScenarios(unit.dir, unit.name);
|
|
41
|
+
const ids = new Set(current.map((s) => s.id));
|
|
42
|
+
if (i.scenario && !ids.has(i.scenario) && !lock?.scenarios[i.scenario]) {
|
|
43
|
+
throw new Error(`--scenario ${i.scenario} names no scenario of ${i.unit} (current: ${[...ids].join(', ') || 'none'})`);
|
|
44
|
+
}
|
|
45
|
+
const chosen = current.filter((s) => !i.scenario || s.id === i.scenario);
|
|
46
|
+
const dup = [...new Set(chosen.map((s) => s.id))].find((id) => current.filter((s) => s.id === id).length > 1);
|
|
47
|
+
if (dup) throw new Error(`Refused: scenario id ${dup} is used by ${current.filter((s) => s.id === dup).length} scenarios — a lock entry must name exactly one. Give each its own ID.`);
|
|
48
|
+
const outlines = chosen.filter((s) => s.source.outline).map((s) => s.id);
|
|
49
|
+
if (outlines.length) throw new Error(`Refused: ${outlines.join(', ')} ${outlines.length > 1 ? 'are' : 'is a'} Scenario Outline — the compiler does not support it, so it cannot be locked. Rewrite it as @cases data.`);
|
|
50
|
+
const tampered = new Set(lock?.tampered ?? []);
|
|
51
|
+
const approve = chosen.filter((s) => { const e = lock?.scenarios[s.id]; return !isHumanApproved(e) || e.hash !== s.hash || tampered.has(s.id); });
|
|
52
|
+
const removed = Object.keys(lock?.scenarios ?? {}).filter((id) => !ids.has(id) && (!i.scenario || id === i.scenario));
|
|
53
|
+
const write: ApprovalWrite = { projectRoot: i.projectRoot, unitDir: unit.dir, unit: unit.name, approve, removed, reason: i.reason, lock };
|
|
54
|
+
return { write, lock, fingerprint: canonicalJson({ lock, approve: approve.map((s) => [s.id, s.hash]), removed }) };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function describe(sc: ContractScenario, lock: ReadLock | null): string {
|
|
58
|
+
const entry = lock?.scenarios[sc.id];
|
|
59
|
+
if (!isHumanApproved(entry) || lock?.tampered.includes(sc.id)) return `+ ${sc.id} new (${sc.steps.length} steps, ${sc.implementation})`;
|
|
60
|
+
const r = classifyScenario(sc.id, entry, sc);
|
|
61
|
+
return `~ ${sc.id} ${r.class}${r.findings.length ? ` — ${r.findings.map((f) => f.detail).join('; ')}` : ''}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function approveContract(i: ApproveInput): Promise<ApproveResult> {
|
|
65
|
+
const before = plan(i);
|
|
66
|
+
const { approve, removed } = before.write;
|
|
67
|
+
const lockPath = lockPathFor(before.write.unitDir);
|
|
68
|
+
if (!approve.length && !removed.length) return { status: 'nothing-to-approve', lockPath, approved: [], removed: [] };
|
|
69
|
+
checkApprovalSecrets(before.write);
|
|
70
|
+
|
|
71
|
+
const unnamed = approve.filter((s) => !s.source.hasId).length;
|
|
72
|
+
await requireTypedConfirmation({
|
|
73
|
+
what: `approve the Test Contract of ${i.unit} (${approve.length} scenario(s)${removed.length ? `, ${removed.length} removed` : ''})`,
|
|
74
|
+
phrase: i.unit,
|
|
75
|
+
command: formatCommand(['sungen', 'contract', 'approve', '--screen', i.unit, ...(i.scenario ? ['--scenario', i.scenario] : []), ...(i.reason ? ['--reason', i.reason] : [])]),
|
|
76
|
+
summary: [
|
|
77
|
+
...approve.map((s) => describe(s, before.lock)),
|
|
78
|
+
...removed.map((id) => `- ${id} removed from the feature — its approved checks leave the contract`),
|
|
79
|
+
...(unnamed ? [`note: ${unnamed} scenario(s) have no ID and are locked by name — renaming one will read as removing it`] : []),
|
|
80
|
+
`recorded by: ${gitUserName(i.projectRoot)}`,
|
|
81
|
+
],
|
|
82
|
+
io: i.io,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const after = plan(i);
|
|
86
|
+
if (after.fingerprint !== before.fingerprint) {
|
|
87
|
+
throw new Error('Refused: the feature or the lock changed while you were confirming — nothing was written. Run the command again and review the new summary.');
|
|
88
|
+
}
|
|
89
|
+
const { decisionId } = recordContractApproval(after.write);
|
|
90
|
+
// A derived `@free @proposed` scenario stops being a proposal once QA locks it (DOS-14.8).
|
|
91
|
+
const approvedIds = new Set(approve.map((s) => s.id));
|
|
92
|
+
for (const f of contractFeatureFiles(after.write.unitDir, after.write.unit)) dropProposedTags(f, approvedIds);
|
|
93
|
+
return { status: 'approved', lockPath, decisionId, approved: approve.map((s) => s.id), removed };
|
|
94
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an assertion checks — the CLOSED vocabulary of the strength ladder (DOS-14.1, DOS-14.4).
|
|
3
|
+
*
|
|
4
|
+
* Read off the normalized sentence the QA wrote (the documented `see` / `is on` / `expect` forms of
|
|
5
|
+
* sungen-gherkin-syntax), not off the compiler's pattern registry: that registry is assembled from
|
|
6
|
+
* whichever drivers a machine has installed, so a hash built on it would differ between two
|
|
7
|
+
* checkouts of the same `.feature`, and the hook would judge differently from the CLI. A sentence
|
|
8
|
+
* outside the vocabulary is `unknown`, and an unknown check that changed is `review`, never `match`.
|
|
9
|
+
*
|
|
10
|
+
* strength 1 visible · exists (something is there)
|
|
11
|
+
* strength 2 page · state · contains · matches · range · key-matching · child · url-/title-contains|matches
|
|
12
|
+
* strength 3 equals · count · table-data · tab-order · schema · url · title
|
|
13
|
+
* `all:` (every item) adds one. A negation (`not see`, `is not <state>`, `is hidden`) is a flag.
|
|
14
|
+
*/
|
|
15
|
+
import type { StateClause } from '../generators/test-generator/patterns/types';
|
|
16
|
+
|
|
17
|
+
export interface AssertShape { matcher: string; negated: boolean }
|
|
18
|
+
|
|
19
|
+
const NEGATION = /\b(?:not|no longer|never|cannot|can't|don't|doesn't|isn't|aren't|shouldn't)\b/;
|
|
20
|
+
const NOT_SEE = /^(?:do not|does not|don't|doesn't|should not|shouldn't|cannot|can't|not|never) see\b/;
|
|
21
|
+
const IS_NOT_STATE = /\bis not (sorted ascending|sorted descending|unchecked|checked|hidden|visible|disabled|enabled|focused|empty|loading|selected)$/;
|
|
22
|
+
const RANGE = /\b(?:at least|at most|more than|less than|greater than|fewer than|between)\b/;
|
|
23
|
+
const PAGE_SUBJECT = /^see (?:the )?(?:current |page )?(url|title)\b(.*)$/;
|
|
24
|
+
/** A state and its complement are one check with a negation: hidden = not visible. */
|
|
25
|
+
const STATE_AS: Partial<Record<StateClause, [string, boolean]>> = {
|
|
26
|
+
visible: ['visible', false], hidden: ['visible', true],
|
|
27
|
+
enabled: ['enabled', false], disabled: ['enabled', true],
|
|
28
|
+
checked: ['checked', false], unchecked: ['checked', true],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function comparison(rest: string): string | null {
|
|
32
|
+
if (/\bcontains?\b/.test(rest)) return '-contains';
|
|
33
|
+
if (/\bmatches\b/.test(rest)) return '-matches';
|
|
34
|
+
return /\b(?:is|equals?|with) \{\}|^ ?\{\}$/.test(rest) ? '' : null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function baseMatcher(verb: string, state?: StateClause): string {
|
|
38
|
+
if (/^expect\b/.test(verb)) {
|
|
39
|
+
if (/\bmatches schema\b/.test(verb)) return 'schema';
|
|
40
|
+
if (RANGE.test(verb)) return 'range';
|
|
41
|
+
if (/\bcontains?\b/.test(verb)) return 'contains';
|
|
42
|
+
if (/\bmatches\b/.test(verb)) return 'matches';
|
|
43
|
+
return /\b(?:is|equals?)\b/.test(verb) ? 'equals' : 'unknown';
|
|
44
|
+
}
|
|
45
|
+
if (/\bin (?:local|session) storage\b/.test(verb)) {
|
|
46
|
+
if (/\bkey matching\b/.test(verb)) return 'key-matching';
|
|
47
|
+
if (/\bhas length\b/.test(verb)) return 'count';
|
|
48
|
+
if (/\bis not empty\b/.test(verb)) return 'state:empty';
|
|
49
|
+
return /\b(?:exists?|exist)\b/.test(verb) ? 'exists' : 'unknown';
|
|
50
|
+
}
|
|
51
|
+
if (/^see tab order\b/.test(verb)) return 'tab-order';
|
|
52
|
+
if (/\bmatch data$/.test(verb)) return 'table-data';
|
|
53
|
+
if (!/^(?:see|is on)\b/.test(verb)) return 'unknown';
|
|
54
|
+
const page = verb.match(PAGE_SUBJECT);
|
|
55
|
+
if (page) { const c = comparison(page[2]); return c === null ? 'unknown' : `${page[1]}${c}`; }
|
|
56
|
+
if (state) return STATE_AS[state]?.[0] ?? `state:${state}`;
|
|
57
|
+
if (/^see all \[\] contains? \[\]/.test(verb)) return 'child';
|
|
58
|
+
if (RANGE.test(verb)) return 'range';
|
|
59
|
+
if (/\bmatches \{\}/.test(verb)) return 'matches';
|
|
60
|
+
if (/\b(?:contains?|includes?) \{\}/.test(verb)) return 'contains';
|
|
61
|
+
if (/\b(?:has|have|with) (?:text|value) \{\}|\bwith \{\}/.test(verb)) return 'equals';
|
|
62
|
+
if (/\b(?:has|have) (?:\d+|\{\})(?: [\w-]+)?$/.test(verb)) return 'count';
|
|
63
|
+
if (/^is on \[\] (?:page|screen|dialog)$|^see \[\] page$/.test(verb)) return 'page';
|
|
64
|
+
if (/^see (?:all )?\[\](?: [\w-]+)?$/.test(verb)) return 'visible';
|
|
65
|
+
return 'unknown';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** What an assertion sentence (the normalized `verb`) checks. `state` is the parser's trailing clause. */
|
|
69
|
+
export function assertShapeOf(verb: string, parsedState?: StateClause): AssertShape {
|
|
70
|
+
const v = verb.replace(NOT_SEE, 'see');
|
|
71
|
+
const state = parsedState ?? (v.match(IS_NOT_STATE)?.[1] as StateClause | undefined);
|
|
72
|
+
const base = baseMatcher(v, state);
|
|
73
|
+
const flips = state ? STATE_AS[state]?.[1] === true : false;
|
|
74
|
+
const negated = NEGATION.test(verb) !== flips;
|
|
75
|
+
const all = /^see all\b/.test(v) && base !== 'unknown';
|
|
76
|
+
return { matcher: all ? `all:${base}` : base, negated };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const STRENGTH: Record<string, number> = {
|
|
80
|
+
visible: 1, exists: 1,
|
|
81
|
+
page: 2, enabled: 2, checked: 2, contains: 2, matches: 2, range: 2, 'key-matching': 2, child: 2,
|
|
82
|
+
'url-contains': 2, 'url-matches': 2, 'title-contains': 2, 'title-matches': 2,
|
|
83
|
+
equals: 3, count: 3, 'table-data': 3, 'tab-order': 3, schema: 3, url: 3, title: 3,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/** The ordinal strength of a matcher, or null when the ladder cannot judge it. */
|
|
87
|
+
export function matcherStrength(matcher: string | undefined): number | null {
|
|
88
|
+
if (!matcher || matcher === 'unknown') return null;
|
|
89
|
+
const all = matcher.startsWith('all:');
|
|
90
|
+
const base = all ? matcher.slice(4) : matcher;
|
|
91
|
+
const s = base.startsWith('state:') ? 2 : STRENGTH[base];
|
|
92
|
+
return s === undefined ? null : s + (all ? 1 : 0);
|
|
93
|
+
}
|