@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
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
import { formatEmptyRuleAdvice } from '@shrkcrft/core';
|
|
2
|
+
import { planeScanExcludeDirs, readScopeCoverage } from '@shrkcrft/boundaries';
|
|
3
|
+
import { warmCliReferenceRegistries } from "../surface/cli-command-resolver.js";
|
|
4
|
+
import { checkDocReferences, inspectSharkcraft, resolveProjectConfig, } from '@shrkcrft/inspector';
|
|
5
|
+
import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
|
|
6
|
+
import { PositionalMode } from "../dispatch/positional-mode.js";
|
|
7
|
+
import { ExitCode } from "../exit-codes.js";
|
|
8
|
+
import { asJson, header, kv } from "../output/format-output.js";
|
|
9
|
+
import { buildGateEnvelope } from "../gates/gate-envelope.js";
|
|
10
|
+
import { verdictLine } from "../gates/verdict-line.js";
|
|
11
|
+
import { acceptedEmptyNote } from "../gates/accepted-empty-note.js";
|
|
12
|
+
import { emptyRuleAdviceLines } from "../gates/empty-rule-advice-lines.js";
|
|
13
|
+
import { qualifyCleanForUnits } from "../gates/qualify-clean-for-units.js";
|
|
14
|
+
import { unitStateNotes } from "../gates/unit-state-notes.js";
|
|
15
|
+
import { planeVerdictForExit } from "../gates/plane-verdict.js";
|
|
16
|
+
import { seamRejectedRules } from "../gates/seam-rejected-rules.js";
|
|
17
|
+
const SCHEMA = 'sharkcraft.doc-references/v1';
|
|
18
|
+
/**
|
|
19
|
+
* What one doc-reference rule examined — shared by `docs references check` and
|
|
20
|
+
* the aggregate (`gates check`, `quality`), so both report the same scope.
|
|
21
|
+
*
|
|
22
|
+
* The unit is the id-shaped tokens the rule matched. Tokens it did NOT check
|
|
23
|
+
* were skipped by the rule's own config — an `exempt` id, an in-file
|
|
24
|
+
* `exemptMarker`, the `requireContext` gate — which is a deliberate narrowing,
|
|
25
|
+
* so it is accepted by that config and printed as such rather than silently
|
|
26
|
+
* shrinking the denominator.
|
|
27
|
+
*/
|
|
28
|
+
export function docReferenceCoverage(r) {
|
|
29
|
+
// An intended-empty rule (round 13: every `files` inclusion glob marked
|
|
30
|
+
// `expectEmpty`, no document matched) is covered by its acceptance — the
|
|
31
|
+
// settle's own record, printed at exit 0.
|
|
32
|
+
if (r.emptyCoverage !== undefined)
|
|
33
|
+
return r.emptyCoverage;
|
|
34
|
+
// A document the reader could not read (over the read cap) folds in through
|
|
35
|
+
// the one rule every plane uses: `examined N of M files`, named.
|
|
36
|
+
return readScopeCoverage(planeDocReferenceCoverage(r), r.readScope);
|
|
37
|
+
}
|
|
38
|
+
function planeDocReferenceCoverage(r) {
|
|
39
|
+
if (r.error !== undefined) {
|
|
40
|
+
return { unit: 'references', expected: 0, examined: 0, reason: 'the rule could not run' };
|
|
41
|
+
}
|
|
42
|
+
const expected = r.tokensChecked + r.tokensSkipped;
|
|
43
|
+
return {
|
|
44
|
+
unit: 'references',
|
|
45
|
+
expected,
|
|
46
|
+
examined: r.tokensChecked,
|
|
47
|
+
...(r.skipReason !== undefined
|
|
48
|
+
? { reason: r.skipReason }
|
|
49
|
+
: r.tokensSkipped > 0
|
|
50
|
+
? { reason: "skipped by the rule's own exempt / exemptMarker / requireContext config" }
|
|
51
|
+
: {}),
|
|
52
|
+
...(r.tokensSkipped > 0 && r.tokensChecked > 0
|
|
53
|
+
? { acceptedBy: 'the rule config (exempt / exemptMarker / requireContext)' }
|
|
54
|
+
: {}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async function prepare(args,
|
|
58
|
+
/** `rejectedKnown`: the verdict verb may select a rejected rule by `--id` (its errored row). */
|
|
59
|
+
opts = {}) {
|
|
60
|
+
const cwd = resolveCwd(args);
|
|
61
|
+
const json = flagBool(args, 'json');
|
|
62
|
+
const loaded = await resolveProjectConfig(cwd);
|
|
63
|
+
if (!loaded.ok) {
|
|
64
|
+
const msg = loaded.error.message;
|
|
65
|
+
if (json)
|
|
66
|
+
process.stdout.write(asJson({ schema: SCHEMA, error: msg }) + '\n');
|
|
67
|
+
else
|
|
68
|
+
process.stderr.write(`Could not load config: ${msg}\n Run \`shrk doctor\` for details.\n`);
|
|
69
|
+
return { ok: false, code: ExitCode.UsageError };
|
|
70
|
+
}
|
|
71
|
+
const all = loaded.value.config.docReferences ?? [];
|
|
72
|
+
// A pack doc-reference rule the merge seam REJECTED is a configured rule
|
|
73
|
+
// that never ran — an ERRORED row on this verb exactly as on `gates check`
|
|
74
|
+
// (round 13, P3 review). It was one `! … invalid docReference element … —
|
|
75
|
+
// skipped` line under a ✓ at exit 0 (or "No doc-reference rules declared"
|
|
76
|
+
// at 2 when it was the only rule) while `gates check` exited 1 on the tree.
|
|
77
|
+
const rejectedAll = seamRejectedRules(loaded.value, ['doc-reference']);
|
|
78
|
+
let rules = all;
|
|
79
|
+
let rejected = rejectedAll;
|
|
80
|
+
const id = flagString(args, 'id');
|
|
81
|
+
if (id) {
|
|
82
|
+
const wanted = id.split(',').map((s) => s.trim()).filter(Boolean);
|
|
83
|
+
const known = new Set([
|
|
84
|
+
...all.map((r) => r.id),
|
|
85
|
+
...(opts.rejectedKnown === true ? rejectedAll.map((r) => r.id) : []),
|
|
86
|
+
]);
|
|
87
|
+
const unknown = wanted.filter((w) => !known.has(w));
|
|
88
|
+
if (unknown.length > 0) {
|
|
89
|
+
process.stderr.write(`Unknown doc-reference rule id(s): ${unknown.join(', ')}. Declared: ${[...known].join(', ') || '(none)'}\n`);
|
|
90
|
+
return { ok: false, code: ExitCode.UsageError };
|
|
91
|
+
}
|
|
92
|
+
rules = all.filter((r) => wanted.includes(r.id));
|
|
93
|
+
rejected = rejectedAll.filter((r) => wanted.includes(r.id));
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
ok: true,
|
|
97
|
+
value: {
|
|
98
|
+
cwd,
|
|
99
|
+
rules,
|
|
100
|
+
all,
|
|
101
|
+
rejected,
|
|
102
|
+
// THE plane scan scope — the same authority `gates check` reads.
|
|
103
|
+
excludeDirs: planeScanExcludeDirs(cwd, loaded.value.sharkcraftDir),
|
|
104
|
+
planeDiagnostics: loaded.value.planeDiagnostics,
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Build the inspection the resolver needs.
|
|
110
|
+
*
|
|
111
|
+
* Deliberately lazy — it is only paid for when a `docReferences` rule exists,
|
|
112
|
+
* so a repo without the plane never loads the registries just to be told it has
|
|
113
|
+
* no rules.
|
|
114
|
+
*/
|
|
115
|
+
async function inspectionFor(cwd) {
|
|
116
|
+
// Playbook / construct ids come from a cache an ASYNC load populates; the
|
|
117
|
+
// resolver is sync. Warming here is what makes a correct pack playbook cited
|
|
118
|
+
// in prose actually resolve.
|
|
119
|
+
const inspection = await inspectSharkcraft({ cwd });
|
|
120
|
+
// WITH the command resolver: a `resolvesAs: ['command']` rule resolves
|
|
121
|
+
// against the live command index (without it, `command` is unverifiable
|
|
122
|
+
// and the rule refuses loudly).
|
|
123
|
+
await warmCliReferenceRegistries(inspection);
|
|
124
|
+
return inspection;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The "no rules declared" landing. A VERDICT verb passes its name so its JSON
|
|
128
|
+
* still carries the settled `gate` envelope — nothing declared is `2`.
|
|
129
|
+
*/
|
|
130
|
+
function writeNoRules(json, verb) {
|
|
131
|
+
// A VERDICT verb settles first and renders second, in text AND JSON: nothing
|
|
132
|
+
// declared proposes 0 and the run coverage (expected 0) settles it to 2. The
|
|
133
|
+
// exit comes from the envelope — never a hard-coded code — so text, JSON and
|
|
134
|
+
// gate.exit cannot disagree. List / explain subverbs stay informational.
|
|
135
|
+
const gate = verb !== undefined
|
|
136
|
+
? buildGateEnvelope(verb, ExitCode.VerifiedPass, [], {
|
|
137
|
+
unit: 'doc-reference rules',
|
|
138
|
+
expected: 0,
|
|
139
|
+
examined: 0,
|
|
140
|
+
reason: 'no docReferences[] declared',
|
|
141
|
+
})
|
|
142
|
+
: undefined;
|
|
143
|
+
const exit = gate?.exit ?? ExitCode.NotVerified;
|
|
144
|
+
if (json) {
|
|
145
|
+
process.stdout.write(asJson({
|
|
146
|
+
schema: SCHEMA,
|
|
147
|
+
results: [],
|
|
148
|
+
evaluated: 0,
|
|
149
|
+
verdict: gate ? planeVerdictForExit(gate.exit) : 'not-verified',
|
|
150
|
+
...(gate ? { exitCode: gate.exit, gate } : {}),
|
|
151
|
+
}) + '\n');
|
|
152
|
+
return exit;
|
|
153
|
+
}
|
|
154
|
+
process.stdout.write(header('Doc references'));
|
|
155
|
+
process.stdout.write(' No doc-reference rules declared. Add `docReferences[]` to sharkcraft.config.ts to\n' +
|
|
156
|
+
' catch ids cited in prose (READMEs, docs, agent skill files) that no longer resolve\n' +
|
|
157
|
+
' (see docs/doc-references.md).\n');
|
|
158
|
+
if (gate) {
|
|
159
|
+
const line = verdictLine(gate, 'Nothing declared — accepted.');
|
|
160
|
+
if (line)
|
|
161
|
+
process.stdout.write(`\n${line}\n`);
|
|
162
|
+
}
|
|
163
|
+
return exit;
|
|
164
|
+
}
|
|
165
|
+
function resultJson(r) {
|
|
166
|
+
return {
|
|
167
|
+
id: r.ruleId,
|
|
168
|
+
...(r.description ? { description: r.description } : {}),
|
|
169
|
+
status: r.status,
|
|
170
|
+
severity: r.severity,
|
|
171
|
+
filesScanned: r.filesScanned,
|
|
172
|
+
tokensChecked: r.tokensChecked,
|
|
173
|
+
tokensSkipped: r.tokensSkipped,
|
|
174
|
+
findings: r.findings,
|
|
175
|
+
...(r.skipReason ? { skipReason: r.skipReason } : {}),
|
|
176
|
+
...(r.error ? { error: r.error } : {}),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The round-12 list-verb rejection note (K10): one line per pack doc-reference
|
|
181
|
+
* rule the merge seam REJECTED — the rows `baseline list` / `gates list` print.
|
|
182
|
+
*/
|
|
183
|
+
function writeRejectedDocRules(rejected) {
|
|
184
|
+
if (rejected.length === 0)
|
|
185
|
+
return;
|
|
186
|
+
process.stdout.write(`\n rejected at the pack-plane merge seam — never checked (${rejected.length}):\n`);
|
|
187
|
+
for (const r of rejected)
|
|
188
|
+
process.stdout.write(` ✗ ${r.id} REJECTED — ${r.error ?? 'failed validation'}\n`);
|
|
189
|
+
process.stdout.write(' `shrk packs contributions` names every rejected entry.\n');
|
|
190
|
+
}
|
|
191
|
+
export const docsReferencesCheckCommand = {
|
|
192
|
+
name: 'check',
|
|
193
|
+
description: 'Scan configured docs for id-shaped tokens and assert each resolves to a registered id. Catches a README or skill file citing a template that no longer exists.',
|
|
194
|
+
usage: 'shrk docs references check [--id <ids>] [--json]',
|
|
195
|
+
booleanFlags: new Set(['json']),
|
|
196
|
+
async run(args) {
|
|
197
|
+
const prep = await prepare(args, { rejectedKnown: true });
|
|
198
|
+
if (!prep.ok)
|
|
199
|
+
return prep.code;
|
|
200
|
+
const json = flagBool(args, 'json');
|
|
201
|
+
const rejected = prep.value.rejected;
|
|
202
|
+
if (prep.value.rules.length === 0 && rejected.length === 0)
|
|
203
|
+
return writeNoRules(json, 'docs references check');
|
|
204
|
+
// The resolver's inspection is paid for only when a rule will run.
|
|
205
|
+
const inspection = prep.value.rules.length > 0 ? await inspectionFor(prep.value.cwd) : undefined;
|
|
206
|
+
const results = inspection
|
|
207
|
+
? prep.value.rules.map((r) => checkDocReferences(prep.value.cwd, r, inspection, prep.value.excludeDirs))
|
|
208
|
+
: [];
|
|
209
|
+
// A rule that ERRORED proved nothing — it never got as far as checking an
|
|
210
|
+
// id. So it is not `evaluated`, whatever its severity: a warning-severity
|
|
211
|
+
// rule that could not run must not leave the banner saying "not blocking"
|
|
212
|
+
// over an exit code of 0, which is the same half-truth as a green banner
|
|
213
|
+
// above a list of findings.
|
|
214
|
+
const errored = results.filter((r) => r.status === 'error');
|
|
215
|
+
const failed = results.filter((r) => r.status === 'failed');
|
|
216
|
+
const blocking = [...failed, ...errored].filter((r) => r.severity === 'error');
|
|
217
|
+
const evaluated = results.filter((r) => r.status !== 'skipped' && r.status !== 'error').length;
|
|
218
|
+
const skipped = results.length - evaluated;
|
|
219
|
+
// A rejected pack rule is a configured rule that never ran: 1, as on
|
|
220
|
+
// `gates check` (its ERRORED row, `failed validation — NOT evaluated`).
|
|
221
|
+
const proposed = blocking.length > 0 || rejected.length > 0
|
|
222
|
+
? ExitCode.Failure
|
|
223
|
+
: evaluated === 0 || skipped > 0
|
|
224
|
+
? ExitCode.NotVerified
|
|
225
|
+
: ExitCode.VerifiedPass;
|
|
226
|
+
// Settle first, render second: the envelope is built for text AND JSON, so
|
|
227
|
+
// both return the same settled exit and the ✓ line is printed only from it.
|
|
228
|
+
const unexamined = [
|
|
229
|
+
...results.filter((r) => r.status === 'skipped' || r.status === 'error').map((r) => r.ruleId),
|
|
230
|
+
...rejected.map((r) => r.id),
|
|
231
|
+
];
|
|
232
|
+
const env = buildGateEnvelope('docs references check', proposed, [...results.map((r) => ({
|
|
233
|
+
id: r.ruleId,
|
|
234
|
+
type: 'doc-reference',
|
|
235
|
+
status: r.status,
|
|
236
|
+
severity: r.severity,
|
|
237
|
+
counts: { files: r.filesScanned, tokens: r.tokensChecked, skipped: r.tokensSkipped },
|
|
238
|
+
violations: r.findings.map((f) => ({
|
|
239
|
+
id: f.token,
|
|
240
|
+
file: f.file,
|
|
241
|
+
line: f.line,
|
|
242
|
+
message: f.message,
|
|
243
|
+
...(f.didYouMean.length > 0 ? { hint: `did you mean: ${f.didYouMean.join(', ')}` } : {}),
|
|
244
|
+
})),
|
|
245
|
+
...(r.skipReason ? { skipReason: r.skipReason } : {}),
|
|
246
|
+
...(r.error ? { error: r.error } : {}),
|
|
247
|
+
coverage: docReferenceCoverage(r),
|
|
248
|
+
// The rule's `expectEmpty` acceptance and unit lines (round 13),
|
|
249
|
+
// folded into the envelope's one settle — the accepted line comes from it.
|
|
250
|
+
...(r.unitAcceptance !== undefined ? { unitAcceptance: r.unitAcceptance } : {}),
|
|
251
|
+
...(r.units !== undefined ? { units: r.units } : {}),
|
|
252
|
+
})), ...rejected], {
|
|
253
|
+
unit: 'doc-reference rules',
|
|
254
|
+
expected: results.length + rejected.length,
|
|
255
|
+
examined: results.length + rejected.length - unexamined.length,
|
|
256
|
+
...(unexamined.length > 0 ? { unexamined, reason: 'checked nothing or could not run' } : {}),
|
|
257
|
+
});
|
|
258
|
+
const exit = env.exit;
|
|
259
|
+
if (json) {
|
|
260
|
+
process.stdout.write(asJson({
|
|
261
|
+
schema: SCHEMA,
|
|
262
|
+
results: results.map(resultJson),
|
|
263
|
+
evaluated,
|
|
264
|
+
skipped,
|
|
265
|
+
verdict: exit === ExitCode.Failure ? 'errors' : exit === ExitCode.VerifiedPass ? 'pass' : 'not-verified',
|
|
266
|
+
rejected: rejected.map((r) => ({ id: r.id, error: r.error ?? null })),
|
|
267
|
+
diagnostics: prep.value.planeDiagnostics,
|
|
268
|
+
exitCode: exit,
|
|
269
|
+
gate: env,
|
|
270
|
+
}) + '\n');
|
|
271
|
+
return exit;
|
|
272
|
+
}
|
|
273
|
+
process.stdout.write(header('Doc references'));
|
|
274
|
+
// Round 13 (K6): the printed count is the envelope's (`gate.evaluated`), which
|
|
275
|
+
// never counts a rule accepted as intended-empty — it is named apart. The
|
|
276
|
+
// local `evaluated` keeps counting it for the "nothing ran" proposal above.
|
|
277
|
+
process.stdout.write(kv('evaluated', `${env.evaluated} of ${prep.value.rules.length + rejected.length}${acceptedEmptyNote(env.acceptedEmpty)}`) +
|
|
278
|
+
'\n');
|
|
279
|
+
// THE shared unit-state block (round 13, K2): a dead `files` glob of a rule
|
|
280
|
+
// that still matched, and a LOCAL expectEmpty marker whose target appeared,
|
|
281
|
+
// withhold the ✓ (exit unchanged); a pack marker is INFO.
|
|
282
|
+
const unitNotes = unitStateNotes(results.map((r) => ({
|
|
283
|
+
id: r.ruleId,
|
|
284
|
+
...(r.unitLiveness !== undefined ? { unitLiveness: r.unitLiveness } : {}),
|
|
285
|
+
reportedEmpty: r.status === 'skipped' || r.skipReason !== undefined,
|
|
286
|
+
})));
|
|
287
|
+
for (const r of results) {
|
|
288
|
+
if (r.status === 'skipped') {
|
|
289
|
+
process.stdout.write(` – ${r.ruleId} SKIPPED — ${r.skipReason}\n`);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (r.status === 'error') {
|
|
293
|
+
process.stdout.write(` ! ${r.ruleId} ${r.error}\n`);
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (r.status === 'passed') {
|
|
297
|
+
// Rendered from the SETTLED rule: a pass over part of its scope is
|
|
298
|
+
// `partial`, never a ✓ (the keystone emitter pattern, step 5).
|
|
299
|
+
const settledRule = env.rules.find((x) => x.id === r.ruleId);
|
|
300
|
+
process.stdout.write(settledRule?.status === 'partial'
|
|
301
|
+
? ` ~ ${r.ruleId} PARTIAL — ${settledRule.shortfall ?? 'part of its scope was not examined'}\n`
|
|
302
|
+
: ` ✓ ${r.ruleId} (${r.tokensChecked} reference(s) across ${r.filesScanned} doc(s) all resolve)\n`);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
// A rule that CHECKED nothing failed for a different reason than one with
|
|
306
|
+
// findings, and the loud-skip contract is worthless if it does not say
|
|
307
|
+
// which. `0 unresolved of 0 checked` would send the reader hunting for a
|
|
308
|
+
// bad id when the real problem is a moved directory.
|
|
309
|
+
if (r.skipReason) {
|
|
310
|
+
process.stdout.write(` ✗ ${r.ruleId} FAILED — ${r.skipReason}\n`);
|
|
311
|
+
process.stdout.write(' Nothing was checked, so nothing was enforced.\n' +
|
|
312
|
+
` → ${formatEmptyRuleAdvice({ fails: true })}\n`);
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
process.stdout.write(` ✗ ${r.ruleId} ${r.findings.length} unresolved reference(s) of ${r.tokensChecked} checked\n`);
|
|
316
|
+
for (const f of r.findings.slice(0, 25)) {
|
|
317
|
+
process.stdout.write(` • ${f.token} (${f.file}:${f.line})\n`);
|
|
318
|
+
if (f.didYouMean.length > 0) {
|
|
319
|
+
process.stdout.write(` did you mean: ${f.didYouMean.join(', ')}\n`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (r.findings.length > 25) {
|
|
323
|
+
process.stdout.write(` … (${r.findings.length - 25} more)\n`);
|
|
324
|
+
}
|
|
325
|
+
const hint = r.findings.find((f) => f.hint)?.hint;
|
|
326
|
+
if (hint)
|
|
327
|
+
process.stdout.write(` → ${hint}\n`);
|
|
328
|
+
}
|
|
329
|
+
for (const r of rejected)
|
|
330
|
+
process.stdout.write(` ✗ ${r.id} REJECTED — ${r.error ?? 'failed validation'}\n`);
|
|
331
|
+
for (const d of prep.value.planeDiagnostics)
|
|
332
|
+
process.stdout.write(` ! ${d}\n`);
|
|
333
|
+
// THE empty-rule advice (round 13, K8) for a rule that matched nothing and
|
|
334
|
+
// does not fail on it: only a FAILING empty rule was advised (inline,
|
|
335
|
+
// above), so a soft skip was never told how to make it fail or to mark a
|
|
336
|
+
// planned unit.
|
|
337
|
+
for (const a of emptyRuleAdviceLines(results.filter((r) => r.status === 'skipped').map(() => ({ fails: false })))) {
|
|
338
|
+
process.stdout.write(` ${a}.\n`);
|
|
339
|
+
}
|
|
340
|
+
process.stdout.write(unitNotes.text);
|
|
341
|
+
// A warning-severity rule reports without blocking, but the banner must
|
|
342
|
+
// still say it FIRED. "Every id resolves ✓" printed under a list of
|
|
343
|
+
// unresolved ids is the kind of half-truth that trains people to stop
|
|
344
|
+
// reading the output.
|
|
345
|
+
const warned = failed.filter((r) => r.severity !== 'error');
|
|
346
|
+
const warnedCount = warned.reduce((n, r) => n + r.findings.length, 0);
|
|
347
|
+
const line = verdictLine(env, warned.length > 0
|
|
348
|
+
? `${warnedCount} unresolved reference(s) reported by ${warned.length} warning rule(s) — not blocking.`
|
|
349
|
+
: qualifyCleanForUnits('Every id cited in prose resolves. ✓', unitNotes), proposed === ExitCode.NotVerified
|
|
350
|
+
? errored.length > 0
|
|
351
|
+
? `${errored.length} rule(s) could not run — nothing was proved. This is NOT a pass.`
|
|
352
|
+
: 'Nothing was checked — this is NOT a pass.'
|
|
353
|
+
: undefined);
|
|
354
|
+
if (line)
|
|
355
|
+
process.stdout.write(`\n${line}\n`);
|
|
356
|
+
return exit;
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
export const docsReferencesExplainCommand = {
|
|
360
|
+
name: 'explain',
|
|
361
|
+
description: 'Show every id-shaped token ONE rule considered: where it was found, whether it resolved, and why a token was skipped.',
|
|
362
|
+
usage: 'shrk docs references explain --id <id> [--json]',
|
|
363
|
+
booleanFlags: new Set(['json']),
|
|
364
|
+
async run(args) {
|
|
365
|
+
const id = flagString(args, 'id') ?? args.positional[0];
|
|
366
|
+
if (!id) {
|
|
367
|
+
process.stderr.write('Usage: shrk docs references explain --id <id>\n');
|
|
368
|
+
return ExitCode.UsageError;
|
|
369
|
+
}
|
|
370
|
+
const forwarded = { ...args, flags: new Map(args.flags) };
|
|
371
|
+
forwarded.flags.set('id', id);
|
|
372
|
+
// A rejected pack rule's id is a DECLARED one (K10): `explain` names its
|
|
373
|
+
// rejection — it called the id unknown (a usage error, 3).
|
|
374
|
+
const prep = await prepare(forwarded, { rejectedKnown: true });
|
|
375
|
+
if (!prep.ok)
|
|
376
|
+
return prep.code;
|
|
377
|
+
const rule = prep.value.rules[0];
|
|
378
|
+
if (!rule) {
|
|
379
|
+
const rejectedRule = prep.value.rejected[0];
|
|
380
|
+
if (rejectedRule === undefined)
|
|
381
|
+
return writeNoRules(flagBool(args, 'json'));
|
|
382
|
+
if (flagBool(args, 'json')) {
|
|
383
|
+
process.stdout.write(asJson({
|
|
384
|
+
schema: 'sharkcraft.doc-references-explain/v1',
|
|
385
|
+
id: rejectedRule.id,
|
|
386
|
+
rejected: true,
|
|
387
|
+
error: rejectedRule.error ?? null,
|
|
388
|
+
}) + '\n');
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
process.stdout.write(header(`Doc references: ${rejectedRule.id}`));
|
|
392
|
+
writeRejectedDocRules([rejectedRule]);
|
|
393
|
+
}
|
|
394
|
+
// A rule that never loaded cannot be explained: a failure, as every
|
|
395
|
+
// registry verb answers a rejected pack registry.
|
|
396
|
+
return ExitCode.Failure;
|
|
397
|
+
}
|
|
398
|
+
const inspection = await inspectionFor(prep.value.cwd);
|
|
399
|
+
const result = checkDocReferences(prep.value.cwd, rule, inspection, prep.value.excludeDirs);
|
|
400
|
+
if (flagBool(args, 'json')) {
|
|
401
|
+
process.stdout.write(asJson({
|
|
402
|
+
schema: 'sharkcraft.doc-references-explain/v1',
|
|
403
|
+
...resultJson(result),
|
|
404
|
+
tokens: result.tokens,
|
|
405
|
+
resolvesAs: rule.resolvesAs,
|
|
406
|
+
requireContext: rule.requireContext ?? 'backtick',
|
|
407
|
+
}) + '\n');
|
|
408
|
+
return ExitCode.VerifiedPass;
|
|
409
|
+
}
|
|
410
|
+
process.stdout.write(header(`Doc references: ${rule.id}`));
|
|
411
|
+
if (rule.description)
|
|
412
|
+
process.stdout.write(` ${rule.description}\n`);
|
|
413
|
+
process.stdout.write(kv('files', rule.files.join(', ')) + '\n');
|
|
414
|
+
process.stdout.write(kv('token pattern', `/${rule.tokenPattern}/`) + '\n');
|
|
415
|
+
process.stdout.write(kv('resolves as', rule.resolvesAs.join(', ')) + '\n');
|
|
416
|
+
process.stdout.write(kv('context gate', rule.requireContext ?? 'backtick') + '\n');
|
|
417
|
+
process.stdout.write(kv('docs scanned', String(result.filesScanned)) + '\n');
|
|
418
|
+
process.stdout.write(kv('tokens', `${result.tokensChecked} checked, ${result.tokensSkipped} skipped`) + '\n');
|
|
419
|
+
if (result.error)
|
|
420
|
+
process.stdout.write(` ! ${result.error}\n`);
|
|
421
|
+
process.stdout.write('\n');
|
|
422
|
+
for (const t of result.tokens.slice(0, 100)) {
|
|
423
|
+
const verdict = t.skipped
|
|
424
|
+
? `skipped (${t.skipped})`
|
|
425
|
+
: t.resolvedAs
|
|
426
|
+
? `✓ ${t.resolvedAs}`
|
|
427
|
+
: '✗ UNRESOLVED';
|
|
428
|
+
process.stdout.write(` ${t.token} (${t.file}:${t.line}) — ${verdict}\n`);
|
|
429
|
+
}
|
|
430
|
+
if (result.tokens.length > 100) {
|
|
431
|
+
process.stdout.write(` … (${result.tokens.length - 100} more)\n`);
|
|
432
|
+
}
|
|
433
|
+
return ExitCode.VerifiedPass;
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
export const docsReferencesListCommand = {
|
|
437
|
+
name: 'list',
|
|
438
|
+
description: 'List every declared doc-reference rule: its globs, token shape, and target registries.',
|
|
439
|
+
usage: 'shrk docs references list [--json]',
|
|
440
|
+
booleanFlags: new Set(['json']),
|
|
441
|
+
async run(args) {
|
|
442
|
+
const prep = await prepare(args);
|
|
443
|
+
if (!prep.ok)
|
|
444
|
+
return prep.code;
|
|
445
|
+
const json = flagBool(args, 'json');
|
|
446
|
+
// Round 13 (K10): a pack doc-reference rule the merge seam REJECTED is a
|
|
447
|
+
// declared rule that never runs — listed, as `baseline list` / `gates
|
|
448
|
+
// list` list theirs (it was absent from `list` and unknown to `explain`).
|
|
449
|
+
const rejected = prep.value.rejected;
|
|
450
|
+
if (prep.value.all.length === 0 && rejected.length === 0)
|
|
451
|
+
return writeNoRules(json);
|
|
452
|
+
if (json) {
|
|
453
|
+
process.stdout.write(asJson({
|
|
454
|
+
schema: SCHEMA,
|
|
455
|
+
rules: prep.value.all,
|
|
456
|
+
rejected: rejected.map((r) => ({ id: r.id, error: r.error ?? null })),
|
|
457
|
+
}) + '\n');
|
|
458
|
+
return ExitCode.VerifiedPass;
|
|
459
|
+
}
|
|
460
|
+
process.stdout.write(header(`Doc-reference rules (${prep.value.all.length})`));
|
|
461
|
+
for (const r of prep.value.all) {
|
|
462
|
+
process.stdout.write(` • ${r.id}\n`);
|
|
463
|
+
process.stdout.write(` files ${r.files.join(', ')}\n`);
|
|
464
|
+
process.stdout.write(` token /${r.tokenPattern}/\n`);
|
|
465
|
+
process.stdout.write(` resolves ${r.resolvesAs.join(', ')}\n`);
|
|
466
|
+
process.stdout.write(` context ${r.requireContext ?? 'backtick'}\n`);
|
|
467
|
+
if (r.description)
|
|
468
|
+
process.stdout.write(` ${r.description}\n`);
|
|
469
|
+
}
|
|
470
|
+
writeRejectedDocRules(rejected);
|
|
471
|
+
return ExitCode.VerifiedPass;
|
|
472
|
+
},
|
|
473
|
+
};
|
|
474
|
+
/** `shrk docs references <verb>` — dispatches to check / explain / list. */
|
|
475
|
+
export const docsReferencesCommand = {
|
|
476
|
+
name: 'references',
|
|
477
|
+
description: 'Prose-reference linter: assert every id cited in free text (READMEs, docs, agent skill files) still resolves to a registered id.',
|
|
478
|
+
usage: 'shrk docs references check | explain --id <id> | list',
|
|
479
|
+
// Declared (round 11 review): the dispatcher guard refuses any other token
|
|
480
|
+
// with the closest subverb, `help` and the index see the three verbs, and
|
|
481
|
+
// the declared walk reaches the verdict path — so a bad flag on `docs
|
|
482
|
+
// references check` is a usage error of `docs references check` (3), never
|
|
483
|
+
// one of `docs references` (2).
|
|
484
|
+
positionals: PositionalMode.None,
|
|
485
|
+
subverbs: [
|
|
486
|
+
{
|
|
487
|
+
name: docsReferencesCheckCommand.name,
|
|
488
|
+
description: docsReferencesCheckCommand.description,
|
|
489
|
+
usage: docsReferencesCheckCommand.usage,
|
|
490
|
+
positionals: PositionalMode.None,
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
name: docsReferencesExplainCommand.name,
|
|
494
|
+
description: docsReferencesExplainCommand.description,
|
|
495
|
+
usage: docsReferencesExplainCommand.usage,
|
|
496
|
+
positionals: PositionalMode.Free,
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
name: docsReferencesListCommand.name,
|
|
500
|
+
description: docsReferencesListCommand.description,
|
|
501
|
+
usage: docsReferencesListCommand.usage,
|
|
502
|
+
positionals: PositionalMode.None,
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
booleanFlags: new Set(['json']),
|
|
506
|
+
async run(args) {
|
|
507
|
+
const sub = args.positional[0];
|
|
508
|
+
const rest = { ...args, positional: args.positional.slice(1) };
|
|
509
|
+
if (sub === 'check')
|
|
510
|
+
return docsReferencesCheckCommand.run(rest);
|
|
511
|
+
if (sub === 'explain')
|
|
512
|
+
return docsReferencesExplainCommand.run(rest);
|
|
513
|
+
if (sub === 'list')
|
|
514
|
+
return docsReferencesListCommand.run(rest);
|
|
515
|
+
// Only a bare `shrk docs references` lands here: the guard refused any
|
|
516
|
+
// other token before this body ran.
|
|
517
|
+
process.stderr.write('Usage: shrk docs references check | explain --id <id> | list\n');
|
|
518
|
+
return ExitCode.UsageError;
|
|
519
|
+
},
|
|
520
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.command.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.command.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.command.ts"],"names":[],"mappings":"AAwBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAmShC,eAAO,MAAM,aAAa,EAAE,eAc3B,CAAC;AA4gBF,eAAO,MAAM,qBAAqB,EAAE,eAmCnC,CAAC;AAuDF,eAAO,MAAM,yBAAyB,EAAE,eAavC,CAAC;AAIF,eAAO,MAAM,wBAAwB,EAAE,eA2CtC,CAAC;AAgCF,eAAO,MAAM,6BAA6B,EAAE,eAa3C,CAAC"}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { detectGraphFreshness } from '@shrkcrft/graph';
|
|
2
|
+
import { buildAcknowledgement, buildAiReadinessReport, buildSuppressionEntry, detectUnregisteredExports, doctorSuppressionsFile, DoctorSeverity, filterDoctorResult, inspectSharkcraft, loadDoctorSuppressions, renderAcknowledgementsText, doctorVerdict, runDoctor, saveDoctorSuppressions, summarizeAcknowledgements, } from '@shrkcrft/inspector';
|
|
2
3
|
import { detectProjectShape } from '@shrkcrft/workspace';
|
|
3
4
|
import { loadSurfaceContext } from "../surface/load-surface-context.js";
|
|
4
5
|
import { buildSurfaceSummary } from "../surface/surface-summary.js";
|
|
5
6
|
import { renderShapeLine } from "../surface/shape-defaults.js";
|
|
6
7
|
import { existsSync } from 'node:fs';
|
|
7
8
|
import { flagBool, flagNumber, flagString, flagList, resolveCwd, } from "../command-registry.js";
|
|
9
|
+
import { PositionalMode } from "../dispatch/positional-mode.js";
|
|
8
10
|
import { SemanticIndex, listIndexableFiles } from '@shrkcrft/embeddings';
|
|
9
11
|
import { asJson, header, kv } from "../output/format-output.js";
|
|
10
12
|
import { maybeRunInWatchMode } from "../output/watch-loop.js";
|
|
11
13
|
import { doctorHints, renderFailureHints } from "../output/failure-hints.js";
|
|
14
|
+
import { settleVerdict } from "../gates/settle-verdict.js";
|
|
15
|
+
import { verdictLine } from "../gates/verdict-line.js";
|
|
12
16
|
import { foldDoctorChecks, renderFoldedSummary, DoctorState, } from "../doctor/doctor-tags.js";
|
|
13
17
|
import { enrichWithLlmRecommendations, renderRecommendationsMarkdown, } from '@shrkcrft/ai';
|
|
14
18
|
const SEVERITY_LABEL = {
|
|
@@ -157,6 +161,39 @@ function augmentWithSemanticIndexCheck(result, cwd) {
|
|
|
157
161
|
summary.errors = (summary.errors ?? 0) + 1;
|
|
158
162
|
return { ...result, checks, summary };
|
|
159
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* "Unregistered entry exports" (round 11 §3.1): an entry a group module exports
|
|
166
|
+
* that the aggregator registering it never lists is silently invisible. Added
|
|
167
|
+
* only when something is found (an error → exit 1); a clean repo sees no new
|
|
168
|
+
* line. The check lives in the inspector (`detectUnregisteredExports`) and is
|
|
169
|
+
* async (it imports the group modules), so it is appended here.
|
|
170
|
+
*/
|
|
171
|
+
async function augmentWithUnregisteredExports(result, inspection) {
|
|
172
|
+
let found = [];
|
|
173
|
+
try {
|
|
174
|
+
found = await detectUnregisteredExports(inspection);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
if (found.length === 0)
|
|
180
|
+
return result;
|
|
181
|
+
const shown = found.slice(0, 10).map((u) => `${u.group}${u.line > 0 ? `:${u.line}` : ''} — ${u.message}`);
|
|
182
|
+
const more = found.length > shown.length ? ` (+${found.length - shown.length} more)` : '';
|
|
183
|
+
const check = {
|
|
184
|
+
id: 'unregistered-entry-exports',
|
|
185
|
+
title: 'Unregistered entry exports',
|
|
186
|
+
severity: DoctorSeverity.Error,
|
|
187
|
+
category: 'unregistered-entry-exports',
|
|
188
|
+
code: 'unregistered-export',
|
|
189
|
+
message: `${found.length} exported entr${found.length === 1 ? 'y is' : 'ies are'} never registered, so no lookup can see ${found.length === 1 ? 'it' : 'them'}: ${shown.join('; ')}${more}`,
|
|
190
|
+
fix: "Add each export to its aggregator's array, or re-export the group module with `export * from './<group>'`.",
|
|
191
|
+
};
|
|
192
|
+
const summary = { ...result.summary, errors: (result.summary.errors ?? 0) + 1 };
|
|
193
|
+
// An error check is a failed doctor: `passed` is what the exit code, the
|
|
194
|
+
// JSON `ready` and the Verdict line all read, so it must flip with it.
|
|
195
|
+
return { ...result, passed: false, checks: [...result.checks, check], summary };
|
|
196
|
+
}
|
|
160
197
|
function renderSemanticIndexCheck(report) {
|
|
161
198
|
if (!report.hasIndex) {
|
|
162
199
|
return {
|
|
@@ -214,6 +251,9 @@ function renderSemanticIndexCheck(report) {
|
|
|
214
251
|
}
|
|
215
252
|
export const doctorCommand = {
|
|
216
253
|
name: 'doctor',
|
|
254
|
+
// Mixed-mode: suppress / suppressions / acknowledge / acknowledgements are
|
|
255
|
+
// trie children; a bare token reaching this handler used to run the doctor.
|
|
256
|
+
positionals: PositionalMode.None,
|
|
217
257
|
description: 'Validate the local SharkCraft setup (config, knowledge, templates, project). `--focus errors|warnings-new|info`, `--hide <category,...>`, `--quiet-known` filter the headline view using `sharkcraft/doctor.suppressions.json`. `--watch`/`--once`/`--debounce` for live mode. `--explain-quality` shows the per-warning "why this matters" line so warnings stop being permanent yellow noise. `--blockers` shows only must-fix findings (errors + warning-category in {config-invalid, pack-signature-invalid, plan-signature-divergent, asset-load-failed}); exit code is non-zero iff a blocker remains. `--llm-recommendations` layers a local-LLM-derived list of concrete next-steps onto the deterministic output (no-op when no provider is reachable). Subcommands: `suppress`, `suppressions list|check`, `watch`.',
|
|
218
258
|
usage: 'shrk [--cwd <dir>] doctor [--no-config] [--json] [--strict[=errors|warnings|all]] [--blockers] [--show-advisory] [--min-score <0-100>] [--focus errors,warnings-new,info] [--hide action-hint-quality,...] [--quiet-known] [--explain-quality] [--llm-recommendations] [--provider auto|ollama|llamacpp] [--watch [--once] [--debounce N]]',
|
|
219
259
|
async run(args) {
|
|
@@ -236,7 +276,7 @@ async function doctorCommandImpl(args) {
|
|
|
236
276
|
inspectOpts.loaderTimeoutMs = loaderTimeout;
|
|
237
277
|
}
|
|
238
278
|
const inspection = await inspectSharkcraft(inspectOpts);
|
|
239
|
-
const result = augmentWithSemanticIndexCheck(runDoctor(inspection), cwd);
|
|
279
|
+
const result = await augmentWithUnregisteredExports(augmentWithSemanticIndexCheck(runDoctor(inspection, { graphDivergence: detectGraphFreshness(cwd) }), cwd), inspection);
|
|
240
280
|
const report = buildAiReadinessReport(inspection);
|
|
241
281
|
if (debug) {
|
|
242
282
|
process.stderr.write(`[debug] inspection elapsed ${inspection.inspectionElapsedMs}ms cache=${inspection.cacheEnabled ? 'on' : 'off'} loaders=${inspection.loaderDiagnostics.length}\n`);
|
|
@@ -330,7 +370,7 @@ async function doctorCommandImpl(args) {
|
|
|
330
370
|
// When --blockers is set, the exit code reflects ONLY the
|
|
331
371
|
// remaining blocker set. This is the agent-friendly contract: 0 means
|
|
332
372
|
// "nothing must-fix", 1 means "at least one blocker remains".
|
|
333
|
-
const
|
|
373
|
+
const proposedExitCode = noConfigLenient
|
|
334
374
|
? 0
|
|
335
375
|
: blockersOnly
|
|
336
376
|
? blockerCount > 0
|
|
@@ -339,6 +379,13 @@ async function doctorCommandImpl(args) {
|
|
|
339
379
|
: (result.passed && !strictEval.failed && !minScoreFailed && !ackExpired)
|
|
340
380
|
? 0
|
|
341
381
|
: 1;
|
|
382
|
+
// A scope the doctor could not verify (a compiled pack build with no build
|
|
383
|
+
// record, never compared with its source) settles a clean run to NOT
|
|
384
|
+
// VERIFIED (2), as `packs doctor` does. It never reads "Ready ✓". The
|
|
385
|
+
// advisory `--no-config` run and the filtered `--blockers` view keep
|
|
386
|
+
// their own contracts.
|
|
387
|
+
const doctorSettled = noConfigLenient || blockersOnly ? undefined : settleVerdict(proposedExitCode, result.coverage ?? []);
|
|
388
|
+
const overallExitCode = doctorSettled?.exit ?? proposedExitCode;
|
|
342
389
|
if (flagBool(args, 'json')) {
|
|
343
390
|
// Also compute the folded view for machine consumers so JSON
|
|
344
391
|
// callers see source/state tags + folded counts.
|
|
@@ -366,7 +413,9 @@ async function doctorCommandImpl(args) {
|
|
|
366
413
|
}
|
|
367
414
|
process.stdout.write(asJson({
|
|
368
415
|
targetRoot: inspection.projectRoot,
|
|
369
|
-
|
|
416
|
+
// THE doctor settlement (`doctorVerdict`), shared with `shrk check`,
|
|
417
|
+
// the dashboard and MCP: never ready over an unverified scope.
|
|
418
|
+
ready: doctorVerdict(result).ready && inspection.knowledgeEntries.length > 0,
|
|
370
419
|
strict: strictMode,
|
|
371
420
|
strictCountedWarnings: strictEval.countedWarnings,
|
|
372
421
|
strictExcludedWarnings: strictEval.excludedWarnings,
|
|
@@ -374,6 +423,7 @@ async function doctorCommandImpl(args) {
|
|
|
374
423
|
strictFailed: strictEval.failed,
|
|
375
424
|
minScoreFailed,
|
|
376
425
|
exitCode: overallExitCode,
|
|
426
|
+
...(doctorSettled && doctorSettled.shortfalls.length > 0 ? { shortfalls: doctorSettled.shortfalls } : {}),
|
|
377
427
|
// Blockers preset state. Shape stays stable when --blockers is off.
|
|
378
428
|
blockers: blockersOnly
|
|
379
429
|
? {
|
|
@@ -541,6 +591,11 @@ async function doctorCommandImpl(args) {
|
|
|
541
591
|
if (noConfigLenient) {
|
|
542
592
|
process.stdout.write('\nVerdict: --no-config mode — repo has no sharkcraft/ yet (advisory). Detection works regardless.\n');
|
|
543
593
|
}
|
|
594
|
+
else if (doctorSettled?.verdict === 'not-verified') {
|
|
595
|
+
const line = verdictLine(doctorSettled, '', 'Verdict: NOT VERIFIED — part of the setup could not be checked.');
|
|
596
|
+
if (line)
|
|
597
|
+
process.stdout.write(`\n${line}\n`);
|
|
598
|
+
}
|
|
544
599
|
else if (result.passed && hasContent) {
|
|
545
600
|
process.stdout.write('\nVerdict: Ready for AI-agent use. ✓\n');
|
|
546
601
|
}
|
|
@@ -707,7 +762,7 @@ async function suppressionsListRun(args) {
|
|
|
707
762
|
async function suppressionsCheckRun(args) {
|
|
708
763
|
const cwd = resolveCwd(args);
|
|
709
764
|
const inspection = await inspectSharkcraft({ cwd });
|
|
710
|
-
const result = runDoctor(inspection);
|
|
765
|
+
const result = runDoctor(inspection, { graphDivergence: detectGraphFreshness(cwd) });
|
|
711
766
|
const cfg = loadDoctorSuppressions(cwd);
|
|
712
767
|
const filtered = filterDoctorResult(result, { suppressions: cfg.doctorSuppressions });
|
|
713
768
|
const unused = filtered.appliedSuppressions.filter((a) => a.matched === 0);
|