@shrkcrft/cli 0.1.0-alpha.29 → 0.1.0-alpha.31
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/asset-preview/apply-asset-preview.js +1 -1
- package/dist/authoring/authoring-kit.d.ts +9 -1
- package/dist/authoring/authoring-kit.d.ts.map +1 -1
- package/dist/authoring/authoring-kit.js +26 -13
- package/dist/bootstrap/unlinked-workspace-dependency.d.ts +11 -0
- package/dist/bootstrap/unlinked-workspace-dependency.d.ts.map +1 -0
- package/dist/bootstrap/unlinked-workspace-dependency.js +99 -0
- package/dist/command-registry.d.ts +100 -1
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +130 -3
- package/dist/commands/api-diff.command.d.ts.map +1 -1
- package/dist/commands/api-diff.command.js +12 -0
- package/dist/commands/apply.command.d.ts.map +1 -1
- package/dist/commands/apply.command.js +3 -0
- package/dist/commands/arch.command.d.ts.map +1 -1
- package/dist/commands/arch.command.js +26 -7
- package/dist/commands/architecture.command.d.ts.map +1 -1
- package/dist/commands/architecture.command.js +8 -2
- package/dist/commands/baseline.command.d.ts +76 -0
- package/dist/commands/baseline.command.d.ts.map +1 -1
- package/dist/commands/baseline.command.js +599 -75
- package/dist/commands/biome.command.d.ts.map +1 -1
- package/dist/commands/biome.command.js +20 -0
- package/dist/commands/boundaries.command.d.ts +9 -1
- package/dist/commands/boundaries.command.d.ts.map +1 -1
- package/dist/commands/boundaries.command.js +88 -20
- package/dist/commands/bundle.command.d.ts.map +1 -1
- package/dist/commands/bundle.command.js +57 -11
- package/dist/commands/cache-align.command.d.ts.map +1 -1
- package/dist/commands/cache-align.command.js +3 -1
- package/dist/commands/changelog-data.d.ts.map +1 -1
- package/dist/commands/changelog-data.js +164 -0
- package/dist/commands/changes.command.d.ts.map +1 -1
- package/dist/commands/changes.command.js +15 -0
- package/dist/commands/check.command.d.ts.map +1 -1
- package/dist/commands/check.command.js +1260 -324
- package/dist/commands/checks.command.d.ts.map +1 -1
- package/dist/commands/checks.command.js +188 -40
- package/dist/commands/ci.command.d.ts.map +1 -1
- package/dist/commands/ci.command.js +35 -2
- package/dist/commands/code-intel.command.d.ts.map +1 -1
- package/dist/commands/code-intel.command.js +8 -1
- package/dist/commands/command-catalog.d.ts +23 -1
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +152 -35
- package/dist/commands/commands.command.d.ts +21 -3
- package/dist/commands/commands.command.d.ts.map +1 -1
- package/dist/commands/commands.command.js +172 -27
- package/dist/commands/compress.command.d.ts.map +1 -1
- package/dist/commands/compress.command.js +4 -0
- package/dist/commands/constructs.command.d.ts.map +1 -1
- package/dist/commands/constructs.command.js +50 -12
- package/dist/commands/context.command.d.ts.map +1 -1
- package/dist/commands/context.command.js +40 -5
- package/dist/commands/contract-templates.command.d.ts.map +1 -1
- package/dist/commands/contract-templates.command.js +9 -1
- package/dist/commands/contract.command.d.ts.map +1 -1
- package/dist/commands/contract.command.js +35 -0
- package/dist/commands/conventions.command.d.ts.map +1 -1
- package/dist/commands/conventions.command.js +189 -29
- package/dist/commands/coverage.command.d.ts.map +1 -1
- package/dist/commands/coverage.command.js +9 -0
- package/dist/commands/daily.commands.d.ts +0 -1
- package/dist/commands/daily.commands.d.ts.map +1 -1
- package/dist/commands/daily.commands.js +12 -76
- package/dist/commands/dashboard.command.d.ts.map +1 -1
- package/dist/commands/dashboard.command.js +10 -0
- package/dist/commands/dev.command.d.ts.map +1 -1
- package/dist/commands/dev.command.js +45 -2
- package/dist/commands/diagnostics.command.d.ts +0 -2
- package/dist/commands/diagnostics.command.d.ts.map +1 -1
- package/dist/commands/diagnostics.command.js +5 -78
- package/dist/commands/diff-check.command.d.ts +6 -4
- package/dist/commands/diff-check.command.d.ts.map +1 -1
- package/dist/commands/diff-check.command.js +190 -103
- package/dist/commands/docs-references.command.d.ts +20 -0
- package/dist/commands/docs-references.command.d.ts.map +1 -0
- package/dist/commands/docs-references.command.js +520 -0
- package/dist/commands/doctor.command.d.ts.map +1 -1
- package/dist/commands/doctor.command.js +60 -5
- package/dist/commands/drift.command.d.ts.map +1 -1
- package/dist/commands/drift.command.js +17 -4
- package/dist/commands/eslint.command.d.ts.map +1 -1
- package/dist/commands/eslint.command.js +20 -0
- package/dist/commands/export.command.d.ts.map +1 -1
- package/dist/commands/export.command.js +23 -1
- package/dist/commands/feedback-dispatch.command.d.ts.map +1 -1
- package/dist/commands/feedback-dispatch.command.js +29 -0
- package/dist/commands/feedback.command.d.ts.map +1 -1
- package/dist/commands/feedback.command.js +6 -1
- package/dist/commands/finish.command.d.ts.map +1 -1
- package/dist/commands/finish.command.js +32 -8
- package/dist/commands/fix.command.d.ts.map +1 -1
- package/dist/commands/fix.command.js +19 -0
- package/dist/commands/gate.command.d.ts +6 -1
- package/dist/commands/gate.command.d.ts.map +1 -1
- package/dist/commands/gate.command.js +50 -124
- package/dist/commands/gates.command.d.ts +54 -0
- package/dist/commands/gates.command.d.ts.map +1 -1
- package/dist/commands/gates.command.js +1314 -64
- package/dist/commands/gen.command.d.ts.map +1 -1
- package/dist/commands/gen.command.js +4 -0
- package/dist/commands/generated.command.d.ts +62 -0
- package/dist/commands/generated.command.d.ts.map +1 -1
- package/dist/commands/generated.command.js +639 -156
- package/dist/commands/graph-code-subverbs.d.ts +15 -0
- package/dist/commands/graph-code-subverbs.d.ts.map +1 -1
- package/dist/commands/graph-code-subverbs.js +203 -25
- package/dist/commands/graph.command.d.ts.map +1 -1
- package/dist/commands/graph.command.js +79 -37
- package/dist/commands/help.command.d.ts +30 -6
- package/dist/commands/help.command.d.ts.map +1 -1
- package/dist/commands/help.command.js +323 -199
- package/dist/commands/helper.command.d.ts +1 -0
- package/dist/commands/helper.command.d.ts.map +1 -1
- package/dist/commands/helper.command.js +195 -56
- package/dist/commands/impact.command.d.ts.map +1 -1
- package/dist/commands/impact.command.js +115 -12
- package/dist/commands/infer.command.d.ts.map +1 -1
- package/dist/commands/infer.command.js +20 -45
- package/dist/commands/ingest.command.d.ts +0 -1
- package/dist/commands/ingest.command.d.ts.map +1 -1
- package/dist/commands/ingest.command.js +25 -41
- package/dist/commands/knowledge-author.command.d.ts +0 -3
- package/dist/commands/knowledge-author.command.d.ts.map +1 -1
- package/dist/commands/knowledge-author.command.js +10 -23
- package/dist/commands/knowledge.command.d.ts.map +1 -1
- package/dist/commands/knowledge.command.js +469 -129
- package/dist/commands/languages.command.d.ts.map +1 -1
- package/dist/commands/languages.command.js +27 -0
- package/dist/commands/lint.command.d.ts.map +1 -1
- package/dist/commands/lint.command.js +3 -0
- package/dist/commands/mcp.command.d.ts +18 -0
- package/dist/commands/mcp.command.d.ts.map +1 -1
- package/dist/commands/mcp.command.js +33 -8
- package/dist/commands/onboard.command.d.ts.map +1 -1
- package/dist/commands/onboard.command.js +20 -0
- package/dist/commands/owners.command.d.ts.map +1 -1
- package/dist/commands/owners.command.js +14 -2
- package/dist/commands/packs-new.d.ts +13 -1
- package/dist/commands/packs-new.d.ts.map +1 -1
- package/dist/commands/packs-new.js +500 -335
- package/dist/commands/packs.command.d.ts.map +1 -1
- package/dist/commands/packs.command.js +378 -36
- package/dist/commands/paths.command.d.ts.map +1 -1
- package/dist/commands/paths.command.js +9 -1
- package/dist/commands/pipelines.command.d.ts.map +1 -1
- package/dist/commands/pipelines.command.js +7 -1
- package/dist/commands/plan-check.command.d.ts.map +1 -1
- package/dist/commands/plan-check.command.js +3 -0
- package/dist/commands/plan.command.d.ts.map +1 -1
- package/dist/commands/plan.command.js +3 -0
- package/dist/commands/playbooks.command.d.ts.map +1 -1
- package/dist/commands/playbooks.command.js +7 -2
- package/dist/commands/policy-lint.command.d.ts +19 -2
- package/dist/commands/policy-lint.command.d.ts.map +1 -1
- package/dist/commands/policy-lint.command.js +224 -65
- package/dist/commands/policy.command.d.ts.map +1 -1
- package/dist/commands/policy.command.js +6 -1
- package/dist/commands/pr.command.d.ts.map +1 -1
- package/dist/commands/pr.command.js +14 -0
- package/dist/commands/presets.command.d.ts.map +1 -1
- package/dist/commands/presets.command.js +12 -27
- package/dist/commands/profiles.command.d.ts.map +1 -1
- package/dist/commands/profiles.command.js +94 -26
- package/dist/commands/provenance.command.js +1 -1
- package/dist/commands/quality.command.d.ts.map +1 -1
- package/dist/commands/quality.command.js +129 -33
- package/dist/commands/recommend.command.d.ts +20 -4
- package/dist/commands/recommend.command.d.ts.map +1 -1
- package/dist/commands/recommend.command.js +172 -278
- package/dist/commands/registrations.command.d.ts.map +1 -1
- package/dist/commands/registrations.command.js +138 -13
- package/dist/commands/registry-lifecycle-run.d.ts +14 -0
- package/dist/commands/registry-lifecycle-run.d.ts.map +1 -0
- package/dist/commands/registry-lifecycle-run.js +336 -0
- package/dist/commands/registry.command.d.ts.map +1 -1
- package/dist/commands/registry.command.js +235 -62
- package/dist/commands/release.command.d.ts.map +1 -1
- package/dist/commands/release.command.js +99 -20
- package/dist/commands/report.command.d.ts.map +1 -1
- package/dist/commands/report.command.js +38 -2
- package/dist/commands/reuse-coverage.command.d.ts +23 -0
- package/dist/commands/reuse-coverage.command.d.ts.map +1 -0
- package/dist/commands/reuse-coverage.command.js +536 -0
- package/dist/commands/reuse.command.d.ts +3 -18
- package/dist/commands/reuse.command.d.ts.map +1 -1
- package/dist/commands/reuse.command.js +395 -244
- package/dist/commands/review.command.d.ts.map +1 -1
- package/dist/commands/review.command.js +33 -1
- package/dist/commands/rounds.command.d.ts.map +1 -1
- package/dist/commands/rounds.command.js +5 -0
- package/dist/commands/safety.command.d.ts.map +1 -1
- package/dist/commands/safety.command.js +9 -0
- package/dist/commands/scaffolds.command.d.ts.map +1 -1
- package/dist/commands/scaffolds.command.js +97 -25
- package/dist/commands/search.command.d.ts +0 -8
- package/dist/commands/search.command.d.ts.map +1 -1
- package/dist/commands/search.command.js +136 -28
- package/dist/commands/self-config-xrefs.command.d.ts +24 -0
- package/dist/commands/self-config-xrefs.command.d.ts.map +1 -0
- package/dist/commands/self-config-xrefs.command.js +170 -0
- package/dist/commands/self-config.command.d.ts.map +1 -1
- package/dist/commands/self-config.command.js +261 -65
- package/dist/commands/smart-context.command.d.ts.map +1 -1
- package/dist/commands/smart-context.command.js +39 -3
- package/dist/commands/spec.command.d.ts.map +1 -1
- package/dist/commands/spec.command.js +3 -0
- package/dist/commands/stats.command.d.ts.map +1 -1
- package/dist/commands/stats.command.js +3 -0
- package/dist/commands/surface.command.d.ts +6 -1
- package/dist/commands/surface.command.d.ts.map +1 -1
- package/dist/commands/surface.command.js +256 -54
- package/dist/commands/task-context.command.js +1 -1
- package/dist/commands/task.command.d.ts.map +1 -1
- package/dist/commands/task.command.js +22 -1
- package/dist/commands/templates.command.d.ts +4 -0
- package/dist/commands/templates.command.d.ts.map +1 -1
- package/dist/commands/templates.command.js +109 -22
- package/dist/commands/test.command.d.ts.map +1 -1
- package/dist/commands/test.command.js +161 -33
- package/dist/commands/tests.command.d.ts.map +1 -1
- package/dist/commands/tests.command.js +29 -3
- package/dist/commands/trace.command.d.ts.map +1 -1
- package/dist/commands/trace.command.js +29 -4
- package/dist/commands/watch.command.d.ts.map +1 -1
- package/dist/commands/watch.command.js +3 -0
- package/dist/commands/why.command.d.ts.map +1 -1
- package/dist/commands/why.command.js +3 -0
- package/dist/commands/wiring.command.d.ts +18 -4
- package/dist/commands/wiring.command.d.ts.map +1 -1
- package/dist/commands/wiring.command.js +362 -74
- package/dist/dashboard/code-intelligence-data.js +4 -4
- package/dist/diff/deleted-orphan-coverage.d.ts +32 -0
- package/dist/diff/deleted-orphan-coverage.d.ts.map +1 -0
- package/dist/diff/deleted-orphan-coverage.js +107 -0
- package/dist/diff/deleted-orphan-scope-notes.d.ts +23 -0
- package/dist/diff/deleted-orphan-scope-notes.d.ts.map +1 -0
- package/dist/diff/deleted-orphan-scope-notes.js +49 -0
- package/dist/diff/deleted-orphans.d.ts +32 -0
- package/dist/diff/deleted-orphans.d.ts.map +1 -1
- package/dist/diff/deleted-orphans.js +42 -2
- package/dist/dispatch/closest-match.d.ts +15 -0
- package/dist/dispatch/closest-match.d.ts.map +1 -0
- package/dist/dispatch/closest-match.js +47 -0
- package/dist/dispatch/global-flags.d.ts +94 -0
- package/dist/dispatch/global-flags.d.ts.map +1 -0
- package/dist/dispatch/global-flags.js +123 -0
- package/dist/dispatch/guard-invocation-input.d.ts +24 -0
- package/dist/dispatch/guard-invocation-input.d.ts.map +1 -0
- package/dist/dispatch/guard-invocation-input.js +1 -0
- package/dist/dispatch/guard-invocation.d.ts +33 -0
- package/dist/dispatch/guard-invocation.d.ts.map +1 -0
- package/dist/dispatch/guard-invocation.js +183 -0
- package/dist/dispatch/help-intercept.d.ts +22 -0
- package/dist/dispatch/help-intercept.d.ts.map +1 -0
- package/dist/dispatch/help-intercept.js +42 -0
- package/dist/dispatch/i-declared-invocation.d.ts +17 -0
- package/dist/dispatch/i-declared-invocation.d.ts.map +1 -0
- package/dist/dispatch/i-declared-invocation.js +1 -0
- package/dist/dispatch/i-unknown-flag-refusal-input.d.ts +28 -0
- package/dist/dispatch/i-unknown-flag-refusal-input.d.ts.map +1 -0
- package/dist/dispatch/i-unknown-flag-refusal-input.js +1 -0
- package/dist/dispatch/invocation-rejection-kind.d.ts +15 -0
- package/dist/dispatch/invocation-rejection-kind.d.ts.map +1 -0
- package/dist/dispatch/invocation-rejection-kind.js +15 -0
- package/dist/dispatch/invocation-rejection.d.ts +18 -0
- package/dist/dispatch/invocation-rejection.d.ts.map +1 -0
- package/dist/dispatch/invocation-rejection.js +1 -0
- package/dist/dispatch/judge-invocation.d.ts +24 -0
- package/dist/dispatch/judge-invocation.d.ts.map +1 -0
- package/dist/dispatch/judge-invocation.js +50 -0
- package/dist/dispatch/positional-mode.d.ts +18 -0
- package/dist/dispatch/positional-mode.d.ts.map +1 -0
- package/dist/dispatch/positional-mode.js +18 -0
- package/dist/dispatch/read-tracking-map.d.ts +28 -0
- package/dist/dispatch/read-tracking-map.d.ts.map +1 -0
- package/dist/dispatch/read-tracking-map.js +58 -0
- package/dist/dispatch/refuse-sibling-valve-flags.d.ts +30 -0
- package/dist/dispatch/refuse-sibling-valve-flags.d.ts.map +1 -0
- package/dist/dispatch/refuse-sibling-valve-flags.js +65 -0
- package/dist/dispatch/subverb-spec.d.ts +26 -0
- package/dist/dispatch/subverb-spec.d.ts.map +1 -0
- package/dist/dispatch/subverb-spec.js +1 -0
- package/dist/dispatch/undocumented-flag-reads.d.ts +22 -0
- package/dist/dispatch/undocumented-flag-reads.d.ts.map +1 -0
- package/dist/dispatch/undocumented-flag-reads.js +283 -0
- package/dist/dispatch/unknown-flag-refusal-mode.d.ts +13 -0
- package/dist/dispatch/unknown-flag-refusal-mode.d.ts.map +1 -0
- package/dist/dispatch/unknown-flag-refusal-mode.js +13 -0
- package/dist/dispatch/unknown-flag-refusal.d.ts +22 -0
- package/dist/dispatch/unknown-flag-refusal.d.ts.map +1 -0
- package/dist/dispatch/unknown-flag-refusal.js +57 -0
- package/dist/dispatch/unread-flags.d.ts +152 -0
- package/dist/dispatch/unread-flags.d.ts.map +1 -0
- package/dist/dispatch/unread-flags.js +295 -0
- package/dist/dispatch/verdict-valve-flag.d.ts +21 -0
- package/dist/dispatch/verdict-valve-flag.d.ts.map +1 -0
- package/dist/dispatch/verdict-valve-flag.js +21 -0
- package/dist/dispatch/walk-declared-subverbs.d.ts +14 -0
- package/dist/dispatch/walk-declared-subverbs.d.ts.map +1 -0
- package/dist/dispatch/walk-declared-subverbs.js +28 -0
- package/dist/exit-codes.d.ts +41 -3
- package/dist/exit-codes.d.ts.map +1 -1
- package/dist/exit-codes.js +153 -14
- package/dist/finish/run-finish.d.ts +72 -5
- package/dist/finish/run-finish.d.ts.map +1 -1
- package/dist/finish/run-finish.js +453 -104
- package/dist/gates/accepted-empty-note.d.ts +10 -0
- package/dist/gates/accepted-empty-note.d.ts.map +1 -0
- package/dist/gates/accepted-empty-note.js +11 -0
- package/dist/gates/allow-empty.d.ts +25 -0
- package/dist/gates/allow-empty.d.ts.map +1 -0
- package/dist/gates/allow-empty.js +27 -0
- package/dist/gates/asset-doctor-failing-units.d.ts +16 -0
- package/dist/gates/asset-doctor-failing-units.d.ts.map +1 -0
- package/dist/gates/asset-doctor-failing-units.js +14 -0
- package/dist/gates/asset-doctor-failure-line.d.ts +16 -0
- package/dist/gates/asset-doctor-failure-line.d.ts.map +1 -0
- package/dist/gates/asset-doctor-failure-line.js +28 -0
- package/dist/gates/empty-rule-advice-lines.d.ts +15 -0
- package/dist/gates/empty-rule-advice-lines.d.ts.map +1 -0
- package/dist/gates/empty-rule-advice-lines.js +20 -0
- package/dist/gates/gate-envelope.d.ts +85 -8
- package/dist/gates/gate-envelope.d.ts.map +1 -1
- package/dist/gates/gate-envelope.js +56 -7
- package/dist/gates/gate-rule-globs.d.ts +67 -0
- package/dist/gates/gate-rule-globs.d.ts.map +1 -0
- package/dist/gates/gate-rule-globs.js +139 -0
- package/dist/gates/gate-rule-view.d.ts +25 -6
- package/dist/gates/gate-rule-view.d.ts.map +1 -1
- package/dist/gates/gate-rule-view.js +105 -77
- package/dist/gates/i-coverage-dead-glob.d.ts +19 -0
- package/dist/gates/i-coverage-dead-glob.d.ts.map +1 -0
- package/dist/gates/i-coverage-dead-glob.js +1 -0
- package/dist/gates/i-coverage-negation.d.ts +13 -0
- package/dist/gates/i-coverage-negation.d.ts.map +1 -0
- package/dist/gates/i-coverage-negation.js +1 -0
- package/dist/gates/i-registration-query-settle-input.d.ts +18 -0
- package/dist/gates/i-registration-query-settle-input.d.ts.map +1 -0
- package/dist/gates/i-registration-query-settle-input.js +1 -0
- package/dist/gates/i-unit-state-note-row.d.ts +16 -0
- package/dist/gates/i-unit-state-note-row.d.ts.map +1 -0
- package/dist/gates/i-unit-state-note-row.js +1 -0
- package/dist/gates/i-unit-state-notes.d.ts +32 -0
- package/dist/gates/i-unit-state-notes.d.ts.map +1 -0
- package/dist/gates/i-unit-state-notes.js +1 -0
- package/dist/gates/incomplete-registry-inventory.d.ts +19 -0
- package/dist/gates/incomplete-registry-inventory.d.ts.map +1 -0
- package/dist/gates/incomplete-registry-inventory.js +63 -0
- package/dist/gates/measure-registration-roles.d.ts +10 -0
- package/dist/gates/measure-registration-roles.d.ts.map +1 -0
- package/dist/gates/measure-registration-roles.js +9 -0
- package/dist/gates/plane-verdict.d.ts +14 -0
- package/dist/gates/plane-verdict.d.ts.map +1 -0
- package/dist/gates/plane-verdict.js +22 -0
- package/dist/gates/qualify-clean-for-units.d.ts +12 -0
- package/dist/gates/qualify-clean-for-units.d.ts.map +1 -0
- package/dist/gates/qualify-clean-for-units.js +18 -0
- package/dist/gates/registration-graph-verdict.d.ts +34 -0
- package/dist/gates/registration-graph-verdict.d.ts.map +1 -0
- package/dist/gates/registration-graph-verdict.js +70 -0
- package/dist/gates/registration-roles.d.ts +9 -0
- package/dist/gates/registration-roles.d.ts.map +1 -0
- package/dist/gates/registration-roles.js +1 -0
- package/dist/gates/registry-liveness.d.ts +11 -0
- package/dist/gates/registry-liveness.d.ts.map +1 -0
- package/dist/gates/registry-liveness.js +13 -0
- package/dist/gates/rule-coverage.d.ts +225 -4
- package/dist/gates/rule-coverage.d.ts.map +1 -1
- package/dist/gates/rule-coverage.js +610 -43
- package/dist/gates/run-gate-planes.d.ts +58 -0
- package/dist/gates/run-gate-planes.d.ts.map +1 -0
- package/dist/gates/run-gate-planes.js +403 -0
- package/dist/gates/scaffold-selftest.d.ts +56 -0
- package/dist/gates/scaffold-selftest.d.ts.map +1 -0
- package/dist/gates/scaffold-selftest.js +119 -0
- package/dist/gates/seam-rejected-rules.d.ts +28 -0
- package/dist/gates/seam-rejected-rules.d.ts.map +1 -0
- package/dist/gates/seam-rejected-rules.js +95 -0
- package/dist/gates/self-test-check.d.ts +29 -0
- package/dist/gates/self-test-check.d.ts.map +1 -0
- package/dist/gates/self-test-check.js +1 -0
- package/dist/gates/self-test-subject.d.ts +28 -0
- package/dist/gates/self-test-subject.d.ts.map +1 -0
- package/dist/gates/self-test-subject.js +1 -0
- package/dist/gates/self-test.d.ts +20 -0
- package/dist/gates/self-test.d.ts.map +1 -0
- package/dist/gates/self-test.js +82 -0
- package/dist/gates/settle-verdict.d.ts +14 -0
- package/dist/gates/settle-verdict.d.ts.map +1 -0
- package/dist/gates/settle-verdict.js +13 -0
- package/dist/gates/settled-verdict.d.ts +8 -0
- package/dist/gates/settled-verdict.d.ts.map +1 -0
- package/dist/gates/settled-verdict.js +1 -0
- package/dist/gates/template-registry-coverage.d.ts +18 -0
- package/dist/gates/template-registry-coverage.d.ts.map +1 -0
- package/dist/gates/template-registry-coverage.js +24 -0
- package/dist/gates/unit-state-notes.d.ts +40 -0
- package/dist/gates/unit-state-notes.d.ts.map +1 -0
- package/dist/gates/unit-state-notes.js +71 -0
- package/dist/gates/verdict-line.d.ts +18 -0
- package/dist/gates/verdict-line.d.ts.map +1 -0
- package/dist/gates/verdict-line.js +40 -0
- package/dist/graph/graph-reuse-lookup.d.ts +10 -0
- package/dist/graph/graph-reuse-lookup.d.ts.map +1 -0
- package/dist/graph/graph-reuse-lookup.js +41 -0
- package/dist/graph/index-behind-hint.d.ts +11 -0
- package/dist/graph/index-behind-hint.d.ts.map +1 -0
- package/dist/graph/index-behind-hint.js +27 -0
- package/dist/knowledge/knowledge-stale-gate-flags.d.ts +3 -0
- package/dist/knowledge/knowledge-stale-gate-flags.d.ts.map +1 -0
- package/dist/knowledge/knowledge-stale-gate-flags.js +1 -0
- package/dist/knowledge/knowledge-stale-gate-input.d.ts +3 -0
- package/dist/knowledge/knowledge-stale-gate-input.d.ts.map +1 -0
- package/dist/knowledge/knowledge-stale-gate-input.js +1 -0
- package/dist/knowledge/knowledge-stale-gate-result.d.ts +3 -0
- package/dist/knowledge/knowledge-stale-gate-result.d.ts.map +1 -0
- package/dist/knowledge/knowledge-stale-gate-result.js +1 -0
- package/dist/knowledge/knowledge-stale-gate.d.ts +10 -0
- package/dist/knowledge/knowledge-stale-gate.d.ts.map +1 -0
- package/dist/knowledge/knowledge-stale-gate.js +9 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +204 -83
- package/dist/output/failure-hints.d.ts.map +1 -1
- package/dist/output/failure-hints.js +11 -9
- package/dist/output/rejected-entries-note.d.ts +57 -0
- package/dist/output/rejected-entries-note.d.ts.map +1 -0
- package/dist/output/rejected-entries-note.js +103 -0
- package/dist/output/stdout-is-pipe.d.ts +13 -0
- package/dist/output/stdout-is-pipe.d.ts.map +1 -0
- package/dist/output/stdout-is-pipe.js +21 -0
- package/dist/packs/stale-build-warning.d.ts +11 -0
- package/dist/packs/stale-build-warning.d.ts.map +1 -0
- package/dist/packs/stale-build-warning.js +23 -0
- package/dist/quality/run-quality.d.ts +123 -0
- package/dist/quality/run-quality.d.ts.map +1 -0
- package/dist/quality/run-quality.js +442 -0
- package/dist/schemas/json-schemas.d.ts +184 -3
- package/dist/schemas/json-schemas.d.ts.map +1 -1
- package/dist/schemas/json-schemas.js +113 -2
- package/dist/shrk.d.ts +3 -0
- package/dist/shrk.d.ts.map +1 -0
- package/dist/shrk.js +30 -0
- package/dist/surface/audience-applicability.d.ts +26 -0
- package/dist/surface/audience-applicability.d.ts.map +1 -0
- package/dist/surface/audience-applicability.js +60 -0
- package/dist/surface/catalog-command-safety.d.ts +18 -0
- package/dist/surface/catalog-command-safety.d.ts.map +1 -0
- package/dist/surface/catalog-command-safety.js +62 -0
- package/dist/surface/cli-command-resolver.d.ts +21 -0
- package/dist/surface/cli-command-resolver.d.ts.map +1 -0
- package/dist/surface/cli-command-resolver.js +87 -0
- package/dist/surface/command-dispatch-kind.d.ts +20 -0
- package/dist/surface/command-dispatch-kind.d.ts.map +1 -0
- package/dist/surface/command-dispatch-kind.js +20 -0
- package/dist/surface/command-index-entry.d.ts +40 -0
- package/dist/surface/command-index-entry.d.ts.map +1 -0
- package/dist/surface/command-index-entry.js +1 -0
- package/dist/surface/command-index.d.ts +77 -0
- package/dist/surface/command-index.d.ts.map +1 -0
- package/dist/surface/command-index.js +323 -0
- package/dist/surface/i-command-index.d.ts +22 -0
- package/dist/surface/i-command-index.d.ts.map +1 -0
- package/dist/surface/i-command-index.js +1 -0
- package/dist/surface/i-command-string-context.d.ts +20 -0
- package/dist/surface/i-command-string-context.d.ts.map +1 -0
- package/dist/surface/i-command-string-context.js +1 -0
- package/dist/surface/i-surface-denial.d.ts +13 -0
- package/dist/surface/i-surface-denial.d.ts.map +1 -0
- package/dist/surface/i-surface-denial.js +1 -0
- package/dist/surface/load-surface-context.d.ts +17 -1
- package/dist/surface/load-surface-context.d.ts.map +1 -1
- package/dist/surface/load-surface-context.js +48 -10
- package/dist/surface/not-enabled-error.d.ts +38 -4
- package/dist/surface/not-enabled-error.d.ts.map +1 -1
- package/dist/surface/not-enabled-error.js +96 -6
- package/dist/surface/profiles.d.ts +7 -0
- package/dist/surface/profiles.d.ts.map +1 -1
- package/dist/surface/resolve-command-string.d.ts +10 -0
- package/dist/surface/resolve-command-string.d.ts.map +1 -0
- package/dist/surface/resolve-command-string.js +572 -0
- package/dist/surface/surface-config-writer.d.ts +7 -2
- package/dist/surface/surface-config-writer.d.ts.map +1 -1
- package/dist/surface/surface-config-writer.js +25 -6
- package/dist/surface/surface-layer.d.ts +11 -0
- package/dist/surface/surface-layer.d.ts.map +1 -0
- package/dist/surface/surface-layer.js +11 -0
- package/dist/surface/surface-refusal-reason.d.ts +16 -0
- package/dist/surface/surface-refusal-reason.d.ts.map +1 -0
- package/dist/surface/surface-refusal-reason.js +16 -0
- package/dist/surface/surface-selector.d.ts +26 -0
- package/dist/surface/surface-selector.d.ts.map +1 -0
- package/dist/surface/surface-selector.js +42 -0
- package/dist/surface/surface-summary.d.ts +61 -18
- package/dist/surface/surface-summary.d.ts.map +1 -1
- package/dist/surface/surface-summary.js +147 -60
- package/dist/surface/tier.d.ts +85 -22
- package/dist/surface/tier.d.ts.map +1 -1
- package/dist/surface/tier.js +132 -30
- package/dist/usage/usage-log.d.ts +6 -1
- package/dist/usage/usage-log.d.ts.map +1 -1
- package/dist/usage/usage-log.js +7 -2
- package/dist/validation/run-validation-loop.d.ts +9 -0
- package/dist/validation/run-validation-loop.d.ts.map +1 -1
- package/dist/validation/run-validation-loop.js +14 -11
- package/dist/validation/typecheck-emitted.d.ts +8 -9
- package/dist/validation/typecheck-emitted.d.ts.map +1 -1
- package/dist/validation/typecheck-emitted.js +17 -97
- package/package.json +34 -34
|
@@ -1,80 +1,227 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { referencedExtractorIds, RuleEmptiness, ruleAssertsEmptyOutput, selectorUnitFails, settleRuleEmptiness, settleUnitLiveness, unitStateLists, UnitLivenessState, } from '@shrkcrft/core';
|
|
2
|
+
import { dotDirsNamedBy, globListLivenessInput, globListSelects, inspectSource, readGlobListUnits, readScopeCoverage, readScopeHasUnread, runPolicyLint, runWiring, scanGeneratedFiles, sourceLivenessRequest, walkMatching, withFileReadCache, wiringSourceSide, } from '@shrkcrft/boundaries';
|
|
3
|
+
import { gateRuleLabeledSources, gateRuleSources } from "./gate-rule-globs.js";
|
|
4
|
+
import { checkDocReferences } from '@shrkcrft/inspector';
|
|
5
|
+
import { buildGateEnvelope } from "./gate-envelope.js";
|
|
6
|
+
import { evaluateSelfTest } from "./self-test.js";
|
|
7
|
+
import { measureRegistrationRoles } from "./measure-registration-roles.js";
|
|
8
|
+
import { baselineLivenessRequest } from "../commands/baseline.command.js";
|
|
9
|
+
import { ExitCode } from "../exit-codes.js";
|
|
2
10
|
export const GATE_COVERAGE_SCHEMA = 'sharkcraft.gate-coverage/v1';
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Why a rule its own negations emptied matched nothing — worded into its
|
|
13
|
+
* coverage reason and its envelope `skipReason`, never the "probably stale" of
|
|
14
|
+
* a selector that matched nothing at all.
|
|
15
|
+
*/
|
|
16
|
+
const EMPTIED_BY_NEGATIONS = 'its own negations exclude every file its inclusion globs select';
|
|
17
|
+
/** Why a rule that matched nothing proves nothing, in the words every coverage row prints. */
|
|
18
|
+
const STALE_SELECTOR = 'matched nothing — the selector is probably stale';
|
|
19
|
+
/** A source inspection's read scope, when it left a matched file unread. */
|
|
20
|
+
function inspectionReadScope(insp) {
|
|
21
|
+
return insp.unread.length > 0 ? { readScope: { read: insp.filesScanned, unread: insp.unread } } : {};
|
|
22
|
+
}
|
|
23
|
+
/** How a report names one extraction source: `a/*.ts, b/*.ts (regex-capture)`. */
|
|
24
|
+
function describeSource(src) {
|
|
25
|
+
const kind = src.extract ??
|
|
26
|
+
(src.pattern !== undefined ? 'regex-capture' : src.arrayProperty !== undefined ? 'array-members' : 'extractor');
|
|
27
|
+
const files = (src.files ?? []).join(', ') || '(no files)';
|
|
28
|
+
return `${files} (${kind}${src.$use ? `, via $use:${src.$use}` : ''})`;
|
|
29
|
+
}
|
|
30
|
+
/** ONE rule-level glob list as the settle reads it, judged off the one reader's walk (memoised under the coverage window). */
|
|
31
|
+
function ruleList(cwd, list, globs, excludeDirs, allowDotDirs) {
|
|
32
|
+
return { list, globs, units: readGlobListUnits(cwd, globs, new Set(excludeDirs), allowDotDirs) };
|
|
33
|
+
}
|
|
34
|
+
/** The labelled-sources request of a source-reading rule (wiring, registry, registration). */
|
|
35
|
+
function sourcesRequest(cwd, view, excludeDirs) {
|
|
36
|
+
return sourceLivenessRequest(cwd, gateRuleLabeledSources(view), excludeDirs, view.id);
|
|
22
37
|
}
|
|
23
|
-
function matchWiring(cwd, rule, excludeDirs) {
|
|
38
|
+
function matchWiring(cwd, view, rule, excludeDirs) {
|
|
24
39
|
const side = wiringSourceSide(rule);
|
|
40
|
+
const sideLabel = rule.chain && rule.chain.length > 0 ? 'chain[0]' : 'declared';
|
|
41
|
+
const base = {
|
|
42
|
+
unitLabel: 'ids',
|
|
43
|
+
idLabel: 'declared tokens',
|
|
44
|
+
consulted: side
|
|
45
|
+
? `wiring rule "${rule.id}" — ${sideLabel} ${describeSource(side)}`
|
|
46
|
+
: `wiring rule "${rule.id}"`,
|
|
47
|
+
liveness: sourcesRequest(cwd, view, excludeDirs),
|
|
48
|
+
primaryLists: [`${sideLabel}.files`],
|
|
49
|
+
};
|
|
25
50
|
if (!side)
|
|
26
|
-
return { filesMatched: 0, unitsMatched: 0,
|
|
51
|
+
return { ...base, filesMatched: 0, unitsMatched: 0, ids: [], error: 'rule sets no source side' };
|
|
27
52
|
const insp = inspectSource(cwd, side, excludeDirs);
|
|
53
|
+
// The REGISTERED side too, through the same evaluator `check wiring` and
|
|
54
|
+
// `gates check` run. A subset rule whose declared selector never produced a
|
|
55
|
+
// registered member is connected — but only partially — and coverage must
|
|
56
|
+
// agree with the check about that, so it asks the check instead of
|
|
57
|
+
// re-deriving the set difference here. (An intended-empty rule's engine
|
|
58
|
+
// record IS its acceptance.)
|
|
59
|
+
const evaluated = insp.error === undefined ? runWiring(cwd, [rule], { excludeDirs }).rules[0] : undefined;
|
|
28
60
|
return {
|
|
61
|
+
...base,
|
|
29
62
|
filesMatched: insp.filesScanned,
|
|
30
63
|
unitsMatched: insp.ids.length,
|
|
31
|
-
unitLabel: 'ids',
|
|
32
64
|
ids: insp.ids,
|
|
65
|
+
...(side.$use ? { viaExtractor: side.$use } : {}),
|
|
33
66
|
...(insp.error ? { error: insp.error } : {}),
|
|
67
|
+
...(insp.hint ? { hint: insp.hint } : {}),
|
|
68
|
+
...(evaluated ? { coverage: evaluated.coverage } : {}),
|
|
69
|
+
...inspectionReadScope(insp),
|
|
34
70
|
};
|
|
35
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* A policy rule's "ids" are its PATTERN MATCHES, exactly as the engine reports
|
|
74
|
+
* each hit: capture group 1 when the pattern has one, else the whole match
|
|
75
|
+
* (whitespace-collapsed, at most 120 chars).
|
|
76
|
+
*
|
|
77
|
+
* Findings AND hits an exemption (`exemptFiles` / `exemptLines`) let through
|
|
78
|
+
* both count — an exempted fixture file is real code the author deliberately
|
|
79
|
+
* allowed, and it is the only liveness pin a policy rule can have ("the
|
|
80
|
+
* forbidden pattern still bites"). A hit the rule's OWN `scan` zone dropped
|
|
81
|
+
* does not count: the zone says that text is prose or a string, and letting it
|
|
82
|
+
* satisfy `expectIds` would be the false signal zones exist to remove.
|
|
83
|
+
*
|
|
84
|
+
* `unitsMatched` stays the content units scanned, so a clean rule with zero
|
|
85
|
+
* hits is still connected (`ok`), not `empty`.
|
|
86
|
+
*/
|
|
36
87
|
function matchPolicy(cwd, rule, excludeDirs) {
|
|
37
88
|
const report = runPolicyLint(cwd, [rule], { excludeDirs });
|
|
38
89
|
const result = report.rules[0];
|
|
90
|
+
// Hits an exemption let through: the fixtures the author deliberately kept.
|
|
91
|
+
// These are the only ids a scaffolded selfTest may pin (see IGateCoverage.pinIds).
|
|
92
|
+
const exempted = report.suppressed
|
|
93
|
+
.filter((s) => s.ruleId === rule.id && (s.via === 'exemptFiles' || s.via === 'exemptLines'))
|
|
94
|
+
.map((s) => s.match);
|
|
95
|
+
const ids = [
|
|
96
|
+
...new Set([
|
|
97
|
+
...report.findings.filter((f) => f.ruleId === rule.id).map((f) => f.match),
|
|
98
|
+
...report.suppressed
|
|
99
|
+
.filter((s) => s.ruleId === rule.id && s.via !== 'scanZone')
|
|
100
|
+
.map((s) => s.match),
|
|
101
|
+
]),
|
|
102
|
+
].sort();
|
|
103
|
+
const own = rule.files ?? [];
|
|
39
104
|
return {
|
|
40
105
|
// A policy rule's "files" and "units" differ only for inline templates.
|
|
41
106
|
filesMatched: result?.unitsScanned ?? 0,
|
|
42
107
|
unitsMatched: result?.unitsScanned ?? 0,
|
|
43
108
|
unitLabel: 'content units',
|
|
44
|
-
|
|
109
|
+
idLabel: 'pattern matches (capture group 1, else the whole match — findings plus exempted hits)',
|
|
110
|
+
consulted: `policy rule "${rule.id}" — /${rule.pattern}/${rule.flags ?? ''} over ` +
|
|
111
|
+
(own.length > 0 ? own.join(', ') : `the ${rule.surface} surface's default globs`),
|
|
112
|
+
ids,
|
|
113
|
+
pinIds: [...new Set(exempted)].sort(),
|
|
114
|
+
// Only the author's own `files[]` is a selector anyone wrote (a surface's
|
|
115
|
+
// default globs are not judged) — the list `runPolicyLint` settles too.
|
|
116
|
+
liveness: {
|
|
117
|
+
subject: rule.id,
|
|
118
|
+
lists: own.length > 0 ? [ruleList(cwd, 'files', own, excludeDirs)] : [],
|
|
119
|
+
marks: rule.expectEmptyUnits ?? [],
|
|
120
|
+
},
|
|
121
|
+
primaryLists: own.length > 0 ? ['files'] : [],
|
|
45
122
|
...(result?.error ? { error: result.error } : {}),
|
|
123
|
+
// The ENGINE's own record, the one `policy-lint` / `gates check` settle on
|
|
124
|
+
// (it names any matched file the reader left unread), never re-derived.
|
|
125
|
+
...(result ? { coverage: result.coverage } : {}),
|
|
126
|
+
// A rule with an unread file carries the file record, whose `examined` is
|
|
127
|
+
// the read count.
|
|
128
|
+
...(result?.unread ? { readScope: { read: result.coverage.examined, unread: result.unread } } : {}),
|
|
46
129
|
};
|
|
47
130
|
}
|
|
48
|
-
function matchRegistry(cwd, decl, excludeDirs) {
|
|
131
|
+
function matchRegistry(cwd, view, decl, excludeDirs) {
|
|
49
132
|
const insp = inspectSource(cwd, decl.source, excludeDirs);
|
|
50
133
|
return {
|
|
51
134
|
filesMatched: insp.filesScanned,
|
|
52
135
|
unitsMatched: insp.ids.length,
|
|
53
136
|
unitLabel: 'ids',
|
|
137
|
+
idLabel: 'registry ids',
|
|
138
|
+
consulted: `registry "${decl.name}" — source ${describeSource(decl.source)}`,
|
|
54
139
|
ids: insp.ids,
|
|
140
|
+
liveness: sourcesRequest(cwd, view, excludeDirs),
|
|
141
|
+
primaryLists: ['source.files'],
|
|
142
|
+
...(decl.source.$use ? { viaExtractor: decl.source.$use } : {}),
|
|
55
143
|
...(insp.error ? { error: insp.error } : {}),
|
|
144
|
+
...(insp.hint ? { hint: insp.hint } : {}),
|
|
145
|
+
...inspectionReadScope(insp),
|
|
56
146
|
};
|
|
57
147
|
}
|
|
58
|
-
function matchRegistration(cwd, idiom, excludeDirs) {
|
|
59
|
-
|
|
148
|
+
function matchRegistration(cwd, view, idiom, excludeDirs) {
|
|
149
|
+
// The ONE per-role measurement `gates check` reads too. Its empty is the
|
|
150
|
+
// declared role's (the idiom's primary selector), and its coverage names
|
|
151
|
+
// every role that examined nothing — an intended-empty role rides on the
|
|
152
|
+
// acceptance instead. So the two verbs agree on "empty", on "partial" and on
|
|
153
|
+
// "accepted" by construction, not by coincidence.
|
|
154
|
+
const roles = measureRegistrationRoles(cwd, idiom, excludeDirs);
|
|
155
|
+
const insp = roles.declared;
|
|
60
156
|
return {
|
|
61
157
|
filesMatched: insp.filesScanned,
|
|
62
158
|
unitsMatched: insp.ids.length,
|
|
63
159
|
unitLabel: 'declared tokens',
|
|
160
|
+
idLabel: 'declared tokens',
|
|
161
|
+
consulted: `registration idiom "${idiom.name}" — declared ${describeSource(idiom.declared)}`,
|
|
64
162
|
ids: insp.ids,
|
|
65
|
-
|
|
163
|
+
liveness: sourcesRequest(cwd, view, excludeDirs),
|
|
164
|
+
primaryLists: ['declared.files'],
|
|
165
|
+
coverage: roles.coverage,
|
|
166
|
+
...(idiom.declared.$use ? { viaExtractor: idiom.declared.$use } : {}),
|
|
167
|
+
// Only the PRIMARY side's error makes the rule misconfigured here, as on
|
|
168
|
+
// the wiring plane. A provided/consumed error is an unexamined role in
|
|
169
|
+
// `roles.coverage`.
|
|
170
|
+
...(roles.roleErrors.declared !== undefined ? { error: roles.roleErrors.declared } : {}),
|
|
171
|
+
...(insp.hint ? { hint: insp.hint } : {}),
|
|
172
|
+
...inspectionReadScope(insp),
|
|
66
173
|
};
|
|
67
174
|
}
|
|
68
175
|
function matchBaseline(cwd, rule, excludeDirs) {
|
|
176
|
+
// THE input request `baseline check` settles too (compute.source + watchFiles).
|
|
177
|
+
const built = baselineLivenessRequest(cwd, rule, excludeDirs);
|
|
69
178
|
// Only the EXTRACTOR half can be inspected without spawning. A command
|
|
70
179
|
// compute is reported honestly as un-inspectable rather than guessed at —
|
|
71
180
|
// `shrk baseline explain --id X` runs it on purpose.
|
|
72
181
|
if (rule.compute.kind !== 'extractor' || !rule.compute.source) {
|
|
182
|
+
// ...but its INPUTS can still be probed. `watchFiles` names the files that
|
|
183
|
+
// feed the command, so globbing them (never spawning) answers the one
|
|
184
|
+
// question the trust layer otherwise cannot: is this rule still connected
|
|
185
|
+
// to the repo at all? A command baseline whose watchFiles point at a moved
|
|
186
|
+
// directory is indistinguishable from a healthy one without this.
|
|
187
|
+
const watch = rule.watchFiles ?? [];
|
|
188
|
+
if (watch.length === 0) {
|
|
189
|
+
return {
|
|
190
|
+
filesMatched: 0,
|
|
191
|
+
unitsMatched: 0,
|
|
192
|
+
unitLabel: 'entries (command compute — not inspected; add `watchFiles` to enable the probe)',
|
|
193
|
+
idLabel: 'entries',
|
|
194
|
+
consulted: `baseline "${rule.id}" — a \`command\` compute (never run by coverage)`,
|
|
195
|
+
ids: [],
|
|
196
|
+
// A selfTest here asserts on a set nothing can produce without
|
|
197
|
+
// spawning the command. Report that instead of a fake "got 0" that
|
|
198
|
+
// would keep the rule red forever.
|
|
199
|
+
notEvaluable: 'a `command` baseline is never run by coverage, and this one declares no `watchFiles` to probe — add `watchFiles` (then the selfTest counts watchFiles paths)',
|
|
200
|
+
liveness: built.request,
|
|
201
|
+
primaryLists: [],
|
|
202
|
+
inspectable: false,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
// The probe walks the POSITIVE set (inclusion globs), then selects through
|
|
206
|
+
// the list — a `!` in watchFiles excludes. EVERY probed path, sorted:
|
|
207
|
+
// `expectIds` may name any watched file, not just whichever five the walk
|
|
208
|
+
// happened to visit first. The one dead-unit decision judges the globs (in
|
|
209
|
+
// the request above), and a directory the walk could not list is an unread
|
|
210
|
+
// entry for it (a glob that may match beneath one is not dead).
|
|
211
|
+
const walked = walkMatching(cwd, watch, new Set(excludeDirs), new Set());
|
|
212
|
+
const probed = walked.filter((p) => globListSelects(p, watch)).sort();
|
|
73
213
|
return {
|
|
74
|
-
filesMatched:
|
|
75
|
-
unitsMatched:
|
|
76
|
-
|
|
77
|
-
|
|
214
|
+
filesMatched: probed.length,
|
|
215
|
+
unitsMatched: probed.length,
|
|
216
|
+
// A zero here is a REAL empty (stale watchFiles), so the label must not
|
|
217
|
+
// carry the "not inspected" marker that suppresses the empty verdict.
|
|
218
|
+
unitLabel: 'watchFiles input(s) (compute unverified — command never run)',
|
|
219
|
+
idLabel: 'watchFiles paths',
|
|
220
|
+
consulted: `baseline "${rule.id}" — watchFiles ${watch.join(', ')} (probed; the command is never run)`,
|
|
221
|
+
ids: probed,
|
|
222
|
+
liveness: built.request,
|
|
223
|
+
// The probe IS this rule's match in coverage: its watchFiles is primary.
|
|
224
|
+
primaryLists: ['watchFiles'],
|
|
78
225
|
};
|
|
79
226
|
}
|
|
80
227
|
const insp = inspectSource(cwd, rule.compute.source, excludeDirs);
|
|
@@ -82,18 +229,72 @@ function matchBaseline(cwd, rule, excludeDirs) {
|
|
|
82
229
|
filesMatched: insp.filesScanned,
|
|
83
230
|
unitsMatched: insp.ids.length,
|
|
84
231
|
unitLabel: 'entries',
|
|
232
|
+
idLabel: 'entries',
|
|
233
|
+
consulted: `baseline "${rule.id}" — compute.source ${describeSource(rule.compute.source)}`,
|
|
85
234
|
ids: insp.ids,
|
|
235
|
+
liveness: built.request,
|
|
236
|
+
primaryLists: built.primaryLists,
|
|
237
|
+
...(rule.compute.source.$use ? { viaExtractor: rule.compute.source.$use } : {}),
|
|
86
238
|
...(insp.error ? { error: insp.error } : {}),
|
|
239
|
+
...(insp.hint ? { hint: insp.hint } : {}),
|
|
240
|
+
...inspectionReadScope(insp),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* A doc-reference rule's "match" is how many id-shaped TOKENS it validated.
|
|
245
|
+
*
|
|
246
|
+
* Files alone would lie: a rule whose globs match 40 docs but whose
|
|
247
|
+
* `requireContext` gate rejects every token is enforcing nothing, and coverage
|
|
248
|
+
* exists precisely to make that visible.
|
|
249
|
+
*/
|
|
250
|
+
function matchDocReference(cwd, rule, inspection, excludeDirs) {
|
|
251
|
+
const res = checkDocReferences(cwd, rule, inspection, excludeDirs);
|
|
252
|
+
return {
|
|
253
|
+
filesMatched: res.filesScanned,
|
|
254
|
+
unitsMatched: res.tokensChecked,
|
|
255
|
+
unitLabel: 'doc reference(s)',
|
|
256
|
+
idLabel: 'validated doc-reference tokens',
|
|
257
|
+
consulted: docReferenceConsulted(rule),
|
|
258
|
+
ids: [...new Set(res.tokens.filter((t) => t.skipped === undefined).map((t) => t.token))].sort(),
|
|
259
|
+
// The rule's `files` judged per unit off the SAME walk the check reads (its
|
|
260
|
+
// dot-dirs included; a memo hit under `withFileReadCache`): a live negation
|
|
261
|
+
// is printed with what it excludes, a dead glob or a `!` excluding nothing
|
|
262
|
+
// is a dead unit — as on every other plane.
|
|
263
|
+
liveness: {
|
|
264
|
+
subject: rule.id,
|
|
265
|
+
lists: [ruleList(cwd, 'files', rule.files, excludeDirs, dotDirsNamedBy(rule.files))],
|
|
266
|
+
marks: rule.expectEmptyUnits ?? [],
|
|
267
|
+
},
|
|
268
|
+
primaryLists: ['files'],
|
|
269
|
+
...(res.error ? { error: res.error } : {}),
|
|
270
|
+
...(res.readScope ? { readScope: res.readScope } : {}),
|
|
87
271
|
};
|
|
88
272
|
}
|
|
273
|
+
function docReferenceConsulted(rule) {
|
|
274
|
+
return (`doc-reference rule "${rule.id}" — /${rule.tokenPattern}/${rule.tokenPatternFlags ?? ''} over ${rule.files.join(', ')}, ` +
|
|
275
|
+
`resolved as ${rule.resolvesAs.join(' | ')}`);
|
|
276
|
+
}
|
|
89
277
|
function matchGenerated(cwd, rule, excludeDirs) {
|
|
90
278
|
const scan = scanGeneratedFiles(cwd, rule, excludeDirs);
|
|
91
279
|
const files = [...scan.generated.keys()];
|
|
280
|
+
// `generatedGlob` judged per unit off the walk `scanGeneratedFiles` just
|
|
281
|
+
// read (a memo hit). `sources[].glob`, `outsideGlob` and `handMaintained`
|
|
282
|
+
// are not judged here: the writers partition the generated set (`unclassified`
|
|
283
|
+
// reports a gap), and a stale bless has its own finding.
|
|
92
284
|
return {
|
|
93
285
|
filesMatched: files.length,
|
|
94
286
|
unitsMatched: files.length,
|
|
95
287
|
unitLabel: 'generated files',
|
|
288
|
+
idLabel: 'generated file paths',
|
|
289
|
+
consulted: `generated artifact "${rule.id}" — ${rule.generatedGlob.join(', ')}`,
|
|
96
290
|
ids: files,
|
|
291
|
+
liveness: {
|
|
292
|
+
subject: rule.id,
|
|
293
|
+
lists: [ruleList(cwd, 'generatedGlob', rule.generatedGlob, excludeDirs)],
|
|
294
|
+
marks: rule.expectEmptyUnits ?? [],
|
|
295
|
+
},
|
|
296
|
+
primaryLists: ['generatedGlob'],
|
|
297
|
+
...(readScopeHasUnread(scan.readScope) ? { readScope: scan.readScope } : {}),
|
|
97
298
|
};
|
|
98
299
|
}
|
|
99
300
|
/**
|
|
@@ -103,53 +304,242 @@ function matchGenerated(cwd, rule, excludeDirs) {
|
|
|
103
304
|
* without side effects; it is reported as un-inspected (never as `empty`), so
|
|
104
305
|
* the report never claims a fact it did not check.
|
|
105
306
|
*/
|
|
106
|
-
export function buildGateCoverage(cwd, rules, excludeDirs = []) {
|
|
307
|
+
export function buildGateCoverage(cwd, rules, excludeDirs = [], extractors = {}, includeAllIds = false, inspection) {
|
|
308
|
+
// Safe to memo the tree reads for exactly this call: coverage NEVER spawns
|
|
309
|
+
// (the `command` baseline is probed, not run) and never writes, so nothing
|
|
310
|
+
// can change the tree between the first rule's scan and the last one's.
|
|
311
|
+
return withFileReadCache(() => buildGateCoverageUncached(cwd, rules, excludeDirs, extractors, includeAllIds, inspection));
|
|
312
|
+
}
|
|
313
|
+
function buildGateCoverageUncached(cwd, rules, excludeDirs, extractors, includeAllIds, inspection) {
|
|
107
314
|
const out = [];
|
|
108
315
|
for (const view of rules) {
|
|
109
316
|
let match;
|
|
110
317
|
switch (view.plane) {
|
|
111
318
|
case 'wiring':
|
|
112
|
-
match = matchWiring(cwd, view.raw, excludeDirs);
|
|
319
|
+
match = matchWiring(cwd, view, view.raw, excludeDirs);
|
|
113
320
|
break;
|
|
114
321
|
case 'policy':
|
|
115
322
|
match = matchPolicy(cwd, view.raw, excludeDirs);
|
|
116
323
|
break;
|
|
117
324
|
case 'registry':
|
|
118
|
-
match = matchRegistry(cwd, view.raw, excludeDirs);
|
|
325
|
+
match = matchRegistry(cwd, view, view.raw, excludeDirs);
|
|
119
326
|
break;
|
|
120
327
|
case 'registration':
|
|
121
|
-
match = matchRegistration(cwd, view.raw, excludeDirs);
|
|
328
|
+
match = matchRegistration(cwd, view, view.raw, excludeDirs);
|
|
122
329
|
break;
|
|
123
330
|
case 'baseline':
|
|
124
331
|
match = matchBaseline(cwd, view.raw, excludeDirs);
|
|
125
332
|
break;
|
|
333
|
+
case 'doc-reference': {
|
|
334
|
+
// The inspection is only built when this plane is actually present, so
|
|
335
|
+
// a repo without it never pays for the registries.
|
|
336
|
+
const rule = view.raw;
|
|
337
|
+
match = inspection
|
|
338
|
+
? matchDocReference(cwd, rule, inspection, excludeDirs)
|
|
339
|
+
: {
|
|
340
|
+
filesMatched: 0,
|
|
341
|
+
unitsMatched: 0,
|
|
342
|
+
unitLabel: 'doc reference(s) (registries not loaded — not inspected)',
|
|
343
|
+
idLabel: 'validated doc-reference tokens',
|
|
344
|
+
consulted: docReferenceConsulted(rule),
|
|
345
|
+
ids: [],
|
|
346
|
+
notEvaluable: 'the registries a doc reference resolves against were not loaded',
|
|
347
|
+
liveness: { subject: rule.id, lists: [], marks: [] },
|
|
348
|
+
primaryLists: [],
|
|
349
|
+
inspectable: false,
|
|
350
|
+
};
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
126
353
|
default:
|
|
127
354
|
match = matchGenerated(cwd, view.raw, excludeDirs);
|
|
128
355
|
break;
|
|
129
356
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
357
|
+
// ONE evaluator for every plane (and for `gates try`). A selector that
|
|
358
|
+
// could not run has no extracted set, so its expectations are unmeasured —
|
|
359
|
+
// reported as such, never as a fabricated "got 0".
|
|
360
|
+
const checks = evaluateSelfTest(view.selfTest, match.error !== undefined && match.notEvaluable === undefined
|
|
361
|
+
? { ...match, notEvaluable: `the selector could not run (${match.error})` }
|
|
362
|
+
: match);
|
|
363
|
+
const failedChecks = checks.filter((c) => c.status === 'failed');
|
|
364
|
+
const unevaluable = checks.filter((c) => c.status === 'not-evaluable');
|
|
365
|
+
const expectationFailures = failedChecks.map((c) => c.message);
|
|
366
|
+
// A selfTest field this plane shape can never evaluate is a misconfigured
|
|
367
|
+
// rule (it can never pass), so it surfaces as the rule's error.
|
|
368
|
+
const error = match.error ?? (unevaluable.length > 0 ? unevaluable.map((c) => c.message).join('; ') : undefined);
|
|
369
|
+
// A structured flag, never a substring of the human label: the quality
|
|
370
|
+
// bundle reads the same fact to settle such a rule on its check's coverage.
|
|
371
|
+
const uninspected = match.inspectable === false;
|
|
372
|
+
// THE gate-plane glob settle (round 13): core's `settleUnitLiveness` over
|
|
373
|
+
// THE observation predicate (`globListLivenessInput`) and every list the
|
|
374
|
+
// rule reads, with its `expectEmpty` markers — the input each plane engine
|
|
375
|
+
// builds too, so `gates coverage`, `gates try`, `quality` and every plane
|
|
376
|
+
// verb judge one glob alike. `settled.dead` is the UNMARKED dead units
|
|
377
|
+
// only; a marked glob is intended-empty (record B) or went-live.
|
|
378
|
+
const settled = settleUnitLiveness(globListLivenessInput(match.liveness));
|
|
379
|
+
const lists = match.liveness.lists;
|
|
380
|
+
const primaryList = lists.find((l) => match.primaryLists.includes(l.list));
|
|
381
|
+
const labelOf = (l, glob) => (l.label !== undefined ? `${l.label}: ${glob}` : glob);
|
|
382
|
+
const negations = lists.flatMap((l) => l.units.negations.map((n) => ({ selector: labelOf(l, n.glob), excludes: n.excludes })));
|
|
383
|
+
const excludedByNegations = primaryList !== undefined && primaryList.units.allExcluded
|
|
384
|
+
? primaryList.units.negations.map((n) => ({ selector: labelOf(primaryList, n.glob), excludes: n.excludes }))
|
|
385
|
+
: undefined;
|
|
386
|
+
const deadGlobUnits = settled.dead.map((u) => ({
|
|
387
|
+
selector: u.label,
|
|
388
|
+
glob: u.unit,
|
|
389
|
+
negation: u.unit.startsWith('!'),
|
|
390
|
+
reason: u.deadReason ?? 'matched 0 files',
|
|
391
|
+
}));
|
|
392
|
+
// A selector that matched a file the reader could not read matched
|
|
393
|
+
// something: it is not stale, so it is never `empty` (and a failOnEmpty
|
|
394
|
+
// rule never FAILS on it). Its coverage names the unread file instead.
|
|
395
|
+
const matchedUnread = readScopeHasUnread(match.readScope);
|
|
396
|
+
// THE rule-emptiness settle (round 13) — the one call that replaces the
|
|
397
|
+
// three `expectEmpty` consults: a FENCE's asserted empty set over live
|
|
398
|
+
// inputs (`ruleAssertsEmptyOutput`), a rule whose every primary inclusion
|
|
399
|
+
// glob is intended-empty and matched no file, or the loud skip. A fence
|
|
400
|
+
// over a DEAD input is stale, never accepted; 0 units out of live files is
|
|
401
|
+
// never assertable.
|
|
402
|
+
const emptiness = settleRuleEmptiness({
|
|
403
|
+
subject: view.id,
|
|
404
|
+
unitLabel: match.unitLabel,
|
|
405
|
+
filesMatched: match.filesMatched,
|
|
406
|
+
unitsMatched: match.unitsMatched,
|
|
407
|
+
unread: matchedUnread,
|
|
408
|
+
emptiedByNegations: excludedByNegations !== undefined,
|
|
409
|
+
emptiedReason: `matched nothing — ${EMPTIED_BY_NEGATIONS}`,
|
|
410
|
+
liveness: settled,
|
|
411
|
+
primaryLists: match.primaryLists,
|
|
412
|
+
assertsEmptyOutput: ruleAssertsEmptyOutput(view),
|
|
413
|
+
failOnEmpty: view.failOnEmpty,
|
|
414
|
+
noFilesReason: STALE_SELECTOR,
|
|
415
|
+
noUnitsReason: STALE_SELECTOR,
|
|
416
|
+
});
|
|
417
|
+
const accepted = emptiness.state === RuleEmptiness.AssertedEmptyOutput || emptiness.state === RuleEmptiness.IntendedEmpty;
|
|
418
|
+
const status = error !== undefined
|
|
133
419
|
? 'error'
|
|
134
|
-
:
|
|
420
|
+
: failedChecks.length > 0
|
|
135
421
|
? 'failed-expectation'
|
|
136
|
-
:
|
|
422
|
+
: !uninspected && emptiness.skipped
|
|
137
423
|
? 'empty'
|
|
138
424
|
: 'ok';
|
|
425
|
+
// The scope this coverage run could actually see. A plane whose engine
|
|
426
|
+
// knows more supplies its own record (wiring, policy, registration — an
|
|
427
|
+
// intended-empty rule's record IS its acceptance); an accepted empty is the
|
|
428
|
+
// settle's own record; a rule coverage could not inspect examined nothing
|
|
429
|
+
// — it is never reported "connected" on faith. Every other plane's record
|
|
430
|
+
// folds the reader's unread files through the one rule, `readScopeCoverage`.
|
|
431
|
+
const coverage = match.coverage ??
|
|
432
|
+
readScopeCoverage(uninspected
|
|
433
|
+
? {
|
|
434
|
+
unit: 'inspectable inputs',
|
|
435
|
+
expected: 1,
|
|
436
|
+
examined: 0,
|
|
437
|
+
reason: `not inspected — ${match.unitLabel}`,
|
|
438
|
+
}
|
|
439
|
+
: (emptiness.coverage ?? {
|
|
440
|
+
unit: match.unitLabel,
|
|
441
|
+
expected: match.unitsMatched,
|
|
442
|
+
examined: match.unitsMatched,
|
|
443
|
+
...(match.unitsMatched === 0
|
|
444
|
+
? {
|
|
445
|
+
// A rule that could not RUN is misconfigured, not stale:
|
|
446
|
+
// its zero is no evidence about the selector at all
|
|
447
|
+
// (round 12 review, R12-X3).
|
|
448
|
+
reason: error !== undefined
|
|
449
|
+
? 'NOT evaluated — the rule is misconfigured (see its error)'
|
|
450
|
+
: (emptiness.skipReason ?? STALE_SELECTOR),
|
|
451
|
+
}
|
|
452
|
+
: {}),
|
|
453
|
+
}), match.readScope);
|
|
454
|
+
const nonLive = settled.units.filter((u) => u.state !== UnitLivenessState.Live);
|
|
139
455
|
out.push({
|
|
140
456
|
id: view.id,
|
|
141
457
|
plane: view.plane,
|
|
142
458
|
...(view.description ? { description: view.description } : {}),
|
|
143
459
|
status,
|
|
460
|
+
coverage,
|
|
461
|
+
...(settled.acceptance !== undefined ? { unitAcceptance: settled.acceptance } : {}),
|
|
462
|
+
...(settled.dead.length + settled.intendedEmpty.length + settled.wentLive.length > 0
|
|
463
|
+
? { units: unitStateLists(settled) }
|
|
464
|
+
: {}),
|
|
465
|
+
...(nonLive.length > 0 ? { unitLiveness: nonLive } : {}),
|
|
466
|
+
...(emptiness.state !== RuleEmptiness.Matched ? { emptiness: emptiness.state } : {}),
|
|
467
|
+
...(emptiness.cause === 'dead-input' && emptiness.skipReason !== undefined
|
|
468
|
+
? { emptyReason: emptiness.skipReason }
|
|
469
|
+
: {}),
|
|
144
470
|
filesMatched: match.filesMatched,
|
|
145
471
|
unitsMatched: match.unitsMatched,
|
|
146
|
-
unitLabel:
|
|
472
|
+
unitLabel: emptiness.state === RuleEmptiness.AssertedEmptyOutput
|
|
473
|
+
? `${match.unitLabel} (empty — the asserted state)`
|
|
474
|
+
: emptiness.state === RuleEmptiness.IntendedEmpty
|
|
475
|
+
? `${match.unitLabel} (empty — asserted by expectEmpty)`
|
|
476
|
+
: match.unitLabel,
|
|
477
|
+
idLabel: match.idLabel,
|
|
478
|
+
consulted: match.consulted,
|
|
147
479
|
sampleIds: match.ids.slice(0, 5),
|
|
480
|
+
...(includeAllIds ? { allIds: match.ids } : {}),
|
|
481
|
+
...(match.pinIds !== undefined ? { pinIds: match.pinIds } : {}),
|
|
482
|
+
...(uninspected ? { inspectable: false } : {}),
|
|
148
483
|
failOnEmpty: view.failOnEmpty,
|
|
149
|
-
...(
|
|
484
|
+
...(error !== undefined ? { error } : {}),
|
|
485
|
+
// A diagnosis of a probably-unintended zero (the import-edges barrel
|
|
486
|
+
// hint) is never printed over an ACCEPTED empty: it would invite the
|
|
487
|
+
// author to "fix" a correct fence.
|
|
488
|
+
...(match.hint && !accepted ? { hint: match.hint } : {}),
|
|
489
|
+
...(match.viaExtractor ? { viaExtractor: match.viaExtractor } : {}),
|
|
150
490
|
expectationFailures,
|
|
491
|
+
...(checks.length > 0 ? { selfTestChecks: checks } : {}),
|
|
492
|
+
deadGlobs: deadGlobUnits.map((u) => u.selector),
|
|
493
|
+
deadGlobUnits,
|
|
494
|
+
negations,
|
|
495
|
+
...(excludedByNegations !== undefined ? { excludedByNegations } : {}),
|
|
496
|
+
globsChecked: lists.reduce((n, l) => n + l.units.checked, 0),
|
|
151
497
|
});
|
|
152
498
|
}
|
|
499
|
+
// Report each SHARED extractor once, with the rules that consume it. One
|
|
500
|
+
// resolve per extractor, not per consumer — the shared definition is a single
|
|
501
|
+
// fact about the tree, and stating it N times would invite the reader to
|
|
502
|
+
// treat N agreeing consumers as N independent confirmations.
|
|
503
|
+
//
|
|
504
|
+
// Consumers are collected from EVERY side of every rule, not just the side
|
|
505
|
+
// coverage happens to inspect: a rule bound to the extractor through its
|
|
506
|
+
// `registered` sink is every bit as bound as one using it for `declared`, and
|
|
507
|
+
// listing half of them would understate the guarantee.
|
|
508
|
+
const consumersByExtractor = new Map();
|
|
509
|
+
for (const view of rules) {
|
|
510
|
+
const label = `${view.plane}:${view.id}`;
|
|
511
|
+
for (const id of referencedExtractorIds(gateRuleSources(view))) {
|
|
512
|
+
const list = consumersByExtractor.get(id) ?? [];
|
|
513
|
+
if (!list.includes(label))
|
|
514
|
+
list.push(label);
|
|
515
|
+
consumersByExtractor.set(id, list);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
const extractorCoverage = [...consumersByExtractor.keys()]
|
|
519
|
+
.sort()
|
|
520
|
+
.map((id) => {
|
|
521
|
+
const definition = extractors[id];
|
|
522
|
+
if (!definition) {
|
|
523
|
+
return {
|
|
524
|
+
id,
|
|
525
|
+
consumers: consumersByExtractor.get(id),
|
|
526
|
+
filesMatched: 0,
|
|
527
|
+
idsMatched: 0,
|
|
528
|
+
sampleIds: [],
|
|
529
|
+
error: 'referenced but not declared in `extractors`',
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
const insp = inspectSource(cwd, definition, excludeDirs);
|
|
533
|
+
return {
|
|
534
|
+
id,
|
|
535
|
+
consumers: consumersByExtractor.get(id),
|
|
536
|
+
filesMatched: insp.filesScanned,
|
|
537
|
+
idsMatched: insp.ids.length,
|
|
538
|
+
sampleIds: insp.ids.slice(0, 5),
|
|
539
|
+
...(insp.error ? { error: insp.error } : {}),
|
|
540
|
+
...(insp.hint ? { hint: insp.hint } : {}),
|
|
541
|
+
};
|
|
542
|
+
});
|
|
153
543
|
const empty = out.filter((r) => r.status === 'empty').length;
|
|
154
544
|
const errored = out.filter((r) => r.status === 'error').length;
|
|
155
545
|
const expectationFailures = out.filter((r) => r.status === 'failed-expectation').length;
|
|
@@ -160,6 +550,183 @@ export function buildGateCoverage(cwd, rules, excludeDirs = []) {
|
|
|
160
550
|
empty,
|
|
161
551
|
errored,
|
|
162
552
|
expectationFailures,
|
|
553
|
+
deadGlobCount: out.filter(reportsDeadGlobs).reduce((n, r) => n + r.deadGlobs.length, 0),
|
|
554
|
+
extractors: extractorCoverage,
|
|
163
555
|
verdict: empty + errored + expectationFailures > 0 ? 'stale' : 'pass',
|
|
164
556
|
};
|
|
165
557
|
}
|
|
558
|
+
/**
|
|
559
|
+
* The coverage report with every pack rule the merge seam REJECTED folded in as
|
|
560
|
+
* a misconfigured (`error`) row (round 12 review, R12-X1) — from THE rows
|
|
561
|
+
* `seamRejectedRules` builds for `gates check`, so the coverage verb and the
|
|
562
|
+
* check cannot disagree about a rule that never ran. It counts in `total` and
|
|
563
|
+
* `errored`, so `settleGateCoverage` fails it (exit 1) and names it unexamined.
|
|
564
|
+
*/
|
|
565
|
+
export function withRejectedRules(report, rejected) {
|
|
566
|
+
if (rejected.length === 0)
|
|
567
|
+
return report;
|
|
568
|
+
const rows = rejected.map((r) => ({
|
|
569
|
+
id: r.id,
|
|
570
|
+
plane: r.type,
|
|
571
|
+
status: 'error',
|
|
572
|
+
coverage: r.coverage,
|
|
573
|
+
filesMatched: 0,
|
|
574
|
+
unitsMatched: 0,
|
|
575
|
+
unitLabel: 'units (rejected at the pack-plane merge seam — not evaluated)',
|
|
576
|
+
idLabel: 'extracted ids',
|
|
577
|
+
consulted: 'nothing — the pack element failed validation before any selector ran',
|
|
578
|
+
sampleIds: [],
|
|
579
|
+
failOnEmpty: true,
|
|
580
|
+
...(r.error !== undefined ? { error: r.error } : {}),
|
|
581
|
+
expectationFailures: [],
|
|
582
|
+
deadGlobs: [],
|
|
583
|
+
deadGlobUnits: [],
|
|
584
|
+
negations: [],
|
|
585
|
+
globsChecked: 0,
|
|
586
|
+
}));
|
|
587
|
+
const all = [...report.rules, ...rows];
|
|
588
|
+
const errored = all.filter((r) => r.status === 'error').length;
|
|
589
|
+
return {
|
|
590
|
+
...report,
|
|
591
|
+
rules: all,
|
|
592
|
+
total: all.length,
|
|
593
|
+
errored,
|
|
594
|
+
verdict: report.empty + errored + report.expectationFailures > 0 ? 'stale' : 'pass',
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Whether a rule's dead globs are a finding of their OWN: the rule is connected
|
|
599
|
+
* (it matched something, or it is an inspected fence / clean rule reported
|
|
600
|
+
* `ok`), so sibling globs can hide the dead ones.
|
|
601
|
+
*
|
|
602
|
+
* A rule already reported as matching nothing has no live sibling to hide
|
|
603
|
+
* behind. Its "matched nothing" verdict (skip, or failOnEmpty failure) already
|
|
604
|
+
* says it, so its dead globs are not counted, drawn or failed a second time.
|
|
605
|
+
* `--fail-on-dead-units` must never turn a soft-empty rule's `2` into a `1`.
|
|
606
|
+
* The report count, the ⚠ lines, the settle and the quality notes all read
|
|
607
|
+
* this one predicate.
|
|
608
|
+
*/
|
|
609
|
+
export function reportsDeadGlobs(r) {
|
|
610
|
+
if (r.deadGlobs.length === 0 || r.status === 'empty')
|
|
611
|
+
return false;
|
|
612
|
+
return r.status === 'ok' || r.unitsMatched > 0;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* THE dead units of a coverage row, each with its reason — what the ⚠ line,
|
|
616
|
+
* the `--fail-on-dead-units` violation and the `shrk quality` note all print,
|
|
617
|
+
* so the three cannot word one unit differently. A row built without
|
|
618
|
+
* `deadGlobUnits` (a hand-built report) falls back to its `deadGlobs` labels,
|
|
619
|
+
* read as inclusion globs that matched nothing.
|
|
620
|
+
*/
|
|
621
|
+
export function coverageDeadUnits(r) {
|
|
622
|
+
if (r.deadGlobUnits !== undefined && r.deadGlobUnits.length === r.deadGlobs.length)
|
|
623
|
+
return r.deadGlobUnits;
|
|
624
|
+
return r.deadGlobs.map((g) => ({ selector: g, glob: g, negation: false, reason: 'matched 0 files' }));
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* THE went-live units of a coverage row (round 13): each glob marked
|
|
628
|
+
* `expectEmpty` whose target now exists — the fence went live. What the ⚠
|
|
629
|
+
* `expectEmpty is stale` rows, the `--fail-on-dead-units` violation and the
|
|
630
|
+
* `shrk quality` note print.
|
|
631
|
+
*/
|
|
632
|
+
export function coverageWentLiveUnits(r) {
|
|
633
|
+
return (r.unitLiveness ?? []).filter((u) => u.state === UnitLivenessState.WentLive);
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* The selector units that FAIL a coverage row under the given flags — decided
|
|
637
|
+
* by THE predicate every `--fail-on-dead-units` consumer calls
|
|
638
|
+
* (`selectorUnitFails`, core): an unmarked dead glob of a connected rule
|
|
639
|
+
* ({@link reportsDeadGlobs}), and a LOCAL went-live marker. A pack marker that
|
|
640
|
+
* went live is INFO, never a failure; an intended-empty unit never fails.
|
|
641
|
+
*/
|
|
642
|
+
export function coverageUnitFailures(r, flags) {
|
|
643
|
+
const dead = reportsDeadGlobs(r)
|
|
644
|
+
? coverageDeadUnits(r)
|
|
645
|
+
.filter(() => selectorUnitFails({ state: UnitLivenessState.Dead }, flags))
|
|
646
|
+
.map((u) => ({ selector: u.selector, message: `${u.reason} (--fail-on-dead-units)` }))
|
|
647
|
+
: [];
|
|
648
|
+
const wentLive = coverageWentLiveUnits(r)
|
|
649
|
+
.filter((u) => selectorUnitFails(u, flags))
|
|
650
|
+
.map((u) => ({ selector: u.label, message: `${u.message} (--fail-on-dead-units)` }));
|
|
651
|
+
return [...dead, ...wentLive];
|
|
652
|
+
}
|
|
653
|
+
/** `declared: src/moved/*.ts (matched 0 files), !src/nowhere/** (excludes nothing — …)`. */
|
|
654
|
+
export function formatDeadUnits(units) {
|
|
655
|
+
return units.map((u) => `${u.selector} (${u.reason})`).join(', ');
|
|
656
|
+
}
|
|
657
|
+
/** `declared: !src/**\/*.spec.ts (1 file), !docs/drafts/** (3 files)`. */
|
|
658
|
+
export function formatNegations(negations) {
|
|
659
|
+
return negations.map((n) => `${n.selector} (${n.excludes} file${n.excludes === 1 ? '' : 's'})`).join(', ');
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Settle a coverage report into the shared `gate` envelope — THE derivation of
|
|
663
|
+
* what `gates coverage` concludes.
|
|
664
|
+
*
|
|
665
|
+
* `gates coverage` and `shrk quality`'s coverage item both call this, so the
|
|
666
|
+
* pre-push bundle cannot pass a rule set the verb itself reports broken (a
|
|
667
|
+
* failed selfTest, a stale failOnEmpty selector, a partial rule). A rule that
|
|
668
|
+
* matched nothing is not-verified (2) by default; `failOnEmpty` on the rule
|
|
669
|
+
* makes it a failure (1); `failOnDeadUnits` makes a dead glob inside a
|
|
670
|
+
* connected rule — or a local marker whose target went live — a failure too
|
|
671
|
+
* (`selectorUnitFails`). Each rule's `expectEmpty` acceptance rides on its
|
|
672
|
+
* envelope rule (`unitAcceptance`) into the one settle.
|
|
673
|
+
*/
|
|
674
|
+
export function settleGateCoverage(report, options = {}) {
|
|
675
|
+
const flags = {
|
|
676
|
+
failOnDeadUnits: options.failOnDeadUnits === true,
|
|
677
|
+
// `gates coverage` is not where --strict promotes warnings (check boundaries is).
|
|
678
|
+
strict: false,
|
|
679
|
+
strictPromotesWarnings: false,
|
|
680
|
+
};
|
|
681
|
+
const unitFailures = (r) => coverageUnitFailures(r, flags);
|
|
682
|
+
const deadFails = (r) => unitFailures(r).length > 0;
|
|
683
|
+
const hard = report.rules.filter((r) => r.status === 'error' ||
|
|
684
|
+
r.status === 'failed-expectation' ||
|
|
685
|
+
(r.status === 'empty' && r.failOnEmpty) ||
|
|
686
|
+
deadFails(r));
|
|
687
|
+
const softEmpty = report.rules.filter((r) => r.status === 'empty' && !r.failOnEmpty);
|
|
688
|
+
const proposed = hard.length > 0 ? ExitCode.Failure : softEmpty.length > 0 ? ExitCode.NotVerified : ExitCode.VerifiedPass;
|
|
689
|
+
const unconnected = report.rules
|
|
690
|
+
.filter((r) => r.status === 'empty' || r.status === 'error')
|
|
691
|
+
.map((r) => r.id);
|
|
692
|
+
return buildGateEnvelope('gates coverage', proposed, report.rules.map((r) => ({
|
|
693
|
+
id: r.id,
|
|
694
|
+
type: r.plane,
|
|
695
|
+
status: r.status === 'ok'
|
|
696
|
+
? deadFails(r)
|
|
697
|
+
? 'failed'
|
|
698
|
+
: 'passed'
|
|
699
|
+
: r.status === 'empty'
|
|
700
|
+
? r.failOnEmpty || deadFails(r)
|
|
701
|
+
? 'failed'
|
|
702
|
+
: 'skipped'
|
|
703
|
+
: r.status === 'error'
|
|
704
|
+
? 'error'
|
|
705
|
+
: 'failed',
|
|
706
|
+
severity: r.failOnEmpty || deadFails(r) ? 'error' : 'warning',
|
|
707
|
+
counts: { files: r.filesMatched, units: r.unitsMatched },
|
|
708
|
+
violations: [
|
|
709
|
+
...r.expectationFailures.map((f) => ({ id: r.id, message: f })),
|
|
710
|
+
...unitFailures(r).map((f) => ({ id: f.selector, message: f.message })),
|
|
711
|
+
],
|
|
712
|
+
...(r.status === 'empty'
|
|
713
|
+
? {
|
|
714
|
+
skipReason: r.emptyReason ??
|
|
715
|
+
(r.excludedByNegations !== undefined
|
|
716
|
+
? `matched 0 ${r.unitLabel} — ${EMPTIED_BY_NEGATIONS}`
|
|
717
|
+
: `matched 0 ${r.unitLabel}`),
|
|
718
|
+
}
|
|
719
|
+
: {}),
|
|
720
|
+
...(r.error ? { error: r.error } : {}),
|
|
721
|
+
coverage: r.coverage,
|
|
722
|
+
...(r.unitAcceptance !== undefined ? { unitAcceptance: r.unitAcceptance } : {}),
|
|
723
|
+
...(r.units !== undefined ? { units: r.units } : {}),
|
|
724
|
+
})), {
|
|
725
|
+
unit: 'rules',
|
|
726
|
+
expected: report.total,
|
|
727
|
+
examined: report.total - unconnected.length,
|
|
728
|
+
...(unconnected.length > 0
|
|
729
|
+
? { unexamined: unconnected, reason: 'matched nothing or could not run' }
|
|
730
|
+
: {}),
|
|
731
|
+
});
|
|
732
|
+
}
|