@shrkcrft/cli 0.1.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +314 -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 +553 -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 +3242 -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 +681 -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 +127 -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 +301 -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 +74 -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 +650 -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 +958 -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 +354 -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 +699 -0
- package/dist/output/failure-hints.d.ts +55 -0
- package/dist/output/failure-hints.d.ts.map +1 -0
- package/dist/output/failure-hints.js +159 -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 +53 -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 +36 -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 +73 -0
|
@@ -0,0 +1,776 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shrk fix` (preview-only fix system).
|
|
3
|
+
*
|
|
4
|
+
* Surfaces structured fix suggestions for the most common high-friction
|
|
5
|
+
* findings (action hints / stale knowledge / template drift). Default is
|
|
6
|
+
* preview-only — nothing is written.
|
|
7
|
+
*
|
|
8
|
+
* `--write-preview` writes preview files under `.sharkcraft/fixes/` ONLY
|
|
9
|
+
* (no source mutation). Stubbed action-hint bodies are clearly marked
|
|
10
|
+
* `needs-human-fill`; doctor continues to warn until they are filled.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import * as nodePath from 'node:path';
|
|
14
|
+
import { AssetKind, AssetProvenanceOperation, buildFixPreview, FixKind, inspectSharkcraft, listFixKinds, recordProvenance, renderFixPreviewMarkdown, } from '@shrkcrft/inspector';
|
|
15
|
+
import { flagBool, flagString, flagList, resolveCwd, } from "../command-registry.js";
|
|
16
|
+
import { asJson, header } from "../output/format-output.js";
|
|
17
|
+
import { applyActionHintStub, } from "../asset-preview/apply-action-hint-stub.js";
|
|
18
|
+
import { applyKnowledgeStaleFix } from "../asset-preview/apply-knowledge-stale-fix.js";
|
|
19
|
+
import { applyTemplateDriftFix } from "../asset-preview/apply-template-drift-fix.js";
|
|
20
|
+
import { applyMissingBarrelFix } from "../asset-preview/apply-missing-barrel.js";
|
|
21
|
+
import { detectAuthoringSource } from "../authoring/authoring-kit.js";
|
|
22
|
+
function parseKinds(args) {
|
|
23
|
+
const kinds = [];
|
|
24
|
+
if (flagBool(args, 'all')) {
|
|
25
|
+
return Object.values(FixKind);
|
|
26
|
+
}
|
|
27
|
+
if (flagBool(args, 'action-hints'))
|
|
28
|
+
kinds.push(FixKind.ActionHints);
|
|
29
|
+
if (flagBool(args, 'knowledge-stale'))
|
|
30
|
+
kinds.push(FixKind.KnowledgeStale);
|
|
31
|
+
if (flagBool(args, 'template-drift'))
|
|
32
|
+
kinds.push(FixKind.TemplateDrift);
|
|
33
|
+
if (flagBool(args, 'boundary'))
|
|
34
|
+
kinds.push(FixKind.Boundary);
|
|
35
|
+
if (flagBool(args, 'convention'))
|
|
36
|
+
kinds.push(FixKind.Convention);
|
|
37
|
+
if (flagBool(args, 'self-config'))
|
|
38
|
+
kinds.push(FixKind.SelfConfig);
|
|
39
|
+
if (flagBool(args, 'pack-conflicts'))
|
|
40
|
+
kinds.push(FixKind.PackConflict);
|
|
41
|
+
if (flagBool(args, 'stale-pack-signature'))
|
|
42
|
+
kinds.push(FixKind.StalePackSignature);
|
|
43
|
+
if (flagBool(args, 'missing-command-hint'))
|
|
44
|
+
kinds.push(FixKind.MissingCommandHint);
|
|
45
|
+
if (flagBool(args, 'missing-convention-reference'))
|
|
46
|
+
kinds.push(FixKind.MissingConventionReference);
|
|
47
|
+
if (flagBool(args, 'missing-template-reference'))
|
|
48
|
+
kinds.push(FixKind.MissingTemplateReference);
|
|
49
|
+
if (flagBool(args, 'broken-playbook-reference'))
|
|
50
|
+
kinds.push(FixKind.BrokenPlaybookReference);
|
|
51
|
+
if (flagBool(args, 'broken-agent-test-reference'))
|
|
52
|
+
kinds.push(FixKind.BrokenAgentTestReference);
|
|
53
|
+
if (flagBool(args, 'broken-routing-hint-reference'))
|
|
54
|
+
kinds.push(FixKind.BrokenRoutingHintReference);
|
|
55
|
+
if (flagBool(args, 'broken-helper-reference'))
|
|
56
|
+
kinds.push(FixKind.BrokenHelperReference);
|
|
57
|
+
const list = flagList(args, 'kinds');
|
|
58
|
+
for (const k of list) {
|
|
59
|
+
const matched = Object.values(FixKind).find((v) => v === k);
|
|
60
|
+
if (matched)
|
|
61
|
+
kinds.push(matched);
|
|
62
|
+
}
|
|
63
|
+
return kinds.length > 0 ? Array.from(new Set(kinds)) : undefined;
|
|
64
|
+
}
|
|
65
|
+
async function runFixPreview(args) {
|
|
66
|
+
const cwd = resolveCwd(args);
|
|
67
|
+
const inspection = await inspectSharkcraft({ cwd });
|
|
68
|
+
const kinds = parseKinds(args);
|
|
69
|
+
// Use the async extended builder so the new kinds resolve.
|
|
70
|
+
const { buildFixPreviewExtended } = await import('@shrkcrft/inspector');
|
|
71
|
+
const report = await buildFixPreviewExtended(inspection, kinds ? { kinds } : {});
|
|
72
|
+
const targetFilter = flagString(args, 'target');
|
|
73
|
+
let visibleReport = report;
|
|
74
|
+
if (targetFilter) {
|
|
75
|
+
const filtered = report.suggestions.filter((s) => s.targetId === targetFilter);
|
|
76
|
+
visibleReport = { ...report, suggestions: filtered };
|
|
77
|
+
}
|
|
78
|
+
// --apply is supported for --action-hints, --knowledge-stale, and --template-drift.
|
|
79
|
+
const wantApply = flagBool(args, 'apply');
|
|
80
|
+
if (wantApply) {
|
|
81
|
+
if (flagBool(args, 'action-hints')) {
|
|
82
|
+
return runActionHintApply(cwd, inspection, visibleReport, args);
|
|
83
|
+
}
|
|
84
|
+
if (flagBool(args, 'knowledge-stale')) {
|
|
85
|
+
return runKnowledgeStaleApply(cwd, inspection, visibleReport, args);
|
|
86
|
+
}
|
|
87
|
+
if (flagBool(args, 'template-drift')) {
|
|
88
|
+
return runTemplateDriftApply(cwd, inspection, visibleReport, args);
|
|
89
|
+
}
|
|
90
|
+
process.stderr.write('Refused: --apply is currently supported for --action-hints, --knowledge-stale, and --template-drift only.\n' +
|
|
91
|
+
'Run preview-only for other kinds (`shrk fix --<kind> --write-preview`).\n');
|
|
92
|
+
return 2;
|
|
93
|
+
}
|
|
94
|
+
if (flagBool(args, 'json')) {
|
|
95
|
+
process.stdout.write(asJson(visibleReport) + '\n');
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
process.stdout.write(renderFixPreviewMarkdown(visibleReport));
|
|
99
|
+
}
|
|
100
|
+
if (flagBool(args, 'write-preview')) {
|
|
101
|
+
const dir = nodePath.join(cwd, '.sharkcraft/fixes');
|
|
102
|
+
if (!existsSync(dir))
|
|
103
|
+
mkdirSync(dir, { recursive: true });
|
|
104
|
+
const aggregatePath = nodePath.join(dir, 'fix-preview.md');
|
|
105
|
+
writeFileSync(aggregatePath, renderFixPreviewMarkdown(visibleReport), 'utf8');
|
|
106
|
+
process.stdout.write(`\nWrote ${aggregatePath}\n`);
|
|
107
|
+
for (const s of visibleReport.suggestions) {
|
|
108
|
+
if (!s.previewFileName)
|
|
109
|
+
continue;
|
|
110
|
+
const file = nodePath.join(dir, s.previewFileName);
|
|
111
|
+
const body = renderFixPreviewMarkdown({ ...visibleReport, suggestions: [s] });
|
|
112
|
+
writeFileSync(file, body, 'utf8');
|
|
113
|
+
}
|
|
114
|
+
process.stdout.write(`Wrote ${visibleReport.suggestions.length} per-suggestion previews under ${dir}/\n`);
|
|
115
|
+
}
|
|
116
|
+
return visibleReport.suggestions.length > 0 ? 1 : 0;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Apply action-hint stubs in place. Preview-first under the hood:
|
|
120
|
+
* we compute every patch via `applyActionHintStub` first, refuse on any
|
|
121
|
+
* divergence (existing actionHints field) unless `--allow-divergent`, and
|
|
122
|
+
* only then write. Provenance is recorded per applied stub.
|
|
123
|
+
*/
|
|
124
|
+
async function runActionHintApply(cwd, inspection, report, args) {
|
|
125
|
+
const allowDivergent = flagBool(args, 'allow-divergent');
|
|
126
|
+
const wantJson = flagBool(args, 'json');
|
|
127
|
+
const actionHintSuggestions = report.suggestions.filter((s) => s.kind === FixKind.ActionHints);
|
|
128
|
+
if (actionHintSuggestions.length === 0) {
|
|
129
|
+
if (wantJson) {
|
|
130
|
+
process.stdout.write(asJson({ applied: [], refused: [], message: 'no action-hint suggestions' }) + '\n');
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
process.stdout.write('No action-hint findings — nothing to apply.\n');
|
|
134
|
+
}
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
// Resolve each suggestion to its owning source file via the inspection.
|
|
138
|
+
const entryById = new Map(inspection.knowledgeEntries.map((e) => [e.id, e]));
|
|
139
|
+
const planned = [];
|
|
140
|
+
const refused = [];
|
|
141
|
+
for (const s of actionHintSuggestions) {
|
|
142
|
+
const entry = entryById.get(s.targetId);
|
|
143
|
+
if (!entry) {
|
|
144
|
+
refused.push({ targetId: s.targetId, reason: 'entry not found in inspection' });
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const origin = entry.source?.origin;
|
|
148
|
+
if (!origin) {
|
|
149
|
+
refused.push({ targetId: s.targetId, reason: 'entry has no source origin (likely pack-contributed)' });
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
// Refuse pack-contributed sources by default. node_modules/ is the
|
|
153
|
+
// canonical marker; we also refuse `dist/` files under packs.
|
|
154
|
+
const relFromCwd = nodePath.relative(cwd, origin);
|
|
155
|
+
const isPackSource = relFromCwd.startsWith('node_modules' + nodePath.sep) ||
|
|
156
|
+
/\bdist\b/.test(relFromCwd);
|
|
157
|
+
if (isPackSource) {
|
|
158
|
+
refused.push({
|
|
159
|
+
targetId: s.targetId,
|
|
160
|
+
reason: `entry is pack-contributed (${relFromCwd}) — edit the pack source and re-sign instead`,
|
|
161
|
+
});
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const stub = applyActionHintStub({
|
|
165
|
+
cwd,
|
|
166
|
+
targetPath: relFromCwd,
|
|
167
|
+
entryId: s.targetId,
|
|
168
|
+
write: false, // preview-first
|
|
169
|
+
allowDivergent,
|
|
170
|
+
});
|
|
171
|
+
if (!stub.ok) {
|
|
172
|
+
refused.push({ targetId: s.targetId, reason: stub.refusal ?? 'unknown' });
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
planned.push({ targetId: s.targetId, sourceFile: relFromCwd, result: stub });
|
|
176
|
+
}
|
|
177
|
+
// If anything was refused and --allow-divergent isn't on, surface and exit
|
|
178
|
+
// non-zero before touching disk.
|
|
179
|
+
if (refused.length > 0 && !allowDivergent) {
|
|
180
|
+
if (wantJson) {
|
|
181
|
+
process.stdout.write(asJson({
|
|
182
|
+
mode: 'refused',
|
|
183
|
+
planned: planned.map((p) => ({ targetId: p.targetId, sourceFile: p.sourceFile })),
|
|
184
|
+
refused,
|
|
185
|
+
}) + '\n');
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
process.stdout.write(header('Fix --action-hints --apply (refused)'));
|
|
189
|
+
process.stdout.write(` planned: ${planned.length}\n`);
|
|
190
|
+
process.stdout.write(` refused: ${refused.length}\n\n`);
|
|
191
|
+
for (const r of refused) {
|
|
192
|
+
process.stdout.write(` • ${r.targetId}: ${r.reason}\n`);
|
|
193
|
+
}
|
|
194
|
+
process.stdout.write('\nNo files written. Pass --allow-divergent to apply the planned subset anyway.\n');
|
|
195
|
+
}
|
|
196
|
+
return 1;
|
|
197
|
+
}
|
|
198
|
+
// Group planned fixes by source file so we apply per-file in one pass.
|
|
199
|
+
// The splicer is idempotent and pure-function — we re-run it with
|
|
200
|
+
// `write: true` and let the writer persist each fix one at a time.
|
|
201
|
+
const applied = [];
|
|
202
|
+
for (const p of planned) {
|
|
203
|
+
const stub = applyActionHintStub({
|
|
204
|
+
cwd,
|
|
205
|
+
targetPath: p.sourceFile,
|
|
206
|
+
entryId: p.targetId,
|
|
207
|
+
write: true,
|
|
208
|
+
allowDivergent,
|
|
209
|
+
});
|
|
210
|
+
if (!stub.ok) {
|
|
211
|
+
refused.push({ targetId: p.targetId, reason: stub.refusal ?? 'second-pass failed' });
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
applied.push({
|
|
215
|
+
targetId: p.targetId,
|
|
216
|
+
sourceFile: p.sourceFile,
|
|
217
|
+
...(stub.insertedAtLine !== undefined ? { insertedAtLine: stub.insertedAtLine } : {}),
|
|
218
|
+
});
|
|
219
|
+
// Record provenance for each applied stub.
|
|
220
|
+
try {
|
|
221
|
+
const src = detectAuthoringSource();
|
|
222
|
+
recordProvenance({
|
|
223
|
+
projectRoot: cwd,
|
|
224
|
+
entry: {
|
|
225
|
+
operation: AssetProvenanceOperation.Update,
|
|
226
|
+
assetKind: AssetKind.Knowledge,
|
|
227
|
+
assetId: p.targetId,
|
|
228
|
+
targetFile: p.sourceFile,
|
|
229
|
+
source: src.source,
|
|
230
|
+
...(src.author ? { author: src.author } : {}),
|
|
231
|
+
...(src.sessionId ? { sessionId: src.sessionId } : {}),
|
|
232
|
+
reason: 'fix --action-hints --apply',
|
|
233
|
+
extra: { fixKind: FixKind.ActionHints, stubbed: true },
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// best-effort
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (wantJson) {
|
|
242
|
+
process.stdout.write(asJson({ mode: 'applied', applied, refused }) + '\n');
|
|
243
|
+
return refused.length > 0 ? 1 : 0;
|
|
244
|
+
}
|
|
245
|
+
process.stdout.write(header('Fix --action-hints --apply'));
|
|
246
|
+
process.stdout.write(` applied: ${applied.length}\n`);
|
|
247
|
+
process.stdout.write(` refused: ${refused.length}\n\n`);
|
|
248
|
+
for (const a of applied) {
|
|
249
|
+
process.stdout.write(` • ${a.targetId} → ${a.sourceFile}${a.insertedAtLine ? `:${a.insertedAtLine}` : ''}\n`);
|
|
250
|
+
}
|
|
251
|
+
if (refused.length > 0) {
|
|
252
|
+
process.stdout.write('\nRefused:\n');
|
|
253
|
+
for (const r of refused)
|
|
254
|
+
process.stdout.write(` • ${r.targetId}: ${r.reason}\n`);
|
|
255
|
+
}
|
|
256
|
+
process.stdout.write('\nStubs use TODO placeholders. Doctor will continue to warn (action-hint-quality) until they are filled.\n');
|
|
257
|
+
process.stdout.write('Re-run `shrk doctor` to confirm the missing-action-hints warnings dropped.\n');
|
|
258
|
+
return refused.length > 0 ? 1 : 0;
|
|
259
|
+
}
|
|
260
|
+
export const fixCommand = {
|
|
261
|
+
name: 'fix',
|
|
262
|
+
description: 'Fix preview system. Preview-only by default. `--write-preview` writes drafts to .sharkcraft/fixes/. `--action-hints --apply` splices stubbed actionHints. `--knowledge-stale --apply [--drop-stale] [--drop-missing]` removes the offending reference in place. `--rename-strategy=wide` surfaces multi-candidate rename suggestions that strict mode silently drops.',
|
|
263
|
+
usage: 'shrk fix [list|doctor|preview] [--action-hints|--knowledge-stale|--template-drift] [--kinds <a,b>] [--target <id>] [--write-preview] [--apply [--allow-divergent] [--drop-stale] [--drop-missing] [--rename-strategy strict|wide]] [--json]',
|
|
264
|
+
async run(args) {
|
|
265
|
+
const sub = args.positional[0];
|
|
266
|
+
if (sub === 'list') {
|
|
267
|
+
return runFixList(args);
|
|
268
|
+
}
|
|
269
|
+
if (sub === 'doctor') {
|
|
270
|
+
return runFixDoctor(args);
|
|
271
|
+
}
|
|
272
|
+
if (sub === 'preview') {
|
|
273
|
+
const sliced = { ...args, positional: args.positional.slice(1) };
|
|
274
|
+
return runFixPreview(sliced);
|
|
275
|
+
}
|
|
276
|
+
if (sub === undefined && (flagBool(args, 'action-hints') || flagBool(args, 'knowledge-stale') || flagBool(args, 'template-drift') || flagBool(args, 'list') || flagBool(args, 'doctor'))) {
|
|
277
|
+
// Allow `shrk fix --action-hints` shorthand.
|
|
278
|
+
return runFixPreview(args);
|
|
279
|
+
}
|
|
280
|
+
return runFixPreview(args);
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* Apply knowledge-stale fixes in place.
|
|
285
|
+
*
|
|
286
|
+
* Resolves each `FixKind.KnowledgeStale` suggestion to a target file
|
|
287
|
+
* (the entry's source origin) and removes the offending reference from
|
|
288
|
+
* the entry's `references[]` array.
|
|
289
|
+
*
|
|
290
|
+
* Modes (opt-in flags):
|
|
291
|
+
* --drop-stale — apply to `outcome=stale` references
|
|
292
|
+
* --drop-missing — apply to `outcome=missing` references
|
|
293
|
+
*
|
|
294
|
+
* Without either flag, the apply refuses (preview-only contract).
|
|
295
|
+
* Pack sources are refused by default (same as the action-hint apply).
|
|
296
|
+
*/
|
|
297
|
+
async function runKnowledgeStaleApply(cwd, inspection, _report, args) {
|
|
298
|
+
const wantJson = flagBool(args, 'json');
|
|
299
|
+
const dropStale = flagBool(args, 'drop-stale');
|
|
300
|
+
const dropMissing = flagBool(args, 'drop-missing');
|
|
301
|
+
// `--rename-strategy=wide` extends rename detection beyond the
|
|
302
|
+
// strict unique-candidate case. Default stays `strict`.
|
|
303
|
+
const renameStrategyFlag = flagString(args, 'rename-strategy');
|
|
304
|
+
const useWide = renameStrategyFlag === 'wide';
|
|
305
|
+
if (renameStrategyFlag && renameStrategyFlag !== 'strict' && renameStrategyFlag !== 'wide') {
|
|
306
|
+
process.stderr.write(`Unknown --rename-strategy "${renameStrategyFlag}". Use strict | wide.\n`);
|
|
307
|
+
return 2;
|
|
308
|
+
}
|
|
309
|
+
// Rebuild the stale report directly so we have full IKnowledgeReferenceCheck
|
|
310
|
+
// shape (the FixKind suggestions are stringy and lose the kind/path/symbol/id).
|
|
311
|
+
const { buildKnowledgeStaleReport, ReferenceCheckOutcome, RenameStrategy } = await import('@shrkcrft/inspector');
|
|
312
|
+
const stale = buildKnowledgeStaleReport(inspection, {
|
|
313
|
+
renameStrategy: useWide ? RenameStrategy.Wide : RenameStrategy.Strict,
|
|
314
|
+
});
|
|
315
|
+
// A rename payload is always actionable; --drop-stale / --drop-missing
|
|
316
|
+
// are only required when the engine has no structured replacement.
|
|
317
|
+
const hasAnyRename = stale.referenceChecks.some((c) => (c.outcome === ReferenceCheckOutcome.Stale || c.outcome === ReferenceCheckOutcome.Missing) &&
|
|
318
|
+
c.replaceWith !== undefined);
|
|
319
|
+
if (!dropStale && !dropMissing && !hasAnyRename) {
|
|
320
|
+
process.stderr.write('Refused: no rename signals in stale-check and no --drop-stale / --drop-missing flag.\n' +
|
|
321
|
+
'Pass one of:\n' +
|
|
322
|
+
' --drop-stale drop references with outcome=stale\n' +
|
|
323
|
+
' --drop-missing drop references with outcome=missing\n' +
|
|
324
|
+
'Renames are applied automatically when the engine identifies the new location.\n');
|
|
325
|
+
return 2;
|
|
326
|
+
}
|
|
327
|
+
const entryById = new Map(inspection.knowledgeEntries.map((e) => [e.id, e]));
|
|
328
|
+
const planned = [];
|
|
329
|
+
const refused = [];
|
|
330
|
+
for (const c of stale.referenceChecks) {
|
|
331
|
+
if (c.outcome !== ReferenceCheckOutcome.Stale && c.outcome !== ReferenceCheckOutcome.Missing) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
// A rename signal is only actionable when `replaceWith.path`
|
|
335
|
+
// (or .id/.symbol) is populated. Wide mode can emit `candidates[]`
|
|
336
|
+
// without a chosen target — those are ambiguous and surfaced for the
|
|
337
|
+
// user, not auto-applied.
|
|
338
|
+
const hasAutoRenameTarget = c.replaceWith !== undefined &&
|
|
339
|
+
(c.replaceWith.path !== undefined ||
|
|
340
|
+
c.replaceWith.id !== undefined ||
|
|
341
|
+
c.replaceWith.symbol !== undefined);
|
|
342
|
+
const hasAmbiguousCandidates = c.replaceWith !== undefined &&
|
|
343
|
+
!hasAutoRenameTarget &&
|
|
344
|
+
(c.replaceWith.candidates?.length ?? 0) > 0;
|
|
345
|
+
if (hasAmbiguousCandidates) {
|
|
346
|
+
refused.push({
|
|
347
|
+
targetId: c.entryId,
|
|
348
|
+
reason: `ambiguous rename (${c.replaceWith.candidates.length} candidates); pass --rename-strategy=strict + manual edit, or rerun with --drop-stale/--drop-missing.`,
|
|
349
|
+
});
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
if (!hasAutoRenameTarget) {
|
|
353
|
+
if (c.outcome === ReferenceCheckOutcome.Stale && !dropStale)
|
|
354
|
+
continue;
|
|
355
|
+
if (c.outcome === ReferenceCheckOutcome.Missing && !dropMissing)
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
const entry = entryById.get(c.entryId);
|
|
359
|
+
if (!entry) {
|
|
360
|
+
refused.push({ targetId: c.entryId, reason: 'entry not found in inspection' });
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
const origin = entry.source?.origin;
|
|
364
|
+
if (!origin) {
|
|
365
|
+
refused.push({
|
|
366
|
+
targetId: c.entryId,
|
|
367
|
+
reason: 'entry has no source origin (likely pack-contributed)',
|
|
368
|
+
});
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
const relFromCwd = nodePath.relative(cwd, origin);
|
|
372
|
+
const isPackSource = relFromCwd.startsWith('node_modules' + nodePath.sep) || /\bdist\b/.test(relFromCwd);
|
|
373
|
+
if (isPackSource) {
|
|
374
|
+
refused.push({
|
|
375
|
+
targetId: c.entryId,
|
|
376
|
+
reason: `entry is pack-contributed (${relFromCwd}) — edit the pack source and re-sign instead`,
|
|
377
|
+
});
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
planned.push({
|
|
381
|
+
targetId: c.entryId,
|
|
382
|
+
sourceFile: relFromCwd,
|
|
383
|
+
outcome: c.outcome === ReferenceCheckOutcome.Stale ? 'stale' : 'missing',
|
|
384
|
+
reference: c.reference,
|
|
385
|
+
...(c.replaceWith
|
|
386
|
+
? {
|
|
387
|
+
renameTo: {
|
|
388
|
+
...(c.replaceWith.path !== undefined ? { path: c.replaceWith.path } : {}),
|
|
389
|
+
...(c.replaceWith.id !== undefined ? { id: c.replaceWith.id } : {}),
|
|
390
|
+
...(c.replaceWith.symbol !== undefined ? { symbol: c.replaceWith.symbol } : {}),
|
|
391
|
+
},
|
|
392
|
+
}
|
|
393
|
+
: {}),
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
// Preview-first: run with write=false for every planned fix (rename or drop).
|
|
397
|
+
for (const p of planned) {
|
|
398
|
+
const dry = applyKnowledgeStaleFix({
|
|
399
|
+
cwd,
|
|
400
|
+
targetPath: p.sourceFile,
|
|
401
|
+
entryId: p.targetId,
|
|
402
|
+
reference: p.reference,
|
|
403
|
+
write: false,
|
|
404
|
+
...(p.renameTo ? { renameTo: p.renameTo } : {}),
|
|
405
|
+
});
|
|
406
|
+
if (!dry.ok) {
|
|
407
|
+
refused.push({ targetId: p.targetId, reason: dry.refusal ?? 'preview failed' });
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const allowDivergent = flagBool(args, 'allow-divergent');
|
|
411
|
+
if (refused.length > 0 && !allowDivergent) {
|
|
412
|
+
if (wantJson) {
|
|
413
|
+
process.stdout.write(asJson({
|
|
414
|
+
mode: 'refused',
|
|
415
|
+
planned: planned.map((p) => ({ targetId: p.targetId, sourceFile: p.sourceFile, outcome: p.outcome })),
|
|
416
|
+
refused,
|
|
417
|
+
}) + '\n');
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
process.stdout.write(header('Fix --knowledge-stale --apply (refused)'));
|
|
421
|
+
process.stdout.write(` planned: ${planned.length}\n`);
|
|
422
|
+
process.stdout.write(` refused: ${refused.length}\n\n`);
|
|
423
|
+
for (const r of refused)
|
|
424
|
+
process.stdout.write(` • ${r.targetId}: ${r.reason}\n`);
|
|
425
|
+
process.stdout.write('\nNo files written. Pass --allow-divergent to apply the planned subset anyway.\n');
|
|
426
|
+
}
|
|
427
|
+
return 1;
|
|
428
|
+
}
|
|
429
|
+
// Second pass: write. Re-build the planned list to only the entries
|
|
430
|
+
// that survived preview (when --allow-divergent, refused entries are
|
|
431
|
+
// dropped here).
|
|
432
|
+
const survivors = planned.filter((p) => !refused.some((r) => r.targetId === p.targetId));
|
|
433
|
+
const applied = [];
|
|
434
|
+
for (const p of survivors) {
|
|
435
|
+
const result = applyKnowledgeStaleFix({
|
|
436
|
+
cwd,
|
|
437
|
+
targetPath: p.sourceFile,
|
|
438
|
+
entryId: p.targetId,
|
|
439
|
+
reference: p.reference,
|
|
440
|
+
write: true,
|
|
441
|
+
...(p.renameTo ? { renameTo: p.renameTo } : {}),
|
|
442
|
+
});
|
|
443
|
+
if (!result.ok) {
|
|
444
|
+
refused.push({ targetId: p.targetId, reason: result.refusal ?? 'second-pass failed' });
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
applied.push({
|
|
448
|
+
targetId: p.targetId,
|
|
449
|
+
sourceFile: p.sourceFile,
|
|
450
|
+
outcome: p.outcome,
|
|
451
|
+
mode: result.mode,
|
|
452
|
+
removed: result.removedCount,
|
|
453
|
+
...(p.renameTo ? { renamedTo: p.renameTo } : {}),
|
|
454
|
+
});
|
|
455
|
+
try {
|
|
456
|
+
const src = detectAuthoringSource();
|
|
457
|
+
recordProvenance({
|
|
458
|
+
projectRoot: cwd,
|
|
459
|
+
entry: {
|
|
460
|
+
operation: AssetProvenanceOperation.Update,
|
|
461
|
+
assetKind: AssetKind.Knowledge,
|
|
462
|
+
assetId: p.targetId,
|
|
463
|
+
targetFile: p.sourceFile,
|
|
464
|
+
source: src.source,
|
|
465
|
+
...(src.author ? { author: src.author } : {}),
|
|
466
|
+
...(src.sessionId ? { sessionId: src.sessionId } : {}),
|
|
467
|
+
reason: `fix --knowledge-stale --apply (${result.mode}-${p.outcome})`,
|
|
468
|
+
extra: {
|
|
469
|
+
fixKind: FixKind.KnowledgeStale,
|
|
470
|
+
applied: result.mode,
|
|
471
|
+
outcome: p.outcome,
|
|
472
|
+
...(p.renameTo ? { renamedTo: p.renameTo } : {}),
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
catch {
|
|
478
|
+
// best-effort
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
if (wantJson) {
|
|
482
|
+
process.stdout.write(asJson({ mode: 'applied', applied, refused }) + '\n');
|
|
483
|
+
return refused.length > 0 ? 1 : 0;
|
|
484
|
+
}
|
|
485
|
+
process.stdout.write(header('Fix --knowledge-stale --apply'));
|
|
486
|
+
const renameCount = applied.filter((a) => a.mode === 'rename').length;
|
|
487
|
+
const dropCount = applied.filter((a) => a.mode === 'drop').length;
|
|
488
|
+
process.stdout.write(` applied: ${applied.length} (${renameCount} renamed, ${dropCount} dropped)\n`);
|
|
489
|
+
process.stdout.write(` refused: ${refused.length}\n\n`);
|
|
490
|
+
for (const a of applied) {
|
|
491
|
+
if (a.mode === 'rename') {
|
|
492
|
+
const to = a.renamedTo ?? {};
|
|
493
|
+
const target = to.path ?? to.id ?? to.symbol ?? '?';
|
|
494
|
+
process.stdout.write(` • ${a.targetId} → ${a.sourceFile} (rename → ${target})\n`);
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
process.stdout.write(` • ${a.targetId} → ${a.sourceFile} (drop ${a.outcome}, removed=${a.removed})\n`);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
if (refused.length > 0) {
|
|
501
|
+
process.stdout.write('\nRefused:\n');
|
|
502
|
+
for (const r of refused)
|
|
503
|
+
process.stdout.write(` • ${r.targetId}: ${r.reason}\n`);
|
|
504
|
+
}
|
|
505
|
+
process.stdout.write('\nRe-run `shrk doctor` / `shrk knowledge stale-check --ci` to confirm the stale count dropped.\n');
|
|
506
|
+
return refused.length > 0 ? 1 : 0;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Apply template-drift fixes in place.
|
|
510
|
+
*
|
|
511
|
+
* Scope: only `related-id-unresolved`. Other codes are template-body
|
|
512
|
+
* issues and stay preview-only.
|
|
513
|
+
*/
|
|
514
|
+
async function runTemplateDriftApply(cwd, inspection, _report, args) {
|
|
515
|
+
const wantJson = flagBool(args, 'json');
|
|
516
|
+
const { buildTemplateDriftReport } = await import('@shrkcrft/inspector');
|
|
517
|
+
const drift = buildTemplateDriftReport(inspection, {});
|
|
518
|
+
// Pull related-id-unresolved findings and pair each with its source.
|
|
519
|
+
const templateSources = inspection.templateSources;
|
|
520
|
+
// Local templates are loaded from cfg.templateFiles — resolve them
|
|
521
|
+
// against the sharkcraft dir.
|
|
522
|
+
const cfg = inspection.config;
|
|
523
|
+
const sharkDir = inspection.sharkcraftDir ?? null;
|
|
524
|
+
const localTemplateFiles = [];
|
|
525
|
+
if (cfg && sharkDir) {
|
|
526
|
+
for (const f of (cfg.templateFiles ?? [])) {
|
|
527
|
+
localTemplateFiles.push(nodePath.join(sharkDir, f));
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
const planned = [];
|
|
531
|
+
const plannedBarrels = [];
|
|
532
|
+
const refused = [];
|
|
533
|
+
for (const e of drift.entries) {
|
|
534
|
+
for (const issue of e.issues) {
|
|
535
|
+
if (issue.code === 'related-id-unresolved') {
|
|
536
|
+
const src = templateSources.get(e.templateId);
|
|
537
|
+
if (!src || src.type === 'pack') {
|
|
538
|
+
refused.push({
|
|
539
|
+
templateId: e.templateId,
|
|
540
|
+
reason: 'template is pack-contributed — edit the pack source and re-sign instead',
|
|
541
|
+
});
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
const m = /related id\s+["']([^"']+)["']/i.exec(issue.message);
|
|
545
|
+
if (!m) {
|
|
546
|
+
refused.push({
|
|
547
|
+
templateId: e.templateId,
|
|
548
|
+
reason: `cannot parse unresolved related id from message: ${issue.message}`,
|
|
549
|
+
});
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
const droppedRelatedId = m[1];
|
|
553
|
+
let sourceFile = null;
|
|
554
|
+
for (const candidate of localTemplateFiles) {
|
|
555
|
+
try {
|
|
556
|
+
const body = (await import('node:fs')).readFileSync(candidate, 'utf8');
|
|
557
|
+
if (new RegExp(`id\\s*:\\s*['"]${e.templateId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}['"]`).test(body)) {
|
|
558
|
+
sourceFile = candidate;
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
catch {
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (!sourceFile) {
|
|
567
|
+
refused.push({
|
|
568
|
+
templateId: e.templateId,
|
|
569
|
+
reason: `could not locate local source file for template ${e.templateId}`,
|
|
570
|
+
});
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
planned.push({
|
|
574
|
+
templateId: e.templateId,
|
|
575
|
+
sourceFile: nodePath.relative(cwd, sourceFile),
|
|
576
|
+
droppedRelatedId,
|
|
577
|
+
});
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
// Missing-barrel: parse the offending barrel path from the
|
|
581
|
+
// message ("export op references missing barrel <path>.") and
|
|
582
|
+
// plan an auto-create.
|
|
583
|
+
if (issue.code === 'missing-barrel') {
|
|
584
|
+
// The message is e.g. `export op references missing barrel "libs/.../index.ts".`
|
|
585
|
+
const m = /missing barrel\s+["']([^"']+)["']/i.exec(issue.message);
|
|
586
|
+
if (!m) {
|
|
587
|
+
refused.push({
|
|
588
|
+
templateId: e.templateId,
|
|
589
|
+
reason: `cannot parse missing barrel path from message: ${issue.message}`,
|
|
590
|
+
});
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
const barrelPath = m[1];
|
|
594
|
+
plannedBarrels.push({ templateId: e.templateId, barrelPath });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
if (planned.length === 0 && plannedBarrels.length === 0 && refused.length === 0) {
|
|
599
|
+
if (wantJson) {
|
|
600
|
+
process.stdout.write(asJson({ mode: 'applied', applied: [], appliedBarrels: [], refused: [], note: 'no applicable template-drift fixes' }) + '\n');
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
process.stdout.write('No applicable template-drift fixes (supports related-id-unresolved + missing-barrel).\n');
|
|
604
|
+
}
|
|
605
|
+
return 0;
|
|
606
|
+
}
|
|
607
|
+
// Preview-first.
|
|
608
|
+
for (const p of planned) {
|
|
609
|
+
const dry = applyTemplateDriftFix({
|
|
610
|
+
cwd,
|
|
611
|
+
targetPath: p.sourceFile,
|
|
612
|
+
templateId: p.templateId,
|
|
613
|
+
droppedRelatedId: p.droppedRelatedId,
|
|
614
|
+
write: false,
|
|
615
|
+
});
|
|
616
|
+
if (!dry.ok)
|
|
617
|
+
refused.push({ templateId: p.templateId, reason: dry.refusal ?? 'preview failed' });
|
|
618
|
+
}
|
|
619
|
+
for (const b of plannedBarrels) {
|
|
620
|
+
const dry = applyMissingBarrelFix({ cwd, barrelPath: b.barrelPath, write: false });
|
|
621
|
+
if (!dry.ok) {
|
|
622
|
+
refused.push({ templateId: b.templateId, reason: dry.refusal ?? 'barrel preview failed' });
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
const allowDivergent = flagBool(args, 'allow-divergent');
|
|
626
|
+
if (refused.length > 0 && !allowDivergent) {
|
|
627
|
+
if (wantJson) {
|
|
628
|
+
process.stdout.write(asJson({
|
|
629
|
+
mode: 'refused',
|
|
630
|
+
planned: planned.map((p) => ({ templateId: p.templateId, sourceFile: p.sourceFile, droppedRelatedId: p.droppedRelatedId })),
|
|
631
|
+
plannedBarrels,
|
|
632
|
+
refused,
|
|
633
|
+
}) + '\n');
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
process.stdout.write(header('Fix --template-drift --apply (refused)'));
|
|
637
|
+
process.stdout.write(` planned: ${planned.length} drops, ${plannedBarrels.length} barrels\n`);
|
|
638
|
+
process.stdout.write(` refused: ${refused.length}\n\n`);
|
|
639
|
+
for (const r of refused)
|
|
640
|
+
process.stdout.write(` • ${r.templateId}: ${r.reason}\n`);
|
|
641
|
+
process.stdout.write('\nNo files written. Pass --allow-divergent to apply the planned subset anyway.\n');
|
|
642
|
+
}
|
|
643
|
+
return 1;
|
|
644
|
+
}
|
|
645
|
+
const survivors = planned.filter((p) => !refused.some((r) => r.templateId === p.templateId));
|
|
646
|
+
const surviveBarrels = plannedBarrels.filter((b) => !refused.some((r) => r.templateId === b.templateId));
|
|
647
|
+
const applied = [];
|
|
648
|
+
const appliedBarrels = [];
|
|
649
|
+
for (const p of survivors) {
|
|
650
|
+
const result = applyTemplateDriftFix({
|
|
651
|
+
cwd,
|
|
652
|
+
targetPath: p.sourceFile,
|
|
653
|
+
templateId: p.templateId,
|
|
654
|
+
droppedRelatedId: p.droppedRelatedId,
|
|
655
|
+
write: true,
|
|
656
|
+
});
|
|
657
|
+
if (!result.ok) {
|
|
658
|
+
refused.push({ templateId: p.templateId, reason: result.refusal ?? 'second-pass failed' });
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
applied.push({
|
|
662
|
+
templateId: p.templateId,
|
|
663
|
+
sourceFile: p.sourceFile,
|
|
664
|
+
droppedRelatedId: p.droppedRelatedId,
|
|
665
|
+
removed: result.removedCount,
|
|
666
|
+
});
|
|
667
|
+
try {
|
|
668
|
+
const src = detectAuthoringSource();
|
|
669
|
+
recordProvenance({
|
|
670
|
+
projectRoot: cwd,
|
|
671
|
+
entry: {
|
|
672
|
+
operation: AssetProvenanceOperation.Update,
|
|
673
|
+
assetKind: AssetKind.Template,
|
|
674
|
+
assetId: p.templateId,
|
|
675
|
+
targetFile: p.sourceFile,
|
|
676
|
+
source: src.source,
|
|
677
|
+
...(src.author ? { author: src.author } : {}),
|
|
678
|
+
...(src.sessionId ? { sessionId: src.sessionId } : {}),
|
|
679
|
+
reason: `fix --template-drift --apply (drop-related ${p.droppedRelatedId})`,
|
|
680
|
+
extra: { fixKind: FixKind.TemplateDrift, code: 'related-id-unresolved', dropped: p.droppedRelatedId },
|
|
681
|
+
},
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
catch {
|
|
685
|
+
// best-effort
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
for (const b of surviveBarrels) {
|
|
689
|
+
const result = applyMissingBarrelFix({ cwd, barrelPath: b.barrelPath, write: true });
|
|
690
|
+
if (!result.ok) {
|
|
691
|
+
refused.push({ templateId: b.templateId, reason: result.refusal ?? 'barrel write failed' });
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
appliedBarrels.push({ templateId: b.templateId, barrelPath: b.barrelPath });
|
|
695
|
+
try {
|
|
696
|
+
const src = detectAuthoringSource();
|
|
697
|
+
recordProvenance({
|
|
698
|
+
projectRoot: cwd,
|
|
699
|
+
entry: {
|
|
700
|
+
operation: AssetProvenanceOperation.Update,
|
|
701
|
+
assetKind: AssetKind.Template,
|
|
702
|
+
assetId: b.templateId,
|
|
703
|
+
targetFile: b.barrelPath,
|
|
704
|
+
source: src.source,
|
|
705
|
+
...(src.author ? { author: src.author } : {}),
|
|
706
|
+
...(src.sessionId ? { sessionId: src.sessionId } : {}),
|
|
707
|
+
reason: `fix --template-drift --apply (missing-barrel)`,
|
|
708
|
+
extra: { fixKind: FixKind.TemplateDrift, code: 'missing-barrel', created: b.barrelPath },
|
|
709
|
+
},
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
catch {
|
|
713
|
+
// best-effort
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
if (wantJson) {
|
|
717
|
+
process.stdout.write(asJson({ mode: 'applied', applied, appliedBarrels, refused }) + '\n');
|
|
718
|
+
return refused.length > 0 ? 1 : 0;
|
|
719
|
+
}
|
|
720
|
+
process.stdout.write(header('Fix --template-drift --apply'));
|
|
721
|
+
process.stdout.write(` applied: ${applied.length} drops, ${appliedBarrels.length} barrels\n`);
|
|
722
|
+
process.stdout.write(` refused: ${refused.length}\n\n`);
|
|
723
|
+
for (const a of applied) {
|
|
724
|
+
process.stdout.write(` • ${a.templateId} → ${a.sourceFile} (drop related "${a.droppedRelatedId}", removed=${a.removed})\n`);
|
|
725
|
+
}
|
|
726
|
+
for (const a of appliedBarrels) {
|
|
727
|
+
process.stdout.write(` • ${a.templateId} → ${a.barrelPath} (created barrel)\n`);
|
|
728
|
+
}
|
|
729
|
+
if (refused.length > 0) {
|
|
730
|
+
process.stdout.write('\nRefused:\n');
|
|
731
|
+
for (const r of refused)
|
|
732
|
+
process.stdout.write(` • ${r.templateId}: ${r.reason}\n`);
|
|
733
|
+
}
|
|
734
|
+
process.stdout.write('\nRe-run `shrk templates drift --min-severity warning` to confirm the drift count dropped.\n' +
|
|
735
|
+
'Barrels are created as `export {};` placeholders — populate them with the expected re-exports.\n');
|
|
736
|
+
return refused.length > 0 ? 1 : 0;
|
|
737
|
+
}
|
|
738
|
+
function runFixList(args) {
|
|
739
|
+
const kinds = listFixKinds();
|
|
740
|
+
if (flagBool(args, 'json')) {
|
|
741
|
+
process.stdout.write(asJson(kinds) + '\n');
|
|
742
|
+
return 0;
|
|
743
|
+
}
|
|
744
|
+
process.stdout.write(header('Available fix kinds'));
|
|
745
|
+
for (const k of kinds) {
|
|
746
|
+
process.stdout.write(` ${k.kind.padEnd(20)} ${k.description}\n`);
|
|
747
|
+
}
|
|
748
|
+
return 0;
|
|
749
|
+
}
|
|
750
|
+
async function runFixDoctor(args) {
|
|
751
|
+
const cwd = resolveCwd(args);
|
|
752
|
+
const inspection = await inspectSharkcraft({ cwd });
|
|
753
|
+
const report = buildFixPreview(inspection);
|
|
754
|
+
const errors = report.suggestions.filter((s) => s.severity === 'error').length;
|
|
755
|
+
const warnings = report.suggestions.filter((s) => s.severity === 'warning').length;
|
|
756
|
+
if (flagBool(args, 'json')) {
|
|
757
|
+
process.stdout.write(asJson({ schema: 'sharkcraft.fix-doctor/v1', counts: { errors, warnings }, report }) + '\n');
|
|
758
|
+
return errors > 0 ? 1 : 0;
|
|
759
|
+
}
|
|
760
|
+
process.stdout.write(header('Fix doctor'));
|
|
761
|
+
process.stdout.write(` errors: ${errors}\n`);
|
|
762
|
+
process.stdout.write(` warnings: ${warnings}\n`);
|
|
763
|
+
if (report.suggestions.length === 0) {
|
|
764
|
+
process.stdout.write('\nNo outstanding fixes.\n');
|
|
765
|
+
return 0;
|
|
766
|
+
}
|
|
767
|
+
process.stdout.write('\nTop suggestions:\n');
|
|
768
|
+
for (const s of report.suggestions.slice(0, 10)) {
|
|
769
|
+
process.stdout.write(` [${s.severity}] ${s.kind} ${s.targetId}\n`);
|
|
770
|
+
}
|
|
771
|
+
process.stdout.write('\nNext commands:\n');
|
|
772
|
+
process.stdout.write(' shrk fix preview --action-hints\n');
|
|
773
|
+
process.stdout.write(' shrk fix preview --knowledge-stale\n');
|
|
774
|
+
process.stdout.write(' shrk fix preview --template-drift\n');
|
|
775
|
+
return errors > 0 ? 1 : 0;
|
|
776
|
+
}
|