@skillsmith/mcp-server 0.4.13 → 0.5.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/CHANGELOG.md +37 -4
- package/README.md +89 -13
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/__tests__/compare.test.js +5 -5
- package/dist/src/__tests__/compare.test.js.map +1 -1
- package/dist/src/__tests__/context-listeners.test.d.ts +12 -0
- package/dist/src/__tests__/context-listeners.test.d.ts.map +1 -0
- package/dist/src/__tests__/context-listeners.test.js +87 -0
- package/dist/src/__tests__/context-listeners.test.js.map +1 -0
- package/dist/src/__tests__/context.test.js +84 -82
- package/dist/src/__tests__/context.test.js.map +1 -1
- package/dist/src/__tests__/get-skill.api-path.test.js +21 -14
- package/dist/src/__tests__/get-skill.api-path.test.js.map +1 -1
- package/dist/src/__tests__/get-skill.test.js +5 -5
- package/dist/src/__tests__/get-skill.test.js.map +1 -1
- package/dist/src/__tests__/index-local.test.js +5 -5
- package/dist/src/__tests__/index-local.test.js.map +1 -1
- package/dist/src/__tests__/recommend-online-path.test.js +5 -5
- package/dist/src/__tests__/recommend-online-path.test.js.map +1 -1
- package/dist/src/__tests__/recommend.test.js +9 -9
- package/dist/src/__tests__/recommend.test.js.map +1 -1
- package/dist/src/__tests__/search-compatible-with.test.d.ts +10 -0
- package/dist/src/__tests__/search-compatible-with.test.d.ts.map +1 -0
- package/dist/src/__tests__/search-compatible-with.test.js +96 -0
- package/dist/src/__tests__/search-compatible-with.test.js.map +1 -0
- package/dist/src/__tests__/search-online-path.test.js +5 -5
- package/dist/src/__tests__/search-online-path.test.js.map +1 -1
- package/dist/src/__tests__/search.test.js +16 -101
- package/dist/src/__tests__/search.test.js.map +1 -1
- package/dist/src/__tests__/test-utils.d.ts +18 -3
- package/dist/src/__tests__/test-utils.d.ts.map +1 -1
- package/dist/src/__tests__/test-utils.js +24 -7
- package/dist/src/__tests__/test-utils.js.map +1 -1
- package/dist/src/audit/audit-history.d.ts +77 -0
- package/dist/src/audit/audit-history.d.ts.map +1 -0
- package/dist/src/audit/audit-history.js +98 -0
- package/dist/src/audit/audit-history.js.map +1 -0
- package/dist/src/audit/audit-report-writer.d.ts +82 -0
- package/dist/src/audit/audit-report-writer.d.ts.map +1 -0
- package/dist/src/audit/audit-report-writer.js +241 -0
- package/dist/src/audit/audit-report-writer.js.map +1 -0
- package/dist/src/audit/audit-suggestions.d.ts +52 -0
- package/dist/src/audit/audit-suggestions.d.ts.map +1 -0
- package/dist/src/audit/audit-suggestions.js +90 -0
- package/dist/src/audit/audit-suggestions.js.map +1 -0
- package/dist/src/audit/bootstrap-unmanaged.d.ts +66 -0
- package/dist/src/audit/bootstrap-unmanaged.d.ts.map +1 -0
- package/dist/src/audit/bootstrap-unmanaged.js +91 -0
- package/dist/src/audit/bootstrap-unmanaged.js.map +1 -0
- package/dist/src/audit/collision-detector.d.ts +72 -0
- package/dist/src/audit/collision-detector.d.ts.map +1 -0
- package/dist/src/audit/collision-detector.helpers.d.ts +63 -0
- package/dist/src/audit/collision-detector.helpers.d.ts.map +1 -0
- package/dist/src/audit/collision-detector.helpers.js +141 -0
- package/dist/src/audit/collision-detector.helpers.js.map +1 -0
- package/dist/src/audit/collision-detector.js +172 -0
- package/dist/src/audit/collision-detector.js.map +1 -0
- package/dist/src/audit/collision-detector.semantic.helpers.d.ts +49 -0
- package/dist/src/audit/collision-detector.semantic.helpers.d.ts.map +1 -0
- package/dist/src/audit/collision-detector.semantic.helpers.js +121 -0
- package/dist/src/audit/collision-detector.semantic.helpers.js.map +1 -0
- package/dist/src/audit/collision-detector.types.d.ts +70 -0
- package/dist/src/audit/collision-detector.types.d.ts.map +1 -0
- package/dist/src/audit/collision-detector.types.js +9 -0
- package/dist/src/audit/collision-detector.types.js.map +1 -0
- package/dist/src/audit/edit-applier.d.ts +64 -0
- package/dist/src/audit/edit-applier.d.ts.map +1 -0
- package/dist/src/audit/edit-applier.js +233 -0
- package/dist/src/audit/edit-applier.js.map +1 -0
- package/dist/src/audit/edit-applier.types.d.ts +72 -0
- package/dist/src/audit/edit-applier.types.d.ts.map +1 -0
- package/dist/src/audit/edit-applier.types.js +13 -0
- package/dist/src/audit/edit-applier.types.js.map +1 -0
- package/dist/src/audit/edit-suggester.d.ts +63 -0
- package/dist/src/audit/edit-suggester.d.ts.map +1 -0
- package/dist/src/audit/edit-suggester.js +326 -0
- package/dist/src/audit/edit-suggester.js.map +1 -0
- package/dist/src/audit/edit-suggester.types.d.ts +148 -0
- package/dist/src/audit/edit-suggester.types.d.ts.map +1 -0
- package/dist/src/audit/edit-suggester.types.js +17 -0
- package/dist/src/audit/edit-suggester.types.js.map +1 -0
- package/dist/src/audit/framework-adapter.d.ts +54 -0
- package/dist/src/audit/framework-adapter.d.ts.map +1 -0
- package/dist/src/audit/framework-adapter.js +251 -0
- package/dist/src/audit/framework-adapter.js.map +1 -0
- package/dist/src/audit/framework-adapter.types.d.ts +162 -0
- package/dist/src/audit/framework-adapter.types.d.ts.map +1 -0
- package/dist/src/audit/framework-adapter.types.js +31 -0
- package/dist/src/audit/framework-adapter.types.js.map +1 -0
- package/dist/src/audit/index.d.ts +46 -0
- package/dist/src/audit/index.d.ts.map +1 -0
- package/dist/src/audit/index.js +44 -0
- package/dist/src/audit/index.js.map +1 -0
- package/dist/src/audit/install-preflight.d.ts +99 -0
- package/dist/src/audit/install-preflight.d.ts.map +1 -0
- package/dist/src/audit/install-preflight.js +320 -0
- package/dist/src/audit/install-preflight.js.map +1 -0
- package/dist/src/audit/namespace-audit.types.d.ts +100 -0
- package/dist/src/audit/namespace-audit.types.d.ts.map +1 -0
- package/dist/src/audit/namespace-audit.types.js +20 -0
- package/dist/src/audit/namespace-audit.types.js.map +1 -0
- package/dist/src/audit/namespace-overrides.d.ts +79 -0
- package/dist/src/audit/namespace-overrides.d.ts.map +1 -0
- package/dist/src/audit/namespace-overrides.js +228 -0
- package/dist/src/audit/namespace-overrides.js.map +1 -0
- package/dist/src/audit/namespace-overrides.types.d.ts +115 -0
- package/dist/src/audit/namespace-overrides.types.d.ts.map +1 -0
- package/dist/src/audit/namespace-overrides.types.js +26 -0
- package/dist/src/audit/namespace-overrides.types.js.map +1 -0
- package/dist/src/audit/rename-engine.apply-paths.d.ts +54 -0
- package/dist/src/audit/rename-engine.apply-paths.d.ts.map +1 -0
- package/dist/src/audit/rename-engine.apply-paths.js +126 -0
- package/dist/src/audit/rename-engine.apply-paths.js.map +1 -0
- package/dist/src/audit/rename-engine.d.ts +59 -0
- package/dist/src/audit/rename-engine.d.ts.map +1 -0
- package/dist/src/audit/rename-engine.helpers.d.ts +63 -0
- package/dist/src/audit/rename-engine.helpers.d.ts.map +1 -0
- package/dist/src/audit/rename-engine.helpers.js +224 -0
- package/dist/src/audit/rename-engine.helpers.js.map +1 -0
- package/dist/src/audit/rename-engine.js +393 -0
- package/dist/src/audit/rename-engine.js.map +1 -0
- package/dist/src/audit/rename-engine.types.d.ts +157 -0
- package/dist/src/audit/rename-engine.types.d.ts.map +1 -0
- package/dist/src/audit/rename-engine.types.js +15 -0
- package/dist/src/audit/rename-engine.types.js.map +1 -0
- package/dist/src/audit/run-inventory-audit.d.ts +95 -0
- package/dist/src/audit/run-inventory-audit.d.ts.map +1 -0
- package/dist/src/audit/run-inventory-audit.js +245 -0
- package/dist/src/audit/run-inventory-audit.js.map +1 -0
- package/dist/src/audit/suggestion-chain.d.ts +89 -0
- package/dist/src/audit/suggestion-chain.d.ts.map +1 -0
- package/dist/src/audit/suggestion-chain.js +121 -0
- package/dist/src/audit/suggestion-chain.js.map +1 -0
- package/dist/src/audit-tool-dispatch.d.ts +61 -0
- package/dist/src/audit-tool-dispatch.d.ts.map +1 -0
- package/dist/src/audit-tool-dispatch.js +114 -0
- package/dist/src/audit-tool-dispatch.js.map +1 -0
- package/dist/src/index.js +34 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexer/LocalIndexer.d.ts +8 -1
- package/dist/src/indexer/LocalIndexer.d.ts.map +1 -1
- package/dist/src/indexer/LocalIndexer.js +42 -38
- package/dist/src/indexer/LocalIndexer.js.map +1 -1
- package/dist/src/middleware/__tests__/license.gate.test.js +21 -2
- package/dist/src/middleware/__tests__/license.gate.test.js.map +1 -1
- package/dist/src/middleware/license.gate.d.ts +14 -0
- package/dist/src/middleware/license.gate.d.ts.map +1 -1
- package/dist/src/middleware/license.gate.js +52 -1
- package/dist/src/middleware/license.gate.js.map +1 -1
- package/dist/src/onboarding/install-assets.d.ts.map +1 -1
- package/dist/src/onboarding/install-assets.js +11 -5
- package/dist/src/onboarding/install-assets.js.map +1 -1
- package/dist/src/tool-dispatch.d.ts.map +1 -1
- package/dist/src/tool-dispatch.js +6 -4
- package/dist/src/tool-dispatch.js.map +1 -1
- package/dist/src/tools/analytics.service.test.js +6 -4
- package/dist/src/tools/analytics.service.test.js.map +1 -1
- package/dist/src/tools/apply-namespace-rename.d.ts +71 -0
- package/dist/src/tools/apply-namespace-rename.d.ts.map +1 -0
- package/dist/src/tools/apply-namespace-rename.js +137 -0
- package/dist/src/tools/apply-namespace-rename.js.map +1 -0
- package/dist/src/tools/apply-namespace-rename.types.d.ts +46 -0
- package/dist/src/tools/apply-namespace-rename.types.d.ts.map +1 -0
- package/dist/src/tools/apply-namespace-rename.types.js +9 -0
- package/dist/src/tools/apply-namespace-rename.types.js.map +1 -0
- package/dist/src/tools/apply-recommended-edit.d.ts +50 -0
- package/dist/src/tools/apply-recommended-edit.d.ts.map +1 -0
- package/dist/src/tools/apply-recommended-edit.js +112 -0
- package/dist/src/tools/apply-recommended-edit.js.map +1 -0
- package/dist/src/tools/apply-recommended-edit.types.d.ts +49 -0
- package/dist/src/tools/apply-recommended-edit.types.d.ts.map +1 -0
- package/dist/src/tools/apply-recommended-edit.types.js +14 -0
- package/dist/src/tools/apply-recommended-edit.types.js.map +1 -0
- package/dist/src/tools/audit-tools.d.ts +4 -4
- package/dist/src/tools/compare.types.js +1 -1
- package/dist/src/tools/compare.types.js.map +1 -1
- package/dist/src/tools/compliance-tools.service.test.js +6 -4
- package/dist/src/tools/compliance-tools.service.test.js.map +1 -1
- package/dist/src/tools/get-skill.d.ts.map +1 -1
- package/dist/src/tools/get-skill.js +1 -1
- package/dist/src/tools/get-skill.js.map +1 -1
- package/dist/src/tools/install.backup-gc.d.ts +61 -0
- package/dist/src/tools/install.backup-gc.d.ts.map +1 -0
- package/dist/src/tools/install.backup-gc.js +166 -0
- package/dist/src/tools/install.backup-gc.js.map +1 -0
- package/dist/src/tools/install.conflict-helpers.d.ts +29 -2
- package/dist/src/tools/install.conflict-helpers.d.ts.map +1 -1
- package/dist/src/tools/install.conflict-helpers.js +37 -4
- package/dist/src/tools/install.conflict-helpers.js.map +1 -1
- package/dist/src/tools/install.d.ts +15 -1
- package/dist/src/tools/install.d.ts.map +1 -1
- package/dist/src/tools/install.js +168 -8
- package/dist/src/tools/install.js.map +1 -1
- package/dist/src/tools/install.ledger-replay.d.ts +52 -0
- package/dist/src/tools/install.ledger-replay.d.ts.map +1 -0
- package/dist/src/tools/install.ledger-replay.js +88 -0
- package/dist/src/tools/install.ledger-replay.js.map +1 -0
- package/dist/src/tools/install.namespace-gate.d.ts +68 -0
- package/dist/src/tools/install.namespace-gate.d.ts.map +1 -0
- package/dist/src/tools/install.namespace-gate.js +129 -0
- package/dist/src/tools/install.namespace-gate.js.map +1 -0
- package/dist/src/tools/install.test.js +136 -1
- package/dist/src/tools/install.test.js.map +1 -1
- package/dist/src/tools/install.tool.d.ts +17 -0
- package/dist/src/tools/install.tool.d.ts.map +1 -1
- package/dist/src/tools/install.tool.js +19 -1
- package/dist/src/tools/install.tool.js.map +1 -1
- package/dist/src/tools/install.types.d.ts +35 -1
- package/dist/src/tools/install.types.d.ts.map +1 -1
- package/dist/src/tools/install.types.js +24 -2
- package/dist/src/tools/install.types.js.map +1 -1
- package/dist/src/tools/namespace-audit/telemetry.d.ts +80 -0
- package/dist/src/tools/namespace-audit/telemetry.d.ts.map +1 -0
- package/dist/src/tools/namespace-audit/telemetry.js +129 -0
- package/dist/src/tools/namespace-audit/telemetry.js.map +1 -0
- package/dist/src/tools/outdated.test.js +2 -2
- package/dist/src/tools/outdated.test.js.map +1 -1
- package/dist/src/tools/publish-private.test.js +2 -2
- package/dist/src/tools/publish-private.test.js.map +1 -1
- package/dist/src/tools/recommend.types.d.ts +2 -2
- package/dist/src/tools/recommend.types.js +1 -1
- package/dist/src/tools/recommend.types.js.map +1 -1
- package/dist/src/tools/search.d.ts +2 -2
- package/dist/src/tools/search.d.ts.map +1 -1
- package/dist/src/tools/search.js +3 -3
- package/dist/src/tools/search.js.map +1 -1
- package/dist/src/tools/skill-audit.test.js +2 -2
- package/dist/src/tools/skill-audit.test.js.map +1 -1
- package/dist/src/tools/skill-diff.d.ts +1 -1
- package/dist/src/tools/skill-inventory-audit.d.ts +67 -0
- package/dist/src/tools/skill-inventory-audit.d.ts.map +1 -0
- package/dist/src/tools/skill-inventory-audit.js +112 -0
- package/dist/src/tools/skill-inventory-audit.js.map +1 -0
- package/dist/src/tools/skill-inventory-audit.types.d.ts +67 -0
- package/dist/src/tools/skill-inventory-audit.types.d.ts.map +1 -0
- package/dist/src/tools/skill-inventory-audit.types.js +14 -0
- package/dist/src/tools/skill-inventory-audit.types.js.map +1 -0
- package/dist/src/tools/skill-pack-audit.d.ts.map +1 -1
- package/dist/src/tools/skill-pack-audit.helpers.d.ts.map +1 -1
- package/dist/src/tools/skill-pack-audit.helpers.js +15 -2
- package/dist/src/tools/skill-pack-audit.helpers.js.map +1 -1
- package/dist/src/tools/skill-pack-audit.js +15 -1
- package/dist/src/tools/skill-pack-audit.js.map +1 -1
- package/dist/src/tools/skill-rescan.d.ts.map +1 -1
- package/dist/src/tools/skill-rescan.js +4 -2
- package/dist/src/tools/skill-rescan.js.map +1 -1
- package/dist/src/tools/suggest.d.ts +2 -2
- package/dist/src/tools/uninstall.d.ts +1 -1
- package/dist/src/tools/uninstall.d.ts.map +1 -1
- package/dist/src/tools/uninstall.js +17 -3
- package/dist/src/tools/uninstall.js.map +1 -1
- package/dist/src/tools/validate.types.d.ts +10 -1
- package/dist/src/tools/validate.types.d.ts.map +1 -1
- package/dist/src/tools/validate.types.js +11 -2
- package/dist/src/tools/validate.types.js.map +1 -1
- package/dist/src/utils/installed-skills.d.ts.map +1 -1
- package/dist/src/utils/installed-skills.js +8 -6
- package/dist/src/utils/installed-skills.js.map +1 -1
- package/dist/src/utils/local-inventory.d.ts +29 -0
- package/dist/src/utils/local-inventory.d.ts.map +1 -0
- package/dist/src/utils/local-inventory.helpers.d.ts +96 -0
- package/dist/src/utils/local-inventory.helpers.d.ts.map +1 -0
- package/dist/src/utils/local-inventory.helpers.js +279 -0
- package/dist/src/utils/local-inventory.helpers.js.map +1 -0
- package/dist/src/utils/local-inventory.js +202 -0
- package/dist/src/utils/local-inventory.js.map +1 -0
- package/dist/src/utils/local-inventory.types.d.ts +100 -0
- package/dist/src/utils/local-inventory.types.d.ts.map +1 -0
- package/dist/src/utils/local-inventory.types.js +9 -0
- package/dist/src/utils/local-inventory.types.js.map +1 -0
- package/dist/src/webhooks/stripe-webhook-endpoint.d.ts +12 -0
- package/dist/src/webhooks/stripe-webhook-endpoint.d.ts.map +1 -1
- package/dist/src/webhooks/stripe-webhook-endpoint.js +30 -9
- package/dist/src/webhooks/stripe-webhook-endpoint.js.map +1 -1
- package/dist/src/webhooks/webhook-endpoint.d.ts +13 -0
- package/dist/src/webhooks/webhook-endpoint.d.ts.map +1 -1
- package/dist/src/webhooks/webhook-endpoint.js +31 -9
- package/dist/src/webhooks/webhook-endpoint.js.map +1 -1
- package/dist/tests/compare.test.js +5 -5
- package/dist/tests/compare.test.js.map +1 -1
- package/dist/tests/context-async-listeners.test.d.ts +12 -0
- package/dist/tests/context-async-listeners.test.d.ts.map +1 -0
- package/dist/tests/context-async-listeners.test.js +62 -0
- package/dist/tests/context-async-listeners.test.js.map +1 -0
- package/dist/tests/e2e/compare.e2e.test.js +9 -3
- package/dist/tests/e2e/compare.e2e.test.js.map +1 -1
- package/dist/tests/e2e/install-flow.e2e.test.js +9 -3
- package/dist/tests/e2e/install-flow.e2e.test.js.map +1 -1
- package/dist/tests/e2e/recommend.e2e.test.js +9 -3
- package/dist/tests/e2e/recommend.e2e.test.js.map +1 -1
- package/dist/tests/e2e/skill-flow.e2e.test.js +17 -5
- package/dist/tests/e2e/skill-flow.e2e.test.js.map +1 -1
- package/dist/tests/e2e/suggest.e2e.test.js +11 -3
- package/dist/tests/e2e/suggest.e2e.test.js.map +1 -1
- package/dist/tests/install-assets.test.d.ts +16 -0
- package/dist/tests/install-assets.test.d.ts.map +1 -0
- package/dist/tests/install-assets.test.js +72 -0
- package/dist/tests/install-assets.test.js.map +1 -0
- package/dist/tests/integration/audit-roundtrip.test.d.ts +29 -0
- package/dist/tests/integration/audit-roundtrip.test.d.ts.map +1 -0
- package/dist/tests/integration/audit-roundtrip.test.js +214 -0
- package/dist/tests/integration/audit-roundtrip.test.js.map +1 -0
- package/dist/tests/integration/install-namespace.integration.test.d.ts +14 -0
- package/dist/tests/integration/install-namespace.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/install-namespace.integration.test.js +414 -0
- package/dist/tests/integration/install-namespace.integration.test.js.map +1 -0
- package/dist/tests/performance/search-performance.test.js +9 -3
- package/dist/tests/performance/search-performance.test.js.map +1 -1
- package/dist/tests/tool-descriptions.test.d.ts +16 -0
- package/dist/tests/tool-descriptions.test.d.ts.map +1 -0
- package/dist/tests/tool-descriptions.test.js +63 -0
- package/dist/tests/tool-descriptions.test.js.map +1 -0
- package/dist/tests/tools.test.js +5 -5
- package/dist/tests/tools.test.js.map +1 -1
- package/dist/tests/unit/apply-namespace-rename.test.d.ts +24 -0
- package/dist/tests/unit/apply-namespace-rename.test.d.ts.map +1 -0
- package/dist/tests/unit/apply-namespace-rename.test.js +205 -0
- package/dist/tests/unit/apply-namespace-rename.test.js.map +1 -0
- package/dist/tests/unit/apply-recommended-edit.test.d.ts +28 -0
- package/dist/tests/unit/apply-recommended-edit.test.d.ts.map +1 -0
- package/dist/tests/unit/apply-recommended-edit.test.js +229 -0
- package/dist/tests/unit/apply-recommended-edit.test.js.map +1 -0
- package/dist/tests/unit/audit-history.test.d.ts +11 -0
- package/dist/tests/unit/audit-history.test.d.ts.map +1 -0
- package/dist/tests/unit/audit-history.test.js +183 -0
- package/dist/tests/unit/audit-history.test.js.map +1 -0
- package/dist/tests/unit/audit-report-writer.test.d.ts +7 -0
- package/dist/tests/unit/audit-report-writer.test.d.ts.map +1 -0
- package/dist/tests/unit/audit-report-writer.test.js +249 -0
- package/dist/tests/unit/audit-report-writer.test.js.map +1 -0
- package/dist/tests/unit/audit-tool-dispatch.test.d.ts +17 -0
- package/dist/tests/unit/audit-tool-dispatch.test.d.ts.map +1 -0
- package/dist/tests/unit/audit-tool-dispatch.test.js +133 -0
- package/dist/tests/unit/audit-tool-dispatch.test.js.map +1 -0
- package/dist/tests/unit/collision-detector.semantic.test.d.ts +12 -0
- package/dist/tests/unit/collision-detector.semantic.test.d.ts.map +1 -0
- package/dist/tests/unit/collision-detector.semantic.test.js +281 -0
- package/dist/tests/unit/collision-detector.semantic.test.js.map +1 -0
- package/dist/tests/unit/collision-detector.test.d.ts +8 -0
- package/dist/tests/unit/collision-detector.test.d.ts.map +1 -0
- package/dist/tests/unit/collision-detector.test.js +266 -0
- package/dist/tests/unit/collision-detector.test.js.map +1 -0
- package/dist/tests/unit/edit-applier.test.d.ts +17 -0
- package/dist/tests/unit/edit-applier.test.d.ts.map +1 -0
- package/dist/tests/unit/edit-applier.test.js +165 -0
- package/dist/tests/unit/edit-applier.test.js.map +1 -0
- package/dist/tests/unit/edit-suggester.fixtures.d.ts +38 -0
- package/dist/tests/unit/edit-suggester.fixtures.d.ts.map +1 -0
- package/dist/tests/unit/edit-suggester.fixtures.js +84 -0
- package/dist/tests/unit/edit-suggester.fixtures.js.map +1 -0
- package/dist/tests/unit/edit-suggester.test.d.ts +17 -0
- package/dist/tests/unit/edit-suggester.test.d.ts.map +1 -0
- package/dist/tests/unit/edit-suggester.test.js +356 -0
- package/dist/tests/unit/edit-suggester.test.js.map +1 -0
- package/dist/tests/unit/framework-adapter.test.d.ts +30 -0
- package/dist/tests/unit/framework-adapter.test.d.ts.map +1 -0
- package/dist/tests/unit/framework-adapter.test.js +221 -0
- package/dist/tests/unit/framework-adapter.test.js.map +1 -0
- package/dist/tests/unit/install-preflight.test.d.ts +17 -0
- package/dist/tests/unit/install-preflight.test.d.ts.map +1 -0
- package/dist/tests/unit/install-preflight.test.js +270 -0
- package/dist/tests/unit/install-preflight.test.js.map +1 -0
- package/dist/tests/unit/install.backup-gc.test.d.ts +18 -0
- package/dist/tests/unit/install.backup-gc.test.d.ts.map +1 -0
- package/dist/tests/unit/install.backup-gc.test.js +177 -0
- package/dist/tests/unit/install.backup-gc.test.js.map +1 -0
- package/dist/tests/unit/install.ledger-replay.test.d.ts +12 -0
- package/dist/tests/unit/install.ledger-replay.test.d.ts.map +1 -0
- package/dist/tests/unit/install.ledger-replay.test.js +98 -0
- package/dist/tests/unit/install.ledger-replay.test.js.map +1 -0
- package/dist/tests/unit/local-inventory.test.d.ts +8 -0
- package/dist/tests/unit/local-inventory.test.d.ts.map +1 -0
- package/dist/tests/unit/local-inventory.test.js +165 -0
- package/dist/tests/unit/local-inventory.test.js.map +1 -0
- package/dist/tests/unit/namespace-audit-telemetry.test.d.ts +10 -0
- package/dist/tests/unit/namespace-audit-telemetry.test.d.ts.map +1 -0
- package/dist/tests/unit/namespace-audit-telemetry.test.js +215 -0
- package/dist/tests/unit/namespace-audit-telemetry.test.js.map +1 -0
- package/dist/tests/unit/namespace-overrides.test.d.ts +18 -0
- package/dist/tests/unit/namespace-overrides.test.d.ts.map +1 -0
- package/dist/tests/unit/namespace-overrides.test.js +210 -0
- package/dist/tests/unit/namespace-overrides.test.js.map +1 -0
- package/dist/tests/unit/rename-engine.test.d.ts +26 -0
- package/dist/tests/unit/rename-engine.test.d.ts.map +1 -0
- package/dist/tests/unit/rename-engine.test.js +367 -0
- package/dist/tests/unit/rename-engine.test.js.map +1 -0
- package/dist/tests/unit/skill-inventory-audit.test.d.ts +20 -0
- package/dist/tests/unit/skill-inventory-audit.test.d.ts.map +1 -0
- package/dist/tests/unit/skill-inventory-audit.test.js +299 -0
- package/dist/tests/unit/skill-inventory-audit.test.js.map +1 -0
- package/dist/tests/unit/skill-pack-audit.helpers.test.d.ts +11 -0
- package/dist/tests/unit/skill-pack-audit.helpers.test.d.ts.map +1 -0
- package/dist/tests/unit/skill-pack-audit.helpers.test.js +61 -0
- package/dist/tests/unit/skill-pack-audit.helpers.test.js.map +1 -0
- package/dist/tests/unit/skill-pack-audit.test.js +1 -1
- package/dist/tests/unit/skill-pack-audit.test.js.map +1 -1
- package/dist/tests/unit/suggestion-chain.test.d.ts +17 -0
- package/dist/tests/unit/suggestion-chain.test.d.ts.map +1 -0
- package/dist/tests/unit/suggestion-chain.test.js +191 -0
- package/dist/tests/unit/suggestion-chain.test.js.map +1 -0
- package/dist/tests/webhooks/standalone-shutdown.test.d.ts +12 -0
- package/dist/tests/webhooks/standalone-shutdown.test.d.ts.map +1 -0
- package/dist/tests/webhooks/standalone-shutdown.test.js +91 -0
- package/dist/tests/webhooks/standalone-shutdown.test.js.map +1 -0
- package/package.json +17 -4
- package/server.json +3 -3
- package/src/assets/skills/skillsmith/SKILL.md +109 -80
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Markdown audit-report writer for SMI-4587 Wave 1 Step 7/8.
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/audit-report-writer
|
|
4
|
+
*
|
|
5
|
+
* Renders an `InventoryAuditResult` into the markdown report stored at
|
|
6
|
+
* `~/.skillsmith/audits/<auditId>/report.md`. Atomic via tmp-file +
|
|
7
|
+
* `fs.rename` (mirrors `audit-history.ts`).
|
|
8
|
+
*
|
|
9
|
+
* Sections, in order (plan §446):
|
|
10
|
+
* 1. Summary header — auditId, generated-at, totals
|
|
11
|
+
* 2. CLAUDE.md scan caveat — only when any inventory entry is
|
|
12
|
+
* `kind: 'claude_md_rule'` (D-ANTI-1)
|
|
13
|
+
* 3. Exact collisions — each lists involved entries with absolute paths
|
|
14
|
+
* 4. Generic flags — matched tokens, suggested rename if any
|
|
15
|
+
* 5. Semantic collisions — cosine score, overlapping phrases
|
|
16
|
+
* 6. Recommended edits — Wave 3 plumbing; Wave 1 emits a placeholder
|
|
17
|
+
*
|
|
18
|
+
* Wave 2/4 import this writer via `@skillsmith/mcp-server/audit` (Step 9
|
|
19
|
+
* barrel).
|
|
20
|
+
*/
|
|
21
|
+
import type { InventoryAuditResult } from './collision-detector.types.js';
|
|
22
|
+
import type { RenameSuggestion } from './rename-engine.types.js';
|
|
23
|
+
import type { RecommendedEdit } from './edit-suggester.types.js';
|
|
24
|
+
export interface AuditReportRenderOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Override the report's "Generated" timestamp. Defaults to a fresh
|
|
27
|
+
* `new Date()` at render time. Tests pin this to keep snapshots
|
|
28
|
+
* deterministic; production callers pass nothing.
|
|
29
|
+
*/
|
|
30
|
+
generatedAt?: Date;
|
|
31
|
+
/**
|
|
32
|
+
* Per-collision rename suggestions to render in the "Recommended edits"
|
|
33
|
+
* section (SMI-4588 Wave 2 PR #4 / Step 8). When provided AND non-empty,
|
|
34
|
+
* the writer replaces the Wave 1 placeholder with a table of
|
|
35
|
+
* `currentName → suggested` pairs plus a copy-paste-ready CLI
|
|
36
|
+
* invocation per row. Pass nothing (or an empty array) to keep the
|
|
37
|
+
* Wave 1 placeholder behavior — backward-compatible with existing
|
|
38
|
+
* audit-report consumers.
|
|
39
|
+
*
|
|
40
|
+
* Wave 4 wires this from `runInstallPreflight` /
|
|
41
|
+
* `generateRenameSuggestions` outputs; Wave 2 ships only the
|
|
42
|
+
* rendering surface.
|
|
43
|
+
*/
|
|
44
|
+
renameSuggestions?: ReadonlyArray<RenameSuggestion>;
|
|
45
|
+
/**
|
|
46
|
+
* Recommended prose edits to render in the "Recommended Edits"
|
|
47
|
+
* section (SMI-4589 Wave 3). When provided AND non-empty, the writer
|
|
48
|
+
* renders each edit as a `diff` fenced markdown block per plan §2.
|
|
49
|
+
* Pass nothing (or an empty array) to omit the section entirely.
|
|
50
|
+
*
|
|
51
|
+
* Wave 4 wires this from `runEditSuggester` outputs; Wave 3 ships
|
|
52
|
+
* only the rendering surface here. Per the per-template gate
|
|
53
|
+
* ratified 2026-05-01, only `add_domain_qualifier`-pattern edits
|
|
54
|
+
* surface in v1; failing-template edits are absent from
|
|
55
|
+
* `runEditSuggester`'s output entirely.
|
|
56
|
+
*/
|
|
57
|
+
recommendedEdits?: ReadonlyArray<RecommendedEdit>;
|
|
58
|
+
}
|
|
59
|
+
export interface AuditReportWriteOptions extends AuditReportRenderOptions {
|
|
60
|
+
/**
|
|
61
|
+
* Per-audit directory (sibling of `result.json`). The writer assumes the
|
|
62
|
+
* directory already exists — `writeAuditHistory` creates it.
|
|
63
|
+
*/
|
|
64
|
+
auditDir: string;
|
|
65
|
+
}
|
|
66
|
+
export interface AuditReportWriteResult {
|
|
67
|
+
/** Absolute path to the rendered `report.md`. */
|
|
68
|
+
reportPath: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Render an `InventoryAuditResult` into the audit-report markdown body.
|
|
72
|
+
* Pure — no IO. Exposed so tests can inspect the output without round-
|
|
73
|
+
* tripping through the filesystem.
|
|
74
|
+
*/
|
|
75
|
+
export declare function renderAuditReport(result: InventoryAuditResult, opts?: AuditReportRenderOptions): string;
|
|
76
|
+
/**
|
|
77
|
+
* Persist the rendered report to `<auditDir>/report.md`. Atomic via
|
|
78
|
+
* tmp-file + `fs.rename`, matching the audit-history writer's contract so
|
|
79
|
+
* concurrent readers never observe a partially-written file.
|
|
80
|
+
*/
|
|
81
|
+
export declare function writeAuditReport(result: InventoryAuditResult, opts: AuditReportWriteOptions): Promise<AuditReportWriteResult>;
|
|
82
|
+
//# sourceMappingURL=audit-report-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-report-writer.d.ts","sourceRoot":"","sources":["../../../src/audit/audit-report-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,KAAK,EAIV,oBAAoB,EAErB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEhE,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,WAAW,CAAC,EAAE,IAAI,CAAA;IAClB;;;;;;;;;;;;OAYG;IACH,iBAAiB,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAA;IACnD;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAA;CAClD;AAED,MAAM,WAAW,uBAAwB,SAAQ,wBAAwB;IACvE;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,oBAAoB,EAC5B,IAAI,GAAE,wBAA6B,GAClC,MAAM,CAoCR;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,sBAAsB,CAAC,CAYjC"}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Markdown audit-report writer for SMI-4587 Wave 1 Step 7/8.
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/audit-report-writer
|
|
4
|
+
*
|
|
5
|
+
* Renders an `InventoryAuditResult` into the markdown report stored at
|
|
6
|
+
* `~/.skillsmith/audits/<auditId>/report.md`. Atomic via tmp-file +
|
|
7
|
+
* `fs.rename` (mirrors `audit-history.ts`).
|
|
8
|
+
*
|
|
9
|
+
* Sections, in order (plan §446):
|
|
10
|
+
* 1. Summary header — auditId, generated-at, totals
|
|
11
|
+
* 2. CLAUDE.md scan caveat — only when any inventory entry is
|
|
12
|
+
* `kind: 'claude_md_rule'` (D-ANTI-1)
|
|
13
|
+
* 3. Exact collisions — each lists involved entries with absolute paths
|
|
14
|
+
* 4. Generic flags — matched tokens, suggested rename if any
|
|
15
|
+
* 5. Semantic collisions — cosine score, overlapping phrases
|
|
16
|
+
* 6. Recommended edits — Wave 3 plumbing; Wave 1 emits a placeholder
|
|
17
|
+
*
|
|
18
|
+
* Wave 2/4 import this writer via `@skillsmith/mcp-server/audit` (Step 9
|
|
19
|
+
* barrel).
|
|
20
|
+
*/
|
|
21
|
+
import * as fs from 'node:fs/promises';
|
|
22
|
+
import * as path from 'node:path';
|
|
23
|
+
/**
|
|
24
|
+
* Render an `InventoryAuditResult` into the audit-report markdown body.
|
|
25
|
+
* Pure — no IO. Exposed so tests can inspect the output without round-
|
|
26
|
+
* tripping through the filesystem.
|
|
27
|
+
*/
|
|
28
|
+
export function renderAuditReport(result, opts = {}) {
|
|
29
|
+
const generatedAt = opts.generatedAt ?? new Date();
|
|
30
|
+
const sections = [];
|
|
31
|
+
sections.push(renderSummaryHeader(result, generatedAt));
|
|
32
|
+
if (containsClaudeMdRule(result)) {
|
|
33
|
+
sections.push(renderClaudeMdCaveat());
|
|
34
|
+
}
|
|
35
|
+
if (result.exactCollisions.length > 0) {
|
|
36
|
+
sections.push(renderExactCollisions(result.exactCollisions));
|
|
37
|
+
}
|
|
38
|
+
if (result.genericFlags.length > 0) {
|
|
39
|
+
sections.push(renderGenericFlags(result.genericFlags));
|
|
40
|
+
}
|
|
41
|
+
if (result.semanticCollisions.length > 0) {
|
|
42
|
+
sections.push(renderSemanticCollisions(result.semanticCollisions));
|
|
43
|
+
}
|
|
44
|
+
sections.push(renderRecommendedEdits(opts.renameSuggestions, result.auditId));
|
|
45
|
+
// SMI-4589 Wave 3: prose-edit suggestions render in their own section
|
|
46
|
+
// immediately after the Wave 2 rename-suggestion section. Empty input
|
|
47
|
+
// omits the section entirely (no placeholder text — keeps the report
|
|
48
|
+
// tight when no semantic collisions fired).
|
|
49
|
+
if (opts.recommendedEdits && opts.recommendedEdits.length > 0) {
|
|
50
|
+
sections.push(renderRecommendedEditsSection(opts.recommendedEdits));
|
|
51
|
+
}
|
|
52
|
+
// Single trailing newline. `trimEnd()` (not `/\n+$/`) is intentional —
|
|
53
|
+
// see SMI-4733: any non-`\n` trailing whitespace that leaks in is
|
|
54
|
+
// acceptable to strip in an ASCII report, and the non-regex form
|
|
55
|
+
// sidesteps polynomial backtracking flagged by CodeQL.
|
|
56
|
+
return sections.join('\n').trimEnd() + '\n';
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Persist the rendered report to `<auditDir>/report.md`. Atomic via
|
|
60
|
+
* tmp-file + `fs.rename`, matching the audit-history writer's contract so
|
|
61
|
+
* concurrent readers never observe a partially-written file.
|
|
62
|
+
*/
|
|
63
|
+
export async function writeAuditReport(result, opts) {
|
|
64
|
+
const reportPath = path.join(opts.auditDir, 'report.md');
|
|
65
|
+
const tmpPath = `${reportPath}.tmp`;
|
|
66
|
+
await fs.mkdir(opts.auditDir, { recursive: true });
|
|
67
|
+
const body = renderAuditReport(result, {
|
|
68
|
+
generatedAt: opts.generatedAt,
|
|
69
|
+
renameSuggestions: opts.renameSuggestions,
|
|
70
|
+
recommendedEdits: opts.recommendedEdits,
|
|
71
|
+
});
|
|
72
|
+
await fs.writeFile(tmpPath, body, 'utf-8');
|
|
73
|
+
await fs.rename(tmpPath, reportPath);
|
|
74
|
+
return { reportPath };
|
|
75
|
+
}
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Section renderers
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
function renderSummaryHeader(result, generatedAt) {
|
|
80
|
+
const lines = [];
|
|
81
|
+
lines.push(`# Skillsmith Namespace Audit — ${result.auditId}`);
|
|
82
|
+
lines.push('');
|
|
83
|
+
lines.push(`- Generated: ${generatedAt.toISOString()}`);
|
|
84
|
+
lines.push(`- Total entries scanned: ${result.summary.totalEntries}`);
|
|
85
|
+
lines.push(`- Total flags: ${result.summary.totalFlags}`);
|
|
86
|
+
lines.push(` - Errors (exact collisions): ${result.summary.errorCount}`);
|
|
87
|
+
lines.push(` - Warnings (generic + semantic): ${result.summary.warningCount}`);
|
|
88
|
+
lines.push(`- Audit duration: ${result.summary.durationMs.toFixed(2)}ms`);
|
|
89
|
+
lines.push('');
|
|
90
|
+
return lines.join('\n');
|
|
91
|
+
}
|
|
92
|
+
function renderClaudeMdCaveat() {
|
|
93
|
+
const lines = [];
|
|
94
|
+
lines.push('## CLAUDE.md scan caveat');
|
|
95
|
+
lines.push('');
|
|
96
|
+
lines.push('This audit included trigger phrases extracted from `CLAUDE.md` rules. ');
|
|
97
|
+
lines.push('Phrase extraction is heuristic — false-positives are possible when a ');
|
|
98
|
+
lines.push('rule is phrased imperatively ("when X, do Y") without intending to ');
|
|
99
|
+
lines.push('overlap with a skill trigger. Review collisions involving ');
|
|
100
|
+
lines.push('`claude_md_rule` entries before applying any rename.');
|
|
101
|
+
lines.push('');
|
|
102
|
+
return lines.join('\n');
|
|
103
|
+
}
|
|
104
|
+
function renderExactCollisions(flags) {
|
|
105
|
+
const lines = [];
|
|
106
|
+
lines.push('## Exact collisions');
|
|
107
|
+
lines.push('');
|
|
108
|
+
for (const flag of flags) {
|
|
109
|
+
lines.push(`### \`${flag.identifier}\` (${flag.entries.length} entries)`);
|
|
110
|
+
lines.push('');
|
|
111
|
+
lines.push(`- Severity: **${flag.severity}**`);
|
|
112
|
+
lines.push(`- Collision id: \`${flag.collisionId}\``);
|
|
113
|
+
lines.push(`- Reason: ${flag.reason}`);
|
|
114
|
+
lines.push('- Involved entries:');
|
|
115
|
+
for (const entry of flag.entries) {
|
|
116
|
+
lines.push(` - [${entry.kind}] ${entry.source_path}`);
|
|
117
|
+
}
|
|
118
|
+
lines.push('');
|
|
119
|
+
}
|
|
120
|
+
return lines.join('\n');
|
|
121
|
+
}
|
|
122
|
+
function renderGenericFlags(flags) {
|
|
123
|
+
const lines = [];
|
|
124
|
+
lines.push('## Generic-token flags');
|
|
125
|
+
lines.push('');
|
|
126
|
+
for (const flag of flags) {
|
|
127
|
+
lines.push(`### \`${flag.identifier}\``);
|
|
128
|
+
lines.push('');
|
|
129
|
+
lines.push(`- Severity: **${flag.severity}**`);
|
|
130
|
+
lines.push(`- Collision id: \`${flag.collisionId}\``);
|
|
131
|
+
lines.push(`- Source: ${flag.entry.source_path}`);
|
|
132
|
+
lines.push(`- Matched generic tokens: ${formatTokens(flag.matchedTokens)}`);
|
|
133
|
+
lines.push(`- Reason: ${flag.reason}`);
|
|
134
|
+
lines.push('');
|
|
135
|
+
}
|
|
136
|
+
return lines.join('\n');
|
|
137
|
+
}
|
|
138
|
+
function renderSemanticCollisions(flags) {
|
|
139
|
+
const lines = [];
|
|
140
|
+
lines.push('## Semantic collisions');
|
|
141
|
+
lines.push('');
|
|
142
|
+
for (const flag of flags) {
|
|
143
|
+
lines.push(`### ${describeEntry(flag.entryA)} ↔ ${describeEntry(flag.entryB)}`);
|
|
144
|
+
lines.push('');
|
|
145
|
+
lines.push(`- Severity: **${flag.severity}**`);
|
|
146
|
+
lines.push(`- Collision id: \`${flag.collisionId}\``);
|
|
147
|
+
lines.push(`- Cosine score: ${flag.cosineScore.toFixed(3)}`);
|
|
148
|
+
lines.push(`- Reason: ${flag.reason}`);
|
|
149
|
+
lines.push(`- Entry A: ${flag.entryA.source_path}`);
|
|
150
|
+
lines.push(`- Entry B: ${flag.entryB.source_path}`);
|
|
151
|
+
if (flag.overlappingPhrases.length > 0) {
|
|
152
|
+
lines.push('- Overlapping phrases:');
|
|
153
|
+
for (const pair of flag.overlappingPhrases) {
|
|
154
|
+
lines.push(` - "${pair.phrase1}" ↔ "${pair.phrase2}" (sim ${pair.similarity.toFixed(3)})`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
lines.push('');
|
|
158
|
+
}
|
|
159
|
+
return lines.join('\n');
|
|
160
|
+
}
|
|
161
|
+
function renderRecommendedEdits(suggestions, auditId) {
|
|
162
|
+
const lines = [];
|
|
163
|
+
lines.push('## Recommended edits');
|
|
164
|
+
lines.push('');
|
|
165
|
+
if (!suggestions || suggestions.length === 0) {
|
|
166
|
+
// Wave 1 placeholder preserved for backward compatibility — no
|
|
167
|
+
// suggestion data was passed in.
|
|
168
|
+
lines.push('_No automated edits suggested in Wave 1._');
|
|
169
|
+
lines.push('');
|
|
170
|
+
return lines.join('\n');
|
|
171
|
+
}
|
|
172
|
+
// Wave 2 PR #4 (Step 8): render a markdown table of rename suggestions
|
|
173
|
+
// with copy-paste-ready CLI invocations. Wave 4 wires the actual CLI;
|
|
174
|
+
// this writer just renders the suggestion text.
|
|
175
|
+
lines.push('| Current name | Suggested rename | Apply action | Apply command |');
|
|
176
|
+
lines.push('|---|---|---|---|');
|
|
177
|
+
for (const suggestion of suggestions) {
|
|
178
|
+
const cmd = `\`sklx audit collisions apply ${auditId} ${suggestion.collisionId}\``;
|
|
179
|
+
lines.push(`| \`${suggestion.currentName}\` | \`${suggestion.suggested}\` | ${suggestion.applyAction} | ${cmd} |`);
|
|
180
|
+
}
|
|
181
|
+
lines.push('');
|
|
182
|
+
for (const suggestion of suggestions) {
|
|
183
|
+
lines.push(`### \`${suggestion.currentName}\` → \`${suggestion.suggested}\``);
|
|
184
|
+
lines.push('');
|
|
185
|
+
lines.push(`- Collision id: \`${suggestion.collisionId}\``);
|
|
186
|
+
lines.push(`- Reason: ${suggestion.reason}`);
|
|
187
|
+
lines.push(`- Source: ${suggestion.entry.source_path}`);
|
|
188
|
+
lines.push('');
|
|
189
|
+
}
|
|
190
|
+
return lines.join('\n');
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* SMI-4589 Wave 3: render the prose-edit suggestions section. Each edit
|
|
194
|
+
* becomes a markdown block with file/lineRange metadata and a `diff`
|
|
195
|
+
* fenced code block showing the before/after pair with `-`/`+` line
|
|
196
|
+
* prefixes — renders with syntax highlighting in GitHub / VSCode.
|
|
197
|
+
*
|
|
198
|
+
* Plan §2 mandates the diff block format over separate before/after
|
|
199
|
+
* plain-text blocks because the unified-diff form gives free
|
|
200
|
+
* highlighting and a familiar review surface.
|
|
201
|
+
*/
|
|
202
|
+
function renderRecommendedEditsSection(edits) {
|
|
203
|
+
const lines = [];
|
|
204
|
+
lines.push('## Recommended Edits');
|
|
205
|
+
lines.push('');
|
|
206
|
+
for (const edit of edits) {
|
|
207
|
+
lines.push(`### Recommended edit: differentiate from \`${edit.otherEntry.identifier}\``);
|
|
208
|
+
lines.push('');
|
|
209
|
+
lines.push(`**File**: \`${edit.filePath}\``);
|
|
210
|
+
lines.push(`**Lines**: ${edit.lineRange.start}-${edit.lineRange.end}`);
|
|
211
|
+
lines.push(`**Pattern**: \`${edit.pattern}\` (${edit.applyMode})`);
|
|
212
|
+
lines.push('');
|
|
213
|
+
lines.push('```diff');
|
|
214
|
+
for (const beforeLine of edit.before.split('\n')) {
|
|
215
|
+
lines.push(`-${beforeLine}`);
|
|
216
|
+
}
|
|
217
|
+
for (const afterLine of edit.after.split('\n')) {
|
|
218
|
+
lines.push(`+${afterLine}`);
|
|
219
|
+
}
|
|
220
|
+
lines.push('```');
|
|
221
|
+
lines.push('');
|
|
222
|
+
lines.push(`**Why**: ${edit.rationale}`);
|
|
223
|
+
lines.push('');
|
|
224
|
+
}
|
|
225
|
+
return lines.join('\n');
|
|
226
|
+
}
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
// Helpers
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
function containsClaudeMdRule(result) {
|
|
231
|
+
return result.inventory.some((e) => e.kind === 'claude_md_rule');
|
|
232
|
+
}
|
|
233
|
+
function describeEntry(entry) {
|
|
234
|
+
return `\`${entry.identifier}\` (${entry.kind})`;
|
|
235
|
+
}
|
|
236
|
+
function formatTokens(tokens) {
|
|
237
|
+
if (tokens.length === 0)
|
|
238
|
+
return '_none_';
|
|
239
|
+
return tokens.map((t) => `\`${t}\``).join(', ');
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=audit-report-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-report-writer.js","sourceRoot":"","sources":["../../../src/audit/audit-report-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Per-audit suggestion persistence (SMI-4590 Wave 4 PR 4).
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/audit-suggestions
|
|
4
|
+
*
|
|
5
|
+
* Persists `RenameSuggestion[]` (Wave 2) + `RecommendedEdit[]` (Wave 3)
|
|
6
|
+
* alongside the existing `~/.skillsmith/audits/<auditId>/result.json`
|
|
7
|
+
* (Wave 1, see `audit-history.ts`). The `apply_namespace_rename` and
|
|
8
|
+
* `apply_recommended_edit` MCP tools (this PR) read this file to look up
|
|
9
|
+
* the suggestion that corresponds to a `(auditId, collisionId)` pair.
|
|
10
|
+
*
|
|
11
|
+
* File layout: `<auditDir>/suggestions.json` — atomic via tmp-file +
|
|
12
|
+
* `fs.rename`, mirroring `audit-history.ts`. Schema is versioned so a
|
|
13
|
+
* future PR can extend the persisted shape without breaking older
|
|
14
|
+
* audit dirs.
|
|
15
|
+
*
|
|
16
|
+
* Why a sibling file (vs. extending `result.json`):
|
|
17
|
+
* - `result.json` is keyed by `InventoryAuditResult` shape (Wave 1
|
|
18
|
+
* barrel surface). Extending it pulls Wave 2/3 types into Wave 1's
|
|
19
|
+
* persistence layer.
|
|
20
|
+
* - The CLI (PR 5) wants to render `result.json` as-is for
|
|
21
|
+
* `--report-only` callers; suggestions live alongside but aren't
|
|
22
|
+
* part of the inventory snapshot.
|
|
23
|
+
*/
|
|
24
|
+
import type { RecommendedEdit } from './edit-suggester.types.js';
|
|
25
|
+
import type { RenameSuggestion } from './rename-engine.types.js';
|
|
26
|
+
/** Persisted shape. `version: 1` is the only supported schema. */
|
|
27
|
+
export interface AuditSuggestionsFile {
|
|
28
|
+
version: 1;
|
|
29
|
+
auditId: string;
|
|
30
|
+
renameSuggestions: RenameSuggestion[];
|
|
31
|
+
recommendedEdits: RecommendedEdit[];
|
|
32
|
+
}
|
|
33
|
+
export interface AuditSuggestionsOptions {
|
|
34
|
+
/** Override the audits root (default `~/.skillsmith/audits`). */
|
|
35
|
+
auditsDir?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Persist the suggestion arrays for `auditId` to
|
|
39
|
+
* `<auditsDir>/<auditId>/suggestions.json`. Atomic. Creates the per-audit
|
|
40
|
+
* directory if missing (matches `writeAuditHistory` semantics).
|
|
41
|
+
*/
|
|
42
|
+
export declare function writeAuditSuggestions(auditId: string, renameSuggestions: ReadonlyArray<RenameSuggestion>, recommendedEdits: ReadonlyArray<RecommendedEdit>, opts?: AuditSuggestionsOptions): Promise<{
|
|
43
|
+
suggestionsPath: string;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Read back the persisted suggestions for `auditId`. Returns `null` for
|
|
47
|
+
* unknown / missing audit dirs and for malformed / wrong-version files.
|
|
48
|
+
* Callers treat the absence as "no suggestions"; the apply-tools surface
|
|
49
|
+
* a typed error when the lookup is required but returns null.
|
|
50
|
+
*/
|
|
51
|
+
export declare function readAuditSuggestions(auditId: string, opts?: AuditSuggestionsOptions): Promise<AuditSuggestionsFile | null>;
|
|
52
|
+
//# sourceMappingURL=audit-suggestions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-suggestions.d.ts","sourceRoot":"","sources":["../../../src/audit/audit-suggestions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAIhE,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,iBAAiB,EAAE,gBAAgB,EAAE,CAAA;IACrC,gBAAgB,EAAE,eAAe,EAAE,CAAA;CACpC;AAED,MAAM,WAAW,uBAAuB;IACtC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,iBAAiB,EAAE,aAAa,CAAC,gBAAgB,CAAC,EAClD,gBAAgB,EAAE,aAAa,CAAC,eAAe,CAAC,EAChD,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC;IAAE,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBtC;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAoBtC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Per-audit suggestion persistence (SMI-4590 Wave 4 PR 4).
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/audit-suggestions
|
|
4
|
+
*
|
|
5
|
+
* Persists `RenameSuggestion[]` (Wave 2) + `RecommendedEdit[]` (Wave 3)
|
|
6
|
+
* alongside the existing `~/.skillsmith/audits/<auditId>/result.json`
|
|
7
|
+
* (Wave 1, see `audit-history.ts`). The `apply_namespace_rename` and
|
|
8
|
+
* `apply_recommended_edit` MCP tools (this PR) read this file to look up
|
|
9
|
+
* the suggestion that corresponds to a `(auditId, collisionId)` pair.
|
|
10
|
+
*
|
|
11
|
+
* File layout: `<auditDir>/suggestions.json` — atomic via tmp-file +
|
|
12
|
+
* `fs.rename`, mirroring `audit-history.ts`. Schema is versioned so a
|
|
13
|
+
* future PR can extend the persisted shape without breaking older
|
|
14
|
+
* audit dirs.
|
|
15
|
+
*
|
|
16
|
+
* Why a sibling file (vs. extending `result.json`):
|
|
17
|
+
* - `result.json` is keyed by `InventoryAuditResult` shape (Wave 1
|
|
18
|
+
* barrel surface). Extending it pulls Wave 2/3 types into Wave 1's
|
|
19
|
+
* persistence layer.
|
|
20
|
+
* - The CLI (PR 5) wants to render `result.json` as-is for
|
|
21
|
+
* `--report-only` callers; suggestions live alongside but aren't
|
|
22
|
+
* part of the inventory snapshot.
|
|
23
|
+
*/
|
|
24
|
+
import * as fs from 'node:fs/promises';
|
|
25
|
+
import * as os from 'node:os';
|
|
26
|
+
import * as path from 'node:path';
|
|
27
|
+
const DEFAULT_AUDITS_DIR = path.join(os.homedir(), '.skillsmith', 'audits');
|
|
28
|
+
/**
|
|
29
|
+
* Persist the suggestion arrays for `auditId` to
|
|
30
|
+
* `<auditsDir>/<auditId>/suggestions.json`. Atomic. Creates the per-audit
|
|
31
|
+
* directory if missing (matches `writeAuditHistory` semantics).
|
|
32
|
+
*/
|
|
33
|
+
export async function writeAuditSuggestions(auditId, renameSuggestions, recommendedEdits, opts = {}) {
|
|
34
|
+
const auditsDir = opts.auditsDir ?? DEFAULT_AUDITS_DIR;
|
|
35
|
+
const auditDir = path.join(auditsDir, auditId);
|
|
36
|
+
const suggestionsPath = path.join(auditDir, 'suggestions.json');
|
|
37
|
+
const tmpPath = `${suggestionsPath}.tmp`;
|
|
38
|
+
await fs.mkdir(auditDir, { recursive: true });
|
|
39
|
+
const payload = {
|
|
40
|
+
version: 1,
|
|
41
|
+
auditId,
|
|
42
|
+
renameSuggestions: [...renameSuggestions],
|
|
43
|
+
recommendedEdits: [...recommendedEdits],
|
|
44
|
+
};
|
|
45
|
+
await fs.writeFile(tmpPath, JSON.stringify(payload, null, 2), 'utf-8');
|
|
46
|
+
await fs.rename(tmpPath, suggestionsPath);
|
|
47
|
+
return { suggestionsPath };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Read back the persisted suggestions for `auditId`. Returns `null` for
|
|
51
|
+
* unknown / missing audit dirs and for malformed / wrong-version files.
|
|
52
|
+
* Callers treat the absence as "no suggestions"; the apply-tools surface
|
|
53
|
+
* a typed error when the lookup is required but returns null.
|
|
54
|
+
*/
|
|
55
|
+
export async function readAuditSuggestions(auditId, opts = {}) {
|
|
56
|
+
const auditsDir = opts.auditsDir ?? DEFAULT_AUDITS_DIR;
|
|
57
|
+
const suggestionsPath = path.join(auditsDir, auditId, 'suggestions.json');
|
|
58
|
+
let raw;
|
|
59
|
+
try {
|
|
60
|
+
raw = await fs.readFile(suggestionsPath, 'utf-8');
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
let parsed;
|
|
66
|
+
try {
|
|
67
|
+
parsed = JSON.parse(raw);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
if (!isAuditSuggestionsFile(parsed))
|
|
73
|
+
return null;
|
|
74
|
+
return parsed;
|
|
75
|
+
}
|
|
76
|
+
function isAuditSuggestionsFile(v) {
|
|
77
|
+
if (!v || typeof v !== 'object')
|
|
78
|
+
return false;
|
|
79
|
+
const obj = v;
|
|
80
|
+
if (obj.version !== 1)
|
|
81
|
+
return false;
|
|
82
|
+
if (typeof obj.auditId !== 'string' || obj.auditId.length === 0)
|
|
83
|
+
return false;
|
|
84
|
+
if (!Array.isArray(obj.renameSuggestions))
|
|
85
|
+
return false;
|
|
86
|
+
if (!Array.isArray(obj.recommendedEdits))
|
|
87
|
+
return false;
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=audit-suggestions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-suggestions.js","sourceRoot":"","sources":["../../../src/audit/audit-suggestions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Bootstrap unmanaged skills for SMI-4587 Wave 1 Step 6a.
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/bootstrap-unmanaged
|
|
4
|
+
*
|
|
5
|
+
* Iterates over inventory entries and registers any unmanaged SKILL.md
|
|
6
|
+
* via `index_local`. Failures are converted into typed `warnings[]`
|
|
7
|
+
* entries (`namespace.inventory.bootstrap_failed`) — never thrown — so
|
|
8
|
+
* the audit run can complete even when individual bootstrap calls fail
|
|
9
|
+
* (decision #12 in plan).
|
|
10
|
+
*
|
|
11
|
+
* Wave 1 PR #4 (Step 8 / NEW-E-2) wires the real `indexLocalSkill` core
|
|
12
|
+
* helper as the default `bootstrapFn` — replacing PR #3's no-op stub. The
|
|
13
|
+
* MCP-side `parseFrontmatter` is injected so behaviour matches the
|
|
14
|
+
* existing `LocalIndexer` path bit-for-bit.
|
|
15
|
+
*
|
|
16
|
+
* "Unmanaged" = `kind: 'skill'` AND `meta.author` is undefined (i.e.,
|
|
17
|
+
* the skill is not registered in `~/.skillsmith/manifest.json`).
|
|
18
|
+
*/
|
|
19
|
+
import type { InventoryEntry, ScanWarning } from '../utils/local-inventory.types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Per-entry bootstrap callback. Implementations register the skill with
|
|
22
|
+
* `index_local` (or the future `indexLocalSkill` core helper) and return
|
|
23
|
+
* void on success. Throwing converts to a typed warning, never a hard
|
|
24
|
+
* fail.
|
|
25
|
+
*/
|
|
26
|
+
export type BootstrapFn = (entry: InventoryEntry) => Promise<void>;
|
|
27
|
+
export interface BootstrapUnmanagedOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Bootstrap callback. Defaults to {@link defaultIndexLocalSkillBootstrap}
|
|
30
|
+
* (PR #4 / NEW-E-2 wiring) which delegates to the real `indexLocalSkill`
|
|
31
|
+
* core helper. Tests can substitute a vi.fn() to assert call counts and
|
|
32
|
+
* exercise the failure-warning path.
|
|
33
|
+
*/
|
|
34
|
+
bootstrapFn?: BootstrapFn;
|
|
35
|
+
/** Optional logger sink for non-fatal diagnostics (debug-level). */
|
|
36
|
+
logger?: {
|
|
37
|
+
debug?: (msg: string, meta?: unknown) => void;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export interface BootstrapUnmanagedResult {
|
|
41
|
+
/** Number of entries that were considered unmanaged candidates. */
|
|
42
|
+
attempted: number;
|
|
43
|
+
/** Subset of `attempted` that completed without throwing. */
|
|
44
|
+
succeeded: number;
|
|
45
|
+
/** Warnings produced by failed bootstrap attempts (one per failure). */
|
|
46
|
+
warnings: ScanWarning[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Identify unmanaged SKILL.md entries — `kind: 'skill'` with no
|
|
50
|
+
* `meta.author` (i.e., not registered in `~/.skillsmith/manifest.json`).
|
|
51
|
+
* Exported so tests + future callers can re-use the predicate.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isUnmanagedSkill(entry: InventoryEntry): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Run the bootstrap pass over an inventory snapshot.
|
|
56
|
+
*
|
|
57
|
+
* Contract:
|
|
58
|
+
* - Never throws. Per-entry failures convert to a `ScanWarning` with
|
|
59
|
+
* code `namespace.inventory.bootstrap_failed`.
|
|
60
|
+
* - Always returns; callers can append `result.warnings` onto the
|
|
61
|
+
* audit-level warnings array.
|
|
62
|
+
* - Pure aside from the `bootstrapFn` side effect; safe to invoke in
|
|
63
|
+
* dry-run / unit-test mode by supplying a no-op `bootstrapFn`.
|
|
64
|
+
*/
|
|
65
|
+
export declare function bootstrapUnmanagedSkills(inventory: ReadonlyArray<InventoryEntry>, opts?: BootstrapUnmanagedOptions): Promise<BootstrapUnmanagedResult>;
|
|
66
|
+
//# sourceMappingURL=bootstrap-unmanaged.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap-unmanaged.d.ts","sourceRoot":"","sources":["../../../src/audit/bootstrap-unmanaged.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAIpF;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAElE,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,oEAAoE;IACpE,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE,CAAA;CAC3D;AAED,MAAM,WAAW,wBAAwB;IACvC,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAA;IACjB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAA;IACjB,wEAAwE;IACxE,QAAQ,EAAE,WAAW,EAAE,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAE/D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,EACxC,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,wBAAwB,CAAC,CA+BnC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Bootstrap unmanaged skills for SMI-4587 Wave 1 Step 6a.
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/bootstrap-unmanaged
|
|
4
|
+
*
|
|
5
|
+
* Iterates over inventory entries and registers any unmanaged SKILL.md
|
|
6
|
+
* via `index_local`. Failures are converted into typed `warnings[]`
|
|
7
|
+
* entries (`namespace.inventory.bootstrap_failed`) — never thrown — so
|
|
8
|
+
* the audit run can complete even when individual bootstrap calls fail
|
|
9
|
+
* (decision #12 in plan).
|
|
10
|
+
*
|
|
11
|
+
* Wave 1 PR #4 (Step 8 / NEW-E-2) wires the real `indexLocalSkill` core
|
|
12
|
+
* helper as the default `bootstrapFn` — replacing PR #3's no-op stub. The
|
|
13
|
+
* MCP-side `parseFrontmatter` is injected so behaviour matches the
|
|
14
|
+
* existing `LocalIndexer` path bit-for-bit.
|
|
15
|
+
*
|
|
16
|
+
* "Unmanaged" = `kind: 'skill'` AND `meta.author` is undefined (i.e.,
|
|
17
|
+
* the skill is not registered in `~/.skillsmith/manifest.json`).
|
|
18
|
+
*/
|
|
19
|
+
import { indexLocalSkill } from '@skillsmith/core';
|
|
20
|
+
import { WARNING_CODES } from '../utils/local-inventory.helpers.js';
|
|
21
|
+
import { parseFrontmatter } from '../indexer/FrontmatterParser.js';
|
|
22
|
+
/**
|
|
23
|
+
* Identify unmanaged SKILL.md entries — `kind: 'skill'` with no
|
|
24
|
+
* `meta.author` (i.e., not registered in `~/.skillsmith/manifest.json`).
|
|
25
|
+
* Exported so tests + future callers can re-use the predicate.
|
|
26
|
+
*/
|
|
27
|
+
export function isUnmanagedSkill(entry) {
|
|
28
|
+
return entry.kind === 'skill' && !entry.meta?.author;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Run the bootstrap pass over an inventory snapshot.
|
|
32
|
+
*
|
|
33
|
+
* Contract:
|
|
34
|
+
* - Never throws. Per-entry failures convert to a `ScanWarning` with
|
|
35
|
+
* code `namespace.inventory.bootstrap_failed`.
|
|
36
|
+
* - Always returns; callers can append `result.warnings` onto the
|
|
37
|
+
* audit-level warnings array.
|
|
38
|
+
* - Pure aside from the `bootstrapFn` side effect; safe to invoke in
|
|
39
|
+
* dry-run / unit-test mode by supplying a no-op `bootstrapFn`.
|
|
40
|
+
*/
|
|
41
|
+
export async function bootstrapUnmanagedSkills(inventory, opts = {}) {
|
|
42
|
+
const bootstrapFn = opts.bootstrapFn ?? defaultIndexLocalSkillBootstrap;
|
|
43
|
+
const warnings = [];
|
|
44
|
+
let attempted = 0;
|
|
45
|
+
let succeeded = 0;
|
|
46
|
+
for (const entry of inventory) {
|
|
47
|
+
if (!isUnmanagedSkill(entry))
|
|
48
|
+
continue;
|
|
49
|
+
attempted++;
|
|
50
|
+
try {
|
|
51
|
+
await bootstrapFn(entry);
|
|
52
|
+
succeeded++;
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
56
|
+
warnings.push({
|
|
57
|
+
code: WARNING_CODES.BOOTSTRAP_FAILED,
|
|
58
|
+
message: `bootstrap failed for ${entry.source_path}: ${message}`,
|
|
59
|
+
context: {
|
|
60
|
+
source_path: entry.source_path,
|
|
61
|
+
identifier: entry.identifier,
|
|
62
|
+
error: message,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
opts.logger?.debug?.('bootstrap_failed', {
|
|
66
|
+
source_path: entry.source_path,
|
|
67
|
+
error: message,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return { attempted, succeeded, warnings };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Default bootstrap implementation (SMI-4587 Wave 1 PR #4 / NEW-E-2).
|
|
75
|
+
*
|
|
76
|
+
* Delegates to `indexLocalSkill` from `@skillsmith/core/skills/index-local`
|
|
77
|
+
* with the MCP-side `parseFrontmatter` injected so we keep parity with the
|
|
78
|
+
* existing `LocalIndexer` path. Synchronous filesystem reads inside the
|
|
79
|
+
* core helper are wrapped in `Promise.resolve()` so the audit pipeline can
|
|
80
|
+
* await uniformly.
|
|
81
|
+
*
|
|
82
|
+
* Errors propagate upward — `bootstrapUnmanagedSkills` converts them into
|
|
83
|
+
* typed `ScanWarning` entries with code
|
|
84
|
+
* `namespace.inventory.bootstrap_failed`.
|
|
85
|
+
*/
|
|
86
|
+
async function defaultIndexLocalSkillBootstrap(entry) {
|
|
87
|
+
await Promise.resolve(indexLocalSkill(entry.source_path, {
|
|
88
|
+
parseFrontmatter,
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=bootstrap-unmanaged.js.map
|