@skillsmith/mcp-server 0.4.13 → 0.5.0
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 +32 -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 +1 -1
- 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/compliance-tools.service.test.js +6 -4
- package/dist/src/tools/compliance-tools.service.test.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 +162 -7
- 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 +71 -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/search.d.ts +2 -2
- 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 +10 -1
- 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/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/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 +2 -2
|
@@ -14,11 +14,17 @@
|
|
|
14
14
|
* - Wires onProgress to MCP protocol notifications
|
|
15
15
|
*/
|
|
16
16
|
import { SkillInstallationService, emitInstallEvent, } from '@skillsmith/core';
|
|
17
|
+
import { addLink, getInstallPath, resolveClientPath } from '@skillsmith/core/install';
|
|
18
|
+
import { resolveAuditMode, isAuditMode } from '@skillsmith/core/config/audit-mode';
|
|
17
19
|
import { getToolContext } from '../context.js';
|
|
18
|
-
import { installInputSchema } from './install.types.js';
|
|
20
|
+
import { CLAUDE_SKILLS_DIR, installInputSchema } from './install.types.js';
|
|
19
21
|
import { loadManifest, lookupSkillFromRegistry } from './install.helpers.js';
|
|
22
|
+
import { FIELD_LIMITS } from './validate.types.js';
|
|
20
23
|
// SMI-1867: Conflict resolution logic (extracted per governance review)
|
|
21
24
|
import { checkForConflicts } from './install.conflict.js';
|
|
25
|
+
// SMI-4588 Wave 2 PR #3: namespace pre-flight + ledger replay + mode gate.
|
|
26
|
+
import { runNamespaceGate } from './install.namespace-gate.js';
|
|
27
|
+
import * as path from 'path';
|
|
22
28
|
// SMI-2741: MCP tool definition extracted to companion file
|
|
23
29
|
export { installTool } from './install.tool.js';
|
|
24
30
|
export { default } from './install.tool.js';
|
|
@@ -57,7 +63,22 @@ function buildValidationError(message) {
|
|
|
57
63
|
};
|
|
58
64
|
}
|
|
59
65
|
/**
|
|
60
|
-
*
|
|
66
|
+
* SMI-4737: structured tool-error envelope for `extractSkillName` throws.
|
|
67
|
+
* Adversarial `skillId` values that survive Zod's 512-char boundary but
|
|
68
|
+
* produce an over-cap (>128 char) extracted segment are rejected here so
|
|
69
|
+
* the throw never escapes the MCP handler. Mirrors the `buildValidationError`
|
|
70
|
+
* shape (application-level failure, not MCP protocol-level `isError`).
|
|
71
|
+
*/
|
|
72
|
+
function buildInvalidSkillIdError(skillId, message) {
|
|
73
|
+
return {
|
|
74
|
+
success: false,
|
|
75
|
+
skillId,
|
|
76
|
+
installPath: '',
|
|
77
|
+
error: `invalid_skill_id: ${message}`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Install a skill from GitHub to the local agent skills directory (~/.claude/skills/).
|
|
61
82
|
*
|
|
62
83
|
* Delegates core logic to SkillInstallationService from @skillsmith/core.
|
|
63
84
|
* Adds MCP-specific conflict resolution (three-way merge, backup).
|
|
@@ -81,14 +102,53 @@ export async function installSkill(input, _context) {
|
|
|
81
102
|
if (!parsed.success) {
|
|
82
103
|
const message = parsed.error.issues
|
|
83
104
|
.map((issue) => {
|
|
84
|
-
|
|
85
|
-
|
|
105
|
+
// Renamed from `path` to `issuePath` to avoid shadowing the
|
|
106
|
+
// module-level `path` import (no-shadow hygiene).
|
|
107
|
+
const issuePath = issue.path.length > 0 ? issue.path.join('.') : '<root>';
|
|
108
|
+
return `${issuePath}: ${issue.message}`;
|
|
86
109
|
})
|
|
87
110
|
.join('; ');
|
|
88
111
|
return buildValidationError(message);
|
|
89
112
|
}
|
|
90
113
|
const validInput = parsed.data;
|
|
114
|
+
// SMI-4588 Wave 2 PR #3: namespace pre-flight + mode gate. Runs BEFORE
|
|
115
|
+
// service construction so a `preventative`-mode collision short-circuits
|
|
116
|
+
// the install with no side effects. Pre-flight failure is non-blocking
|
|
117
|
+
// (Edit 2) — `runNamespaceGate` swallows internal throws and returns
|
|
118
|
+
// `decision: 'proceed'`.
|
|
119
|
+
// SMI-4737: extractSkillName (called via buildPreflightCandidate) throws on
|
|
120
|
+
// over-cap (>128 char) extracted segments; surface as structured envelope.
|
|
121
|
+
let candidate;
|
|
122
|
+
try {
|
|
123
|
+
candidate = buildPreflightCandidate(validInput.skillId);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
return buildInvalidSkillIdError(validInput.skillId, err instanceof Error ? err.message : String(err));
|
|
127
|
+
}
|
|
128
|
+
const tier = resolveCallerTier();
|
|
129
|
+
const auditMode = resolveAuditMode({
|
|
130
|
+
tier,
|
|
131
|
+
override: readAuditModeOverride(),
|
|
132
|
+
});
|
|
133
|
+
const gate = await runNamespaceGate({ candidate, mode: auditMode, tier });
|
|
134
|
+
if (gate.decision === 'block') {
|
|
135
|
+
// Decision #2: preventative mode blocks; agent must call
|
|
136
|
+
// `apply_namespace_rename` then re-invoke install. The skill is NOT
|
|
137
|
+
// touched on disk.
|
|
138
|
+
return {
|
|
139
|
+
success: false,
|
|
140
|
+
skillId: validInput.skillId,
|
|
141
|
+
installPath: '',
|
|
142
|
+
error: 'Namespace collision detected; install blocked in preventative audit mode.',
|
|
143
|
+
...gate.resultPatch,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
91
146
|
const context = _context ?? getToolContext();
|
|
147
|
+
// SMI-4578: resolve target install directory. Explicit `client` arg
|
|
148
|
+
// wins; otherwise fall back to SKILLSMITH_CLIENT env (or claude-code).
|
|
149
|
+
const effectiveSkillsDir = validInput.client
|
|
150
|
+
? getInstallPath(validInput.client)
|
|
151
|
+
: resolveClientPath();
|
|
92
152
|
// SMI-3483: Create core service instance with MCP context wiring
|
|
93
153
|
// SMI-3873: aiDefenceFeedback omitted -- MCP server cannot call Ruflo tools.
|
|
94
154
|
const service = new SkillInstallationService({
|
|
@@ -98,6 +158,7 @@ export async function installSkill(input, _context) {
|
|
|
98
158
|
registryLookup: new McpRegistryLookup(context),
|
|
99
159
|
coInstallRecorder: context.coInstallRepository,
|
|
100
160
|
sessionInstalledSkillIds: context.sessionInstalledSkillIds,
|
|
161
|
+
skillsDir: effectiveSkillsDir,
|
|
101
162
|
});
|
|
102
163
|
// SMI-1867: Pre-flight conflict check for reinstall with force
|
|
103
164
|
// This is MCP-specific (three-way merge UI, backup, storeOriginal)
|
|
@@ -133,17 +194,111 @@ export async function installSkill(input, _context) {
|
|
|
133
194
|
success: result.success,
|
|
134
195
|
durationMs: Date.now() - installStart,
|
|
135
196
|
});
|
|
197
|
+
// SMI-4578: fan-out to additional clients after primary install. Failures
|
|
198
|
+
// are logged but do NOT mark the overall install as failed — canonical
|
|
199
|
+
// install at `client` is already complete.
|
|
200
|
+
if (result.success && validInput.alsoLink.length > 0) {
|
|
201
|
+
const fromClient = validInput.client ?? 'claude-code';
|
|
202
|
+
const skillName = extractSkillName(validInput.skillId);
|
|
203
|
+
for (const target of validInput.alsoLink) {
|
|
204
|
+
if (target === fromClient)
|
|
205
|
+
continue;
|
|
206
|
+
try {
|
|
207
|
+
await addLink({
|
|
208
|
+
skillId: skillName,
|
|
209
|
+
fromClient,
|
|
210
|
+
toClient: target,
|
|
211
|
+
preferSymlink: validInput.symlink,
|
|
212
|
+
force: validInput.force,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
catch (linkErr) {
|
|
216
|
+
// Best-effort fan-out — log but don't fail the install
|
|
217
|
+
console.error(`[install] alsoLink to ${target} failed:`, linkErr instanceof Error ? linkErr.message : String(linkErr));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// SMI-4588 Wave 2 PR #3: surface non-blocking namespace warnings (and
|
|
222
|
+
// installComplete=true marker) on `power_user` / `governance` paths.
|
|
223
|
+
// `pendingCollision` is intentionally not merged here — it is exclusive
|
|
224
|
+
// to the blocking-mode early return above.
|
|
225
|
+
if (gate.resultPatch.warnings && gate.resultPatch.warnings.length > 0) {
|
|
226
|
+
return {
|
|
227
|
+
...result,
|
|
228
|
+
installComplete: gate.resultPatch.installComplete,
|
|
229
|
+
warnings: gate.resultPatch.warnings,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
136
232
|
return result;
|
|
137
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Build the `CandidateSkill` shape consumed by `runNamespaceGate`. The
|
|
236
|
+
* pre-flight runs before any disk write, so the path is projected.
|
|
237
|
+
*
|
|
238
|
+
* `extractSkillName` mirrors the manifest-key derivation used elsewhere in
|
|
239
|
+
* this file; the `skillId` is propagated when the input is a registry id
|
|
240
|
+
* (`<author>/<name>`) so ledger lookups key on the canonical form.
|
|
241
|
+
*/
|
|
242
|
+
function buildPreflightCandidate(skillId) {
|
|
243
|
+
const skillName = extractSkillName(skillId);
|
|
244
|
+
const isRegistryId = skillId.includes('/') && !skillId.startsWith('https://');
|
|
245
|
+
const author = isRegistryId ? skillId.split('/')[0] : null;
|
|
246
|
+
return {
|
|
247
|
+
identifier: skillName,
|
|
248
|
+
projectedSourcePath: path.join(CLAUDE_SKILLS_DIR, skillName),
|
|
249
|
+
skillId: isRegistryId ? skillId : null,
|
|
250
|
+
author,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Resolve the caller's subscription tier for the audit-mode resolver.
|
|
255
|
+
* Reads `SKILLSMITH_TIER` env var; falls through to `'community'` (the
|
|
256
|
+
* resolver's fail-safe default) when unset or invalid. The MCP subprocess
|
|
257
|
+
* has no JWT context, so env var is the only signal available without
|
|
258
|
+
* cross-cutting changes (Wave 4 will revisit if richer tier resolution
|
|
259
|
+
* becomes load-bearing).
|
|
260
|
+
*/
|
|
261
|
+
function resolveCallerTier() {
|
|
262
|
+
const raw = process.env['SKILLSMITH_TIER'];
|
|
263
|
+
if (raw === 'community' || raw === 'individual' || raw === 'team' || raw === 'enterprise') {
|
|
264
|
+
return raw;
|
|
265
|
+
}
|
|
266
|
+
return 'community';
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Read the optional `SKILLSMITH_AUDIT_MODE` override. Invalid values fall
|
|
270
|
+
* through to `null` so the resolver applies the tier default.
|
|
271
|
+
*/
|
|
272
|
+
function readAuditModeOverride() {
|
|
273
|
+
const raw = process.env['SKILLSMITH_AUDIT_MODE'];
|
|
274
|
+
return isAuditMode(raw) ? raw : null;
|
|
275
|
+
}
|
|
138
276
|
/**
|
|
139
277
|
* Best-effort skill name extraction for conflict pre-check.
|
|
140
278
|
* Does not need to be perfect -- just needs to match manifest keys.
|
|
279
|
+
*
|
|
280
|
+
* SMI-4737: throws when the extracted segment exceeds `FIELD_LIMITS.token`
|
|
281
|
+
* (128 chars). Adversarial `skillId` inputs that survive the Zod 512-char
|
|
282
|
+
* boundary but produce an over-cap segment are rejected at the derivation
|
|
283
|
+
* site so they cannot reach `sanitizeSegment`'s defensive 256-char floor
|
|
284
|
+
* (SMI-4733). Caller sites must wrap in try/catch and surface a structured
|
|
285
|
+
* tool-error envelope; the throw must not escape the MCP handler.
|
|
286
|
+
*
|
|
287
|
+
* Exported for direct unit testing (SMI-4737 tests).
|
|
141
288
|
*/
|
|
142
|
-
function extractSkillName(skillId) {
|
|
289
|
+
export function extractSkillName(skillId) {
|
|
290
|
+
let name;
|
|
143
291
|
if (skillId.includes('/')) {
|
|
144
292
|
const parts = skillId.split('/');
|
|
145
|
-
|
|
293
|
+
name = parts[parts.length - 1];
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
name = skillId;
|
|
297
|
+
}
|
|
298
|
+
if (name.length > FIELD_LIMITS.token) {
|
|
299
|
+
throw new Error(`Extracted skill name exceeds ${FIELD_LIMITS.token} chars (got ${name.length}). ` +
|
|
300
|
+
`skillId: ${skillId.slice(0, 64)}${skillId.length > 64 ? '...' : ''}`);
|
|
146
301
|
}
|
|
147
|
-
return
|
|
302
|
+
return name;
|
|
148
303
|
}
|
|
149
304
|
//# sourceMappingURL=install.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/tools/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,wBAAwB,EACxB,gBAAgB,GAGjB,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/tools/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,wBAAwB,EACxB,gBAAgB,GAGjB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AACrF,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAa,MAAM,oCAAoC,CAAA;AAE7F,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAsB,MAAM,oBAAoB,CAAA;AAC9F,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD,wEAAwE;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAEzD,2EAA2E;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAE9D,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,4DAA4D;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAE3C,uEAAuE;AACvE,OAAO,EAAE,kBAAkB,EAAyC,MAAM,oBAAoB,CAAA;AAE9F;;;GAGG;AACH,MAAM,iBAAiB;IACD;IAApB,YAAoB,OAAoB;QAApB,YAAO,GAAP,OAAO,CAAa;IAAG,CAAC;IAE5C,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,OAAO,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IACvD,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,SAAS,oBAAoB,CAAC,OAAe;IAC3C,OAAO;QACL,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,EAAE;QACf,KAAK,EAAE,0BAA0B,OAAO,EAAE;KAC3C,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,wBAAwB,CAAC,OAAe,EAAE,OAAe;IAChE,OAAO;QACL,OAAO,EAAE,KAAK;QACd,OAAO;QACP,WAAW,EAAE,EAAE;QACf,KAAK,EAAE,qBAAqB,OAAO,EAAE;KACtC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAc,EAAE,QAAsB;IACvE,sEAAsE;IACtE,6EAA6E;IAC7E,4EAA4E;IAC5E,4EAA4E;IAC5E,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aAChC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACb,4DAA4D;YAC5D,kDAAkD;YAClD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;YACzE,OAAO,GAAG,SAAS,KAAK,KAAK,CAAC,OAAO,EAAE,CAAA;QACzC,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAA;QACb,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAA;IACtC,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAA;IAE9B,uEAAuE;IACvE,yEAAyE;IACzE,uEAAuE;IACvE,qEAAqE;IACrE,yBAAyB;IACzB,4EAA4E;IAC5E,2EAA2E;IAC3E,IAAI,SAAyB,CAAA;IAC7B,IAAI,CAAC;QACH,SAAS,GAAG,uBAAuB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IACzD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,wBAAwB,CAC7B,UAAU,CAAC,OAAO,EAClB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAA;IACH,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAA;IAChC,MAAM,SAAS,GAAG,gBAAgB,CAAC;QACjC,IAAI;QACJ,QAAQ,EAAE,qBAAqB,EAAE;KAClC,CAAC,CAAA;IACF,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACzE,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC9B,yDAAyD;QACzD,oEAAoE;QACpE,mBAAmB;QACnB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,WAAW,EAAE,EAAE;YACf,KAAK,EAAE,2EAA2E;YAClF,GAAG,IAAI,CAAC,WAAW;SACpB,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,IAAI,cAAc,EAAE,CAAA;IAE5C,oEAAoE;IACpE,uEAAuE;IACvE,MAAM,kBAAkB,GAAG,UAAU,CAAC,MAAM;QAC1C,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC;QACnC,CAAC,CAAC,iBAAiB,EAAE,CAAA;IAEvB,iEAAiE;IACjE,6EAA6E;IAC7E,MAAM,OAAO,GAAG,IAAI,wBAAwB,CAAC;QAC3C,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,SAAS,EAAE,OAAO,CAAC,eAAe;QAClC,mBAAmB,EAAE,OAAO,CAAC,yBAAyB;QACtD,cAAc,EAAE,IAAI,iBAAiB,CAAC,OAAO,CAAC;QAC9C,iBAAiB,EAAE,OAAO,CAAC,mBAAmB;QAC9C,wBAAwB,EAAE,OAAO,CAAC,wBAAwB;QAC1D,SAAS,EAAE,kBAAkB;KAC9B,CAAC,CAAA;IAEF,+DAA+D;IAC/D,mEAAmE;IACnE,IAAI,UAAU,CAAC,KAAK,IAAI,UAAU,CAAC,cAAc,EAAE,CAAC;QAClD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAA;YACrC,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YAEtD,IAAI,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxC,MAAM,WAAW,GAAG,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,WAAW,CAAA;gBAEnE,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAC3C,SAAS,EACT,WAAW,EACX,QAAQ,EACR,UAAU,CAAC,cAAc,EACzB,UAAU,CAAC,OAAO,CACnB,CAAA;gBAED,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;oBACjC,OAAO,aAAa,CAAC,WAAY,CAAA;gBACnC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAC/B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE;QACvD,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,QAAQ,EAAE,UAAU,CAAC,QAAQ;QAC7B,YAAY,EAAE,UAAU,CAAC,YAAY;QACrC,cAAc,EAAE,UAAU,CAAC,cAAc;QACzC,SAAS,EAAE,UAAU,CAAC,SAAS;KAChC,CAAC,CAAA;IAEF,sEAAsE;IACtE,KAAK,gBAAgB,CAAC;QACpB,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY;KACtC,CAAC,CAAA;IAEF,0EAA0E;IAC1E,uEAAuE;IACvE,2CAA2C;IAC3C,IAAI,MAAM,CAAC,OAAO,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrD,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,IAAI,aAAa,CAAA;QACrD,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QACtD,KAAK,MAAM,MAAM,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;YACzC,IAAI,MAAM,KAAK,UAAU;gBAAE,SAAQ;YACnC,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC;oBACZ,OAAO,EAAE,SAAS;oBAClB,UAAU;oBACV,QAAQ,EAAE,MAAM;oBAChB,aAAa,EAAE,UAAU,CAAC,OAAO;oBACjC,KAAK,EAAE,UAAU,CAAC,KAAK;iBACxB,CAAC,CAAA;YACJ,CAAC;YAAC,OAAO,OAAO,EAAE,CAAC;gBACjB,uDAAuD;gBACvD,OAAO,CAAC,KAAK,CACX,yBAAyB,MAAM,UAAU,EACzC,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAC7D,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,qEAAqE;IACrE,wEAAwE;IACxE,2CAA2C;IAC3C,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtE,OAAO;YACL,GAAG,MAAM;YACT,eAAe,EAAE,IAAI,CAAC,WAAW,CAAC,eAAe;YACjD,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ;SACpC,CAAA;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,uBAAuB,CAAC,OAAe;IAC9C,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAA;IAC7E,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC1D,OAAO;QACL,UAAU,EAAE,SAAS;QACrB,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC;QAC5D,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;QACtC,MAAM;KACP,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,iBAAiB;IACxB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAC1C,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,YAAY,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;QAC1F,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,OAAO,WAAW,CAAA;AACpB,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB;IAC5B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;IAChD,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;AACtC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,IAAI,IAAY,CAAA;IAChB,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAChC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAChC,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,OAAO,CAAA;IAChB,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CACb,gCAAgC,YAAY,CAAC,KAAK,eAAe,IAAI,CAAC,MAAM,KAAK;YAC/E,YAAY,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CACxE,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Ledger-replay rewriter for the install hot path
|
|
3
|
+
* (SMI-4588 Wave 2 Step 6, PR #3).
|
|
4
|
+
* @module @skillsmith/mcp-server/tools/install.ledger-replay
|
|
5
|
+
*
|
|
6
|
+
* Pure rewriter: takes an install candidate and the namespace-overrides
|
|
7
|
+
* ledger, returns the candidate rewritten to its previously-renamed
|
|
8
|
+
* identifier when a matching ledger entry exists. Conceptually identical
|
|
9
|
+
* to git's `rerere` — the user's prior manual rename is silently
|
|
10
|
+
* re-applied so a pack version bump never resurrects the original
|
|
11
|
+
* `/ship` filename.
|
|
12
|
+
*
|
|
13
|
+
* This module is deliberately pure (no fs, no side effects) so it can
|
|
14
|
+
* compose into the install hot path without changing the on-disk write
|
|
15
|
+
* timing. The caller (install.ts) loads the ledger once via
|
|
16
|
+
* `readLedger()` and passes it in, then runs pre-flight against the
|
|
17
|
+
* REWRITTEN candidate identifier — the rewrite must happen before
|
|
18
|
+
* collision detection so a previously-resolved collision doesn't
|
|
19
|
+
* re-surface as a fresh warning on every install.
|
|
20
|
+
*
|
|
21
|
+
* Plan §3 — install integration step 3 (ledger replay).
|
|
22
|
+
*/
|
|
23
|
+
import type { OverrideRecord, OverridesLedger } from '../audit/namespace-overrides.types.js';
|
|
24
|
+
import type { CandidateSkill } from '../audit/install-preflight.js';
|
|
25
|
+
export interface LedgerReplayResult {
|
|
26
|
+
/** Candidate after applying any ledger overrides (`identifier`/`projectedSourcePath` rewritten). */
|
|
27
|
+
candidate: CandidateSkill;
|
|
28
|
+
/** Override entries that matched the candidate. Empty when no replay occurred. */
|
|
29
|
+
applied: OverrideRecord[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Rewrite the candidate skill's identifier (and projected source path)
|
|
33
|
+
* when a matching ledger override exists. Match keys:
|
|
34
|
+
*
|
|
35
|
+
* - `(skillId, kind: 'skill', originalIdentifier === candidate.identifier)`
|
|
36
|
+
*
|
|
37
|
+
* When `candidate.skillId` is provided, the lookup is keyed against the
|
|
38
|
+
* Skillsmith manifest skillId (`<author>/<name>`). When omitted, the
|
|
39
|
+
* lookup falls back to identifier-only matching across all `skillId`s —
|
|
40
|
+
* the user's local override applies regardless of registration state.
|
|
41
|
+
*
|
|
42
|
+
* Multiple matches: applies them in iteration order. In practice only
|
|
43
|
+
* one entry per `(skillId, originalIdentifier)` exists thanks to
|
|
44
|
+
* `appendOverride`'s dedupe, but the loop is defensive against ledger
|
|
45
|
+
* mutation outside the writer (e.g., a user hand-edits the JSON).
|
|
46
|
+
*
|
|
47
|
+
* Returns the candidate unchanged when no entry matches OR the ledger is
|
|
48
|
+
* empty. Reference equality on `candidate` is preserved for the no-op
|
|
49
|
+
* branch so callers can detect "no replay happened" without recomputing.
|
|
50
|
+
*/
|
|
51
|
+
export declare function applyLedgerReplay(candidate: CandidateSkill, ledger: OverridesLedger): LedgerReplayResult;
|
|
52
|
+
//# sourceMappingURL=install.ledger-replay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.ledger-replay.d.ts","sourceRoot":"","sources":["../../../src/tools/install.ledger-replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAA;AAC5F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAEnE,MAAM,WAAW,kBAAkB;IACjC,oGAAoG;IACpG,SAAS,EAAE,cAAc,CAAA;IACzB,kFAAkF;IAClF,OAAO,EAAE,cAAc,EAAE,CAAA;CAC1B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,cAAc,EACzB,MAAM,EAAE,eAAe,GACtB,kBAAkB,CA+CpB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Ledger-replay rewriter for the install hot path
|
|
3
|
+
* (SMI-4588 Wave 2 Step 6, PR #3).
|
|
4
|
+
* @module @skillsmith/mcp-server/tools/install.ledger-replay
|
|
5
|
+
*
|
|
6
|
+
* Pure rewriter: takes an install candidate and the namespace-overrides
|
|
7
|
+
* ledger, returns the candidate rewritten to its previously-renamed
|
|
8
|
+
* identifier when a matching ledger entry exists. Conceptually identical
|
|
9
|
+
* to git's `rerere` — the user's prior manual rename is silently
|
|
10
|
+
* re-applied so a pack version bump never resurrects the original
|
|
11
|
+
* `/ship` filename.
|
|
12
|
+
*
|
|
13
|
+
* This module is deliberately pure (no fs, no side effects) so it can
|
|
14
|
+
* compose into the install hot path without changing the on-disk write
|
|
15
|
+
* timing. The caller (install.ts) loads the ledger once via
|
|
16
|
+
* `readLedger()` and passes it in, then runs pre-flight against the
|
|
17
|
+
* REWRITTEN candidate identifier — the rewrite must happen before
|
|
18
|
+
* collision detection so a previously-resolved collision doesn't
|
|
19
|
+
* re-surface as a fresh warning on every install.
|
|
20
|
+
*
|
|
21
|
+
* Plan §3 — install integration step 3 (ledger replay).
|
|
22
|
+
*/
|
|
23
|
+
import { findOverride } from '../audit/namespace-overrides.js';
|
|
24
|
+
/**
|
|
25
|
+
* Rewrite the candidate skill's identifier (and projected source path)
|
|
26
|
+
* when a matching ledger override exists. Match keys:
|
|
27
|
+
*
|
|
28
|
+
* - `(skillId, kind: 'skill', originalIdentifier === candidate.identifier)`
|
|
29
|
+
*
|
|
30
|
+
* When `candidate.skillId` is provided, the lookup is keyed against the
|
|
31
|
+
* Skillsmith manifest skillId (`<author>/<name>`). When omitted, the
|
|
32
|
+
* lookup falls back to identifier-only matching across all `skillId`s —
|
|
33
|
+
* the user's local override applies regardless of registration state.
|
|
34
|
+
*
|
|
35
|
+
* Multiple matches: applies them in iteration order. In practice only
|
|
36
|
+
* one entry per `(skillId, originalIdentifier)` exists thanks to
|
|
37
|
+
* `appendOverride`'s dedupe, but the loop is defensive against ledger
|
|
38
|
+
* mutation outside the writer (e.g., a user hand-edits the JSON).
|
|
39
|
+
*
|
|
40
|
+
* Returns the candidate unchanged when no entry matches OR the ledger is
|
|
41
|
+
* empty. Reference equality on `candidate` is preserved for the no-op
|
|
42
|
+
* branch so callers can detect "no replay happened" without recomputing.
|
|
43
|
+
*/
|
|
44
|
+
export function applyLedgerReplay(candidate, ledger) {
|
|
45
|
+
if (ledger.overrides.length === 0) {
|
|
46
|
+
return { candidate, applied: [] };
|
|
47
|
+
}
|
|
48
|
+
const applied = [];
|
|
49
|
+
let workingIdentifier = candidate.identifier;
|
|
50
|
+
let workingPath = candidate.projectedSourcePath;
|
|
51
|
+
// Iterate until no more matches. Loop bound: ledger length (defensive).
|
|
52
|
+
for (let pass = 0; pass < ledger.overrides.length; pass++) {
|
|
53
|
+
const match = findOverride(ledger, {
|
|
54
|
+
skillId: candidate.skillId ?? undefined,
|
|
55
|
+
kind: 'skill',
|
|
56
|
+
originalIdentifier: workingIdentifier,
|
|
57
|
+
});
|
|
58
|
+
if (!match)
|
|
59
|
+
break;
|
|
60
|
+
// Avoid cycles: the same entry must not apply twice.
|
|
61
|
+
if (applied.some((a) => a.id === match.id))
|
|
62
|
+
break;
|
|
63
|
+
applied.push(match);
|
|
64
|
+
workingIdentifier = match.renamedTo;
|
|
65
|
+
// Project the post-replay source path under the same parent as the
|
|
66
|
+
// original projection. The ledger stores the absolute renamed path,
|
|
67
|
+
// but at install time the candidate may have a different parent
|
|
68
|
+
// (e.g. a `~/.claude/skills/<token>` projection). Replace only the
|
|
69
|
+
// basename so cross-host path migrations don't break replay.
|
|
70
|
+
const parentSep = workingPath.lastIndexOf('/');
|
|
71
|
+
workingPath =
|
|
72
|
+
parentSep === -1
|
|
73
|
+
? match.renamedTo
|
|
74
|
+
: `${workingPath.slice(0, parentSep + 1)}${match.renamedTo}`;
|
|
75
|
+
}
|
|
76
|
+
if (applied.length === 0) {
|
|
77
|
+
return { candidate, applied: [] };
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
candidate: {
|
|
81
|
+
...candidate,
|
|
82
|
+
identifier: workingIdentifier,
|
|
83
|
+
projectedSourcePath: workingPath,
|
|
84
|
+
},
|
|
85
|
+
applied,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=install.ledger-replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.ledger-replay.js","sourceRoot":"","sources":["../../../src/tools/install.ledger-replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AAW9D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAyB,EACzB,MAAuB;IAEvB,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;IACnC,CAAC;IAED,MAAM,OAAO,GAAqB,EAAE,CAAA;IACpC,IAAI,iBAAiB,GAAG,SAAS,CAAC,UAAU,CAAA;IAC5C,IAAI,WAAW,GAAG,SAAS,CAAC,mBAAmB,CAAA;IAE/C,wEAAwE;IACxE,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE;YACjC,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,SAAS;YACvC,IAAI,EAAE,OAAO;YACb,kBAAkB,EAAE,iBAAiB;SACtC,CAAC,CAAA;QACF,IAAI,CAAC,KAAK;YAAE,MAAK;QAEjB,qDAAqD;QACrD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC;YAAE,MAAK;QAEjD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACnB,iBAAiB,GAAG,KAAK,CAAC,SAAS,CAAA;QACnC,mEAAmE;QACnE,oEAAoE;QACpE,gEAAgE;QAChE,mEAAmE;QACnE,6DAA6D;QAC7D,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;QAC9C,WAAW;YACT,SAAS,KAAK,CAAC,CAAC;gBACd,CAAC,CAAC,KAAK,CAAC,SAAS;gBACjB,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,EAAE,CAAA;IAClE,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;IACnC,CAAC;IAED,OAAO;QACL,SAAS,EAAE;YACT,GAAG,SAAS;YACZ,UAAU,EAAE,iBAAiB;YAC7B,mBAAmB,EAAE,WAAW;SACjC;QACD,OAAO;KACR,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Namespace pre-flight + mode gate for the install hot path
|
|
3
|
+
* (SMI-4588 Wave 2 Step 6, PR #3).
|
|
4
|
+
* @module @skillsmith/mcp-server/tools/install.namespace-gate
|
|
5
|
+
*
|
|
6
|
+
* Encapsulates the three steps that bracket `service.install()` in the
|
|
7
|
+
* MCP install tool:
|
|
8
|
+
*
|
|
9
|
+
* 1. Ledger replay — rewrite the candidate skill's identifier when a
|
|
10
|
+
* previously-recorded user rename matches.
|
|
11
|
+
* 2. Pre-flight collision detection + suggestion-chain generation.
|
|
12
|
+
* 3. Mode gate (`preventative` blocks; `power_user`/`governance` warn).
|
|
13
|
+
*
|
|
14
|
+
* Extracted from `install.ts` per Step 6's "unconditional extraction"
|
|
15
|
+
* directive — keeps the hot-path file under the 500-LOC limit and keeps
|
|
16
|
+
* the new logic independently testable.
|
|
17
|
+
*
|
|
18
|
+
* Edits applied (plan-review 2026-05-02):
|
|
19
|
+
* - Edit 2: pre-flight scanner failure is ALWAYS non-blocking. The
|
|
20
|
+
* `runInstallPreflight` module already degrades on detector throws;
|
|
21
|
+
* this gate additionally swallows ledger-read errors (including
|
|
22
|
+
* `namespace.ledger.version_unsupported`) so a downgraded ledger
|
|
23
|
+
* never bricks installs.
|
|
24
|
+
* - Edit 6: typed `version_unsupported` error caught here, not bubbled.
|
|
25
|
+
* - Edit 7: pre-flight returns `auditId` explicitly; this gate threads
|
|
26
|
+
* it into the `pendingCollision` envelope without re-deriving.
|
|
27
|
+
*/
|
|
28
|
+
import { type CandidateSkill, type RunInstallPreflightResult } from '../audit/install-preflight.js';
|
|
29
|
+
import type { AuditMode, Tier } from '@skillsmith/core/config/audit-mode';
|
|
30
|
+
import type { InstallResult } from './install.types.js';
|
|
31
|
+
export interface NamespaceGateInput {
|
|
32
|
+
/** Synthesized candidate for the skill being installed. */
|
|
33
|
+
candidate: CandidateSkill;
|
|
34
|
+
/** Resolved audit mode (caller resolves via `resolveAuditMode`). */
|
|
35
|
+
mode: AuditMode;
|
|
36
|
+
/** Subscription tier (passed through to detector for telemetry consistency). */
|
|
37
|
+
tier: Tier;
|
|
38
|
+
}
|
|
39
|
+
export interface NamespaceGateOutcome {
|
|
40
|
+
/**
|
|
41
|
+
* `'block'` only fires when `mode === 'preventative'` AND a candidate-
|
|
42
|
+
* involved collision was detected. Caller short-circuits the install
|
|
43
|
+
* with the `pendingCollision` envelope.
|
|
44
|
+
*/
|
|
45
|
+
decision: 'block' | 'proceed';
|
|
46
|
+
/**
|
|
47
|
+
* The (possibly ledger-replayed) candidate. Caller MAY use this for
|
|
48
|
+
* post-install side effects, but Wave 2 PR #3 does not yet wire
|
|
49
|
+
* post-install rename — the ledger-replay rewrites the candidate in
|
|
50
|
+
* place at the pre-flight boundary so the surfaced suggestions match.
|
|
51
|
+
*/
|
|
52
|
+
candidate: CandidateSkill;
|
|
53
|
+
/** Always present — populated by `runInstallPreflight`. */
|
|
54
|
+
preflight: RunInstallPreflightResult;
|
|
55
|
+
/**
|
|
56
|
+
* `InstallResult` payload to merge into the caller's return value.
|
|
57
|
+
* Populated for both `block` and `proceed` paths so the install hot
|
|
58
|
+
* path has a single shape to splat.
|
|
59
|
+
*/
|
|
60
|
+
resultPatch: Pick<InstallResult, 'installComplete' | 'pendingCollision' | 'warnings'>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Run the namespace pre-flight + apply the mode gate. Returns a decision
|
|
64
|
+
* the install hot path branches on. Never throws — all failure paths
|
|
65
|
+
* degrade to `decision: 'proceed'` with a logged warning (Edit 2).
|
|
66
|
+
*/
|
|
67
|
+
export declare function runNamespaceGate(input: NamespaceGateInput): Promise<NamespaceGateOutcome>;
|
|
68
|
+
//# sourceMappingURL=install.namespace-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.namespace-gate.d.ts","sourceRoot":"","sources":["../../../src/tools/install.namespace-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,yBAAyB,EAC/B,MAAM,+BAA+B,CAAA;AAKtC,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAA;AAGzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,SAAS,EAAE,cAAc,CAAA;IACzB,oEAAoE;IACpE,IAAI,EAAE,SAAS,CAAA;IACf,gFAAgF;IAChF,IAAI,EAAE,IAAI,CAAA;CACX;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B;;;;;OAKG;IACH,SAAS,EAAE,cAAc,CAAA;IACzB,2DAA2D;IAC3D,SAAS,EAAE,yBAAyB,CAAA;IACpC;;;;OAIG;IACH,WAAW,EAAE,IAAI,CAAC,aAAa,EAAE,iBAAiB,GAAG,kBAAkB,GAAG,UAAU,CAAC,CAAA;CACtF;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6E/F"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Namespace pre-flight + mode gate for the install hot path
|
|
3
|
+
* (SMI-4588 Wave 2 Step 6, PR #3).
|
|
4
|
+
* @module @skillsmith/mcp-server/tools/install.namespace-gate
|
|
5
|
+
*
|
|
6
|
+
* Encapsulates the three steps that bracket `service.install()` in the
|
|
7
|
+
* MCP install tool:
|
|
8
|
+
*
|
|
9
|
+
* 1. Ledger replay — rewrite the candidate skill's identifier when a
|
|
10
|
+
* previously-recorded user rename matches.
|
|
11
|
+
* 2. Pre-flight collision detection + suggestion-chain generation.
|
|
12
|
+
* 3. Mode gate (`preventative` blocks; `power_user`/`governance` warn).
|
|
13
|
+
*
|
|
14
|
+
* Extracted from `install.ts` per Step 6's "unconditional extraction"
|
|
15
|
+
* directive — keeps the hot-path file under the 500-LOC limit and keeps
|
|
16
|
+
* the new logic independently testable.
|
|
17
|
+
*
|
|
18
|
+
* Edits applied (plan-review 2026-05-02):
|
|
19
|
+
* - Edit 2: pre-flight scanner failure is ALWAYS non-blocking. The
|
|
20
|
+
* `runInstallPreflight` module already degrades on detector throws;
|
|
21
|
+
* this gate additionally swallows ledger-read errors (including
|
|
22
|
+
* `namespace.ledger.version_unsupported`) so a downgraded ledger
|
|
23
|
+
* never bricks installs.
|
|
24
|
+
* - Edit 6: typed `version_unsupported` error caught here, not bubbled.
|
|
25
|
+
* - Edit 7: pre-flight returns `auditId` explicitly; this gate threads
|
|
26
|
+
* it into the `pendingCollision` envelope without re-deriving.
|
|
27
|
+
*/
|
|
28
|
+
import { runInstallPreflight, } from '../audit/install-preflight.js';
|
|
29
|
+
import { newAuditId } from '../audit/audit-history.js';
|
|
30
|
+
import { readLedger } from '../audit/namespace-overrides.js';
|
|
31
|
+
import { applyLedgerReplay } from './install.ledger-replay.js';
|
|
32
|
+
import { scanLocalInventory } from '../utils/local-inventory.js';
|
|
33
|
+
/**
|
|
34
|
+
* Run the namespace pre-flight + apply the mode gate. Returns a decision
|
|
35
|
+
* the install hot path branches on. Never throws — all failure paths
|
|
36
|
+
* degrade to `decision: 'proceed'` with a logged warning (Edit 2).
|
|
37
|
+
*/
|
|
38
|
+
export async function runNamespaceGate(input) {
|
|
39
|
+
const { mode, tier } = input;
|
|
40
|
+
// Step 1 — ledger replay. Read the ledger; on failure (including
|
|
41
|
+
// `version_unsupported`), degrade to "no replay, no preflight" because
|
|
42
|
+
// we cannot trust the candidate's effective identifier without it.
|
|
43
|
+
let candidate = input.candidate;
|
|
44
|
+
try {
|
|
45
|
+
const ledger = await readLedger();
|
|
46
|
+
const replay = applyLedgerReplay(input.candidate, ledger);
|
|
47
|
+
candidate = replay.candidate;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
// Edit 6: typed version_unsupported (or any other ledger error)
|
|
51
|
+
// surfaces here. Pre-flight is non-blocking; degrade.
|
|
52
|
+
console.warn(`[install.namespace-gate] ledger read failed (${err.message}); skipping pre-flight`);
|
|
53
|
+
return degradedProceed(candidate);
|
|
54
|
+
}
|
|
55
|
+
// Step 2 — scan local inventory + run pre-flight. The scanner runs
|
|
56
|
+
// synchronously per call (Wave 1 plumbing). Errors here also degrade.
|
|
57
|
+
let existingInventory;
|
|
58
|
+
try {
|
|
59
|
+
const scan = await scanLocalInventory();
|
|
60
|
+
existingInventory = scan.entries;
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
console.warn(`[install.namespace-gate] scanLocalInventory failed (${err.message}); skipping pre-flight`);
|
|
64
|
+
return degradedProceed(candidate);
|
|
65
|
+
}
|
|
66
|
+
let preflight;
|
|
67
|
+
try {
|
|
68
|
+
preflight = await runInstallPreflight({
|
|
69
|
+
existingInventory,
|
|
70
|
+
candidate,
|
|
71
|
+
mode,
|
|
72
|
+
tier,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
// `runInstallPreflight` itself already catches detector throws and
|
|
77
|
+
// degrades, but a defensive outer catch keeps the install hot path
|
|
78
|
+
// bulletproof against any future regression.
|
|
79
|
+
console.warn(`[install.namespace-gate] runInstallPreflight threw (${err.message}); proceeding non-blocking`);
|
|
80
|
+
return degradedProceed(candidate);
|
|
81
|
+
}
|
|
82
|
+
// Step 3 — mode gate.
|
|
83
|
+
const hasCollision = preflight.pendingCollision !== null;
|
|
84
|
+
if (mode === 'preventative' && hasCollision) {
|
|
85
|
+
return {
|
|
86
|
+
decision: 'block',
|
|
87
|
+
candidate,
|
|
88
|
+
preflight,
|
|
89
|
+
resultPatch: {
|
|
90
|
+
installComplete: false,
|
|
91
|
+
pendingCollision: preflight.pendingCollision ?? undefined,
|
|
92
|
+
warnings: preflight.warnings.length > 0 ? preflight.warnings : undefined,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// power_user / governance / preventative-without-collision all proceed.
|
|
97
|
+
return {
|
|
98
|
+
decision: 'proceed',
|
|
99
|
+
candidate,
|
|
100
|
+
preflight,
|
|
101
|
+
resultPatch: {
|
|
102
|
+
installComplete: true,
|
|
103
|
+
warnings: preflight.warnings.length > 0 ? preflight.warnings : undefined,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Degraded-proceed shape used when ledger read, inventory scan, or
|
|
109
|
+
* pre-flight throws. Caller continues the install with no warnings.
|
|
110
|
+
*
|
|
111
|
+
* `auditId` is allocated via `newAuditId()` even on the degraded path so
|
|
112
|
+
* the `AuditId` brand invariant holds for any defensive consumer that
|
|
113
|
+
* reads `preflight.auditId` without checking `decision` first.
|
|
114
|
+
*/
|
|
115
|
+
function degradedProceed(candidate) {
|
|
116
|
+
return {
|
|
117
|
+
decision: 'proceed',
|
|
118
|
+
candidate,
|
|
119
|
+
preflight: {
|
|
120
|
+
warnings: [],
|
|
121
|
+
pendingCollision: null,
|
|
122
|
+
auditId: newAuditId(),
|
|
123
|
+
},
|
|
124
|
+
resultPatch: {
|
|
125
|
+
installComplete: true,
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=install.namespace-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.namespace-gate.js","sourceRoot":"","sources":["../../../src/tools/install.namespace-gate.ts"],"names":[],"mappings":"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"}
|