@matteeh/osq 0.2.1 → 0.2.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/README.md +234 -15
- package/dist/cli/approve.d.ts +7 -0
- package/dist/cli/approve.d.ts.map +1 -1
- package/dist/cli/approve.js +34 -0
- package/dist/cli/approve.js.map +1 -1
- package/dist/cli/bin.js +2 -3
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/check.d.ts +15 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +65 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +10 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +6 -1
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/lint.d.ts +3 -0
- package/dist/cli/lint.d.ts.map +1 -1
- package/dist/cli/lint.js +33 -14
- package/dist/cli/lint.js.map +1 -1
- package/dist/cli/plan-queue.d.ts +10 -4
- package/dist/cli/plan-queue.d.ts.map +1 -1
- package/dist/cli/plan-queue.js +20 -19
- package/dist/cli/plan-queue.js.map +1 -1
- package/dist/cli/plan-sections.d.ts +15 -0
- package/dist/cli/plan-sections.d.ts.map +1 -0
- package/dist/cli/plan-sections.js +47 -0
- package/dist/cli/plan-sections.js.map +1 -0
- package/dist/cli/plan.d.ts +1 -0
- package/dist/cli/plan.d.ts.map +1 -1
- package/dist/cli/plan.js +14 -4
- package/dist/cli/plan.js.map +1 -1
- package/dist/cli/report.d.ts.map +1 -1
- package/dist/cli/report.js +73 -1
- package/dist/cli/report.js.map +1 -1
- package/dist/cli/run.d.ts +7 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +22 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/verified.d.ts +15 -0
- package/dist/cli/verified.d.ts.map +1 -0
- package/dist/cli/verified.js +34 -0
- package/dist/cli/verified.js.map +1 -0
- package/dist/core/foundation/config-agents.d.ts +16 -0
- package/dist/core/foundation/config-agents.d.ts.map +1 -0
- package/dist/core/foundation/config-agents.js +2 -0
- package/dist/core/foundation/config-agents.js.map +1 -0
- package/dist/core/foundation/config-claude.d.ts +48 -0
- package/dist/core/foundation/config-claude.d.ts.map +1 -0
- package/dist/core/foundation/config-claude.js +106 -0
- package/dist/core/foundation/config-claude.js.map +1 -0
- package/dist/core/foundation/config-codex-resolve.d.ts +10 -0
- package/dist/core/foundation/config-codex-resolve.d.ts.map +1 -0
- package/dist/core/foundation/config-codex-resolve.js +24 -0
- package/dist/core/foundation/config-codex-resolve.js.map +1 -0
- package/dist/core/foundation/config-file.d.ts +18 -0
- package/dist/core/foundation/config-file.d.ts.map +1 -0
- package/dist/core/foundation/config-file.js +46 -0
- package/dist/core/foundation/config-file.js.map +1 -0
- package/dist/core/foundation/config-gates.d.ts +2 -0
- package/dist/core/foundation/config-gates.d.ts.map +1 -1
- package/dist/core/foundation/config-gates.js +8 -0
- package/dist/core/foundation/config-gates.js.map +1 -1
- package/dist/core/foundation/config-opencode.d.ts +25 -0
- package/dist/core/foundation/config-opencode.d.ts.map +1 -0
- package/dist/core/foundation/config-opencode.js +55 -0
- package/dist/core/foundation/config-opencode.js.map +1 -0
- package/dist/core/foundation/config-pi.d.ts +10 -0
- package/dist/core/foundation/config-pi.d.ts.map +1 -1
- package/dist/core/foundation/config-pi.js +13 -0
- package/dist/core/foundation/config-pi.js.map +1 -1
- package/dist/core/foundation/config-planning.d.ts +12 -1
- package/dist/core/foundation/config-planning.d.ts.map +1 -1
- package/dist/core/foundation/config-planning.js +29 -1
- package/dist/core/foundation/config-planning.js.map +1 -1
- package/dist/core/foundation/config-traceability.d.ts +28 -0
- package/dist/core/foundation/config-traceability.d.ts.map +1 -0
- package/dist/core/foundation/config-traceability.js +63 -0
- package/dist/core/foundation/config-traceability.js.map +1 -0
- package/dist/core/foundation/config-user.d.ts +32 -0
- package/dist/core/foundation/config-user.d.ts.map +1 -0
- package/dist/core/foundation/config-user.js +2 -0
- package/dist/core/foundation/config-user.js.map +1 -0
- package/dist/core/foundation/config-vcs.d.ts +29 -0
- package/dist/core/foundation/config-vcs.d.ts.map +1 -0
- package/dist/core/foundation/config-vcs.js +57 -0
- package/dist/core/foundation/config-vcs.js.map +1 -0
- package/dist/core/foundation/config.d.ts +23 -24
- package/dist/core/foundation/config.d.ts.map +1 -1
- package/dist/core/foundation/config.js +29 -36
- package/dist/core/foundation/config.js.map +1 -1
- package/dist/core/foundation/decisions-validate.d.ts +16 -0
- package/dist/core/foundation/decisions-validate.d.ts.map +1 -0
- package/dist/core/foundation/decisions-validate.js +74 -0
- package/dist/core/foundation/decisions-validate.js.map +1 -0
- package/dist/core/foundation/decisions.d.ts +34 -0
- package/dist/core/foundation/decisions.d.ts.map +1 -0
- package/dist/core/foundation/decisions.js +152 -0
- package/dist/core/foundation/decisions.js.map +1 -0
- package/dist/core/foundation/doctor-decisions.d.ts +9 -0
- package/dist/core/foundation/doctor-decisions.d.ts.map +1 -0
- package/dist/core/foundation/doctor-decisions.js +49 -0
- package/dist/core/foundation/doctor-decisions.js.map +1 -0
- package/dist/core/foundation/doctor-managed.d.ts.map +1 -1
- package/dist/core/foundation/doctor-managed.js +3 -0
- package/dist/core/foundation/doctor-managed.js.map +1 -1
- package/dist/core/foundation/doctor-prices.d.ts +8 -0
- package/dist/core/foundation/doctor-prices.d.ts.map +1 -0
- package/dist/core/foundation/doctor-prices.js +25 -0
- package/dist/core/foundation/doctor-prices.js.map +1 -0
- package/dist/core/foundation/doctor.d.ts.map +1 -1
- package/dist/core/foundation/doctor.js +20 -30
- package/dist/core/foundation/doctor.js.map +1 -1
- package/dist/core/foundation/harness-catalog.d.ts +7 -8
- package/dist/core/foundation/harness-catalog.d.ts.map +1 -1
- package/dist/core/foundation/harness-catalog.js +26 -41
- package/dist/core/foundation/harness-catalog.js.map +1 -1
- package/dist/core/foundation/init-blocks.d.ts +1 -1
- package/dist/core/foundation/init-blocks.d.ts.map +1 -1
- package/dist/core/foundation/init-blocks.js +51 -14
- package/dist/core/foundation/init-blocks.js.map +1 -1
- package/dist/core/foundation/init.d.ts +4 -0
- package/dist/core/foundation/init.d.ts.map +1 -1
- package/dist/core/foundation/init.js +7 -0
- package/dist/core/foundation/init.js.map +1 -1
- package/dist/core/foundation/new.d.ts +4 -1
- package/dist/core/foundation/new.d.ts.map +1 -1
- package/dist/core/foundation/new.js +18 -8
- package/dist/core/foundation/new.js.map +1 -1
- package/dist/core/foundation/package-root.d.ts +6 -0
- package/dist/core/foundation/package-root.d.ts.map +1 -1
- package/dist/core/foundation/package-root.js +6 -0
- package/dist/core/foundation/package-root.js.map +1 -1
- package/dist/core/foundation/rules-block.d.ts +11 -0
- package/dist/core/foundation/rules-block.d.ts.map +1 -0
- package/dist/core/foundation/rules-block.js +90 -0
- package/dist/core/foundation/rules-block.js.map +1 -0
- package/dist/core/foundation/traceability-block.d.ts +13 -0
- package/dist/core/foundation/traceability-block.d.ts.map +1 -0
- package/dist/core/foundation/traceability-block.js +124 -0
- package/dist/core/foundation/traceability-block.js.map +1 -0
- package/dist/core/lifecycle/done.d.ts.map +1 -1
- package/dist/core/lifecycle/done.js +2 -4
- package/dist/core/lifecycle/done.js.map +1 -1
- package/dist/core/lifecycle/recertify.d.ts +9 -0
- package/dist/core/lifecycle/recertify.d.ts.map +1 -0
- package/dist/core/lifecycle/recertify.js +27 -0
- package/dist/core/lifecycle/recertify.js.map +1 -0
- package/dist/core/lifecycle/reject.d.ts.map +1 -1
- package/dist/core/lifecycle/reject.js +3 -4
- package/dist/core/lifecycle/reject.js.map +1 -1
- package/dist/core/lifecycle/retry.d.ts.map +1 -1
- package/dist/core/lifecycle/retry.js +6 -20
- package/dist/core/lifecycle/retry.js.map +1 -1
- package/dist/core/lifecycle/verification-record.d.ts +42 -0
- package/dist/core/lifecycle/verification-record.d.ts.map +1 -0
- package/dist/core/lifecycle/verification-record.js +76 -0
- package/dist/core/lifecycle/verification-record.js.map +1 -0
- package/dist/core/report/approval-flags.d.ts +16 -3
- package/dist/core/report/approval-flags.d.ts.map +1 -1
- package/dist/core/report/approval-flags.js +59 -22
- package/dist/core/report/approval-flags.js.map +1 -1
- package/dist/core/report/brief-to-approval.d.ts +7 -0
- package/dist/core/report/brief-to-approval.d.ts.map +1 -0
- package/dist/core/report/brief-to-approval.js +43 -0
- package/dist/core/report/brief-to-approval.js.map +1 -0
- package/dist/core/report/planning-price-gaps.d.ts +10 -0
- package/dist/core/report/planning-price-gaps.d.ts.map +1 -0
- package/dist/core/report/planning-price-gaps.js +37 -0
- package/dist/core/report/planning-price-gaps.js.map +1 -0
- package/dist/core/report/planning-slice-lookup.d.ts.map +1 -1
- package/dist/core/report/planning-slice-lookup.js +3 -9
- package/dist/core/report/planning-slice-lookup.js.map +1 -1
- package/dist/core/report/recent-disclosures.d.ts +18 -0
- package/dist/core/report/recent-disclosures.d.ts.map +1 -0
- package/dist/core/report/recent-disclosures.js +105 -0
- package/dist/core/report/recent-disclosures.js.map +1 -0
- package/dist/core/report/record-disclosures.d.ts +14 -0
- package/dist/core/report/record-disclosures.d.ts.map +1 -0
- package/dist/core/report/record-disclosures.js +30 -0
- package/dist/core/report/record-disclosures.js.map +1 -0
- package/dist/core/report/record-estimates.d.ts +25 -0
- package/dist/core/report/record-estimates.d.ts.map +1 -0
- package/dist/core/report/record-estimates.js +83 -0
- package/dist/core/report/record-estimates.js.map +1 -0
- package/dist/core/report/record-rework.d.ts +19 -0
- package/dist/core/report/record-rework.d.ts.map +1 -0
- package/dist/core/report/record-rework.js +50 -0
- package/dist/core/report/record-rework.js.map +1 -0
- package/dist/core/report/record-verification.d.ts +16 -0
- package/dist/core/report/record-verification.d.ts.map +1 -0
- package/dist/core/report/record-verification.js +33 -0
- package/dist/core/report/record-verification.js.map +1 -0
- package/dist/core/report/report-dependencies.d.ts +29 -0
- package/dist/core/report/report-dependencies.d.ts.map +1 -0
- package/dist/core/report/report-dependencies.js +92 -0
- package/dist/core/report/report-dependencies.js.map +1 -0
- package/dist/core/report/report-events.d.ts +1 -0
- package/dist/core/report/report-events.d.ts.map +1 -1
- package/dist/core/report/report-events.js +8 -26
- package/dist/core/report/report-events.js.map +1 -1
- package/dist/core/report/report-mutation.d.ts +34 -0
- package/dist/core/report/report-mutation.d.ts.map +1 -0
- package/dist/core/report/report-mutation.js +191 -0
- package/dist/core/report/report-mutation.js.map +1 -0
- package/dist/core/report/report-scope.d.ts +21 -0
- package/dist/core/report/report-scope.d.ts.map +1 -0
- package/dist/core/report/report-scope.js +61 -0
- package/dist/core/report/report-scope.js.map +1 -0
- package/dist/core/report/report-traceability.d.ts +29 -0
- package/dist/core/report/report-traceability.d.ts.map +1 -0
- package/dist/core/report/report-traceability.js +94 -0
- package/dist/core/report/report-traceability.js.map +1 -0
- package/dist/core/report/report.d.ts +35 -1
- package/dist/core/report/report.d.ts.map +1 -1
- package/dist/core/report/report.js +130 -111
- package/dist/core/report/report.js.map +1 -1
- package/dist/core/report/result-sections.d.ts +30 -0
- package/dist/core/report/result-sections.d.ts.map +1 -0
- package/dist/core/report/result-sections.js +125 -0
- package/dist/core/report/result-sections.js.map +1 -0
- package/dist/core/report/scope-size.d.ts +7 -0
- package/dist/core/report/scope-size.d.ts.map +1 -0
- package/dist/core/report/scope-size.js +22 -0
- package/dist/core/report/scope-size.js.map +1 -0
- package/dist/core/run/commit-message.d.ts +24 -0
- package/dist/core/run/commit-message.d.ts.map +1 -0
- package/dist/core/run/commit-message.js +76 -0
- package/dist/core/run/commit-message.js.map +1 -0
- package/dist/core/run/dead-commit.d.ts +10 -0
- package/dist/core/run/dead-commit.d.ts.map +1 -0
- package/dist/core/run/dead-commit.js +70 -0
- package/dist/core/run/dead-commit.js.map +1 -0
- package/dist/core/run/focused-tests.d.ts +43 -0
- package/dist/core/run/focused-tests.d.ts.map +1 -0
- package/dist/core/run/focused-tests.js +116 -0
- package/dist/core/run/focused-tests.js.map +1 -0
- package/dist/core/run/manifest-approval.d.ts +7 -0
- package/dist/core/run/manifest-approval.d.ts.map +1 -0
- package/dist/core/run/manifest-approval.js +30 -0
- package/dist/core/run/manifest-approval.js.map +1 -0
- package/dist/core/run/manifest.d.ts +11 -1
- package/dist/core/run/manifest.d.ts.map +1 -1
- package/dist/core/run/manifest.js +52 -11
- package/dist/core/run/manifest.js.map +1 -1
- package/dist/core/run/mutation-report.d.ts +29 -0
- package/dist/core/run/mutation-report.d.ts.map +1 -0
- package/dist/core/run/mutation-report.js +107 -0
- package/dist/core/run/mutation-report.js.map +1 -0
- package/dist/core/run/mutation-run.d.ts +32 -0
- package/dist/core/run/mutation-run.d.ts.map +1 -0
- package/dist/core/run/mutation-run.js +80 -0
- package/dist/core/run/mutation-run.js.map +1 -0
- package/dist/core/run/verification.d.ts +12 -1
- package/dist/core/run/verification.d.ts.map +1 -1
- package/dist/core/run/verification.js +24 -2
- package/dist/core/run/verification.js.map +1 -1
- package/dist/core/spec/approve-worktree-shared.d.ts +33 -0
- package/dist/core/spec/approve-worktree-shared.d.ts.map +1 -0
- package/dist/core/spec/approve-worktree-shared.js +59 -0
- package/dist/core/spec/approve-worktree-shared.js.map +1 -0
- package/dist/core/spec/approve-worktree.d.ts +21 -0
- package/dist/core/spec/approve-worktree.d.ts.map +1 -0
- package/dist/core/spec/approve-worktree.js +153 -0
- package/dist/core/spec/approve-worktree.js.map +1 -0
- package/dist/core/spec/approve.d.ts +20 -10
- package/dist/core/spec/approve.d.ts.map +1 -1
- package/dist/core/spec/approve.js +57 -54
- package/dist/core/spec/approve.js.map +1 -1
- package/dist/core/spec/capability-impact.d.ts +43 -0
- package/dist/core/spec/capability-impact.d.ts.map +1 -0
- package/dist/core/spec/capability-impact.js +85 -0
- package/dist/core/spec/capability-impact.js.map +1 -0
- package/dist/core/spec/decisions-lint.d.ts +18 -0
- package/dist/core/spec/decisions-lint.d.ts.map +1 -0
- package/dist/core/spec/decisions-lint.js +127 -0
- package/dist/core/spec/decisions-lint.js.map +1 -0
- package/dist/core/spec/delta.d.ts +6 -0
- package/dist/core/spec/delta.d.ts.map +1 -1
- package/dist/core/spec/delta.js +73 -5
- package/dist/core/spec/delta.js.map +1 -1
- package/dist/core/spec/digest-decisions.d.ts +27 -0
- package/dist/core/spec/digest-decisions.d.ts.map +1 -0
- package/dist/core/spec/digest-decisions.js +86 -0
- package/dist/core/spec/digest-decisions.js.map +1 -0
- package/dist/core/spec/digest-format.d.ts +4 -0
- package/dist/core/spec/digest-format.d.ts.map +1 -0
- package/dist/core/spec/digest-format.js +44 -0
- package/dist/core/spec/digest-format.js.map +1 -0
- package/dist/core/spec/digest.d.ts +5 -3
- package/dist/core/spec/digest.d.ts.map +1 -1
- package/dist/core/spec/digest.js +14 -33
- package/dist/core/spec/digest.js.map +1 -1
- package/dist/core/spec/human-steps.d.ts +20 -0
- package/dist/core/spec/human-steps.d.ts.map +1 -0
- package/dist/core/spec/human-steps.js +52 -0
- package/dist/core/spec/human-steps.js.map +1 -0
- package/dist/core/spec/impact-lint.d.ts +24 -0
- package/dist/core/spec/impact-lint.d.ts.map +1 -0
- package/dist/core/spec/impact-lint.js +39 -0
- package/dist/core/spec/impact-lint.js.map +1 -0
- package/dist/core/spec/import-graph.d.ts +35 -0
- package/dist/core/spec/import-graph.d.ts.map +1 -0
- package/dist/core/spec/import-graph.js +155 -0
- package/dist/core/spec/import-graph.js.map +1 -0
- package/dist/core/spec/lint-findings.d.ts +44 -0
- package/dist/core/spec/lint-findings.d.ts.map +1 -0
- package/dist/core/spec/lint-findings.js +56 -0
- package/dist/core/spec/lint-findings.js.map +1 -0
- package/dist/core/spec/lint-output.d.ts +53 -0
- package/dist/core/spec/lint-output.d.ts.map +1 -0
- package/dist/core/spec/lint-output.js +87 -0
- package/dist/core/spec/lint-output.js.map +1 -0
- package/dist/core/spec/linter.d.ts +14 -4
- package/dist/core/spec/linter.d.ts.map +1 -1
- package/dist/core/spec/linter.js +271 -111
- package/dist/core/spec/linter.js.map +1 -1
- package/dist/core/spec/merged-spec-check.d.ts +24 -0
- package/dist/core/spec/merged-spec-check.d.ts.map +1 -0
- package/dist/core/spec/merged-spec-check.js +95 -0
- package/dist/core/spec/merged-spec-check.js.map +1 -0
- package/dist/core/spec/openspec-issues.d.ts +58 -0
- package/dist/core/spec/openspec-issues.d.ts.map +1 -0
- package/dist/core/spec/openspec-issues.js +166 -0
- package/dist/core/spec/openspec-issues.js.map +1 -0
- package/dist/core/spec/parser.d.ts +1 -0
- package/dist/core/spec/parser.d.ts.map +1 -1
- package/dist/core/spec/parser.js +16 -6
- package/dist/core/spec/parser.js.map +1 -1
- package/dist/core/spec/scenario-impact.d.ts +47 -0
- package/dist/core/spec/scenario-impact.d.ts.map +1 -0
- package/dist/core/spec/scenario-impact.js +130 -0
- package/dist/core/spec/scenario-impact.js.map +1 -0
- package/dist/core/spec/test-impact.d.ts +28 -0
- package/dist/core/spec/test-impact.d.ts.map +1 -0
- package/dist/core/spec/test-impact.js +119 -0
- package/dist/core/spec/test-impact.js.map +1 -0
- package/dist/core/spec/traceability-links.d.ts +50 -0
- package/dist/core/spec/traceability-links.d.ts.map +1 -0
- package/dist/core/spec/traceability-links.js +120 -0
- package/dist/core/spec/traceability-links.js.map +1 -0
- package/dist/core/spec/traceability-lint.d.ts +29 -0
- package/dist/core/spec/traceability-lint.d.ts.map +1 -0
- package/dist/core/spec/traceability-lint.js +143 -0
- package/dist/core/spec/traceability-lint.js.map +1 -0
- package/dist/core/status/blocked-item.d.ts +8 -0
- package/dist/core/status/blocked-item.d.ts.map +1 -0
- package/dist/core/status/blocked-item.js +45 -0
- package/dist/core/status/blocked-item.js.map +1 -0
- package/dist/core/status/change-locations.d.ts +44 -0
- package/dist/core/status/change-locations.d.ts.map +1 -0
- package/dist/core/status/change-locations.js +138 -0
- package/dist/core/status/change-locations.js.map +1 -0
- package/dist/core/status/dependency-readiness.d.ts +11 -0
- package/dist/core/status/dependency-readiness.d.ts.map +1 -0
- package/dist/core/status/dependency-readiness.js +39 -0
- package/dist/core/status/dependency-readiness.js.map +1 -0
- package/dist/core/status/inbox-projection.d.ts.map +1 -1
- package/dist/core/status/inbox-projection.js +23 -4
- package/dist/core/status/inbox-projection.js.map +1 -1
- package/dist/core/status/inbox-text.d.ts.map +1 -1
- package/dist/core/status/inbox-text.js +34 -3
- package/dist/core/status/inbox-text.js.map +1 -1
- package/dist/core/status/inbox.d.ts +10 -1
- package/dist/core/status/inbox.d.ts.map +1 -1
- package/dist/core/status/inbox.js +19 -1
- package/dist/core/status/inbox.js.map +1 -1
- package/dist/core/status/layout.d.ts +6 -0
- package/dist/core/status/layout.d.ts.map +1 -1
- package/dist/core/status/layout.js +8 -0
- package/dist/core/status/layout.js.map +1 -1
- package/dist/core/status/next-step.d.ts +17 -0
- package/dist/core/status/next-step.d.ts.map +1 -0
- package/dist/core/status/next-step.js +85 -0
- package/dist/core/status/next-step.js.map +1 -0
- package/dist/core/status/pre-spawn-words.d.ts +13 -0
- package/dist/core/status/pre-spawn-words.d.ts.map +1 -0
- package/dist/core/status/pre-spawn-words.js +26 -0
- package/dist/core/status/pre-spawn-words.js.map +1 -0
- package/dist/core/status/queue-parser.d.ts +1 -0
- package/dist/core/status/queue-parser.d.ts.map +1 -1
- package/dist/core/status/queue-parser.js +41 -2
- package/dist/core/status/queue-parser.js.map +1 -1
- package/dist/core/status/queue-planning.d.ts +1 -0
- package/dist/core/status/queue-planning.d.ts.map +1 -1
- package/dist/core/status/queue-planning.js +24 -12
- package/dist/core/status/queue-planning.js.map +1 -1
- package/dist/core/status/queue-report-detail.d.ts.map +1 -1
- package/dist/core/status/queue-report-detail.js +5 -3
- package/dist/core/status/queue-report-detail.js.map +1 -1
- package/dist/core/status/queue-state.d.ts +1 -1
- package/dist/core/status/queue-state.d.ts.map +1 -1
- package/dist/core/status/queue-state.js +27 -41
- package/dist/core/status/queue-state.js.map +1 -1
- package/dist/core/status/show.d.ts +25 -0
- package/dist/core/status/show.d.ts.map +1 -1
- package/dist/core/status/show.js +354 -91
- package/dist/core/status/show.js.map +1 -1
- package/dist/core/status/state.d.ts.map +1 -1
- package/dist/core/status/state.js +1 -23
- package/dist/core/status/state.js.map +1 -1
- package/dist/core/status/status.d.ts +18 -0
- package/dist/core/status/status.d.ts.map +1 -1
- package/dist/core/status/status.js +59 -80
- package/dist/core/status/status.js.map +1 -1
- package/dist/core/status/verification.d.ts +27 -0
- package/dist/core/status/verification.d.ts.map +1 -0
- package/dist/core/status/verification.js +111 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/trace/function-ranges.d.ts +30 -0
- package/dist/core/trace/function-ranges.d.ts.map +1 -0
- package/dist/core/trace/function-ranges.js +250 -0
- package/dist/core/trace/function-ranges.js.map +1 -0
- package/dist/core/trace/mutation-pick.d.ts +55 -0
- package/dist/core/trace/mutation-pick.d.ts.map +1 -0
- package/dist/core/trace/mutation-pick.js +96 -0
- package/dist/core/trace/mutation-pick.js.map +1 -0
- package/dist/core/trace/scenario-index.d.ts +27 -0
- package/dist/core/trace/scenario-index.d.ts.map +1 -0
- package/dist/core/trace/scenario-index.js +76 -0
- package/dist/core/trace/scenario-index.js.map +1 -0
- package/dist/core/trace/scenario-lookup.d.ts +14 -0
- package/dist/core/trace/scenario-lookup.d.ts.map +1 -0
- package/dist/core/trace/scenario-lookup.js +179 -0
- package/dist/core/trace/scenario-lookup.js.map +1 -0
- package/dist/core/trace/tag-scan.d.ts +44 -0
- package/dist/core/trace/tag-scan.d.ts.map +1 -0
- package/dist/core/trace/tag-scan.js +200 -0
- package/dist/core/trace/tag-scan.js.map +1 -0
- package/dist/core/vcs/doctor-git.d.ts +13 -0
- package/dist/core/vcs/doctor-git.d.ts.map +1 -0
- package/dist/core/vcs/doctor-git.js +114 -0
- package/dist/core/vcs/doctor-git.js.map +1 -0
- package/dist/core/vcs/git-vcs-write.d.ts +47 -0
- package/dist/core/vcs/git-vcs-write.d.ts.map +1 -0
- package/dist/core/vcs/git-vcs-write.js +210 -0
- package/dist/core/vcs/git-vcs-write.js.map +1 -0
- package/dist/core/vcs/git-vcs.d.ts +40 -0
- package/dist/core/vcs/git-vcs.d.ts.map +1 -0
- package/dist/core/vcs/git-vcs.js +170 -0
- package/dist/core/vcs/git-vcs.js.map +1 -0
- package/dist/core/vcs/no-vcs.d.ts +26 -0
- package/dist/core/vcs/no-vcs.d.ts.map +1 -0
- package/dist/core/vcs/no-vcs.js +62 -0
- package/dist/core/vcs/no-vcs.js.map +1 -0
- package/dist/core/vcs/select.d.ts +11 -0
- package/dist/core/vcs/select.d.ts.map +1 -0
- package/dist/core/vcs/select.js +33 -0
- package/dist/core/vcs/select.js.map +1 -0
- package/dist/core/vcs/snapshot.d.ts +34 -0
- package/dist/core/vcs/snapshot.d.ts.map +1 -0
- package/dist/core/vcs/snapshot.js +71 -0
- package/dist/core/vcs/snapshot.js.map +1 -0
- package/dist/core/vcs/vcs.d.ts +55 -0
- package/dist/core/vcs/vcs.d.ts.map +1 -0
- package/dist/core/vcs/vcs.js +2 -0
- package/dist/core/vcs/vcs.js.map +1 -0
- package/dist/core/vcs/worktree.d.ts +10 -0
- package/dist/core/vcs/worktree.d.ts.map +1 -0
- package/dist/core/vcs/worktree.js +25 -0
- package/dist/core/vcs/worktree.js.map +1 -0
- package/dist/core/web/web-data-folders.d.ts.map +1 -1
- package/dist/core/web/web-data-folders.js +18 -33
- package/dist/core/web/web-data-folders.js.map +1 -1
- package/dist/core/web/web-data-lifecycle.d.ts.map +1 -1
- package/dist/core/web/web-data-lifecycle.js +2 -1
- package/dist/core/web/web-data-lifecycle.js.map +1 -1
- package/dist/core/web/web-events.d.ts +8 -6
- package/dist/core/web/web-events.d.ts.map +1 -1
- package/dist/core/web/web-events.js +7 -31
- package/dist/core/web/web-events.js.map +1 -1
- package/dist/core/web/web-server.d.ts.map +1 -1
- package/dist/core/web/web-server.js +3 -0
- package/dist/core/web/web-server.js.map +1 -1
- package/dist/core/web/web-trees.d.ts +27 -0
- package/dist/core/web/web-trees.d.ts.map +1 -0
- package/dist/core/web/web-trees.js +82 -0
- package/dist/core/web/web-trees.js.map +1 -0
- package/dist/harness/claude/claude-exec-args.d.ts +13 -0
- package/dist/harness/claude/claude-exec-args.d.ts.map +1 -0
- package/dist/harness/claude/claude-exec-args.js +61 -0
- package/dist/harness/claude/claude-exec-args.js.map +1 -0
- package/dist/harness/claude/claude-exec.d.ts +12 -0
- package/dist/harness/claude/claude-exec.d.ts.map +1 -0
- package/dist/harness/claude/claude-exec.js +79 -0
- package/dist/harness/claude/claude-exec.js.map +1 -0
- package/dist/harness/claude/claude-stream.d.ts +31 -0
- package/dist/harness/claude/claude-stream.d.ts.map +1 -0
- package/dist/harness/claude/claude-stream.js +150 -0
- package/dist/harness/claude/claude-stream.js.map +1 -0
- package/dist/harness/claude/claude-tools.d.ts +5 -0
- package/dist/harness/claude/claude-tools.d.ts.map +1 -0
- package/dist/harness/claude/claude-tools.js +30 -0
- package/dist/harness/claude/claude-tools.js.map +1 -0
- package/dist/harness/index.d.ts +1 -0
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +3 -0
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/opencode/opencode-session.d.ts +42 -0
- package/dist/harness/opencode/opencode-session.d.ts.map +1 -0
- package/dist/harness/opencode/opencode-session.js +123 -0
- package/dist/harness/opencode/opencode-session.js.map +1 -0
- package/dist/harness/opencode/opencode.d.ts +2 -1
- package/dist/harness/opencode/opencode.d.ts.map +1 -1
- package/dist/harness/opencode/opencode.js +52 -28
- package/dist/harness/opencode/opencode.js.map +1 -1
- package/dist/harness/prompt.js +1 -1
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/types.d.ts +112 -1
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +2 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/scenario.d.ts +29 -0
- package/dist/testing/scenario.d.ts.map +1 -0
- package/dist/testing/scenario.js +157 -0
- package/dist/testing/scenario.js.map +1 -0
- package/dist/watcher/archiver.d.ts +2 -1
- package/dist/watcher/archiver.d.ts.map +1 -1
- package/dist/watcher/archiver.js +27 -2
- package/dist/watcher/archiver.js.map +1 -1
- package/dist/watcher/auto-recertify.d.ts +27 -0
- package/dist/watcher/auto-recertify.d.ts.map +1 -0
- package/dist/watcher/auto-recertify.js +113 -0
- package/dist/watcher/auto-recertify.js.map +1 -0
- package/dist/watcher/auto-retry.d.ts +1 -1
- package/dist/watcher/auto-retry.d.ts.map +1 -1
- package/dist/watcher/auto-retry.js +3 -11
- package/dist/watcher/auto-retry.js.map +1 -1
- package/dist/watcher/baseline-key.d.ts +17 -0
- package/dist/watcher/baseline-key.d.ts.map +1 -0
- package/dist/watcher/baseline-key.js +31 -0
- package/dist/watcher/baseline-key.js.map +1 -0
- package/dist/watcher/baseline.d.ts +32 -0
- package/dist/watcher/baseline.d.ts.map +1 -0
- package/dist/watcher/baseline.js +166 -0
- package/dist/watcher/baseline.js.map +1 -0
- package/dist/watcher/blocked.d.ts +12 -0
- package/dist/watcher/blocked.d.ts.map +1 -0
- package/dist/watcher/blocked.js +24 -0
- package/dist/watcher/blocked.js.map +1 -0
- package/dist/watcher/dependencies.d.ts +28 -0
- package/dist/watcher/dependencies.d.ts.map +1 -0
- package/dist/watcher/dependencies.js +152 -0
- package/dist/watcher/dependencies.js.map +1 -0
- package/dist/watcher/done-metadata.d.ts +4 -0
- package/dist/watcher/done-metadata.d.ts.map +1 -0
- package/dist/watcher/done-metadata.js +20 -0
- package/dist/watcher/done-metadata.js.map +1 -0
- package/dist/watcher/failure-reason.d.ts +1 -1
- package/dist/watcher/failure-reason.d.ts.map +1 -1
- package/dist/watcher/focused-verify.d.ts +17 -0
- package/dist/watcher/focused-verify.d.ts.map +1 -0
- package/dist/watcher/focused-verify.js +54 -0
- package/dist/watcher/focused-verify.js.map +1 -0
- package/dist/watcher/git-guard.d.ts +24 -0
- package/dist/watcher/git-guard.d.ts.map +1 -0
- package/dist/watcher/git-guard.js +95 -0
- package/dist/watcher/git-guard.js.map +1 -0
- package/dist/watcher/instructions-drift.d.ts +21 -0
- package/dist/watcher/instructions-drift.d.ts.map +1 -0
- package/dist/watcher/instructions-drift.js +115 -0
- package/dist/watcher/instructions-drift.js.map +1 -0
- package/dist/watcher/loop.d.ts.map +1 -1
- package/dist/watcher/loop.js +36 -50
- package/dist/watcher/loop.js.map +1 -1
- package/dist/watcher/measures.d.ts.map +1 -1
- package/dist/watcher/measures.js +22 -39
- package/dist/watcher/measures.js.map +1 -1
- package/dist/watcher/mutation-check.d.ts +42 -0
- package/dist/watcher/mutation-check.d.ts.map +1 -0
- package/dist/watcher/mutation-check.js +147 -0
- package/dist/watcher/mutation-check.js.map +1 -0
- package/dist/watcher/regression.d.ts +10 -5
- package/dist/watcher/regression.d.ts.map +1 -1
- package/dist/watcher/regression.js +29 -22
- package/dist/watcher/regression.js.map +1 -1
- package/dist/watcher/runner.d.ts.map +1 -1
- package/dist/watcher/runner.js +12 -14
- package/dist/watcher/runner.js.map +1 -1
- package/dist/watcher/spawn.d.ts.map +1 -1
- package/dist/watcher/spawn.js +5 -0
- package/dist/watcher/spawn.js.map +1 -1
- package/dist/watcher/task-verify.d.ts +7 -2
- package/dist/watcher/task-verify.d.ts.map +1 -1
- package/dist/watcher/task-verify.js +33 -8
- package/dist/watcher/task-verify.js.map +1 -1
- package/dist/watcher/verify.d.ts +1 -5
- package/dist/watcher/verify.d.ts.map +1 -1
- package/dist/watcher/verify.js +2 -6
- package/dist/watcher/verify.js.map +1 -1
- package/package.json +5 -1
- package/templates/PLANNER.md +35 -9
- package/templates/openspec/config.yaml +1 -1
- package/templates/openspec/schemas/osq/schema.yaml +4 -2
- package/templates/openspec/schemas/osq/templates/proposal.md +9 -2
- package/templates/proposal.md +9 -2
- package/ui/dist/assets/{index-CZYeQ8la.js → index-D39uYbbL.js} +1 -1
- package/ui/dist/index.html +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { TraceabilityMode } from '../foundation/config-traceability.js';
|
|
2
|
+
import type { ScenarioIndex } from '../trace/scenario-index.js';
|
|
3
|
+
import { type LintFinding } from './lint-findings.js';
|
|
4
|
+
/**
|
|
5
|
+
* The blast radius of a scenario the change alters: a MODIFIED scenario whose
|
|
6
|
+
* block differs from the living spec's, or a scenario in a REMOVED requirement.
|
|
7
|
+
* Each test naming it is listed, and each test no task scopes for modification
|
|
8
|
+
* is reported. This module also reads what each delta changes.
|
|
9
|
+
*/
|
|
10
|
+
/** One delta capability's added, differing modified, and removed scenarios. */
|
|
11
|
+
export interface CapabilityChange {
|
|
12
|
+
readonly capability: string;
|
|
13
|
+
readonly deltaPath: string;
|
|
14
|
+
readonly addedNames: readonly string[];
|
|
15
|
+
readonly modifiedNames: readonly string[];
|
|
16
|
+
readonly removedNames: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
/** One scenario the change alters, with the delta that alters it. */
|
|
19
|
+
export interface BlastScenario {
|
|
20
|
+
readonly capability: string;
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly deltaPath: string;
|
|
23
|
+
}
|
|
24
|
+
/** One task's modification authority for the blast-radius check. */
|
|
25
|
+
export interface ScenarioImpactTask {
|
|
26
|
+
readonly resolvedPaths: readonly string[];
|
|
27
|
+
readonly testsModify: boolean;
|
|
28
|
+
}
|
|
29
|
+
/** Everything the blast-radius rules read, already collected by the entry module. */
|
|
30
|
+
export interface ScenarioImpactInput {
|
|
31
|
+
readonly mode: TraceabilityMode;
|
|
32
|
+
readonly index: ScenarioIndex;
|
|
33
|
+
readonly optedIn: ReadonlySet<string>;
|
|
34
|
+
readonly tasks: readonly ScenarioImpactTask[];
|
|
35
|
+
readonly scenarios: readonly BlastScenario[];
|
|
36
|
+
}
|
|
37
|
+
/** Capability directories under a `specs` root that hold a `spec.md`. */
|
|
38
|
+
export declare function specDirectories(specsDir: string): Promise<string[]>;
|
|
39
|
+
/** Capability names with a delta spec file in the change folder. */
|
|
40
|
+
export declare function readDeltaCapabilities(folderPath: string): Promise<string[]>;
|
|
41
|
+
/** Read each delta capability's added, differing modified, and removed scenarios. */
|
|
42
|
+
export declare function readCapabilityChanges(projectRoot: string, folderPath: string, openspecRoot: string, deltas: readonly string[]): Promise<Map<string, CapabilityChange>>;
|
|
43
|
+
/** Every scenario the change alters, in capability and delta order. */
|
|
44
|
+
export declare function blastScenarios(changes: ReadonlyMap<string, CapabilityChange>): BlastScenario[];
|
|
45
|
+
/** The scenario listing and modification warnings for the altered scenarios. */
|
|
46
|
+
export declare function scenarioImpactFindings(input: ScenarioImpactInput): LintFinding[];
|
|
47
|
+
//# sourceMappingURL=scenario-impact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario-impact.d.ts","sourceRoot":"","sources":["../../../src/core/spec/scenario-impact.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,oBAAoB,CAAC;AAEnE;;;;;GAKG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,oEAAoE;AACpE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,qFAAqF;AACrF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC9C,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;CAC9C;AAcD,yEAAyE;AACzE,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAazE;AAED,oEAAoE;AACpE,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAE3E;AAiBD,qFAAqF;AACrF,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CA4CxC;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,aAAa,EAAE,CAQ9F;AAOD,gFAAgF;AAChF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,WAAW,EAAE,CA+BhF"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parseCapabilitySpec, parseDelta } from './delta.js';
|
|
4
|
+
import { makeFinding } from './lint-findings.js';
|
|
5
|
+
/** Repository-relative POSIX path. */
|
|
6
|
+
function repositoryPath(projectRoot, absolutePath) {
|
|
7
|
+
return path.relative(projectRoot, absolutePath).split(path.sep).join('/');
|
|
8
|
+
}
|
|
9
|
+
function statExists(target) {
|
|
10
|
+
return fs
|
|
11
|
+
.stat(target)
|
|
12
|
+
.then(() => true)
|
|
13
|
+
.catch(() => false);
|
|
14
|
+
}
|
|
15
|
+
/** Capability directories under a `specs` root that hold a `spec.md`. */
|
|
16
|
+
export async function specDirectories(specsDir) {
|
|
17
|
+
let entries;
|
|
18
|
+
try {
|
|
19
|
+
entries = await fs.readdir(specsDir, { withFileTypes: true });
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const names = [];
|
|
25
|
+
for (const entry of entries) {
|
|
26
|
+
if (!entry.isDirectory())
|
|
27
|
+
continue;
|
|
28
|
+
if (await statExists(path.join(specsDir, entry.name, 'spec.md')))
|
|
29
|
+
names.push(entry.name);
|
|
30
|
+
}
|
|
31
|
+
return names.sort();
|
|
32
|
+
}
|
|
33
|
+
/** Capability names with a delta spec file in the change folder. */
|
|
34
|
+
export function readDeltaCapabilities(folderPath) {
|
|
35
|
+
return specDirectories(path.join(folderPath, 'specs'));
|
|
36
|
+
}
|
|
37
|
+
/** Requirement name to scenario name to its verbatim block. */
|
|
38
|
+
function requirementScenarios(content) {
|
|
39
|
+
const requirements = new Map();
|
|
40
|
+
for (const requirement of parseCapabilitySpec(content).requirements) {
|
|
41
|
+
const scenarios = new Map();
|
|
42
|
+
for (const scenario of requirement.scenarios)
|
|
43
|
+
scenarios.set(scenario.name, scenario.raw);
|
|
44
|
+
requirements.set(requirement.name, scenarios);
|
|
45
|
+
}
|
|
46
|
+
return requirements;
|
|
47
|
+
}
|
|
48
|
+
function sameScenarioBlock(left, right) {
|
|
49
|
+
return left.replace(/\r\n?/g, '\n').trim() === right.replace(/\r\n?/g, '\n').trim();
|
|
50
|
+
}
|
|
51
|
+
/** Read each delta capability's added, differing modified, and removed scenarios. */
|
|
52
|
+
export async function readCapabilityChanges(projectRoot, folderPath, openspecRoot, deltas) {
|
|
53
|
+
const changes = new Map();
|
|
54
|
+
for (const capability of deltas) {
|
|
55
|
+
const deltaAbs = path.join(folderPath, 'specs', capability, 'spec.md');
|
|
56
|
+
const deltaContent = await fs.readFile(deltaAbs, 'utf8').catch(() => null);
|
|
57
|
+
if (deltaContent === null)
|
|
58
|
+
continue;
|
|
59
|
+
const delta = parseDelta(deltaContent);
|
|
60
|
+
const livingContent = await fs
|
|
61
|
+
.readFile(path.join(openspecRoot, 'specs', capability, 'spec.md'), 'utf8')
|
|
62
|
+
.catch(() => null);
|
|
63
|
+
const living = livingContent === null
|
|
64
|
+
? new Map()
|
|
65
|
+
: requirementScenarios(livingContent);
|
|
66
|
+
const addedNames = [];
|
|
67
|
+
for (const requirement of delta.added) {
|
|
68
|
+
for (const scenario of requirement.scenarios)
|
|
69
|
+
addedNames.push(scenario.name);
|
|
70
|
+
}
|
|
71
|
+
const modifiedNames = [];
|
|
72
|
+
for (const requirement of delta.modified) {
|
|
73
|
+
const existing = living.get(requirement.name);
|
|
74
|
+
for (const scenario of requirement.scenarios) {
|
|
75
|
+
const raw = existing?.get(scenario.name);
|
|
76
|
+
if (raw === undefined || !sameScenarioBlock(raw, scenario.raw)) {
|
|
77
|
+
modifiedNames.push(scenario.name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const removedNames = [];
|
|
82
|
+
for (const requirement of delta.removed) {
|
|
83
|
+
const existing = living.get(requirement.name);
|
|
84
|
+
if (existing !== undefined)
|
|
85
|
+
removedNames.push(...existing.keys());
|
|
86
|
+
}
|
|
87
|
+
changes.set(capability, {
|
|
88
|
+
capability,
|
|
89
|
+
deltaPath: repositoryPath(projectRoot, deltaAbs),
|
|
90
|
+
addedNames,
|
|
91
|
+
modifiedNames,
|
|
92
|
+
removedNames,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return changes;
|
|
96
|
+
}
|
|
97
|
+
/** Every scenario the change alters, in capability and delta order. */
|
|
98
|
+
export function blastScenarios(changes) {
|
|
99
|
+
const scenarios = [];
|
|
100
|
+
for (const change of changes.values()) {
|
|
101
|
+
for (const name of [...change.modifiedNames, ...change.removedNames]) {
|
|
102
|
+
scenarios.push({ capability: change.capability, name, deltaPath: change.deltaPath });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return scenarios;
|
|
106
|
+
}
|
|
107
|
+
/** True when a task holds the test in its resolved scope with tests.modify. */
|
|
108
|
+
function scopedForModification(tasks, test) {
|
|
109
|
+
return tasks.some((task) => task.testsModify && task.resolvedPaths.includes(test));
|
|
110
|
+
}
|
|
111
|
+
/** The scenario listing and modification warnings for the altered scenarios. */
|
|
112
|
+
export function scenarioImpactFindings(input) {
|
|
113
|
+
if (input.index.scenarioTestFiles.length === 0)
|
|
114
|
+
return [];
|
|
115
|
+
const findings = [];
|
|
116
|
+
for (const scenario of input.scenarios) {
|
|
117
|
+
const tests = input.index.testsNaming(scenario.capability, scenario.name);
|
|
118
|
+
if (tests.length === 0)
|
|
119
|
+
continue;
|
|
120
|
+
const severity = input.mode === 'require' && input.optedIn.has(scenario.capability) ? 'error' : 'warning';
|
|
121
|
+
findings.push(makeFinding(severity, { file: scenario.deltaPath }, `Scenario "${scenario.name}" in ${scenario.capability} changes; tests naming it: ${tests.join(', ')}`));
|
|
122
|
+
for (const test of tests) {
|
|
123
|
+
if (scopedForModification(input.tasks, test))
|
|
124
|
+
continue;
|
|
125
|
+
findings.push(makeFinding(severity, { file: test }, `${test} names changed scenario "${scenario.name}" but no task scopes it with tests.modify: true`));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return findings;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=scenario-impact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario-impact.js","sourceRoot":"","sources":["../../../src/core/spec/scenario-impact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type ImportGraph } from './import-graph.js';
|
|
2
|
+
import { type LintFinding } from './lint-findings.js';
|
|
3
|
+
/**
|
|
4
|
+
* The import-graph half of impact lint: a task that reaches a preexisting test
|
|
5
|
+
* it may not modify, and a verify that names tests which reach nothing in the
|
|
6
|
+
* task's scope. Both consume the shared graph and never affect validity.
|
|
7
|
+
*/
|
|
8
|
+
/** One task's resolved scope, as lint already computed it. */
|
|
9
|
+
export interface TestImpactTask {
|
|
10
|
+
readonly taskNumber: string;
|
|
11
|
+
readonly taskPath: string;
|
|
12
|
+
readonly existingPaths: readonly string[];
|
|
13
|
+
readonly testsModify: boolean;
|
|
14
|
+
readonly verify: string;
|
|
15
|
+
}
|
|
16
|
+
/** Limits read from `limits.importGraphDepth` and `limits.maxListedImporters`. */
|
|
17
|
+
export interface FrozenTestLimits {
|
|
18
|
+
readonly maxDepth: number;
|
|
19
|
+
readonly maxListed: number;
|
|
20
|
+
}
|
|
21
|
+
/** Warn once per task whose existing scope is reached by an unmodifiable test. */
|
|
22
|
+
export declare function frozenTestFindings(tasks: readonly TestImpactTask[], graph: ImportGraph, limits: FrozenTestLimits): LintFinding[];
|
|
23
|
+
/**
|
|
24
|
+
* Warn once per task whose verify names only existing tests and none of them
|
|
25
|
+
* reaches an existing file in the task's scope at any depth.
|
|
26
|
+
*/
|
|
27
|
+
export declare function verifyWithoutScopeFindings(projectRoot: string, tasks: readonly TestImpactTask[], graph: ImportGraph): Promise<LintFinding[]>;
|
|
28
|
+
//# sourceMappingURL=test-impact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-impact.d.ts","sourceRoot":"","sources":["../../../src/core/spec/test-impact.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAgC,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,oBAAoB,CAAC;AAGnE;;;;GAIG;AAEH,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AA6CD,kFAAkF;AAClF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,gBAAgB,GACvB,WAAW,EAAE,CA4Bf;AA2CD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CAyBxB"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { resolveScope } from '../run/scope.js';
|
|
4
|
+
import { reachImporters, reachImports } from './import-graph.js';
|
|
5
|
+
import { makeFinding } from './lint-findings.js';
|
|
6
|
+
import { listNamedPaths } from './verify-paths.js';
|
|
7
|
+
/** Test files governed by the `tests.modify` gate; mirrors the `tests/**` default. */
|
|
8
|
+
function isTestPath(relativePath) {
|
|
9
|
+
return relativePath === 'tests' || relativePath.startsWith('tests/');
|
|
10
|
+
}
|
|
11
|
+
/** Every existing test a task in the change may modify through `tests.modify`. */
|
|
12
|
+
function modifiableTests(tasks) {
|
|
13
|
+
const modifiable = new Set();
|
|
14
|
+
for (const task of tasks) {
|
|
15
|
+
if (!task.testsModify)
|
|
16
|
+
continue;
|
|
17
|
+
for (const existing of task.existingPaths) {
|
|
18
|
+
if (isTestPath(existing))
|
|
19
|
+
modifiable.add(existing);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return modifiable;
|
|
23
|
+
}
|
|
24
|
+
/** The scoped file a reached test imports, or null when none intersects scope. */
|
|
25
|
+
function scopedTarget(graph, test, scoped) {
|
|
26
|
+
const reached = reachImports(graph, [test])
|
|
27
|
+
.filter((file) => scoped.has(file))
|
|
28
|
+
.sort();
|
|
29
|
+
return reached[0] ?? null;
|
|
30
|
+
}
|
|
31
|
+
/** The one-sentence frozen-test warning, capped by `maxListed`. */
|
|
32
|
+
function formatFrozenTestWarning(taskNumber, entries, maxListed) {
|
|
33
|
+
const listed = entries.slice(0, maxListed);
|
|
34
|
+
const direct = entries.filter((entry) => entry.depth === 1).length;
|
|
35
|
+
const list = listed.map((entry) => `${entry.test} (${entry.file})`).join(', ');
|
|
36
|
+
const rest = entries.length - listed.length;
|
|
37
|
+
const more = rest > 0 ? ` and ${rest} more` : '';
|
|
38
|
+
return `Task ${taskNumber} scope is imported by ${entries.length} preexisting tests that no task may modify, ${direct} directly: ${list}${more}. Add each test the task will change to its scope with tests.modify: true`;
|
|
39
|
+
}
|
|
40
|
+
/** Warn once per task whose existing scope is reached by an unmodifiable test. */
|
|
41
|
+
export function frozenTestFindings(tasks, graph, limits) {
|
|
42
|
+
if (graph.files.length === 0)
|
|
43
|
+
return [];
|
|
44
|
+
const modifiable = modifiableTests(tasks);
|
|
45
|
+
const findings = [];
|
|
46
|
+
for (const task of tasks) {
|
|
47
|
+
if (task.existingPaths.length === 0)
|
|
48
|
+
continue;
|
|
49
|
+
const scoped = new Set(task.existingPaths);
|
|
50
|
+
const reachedTests = reachImporters(graph, task.existingPaths, limits.maxDepth).filter((entry) => isTestPath(entry.file) && !modifiable.has(entry.file));
|
|
51
|
+
if (reachedTests.length === 0)
|
|
52
|
+
continue;
|
|
53
|
+
const entries = reachedTests.map((entry) => ({
|
|
54
|
+
depth: entry.depth,
|
|
55
|
+
test: entry.file,
|
|
56
|
+
file: scopedTarget(graph, entry.file, scoped) ?? task.existingPaths[0] ?? '',
|
|
57
|
+
}));
|
|
58
|
+
findings.push(makeFinding('warning', { file: task.taskPath }, formatFrozenTestWarning(task.taskNumber, entries, limits.maxListed)));
|
|
59
|
+
}
|
|
60
|
+
return findings;
|
|
61
|
+
}
|
|
62
|
+
/** A path operand without glob metacharacters. */
|
|
63
|
+
function isExactOperand(operand) {
|
|
64
|
+
return !/[*?]/.test(operand);
|
|
65
|
+
}
|
|
66
|
+
async function pathExists(target) {
|
|
67
|
+
return fs
|
|
68
|
+
.stat(target)
|
|
69
|
+
.then(() => true)
|
|
70
|
+
.catch(() => false);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The existing test files a verify names, or null when any named test operand is
|
|
74
|
+
* missing or an unmatched glob. An operand that names no test yields an empty
|
|
75
|
+
* list.
|
|
76
|
+
*/
|
|
77
|
+
async function verifiedTestPaths(projectRoot, command) {
|
|
78
|
+
const seen = new Set();
|
|
79
|
+
const tests = [];
|
|
80
|
+
for (const named of listNamedPaths(command)) {
|
|
81
|
+
if (!isTestPath(named) || seen.has(named))
|
|
82
|
+
continue;
|
|
83
|
+
seen.add(named);
|
|
84
|
+
if (isExactOperand(named)) {
|
|
85
|
+
if (!(await pathExists(path.join(projectRoot, named))))
|
|
86
|
+
return null;
|
|
87
|
+
tests.push(named);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const matches = (await resolveScope(projectRoot, [named]))
|
|
91
|
+
.filter((entry) => entry.absolutePath !== null && isTestPath(entry.relativePath))
|
|
92
|
+
.map((entry) => entry.relativePath);
|
|
93
|
+
if (matches.length === 0)
|
|
94
|
+
return null;
|
|
95
|
+
tests.push(...matches);
|
|
96
|
+
}
|
|
97
|
+
return tests;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Warn once per task whose verify names only existing tests and none of them
|
|
101
|
+
* reaches an existing file in the task's scope at any depth.
|
|
102
|
+
*/
|
|
103
|
+
export async function verifyWithoutScopeFindings(projectRoot, tasks, graph) {
|
|
104
|
+
const findings = [];
|
|
105
|
+
const graphFiles = new Set(graph.files);
|
|
106
|
+
for (const task of tasks) {
|
|
107
|
+
const named = await verifiedTestPaths(projectRoot, task.verify);
|
|
108
|
+
const tests = named?.filter((test) => graphFiles.has(test)) ?? [];
|
|
109
|
+
if (tests.length === 0)
|
|
110
|
+
continue;
|
|
111
|
+
const scoped = new Set(task.existingPaths);
|
|
112
|
+
const reachesScope = tests.some((test) => reachImports(graph, [test]).some((file) => scoped.has(file)));
|
|
113
|
+
if (reachesScope)
|
|
114
|
+
continue;
|
|
115
|
+
findings.push(makeFinding('warning', { file: task.taskPath }, `Task ${task.taskNumber} verify runs ${tests.join(', ')} but none of them imports a file in the task's scope`));
|
|
116
|
+
}
|
|
117
|
+
return findings;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=test-impact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-impact.js","sourceRoot":"","sources":["../../../src/core/spec/test-impact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { TraceabilityMode } from '../foundation/config-traceability.js';
|
|
2
|
+
import type { Adr } from '../foundation/decisions.js';
|
|
3
|
+
import type { ScenarioIndex } from '../trace/scenario-index.js';
|
|
4
|
+
import { type CapabilityOwnership } from './capability-impact.js';
|
|
5
|
+
import { type LintFinding, type LintSeverity } from './lint-findings.js';
|
|
6
|
+
/**
|
|
7
|
+
* The link half of traceability lint: an added or modified scenario no scoped
|
|
8
|
+
* test names, a tag naming a missing scenario, a tagged function no covering
|
|
9
|
+
* test reaches, an ADR tag that is missing, unaccepted, or out of scope, and
|
|
10
|
+
* two effective scenarios sharing a name.
|
|
11
|
+
*/
|
|
12
|
+
/** One task's number, file, and resolved scope for planned-scenario reading. */
|
|
13
|
+
export interface PlannedTask {
|
|
14
|
+
readonly taskNumber: string;
|
|
15
|
+
readonly taskPath: string;
|
|
16
|
+
readonly resolvedPaths: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
/** The stable key for one capability/scenario pair. */
|
|
19
|
+
export declare function scenarioKey(capability: string, name: string): string;
|
|
20
|
+
/** The severity every traceability finding takes from the configured mode. */
|
|
21
|
+
export declare function traceabilitySeverity(mode: TraceabilityMode): LintSeverity;
|
|
22
|
+
/** One opted-in capability's scenario facts for the link rules. */
|
|
23
|
+
export interface CapabilityLinkInfo {
|
|
24
|
+
readonly capability: string;
|
|
25
|
+
/** Repository-relative delta spec path, or null when the change has none. */
|
|
26
|
+
readonly deltaPath: string | null;
|
|
27
|
+
/** Every scenario name in the effective spec, in document order. */
|
|
28
|
+
readonly effectiveNames: readonly string[];
|
|
29
|
+
/** Added scenarios plus modified scenarios whose block differs. */
|
|
30
|
+
readonly alteredNames: readonly string[];
|
|
31
|
+
}
|
|
32
|
+
/** Everything the link rules read, already collected by the entry module. */
|
|
33
|
+
export interface TraceabilityLinksInput {
|
|
34
|
+
readonly mode: TraceabilityMode;
|
|
35
|
+
readonly index: ScenarioIndex;
|
|
36
|
+
readonly scopedFiles: ReadonlySet<string>;
|
|
37
|
+
readonly optedIn: ReadonlySet<string>;
|
|
38
|
+
readonly capabilities: readonly CapabilityLinkInfo[];
|
|
39
|
+
/** `scenarioKey` values a task with a test path lists under `## Scenarios`. */
|
|
40
|
+
readonly planned: ReadonlySet<string>;
|
|
41
|
+
readonly namedByScopedTest: (capability: string, name: string) => boolean;
|
|
42
|
+
readonly plannedCoversFunction: (file: string, capability: string, name: string) => boolean;
|
|
43
|
+
readonly adrs: readonly Adr[];
|
|
44
|
+
readonly ownerships: readonly CapabilityOwnership[];
|
|
45
|
+
}
|
|
46
|
+
/** Every link finding: scenario links, tags, and ADRs, all in scope order. */
|
|
47
|
+
export declare function linkFindings(input: TraceabilityLinksInput): LintFinding[];
|
|
48
|
+
/** True when a planned scenario covers a function in the planning task's scope. */
|
|
49
|
+
export declare function plannedCoversFunction(tasks: readonly PlannedTask[], planned: ReadonlyMap<string, Set<string>>, file: string, capability: string, name: string, namedByScopedTest: (capability: string, name: string) => boolean): boolean;
|
|
50
|
+
//# sourceMappingURL=traceability-links.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traceability-links.d.ts","sourceRoot":"","sources":["../../../src/core/spec/traceability-links.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,4BAA4B,CAAC;AAEtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,KAAK,mBAAmB,EAAqB,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAe,MAAM,oBAAoB,CAAC;AAEtF;;;;;GAKG;AAEH,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED,uDAAuD;AACvD,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAEzE;AAED,mEAAmE;AACnE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,oEAAoE;IACpE,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACrD,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1E,QAAQ,CAAC,qBAAqB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5F,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACrD;AAwJD,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,sBAAsB,GAAG,WAAW,EAAE,CAEzE;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EACzC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,GAC/D,OAAO,CAMT"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { sameAdrNumber } from '../foundation/decisions.js';
|
|
2
|
+
import { ownerCapabilities } from './capability-impact.js';
|
|
3
|
+
import { makeFinding } from './lint-findings.js';
|
|
4
|
+
/** The stable key for one capability/scenario pair. */
|
|
5
|
+
export function scenarioKey(capability, name) {
|
|
6
|
+
return `${capability}\u0000${name}`;
|
|
7
|
+
}
|
|
8
|
+
/** The severity every traceability finding takes from the configured mode. */
|
|
9
|
+
export function traceabilitySeverity(mode) {
|
|
10
|
+
return mode === 'require' ? 'error' : 'warning';
|
|
11
|
+
}
|
|
12
|
+
/** The first scenario name that appears more than once, in document order. */
|
|
13
|
+
function firstDuplicate(names) {
|
|
14
|
+
const seen = new Set();
|
|
15
|
+
for (const name of names) {
|
|
16
|
+
if (seen.has(name))
|
|
17
|
+
return name;
|
|
18
|
+
seen.add(name);
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
/** Scenario-level findings: duplicate names and altered scenarios no test names. */
|
|
23
|
+
function scenarioFindings(input) {
|
|
24
|
+
const findings = [];
|
|
25
|
+
const severity = traceabilitySeverity(input.mode);
|
|
26
|
+
for (const info of input.capabilities) {
|
|
27
|
+
if (info.deltaPath !== null) {
|
|
28
|
+
const duplicate = firstDuplicate(info.effectiveNames);
|
|
29
|
+
if (duplicate !== null) {
|
|
30
|
+
findings.push(makeFinding(severity, { file: info.deltaPath }, `${info.capability}: two scenarios named "${duplicate}"`));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (info.deltaPath === null)
|
|
34
|
+
continue;
|
|
35
|
+
for (const name of info.alteredNames) {
|
|
36
|
+
if (input.planned.has(scenarioKey(info.capability, name)))
|
|
37
|
+
continue;
|
|
38
|
+
if (input.namedByScopedTest(info.capability, name))
|
|
39
|
+
continue;
|
|
40
|
+
findings.push(makeFinding(severity, { file: info.deltaPath }, `${info.capability}: no test names scenario "${name}"`));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return findings;
|
|
44
|
+
}
|
|
45
|
+
/** The capabilities a function serves, from its tags or its file's owners. */
|
|
46
|
+
function servedCapabilities(input, file, scenarios) {
|
|
47
|
+
if (scenarios.length > 0) {
|
|
48
|
+
return [...new Set(scenarios.map((scenario) => scenario.capability))];
|
|
49
|
+
}
|
|
50
|
+
return ownerCapabilities(input.ownerships, file);
|
|
51
|
+
}
|
|
52
|
+
/** True when an accepted ADR applies to `all` or to a served capability. */
|
|
53
|
+
function adrApplies(adr, served) {
|
|
54
|
+
if (adr.appliesTo === 'all')
|
|
55
|
+
return true;
|
|
56
|
+
if (!Array.isArray(adr.appliesTo))
|
|
57
|
+
return false;
|
|
58
|
+
return adr.appliesTo.some((capability) => served.includes(capability));
|
|
59
|
+
}
|
|
60
|
+
/** The ADR findings for one function's `@adr` tags. */
|
|
61
|
+
function adrFindings(input, file, fnName, adrNumbers, served, severity) {
|
|
62
|
+
const findings = [];
|
|
63
|
+
for (const number of adrNumbers) {
|
|
64
|
+
const adr = input.adrs.find((candidate) => sameAdrNumber(candidate.number, number));
|
|
65
|
+
if (adr === undefined || adr.status !== 'accepted') {
|
|
66
|
+
findings.push(makeFinding(severity, { file }, `${fnName}: ADR ${number} doesn't exist or isn't accepted`));
|
|
67
|
+
}
|
|
68
|
+
else if (!adrApplies(adr, served)) {
|
|
69
|
+
findings.push(makeFinding(severity, { file }, `${fnName}: ADR ${number} doesn't apply to any capability it serves`));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return findings;
|
|
73
|
+
}
|
|
74
|
+
/** True when a test that covers a function also names the scenario. */
|
|
75
|
+
function coveredByName(input, file, fnName, capability, scenario) {
|
|
76
|
+
const naming = new Set(input.index.testsNaming(capability, scenario));
|
|
77
|
+
return input.index.coveringTests(file, fnName).some((test) => naming.has(test));
|
|
78
|
+
}
|
|
79
|
+
/** Tag and ADR findings for the exported functions inside resolved scopes. */
|
|
80
|
+
function functionFindings(input) {
|
|
81
|
+
const findings = [];
|
|
82
|
+
const severity = traceabilitySeverity(input.mode);
|
|
83
|
+
const namesByCapability = new Map(input.capabilities.map((info) => [info.capability, new Set(info.effectiveNames)]));
|
|
84
|
+
for (const fn of input.index.functions) {
|
|
85
|
+
if (!input.scopedFiles.has(fn.file))
|
|
86
|
+
continue;
|
|
87
|
+
for (const tag of fn.scenarios) {
|
|
88
|
+
if (!input.optedIn.has(tag.capability))
|
|
89
|
+
continue;
|
|
90
|
+
const names = namesByCapability.get(tag.capability) ?? new Set();
|
|
91
|
+
if (!names.has(tag.name)) {
|
|
92
|
+
findings.push(makeFinding(severity, { file: fn.file }, `${fn.name}: names a scenario the ${tag.capability} spec doesn't have: "${tag.name}"`));
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const planned = input.plannedCoversFunction(fn.file, tag.capability, tag.name);
|
|
96
|
+
if (!planned && !coveredByName(input, fn.file, fn.name, tag.capability, tag.name)) {
|
|
97
|
+
findings.push(makeFinding(severity, { file: fn.file }, `${fn.name}: no test for "${tag.name}" covers it`));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (fn.adrs.length === 0)
|
|
101
|
+
continue;
|
|
102
|
+
const served = servedCapabilities(input, fn.file, fn.scenarios);
|
|
103
|
+
if (!served.some((capability) => input.optedIn.has(capability)))
|
|
104
|
+
continue;
|
|
105
|
+
findings.push(...adrFindings(input, fn.file, fn.name, fn.adrs, served, severity));
|
|
106
|
+
}
|
|
107
|
+
return findings;
|
|
108
|
+
}
|
|
109
|
+
/** Every link finding: scenario links, tags, and ADRs, all in scope order. */
|
|
110
|
+
export function linkFindings(input) {
|
|
111
|
+
return [...scenarioFindings(input), ...functionFindings(input)];
|
|
112
|
+
}
|
|
113
|
+
/** True when a planned scenario covers a function in the planning task's scope. */
|
|
114
|
+
export function plannedCoversFunction(tasks, planned, file, capability, name, namedByScopedTest) {
|
|
115
|
+
if (namedByScopedTest(capability, name))
|
|
116
|
+
return false;
|
|
117
|
+
const key = scenarioKey(capability, name);
|
|
118
|
+
return tasks.some((task) => planned.get(task.taskNumber)?.has(key) === true && task.resolvedPaths.includes(file));
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=traceability-links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traceability-links.js","sourceRoot":"","sources":["../../../src/core/spec/traceability-links.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { OsqConfig } from '../foundation/config.js';
|
|
2
|
+
import type { ImportGraph } from './import-graph.js';
|
|
3
|
+
import { type LintFinding } from './lint-findings.js';
|
|
4
|
+
/**
|
|
5
|
+
* Scenario traceability lint: one entrypoint that reads the effective spec,
|
|
6
|
+
* the scenario index built from the import graph, and each task's planned
|
|
7
|
+
* scenarios, then returns the link findings and the blast radius of changed
|
|
8
|
+
* scenarios. It is computed in one call from `lintChangeFolder`.
|
|
9
|
+
*/
|
|
10
|
+
/** One task's resolved scope, for planning and blast-radius checks. */
|
|
11
|
+
export interface TraceabilityTask {
|
|
12
|
+
readonly taskNumber: string;
|
|
13
|
+
readonly taskPath: string;
|
|
14
|
+
/** Every resolved scope path, existing or not. */
|
|
15
|
+
readonly resolvedPaths: readonly string[];
|
|
16
|
+
readonly testsModify: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface TraceabilityInput {
|
|
19
|
+
readonly projectRoot: string;
|
|
20
|
+
readonly folderPath: string;
|
|
21
|
+
readonly config: OsqConfig;
|
|
22
|
+
/** Repository-relative `proposal.md`; kept for the entry contract. */
|
|
23
|
+
readonly proposalPath: string;
|
|
24
|
+
readonly tasks: readonly TraceabilityTask[];
|
|
25
|
+
readonly importGraph: ImportGraph;
|
|
26
|
+
}
|
|
27
|
+
/** Collect the traceability findings for one change folder. */
|
|
28
|
+
export declare function collectTraceabilityFindings(input: TraceabilityInput): Promise<LintFinding[]>;
|
|
29
|
+
//# sourceMappingURL=traceability-lint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traceability-lint.d.ts","sourceRoot":"","sources":["../../../src/core/spec/traceability-lint.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAMzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,oBAAoB,CAAC;AAkBnE;;;;;GAKG;AAEH,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC5C,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;CACnC;AAkHD,+DAA+D;AAC/D,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,WAAW,EAAE,CAAC,CAgExB"}
|