@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,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared `runInventoryAudit` composition helper (SMI-4590 Wave 4 PR 4).
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/run-inventory-audit
|
|
4
|
+
*
|
|
5
|
+
* Composes Wave 1 (scan + detect + history) + Wave 2 (rename suggestions)
|
|
6
|
+
* + Wave 3 (recommended edits) + Wave 4 PR 3 (exclusions filter) into a
|
|
7
|
+
* single entry-point used by both the `skill_inventory_audit` MCP tool
|
|
8
|
+
* (this PR) and the `sklx audit collisions` CLI command (PR 5).
|
|
9
|
+
*
|
|
10
|
+
* Plan: docs/internal/implementation/smi-4590-cli-mcp-framework-adapter.md §1.
|
|
11
|
+
*
|
|
12
|
+
* Pipeline:
|
|
13
|
+
* 1. `scanLocalInventory` (Wave 1) — scan the inventory.
|
|
14
|
+
* 2. `detectCollisions` (Wave 1) — three-pass detector.
|
|
15
|
+
* 3. Build `RenameSuggestion[]` (Wave 2 types) — one per exact collision,
|
|
16
|
+
* using `generateSuggestionChain` to pick a non-colliding name and
|
|
17
|
+
* mtime-descending tiebreak to pick which entry to rename.
|
|
18
|
+
* 4. `runEditSuggester` (Wave 3) — recommended prose edits.
|
|
19
|
+
* 5. Apply `~/.skillsmith/audit-exclusions.json` filter (Wave 4 PR 3)
|
|
20
|
+
* when `applyExclusions !== false`.
|
|
21
|
+
* 6. `writeAuditHistory` (Wave 1) — persist `result.json`.
|
|
22
|
+
* 7. `writeAuditSuggestions` (this PR) — persist `suggestions.json`
|
|
23
|
+
* (so PR 4's apply-tools can look up rename + edit by collisionId).
|
|
24
|
+
* 8. Build + return the response shape.
|
|
25
|
+
*
|
|
26
|
+
* Tier defaults to `'community'` (cheapest fail-safe). Callers (the MCP
|
|
27
|
+
* tool, the CLI) pass through their resolved tier; the session-start
|
|
28
|
+
* audit hook (PR 6) passes the user's resolved tier from license info.
|
|
29
|
+
*/
|
|
30
|
+
import type { Tier } from '@skillsmith/core/config/audit-mode';
|
|
31
|
+
import type { InventoryEntry } from '../utils/local-inventory.types.js';
|
|
32
|
+
import type { ExactCollisionFlag, GenericTokenFlag, SemanticCollisionFlag } from './collision-detector.types.js';
|
|
33
|
+
import type { RecommendedEdit } from './edit-suggester.types.js';
|
|
34
|
+
import type { RenameSuggestion } from './rename-engine.types.js';
|
|
35
|
+
/**
|
|
36
|
+
* Input for {@link runInventoryAudit}. All fields optional — the MCP tool
|
|
37
|
+
* input schema rejects unknowns and home-dir traversal at the boundary.
|
|
38
|
+
*/
|
|
39
|
+
export interface RunInventoryAuditOptions {
|
|
40
|
+
/** Gate the semantic-overlap pass (Wave 1). Defaults to `false`. */
|
|
41
|
+
deep?: boolean;
|
|
42
|
+
/** Override `os.homedir()`. Caller (MCP tool) Zod-validates the path. */
|
|
43
|
+
homeDir?: string;
|
|
44
|
+
/** Optional project CLAUDE.md to scan in addition to the user one. */
|
|
45
|
+
projectDir?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Filter collision flags whose entries match
|
|
48
|
+
* `~/.skillsmith/audit-exclusions.json`. Defaults to `true`. Enterprise
|
|
49
|
+
* scheduled-scan runner (PR 6) passes `false` so the governance pass
|
|
50
|
+
* sees un-filtered findings for policy enforcement.
|
|
51
|
+
*/
|
|
52
|
+
applyExclusions?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Subscription tier of the caller — gates the semantic pass per the
|
|
55
|
+
* audit-mode resolver. Defaults to `'community'` (preventative mode →
|
|
56
|
+
* exact + generic only). The MCP tool resolves the caller tier from
|
|
57
|
+
* license info before invoking; the CLI command passes through the same.
|
|
58
|
+
*/
|
|
59
|
+
tier?: Tier;
|
|
60
|
+
}
|
|
61
|
+
/** Response shape returned to MCP / CLI callers. */
|
|
62
|
+
export interface RunInventoryAuditResult {
|
|
63
|
+
auditId: string;
|
|
64
|
+
inventory: InventoryEntry[];
|
|
65
|
+
exactCollisions: ExactCollisionFlag[];
|
|
66
|
+
/**
|
|
67
|
+
* Wave 1's `genericFlags` (typed `GenericTokenFlag[]`). Plan §99–108
|
|
68
|
+
* referenced this field as `TriggerQualityEntry[]`; the canonical Wave 1
|
|
69
|
+
* type is `GenericTokenFlag`. Field name preserved per spec.
|
|
70
|
+
*/
|
|
71
|
+
genericFlags: GenericTokenFlag[];
|
|
72
|
+
semanticCollisions: SemanticCollisionFlag[];
|
|
73
|
+
renameSuggestions: RenameSuggestion[];
|
|
74
|
+
recommendedEdits: RecommendedEdit[];
|
|
75
|
+
/** Absolute path to the rendered `report.md` for this audit. */
|
|
76
|
+
reportPath: string;
|
|
77
|
+
summary: {
|
|
78
|
+
totalEntries: number;
|
|
79
|
+
totalFlags: number;
|
|
80
|
+
errorCount: number;
|
|
81
|
+
warningCount: number;
|
|
82
|
+
durationMs: number;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Run the full inventory audit pipeline. Single entrypoint shared by the
|
|
87
|
+
* MCP `skill_inventory_audit` tool and the CLI `sklx audit collisions`
|
|
88
|
+
* command.
|
|
89
|
+
*
|
|
90
|
+
* Stateless — every call generates a fresh `auditId` (via the detector's
|
|
91
|
+
* default ULID generator) and writes the corresponding history +
|
|
92
|
+
* suggestions files to `~/.skillsmith/audits/<auditId>/`.
|
|
93
|
+
*/
|
|
94
|
+
export declare function runInventoryAudit(opts?: RunInventoryAuditOptions): Promise<RunInventoryAuditResult>;
|
|
95
|
+
//# sourceMappingURL=run-inventory-audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-inventory-audit.d.ts","sourceRoot":"","sources":["../../../src/audit/run-inventory-audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAUH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAA;AAG9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAEvE,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACtB,MAAM,+BAA+B,CAAA;AAKtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEhE,OAAO,KAAK,EAAgB,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAG9E;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,IAAI,CAAA;CACZ;AAED,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,eAAe,EAAE,kBAAkB,EAAE,CAAA;IACrC;;;;OAIG;IACH,YAAY,EAAE,gBAAgB,EAAE,CAAA;IAChC,kBAAkB,EAAE,qBAAqB,EAAE,CAAA;IAC3C,iBAAiB,EAAE,gBAAgB,EAAE,CAAA;IACrC,gBAAgB,EAAE,eAAe,EAAE,CAAA;IACnC,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE;QACP,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,EAAE,MAAM,CAAA;QAClB,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,EAAE,MAAM,CAAA;KACnB,CAAA;CACF;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,GAAE,wBAA6B,GAClC,OAAO,CAAC,uBAAuB,CAAC,CAgFlC"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared `runInventoryAudit` composition helper (SMI-4590 Wave 4 PR 4).
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/run-inventory-audit
|
|
4
|
+
*
|
|
5
|
+
* Composes Wave 1 (scan + detect + history) + Wave 2 (rename suggestions)
|
|
6
|
+
* + Wave 3 (recommended edits) + Wave 4 PR 3 (exclusions filter) into a
|
|
7
|
+
* single entry-point used by both the `skill_inventory_audit` MCP tool
|
|
8
|
+
* (this PR) and the `sklx audit collisions` CLI command (PR 5).
|
|
9
|
+
*
|
|
10
|
+
* Plan: docs/internal/implementation/smi-4590-cli-mcp-framework-adapter.md §1.
|
|
11
|
+
*
|
|
12
|
+
* Pipeline:
|
|
13
|
+
* 1. `scanLocalInventory` (Wave 1) — scan the inventory.
|
|
14
|
+
* 2. `detectCollisions` (Wave 1) — three-pass detector.
|
|
15
|
+
* 3. Build `RenameSuggestion[]` (Wave 2 types) — one per exact collision,
|
|
16
|
+
* using `generateSuggestionChain` to pick a non-colliding name and
|
|
17
|
+
* mtime-descending tiebreak to pick which entry to rename.
|
|
18
|
+
* 4. `runEditSuggester` (Wave 3) — recommended prose edits.
|
|
19
|
+
* 5. Apply `~/.skillsmith/audit-exclusions.json` filter (Wave 4 PR 3)
|
|
20
|
+
* when `applyExclusions !== false`.
|
|
21
|
+
* 6. `writeAuditHistory` (Wave 1) — persist `result.json`.
|
|
22
|
+
* 7. `writeAuditSuggestions` (this PR) — persist `suggestions.json`
|
|
23
|
+
* (so PR 4's apply-tools can look up rename + edit by collisionId).
|
|
24
|
+
* 8. Build + return the response shape.
|
|
25
|
+
*
|
|
26
|
+
* Tier defaults to `'community'` (cheapest fail-safe). Callers (the MCP
|
|
27
|
+
* tool, the CLI) pass through their resolved tier; the session-start
|
|
28
|
+
* audit hook (PR 6) passes the user's resolved tier from license info.
|
|
29
|
+
*/
|
|
30
|
+
import * as os from 'node:os';
|
|
31
|
+
import { loadExclusions, isExcluded as isExcludedCore, } from '@skillsmith/core/audit';
|
|
32
|
+
import { scanLocalInventory } from '../utils/local-inventory.js';
|
|
33
|
+
import { detectCollisions } from './collision-detector.js';
|
|
34
|
+
import { writeAuditHistory } from './audit-history.js';
|
|
35
|
+
import { writeAuditReport } from './audit-report-writer.js';
|
|
36
|
+
import { writeAuditSuggestions } from './audit-suggestions.js';
|
|
37
|
+
import { runEditSuggester } from './edit-suggester.js';
|
|
38
|
+
import { generateSuggestionChain } from './suggestion-chain.js';
|
|
39
|
+
import { FIELD_LIMITS } from '../tools/validate.types.js';
|
|
40
|
+
/**
|
|
41
|
+
* Run the full inventory audit pipeline. Single entrypoint shared by the
|
|
42
|
+
* MCP `skill_inventory_audit` tool and the CLI `sklx audit collisions`
|
|
43
|
+
* command.
|
|
44
|
+
*
|
|
45
|
+
* Stateless — every call generates a fresh `auditId` (via the detector's
|
|
46
|
+
* default ULID generator) and writes the corresponding history +
|
|
47
|
+
* suggestions files to `~/.skillsmith/audits/<auditId>/`.
|
|
48
|
+
*/
|
|
49
|
+
export async function runInventoryAudit(opts = {}) {
|
|
50
|
+
const startedAt = process.hrtime.bigint();
|
|
51
|
+
// Step 1: scan the local inventory.
|
|
52
|
+
const homeDir = opts.homeDir ?? os.homedir();
|
|
53
|
+
const scan = await scanLocalInventory({
|
|
54
|
+
homeDir,
|
|
55
|
+
...(opts.projectDir !== undefined ? { projectDir: opts.projectDir } : {}),
|
|
56
|
+
});
|
|
57
|
+
// Step 2: run the three-pass detector. Tier resolves the audit-mode
|
|
58
|
+
// (preventative → exact + generic; power_user / governance → +semantic).
|
|
59
|
+
// `deep: true` opts into the semantic pass via the `auditModeOverride`
|
|
60
|
+
// path so callers don't need to know about tier semantics.
|
|
61
|
+
const tier = opts.tier ?? 'community';
|
|
62
|
+
const detectorOpts = { tier };
|
|
63
|
+
if (opts.deep) {
|
|
64
|
+
detectorOpts.auditModeOverride = 'power_user';
|
|
65
|
+
}
|
|
66
|
+
const detectorResult = await detectCollisions(scan.entries, detectorOpts);
|
|
67
|
+
// Step 3: build rename suggestions for each exact collision.
|
|
68
|
+
const renameSuggestions = buildRenameSuggestions(detectorResult, scan.entries);
|
|
69
|
+
// Step 4: run the edit suggester (Wave 3 — semantic-collision path).
|
|
70
|
+
// Returns an empty array when `semanticCollisions.length === 0`.
|
|
71
|
+
const recommendedEdits = await runEditSuggester(detectorResult);
|
|
72
|
+
// Step 5: apply exclusions filter when requested. Defaults to `true`;
|
|
73
|
+
// Enterprise scheduled-scan (PR 6) passes `false`.
|
|
74
|
+
const applyExclusions = opts.applyExclusions !== false;
|
|
75
|
+
let filtered = detectorResult;
|
|
76
|
+
let filteredRenames = renameSuggestions;
|
|
77
|
+
let filteredEdits = recommendedEdits;
|
|
78
|
+
if (applyExclusions) {
|
|
79
|
+
const exclusions = await loadExclusions();
|
|
80
|
+
filtered = applyExclusionsFilter(detectorResult, exclusions);
|
|
81
|
+
filteredRenames = renameSuggestions.filter((s) => filtered.exactCollisions.some((f) => f.collisionId === s.collisionId));
|
|
82
|
+
const keptCollisionIds = new Set([
|
|
83
|
+
...filtered.exactCollisions.map((f) => f.collisionId),
|
|
84
|
+
...filtered.genericFlags.map((f) => f.collisionId),
|
|
85
|
+
...filtered.semanticCollisions.map((f) => f.collisionId),
|
|
86
|
+
]);
|
|
87
|
+
filteredEdits = recommendedEdits.filter((e) => keptCollisionIds.has(e.collisionId));
|
|
88
|
+
}
|
|
89
|
+
// Step 6: persist `result.json` + `report.md`. The history writer
|
|
90
|
+
// creates the per-audit directory; the report writer reuses it.
|
|
91
|
+
const history = await writeAuditHistory(filtered);
|
|
92
|
+
await writeAuditReport(filtered, {
|
|
93
|
+
auditDir: history.reportPath.replace(/\/report\.md$/, ''),
|
|
94
|
+
renameSuggestions: filteredRenames,
|
|
95
|
+
recommendedEdits: filteredEdits,
|
|
96
|
+
});
|
|
97
|
+
// Step 7: persist `suggestions.json` (this PR — for the apply-tools).
|
|
98
|
+
await writeAuditSuggestions(filtered.auditId, filteredRenames, filteredEdits);
|
|
99
|
+
const durationMs = Number(process.hrtime.bigint() - startedAt) / 1_000_000;
|
|
100
|
+
// Step 8: build the response.
|
|
101
|
+
return {
|
|
102
|
+
auditId: filtered.auditId,
|
|
103
|
+
inventory: filtered.inventory,
|
|
104
|
+
exactCollisions: filtered.exactCollisions,
|
|
105
|
+
genericFlags: filtered.genericFlags,
|
|
106
|
+
semanticCollisions: filtered.semanticCollisions,
|
|
107
|
+
renameSuggestions: filteredRenames,
|
|
108
|
+
recommendedEdits: filteredEdits,
|
|
109
|
+
reportPath: history.reportPath,
|
|
110
|
+
summary: {
|
|
111
|
+
totalEntries: filtered.summary.totalEntries,
|
|
112
|
+
totalFlags: filtered.summary.totalFlags,
|
|
113
|
+
errorCount: filtered.summary.errorCount,
|
|
114
|
+
warningCount: filtered.summary.warningCount,
|
|
115
|
+
durationMs,
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// Helpers
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
/**
|
|
123
|
+
* Build a `RenameSuggestion[]` from each `ExactCollisionFlag`. We pick the
|
|
124
|
+
* **most-recently-installed** entry (mtime descending) as the rename
|
|
125
|
+
* target — matches plan §259 default-entry tiebreak. Falls back to the
|
|
126
|
+
* first entry when mtime is missing.
|
|
127
|
+
*
|
|
128
|
+
* Author / packDomain are left null for v1 — chain falls through to the
|
|
129
|
+
* `local-` prefix path (`local-foo`, `local-foo-<shortHash>`). Wave 4 PR 5
|
|
130
|
+
* extends this with manifest lookups for richer prefixes.
|
|
131
|
+
*/
|
|
132
|
+
function buildRenameSuggestions(result, fullInventory) {
|
|
133
|
+
const suggestions = [];
|
|
134
|
+
for (const flag of result.exactCollisions) {
|
|
135
|
+
if (flag.entries.length === 0)
|
|
136
|
+
continue;
|
|
137
|
+
// mtime-descending tiebreak; missing mtime sinks to the bottom.
|
|
138
|
+
const sorted = [...flag.entries].sort((a, b) => (b.mtime ?? 0) - (a.mtime ?? 0));
|
|
139
|
+
const target = sorted[0];
|
|
140
|
+
const action = inventoryKindToRenameAction(target);
|
|
141
|
+
if (action === null)
|
|
142
|
+
continue; // claude_md_rule entries can't be renamed.
|
|
143
|
+
// SMI-4737: defensive cap on filesystem-derived identifier. Filesystem
|
|
144
|
+
// entries with > 128-char names produce no rename suggestion; the
|
|
145
|
+
// collision is still surfaced via `result.exactCollisions`.
|
|
146
|
+
const rawToken = stripLeadingSlash(target.identifier);
|
|
147
|
+
if (rawToken.length > FIELD_LIMITS.token) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const chain = generateSuggestionChain({
|
|
151
|
+
token: rawToken,
|
|
152
|
+
author: target.meta?.author ?? null,
|
|
153
|
+
packDomain: null,
|
|
154
|
+
tagFallback: target.meta?.tags?.[0] ?? null,
|
|
155
|
+
authorPath: target.source_path,
|
|
156
|
+
existingInventory: fullInventory,
|
|
157
|
+
});
|
|
158
|
+
const lowercaseInventory = new Set(fullInventory.map((e) => e.identifier.toLowerCase()));
|
|
159
|
+
const firstFree = chain.candidates.find((c) => !lowercaseInventory.has(c.toLowerCase()));
|
|
160
|
+
const suggested = firstFree ?? chain.candidates[0] ?? target.identifier;
|
|
161
|
+
suggestions.push({
|
|
162
|
+
collisionId: flag.collisionId,
|
|
163
|
+
entry: target,
|
|
164
|
+
currentName: target.identifier,
|
|
165
|
+
suggested,
|
|
166
|
+
applyAction: action,
|
|
167
|
+
reason: flag.reason,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return suggestions;
|
|
171
|
+
}
|
|
172
|
+
function stripLeadingSlash(identifier) {
|
|
173
|
+
return identifier.startsWith('/') ? identifier.slice(1) : identifier;
|
|
174
|
+
}
|
|
175
|
+
/** Map an `InventoryEntry.kind` to a `RenameAction`, or `null` for unrenamable kinds. */
|
|
176
|
+
function inventoryKindToRenameAction(entry) {
|
|
177
|
+
switch (entry.kind) {
|
|
178
|
+
case 'command':
|
|
179
|
+
return 'rename_command_file';
|
|
180
|
+
case 'agent':
|
|
181
|
+
return 'rename_agent_file';
|
|
182
|
+
case 'skill':
|
|
183
|
+
return 'rename_skill_dir_and_frontmatter';
|
|
184
|
+
case 'claude_md_rule':
|
|
185
|
+
return null;
|
|
186
|
+
default:
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Drop a collision flag iff ANY involved entry matches an exclusion. The
|
|
192
|
+
* intent of an exclusion is "I deliberately keep this entry around" —
|
|
193
|
+
* once the user marks one side acceptable, the rename suggestion against
|
|
194
|
+
* that pair is moot.
|
|
195
|
+
*
|
|
196
|
+
* Inventory itself is NOT filtered — exclusions suppress findings, not
|
|
197
|
+
* inventory entries. The audit report still lists every entry under
|
|
198
|
+
* "Inventory" so the user has full context for their exclusion choices.
|
|
199
|
+
*/
|
|
200
|
+
function applyExclusionsFilter(result, config) {
|
|
201
|
+
if (config.exclusions.length === 0)
|
|
202
|
+
return result;
|
|
203
|
+
const exactCollisions = result.exactCollisions.filter((flag) => !flag.entries.some((entry) => isExcludedInventoryEntry(entry, config)));
|
|
204
|
+
const genericFlags = result.genericFlags.filter((flag) => !isExcludedInventoryEntry(flag.entry, config));
|
|
205
|
+
const semanticCollisions = result.semanticCollisions.filter((flag) => !isExcludedInventoryEntry(flag.entryA, config) &&
|
|
206
|
+
!isExcludedInventoryEntry(flag.entryB, config));
|
|
207
|
+
const errorCount = exactCollisions.length;
|
|
208
|
+
const warningCount = genericFlags.length + semanticCollisions.length;
|
|
209
|
+
return {
|
|
210
|
+
...result,
|
|
211
|
+
exactCollisions,
|
|
212
|
+
genericFlags,
|
|
213
|
+
semanticCollisions,
|
|
214
|
+
summary: {
|
|
215
|
+
...result.summary,
|
|
216
|
+
totalFlags: errorCount + warningCount,
|
|
217
|
+
errorCount,
|
|
218
|
+
warningCount,
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
/** Translate a Wave 1 `InventoryEntry` to the core `ExcludableEntry` shape. */
|
|
223
|
+
function isExcludedInventoryEntry(entry, config) {
|
|
224
|
+
if (entry.kind === 'command') {
|
|
225
|
+
const candidate = {
|
|
226
|
+
kind: 'command',
|
|
227
|
+
commandIdentifier: entry.identifier.startsWith('/')
|
|
228
|
+
? entry.identifier
|
|
229
|
+
: `/${entry.identifier}`,
|
|
230
|
+
};
|
|
231
|
+
return isExcludedCore(candidate, config);
|
|
232
|
+
}
|
|
233
|
+
if (entry.kind === 'skill') {
|
|
234
|
+
const author = entry.meta?.author;
|
|
235
|
+
// Skill exclusions are keyed by `<author>/<identifier>`. Without an
|
|
236
|
+
// author, fall back to bare identifier so a manually-edited
|
|
237
|
+
// exclusions file can still target unmanaged skills.
|
|
238
|
+
const skillId = author ? `${author}/${entry.identifier}` : entry.identifier;
|
|
239
|
+
const candidate = { kind: 'skill', skillId };
|
|
240
|
+
return isExcludedCore(candidate, config);
|
|
241
|
+
}
|
|
242
|
+
// agents + claude_md_rule have no v1 exclusion shape — never excluded.
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=run-inventory-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-inventory-audit.js","sourceRoot":"","sources":["../../../src/audit/run-inventory-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview 3-tier rename fall-through chain (SMI-4588 Wave 2 Step 2, PR #2).
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/suggestion-chain
|
|
4
|
+
*
|
|
5
|
+
* Generates up to 3 ordered rename candidates per decision #11:
|
|
6
|
+
*
|
|
7
|
+
* 1. `${author}-${token}` (e.g. `anthropic-ship`)
|
|
8
|
+
* 2. `${author}-${packDomain}-${token}` (e.g. `anthropic-codehelper-ship`)
|
|
9
|
+
* 3. `${author}-${packDomain}-${token}-${shortHash}` (e.g. `anthropic-codehelper-ship-a4f9`)
|
|
10
|
+
*
|
|
11
|
+
* Each candidate is checked against the supplied `existingInventory` — when
|
|
12
|
+
* a candidate collides with another entry's identifier (case-insensitive),
|
|
13
|
+
* the chain advances to the next tier. If all 3 collide, `exhausted: true`
|
|
14
|
+
* and the caller surfaces the chain to the user via `customName`.
|
|
15
|
+
*
|
|
16
|
+
* Inventory contract (plan §1 Edit 7): `existingInventory` is the
|
|
17
|
+
* snapshot **before** the candidate skill is appended. Otherwise the
|
|
18
|
+
* candidate self-collides at tier 1 and cascades unnecessarily. The install
|
|
19
|
+
* pre-flight maintains two inventory views — `existingInventory` for
|
|
20
|
+
* suggestion generation, `augmentedInventory` for `detectCollisions`.
|
|
21
|
+
*
|
|
22
|
+
* `shortHash` derivation: first 4 hex chars of
|
|
23
|
+
* sha256(`${authorPath}/${token}/${packDomain}`)
|
|
24
|
+
*
|
|
25
|
+
* Birthday-bound collision-free for inventories <10k entries (Wave 0 spike
|
|
26
|
+
* §4 — measured 0% on 36-skill fixture, theoretical bound holds).
|
|
27
|
+
*
|
|
28
|
+
* Plan: docs/internal/implementation/smi-4588-rename-engine-ledger-install.md §1.
|
|
29
|
+
*/
|
|
30
|
+
import type { InventoryEntry } from './collision-detector.types.js';
|
|
31
|
+
import type { SuggestionChain } from './rename-engine.types.js';
|
|
32
|
+
/**
|
|
33
|
+
* Compute the deterministic 4-char `shortHash` suffix used at chain tier 3.
|
|
34
|
+
* Exported for tests; in normal flow callers use `generateSuggestionChain`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function computeShortHash(authorPath: string, token: string, packDomain: string | null): string;
|
|
37
|
+
/**
|
|
38
|
+
* Sanitize an author / tag / token segment for safe use in an identifier.
|
|
39
|
+
* Lowercases, replaces non-`[a-z0-9]` runs with `-`, trims, and dedupes
|
|
40
|
+
* consecutive separators. Mirrors the rule in plan §1 step 1.
|
|
41
|
+
*/
|
|
42
|
+
export declare function sanitizeSegment(raw: string): string;
|
|
43
|
+
export interface GenerateSuggestionChainInput {
|
|
44
|
+
/**
|
|
45
|
+
* The colliding entry's base token (e.g. `ship` for `/ship`,
|
|
46
|
+
* `code-helper` for a skill named `code-helper`). Already stripped of
|
|
47
|
+
* any leading `/` for commands; the chain produces a token-only result
|
|
48
|
+
* — formatting back to `/foo` is the apply-path's job.
|
|
49
|
+
*/
|
|
50
|
+
token: string;
|
|
51
|
+
/**
|
|
52
|
+
* Author segment from manifest. Sanitized inside; pass raw. When
|
|
53
|
+
* `null`/`''`, tier 1 falls through to using the supplied `tagFallback`.
|
|
54
|
+
*/
|
|
55
|
+
author: string | null;
|
|
56
|
+
/**
|
|
57
|
+
* Pack-domain segment (e.g. `codehelper`). Sanitized inside. When
|
|
58
|
+
* `null`, tier 2 is skipped and tier 3 omits the pack-domain segment.
|
|
59
|
+
*/
|
|
60
|
+
packDomain: string | null;
|
|
61
|
+
/**
|
|
62
|
+
* Tag fallback when `author` is unavailable. Already-sanitized values
|
|
63
|
+
* are accepted; the function re-sanitizes idempotently.
|
|
64
|
+
*/
|
|
65
|
+
tagFallback?: string | null;
|
|
66
|
+
/**
|
|
67
|
+
* Repo-relative path used to derive `shortHash` at tier 3. Plan §1 calls
|
|
68
|
+
* for the entry's `source_path` resolved repo-relative; the caller is
|
|
69
|
+
* responsible for the resolution since the rename engine has no concept
|
|
70
|
+
* of "repo root".
|
|
71
|
+
*/
|
|
72
|
+
authorPath: string;
|
|
73
|
+
/**
|
|
74
|
+
* Pre-candidate inventory snapshot (Edit 7). MUST NOT contain the
|
|
75
|
+
* candidate skill — the chain generator self-collides at tier 1
|
|
76
|
+
* otherwise.
|
|
77
|
+
*/
|
|
78
|
+
existingInventory: ReadonlyArray<InventoryEntry>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Walk the 3-tier rename fall-through chain (decision #11). Returns up to
|
|
82
|
+
* 3 ordered candidates and an `exhausted` flag. The caller picks the first
|
|
83
|
+
* non-colliding candidate as the recommended rename.
|
|
84
|
+
*
|
|
85
|
+
* Returns an empty `candidates` array iff `token` itself sanitizes to an
|
|
86
|
+
* empty string (defensive — pathological inputs).
|
|
87
|
+
*/
|
|
88
|
+
export declare function generateSuggestionChain(input: GenerateSuggestionChainInput): SuggestionChain;
|
|
89
|
+
//# sourceMappingURL=suggestion-chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggestion-chain.d.ts","sourceRoot":"","sources":["../../../src/audit/suggestion-chain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAI/D;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,MAAM,CAGR;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAenD;AAiBD,MAAM,WAAW,4BAA4B;IAC3C;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,iBAAiB,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;CACjD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,GAAG,eAAe,CA+C5F"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview 3-tier rename fall-through chain (SMI-4588 Wave 2 Step 2, PR #2).
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/suggestion-chain
|
|
4
|
+
*
|
|
5
|
+
* Generates up to 3 ordered rename candidates per decision #11:
|
|
6
|
+
*
|
|
7
|
+
* 1. `${author}-${token}` (e.g. `anthropic-ship`)
|
|
8
|
+
* 2. `${author}-${packDomain}-${token}` (e.g. `anthropic-codehelper-ship`)
|
|
9
|
+
* 3. `${author}-${packDomain}-${token}-${shortHash}` (e.g. `anthropic-codehelper-ship-a4f9`)
|
|
10
|
+
*
|
|
11
|
+
* Each candidate is checked against the supplied `existingInventory` — when
|
|
12
|
+
* a candidate collides with another entry's identifier (case-insensitive),
|
|
13
|
+
* the chain advances to the next tier. If all 3 collide, `exhausted: true`
|
|
14
|
+
* and the caller surfaces the chain to the user via `customName`.
|
|
15
|
+
*
|
|
16
|
+
* Inventory contract (plan §1 Edit 7): `existingInventory` is the
|
|
17
|
+
* snapshot **before** the candidate skill is appended. Otherwise the
|
|
18
|
+
* candidate self-collides at tier 1 and cascades unnecessarily. The install
|
|
19
|
+
* pre-flight maintains two inventory views — `existingInventory` for
|
|
20
|
+
* suggestion generation, `augmentedInventory` for `detectCollisions`.
|
|
21
|
+
*
|
|
22
|
+
* `shortHash` derivation: first 4 hex chars of
|
|
23
|
+
* sha256(`${authorPath}/${token}/${packDomain}`)
|
|
24
|
+
*
|
|
25
|
+
* Birthday-bound collision-free for inventories <10k entries (Wave 0 spike
|
|
26
|
+
* §4 — measured 0% on 36-skill fixture, theoretical bound holds).
|
|
27
|
+
*
|
|
28
|
+
* Plan: docs/internal/implementation/smi-4588-rename-engine-ledger-install.md §1.
|
|
29
|
+
*/
|
|
30
|
+
import * as crypto from 'node:crypto';
|
|
31
|
+
const SANITIZE_MAX_LENGTH = 256;
|
|
32
|
+
/**
|
|
33
|
+
* Compute the deterministic 4-char `shortHash` suffix used at chain tier 3.
|
|
34
|
+
* Exported for tests; in normal flow callers use `generateSuggestionChain`.
|
|
35
|
+
*/
|
|
36
|
+
export function computeShortHash(authorPath, token, packDomain) {
|
|
37
|
+
const input = `${authorPath}/${token}/${packDomain ?? ''}`;
|
|
38
|
+
return crypto.createHash('sha256').update(input).digest('hex').slice(0, 4);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Sanitize an author / tag / token segment for safe use in an identifier.
|
|
42
|
+
* Lowercases, replaces non-`[a-z0-9]` runs with `-`, trims, and dedupes
|
|
43
|
+
* consecutive separators. Mirrors the rule in plan §1 step 1.
|
|
44
|
+
*/
|
|
45
|
+
export function sanitizeSegment(raw) {
|
|
46
|
+
// Defense-in-depth length cap (SMI-4733): guards against polynomial
|
|
47
|
+
// backtracking on the regex chain below when callers pass unbounded
|
|
48
|
+
// input (e.g. `packDomain` from manifest, `token` from skillId). An
|
|
49
|
+
// empty segment falls through tier construction in
|
|
50
|
+
// `generateSuggestionChain` — same fall-through behavior as a
|
|
51
|
+
// pathologically un-sanitizable input.
|
|
52
|
+
if (raw.length > SANITIZE_MAX_LENGTH) {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
return raw
|
|
56
|
+
.toLowerCase()
|
|
57
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
58
|
+
.replace(/^-+|-+$/g, '')
|
|
59
|
+
.replace(/-{2,}/g, '-');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* `existingInventory` collides with `candidate` when ANY entry has an
|
|
63
|
+
* identifier that case-insensitively equals `candidate`. The check is
|
|
64
|
+
* O(n) per candidate; chain depth is capped at 3 so worst case is O(3n).
|
|
65
|
+
*/
|
|
66
|
+
function collides(candidate, inventory) {
|
|
67
|
+
const needle = candidate.toLowerCase();
|
|
68
|
+
for (const entry of inventory) {
|
|
69
|
+
if (entry.identifier.toLowerCase() === needle) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Walk the 3-tier rename fall-through chain (decision #11). Returns up to
|
|
77
|
+
* 3 ordered candidates and an `exhausted` flag. The caller picks the first
|
|
78
|
+
* non-colliding candidate as the recommended rename.
|
|
79
|
+
*
|
|
80
|
+
* Returns an empty `candidates` array iff `token` itself sanitizes to an
|
|
81
|
+
* empty string (defensive — pathological inputs).
|
|
82
|
+
*/
|
|
83
|
+
export function generateSuggestionChain(input) {
|
|
84
|
+
const token = sanitizeSegment(input.token);
|
|
85
|
+
if (token.length === 0) {
|
|
86
|
+
return { candidates: [], exhausted: true };
|
|
87
|
+
}
|
|
88
|
+
const sanitizedAuthor = input.author ? sanitizeSegment(input.author) : '';
|
|
89
|
+
const sanitizedTag = input.tagFallback ? sanitizeSegment(input.tagFallback) : '';
|
|
90
|
+
const prefix = sanitizedAuthor.length > 0 ? sanitizedAuthor : sanitizedTag;
|
|
91
|
+
// No usable author OR tag fallback → emit a `local-` prefix at tier 1
|
|
92
|
+
// (matches plan §1's third resolution path). Tiers 2 + 3 also fall back
|
|
93
|
+
// to `local-` since neither author nor packDomain can be derived.
|
|
94
|
+
const tierPrefix = prefix.length > 0 ? prefix : 'local';
|
|
95
|
+
const sanitizedPack = input.packDomain ? sanitizeSegment(input.packDomain) : '';
|
|
96
|
+
const shortHash = computeShortHash(input.authorPath, token, sanitizedPack || null);
|
|
97
|
+
// Tier 1: `${prefix}-${token}`
|
|
98
|
+
const tier1 = `${tierPrefix}-${token}`;
|
|
99
|
+
// Tier 2: `${prefix}-${packDomain}-${token}` (skipped when packDomain absent)
|
|
100
|
+
const tier2 = sanitizedPack.length > 0 ? `${tierPrefix}-${sanitizedPack}-${token}` : null;
|
|
101
|
+
// Tier 3: `${prefix}-${packDomain}-${token}-${shortHash}`
|
|
102
|
+
// packDomain segment is included only when available.
|
|
103
|
+
const tier3 = sanitizedPack.length > 0
|
|
104
|
+
? `${tierPrefix}-${sanitizedPack}-${token}-${shortHash}`
|
|
105
|
+
: `${tierPrefix}-${token}-${shortHash}`;
|
|
106
|
+
// Build the candidate list, dropping any null tier and de-duplicating
|
|
107
|
+
// (tier 2 and tier 3 are identical when packDomain is absent — the dedup
|
|
108
|
+
// ensures the agent doesn't see two equal candidates).
|
|
109
|
+
const rawCandidates = [tier1, tier2, tier3].filter((c) => c !== null);
|
|
110
|
+
const candidates = [];
|
|
111
|
+
for (const c of rawCandidates) {
|
|
112
|
+
if (!candidates.includes(c)) {
|
|
113
|
+
candidates.push(c);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Walk the chain — first non-collider wins; if all collide, the chain is
|
|
117
|
+
// exhausted and the agent must escalate via `customName`.
|
|
118
|
+
const exhausted = candidates.every((c) => collides(c, input.existingInventory));
|
|
119
|
+
return { candidates, exhausted };
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=suggestion-chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggestion-chain.js","sourceRoot":"","sources":["../../../src/audit/suggestion-chain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Audit-tool dispatch for the Skillsmith MCP server
|
|
3
|
+
* @module @skillsmith/mcp-server/audit-tool-dispatch
|
|
4
|
+
*
|
|
5
|
+
* SMI-4590 Wave 4 Step 0b: extracted from `tool-dispatch.ts` to keep the
|
|
6
|
+
* parent dispatcher under the 500-LOC file-size gate.
|
|
7
|
+
*
|
|
8
|
+
* Wave 4 PR 4 (this PR) adds three new tools:
|
|
9
|
+
* - `skill_inventory_audit` — full inventory audit (always registered)
|
|
10
|
+
* - `apply_namespace_rename` — apply a Wave 2 rename (always registered)
|
|
11
|
+
* - `apply_recommended_edit` — apply a Wave 3 prose edit; **registered
|
|
12
|
+
* iff `APPLY_TEMPLATE_REGISTRY.size > 0`** (defense-in-depth — if the
|
|
13
|
+
* registry ever empties via rollback, the tool unregisters itself and
|
|
14
|
+
* the audit-report writer surfaces edits as `manual_review` only).
|
|
15
|
+
*
|
|
16
|
+
* Surface: handles dispatch for all audit-family tools. The parent
|
|
17
|
+
* `tool-dispatch.ts` delegates by name match against {@link AUDIT_TOOL_NAMES};
|
|
18
|
+
* this module owns the audit case bodies, license + quota wiring (for the
|
|
19
|
+
* pre-existing `skill_audit` / `skill_pack_audit` cases), and Zod parse
|
|
20
|
+
* error envelopes.
|
|
21
|
+
*
|
|
22
|
+
* Dispatch responses for the three new tools follow the
|
|
23
|
+
* `safeParseOrError` pattern (see `validation.ts`) for protocol-level
|
|
24
|
+
* shape errors, AND embed an application-level `success: false` envelope
|
|
25
|
+
* inside `content[0].text` for domain-level failures (history not found,
|
|
26
|
+
* subcall failed). MCP clients introspect both.
|
|
27
|
+
*/
|
|
28
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
29
|
+
import type { ToolContext } from './context.js';
|
|
30
|
+
import type { LicenseMiddleware } from './middleware/license.js';
|
|
31
|
+
import type { QuotaMiddleware } from './middleware/quota.js';
|
|
32
|
+
/**
|
|
33
|
+
* Tool names handled by this dispatcher. The parent `tool-dispatch.ts`
|
|
34
|
+
* delegates iff the requested tool name is in this set.
|
|
35
|
+
*
|
|
36
|
+
* `apply_recommended_edit` is conditionally included based on
|
|
37
|
+
* `APPLY_TEMPLATE_REGISTRY.size`. When the registry is empty (rollback
|
|
38
|
+
* scenario), the name is omitted from this set AND
|
|
39
|
+
* {@link dispatchAuditTool} returns the standard "Unknown audit tool"
|
|
40
|
+
* error if the dispatcher is somehow reached for that name.
|
|
41
|
+
*/
|
|
42
|
+
export declare const AUDIT_TOOL_NAMES: ReadonlySet<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Returns true if `name` is an audit-family tool dispatched by this module.
|
|
45
|
+
* Parent dispatcher uses this to route — keeping the routing predicate
|
|
46
|
+
* colocated with the case bodies prevents drift.
|
|
47
|
+
*/
|
|
48
|
+
export declare function isAuditToolName(name: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Dispatch an audit-family tool call. Caller must check {@link isAuditToolName}
|
|
51
|
+
* before invoking; unrecognized names throw `Error('Unknown audit tool: <name>')`.
|
|
52
|
+
*
|
|
53
|
+
* @param name MCP tool name (must be in {@link AUDIT_TOOL_NAMES}).
|
|
54
|
+
* @param args Raw tool arguments from the request.
|
|
55
|
+
* @param toolContext Initialized database + repository context.
|
|
56
|
+
* @param licenseMiddleware License validation middleware instance.
|
|
57
|
+
* @param quotaMiddleware Quota enforcement middleware instance.
|
|
58
|
+
* @returns MCP tool response.
|
|
59
|
+
*/
|
|
60
|
+
export declare function dispatchAuditTool(name: string, args: Record<string, unknown> | undefined, toolContext: ToolContext, licenseMiddleware: LicenseMiddleware, quotaMiddleware: QuotaMiddleware): Promise<CallToolResult>;
|
|
61
|
+
//# sourceMappingURL=audit-tool-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-tool-dispatch.d.ts","sourceRoot":"","sources":["../../src/audit-tool-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAA;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAQ/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAA0C,CAAA;AAqB3F;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAaD;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACzC,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,cAAc,CAAC,CAyCzB"}
|