@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
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Atomic reader/writer for the namespace-overrides ledger
|
|
3
|
+
* (SMI-4588 Wave 2 Step 1, PR #1).
|
|
4
|
+
* @module @skillsmith/mcp-server/audit/namespace-overrides
|
|
5
|
+
*
|
|
6
|
+
* Persists `~/.skillsmith/namespace-overrides.json` — the load-bearing
|
|
7
|
+
* artifact that makes consumer-side namespace renames durable across pack
|
|
8
|
+
* version bumps. Conceptually equivalent to git's `rerere` but for
|
|
9
|
+
* namespace identifiers.
|
|
10
|
+
*
|
|
11
|
+
* Atomicity: every write goes through `<path>.tmp` + `fs.rename`. On read,
|
|
12
|
+
* a missing file degrades gracefully to an empty ledger; malformed JSON
|
|
13
|
+
* surfaces as a typed `namespace.ledger.malformed` discriminator (the
|
|
14
|
+
* caller decides whether to log + reset, never silently). A
|
|
15
|
+
* higher-than-supported `version` returns
|
|
16
|
+
* `namespace.ledger.version_unsupported` rather than a silent empty
|
|
17
|
+
* ledger — see plan §2 Edit 6.
|
|
18
|
+
*
|
|
19
|
+
* Concurrent-write boundary: last-write-wins on a single Node event loop
|
|
20
|
+
* via `<path>.tmp` + `fs.rename`. Multi-process scenarios (two MCP
|
|
21
|
+
* instances on the same machine) can lose one write under a tight race;
|
|
22
|
+
* documented as a known limitation in the plan. If multi-process safety
|
|
23
|
+
* becomes load-bearing, a future revision adds advisory locking via
|
|
24
|
+
* `proper-lockfile`.
|
|
25
|
+
*/
|
|
26
|
+
import * as crypto from 'node:crypto';
|
|
27
|
+
import * as fs from 'node:fs/promises';
|
|
28
|
+
import * as os from 'node:os';
|
|
29
|
+
import * as path from 'node:path';
|
|
30
|
+
import { ulid } from 'ulid';
|
|
31
|
+
import { CURRENT_VERSION, } from './namespace-overrides.types.js';
|
|
32
|
+
/**
|
|
33
|
+
* Default ledger path resolver. Re-evaluates `os.homedir()` on every call so
|
|
34
|
+
* test harnesses that toggle `process.env.HOME` (mirroring `getBackupsDir`'s
|
|
35
|
+
* pattern in `tools/install.conflict-helpers.ts`) see the updated location.
|
|
36
|
+
* A captured-at-module-load constant would freeze the path to the spawning
|
|
37
|
+
* process's home directory and silently route all writes there — observed
|
|
38
|
+
* regression during PR #2 test authoring (SMI-4588 Wave 2).
|
|
39
|
+
*/
|
|
40
|
+
function defaultLedgerPath() {
|
|
41
|
+
return path.join(os.homedir(), '.skillsmith', 'namespace-overrides.json');
|
|
42
|
+
}
|
|
43
|
+
const ULID_PREFIX = 'ovr_';
|
|
44
|
+
/**
|
|
45
|
+
* Empty ledger sentinel — used when the file is missing or malformed.
|
|
46
|
+
* Returned by value so callers never share state with a private const.
|
|
47
|
+
*/
|
|
48
|
+
function emptyLedger() {
|
|
49
|
+
return { version: CURRENT_VERSION, overrides: [] };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Read the ledger from disk and return a tagged union. Missing file →
|
|
53
|
+
* `{ kind: 'ok', ledger: <empty> }`. Malformed JSON →
|
|
54
|
+
* `{ kind: 'namespace.ledger.malformed', reason }`. `version > CURRENT_VERSION`
|
|
55
|
+
* → `{ kind: 'namespace.ledger.version_unsupported', found, expected }`.
|
|
56
|
+
*
|
|
57
|
+
* Callers that want the simpler "read or empty" semantics should use
|
|
58
|
+
* `readLedger()` (below) which collapses the discriminator.
|
|
59
|
+
*/
|
|
60
|
+
export async function readLedgerResult(opts = {}) {
|
|
61
|
+
const ledgerPath = opts.ledgerPath ?? defaultLedgerPath();
|
|
62
|
+
let raw;
|
|
63
|
+
try {
|
|
64
|
+
raw = await fs.readFile(ledgerPath, 'utf-8');
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
// ENOENT — missing file degrades to an empty ledger. Anything else
|
|
68
|
+
// (permission denied, EISDIR, etc.) bubbles as malformed so the
|
|
69
|
+
// caller can decide whether to alert.
|
|
70
|
+
if (err.code === 'ENOENT') {
|
|
71
|
+
return { kind: 'ok', ledger: emptyLedger() };
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
kind: 'namespace.ledger.malformed',
|
|
75
|
+
reason: `read failed: ${err.message}`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
let parsed;
|
|
79
|
+
try {
|
|
80
|
+
parsed = JSON.parse(raw);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return {
|
|
84
|
+
kind: 'namespace.ledger.malformed',
|
|
85
|
+
reason: `parse failed: ${err.message}`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
89
|
+
return { kind: 'namespace.ledger.malformed', reason: 'top-level is not an object' };
|
|
90
|
+
}
|
|
91
|
+
const candidate = parsed;
|
|
92
|
+
const versionValue = candidate.version;
|
|
93
|
+
if (typeof versionValue !== 'number' || !Number.isInteger(versionValue) || versionValue < 1) {
|
|
94
|
+
return {
|
|
95
|
+
kind: 'namespace.ledger.malformed',
|
|
96
|
+
reason: `invalid version: ${String(versionValue)}`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (versionValue > CURRENT_VERSION) {
|
|
100
|
+
return {
|
|
101
|
+
kind: 'namespace.ledger.version_unsupported',
|
|
102
|
+
found: versionValue,
|
|
103
|
+
expected: CURRENT_VERSION,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (!Array.isArray(candidate.overrides)) {
|
|
107
|
+
return { kind: 'namespace.ledger.malformed', reason: 'overrides is not an array' };
|
|
108
|
+
}
|
|
109
|
+
// Shape verified; cast back to the canonical type. Per-record validation
|
|
110
|
+
// is intentionally minimal — additive future fields are preserved by the
|
|
111
|
+
// writer's read-modify-write cycle.
|
|
112
|
+
return {
|
|
113
|
+
kind: 'ok',
|
|
114
|
+
ledger: { version: CURRENT_VERSION, overrides: candidate.overrides },
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Convenience wrapper: returns the ledger directly, collapsing the
|
|
119
|
+
* `malformed` branch to an empty ledger plus a `console.warn`. Higher-
|
|
120
|
+
* version files still bubble a thrown error — silently empty-ing a
|
|
121
|
+
* higher-version ledger would corrupt forward-compat (plan §2 Edit 6).
|
|
122
|
+
*
|
|
123
|
+
* For callers that need the typed discriminator, use `readLedgerResult`.
|
|
124
|
+
*/
|
|
125
|
+
export async function readLedger(opts = {}) {
|
|
126
|
+
const result = await readLedgerResult(opts);
|
|
127
|
+
switch (result.kind) {
|
|
128
|
+
case 'ok':
|
|
129
|
+
return result.ledger;
|
|
130
|
+
case 'namespace.ledger.malformed':
|
|
131
|
+
// Malformed → degrade to empty + warn. Install must not break.
|
|
132
|
+
console.warn(`[namespace-overrides] ledger malformed (${result.reason}); using empty ledger`);
|
|
133
|
+
return emptyLedger();
|
|
134
|
+
case 'namespace.ledger.version_unsupported': {
|
|
135
|
+
// Higher-version file: bubble as a typed error — silently empty-ing
|
|
136
|
+
// would shadow the user's persisted renames on a downgrade.
|
|
137
|
+
const err = new Error(`namespace-overrides ledger version ${String(result.found)} is newer than supported version ${String(result.expected)}`);
|
|
138
|
+
err.kind = result.kind;
|
|
139
|
+
err.found = result.found;
|
|
140
|
+
err.expected = result.expected;
|
|
141
|
+
throw err;
|
|
142
|
+
}
|
|
143
|
+
default: {
|
|
144
|
+
// Exhaustiveness — TS verifies via `never`.
|
|
145
|
+
const _exhaustive = result;
|
|
146
|
+
throw new Error(`unreachable: ${String(_exhaustive)}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Write the ledger atomically: `<path>.tmp` + `fs.rename`. Creates the
|
|
152
|
+
* parent directory on first run with `recursive: true` (mirrors
|
|
153
|
+
* audit-history.ts E-MISS-2 fix).
|
|
154
|
+
*/
|
|
155
|
+
export async function writeLedger(ledger, opts = {}) {
|
|
156
|
+
const ledgerPath = opts.ledgerPath ?? defaultLedgerPath();
|
|
157
|
+
// Per-call unique tmp path: two concurrent writers must not clobber
|
|
158
|
+
// each other's staging file (a fixed `<path>.tmp` would race on the
|
|
159
|
+
// writeFile + rename interleaving and surface as ENOENT on rename).
|
|
160
|
+
// The unique suffix preserves last-write-wins on the rename target
|
|
161
|
+
// while making the staging step independent.
|
|
162
|
+
const tmpSuffix = crypto.randomBytes(6).toString('hex');
|
|
163
|
+
const tmpPath = `${ledgerPath}.${tmpSuffix}.tmp`;
|
|
164
|
+
await fs.mkdir(path.dirname(ledgerPath), { recursive: true });
|
|
165
|
+
// Always serialize at CURRENT_VERSION; readers gate on it.
|
|
166
|
+
const normalized = { version: CURRENT_VERSION, overrides: ledger.overrides };
|
|
167
|
+
const json = JSON.stringify(normalized, null, 2);
|
|
168
|
+
try {
|
|
169
|
+
await fs.writeFile(tmpPath, json, 'utf-8');
|
|
170
|
+
await fs.rename(tmpPath, ledgerPath);
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
// Best-effort cleanup of stranded tmp file. ENOENT here is fine —
|
|
174
|
+
// the rename may have already moved the tmp out from under us.
|
|
175
|
+
try {
|
|
176
|
+
await fs.rm(tmpPath, { force: true });
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// swallow
|
|
180
|
+
}
|
|
181
|
+
throw err;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Pure helper: append a new override to a ledger and return a new copy.
|
|
186
|
+
* Original ledger is not mutated. The caller is responsible for
|
|
187
|
+
* persisting the result via `writeLedger` (separation of concerns —
|
|
188
|
+
* tests can build ledgers without touching disk).
|
|
189
|
+
*
|
|
190
|
+
* Idempotency: if an override with the same
|
|
191
|
+
* `(skillId, kind, originalIdentifier, renamedTo)` quadruple already
|
|
192
|
+
* exists, the input is returned unchanged. The caller can detect the
|
|
193
|
+
* no-op by reference equality (`appended === ledger`).
|
|
194
|
+
*/
|
|
195
|
+
export function appendOverride(ledger, override) {
|
|
196
|
+
const duplicate = ledger.overrides.find((existing) => existing.skillId === override.skillId &&
|
|
197
|
+
existing.kind === override.kind &&
|
|
198
|
+
existing.originalIdentifier === override.originalIdentifier &&
|
|
199
|
+
existing.renamedTo === override.renamedTo);
|
|
200
|
+
if (duplicate) {
|
|
201
|
+
return ledger;
|
|
202
|
+
}
|
|
203
|
+
const fullRecord = {
|
|
204
|
+
...override,
|
|
205
|
+
id: `${ULID_PREFIX}${ulid()}`,
|
|
206
|
+
appliedAt: new Date().toISOString(),
|
|
207
|
+
};
|
|
208
|
+
return { version: ledger.version, overrides: [...ledger.overrides, fullRecord] };
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Pure lookup: find an override by `(skillId, kind, originalIdentifier)`.
|
|
212
|
+
* `skillId` may be omitted for local/unregistered artifacts; in that case
|
|
213
|
+
* only `kind` + `originalIdentifier` are matched. Returns the first match
|
|
214
|
+
* or `null`.
|
|
215
|
+
*/
|
|
216
|
+
export function findOverride(ledger, query) {
|
|
217
|
+
const match = ledger.overrides.find((entry) => {
|
|
218
|
+
if (entry.originalIdentifier !== query.originalIdentifier)
|
|
219
|
+
return false;
|
|
220
|
+
if (query.kind !== undefined && entry.kind !== query.kind)
|
|
221
|
+
return false;
|
|
222
|
+
if (query.skillId !== undefined && entry.skillId !== query.skillId)
|
|
223
|
+
return false;
|
|
224
|
+
return true;
|
|
225
|
+
});
|
|
226
|
+
return match ?? null;
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=namespace-overrides.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace-overrides.js","sourceRoot":"","sources":["../../../src/audit/namespace-overrides.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type vocabulary for the namespace-overrides ledger
|
|
3
|
+
* (SMI-4588 Wave 2 Step 1, PR #1).
|
|
4
|
+
* @module @skillsmith/mcp-server/audit/namespace-overrides.types
|
|
5
|
+
*
|
|
6
|
+
* Schema for `~/.skillsmith/namespace-overrides.json`. Modeled on the
|
|
7
|
+
* dependency-intelligence persistence pattern (SMI-3137). The schema is
|
|
8
|
+
* versioned; `CURRENT_VERSION` is bumped only when the on-disk shape
|
|
9
|
+
* changes incompatibly. Reader/writer live in `./namespace-overrides.ts`.
|
|
10
|
+
*
|
|
11
|
+
* Plan: docs/internal/implementation/smi-4588-rename-engine-ledger-install.md §2.
|
|
12
|
+
*/
|
|
13
|
+
import type { InventoryKind } from '../utils/local-inventory.types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Current ledger schema version. Bumped only when the on-disk shape
|
|
16
|
+
* changes incompatibly. Read-path behavior:
|
|
17
|
+
*
|
|
18
|
+
* - `version === CURRENT_VERSION` → return as-is.
|
|
19
|
+
* - `version < CURRENT_VERSION` → caller may run a `migrateLedger` shim
|
|
20
|
+
* (currently no historical versions exist, so any value below 1 is
|
|
21
|
+
* unreachable in practice).
|
|
22
|
+
* - `version > CURRENT_VERSION` → reader returns a typed
|
|
23
|
+
* `namespace.ledger.version_unsupported` error rather than silently
|
|
24
|
+
* degrading to an empty ledger (plan §2 Edit 6).
|
|
25
|
+
*/
|
|
26
|
+
export declare const CURRENT_VERSION: 1;
|
|
27
|
+
export type LedgerVersion = typeof CURRENT_VERSION;
|
|
28
|
+
/**
|
|
29
|
+
* One applied rename. Persisted in `~/.skillsmith/namespace-overrides.json`
|
|
30
|
+
* under `overrides[]`. ULID `id` lets later operations (revert, replay,
|
|
31
|
+
* forensics) reference the entry without depending on `(skillId, kind,
|
|
32
|
+
* originalIdentifier)` triple equality.
|
|
33
|
+
*/
|
|
34
|
+
export interface OverrideRecord {
|
|
35
|
+
/** ULID prefixed with `ovr_` for log-grep readability. */
|
|
36
|
+
id: string;
|
|
37
|
+
/**
|
|
38
|
+
* Skillsmith manifest skill id (`<author>/<name>`) when the renamed
|
|
39
|
+
* artifact is a registered skill, else `null` for local/unregistered
|
|
40
|
+
* commands and agents.
|
|
41
|
+
*/
|
|
42
|
+
skillId: string | null;
|
|
43
|
+
/**
|
|
44
|
+
* Which inventory kind this override applies to. Mirrors
|
|
45
|
+
* `InventoryKind` from local-inventory so a single ledger covers skills,
|
|
46
|
+
* commands, agents, and CLAUDE.md rules (the last for future use; Wave 2
|
|
47
|
+
* does not write claude_md_rule entries).
|
|
48
|
+
*/
|
|
49
|
+
kind: InventoryKind;
|
|
50
|
+
/**
|
|
51
|
+
* The original triggering identifier — e.g. `/ship` for a command,
|
|
52
|
+
* `code-review` for a skill name. This is the field the install-time
|
|
53
|
+
* ledger replay matches against when deciding whether to re-apply a
|
|
54
|
+
* rename.
|
|
55
|
+
*/
|
|
56
|
+
originalIdentifier: string;
|
|
57
|
+
/**
|
|
58
|
+
* The chosen renamed identifier — e.g. `/anthropic-ship`,
|
|
59
|
+
* `anthropic-code-review`.
|
|
60
|
+
*/
|
|
61
|
+
renamedTo: string;
|
|
62
|
+
/** Absolute path to the original on-disk artifact at apply time. */
|
|
63
|
+
originalPath: string;
|
|
64
|
+
/** Absolute path to the renamed on-disk artifact post-apply. */
|
|
65
|
+
renamedPath: string;
|
|
66
|
+
/** ISO-8601 timestamp recorded by the writer (UTC). */
|
|
67
|
+
appliedAt: string;
|
|
68
|
+
/**
|
|
69
|
+
* FK to `~/.skillsmith/audits/<auditId>/result.json`. Lets a forensic
|
|
70
|
+
* lookup re-derive the original collision context.
|
|
71
|
+
*/
|
|
72
|
+
auditId: string;
|
|
73
|
+
/**
|
|
74
|
+
* Human-readable reason — e.g.
|
|
75
|
+
* `"collision with skillsmith/release-tools /ship"`. Surfaced verbatim
|
|
76
|
+
* in the audit-report writer (Wave 2 PR #4 extension).
|
|
77
|
+
*/
|
|
78
|
+
reason: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* On-disk shape of `~/.skillsmith/namespace-overrides.json`.
|
|
82
|
+
*
|
|
83
|
+
* `version` is required and validated on read. Unknown future fields are
|
|
84
|
+
* preserved on read-modify-write at the writer layer (additive
|
|
85
|
+
* extensions don't break older clients), but any `version` strictly
|
|
86
|
+
* greater than `CURRENT_VERSION` triggers a typed error per plan §2.
|
|
87
|
+
*/
|
|
88
|
+
export interface OverridesLedger {
|
|
89
|
+
version: LedgerVersion;
|
|
90
|
+
overrides: OverrideRecord[];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Typed error returned by `readLedger` when the on-disk file declares a
|
|
94
|
+
* higher version than this client understands. The reader does NOT throw
|
|
95
|
+
* — it returns this discriminator so callers can decide whether to abort
|
|
96
|
+
* or fall back. Plan §2 Edit 6.
|
|
97
|
+
*/
|
|
98
|
+
export interface LedgerVersionUnsupportedError {
|
|
99
|
+
kind: 'namespace.ledger.version_unsupported';
|
|
100
|
+
found: number;
|
|
101
|
+
expected: LedgerVersion;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Discriminated union returned by `readLedger`. The success branch is the
|
|
105
|
+
* ledger; the error branches are typed so callers `switch` on `kind` and
|
|
106
|
+
* never silently absorb a higher-version file as empty.
|
|
107
|
+
*/
|
|
108
|
+
export type ReadLedgerResult = {
|
|
109
|
+
kind: 'ok';
|
|
110
|
+
ledger: OverridesLedger;
|
|
111
|
+
} | LedgerVersionUnsupportedError | {
|
|
112
|
+
kind: 'namespace.ledger.malformed';
|
|
113
|
+
reason: string;
|
|
114
|
+
};
|
|
115
|
+
//# sourceMappingURL=namespace-overrides.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace-overrides.types.d.ts","sourceRoot":"","sources":["../../../src/audit/namespace-overrides.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAA;AAEtE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,EAAG,CAAU,CAAA;AAEzC,MAAM,MAAM,aAAa,GAAG,OAAO,eAAe,CAAA;AAElD;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,EAAE,EAAE,MAAM,CAAA;IACV;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB;;;;;OAKG;IACH,IAAI,EAAE,aAAa,CAAA;IACnB;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,CAAA;IAC1B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB,oEAAoE;IACpE,YAAY,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAA;IACnB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,cAAc,EAAE,CAAA;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,sCAAsC,CAAA;IAC5C,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,aAAa,CAAA;CACxB;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACvC,6BAA6B,GAC7B;IAAE,IAAI,EAAE,4BAA4B,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type vocabulary for the namespace-overrides ledger
|
|
3
|
+
* (SMI-4588 Wave 2 Step 1, PR #1).
|
|
4
|
+
* @module @skillsmith/mcp-server/audit/namespace-overrides.types
|
|
5
|
+
*
|
|
6
|
+
* Schema for `~/.skillsmith/namespace-overrides.json`. Modeled on the
|
|
7
|
+
* dependency-intelligence persistence pattern (SMI-3137). The schema is
|
|
8
|
+
* versioned; `CURRENT_VERSION` is bumped only when the on-disk shape
|
|
9
|
+
* changes incompatibly. Reader/writer live in `./namespace-overrides.ts`.
|
|
10
|
+
*
|
|
11
|
+
* Plan: docs/internal/implementation/smi-4588-rename-engine-ledger-install.md §2.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Current ledger schema version. Bumped only when the on-disk shape
|
|
15
|
+
* changes incompatibly. Read-path behavior:
|
|
16
|
+
*
|
|
17
|
+
* - `version === CURRENT_VERSION` → return as-is.
|
|
18
|
+
* - `version < CURRENT_VERSION` → caller may run a `migrateLedger` shim
|
|
19
|
+
* (currently no historical versions exist, so any value below 1 is
|
|
20
|
+
* unreachable in practice).
|
|
21
|
+
* - `version > CURRENT_VERSION` → reader returns a typed
|
|
22
|
+
* `namespace.ledger.version_unsupported` error rather than silently
|
|
23
|
+
* degrading to an empty ledger (plan §2 Edit 6).
|
|
24
|
+
*/
|
|
25
|
+
export const CURRENT_VERSION = 1;
|
|
26
|
+
//# sourceMappingURL=namespace-overrides.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace-overrides.types.js","sourceRoot":"","sources":["../../../src/audit/namespace-overrides.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAU,CAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Apply-path helpers for the rename engine
|
|
3
|
+
* (SMI-4588 Wave 2 Step 4, PR #2).
|
|
4
|
+
* @module @skillsmith/mcp-server/audit/rename-engine.apply-paths
|
|
5
|
+
*
|
|
6
|
+
* Path computation, backup orchestration, and summary formatting helpers
|
|
7
|
+
* extracted from `rename-engine.ts` to keep the main file <500 LOC per
|
|
8
|
+
* CLAUDE.md file-size enforcement (Edit 4 / SMI-1865 governance).
|
|
9
|
+
*
|
|
10
|
+
* **No backup writer here either** — the canonical `createSkillBackup`
|
|
11
|
+
* lives in `tools/install.conflict-helpers.ts`; this file orchestrates
|
|
12
|
+
* single-file staging so that helper can copy a directory worth of one
|
|
13
|
+
* file. Plan §1 Edit 4 still applies.
|
|
14
|
+
*/
|
|
15
|
+
import type { OverrideRecord } from './namespace-overrides.types.js';
|
|
16
|
+
import type { RenameAction, RenameError, RenameSuggestion } from './rename-engine.types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Map a `RenameAction` to the `OverrideRecord.kind` field. `command` /
|
|
19
|
+
* `agent` are 1:1; `rename_skill_dir_and_frontmatter` maps to `skill`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function actionToKind(action: RenameAction): OverrideRecord['kind'];
|
|
22
|
+
/**
|
|
23
|
+
* Compute the destination path on disk for a rename. For command/agent
|
|
24
|
+
* files, swap the basename (sans `.md`) with `newName.md`. For skill
|
|
25
|
+
* directories, rename the directory itself.
|
|
26
|
+
*/
|
|
27
|
+
export declare function computeDestPath(suggestion: RenameSuggestion, newName: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* `entry.meta?.author` may carry a slug like `anthropic` or a Skillsmith
|
|
30
|
+
* manifest skillId like `anthropic/code-helper`. The latter is what the
|
|
31
|
+
* ledger persists as `skillId`; the former is `null`. Heuristic: contains
|
|
32
|
+
* `/` ⇒ skillId.
|
|
33
|
+
*/
|
|
34
|
+
export declare function deriveSkillId(suggestion: RenameSuggestion): string | null;
|
|
35
|
+
export declare function fsErr(reason: string): RenameError;
|
|
36
|
+
export declare function pathExists(target: string): Promise<boolean>;
|
|
37
|
+
/**
|
|
38
|
+
* Run a backup before any on-disk mutation. Returns the backup directory
|
|
39
|
+
* path on success; throws on failure. The error path is wrapped in a
|
|
40
|
+
* typed `RenameError` by the caller.
|
|
41
|
+
*
|
|
42
|
+
* Backup naming: `<getBackupsDir()>/<skillName>/<timestamp>_namespace-rename/`
|
|
43
|
+
* via the canonical helper (plan §1 Edit 4).
|
|
44
|
+
*/
|
|
45
|
+
export declare function runBackup(suggestion: RenameSuggestion): Promise<string>;
|
|
46
|
+
/**
|
|
47
|
+
* Build the inline revert summary (decision #10):
|
|
48
|
+
* `"Renamed /<OLD> → /<NEW>. To undo: sklx audit revert <auditId>"`
|
|
49
|
+
*
|
|
50
|
+
* For skill renames (no leading `/`), the summary still uses the `/`
|
|
51
|
+
* prefix per the plan's literal text — agents render it as-is.
|
|
52
|
+
*/
|
|
53
|
+
export declare function buildSummary(oldIdentifier: string, newIdentifier: string, auditId: string, action: 'apply' | 'revert'): string;
|
|
54
|
+
//# sourceMappingURL=rename-engine.apply-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rename-engine.apply-paths.d.ts","sourceRoot":"","sources":["../../../src/audit/rename-engine.apply-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE3F;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,CASzE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMrF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAIzE;AAED,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAMjD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQjE;AAaD;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB7E;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,GAAG,QAAQ,GACzB,MAAM,CAKR"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Apply-path helpers for the rename engine
|
|
3
|
+
* (SMI-4588 Wave 2 Step 4, PR #2).
|
|
4
|
+
* @module @skillsmith/mcp-server/audit/rename-engine.apply-paths
|
|
5
|
+
*
|
|
6
|
+
* Path computation, backup orchestration, and summary formatting helpers
|
|
7
|
+
* extracted from `rename-engine.ts` to keep the main file <500 LOC per
|
|
8
|
+
* CLAUDE.md file-size enforcement (Edit 4 / SMI-1865 governance).
|
|
9
|
+
*
|
|
10
|
+
* **No backup writer here either** — the canonical `createSkillBackup`
|
|
11
|
+
* lives in `tools/install.conflict-helpers.ts`; this file orchestrates
|
|
12
|
+
* single-file staging so that helper can copy a directory worth of one
|
|
13
|
+
* file. Plan §1 Edit 4 still applies.
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from 'node:fs/promises';
|
|
16
|
+
import * as os from 'node:os';
|
|
17
|
+
import * as path from 'node:path';
|
|
18
|
+
import { createSkillBackup } from '../tools/install.conflict-helpers.js';
|
|
19
|
+
/**
|
|
20
|
+
* Map a `RenameAction` to the `OverrideRecord.kind` field. `command` /
|
|
21
|
+
* `agent` are 1:1; `rename_skill_dir_and_frontmatter` maps to `skill`.
|
|
22
|
+
*/
|
|
23
|
+
export function actionToKind(action) {
|
|
24
|
+
switch (action) {
|
|
25
|
+
case 'rename_command_file':
|
|
26
|
+
return 'command';
|
|
27
|
+
case 'rename_agent_file':
|
|
28
|
+
return 'agent';
|
|
29
|
+
case 'rename_skill_dir_and_frontmatter':
|
|
30
|
+
return 'skill';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Compute the destination path on disk for a rename. For command/agent
|
|
35
|
+
* files, swap the basename (sans `.md`) with `newName.md`. For skill
|
|
36
|
+
* directories, rename the directory itself.
|
|
37
|
+
*/
|
|
38
|
+
export function computeDestPath(suggestion, newName) {
|
|
39
|
+
const src = suggestion.entry.source_path;
|
|
40
|
+
if (suggestion.applyAction === 'rename_skill_dir_and_frontmatter') {
|
|
41
|
+
return path.join(path.dirname(src), newName);
|
|
42
|
+
}
|
|
43
|
+
return path.join(path.dirname(src), `${newName}.md`);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `entry.meta?.author` may carry a slug like `anthropic` or a Skillsmith
|
|
47
|
+
* manifest skillId like `anthropic/code-helper`. The latter is what the
|
|
48
|
+
* ledger persists as `skillId`; the former is `null`. Heuristic: contains
|
|
49
|
+
* `/` ⇒ skillId.
|
|
50
|
+
*/
|
|
51
|
+
export function deriveSkillId(suggestion) {
|
|
52
|
+
const author = suggestion.entry.meta?.author;
|
|
53
|
+
if (typeof author !== 'string' || author.length === 0)
|
|
54
|
+
return null;
|
|
55
|
+
return author.includes('/') ? author : null;
|
|
56
|
+
}
|
|
57
|
+
export function fsErr(reason) {
|
|
58
|
+
return {
|
|
59
|
+
kind: 'namespace.rename.fs_error',
|
|
60
|
+
reason,
|
|
61
|
+
message: `filesystem error during rename: ${reason}`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export async function pathExists(target) {
|
|
65
|
+
try {
|
|
66
|
+
await fs.stat(target);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
if (err.code === 'ENOENT')
|
|
71
|
+
return false;
|
|
72
|
+
throw err;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Stage a single command/agent file under a tmp directory so
|
|
77
|
+
* `createSkillBackup` (which copies a directory) backs up only that file.
|
|
78
|
+
* Returns the tmp-dir path; the caller removes it after the helper runs.
|
|
79
|
+
*/
|
|
80
|
+
async function stageSingleFileForBackup(srcFile) {
|
|
81
|
+
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'skillsmith-rename-stage-'));
|
|
82
|
+
await fs.copyFile(srcFile, path.join(tmp, path.basename(srcFile)));
|
|
83
|
+
return tmp;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Run a backup before any on-disk mutation. Returns the backup directory
|
|
87
|
+
* path on success; throws on failure. The error path is wrapped in a
|
|
88
|
+
* typed `RenameError` by the caller.
|
|
89
|
+
*
|
|
90
|
+
* Backup naming: `<getBackupsDir()>/<skillName>/<timestamp>_namespace-rename/`
|
|
91
|
+
* via the canonical helper (plan §1 Edit 4).
|
|
92
|
+
*/
|
|
93
|
+
export async function runBackup(suggestion) {
|
|
94
|
+
const skillName = path.basename(suggestion.entry.source_path).replace(/\.md$/, '');
|
|
95
|
+
const action = suggestion.applyAction;
|
|
96
|
+
if (action === 'rename_skill_dir_and_frontmatter') {
|
|
97
|
+
return createSkillBackup(skillName, suggestion.entry.source_path, 'namespace-rename');
|
|
98
|
+
}
|
|
99
|
+
// Single-file path — stage, back up the staged dir, clean up.
|
|
100
|
+
const staged = await stageSingleFileForBackup(suggestion.entry.source_path);
|
|
101
|
+
try {
|
|
102
|
+
return await createSkillBackup(skillName, staged, 'namespace-rename');
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
try {
|
|
106
|
+
await fs.rm(staged, { recursive: true, force: true });
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// best-effort
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Build the inline revert summary (decision #10):
|
|
115
|
+
* `"Renamed /<OLD> → /<NEW>. To undo: sklx audit revert <auditId>"`
|
|
116
|
+
*
|
|
117
|
+
* For skill renames (no leading `/`), the summary still uses the `/`
|
|
118
|
+
* prefix per the plan's literal text — agents render it as-is.
|
|
119
|
+
*/
|
|
120
|
+
export function buildSummary(oldIdentifier, newIdentifier, auditId, action) {
|
|
121
|
+
if (action === 'revert') {
|
|
122
|
+
return `Reverted /${oldIdentifier} → /${newIdentifier}. Audit: ${auditId}`;
|
|
123
|
+
}
|
|
124
|
+
return `Renamed /${oldIdentifier} → /${newIdentifier}. To undo: sklx audit revert ${auditId}`;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=rename-engine.apply-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rename-engine.apply-paths.js","sourceRoot":"","sources":["../../../src/audit/rename-engine.apply-paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Rename engine — applies confirmed namespace renames
|
|
3
|
+
* (SMI-4588 Wave 2 Step 4, PR #2).
|
|
4
|
+
* @module @skillsmith/mcp-server/audit/rename-engine
|
|
5
|
+
*
|
|
6
|
+
* Three apply paths, gated on `RenameAction`:
|
|
7
|
+
*
|
|
8
|
+
* - `rename_command_file` — `~/.claude/commands/foo.md` → `<author>-foo.md`
|
|
9
|
+
* - `rename_agent_file` — `~/.claude/agents/foo.md` → `<author>-foo.md`
|
|
10
|
+
* - `rename_skill_dir_and_frontmatter` — rename the directory AND rewrite
|
|
11
|
+
* the SKILL.md `name:` frontmatter field.
|
|
12
|
+
*
|
|
13
|
+
* Plus `action: 'revert'` semantics: looks up the ledger entry by
|
|
14
|
+
* `auditId`, performs the inverse rename (back to `originalIdentifier`),
|
|
15
|
+
* removes the ledger entry, and restores the SKILL.md frontmatter.
|
|
16
|
+
*
|
|
17
|
+
* Backups are owned by the canonical `createSkillBackup` helper at
|
|
18
|
+
* `tools/install.conflict-helpers.ts:87` (plan §1 Edit 4). Single-file
|
|
19
|
+
* renames stage the file under a tmp directory so the helper (which
|
|
20
|
+
* expects a source dir) backs up only the relevant file. Backups land in
|
|
21
|
+
* `~/.claude/skills/.backups/<name>/<timestamp>_namespace-rename/`.
|
|
22
|
+
*
|
|
23
|
+
* Idempotency: before mutating, the engine consults the namespace-overrides
|
|
24
|
+
* ledger. When the same `(skillId, originalIdentifier)` pair is already
|
|
25
|
+
* in the ledger AND the on-disk filename matches the recorded
|
|
26
|
+
* `renamedTo`, the call is a no-op (returns success with
|
|
27
|
+
* `fromPath === toPath` and `backupPath === ''`).
|
|
28
|
+
*
|
|
29
|
+
* Disk-vs-ledger divergence: when the ledger has an entry but the on-disk
|
|
30
|
+
* filename does NOT match `renamedTo`, the engine returns
|
|
31
|
+
* `namespace.ledger.disk_divergence` rather than silently re-applying.
|
|
32
|
+
*
|
|
33
|
+
* Plan: docs/internal/implementation/smi-4588-rename-engine-ledger-install.md §1.
|
|
34
|
+
*/
|
|
35
|
+
import { getBackupsDir } from '../tools/install.conflict-helpers.js';
|
|
36
|
+
import type { ApplyRenameRequest, ApplyRenameResult } from './rename-engine.types.js';
|
|
37
|
+
export { generateSuggestionChain } from './suggestion-chain.js';
|
|
38
|
+
/**
|
|
39
|
+
* Public summary prefix used by the agent / CLI to detect inline revert
|
|
40
|
+
* messages. Matches plan §1 decision #10 verbatim.
|
|
41
|
+
*/
|
|
42
|
+
export declare const REVERT_SUMMARY_PREFIX = "Renamed";
|
|
43
|
+
/**
|
|
44
|
+
* Apply (or revert) a rename. Single entrypoint for Wave 4's MCP tool.
|
|
45
|
+
* Each apply path runs: idempotency check → backup → mutate → ledger
|
|
46
|
+
* append → result. Revert: ledger lookup → inverse rename → ledger
|
|
47
|
+
* remove → result.
|
|
48
|
+
*
|
|
49
|
+
* Idempotency contract: re-applying the same suggestion when the ledger
|
|
50
|
+
* already records it AND on-disk state matches → returns success with
|
|
51
|
+
* `fromPath === toPath` and `backupPath === ''` (no second backup).
|
|
52
|
+
*
|
|
53
|
+
* Disk-vs-ledger divergence: ledger entry exists but on-disk path does
|
|
54
|
+
* NOT match `renamedTo` → `namespace.ledger.disk_divergence` error;
|
|
55
|
+
* caller decides whether to `customName` over the divergence.
|
|
56
|
+
*/
|
|
57
|
+
export declare function applyRename(input: ApplyRenameRequest): Promise<ApplyRenameResult>;
|
|
58
|
+
export { getBackupsDir };
|
|
59
|
+
//# sourceMappingURL=rename-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rename-engine.d.ts","sourceRoot":"","sources":["../../../src/audit/rename-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAKH,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAA;AAYpE,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAElB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAE/D;;;GAGG;AACH,eAAO,MAAM,qBAAqB,YAAY,CAAA;AAE9C;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0MvF;AAiJD,OAAO,EAAE,aAAa,EAAE,CAAA"}
|