@shrkcrft/cli 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +15 -0
- package/dist/asset-preview/apply-action-hint-stub.d.ts +28 -0
- package/dist/asset-preview/apply-action-hint-stub.d.ts.map +1 -0
- package/dist/asset-preview/apply-action-hint-stub.js +170 -0
- package/dist/asset-preview/apply-asset-preview.d.ts +31 -0
- package/dist/asset-preview/apply-asset-preview.d.ts.map +1 -0
- package/dist/asset-preview/apply-asset-preview.js +210 -0
- package/dist/asset-preview/apply-knowledge-stale-fix.d.ts +37 -0
- package/dist/asset-preview/apply-knowledge-stale-fix.d.ts.map +1 -0
- package/dist/asset-preview/apply-knowledge-stale-fix.js +344 -0
- package/dist/asset-preview/apply-missing-barrel.d.ts +15 -0
- package/dist/asset-preview/apply-missing-barrel.d.ts.map +1 -0
- package/dist/asset-preview/apply-missing-barrel.js +65 -0
- package/dist/asset-preview/apply-template-drift-fix.d.ts +21 -0
- package/dist/asset-preview/apply-template-drift-fix.d.ts.map +1 -0
- package/dist/asset-preview/apply-template-drift-fix.js +125 -0
- package/dist/asset-preview/apply-template-update.d.ts +43 -0
- package/dist/asset-preview/apply-template-update.d.ts.map +1 -0
- package/dist/asset-preview/apply-template-update.js +257 -0
- package/dist/asset-preview/entry-mutator.d.ts +106 -0
- package/dist/asset-preview/entry-mutator.d.ts.map +1 -0
- package/dist/asset-preview/entry-mutator.js +428 -0
- package/dist/authoring/authoring-kit.d.ts +36 -0
- package/dist/authoring/authoring-kit.d.ts.map +1 -0
- package/dist/authoring/authoring-kit.js +106 -0
- package/dist/command-registry.d.ts +158 -0
- package/dist/command-registry.d.ts.map +1 -0
- package/dist/command-registry.js +348 -0
- package/dist/commands/apply.command.d.ts +3 -0
- package/dist/commands/apply.command.d.ts.map +1 -0
- package/dist/commands/apply.command.js +879 -0
- package/dist/commands/architecture.command.d.ts +5 -0
- package/dist/commands/architecture.command.d.ts.map +1 -0
- package/dist/commands/architecture.command.js +141 -0
- package/dist/commands/ask.command.d.ts +3 -0
- package/dist/commands/ask.command.d.ts.map +1 -0
- package/dist/commands/ask.command.js +58 -0
- package/dist/commands/audit.command.d.ts +3 -0
- package/dist/commands/audit.command.d.ts.map +1 -0
- package/dist/commands/audit.command.js +141 -0
- package/dist/commands/biome.command.d.ts +7 -0
- package/dist/commands/biome.command.d.ts.map +1 -0
- package/dist/commands/biome.command.js +350 -0
- package/dist/commands/boundaries.command.d.ts +9 -0
- package/dist/commands/boundaries.command.d.ts.map +1 -0
- package/dist/commands/boundaries.command.js +326 -0
- package/dist/commands/brief.command.d.ts +3 -0
- package/dist/commands/brief.command.d.ts.map +1 -0
- package/dist/commands/brief.command.js +206 -0
- package/dist/commands/bundle.command.d.ts +3 -0
- package/dist/commands/bundle.command.d.ts.map +1 -0
- package/dist/commands/bundle.command.js +1183 -0
- package/dist/commands/changes.command.d.ts +3 -0
- package/dist/commands/changes.command.d.ts.map +1 -0
- package/dist/commands/changes.command.js +155 -0
- package/dist/commands/check.command.d.ts +3 -0
- package/dist/commands/check.command.d.ts.map +1 -0
- package/dist/commands/check.command.js +580 -0
- package/dist/commands/checks.command.d.ts +29 -0
- package/dist/commands/checks.command.d.ts.map +1 -0
- package/dist/commands/checks.command.js +521 -0
- package/dist/commands/ci.command.d.ts +3 -0
- package/dist/commands/ci.command.d.ts.map +1 -0
- package/dist/commands/ci.command.js +680 -0
- package/dist/commands/codemod.command.d.ts +3 -0
- package/dist/commands/codemod.command.d.ts.map +1 -0
- package/dist/commands/codemod.command.js +130 -0
- package/dist/commands/command-catalog.d.ts +265 -0
- package/dist/commands/command-catalog.d.ts.map +1 -0
- package/dist/commands/command-catalog.js +3255 -0
- package/dist/commands/commands.command.d.ts +92 -0
- package/dist/commands/commands.command.d.ts.map +1 -0
- package/dist/commands/commands.command.js +1208 -0
- package/dist/commands/constructs.command.d.ts +15 -0
- package/dist/commands/constructs.command.d.ts.map +1 -0
- package/dist/commands/constructs.command.js +669 -0
- package/dist/commands/context.command.d.ts +3 -0
- package/dist/commands/context.command.d.ts.map +1 -0
- package/dist/commands/context.command.js +120 -0
- package/dist/commands/contract-gate.command.d.ts +5 -0
- package/dist/commands/contract-gate.command.d.ts.map +1 -0
- package/dist/commands/contract-gate.command.js +208 -0
- package/dist/commands/contract-templates.command.d.ts +8 -0
- package/dist/commands/contract-templates.command.d.ts.map +1 -0
- package/dist/commands/contract-templates.command.js +151 -0
- package/dist/commands/contract.command.d.ts +3 -0
- package/dist/commands/contract.command.d.ts.map +1 -0
- package/dist/commands/contract.command.js +105 -0
- package/dist/commands/conventions.command.d.ts +8 -0
- package/dist/commands/conventions.command.d.ts.map +1 -0
- package/dist/commands/conventions.command.js +169 -0
- package/dist/commands/coverage.command.d.ts +3 -0
- package/dist/commands/coverage.command.d.ts.map +1 -0
- package/dist/commands/coverage.command.js +56 -0
- package/dist/commands/daily.commands.d.ts +5 -0
- package/dist/commands/daily.commands.d.ts.map +1 -0
- package/dist/commands/daily.commands.js +224 -0
- package/dist/commands/dashboard-export.command.d.ts +4 -0
- package/dist/commands/dashboard-export.command.d.ts.map +1 -0
- package/dist/commands/dashboard-export.command.js +86 -0
- package/dist/commands/dashboard.command.d.ts +3 -0
- package/dist/commands/dashboard.command.d.ts.map +1 -0
- package/dist/commands/dashboard.command.js +106 -0
- package/dist/commands/dev.command.d.ts +3 -0
- package/dist/commands/dev.command.d.ts.map +1 -0
- package/dist/commands/dev.command.js +1392 -0
- package/dist/commands/diagnostics.command.d.ts +5 -0
- package/dist/commands/diagnostics.command.d.ts.map +1 -0
- package/dist/commands/diagnostics.command.js +97 -0
- package/dist/commands/docs.command.d.ts +4 -0
- package/dist/commands/docs.command.d.ts.map +1 -0
- package/dist/commands/docs.command.js +34 -0
- package/dist/commands/doctor.command.d.ts +7 -0
- package/dist/commands/doctor.command.d.ts.map +1 -0
- package/dist/commands/doctor.command.js +682 -0
- package/dist/commands/drift.command.d.ts +3 -0
- package/dist/commands/drift.command.d.ts.map +1 -0
- package/dist/commands/drift.command.js +124 -0
- package/dist/commands/eslint.command.d.ts +7 -0
- package/dist/commands/eslint.command.d.ts.map +1 -0
- package/dist/commands/eslint.command.js +423 -0
- package/dist/commands/explore.command.d.ts +3 -0
- package/dist/commands/explore.command.d.ts.map +1 -0
- package/dist/commands/explore.command.js +65 -0
- package/dist/commands/export-bundle.command.d.ts +6 -0
- package/dist/commands/export-bundle.command.d.ts.map +1 -0
- package/dist/commands/export-bundle.command.js +96 -0
- package/dist/commands/export.command.d.ts +3 -0
- package/dist/commands/export.command.d.ts.map +1 -0
- package/dist/commands/export.command.js +83 -0
- package/dist/commands/feedback-dispatch.command.d.ts +12 -0
- package/dist/commands/feedback-dispatch.command.d.ts.map +1 -0
- package/dist/commands/feedback-dispatch.command.js +63 -0
- package/dist/commands/feedback.command.d.ts +11 -0
- package/dist/commands/feedback.command.d.ts.map +1 -0
- package/dist/commands/feedback.command.js +336 -0
- package/dist/commands/fix.command.d.ts +3 -0
- package/dist/commands/fix.command.d.ts.map +1 -0
- package/dist/commands/fix.command.js +776 -0
- package/dist/commands/gen.command.d.ts +3 -0
- package/dist/commands/gen.command.d.ts.map +1 -0
- package/dist/commands/gen.command.js +136 -0
- package/dist/commands/git.command.d.ts +6 -0
- package/dist/commands/git.command.d.ts.map +1 -0
- package/dist/commands/git.command.js +81 -0
- package/dist/commands/graph.command.d.ts +3 -0
- package/dist/commands/graph.command.d.ts.map +1 -0
- package/dist/commands/graph.command.js +287 -0
- package/dist/commands/grounding.command.d.ts +7 -0
- package/dist/commands/grounding.command.d.ts.map +1 -0
- package/dist/commands/grounding.command.js +54 -0
- package/dist/commands/help.command.d.ts +20 -0
- package/dist/commands/help.command.d.ts.map +1 -0
- package/dist/commands/help.command.js +129 -0
- package/dist/commands/helper.command.d.ts +6 -0
- package/dist/commands/helper.command.d.ts.map +1 -0
- package/dist/commands/helper.command.js +170 -0
- package/dist/commands/ide.command.d.ts +6 -0
- package/dist/commands/ide.command.d.ts.map +1 -0
- package/dist/commands/ide.command.js +340 -0
- package/dist/commands/impact.command.d.ts +3 -0
- package/dist/commands/impact.command.d.ts.map +1 -0
- package/dist/commands/impact.command.js +819 -0
- package/dist/commands/import.command.d.ts +3 -0
- package/dist/commands/import.command.d.ts.map +1 -0
- package/dist/commands/import.command.js +115 -0
- package/dist/commands/infer.command.d.ts +3 -0
- package/dist/commands/infer.command.d.ts.map +1 -0
- package/dist/commands/infer.command.js +227 -0
- package/dist/commands/ingest.command.d.ts +6 -0
- package/dist/commands/ingest.command.d.ts.map +1 -0
- package/dist/commands/ingest.command.js +532 -0
- package/dist/commands/init.command.d.ts +3 -0
- package/dist/commands/init.command.d.ts.map +1 -0
- package/dist/commands/init.command.js +300 -0
- package/dist/commands/inspect.command.d.ts +3 -0
- package/dist/commands/inspect.command.d.ts.map +1 -0
- package/dist/commands/inspect.command.js +122 -0
- package/dist/commands/knowledge-author.command.d.ts +22 -0
- package/dist/commands/knowledge-author.command.d.ts.map +1 -0
- package/dist/commands/knowledge-author.command.js +366 -0
- package/dist/commands/knowledge-propose.command.d.ts +3 -0
- package/dist/commands/knowledge-propose.command.d.ts.map +1 -0
- package/dist/commands/knowledge-propose.command.js +125 -0
- package/dist/commands/knowledge.command.d.ts +18 -0
- package/dist/commands/knowledge.command.d.ts.map +1 -0
- package/dist/commands/knowledge.command.js +538 -0
- package/dist/commands/languages.command.d.ts +3 -0
- package/dist/commands/languages.command.d.ts.map +1 -0
- package/dist/commands/languages.command.js +300 -0
- package/dist/commands/lint.command.d.ts +15 -0
- package/dist/commands/lint.command.d.ts.map +1 -0
- package/dist/commands/lint.command.js +194 -0
- package/dist/commands/mcp.command.d.ts +3 -0
- package/dist/commands/mcp.command.d.ts.map +1 -0
- package/dist/commands/mcp.command.js +203 -0
- package/dist/commands/memory.command.d.ts +11 -0
- package/dist/commands/memory.command.d.ts.map +1 -0
- package/dist/commands/memory.command.js +264 -0
- package/dist/commands/onboard.command.d.ts +3 -0
- package/dist/commands/onboard.command.d.ts.map +1 -0
- package/dist/commands/onboard.command.js +662 -0
- package/dist/commands/orchestrate.command.d.ts +3 -0
- package/dist/commands/orchestrate.command.d.ts.map +1 -0
- package/dist/commands/orchestrate.command.js +49 -0
- package/dist/commands/owners.command.d.ts +5 -0
- package/dist/commands/owners.command.d.ts.map +1 -0
- package/dist/commands/owners.command.js +113 -0
- package/dist/commands/ownership.command.d.ts +5 -0
- package/dist/commands/ownership.command.d.ts.map +1 -0
- package/dist/commands/ownership.command.js +117 -0
- package/dist/commands/pack-author.command.d.ts +30 -0
- package/dist/commands/pack-author.command.d.ts.map +1 -0
- package/dist/commands/pack-author.command.js +242 -0
- package/dist/commands/packs-new.d.ts +27 -0
- package/dist/commands/packs-new.d.ts.map +1 -0
- package/dist/commands/packs-new.js +805 -0
- package/dist/commands/packs.command.d.ts +15 -0
- package/dist/commands/packs.command.d.ts.map +1 -0
- package/dist/commands/packs.command.js +964 -0
- package/dist/commands/paths.command.d.ts +6 -0
- package/dist/commands/paths.command.d.ts.map +1 -0
- package/dist/commands/paths.command.js +97 -0
- package/dist/commands/pipelines.command.d.ts +9 -0
- package/dist/commands/pipelines.command.d.ts.map +1 -0
- package/dist/commands/pipelines.command.js +308 -0
- package/dist/commands/plan-check.command.d.ts +27 -0
- package/dist/commands/plan-check.command.d.ts.map +1 -0
- package/dist/commands/plan-check.command.js +150 -0
- package/dist/commands/plan-simulate.command.d.ts +3 -0
- package/dist/commands/plan-simulate.command.d.ts.map +1 -0
- package/dist/commands/plan-simulate.command.js +60 -0
- package/dist/commands/plan.command.d.ts +8 -0
- package/dist/commands/plan.command.d.ts.map +1 -0
- package/dist/commands/plan.command.js +139 -0
- package/dist/commands/playbooks.command.d.ts +10 -0
- package/dist/commands/playbooks.command.d.ts.map +1 -0
- package/dist/commands/playbooks.command.js +296 -0
- package/dist/commands/plugin.command.d.ts +11 -0
- package/dist/commands/plugin.command.d.ts.map +1 -0
- package/dist/commands/plugin.command.js +394 -0
- package/dist/commands/policy.command.d.ts +8 -0
- package/dist/commands/policy.command.d.ts.map +1 -0
- package/dist/commands/policy.command.js +451 -0
- package/dist/commands/pr.command.d.ts +3 -0
- package/dist/commands/pr.command.d.ts.map +1 -0
- package/dist/commands/pr.command.js +132 -0
- package/dist/commands/preflight.command.d.ts +3 -0
- package/dist/commands/preflight.command.d.ts.map +1 -0
- package/dist/commands/preflight.command.js +102 -0
- package/dist/commands/presets.command.d.ts +17 -0
- package/dist/commands/presets.command.d.ts.map +1 -0
- package/dist/commands/presets.command.js +647 -0
- package/dist/commands/profiles.command.d.ts +7 -0
- package/dist/commands/profiles.command.d.ts.map +1 -0
- package/dist/commands/profiles.command.js +151 -0
- package/dist/commands/provenance.command.d.ts +26 -0
- package/dist/commands/provenance.command.d.ts.map +1 -0
- package/dist/commands/provenance.command.js +237 -0
- package/dist/commands/quality.command.d.ts +5 -0
- package/dist/commands/quality.command.d.ts.map +1 -0
- package/dist/commands/quality.command.js +69 -0
- package/dist/commands/recommend.command.d.ts +4 -0
- package/dist/commands/recommend.command.d.ts.map +1 -0
- package/dist/commands/recommend.command.js +270 -0
- package/dist/commands/registrations.command.d.ts +3 -0
- package/dist/commands/registrations.command.d.ts.map +1 -0
- package/dist/commands/registrations.command.js +300 -0
- package/dist/commands/registry.command.d.ts +4 -0
- package/dist/commands/registry.command.d.ts.map +1 -0
- package/dist/commands/registry.command.js +37 -0
- package/dist/commands/release.command.d.ts +4 -0
- package/dist/commands/release.command.d.ts.map +1 -0
- package/dist/commands/release.command.js +639 -0
- package/dist/commands/repo.command.d.ts +3 -0
- package/dist/commands/repo.command.d.ts.map +1 -0
- package/dist/commands/repo.command.js +24 -0
- package/dist/commands/report.command.d.ts +3 -0
- package/dist/commands/report.command.d.ts.map +1 -0
- package/dist/commands/report.command.js +511 -0
- package/dist/commands/reposet.command.d.ts +6 -0
- package/dist/commands/reposet.command.d.ts.map +1 -0
- package/dist/commands/reposet.command.js +120 -0
- package/dist/commands/review.command.d.ts +3 -0
- package/dist/commands/review.command.d.ts.map +1 -0
- package/dist/commands/review.command.js +380 -0
- package/dist/commands/risk.command.d.ts +3 -0
- package/dist/commands/risk.command.d.ts.map +1 -0
- package/dist/commands/risk.command.js +56 -0
- package/dist/commands/rounds.command.d.ts +8 -0
- package/dist/commands/rounds.command.d.ts.map +1 -0
- package/dist/commands/rounds.command.js +180 -0
- package/dist/commands/rules.command.d.ts +49 -0
- package/dist/commands/rules.command.d.ts.map +1 -0
- package/dist/commands/rules.command.js +435 -0
- package/dist/commands/runtime.command.d.ts +3 -0
- package/dist/commands/runtime.command.d.ts.map +1 -0
- package/dist/commands/runtime.command.js +56 -0
- package/dist/commands/safety.command.d.ts +3 -0
- package/dist/commands/safety.command.d.ts.map +1 -0
- package/dist/commands/safety.command.js +117 -0
- package/dist/commands/scaffolds.command.d.ts +5 -0
- package/dist/commands/scaffolds.command.d.ts.map +1 -0
- package/dist/commands/scaffolds.command.js +122 -0
- package/dist/commands/schemas.command.d.ts +21 -0
- package/dist/commands/schemas.command.d.ts.map +1 -0
- package/dist/commands/schemas.command.js +296 -0
- package/dist/commands/search.command.d.ts +12 -0
- package/dist/commands/search.command.d.ts.map +1 -0
- package/dist/commands/search.command.js +275 -0
- package/dist/commands/self-config.command.d.ts +7 -0
- package/dist/commands/self-config.command.d.ts.map +1 -0
- package/dist/commands/self-config.command.js +156 -0
- package/dist/commands/self.command.d.ts +3 -0
- package/dist/commands/self.command.d.ts.map +1 -0
- package/dist/commands/self.command.js +117 -0
- package/dist/commands/simulate.command.d.ts +3 -0
- package/dist/commands/simulate.command.d.ts.map +1 -0
- package/dist/commands/simulate.command.js +54 -0
- package/dist/commands/spec.command.d.ts +29 -0
- package/dist/commands/spec.command.d.ts.map +1 -0
- package/dist/commands/spec.command.js +985 -0
- package/dist/commands/start-here.command.d.ts +3 -0
- package/dist/commands/start-here.command.d.ts.map +1 -0
- package/dist/commands/start-here.command.js +35 -0
- package/dist/commands/stats.command.d.ts +3 -0
- package/dist/commands/stats.command.d.ts.map +1 -0
- package/dist/commands/stats.command.js +88 -0
- package/dist/commands/surface.command.d.ts +15 -0
- package/dist/commands/surface.command.d.ts.map +1 -0
- package/dist/commands/surface.command.js +328 -0
- package/dist/commands/task-context.command.d.ts +7 -0
- package/dist/commands/task-context.command.d.ts.map +1 -0
- package/dist/commands/task-context.command.js +646 -0
- package/dist/commands/task.command.d.ts +3 -0
- package/dist/commands/task.command.d.ts.map +1 -0
- package/dist/commands/task.command.js +301 -0
- package/dist/commands/template-quality.command.d.ts +5 -0
- package/dist/commands/template-quality.command.d.ts.map +1 -0
- package/dist/commands/template-quality.command.js +128 -0
- package/dist/commands/templates.command.d.ts +26 -0
- package/dist/commands/templates.command.d.ts.map +1 -0
- package/dist/commands/templates.command.js +964 -0
- package/dist/commands/test.command.d.ts +3 -0
- package/dist/commands/test.command.d.ts.map +1 -0
- package/dist/commands/test.command.js +262 -0
- package/dist/commands/tests.command.d.ts +5 -0
- package/dist/commands/tests.command.d.ts.map +1 -0
- package/dist/commands/tests.command.js +97 -0
- package/dist/commands/trace.command.d.ts +3 -0
- package/dist/commands/trace.command.d.ts.map +1 -0
- package/dist/commands/trace.command.js +121 -0
- package/dist/commands/upgrade.command.d.ts +4 -0
- package/dist/commands/upgrade.command.d.ts.map +1 -0
- package/dist/commands/upgrade.command.js +43 -0
- package/dist/commands/version.command.d.ts +3 -0
- package/dist/commands/version.command.d.ts.map +1 -0
- package/dist/commands/version.command.js +10 -0
- package/dist/commands/why.command.d.ts +24 -0
- package/dist/commands/why.command.d.ts.map +1 -0
- package/dist/commands/why.command.js +119 -0
- package/dist/dashboard/dashboard-api-server.d.ts +21 -0
- package/dist/dashboard/dashboard-api-server.d.ts.map +1 -0
- package/dist/dashboard/dashboard-api-server.js +410 -0
- package/dist/dashboard/live-session-server.d.ts +18 -0
- package/dist/dashboard/live-session-server.d.ts.map +1 -0
- package/dist/dashboard/live-session-server.js +133 -0
- package/dist/diff/collect-changed-paths.d.ts +27 -0
- package/dist/diff/collect-changed-paths.d.ts.map +1 -0
- package/dist/diff/collect-changed-paths.js +68 -0
- package/dist/doctor/doctor-tags.d.ts +63 -0
- package/dist/doctor/doctor-tags.d.ts.map +1 -0
- package/dist/doctor/doctor-tags.js +146 -0
- package/dist/export/export-formats.d.ts +22 -0
- package/dist/export/export-formats.d.ts.map +1 -0
- package/dist/export/export-formats.js +135 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/init/detected-block.d.ts +57 -0
- package/dist/init/detected-block.d.ts.map +1 -0
- package/dist/init/detected-block.js +197 -0
- package/dist/init/gitignore.d.ts +30 -0
- package/dist/init/gitignore.d.ts.map +1 -0
- package/dist/init/gitignore.js +110 -0
- package/dist/init/init-templates.d.ts +6 -0
- package/dist/init/init-templates.d.ts.map +1 -0
- package/dist/init/init-templates.js +413 -0
- package/dist/main.d.ts +18 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +721 -0
- package/dist/output/failure-hints.d.ts +63 -0
- package/dist/output/failure-hints.d.ts.map +1 -0
- package/dist/output/failure-hints.js +165 -0
- package/dist/output/format-output.d.ts +9 -0
- package/dist/output/format-output.d.ts.map +1 -0
- package/dist/output/format-output.js +26 -0
- package/dist/output/print-error.d.ts +3 -0
- package/dist/output/print-error.d.ts.map +1 -0
- package/dist/output/print-error.js +14 -0
- package/dist/output/watch-loop.d.ts +37 -0
- package/dist/output/watch-loop.d.ts.map +1 -0
- package/dist/output/watch-loop.js +115 -0
- package/dist/schemas/json-schemas.d.ts +1630 -0
- package/dist/schemas/json-schemas.d.ts.map +1 -0
- package/dist/schemas/json-schemas.js +811 -0
- package/dist/surface/about.d.ts +10 -0
- package/dist/surface/about.d.ts.map +1 -0
- package/dist/surface/about.js +31 -0
- package/dist/surface/load-surface-context.d.ts +34 -0
- package/dist/surface/load-surface-context.d.ts.map +1 -0
- package/dist/surface/load-surface-context.js +100 -0
- package/dist/surface/no-args-landing.d.ts +7 -0
- package/dist/surface/no-args-landing.d.ts.map +1 -0
- package/dist/surface/no-args-landing.js +40 -0
- package/dist/surface/not-enabled-error.d.ts +24 -0
- package/dist/surface/not-enabled-error.d.ts.map +1 -0
- package/dist/surface/not-enabled-error.js +36 -0
- package/dist/surface/profiles.d.ts +37 -0
- package/dist/surface/profiles.d.ts.map +1 -0
- package/dist/surface/profiles.js +151 -0
- package/dist/surface/shape-defaults.d.ts +21 -0
- package/dist/surface/shape-defaults.d.ts.map +1 -0
- package/dist/surface/shape-defaults.js +50 -0
- package/dist/surface/spine-extractor.d.ts +38 -0
- package/dist/surface/spine-extractor.d.ts.map +1 -0
- package/dist/surface/spine-extractor.js +100 -0
- package/dist/surface/surface-config-writer.d.ts +59 -0
- package/dist/surface/surface-config-writer.d.ts.map +1 -0
- package/dist/surface/surface-config-writer.js +135 -0
- package/dist/surface/surface-summary.d.ts +66 -0
- package/dist/surface/surface-summary.d.ts.map +1 -0
- package/dist/surface/surface-summary.js +162 -0
- package/dist/surface/tier.d.ts +100 -0
- package/dist/surface/tier.d.ts.map +1 -0
- package/dist/surface/tier.js +172 -0
- package/dist/task-next/apply-batch-runner.d.ts +42 -0
- package/dist/task-next/apply-batch-runner.d.ts.map +1 -0
- package/dist/task-next/apply-batch-runner.js +192 -0
- package/dist/task-next/task-next-ranker.d.ts +75 -0
- package/dist/task-next/task-next-ranker.d.ts.map +1 -0
- package/dist/task-next/task-next-ranker.js +179 -0
- package/dist/usage/usage-log.d.ts +54 -0
- package/dist/usage/usage-log.d.ts.map +1 -0
- package/dist/usage/usage-log.js +105 -0
- package/dist/validation/run-validation-loop.d.ts +38 -0
- package/dist/validation/run-validation-loop.d.ts.map +1 -0
- package/dist/validation/run-validation-loop.js +100 -0
- package/package.json +72 -0
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
import { buildAcknowledgement, buildAiReadinessReport, buildSuppressionEntry, doctorSuppressionsFile, DoctorSeverity, filterDoctorResult, inspectSharkcraft, loadDoctorSuppressions, renderAcknowledgementsText, runDoctor, saveDoctorSuppressions, summarizeAcknowledgements, } from '@shrkcrft/inspector';
|
|
2
|
+
import { detectProjectShape } from '@shrkcrft/workspace';
|
|
3
|
+
import { loadSurfaceContext } from "../surface/load-surface-context.js";
|
|
4
|
+
import { buildSurfaceSummary } from "../surface/surface-summary.js";
|
|
5
|
+
import { renderShapeLine } from "../surface/shape-defaults.js";
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { flagBool, flagNumber, flagString, flagList, resolveCwd, } from "../command-registry.js";
|
|
8
|
+
import { asJson, header, kv } from "../output/format-output.js";
|
|
9
|
+
import { maybeRunInWatchMode } from "../output/watch-loop.js";
|
|
10
|
+
import { doctorHints, renderFailureHints } from "../output/failure-hints.js";
|
|
11
|
+
import { foldDoctorChecks, renderFoldedSummary, DoctorState, } from "../doctor/doctor-tags.js";
|
|
12
|
+
const SEVERITY_LABEL = {
|
|
13
|
+
[DoctorSeverity.Ok]: 'OK ',
|
|
14
|
+
[DoctorSeverity.Info]: 'INFO ',
|
|
15
|
+
[DoctorSeverity.Warning]: 'WARN ',
|
|
16
|
+
[DoctorSeverity.Error]: 'ERR ',
|
|
17
|
+
};
|
|
18
|
+
function resolveStrictMode(args) {
|
|
19
|
+
const explicit = flagString(args, 'strict');
|
|
20
|
+
if (explicit) {
|
|
21
|
+
if (explicit === 'errors' || explicit === 'warnings' || explicit === 'all') {
|
|
22
|
+
return explicit;
|
|
23
|
+
}
|
|
24
|
+
return 'warnings'; // unknown value → default strict behavior
|
|
25
|
+
}
|
|
26
|
+
if (flagBool(args, 'strict-all'))
|
|
27
|
+
return 'all';
|
|
28
|
+
if (flagBool(args, 'strict-warnings'))
|
|
29
|
+
return 'warnings';
|
|
30
|
+
if (flagBool(args, 'strict-errors'))
|
|
31
|
+
return 'errors';
|
|
32
|
+
if (flagBool(args, 'strict'))
|
|
33
|
+
return 'warnings';
|
|
34
|
+
return 'off';
|
|
35
|
+
}
|
|
36
|
+
function describeStrictMode(mode) {
|
|
37
|
+
switch (mode) {
|
|
38
|
+
case 'all':
|
|
39
|
+
return 'strict=all (every warning fails)';
|
|
40
|
+
case 'warnings':
|
|
41
|
+
return 'strict=warnings (structural warnings fail, hint-quality excluded)';
|
|
42
|
+
case 'errors':
|
|
43
|
+
return 'strict=errors (only errors fail)';
|
|
44
|
+
case 'off':
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function evaluateStrict(mode, checks, errorCount) {
|
|
49
|
+
if (mode === 'off' || mode === 'errors') {
|
|
50
|
+
return {
|
|
51
|
+
failed: false,
|
|
52
|
+
countedWarnings: 0,
|
|
53
|
+
excludedWarnings: 0,
|
|
54
|
+
reason: 'errors-only',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
let countedWarnings = 0;
|
|
58
|
+
let excludedWarnings = 0;
|
|
59
|
+
for (const c of checks) {
|
|
60
|
+
if (c.severity !== DoctorSeverity.Warning)
|
|
61
|
+
continue;
|
|
62
|
+
const isHintQuality = c.id.startsWith('actionhints-');
|
|
63
|
+
if (mode === 'warnings' && isHintQuality) {
|
|
64
|
+
excludedWarnings += 1;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
countedWarnings += 1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const failed = errorCount > 0 || countedWarnings > 0;
|
|
71
|
+
return {
|
|
72
|
+
failed,
|
|
73
|
+
countedWarnings,
|
|
74
|
+
excludedWarnings,
|
|
75
|
+
reason: mode === 'all'
|
|
76
|
+
? 'any warning'
|
|
77
|
+
: 'structural warnings only (hint-quality excluded)',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function buildFilterOptions(args, suppressions) {
|
|
81
|
+
const opts = { suppressions };
|
|
82
|
+
const focus = flagList(args, 'focus');
|
|
83
|
+
if (focus.length > 0) {
|
|
84
|
+
opts.focus = focus;
|
|
85
|
+
}
|
|
86
|
+
const hide = flagList(args, 'hide');
|
|
87
|
+
if (hide.length > 0)
|
|
88
|
+
opts.hide = hide;
|
|
89
|
+
if (flagBool(args, 'quiet-known'))
|
|
90
|
+
opts.quietKnown = true;
|
|
91
|
+
return opts;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Blockers-only preset.
|
|
95
|
+
*
|
|
96
|
+
* A finding is a blocker when:
|
|
97
|
+
* - severity = error, OR
|
|
98
|
+
* - severity = warning AND category is in BLOCKER_WARNING_CATEGORIES.
|
|
99
|
+
*
|
|
100
|
+
* Anything else (action-hint quality, advisory rules, known-noise
|
|
101
|
+
* suppressions) is NOT a blocker. The `--blockers` flag composes with
|
|
102
|
+
* `--json` and `--watch`; exit code is non-zero iff at least one blocker
|
|
103
|
+
* remains after filtering.
|
|
104
|
+
*/
|
|
105
|
+
const BLOCKER_WARNING_CATEGORIES = new Set([
|
|
106
|
+
'config-invalid',
|
|
107
|
+
'pack-signature-invalid',
|
|
108
|
+
'plan-signature-divergent',
|
|
109
|
+
'asset-load-failed',
|
|
110
|
+
// Engine-internal mappings: derivedCategory uses `id.split(...)[0]` for
|
|
111
|
+
// unknown prefixes, so canonical inspector finding ids land in these
|
|
112
|
+
// buckets. We allow-list the buckets explicitly so future additions to
|
|
113
|
+
// the inspector don't accidentally creep into "blockers".
|
|
114
|
+
'config',
|
|
115
|
+
'pack-doctor',
|
|
116
|
+
]);
|
|
117
|
+
function isBlockerCheck(check) {
|
|
118
|
+
if (check.severity === DoctorSeverity.Error)
|
|
119
|
+
return true;
|
|
120
|
+
if (check.severity !== DoctorSeverity.Warning)
|
|
121
|
+
return false;
|
|
122
|
+
const cat = (check.category ?? '').trim();
|
|
123
|
+
if (cat && BLOCKER_WARNING_CATEGORIES.has(cat))
|
|
124
|
+
return true;
|
|
125
|
+
// Some inspector findings emit the category via the id prefix only.
|
|
126
|
+
const id = (check.id ?? '').trim();
|
|
127
|
+
if (id.startsWith('pack-signature'))
|
|
128
|
+
return true;
|
|
129
|
+
if (id.startsWith('plan-signature'))
|
|
130
|
+
return true;
|
|
131
|
+
if (id.startsWith('asset-load'))
|
|
132
|
+
return true;
|
|
133
|
+
if (id.startsWith('config-invalid'))
|
|
134
|
+
return true;
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
async function runDoctorOnce(args) {
|
|
138
|
+
return doctorCommandImpl(args);
|
|
139
|
+
}
|
|
140
|
+
export const doctorCommand = {
|
|
141
|
+
name: 'doctor',
|
|
142
|
+
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. Subcommands: `suppress`, `suppressions list|check`, `watch`.',
|
|
143
|
+
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] [--watch [--once] [--debounce N]]',
|
|
144
|
+
async run(args) {
|
|
145
|
+
const watchExit = await maybeRunInWatchMode(args, runDoctorOnce);
|
|
146
|
+
if (watchExit !== null)
|
|
147
|
+
return watchExit;
|
|
148
|
+
return runDoctorOnce(args);
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
async function doctorCommandImpl(args) {
|
|
152
|
+
const cwd = resolveCwd(args);
|
|
153
|
+
const noCache = flagBool(args, 'no-cache');
|
|
154
|
+
const debug = flagBool(args, 'debug');
|
|
155
|
+
const inspectOpts = {
|
|
156
|
+
cwd,
|
|
157
|
+
useCache: !noCache,
|
|
158
|
+
};
|
|
159
|
+
const loaderTimeout = flagNumber(args, 'loader-timeout');
|
|
160
|
+
if (typeof loaderTimeout === 'number' && loaderTimeout > 0) {
|
|
161
|
+
inspectOpts.loaderTimeoutMs = loaderTimeout;
|
|
162
|
+
}
|
|
163
|
+
const inspection = await inspectSharkcraft(inspectOpts);
|
|
164
|
+
const result = runDoctor(inspection);
|
|
165
|
+
const report = buildAiReadinessReport(inspection);
|
|
166
|
+
if (debug) {
|
|
167
|
+
process.stderr.write(`[debug] inspection elapsed ${inspection.inspectionElapsedMs}ms cache=${inspection.cacheEnabled ? 'on' : 'off'} loaders=${inspection.loaderDiagnostics.length}\n`);
|
|
168
|
+
for (const d of inspection.loaderDiagnostics) {
|
|
169
|
+
process.stderr.write(`[debug] ${d.kind.padEnd(10)} ${d.status.padEnd(12)} ${String(d.elapsedMs).padStart(5)}ms count=${d.count} ${d.deduped ? '(deduped) ' : ''}${d.largeFile ? '(large) ' : ''}${d.filePath}` +
|
|
170
|
+
(d.errorMessage ? ` — ${d.errorMessage}` : '') +
|
|
171
|
+
'\n');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// `--no-config` mode. When the repo has no sharkcraft/, downgrade
|
|
175
|
+
// the missing-folder warning to info-equivalent (we suppress it from
|
|
176
|
+
// both the visible check list and the strict-failure accounting) and
|
|
177
|
+
// make the exit code lenient. The contract: doctor in --no-config
|
|
178
|
+
// mode never red-fails on "no sharkcraft folder"; it red-fails only
|
|
179
|
+
// on real config errors *if* the folder exists.
|
|
180
|
+
const noConfig = flagBool(args, 'no-config');
|
|
181
|
+
const sharkcraftMissing = !inspection.hasSharkcraftFolder;
|
|
182
|
+
if (noConfig && sharkcraftMissing) {
|
|
183
|
+
// Reuse the existing filter machinery — hide the canonical missing-
|
|
184
|
+
// folder warnings by category. We do not mutate the result; the
|
|
185
|
+
// filter view is used for headline + exit code only.
|
|
186
|
+
// The existing inspector emits these as warnings with `category:
|
|
187
|
+
// "sharkcraft-folder"`; if the implementation changes we still
|
|
188
|
+
// catch them via message regex below.
|
|
189
|
+
}
|
|
190
|
+
const strictMode = resolveStrictMode(args);
|
|
191
|
+
const minScore = flagNumber(args, 'min-score');
|
|
192
|
+
const strictEval = evaluateStrict(strictMode, result.checks, result.summary.errors);
|
|
193
|
+
const minScoreFailed = typeof minScore === 'number' && report.score < minScore;
|
|
194
|
+
// Surface acknowledgement state so doctor exit can fail on expired
|
|
195
|
+
// acknowledgements when the caller opts in.
|
|
196
|
+
const hideAcknowledged = flagBool(args, 'hide-acknowledged');
|
|
197
|
+
const failOnExpiredAcknowledgement = flagBool(args, 'fail-on-expired-acknowledgement');
|
|
198
|
+
const suppressionsCfg = loadDoctorSuppressions(cwd);
|
|
199
|
+
const ackSummary = summarizeAcknowledgements(suppressionsCfg.doctorSuppressions);
|
|
200
|
+
// When --hide-acknowledged is set, only entries with an explicit expiry
|
|
201
|
+
// (true acknowledgements) take effect; bare suppressions stay visible.
|
|
202
|
+
const effectiveSuppressions = hideAcknowledged
|
|
203
|
+
? ackSummary.acknowledgements
|
|
204
|
+
: suppressionsCfg.doctorSuppressions;
|
|
205
|
+
const filterOpts = buildFilterOptions(args, effectiveSuppressions);
|
|
206
|
+
const blockersOnly = flagBool(args, 'blockers');
|
|
207
|
+
const useFilter = (filterOpts.focus && filterOpts.focus.length > 0) ||
|
|
208
|
+
(filterOpts.hide && filterOpts.hide.length > 0) ||
|
|
209
|
+
filterOpts.quietKnown === true ||
|
|
210
|
+
effectiveSuppressions.length > 0;
|
|
211
|
+
const filtered = useFilter ? filterDoctorResult(result, filterOpts) : null;
|
|
212
|
+
let visibleChecks = filtered ? filtered.checks : result.checks;
|
|
213
|
+
// `--blockers` preset: keep only blocker-level findings. Applied
|
|
214
|
+
// AFTER the existing filter pass so acknowledgements / hides compose
|
|
215
|
+
// cleanly (an acknowledged blocker still shows when the user passes
|
|
216
|
+
// --blockers, since acknowledgements pre-filter the result above).
|
|
217
|
+
let blockerCount = 0;
|
|
218
|
+
if (blockersOnly) {
|
|
219
|
+
visibleChecks = visibleChecks
|
|
220
|
+
.map((c) => ({ ...c, category: c.category ?? '' }))
|
|
221
|
+
.filter((c) => isBlockerCheck(c));
|
|
222
|
+
blockerCount = visibleChecks.length;
|
|
223
|
+
}
|
|
224
|
+
// When --no-config is set and the repo has no sharkcraft folder,
|
|
225
|
+
// filter the "no sharkcraft folder" / "config missing" warnings so the
|
|
226
|
+
// user does not see noise. The check ids the inspector emits are
|
|
227
|
+
// stable, but we also fall back on the message text in case a future
|
|
228
|
+
// inspector renames them.
|
|
229
|
+
if (noConfig && sharkcraftMissing) {
|
|
230
|
+
visibleChecks = visibleChecks.filter((c) => {
|
|
231
|
+
const id = c.id ?? '';
|
|
232
|
+
const msg = c.message ?? '';
|
|
233
|
+
const isSharkcraftMissing = /^sharkcraft-folder|^config-file|^sharkcraft\.config/i.test(id) ||
|
|
234
|
+
/sharkcraft.*folder|sharkcraft\.config|no sharkcraft/i.test(msg);
|
|
235
|
+
return !isSharkcraftMissing;
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
const ackExpired = ackSummary.expired.length > 0 && failOnExpiredAcknowledgement;
|
|
239
|
+
// Under --no-config + missing sharkcraft, treat the run as advisory: do not
|
|
240
|
+
// red-fail on the inspector's "no sharkcraft" errors / warnings.
|
|
241
|
+
const noConfigLenient = noConfig && sharkcraftMissing;
|
|
242
|
+
// When --blockers is set, the exit code reflects ONLY the
|
|
243
|
+
// remaining blocker set. This is the agent-friendly contract: 0 means
|
|
244
|
+
// "nothing must-fix", 1 means "at least one blocker remains".
|
|
245
|
+
const overallExitCode = noConfigLenient
|
|
246
|
+
? 0
|
|
247
|
+
: blockersOnly
|
|
248
|
+
? blockerCount > 0
|
|
249
|
+
? 1
|
|
250
|
+
: 0
|
|
251
|
+
: (result.passed && !strictEval.failed && !minScoreFailed && !ackExpired)
|
|
252
|
+
? 0
|
|
253
|
+
: 1;
|
|
254
|
+
if (flagBool(args, 'json')) {
|
|
255
|
+
// Also compute the folded view for machine consumers so JSON
|
|
256
|
+
// callers see source/state tags + folded counts.
|
|
257
|
+
const jsonFold = foldDoctorChecks(visibleChecks, {
|
|
258
|
+
ack: {
|
|
259
|
+
acknowledgements: ackSummary.acknowledgements,
|
|
260
|
+
expiredAcknowledgements: ackSummary.expired,
|
|
261
|
+
},
|
|
262
|
+
showAdvisory: flagBool(args, 'show-advisory'),
|
|
263
|
+
showAll: strictMode !== 'off',
|
|
264
|
+
});
|
|
265
|
+
// Project shape + surface totals JSON block.
|
|
266
|
+
let shape = null;
|
|
267
|
+
let surfaceSummary = null;
|
|
268
|
+
try {
|
|
269
|
+
shape = detectProjectShape({
|
|
270
|
+
projectRoot: inspection.projectRoot,
|
|
271
|
+
packageJson: inspection.workspace.raw.packageJson,
|
|
272
|
+
});
|
|
273
|
+
const ctx = await loadSurfaceContext({ cwd: inspection.projectRoot, inspection });
|
|
274
|
+
surfaceSummary = buildSurfaceSummary(ctx.context);
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// ignore
|
|
278
|
+
}
|
|
279
|
+
process.stdout.write(asJson({
|
|
280
|
+
targetRoot: inspection.projectRoot,
|
|
281
|
+
ready: result.passed && inspection.knowledgeEntries.length > 0,
|
|
282
|
+
strict: strictMode,
|
|
283
|
+
strictCountedWarnings: strictEval.countedWarnings,
|
|
284
|
+
strictExcludedWarnings: strictEval.excludedWarnings,
|
|
285
|
+
minScore: minScore ?? null,
|
|
286
|
+
strictFailed: strictEval.failed,
|
|
287
|
+
minScoreFailed,
|
|
288
|
+
exitCode: overallExitCode,
|
|
289
|
+
// Blockers preset state. Shape stays stable when --blockers is off.
|
|
290
|
+
blockers: blockersOnly
|
|
291
|
+
? {
|
|
292
|
+
enabled: true,
|
|
293
|
+
count: blockerCount,
|
|
294
|
+
categories: [...BLOCKER_WARNING_CATEGORIES],
|
|
295
|
+
excludes: ['action-hint-quality', 'advisory-rule', 'known-noise'],
|
|
296
|
+
}
|
|
297
|
+
: { enabled: false },
|
|
298
|
+
// Adaptive surface + project shape.
|
|
299
|
+
shape: shape ? { kind: shape.shape, evidence: shape.evidence } : null,
|
|
300
|
+
surface: surfaceSummary
|
|
301
|
+
? {
|
|
302
|
+
core: surfaceSummary.totals.core,
|
|
303
|
+
extended: surfaceSummary.totals.extended,
|
|
304
|
+
experimental: surfaceSummary.totals.experimental,
|
|
305
|
+
visibleInHelp: surfaceSummary.totals.visible,
|
|
306
|
+
callable: surfaceSummary.totals.callable,
|
|
307
|
+
}
|
|
308
|
+
: null,
|
|
309
|
+
aiReadiness: report,
|
|
310
|
+
acknowledgements: {
|
|
311
|
+
active: ackSummary.acknowledgements.length,
|
|
312
|
+
expiringSoon: ackSummary.expiringSoon.length,
|
|
313
|
+
expired: ackSummary.expired.length,
|
|
314
|
+
bareSuppressions: ackSummary.bareSuppressions.length,
|
|
315
|
+
failOnExpired: failOnExpiredAcknowledgement,
|
|
316
|
+
hideAcknowledged,
|
|
317
|
+
},
|
|
318
|
+
folded: {
|
|
319
|
+
counts: jsonFold.counts,
|
|
320
|
+
visible: jsonFold.visible.length,
|
|
321
|
+
folded: jsonFold.folded.length,
|
|
322
|
+
},
|
|
323
|
+
tags: jsonFold.tagged.map((t) => ({
|
|
324
|
+
id: t.check.id,
|
|
325
|
+
source: t.source,
|
|
326
|
+
state: t.state,
|
|
327
|
+
})),
|
|
328
|
+
...result,
|
|
329
|
+
...(filtered ? { filtered } : {}),
|
|
330
|
+
}) + '\n');
|
|
331
|
+
return overallExitCode;
|
|
332
|
+
}
|
|
333
|
+
process.stdout.write(header('SharkCraft doctor'));
|
|
334
|
+
process.stdout.write(kv('target root', inspection.projectRoot) + '\n');
|
|
335
|
+
process.stdout.write(kv('sharkcraft folder', inspection.sharkcraftDir ?? '(missing)') + '\n');
|
|
336
|
+
// Project shape + surface totals one-liner.
|
|
337
|
+
try {
|
|
338
|
+
const detection = detectProjectShape({
|
|
339
|
+
projectRoot: inspection.projectRoot,
|
|
340
|
+
packageJson: inspection.workspace.raw.packageJson,
|
|
341
|
+
});
|
|
342
|
+
process.stdout.write(kv('shape', renderShapeLine(detection).replace(/^Project shape: /, '')) + '\n');
|
|
343
|
+
const { context } = await loadSurfaceContext({ cwd: inspection.projectRoot, inspection });
|
|
344
|
+
const summary = buildSurfaceSummary(context);
|
|
345
|
+
process.stdout.write(kv('surface', `${summary.totals.core} core + ${summary.totals.extended} extended (${summary.tiers.extended.filter((c) => c.hidden).length} hidden, ${summary.tiers.experimental.filter((c) => c.enabled).length} experimental enabled)`) + '\n');
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
// ignore shape detection errors — doctor must not fail on the audit line.
|
|
349
|
+
}
|
|
350
|
+
if (strictMode !== 'off') {
|
|
351
|
+
process.stdout.write(kv('mode', describeStrictMode(strictMode)) + '\n');
|
|
352
|
+
}
|
|
353
|
+
if (typeof minScore === 'number') {
|
|
354
|
+
process.stdout.write(kv('min readiness', `${minScore}`) + '\n');
|
|
355
|
+
}
|
|
356
|
+
if (blockersOnly) {
|
|
357
|
+
process.stdout.write(kv('mode', 'blockers-only — errors + warnings in {' +
|
|
358
|
+
[...BLOCKER_WARNING_CATEGORIES].join(', ') +
|
|
359
|
+
'}; excludes action-hint-quality, advisory-rule, known-noise') + '\n');
|
|
360
|
+
}
|
|
361
|
+
process.stdout.write('\n');
|
|
362
|
+
const explainQuality = flagBool(args, 'explain-quality');
|
|
363
|
+
// Fold advisory / acknowledged warnings into a summary line by
|
|
364
|
+
// default. `--show-advisory` (or any `--strict` variant) restores the
|
|
365
|
+
// full inline view.
|
|
366
|
+
const showAdvisory = flagBool(args, 'show-advisory');
|
|
367
|
+
const showAll = strictMode !== 'off';
|
|
368
|
+
const fold = foldDoctorChecks(visibleChecks, {
|
|
369
|
+
ack: {
|
|
370
|
+
acknowledgements: ackSummary.acknowledgements,
|
|
371
|
+
expiredAcknowledgements: ackSummary.expired,
|
|
372
|
+
},
|
|
373
|
+
showAdvisory,
|
|
374
|
+
showAll,
|
|
375
|
+
});
|
|
376
|
+
for (const t of fold.visible) {
|
|
377
|
+
const c = t.check;
|
|
378
|
+
const label = SEVERITY_LABEL[c.severity];
|
|
379
|
+
const stateTag = t.state === DoctorState.Blocker
|
|
380
|
+
? ' [blocker]'
|
|
381
|
+
: t.state === DoctorState.Advisory
|
|
382
|
+
? ' [advisory]'
|
|
383
|
+
: t.state === DoctorState.Acknowledged
|
|
384
|
+
? ' [acknowledged]'
|
|
385
|
+
: t.state === DoctorState.ExpiredAcknowledgement
|
|
386
|
+
? ' [expired-ack]'
|
|
387
|
+
: '';
|
|
388
|
+
const sourceTag = ` [src:${t.source}]`;
|
|
389
|
+
const codeTag = c.code ? ` (${c.code})` : '';
|
|
390
|
+
process.stdout.write(`${label} ${c.title}${codeTag}${stateTag}${sourceTag} — ${c.message}\n`);
|
|
391
|
+
if (c.fix && !c.recommendedFix)
|
|
392
|
+
process.stdout.write(` fix: ${c.fix}\n`);
|
|
393
|
+
if (c.recommendedFix)
|
|
394
|
+
process.stdout.write(` fix: ${c.recommendedFix}\n`);
|
|
395
|
+
if (explainQuality && c.whyThisMatters) {
|
|
396
|
+
process.stdout.write(` why: ${c.whyThisMatters}\n`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (fold.folded.length > 0) {
|
|
400
|
+
const summary = renderFoldedSummary(fold);
|
|
401
|
+
if (summary)
|
|
402
|
+
process.stdout.write('\n' + summary);
|
|
403
|
+
}
|
|
404
|
+
process.stdout.write('\n');
|
|
405
|
+
if (filtered) {
|
|
406
|
+
const s = filtered.summary;
|
|
407
|
+
process.stdout.write(`Summary: ${s.ok} ok, ${s.info} info, ${s.warnings} active warnings, ${s.errors} errors\n`);
|
|
408
|
+
if (s.suppressedWarnings + s.suppressedInfo + s.suppressedErrors > 0) {
|
|
409
|
+
process.stdout.write(` (${s.suppressedWarnings + s.suppressedInfo + s.suppressedErrors} suppressed: ${s.suppressedWarnings} warning(s), ${s.suppressedInfo} info, ${s.suppressedErrors} error(s))\n`);
|
|
410
|
+
}
|
|
411
|
+
if (filtered.expiredSuppressions.length > 0) {
|
|
412
|
+
process.stdout.write(` ⚠ ${filtered.expiredSuppressions.length} expired suppression(s) — re-evaluate and remove from sharkcraft/doctor.suppressions.json\n`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
process.stdout.write(`Summary: ${result.summary.ok} ok, ${result.summary.info} info, ${result.summary.warnings} warnings, ${result.summary.errors} errors\n`);
|
|
417
|
+
}
|
|
418
|
+
void buildSuppressionEntry;
|
|
419
|
+
void doctorSuppressionsFile;
|
|
420
|
+
void saveDoctorSuppressions;
|
|
421
|
+
void existsSync;
|
|
422
|
+
if (strictMode === 'warnings' && strictEval.excludedWarnings > 0) {
|
|
423
|
+
process.stdout.write(` (strict=warnings excluded ${strictEval.excludedWarnings} hint-quality warning(s); use --strict=all to include)\n`);
|
|
424
|
+
}
|
|
425
|
+
// Surface acknowledgement state. Bare suppressions don't qualify as
|
|
426
|
+
// acknowledgements; expiring/expired ones get a callout so authors don't
|
|
427
|
+
// forget to re-evaluate.
|
|
428
|
+
if (ackSummary.acknowledgements.length > 0 ||
|
|
429
|
+
ackSummary.expired.length > 0 ||
|
|
430
|
+
ackSummary.expiringSoon.length > 0) {
|
|
431
|
+
process.stdout.write(`Acknowledgements: ${ackSummary.acknowledgements.length} active`);
|
|
432
|
+
if (ackSummary.expiringSoon.length > 0) {
|
|
433
|
+
process.stdout.write(`, ${ackSummary.expiringSoon.length} expiring soon`);
|
|
434
|
+
}
|
|
435
|
+
if (ackSummary.expired.length > 0) {
|
|
436
|
+
process.stdout.write(`, ${ackSummary.expired.length} expired`);
|
|
437
|
+
}
|
|
438
|
+
process.stdout.write('\n');
|
|
439
|
+
if (ackExpired) {
|
|
440
|
+
process.stdout.write(` → --fail-on-expired-acknowledgement set: failing on ${ackSummary.expired.length} expired acknowledgement(s).\n`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
const hasContent = inspection.knowledgeEntries.length > 0;
|
|
444
|
+
if (noConfigLenient) {
|
|
445
|
+
process.stdout.write('\nVerdict: --no-config mode — repo has no sharkcraft/ yet (advisory). Detection works regardless.\n');
|
|
446
|
+
}
|
|
447
|
+
else if (result.passed && hasContent) {
|
|
448
|
+
process.stdout.write('\nVerdict: Ready for AI-agent use. ✓\n');
|
|
449
|
+
}
|
|
450
|
+
else if (result.passed && !hasContent) {
|
|
451
|
+
process.stdout.write('\nVerdict: Setup is valid but empty. Add knowledge to sharkcraft/knowledge.ts.\n');
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
process.stdout.write('\nVerdict: Not ready yet. Fix the errors above and re-run doctor.\n');
|
|
455
|
+
}
|
|
456
|
+
// First-run UX: when sharkcraft/ is missing entirely, point the
|
|
457
|
+
// user at the zero-config init flow directly.
|
|
458
|
+
if (!inspection.sharkcraftDir) {
|
|
459
|
+
process.stdout.write('\nNothing here yet — try `shrk init --zero-config` to detect your stack and pick a preset.\n');
|
|
460
|
+
}
|
|
461
|
+
process.stdout.write(`\nAI-readiness: ${report.score} / 100 (${report.grade})\n`);
|
|
462
|
+
if (report.topRecommendations.length) {
|
|
463
|
+
// Keep the default doctor output short: top 3 recommendations,
|
|
464
|
+
// pass `--verbose` for the full list.
|
|
465
|
+
const verbose = flagBool(args, 'verbose');
|
|
466
|
+
const visible = verbose ? report.topRecommendations : report.topRecommendations.slice(0, 3);
|
|
467
|
+
process.stdout.write(`Top recommendations${verbose ? '' : ` (top ${visible.length})`}:\n`);
|
|
468
|
+
for (const r of visible)
|
|
469
|
+
process.stdout.write(` • ${r}\n`);
|
|
470
|
+
if (!verbose && report.topRecommendations.length > visible.length) {
|
|
471
|
+
process.stdout.write(` … (${report.topRecommendations.length - visible.length} more — pass --verbose to see all)\n`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (strictEval.failed) {
|
|
475
|
+
process.stdout.write(`\nStrict mode: failing because ${strictEval.countedWarnings} warning(s) + ${result.summary.errors} error(s) exist (${strictEval.reason}).\n`);
|
|
476
|
+
}
|
|
477
|
+
if (minScoreFailed) {
|
|
478
|
+
process.stdout.write(`\nMin-score gate: failing because readiness ${report.score} < ${minScore}.\n`);
|
|
479
|
+
}
|
|
480
|
+
// Failure-to-success hints surface only when something is wrong.
|
|
481
|
+
if (overallExitCode !== 0 || result.summary.warnings > 0) {
|
|
482
|
+
const folderMissing = result.checks.some((c) => c.id === 'sharkcraft-folder' && (c.severity === 'error' || c.severity === 'warning'));
|
|
483
|
+
process.stdout.write(renderFailureHints(doctorHints({ sharkcraftFolderMissing: folderMissing })));
|
|
484
|
+
}
|
|
485
|
+
// When there are preview-eligible findings (action-hints,
|
|
486
|
+
// knowledge-stale, template-drift, self-config, pack-conflict,
|
|
487
|
+
// stale-pack-signature), point the user at `shrk fix preview` so a
|
|
488
|
+
// draft patch is one command away. Preview-only; writes only under
|
|
489
|
+
// `.sharkcraft/fixes/`.
|
|
490
|
+
const previewEligible = result.checks.some((c) => (c.severity === 'warning' || c.severity === 'error') &&
|
|
491
|
+
(c.id.startsWith('actionhints-') ||
|
|
492
|
+
c.id.startsWith('action-hint') ||
|
|
493
|
+
c.id.startsWith('knowledge-stale') ||
|
|
494
|
+
c.id.startsWith('template-drift') ||
|
|
495
|
+
c.id.startsWith('self-config') ||
|
|
496
|
+
c.id.startsWith('pack-conflict') ||
|
|
497
|
+
c.id.startsWith('stale-pack-signature')));
|
|
498
|
+
if (previewEligible) {
|
|
499
|
+
process.stdout.write('\nDraft patch available — run `shrk fix preview` for a preview-only patch under `.sharkcraft/fixes/`.\n');
|
|
500
|
+
}
|
|
501
|
+
return overallExitCode;
|
|
502
|
+
}
|
|
503
|
+
export const doctorSuppressCommand = {
|
|
504
|
+
name: 'suppress',
|
|
505
|
+
description: 'Add a doctor finding to sharkcraft/doctor.suppressions.json. Requires --reason.',
|
|
506
|
+
usage: 'shrk doctor suppress [--id <stable-id>] [--code <finding-code>] [--category <cat>] --reason "<text>" [--expires-at <YYYY-MM-DD>] [--allow-error]',
|
|
507
|
+
async run(args) {
|
|
508
|
+
const cwd = resolveCwd(args);
|
|
509
|
+
const reason = flagString(args, 'reason');
|
|
510
|
+
if (!reason) {
|
|
511
|
+
process.stderr.write('Usage: shrk doctor suppress [--id|--code|--category] --reason "<text>"\n');
|
|
512
|
+
return 2;
|
|
513
|
+
}
|
|
514
|
+
const entry = buildSuppressionEntry({
|
|
515
|
+
...(flagString(args, 'id') ? { id: flagString(args, 'id') } : {}),
|
|
516
|
+
...(flagString(args, 'code') ? { code: flagString(args, 'code') } : {}),
|
|
517
|
+
...(flagString(args, 'category') ? { category: flagString(args, 'category') } : {}),
|
|
518
|
+
reason,
|
|
519
|
+
...(flagString(args, 'expires-at') ? { expiresAt: flagString(args, 'expires-at') } : {}),
|
|
520
|
+
...(flagBool(args, 'allow-error') ? { allowError: true } : {}),
|
|
521
|
+
});
|
|
522
|
+
if (!entry.id && !entry.code && !entry.category) {
|
|
523
|
+
process.stderr.write('At least one of --id, --code, --category is required.\n');
|
|
524
|
+
return 2;
|
|
525
|
+
}
|
|
526
|
+
const cfg = loadDoctorSuppressions(cwd);
|
|
527
|
+
const next = {
|
|
528
|
+
schema: cfg.schema,
|
|
529
|
+
doctorSuppressions: [...cfg.doctorSuppressions, entry],
|
|
530
|
+
};
|
|
531
|
+
const written = saveDoctorSuppressions(cwd, next);
|
|
532
|
+
process.stdout.write(`Suppression added → ${written}\n`);
|
|
533
|
+
process.stdout.write(` ${JSON.stringify(entry)}\n`);
|
|
534
|
+
return 0;
|
|
535
|
+
},
|
|
536
|
+
};
|
|
537
|
+
async function suppressionsListRun(args) {
|
|
538
|
+
const cwd = resolveCwd(args);
|
|
539
|
+
const cfg = loadDoctorSuppressions(cwd);
|
|
540
|
+
if (flagBool(args, 'json')) {
|
|
541
|
+
process.stdout.write(asJson(cfg) + '\n');
|
|
542
|
+
return 0;
|
|
543
|
+
}
|
|
544
|
+
if (cfg.doctorSuppressions.length === 0) {
|
|
545
|
+
process.stdout.write('No doctor suppressions configured.\n');
|
|
546
|
+
return 0;
|
|
547
|
+
}
|
|
548
|
+
process.stdout.write(header(`Doctor suppressions (${cfg.doctorSuppressions.length})`));
|
|
549
|
+
for (const s of cfg.doctorSuppressions) {
|
|
550
|
+
const key = s.id ?? s.code ?? s.category ?? '(unknown)';
|
|
551
|
+
const exp = s.expiresAt ? ` [expires ${s.expiresAt}]` : '';
|
|
552
|
+
process.stdout.write(` • ${key}${exp} — ${s.reason}\n`);
|
|
553
|
+
}
|
|
554
|
+
return 0;
|
|
555
|
+
}
|
|
556
|
+
async function suppressionsCheckRun(args) {
|
|
557
|
+
const cwd = resolveCwd(args);
|
|
558
|
+
const inspection = await inspectSharkcraft({ cwd });
|
|
559
|
+
const result = runDoctor(inspection);
|
|
560
|
+
const cfg = loadDoctorSuppressions(cwd);
|
|
561
|
+
const filtered = filterDoctorResult(result, { suppressions: cfg.doctorSuppressions });
|
|
562
|
+
const unused = filtered.appliedSuppressions.filter((a) => a.matched === 0);
|
|
563
|
+
if (flagBool(args, 'json')) {
|
|
564
|
+
process.stdout.write(asJson({ filtered, expired: filtered.expiredSuppressions, unused }) + '\n');
|
|
565
|
+
return filtered.expiredSuppressions.length === 0 && unused.length === 0 ? 0 : 1;
|
|
566
|
+
}
|
|
567
|
+
process.stdout.write(header('Doctor suppressions check'));
|
|
568
|
+
if (filtered.expiredSuppressions.length > 0) {
|
|
569
|
+
process.stdout.write(`Expired (${filtered.expiredSuppressions.length}):\n`);
|
|
570
|
+
for (const e of filtered.expiredSuppressions) {
|
|
571
|
+
process.stdout.write(` • ${e.id ?? e.code ?? e.category ?? '?'} [expired ${e.expiresAt}]\n`);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
if (unused.length > 0) {
|
|
575
|
+
process.stdout.write(`Unused (${unused.length}):\n`);
|
|
576
|
+
for (const u of unused) {
|
|
577
|
+
const e = u.entry;
|
|
578
|
+
process.stdout.write(` • ${e.id ?? e.code ?? e.category ?? '?'} — ${e.reason}\n`);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
if (filtered.expiredSuppressions.length === 0 && unused.length === 0) {
|
|
582
|
+
process.stdout.write('All suppressions still match.\n');
|
|
583
|
+
}
|
|
584
|
+
return filtered.expiredSuppressions.length === 0 && unused.length === 0 ? 0 : 1;
|
|
585
|
+
}
|
|
586
|
+
export const doctorSuppressionsCommand = {
|
|
587
|
+
name: 'suppressions',
|
|
588
|
+
description: 'List or check doctor suppressions. `shrk doctor suppressions list` / `... check`.',
|
|
589
|
+
usage: 'shrk doctor suppressions <list|check> [--json]',
|
|
590
|
+
async run(args) {
|
|
591
|
+
const verb = args.positional[0] ?? 'list';
|
|
592
|
+
const sub = { ...args, positional: args.positional.slice(1) };
|
|
593
|
+
if (verb === 'list')
|
|
594
|
+
return suppressionsListRun(sub);
|
|
595
|
+
if (verb === 'check')
|
|
596
|
+
return suppressionsCheckRun(sub);
|
|
597
|
+
process.stderr.write('Usage: shrk doctor suppressions <list|check>\n');
|
|
598
|
+
return 2;
|
|
599
|
+
},
|
|
600
|
+
};
|
|
601
|
+
// ─── Doctor acknowledgements (typed suppressions) ───────────────────
|
|
602
|
+
export const doctorAcknowledgeCommand = {
|
|
603
|
+
name: 'acknowledge',
|
|
604
|
+
description: 'Add an acknowledgement for a doctor finding. Requires --reason AND an explicit expiry (--expires-in 7d or --expires-at YYYY-MM-DD). Writes to sharkcraft/doctor.suppressions.json.',
|
|
605
|
+
usage: 'shrk doctor acknowledge [--id <stable-id>] [--code <code>] [--category <cat>] --reason "<text>" (--expires-in <7d|48h|2w>|--expires-at <ISO>) [--allow-error]',
|
|
606
|
+
async run(args) {
|
|
607
|
+
const cwd = resolveCwd(args);
|
|
608
|
+
const reason = flagString(args, 'reason');
|
|
609
|
+
const expiresIn = flagString(args, 'expires-in');
|
|
610
|
+
const expiresAt = flagString(args, 'expires-at');
|
|
611
|
+
const id = flagString(args, 'id');
|
|
612
|
+
const code = flagString(args, 'code');
|
|
613
|
+
const category = flagString(args, 'category');
|
|
614
|
+
if (!reason) {
|
|
615
|
+
process.stderr.write('Usage: shrk doctor acknowledge [--id|--code|--category] --reason "<text>" --expires-in 7d\n');
|
|
616
|
+
return 2;
|
|
617
|
+
}
|
|
618
|
+
const result = buildAcknowledgement({
|
|
619
|
+
...(id ? { id } : {}),
|
|
620
|
+
...(code ? { code } : {}),
|
|
621
|
+
...(category ? { category } : {}),
|
|
622
|
+
reason,
|
|
623
|
+
...(expiresIn ? { expiresIn } : {}),
|
|
624
|
+
...(expiresAt ? { expiresAt } : {}),
|
|
625
|
+
...(flagBool(args, 'allow-error') ? { allowError: true } : {}),
|
|
626
|
+
});
|
|
627
|
+
if (!result.ok || !result.entry) {
|
|
628
|
+
process.stderr.write(`Acknowledgement rejected: ${result.error}\n`);
|
|
629
|
+
return 2;
|
|
630
|
+
}
|
|
631
|
+
const cfg = loadDoctorSuppressions(cwd);
|
|
632
|
+
const next = {
|
|
633
|
+
schema: cfg.schema,
|
|
634
|
+
doctorSuppressions: [...cfg.doctorSuppressions, result.entry],
|
|
635
|
+
};
|
|
636
|
+
const written = saveDoctorSuppressions(cwd, next);
|
|
637
|
+
process.stdout.write(`Acknowledgement added → ${written}\n`);
|
|
638
|
+
process.stdout.write(` ${JSON.stringify(result.entry)}\n`);
|
|
639
|
+
return 0;
|
|
640
|
+
},
|
|
641
|
+
};
|
|
642
|
+
async function acknowledgementsListRun(args) {
|
|
643
|
+
const cwd = resolveCwd(args);
|
|
644
|
+
const cfg = loadDoctorSuppressions(cwd);
|
|
645
|
+
const summary = summarizeAcknowledgements(cfg.doctorSuppressions);
|
|
646
|
+
if (flagBool(args, 'json')) {
|
|
647
|
+
process.stdout.write(asJson(summary) + '\n');
|
|
648
|
+
return 0;
|
|
649
|
+
}
|
|
650
|
+
process.stdout.write(renderAcknowledgementsText(summary));
|
|
651
|
+
return 0;
|
|
652
|
+
}
|
|
653
|
+
async function acknowledgementsCheckRun(args) {
|
|
654
|
+
const cwd = resolveCwd(args);
|
|
655
|
+
const cfg = loadDoctorSuppressions(cwd);
|
|
656
|
+
const summary = summarizeAcknowledgements(cfg.doctorSuppressions);
|
|
657
|
+
if (flagBool(args, 'json')) {
|
|
658
|
+
process.stdout.write(asJson(summary) + '\n');
|
|
659
|
+
return summary.expired.length === 0 ? 0 : 1;
|
|
660
|
+
}
|
|
661
|
+
process.stdout.write(renderAcknowledgementsText(summary));
|
|
662
|
+
if (summary.expired.length > 0) {
|
|
663
|
+
process.stdout.write(`\nExpired acknowledgements need to be re-evaluated or renewed.\n`);
|
|
664
|
+
return 1;
|
|
665
|
+
}
|
|
666
|
+
return 0;
|
|
667
|
+
}
|
|
668
|
+
export const doctorAcknowledgementsCommand = {
|
|
669
|
+
name: 'acknowledgements',
|
|
670
|
+
description: 'List / check doctor acknowledgements. Same backing file as suppressions but only entries with reason + expiry are surfaced.',
|
|
671
|
+
usage: 'shrk doctor acknowledgements <list|check> [--json]',
|
|
672
|
+
async run(args) {
|
|
673
|
+
const verb = args.positional[0] ?? 'list';
|
|
674
|
+
const sub = { ...args, positional: args.positional.slice(1) };
|
|
675
|
+
if (verb === 'list')
|
|
676
|
+
return acknowledgementsListRun(sub);
|
|
677
|
+
if (verb === 'check')
|
|
678
|
+
return acknowledgementsCheckRun(sub);
|
|
679
|
+
process.stderr.write('Usage: shrk doctor acknowledgements <list|check>\n');
|
|
680
|
+
return 2;
|
|
681
|
+
},
|
|
682
|
+
};
|