@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 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap-unmanaged.js","sourceRoot":"","sources":["../../../src/audit/bootstrap-unmanaged.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGlD,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AA+BlE;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAqB;IACpD,OAAO,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAA;AACtD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,SAAwC,EACxC,OAAkC,EAAE;IAEpC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,+BAA+B,CAAA;IACvE,MAAM,QAAQ,GAAkB,EAAE,CAAA;IAClC,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,IAAI,SAAS,GAAG,CAAC,CAAA;IAEjB,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;YAAE,SAAQ;QACtC,SAAS,EAAE,CAAA;QACX,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,KAAK,CAAC,CAAA;YACxB,SAAS,EAAE,CAAA;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAChE,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,aAAa,CAAC,gBAAgB;gBACpC,OAAO,EAAE,wBAAwB,KAAK,CAAC,WAAW,KAAK,OAAO,EAAE;gBAChE,OAAO,EAAE;oBACP,WAAW,EAAE,KAAK,CAAC,WAAW;oBAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,KAAK,EAAE,OAAO;iBACf;aACF,CAAC,CAAA;YACF,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,kBAAkB,EAAE;gBACvC,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,KAAK,EAAE,OAAO;aACf,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAA;AAC3C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,UAAU,+BAA+B,CAAC,KAAqB;IAClE,MAAM,OAAO,CAAC,OAAO,CACnB,eAAe,CAAC,KAAK,CAAC,WAAW,EAAE;QACjC,gBAAgB;KACjB,CAAC,CACH,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Three-pass collision detector for the consumer namespace
|
|
3
|
+
* audit. Wave 1 PR1+PR2 ship the exact + generic passes;
|
|
4
|
+
* PR #3 wires the semantic pass (gated by audit_mode) +
|
|
5
|
+
* unmanaged-skill bootstrap + audit-mode resolver dispatch.
|
|
6
|
+
* @module @skillsmith/mcp-server/audit/collision-detector
|
|
7
|
+
* @see SMI-4587
|
|
8
|
+
*
|
|
9
|
+
* The detector is detection-only — file mutation lives in Wave 2's
|
|
10
|
+
* rename engine. Each pass is independently invocable for testing.
|
|
11
|
+
*
|
|
12
|
+
* Audit-mode dispatch (plan §6b):
|
|
13
|
+
* - 'off' -> short-circuit, empty result, no telemetry
|
|
14
|
+
* - 'preventative' -> exact + generic only (no embedding service)
|
|
15
|
+
* - 'power_user' / 'governance' -> + semantic-overlap pass via OverlapDetector
|
|
16
|
+
*
|
|
17
|
+
* Latency invariant (plan §426): in `preventative` mode the
|
|
18
|
+
* `OverlapDetector` is **not instantiated** and `EmbeddingService` is
|
|
19
|
+
* **not touched**. Tests assert zero invocations.
|
|
20
|
+
*/
|
|
21
|
+
import { type AuditMode } from '@skillsmith/core/config/audit-mode';
|
|
22
|
+
import type { Tier as AuditModeTier } from '@skillsmith/core/config/audit-mode';
|
|
23
|
+
import type { InventoryEntry, ScanWarning } from '../utils/local-inventory.types.js';
|
|
24
|
+
import type { InventoryAuditResult } from './collision-detector.types.js';
|
|
25
|
+
import { type BootstrapFn } from './bootstrap-unmanaged.js';
|
|
26
|
+
export interface DetectCollisionsOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Pre-allocated audit id. Useful when the caller wants the id to flow
|
|
29
|
+
* into telemetry / report-writer alongside the detector result.
|
|
30
|
+
* Defaults to a fresh ULID.
|
|
31
|
+
*/
|
|
32
|
+
auditId?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Subscription tier of the caller. Drives the default audit mode via
|
|
35
|
+
* {@link resolveAuditMode}. When omitted, defaults to `'community'`
|
|
36
|
+
* (the cheapest fail-safe).
|
|
37
|
+
*/
|
|
38
|
+
tier?: AuditModeTier;
|
|
39
|
+
/**
|
|
40
|
+
* Explicit audit-mode override (read by the caller from
|
|
41
|
+
* `~/.skillsmith/config.json` `audit_mode` or `SKILLSMITH_AUDIT_MODE`).
|
|
42
|
+
* When set + valid, this beats the tier default.
|
|
43
|
+
*/
|
|
44
|
+
auditModeOverride?: AuditMode | null;
|
|
45
|
+
/**
|
|
46
|
+
* Bootstrap callback for unmanaged SKILL.md entries (Step 6a). Defaults
|
|
47
|
+
* to a no-op until PR #4 wires the real `indexLocalSkill` core helper.
|
|
48
|
+
*/
|
|
49
|
+
bootstrapFn?: BootstrapFn;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Run the configured collision-detection passes over an inventory
|
|
53
|
+
* snapshot.
|
|
54
|
+
*
|
|
55
|
+
* Returns an `InventoryAuditResult` whose `summary.passDurations` records
|
|
56
|
+
* the wall-clock cost of each pass. The semantic pass duration is `0`
|
|
57
|
+
* when the resolved audit-mode short-circuits past it (preventative /
|
|
58
|
+
* off).
|
|
59
|
+
*/
|
|
60
|
+
export declare function detectCollisions(inventory: ReadonlyArray<InventoryEntry>, opts?: DetectCollisionsOptions): Promise<InventoryAuditResult>;
|
|
61
|
+
/**
|
|
62
|
+
* Internal hook used by tests + PR #4 report writer. Returns the
|
|
63
|
+
* bootstrap warnings produced by the most recent `detectCollisions`
|
|
64
|
+
* call. Returns an empty array when the most recent call short-circuited
|
|
65
|
+
* (`auditMode === 'off'`) or no unmanaged skills failed to bootstrap.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getLastBootstrapWarnings(): ReadonlyArray<ScanWarning>;
|
|
68
|
+
export type { ExactCollisionFlag, GenericTokenFlag, InventoryAuditResult, SemanticCollisionFlag, } from './collision-detector.types.js';
|
|
69
|
+
export { detectExactCollisions, detectGenericTokenFlags } from './collision-detector.helpers.js';
|
|
70
|
+
export { bootstrapUnmanagedSkills, isUnmanagedSkill } from './bootstrap-unmanaged.js';
|
|
71
|
+
export type { BootstrapFn } from './bootstrap-unmanaged.js';
|
|
72
|
+
//# sourceMappingURL=collision-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collision-detector.d.ts","sourceRoot":"","sources":["../../../src/audit/collision-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,oCAAoC,CAAA;AACrF,OAAO,KAAK,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,oCAAoC,CAAA;AAE/E,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;AACpF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AAGzE,OAAO,EAA4B,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAIrF,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,IAAI,CAAC,EAAE,aAAa,CAAA;IACpB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,EACxC,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,oBAAoB,CAAC,CAyG/B;AAWD;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,aAAa,CAAC,WAAW,CAAC,CAErE;AAqCD,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAChG,OAAO,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AACrF,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure pass functions for the collision detector
|
|
3
|
+
* (SMI-4587 Wave 1 Steps 4–5).
|
|
4
|
+
* @module @skillsmith/mcp-server/audit/collision-detector.helpers
|
|
5
|
+
*
|
|
6
|
+
* Each pass is a pure function over `InventoryEntry[]`. The orchestrator
|
|
7
|
+
* (`collision-detector.ts`) wires them together. Wave 1 PR1 shipped the
|
|
8
|
+
* exact-name pass; this file now also exposes the generic-token pass
|
|
9
|
+
* (Step 5). Semantic pass lands in a subsequent PR.
|
|
10
|
+
*/
|
|
11
|
+
import type { InventoryEntry } from '../utils/local-inventory.types.js';
|
|
12
|
+
import type { AuditId, ExactCollisionFlag, GenericTokenFlag } from './collision-detector.types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Stable pack-name input passed to {@link derivePackDomain} when running
|
|
15
|
+
* the generic-token pass over the user's local inventory. The user's
|
|
16
|
+
* `~/.claude/` install has no single pack name — using a non-suffixed
|
|
17
|
+
* sentinel forces `derivePackDomain` to fall through Strategy 1 (which
|
|
18
|
+
* keys off `-skills` suffixes) and rely on Strategy 2 (mode of per-entry
|
|
19
|
+
* tags). Centralized here so plan + tests share the same constant.
|
|
20
|
+
*/
|
|
21
|
+
export declare const LOCAL_INVENTORY_PACK_NAME = "local-inventory";
|
|
22
|
+
/**
|
|
23
|
+
* Normalize an identifier for case-insensitive equality. Mirrors the
|
|
24
|
+
* normalization OverlapDetector applies for exact-match comparisons
|
|
25
|
+
* (`OverlapDetector.ts:180-183`).
|
|
26
|
+
*/
|
|
27
|
+
export declare function normalizeIdentifier(id: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Group entries by normalized `identifier`. Returns a Map keyed by the
|
|
30
|
+
* normalized form so callers can find sets-of-2-or-more in O(n).
|
|
31
|
+
*/
|
|
32
|
+
export declare function groupByIdentifier(entries: ReadonlyArray<InventoryEntry>): Map<string, InventoryEntry[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Detect exact-name collisions across the inventory.
|
|
35
|
+
*
|
|
36
|
+
* A collision is two or more entries that share the same normalized
|
|
37
|
+
* `identifier` (case-insensitive, trimmed). Severity is always `error`.
|
|
38
|
+
*
|
|
39
|
+
* Pure O(n) — single Map pass over the input. Each returned flag carries
|
|
40
|
+
* a `collisionId` derived via `deriveCollisionId(auditId, entries)` so
|
|
41
|
+
* Wave 2's ledger can look it up by id.
|
|
42
|
+
*/
|
|
43
|
+
export declare function detectExactCollisions(inventory: ReadonlyArray<InventoryEntry>, auditId: string): ExactCollisionFlag[];
|
|
44
|
+
/**
|
|
45
|
+
* Detect generic-trigger-word flags across the local inventory.
|
|
46
|
+
*
|
|
47
|
+
* Wraps {@link detectGenericTriggerWords} (the existing skill-pack-audit
|
|
48
|
+
* helper) and adapts the per-skill flag shape to this audit's
|
|
49
|
+
* {@link GenericTokenFlag}. Severity is always `warning` here — even
|
|
50
|
+
* skill-name hits, which the pack helper raises as `error`, are demoted
|
|
51
|
+
* to `warning` because the inventory audit is detection-only and the
|
|
52
|
+
* user's existing local install is grandfathered in (rename is opt-in
|
|
53
|
+
* via Wave 2's apply path).
|
|
54
|
+
*
|
|
55
|
+
* `packDomain` is computed once over the entire inventory using
|
|
56
|
+
* {@link derivePackDomain} with a stable sentinel pack name; Strategy 2
|
|
57
|
+
* (mode-of-tags) is the load-bearing branch since the user's inventory
|
|
58
|
+
* has no single pack name. The same `packDomain` is then passed into
|
|
59
|
+
* every per-entry call, so suggestions like `${packDomain}-${token}`
|
|
60
|
+
* are consistent across the report.
|
|
61
|
+
*/
|
|
62
|
+
export declare function detectGenericTokenFlags(inventory: ReadonlyArray<InventoryEntry>, auditId: AuditId): GenericTokenFlag[];
|
|
63
|
+
//# sourceMappingURL=collision-detector.helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collision-detector.helpers.d.ts","sourceRoot":"","sources":["../../../src/audit/collision-detector.helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAA;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAIlG;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,oBAAoB,CAAA;AAE1D;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,CAAC,cAAc,CAAC,GACrC,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAa/B;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,EACxC,OAAO,EAAE,MAAM,GACd,kBAAkB,EAAE,CAoBtB;AAiBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,EACxC,OAAO,EAAE,OAAO,GACf,gBAAgB,EAAE,CAiCpB"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure pass functions for the collision detector
|
|
3
|
+
* (SMI-4587 Wave 1 Steps 4–5).
|
|
4
|
+
* @module @skillsmith/mcp-server/audit/collision-detector.helpers
|
|
5
|
+
*
|
|
6
|
+
* Each pass is a pure function over `InventoryEntry[]`. The orchestrator
|
|
7
|
+
* (`collision-detector.ts`) wires them together. Wave 1 PR1 shipped the
|
|
8
|
+
* exact-name pass; this file now also exposes the generic-token pass
|
|
9
|
+
* (Step 5). Semantic pass lands in a subsequent PR.
|
|
10
|
+
*/
|
|
11
|
+
import { GENERIC_TRIGGERS } from '@skillsmith/core';
|
|
12
|
+
import { deriveCollisionId } from './audit-history.js';
|
|
13
|
+
import { derivePackDomain, detectGenericTriggerWords } from '../tools/skill-pack-audit.helpers.js';
|
|
14
|
+
/**
|
|
15
|
+
* Stable pack-name input passed to {@link derivePackDomain} when running
|
|
16
|
+
* the generic-token pass over the user's local inventory. The user's
|
|
17
|
+
* `~/.claude/` install has no single pack name — using a non-suffixed
|
|
18
|
+
* sentinel forces `derivePackDomain` to fall through Strategy 1 (which
|
|
19
|
+
* keys off `-skills` suffixes) and rely on Strategy 2 (mode of per-entry
|
|
20
|
+
* tags). Centralized here so plan + tests share the same constant.
|
|
21
|
+
*/
|
|
22
|
+
export const LOCAL_INVENTORY_PACK_NAME = 'local-inventory';
|
|
23
|
+
/**
|
|
24
|
+
* Normalize an identifier for case-insensitive equality. Mirrors the
|
|
25
|
+
* normalization OverlapDetector applies for exact-match comparisons
|
|
26
|
+
* (`OverlapDetector.ts:180-183`).
|
|
27
|
+
*/
|
|
28
|
+
export function normalizeIdentifier(id) {
|
|
29
|
+
return id.trim().toLowerCase();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Group entries by normalized `identifier`. Returns a Map keyed by the
|
|
33
|
+
* normalized form so callers can find sets-of-2-or-more in O(n).
|
|
34
|
+
*/
|
|
35
|
+
export function groupByIdentifier(entries) {
|
|
36
|
+
const groups = new Map();
|
|
37
|
+
for (const entry of entries) {
|
|
38
|
+
const key = normalizeIdentifier(entry.identifier);
|
|
39
|
+
if (!key)
|
|
40
|
+
continue; // empty/whitespace identifier — skip silently
|
|
41
|
+
const bucket = groups.get(key);
|
|
42
|
+
if (bucket) {
|
|
43
|
+
bucket.push(entry);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
groups.set(key, [entry]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return groups;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Detect exact-name collisions across the inventory.
|
|
53
|
+
*
|
|
54
|
+
* A collision is two or more entries that share the same normalized
|
|
55
|
+
* `identifier` (case-insensitive, trimmed). Severity is always `error`.
|
|
56
|
+
*
|
|
57
|
+
* Pure O(n) — single Map pass over the input. Each returned flag carries
|
|
58
|
+
* a `collisionId` derived via `deriveCollisionId(auditId, entries)` so
|
|
59
|
+
* Wave 2's ledger can look it up by id.
|
|
60
|
+
*/
|
|
61
|
+
export function detectExactCollisions(inventory, auditId) {
|
|
62
|
+
const groups = groupByIdentifier(inventory);
|
|
63
|
+
const flags = [];
|
|
64
|
+
for (const [, bucket] of groups) {
|
|
65
|
+
if (bucket.length < 2)
|
|
66
|
+
continue;
|
|
67
|
+
const reason = describeCollision(bucket);
|
|
68
|
+
flags.push({
|
|
69
|
+
kind: 'exact',
|
|
70
|
+
collisionId: deriveCollisionId(auditId, bucket),
|
|
71
|
+
identifier: bucket[0]?.identifier ?? '',
|
|
72
|
+
entries: bucket,
|
|
73
|
+
severity: 'error',
|
|
74
|
+
reason,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
// Stable ordering for downstream consumers (report writer relies on this).
|
|
78
|
+
flags.sort((a, b) => a.identifier.localeCompare(b.identifier));
|
|
79
|
+
return flags;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Build the human-readable `reason` string for an exact collision. The
|
|
83
|
+
* message lists the colliding kinds + count so the audit report can
|
|
84
|
+
* render it without re-walking the entries array.
|
|
85
|
+
*/
|
|
86
|
+
function describeCollision(entries) {
|
|
87
|
+
const kinds = new Set(entries.map((e) => e.kind));
|
|
88
|
+
if (kinds.size === 1) {
|
|
89
|
+
const k = entries[0]?.kind ?? 'entry';
|
|
90
|
+
return `${entries.length} ${k}s share the same identifier "${entries[0]?.identifier ?? ''}"`;
|
|
91
|
+
}
|
|
92
|
+
const kindList = [...kinds].sort().join(' / ');
|
|
93
|
+
return `${entries.length} entries (${kindList}) share the same identifier "${entries[0]?.identifier ?? ''}"`;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Detect generic-trigger-word flags across the local inventory.
|
|
97
|
+
*
|
|
98
|
+
* Wraps {@link detectGenericTriggerWords} (the existing skill-pack-audit
|
|
99
|
+
* helper) and adapts the per-skill flag shape to this audit's
|
|
100
|
+
* {@link GenericTokenFlag}. Severity is always `warning` here — even
|
|
101
|
+
* skill-name hits, which the pack helper raises as `error`, are demoted
|
|
102
|
+
* to `warning` because the inventory audit is detection-only and the
|
|
103
|
+
* user's existing local install is grandfathered in (rename is opt-in
|
|
104
|
+
* via Wave 2's apply path).
|
|
105
|
+
*
|
|
106
|
+
* `packDomain` is computed once over the entire inventory using
|
|
107
|
+
* {@link derivePackDomain} with a stable sentinel pack name; Strategy 2
|
|
108
|
+
* (mode-of-tags) is the load-bearing branch since the user's inventory
|
|
109
|
+
* has no single pack name. The same `packDomain` is then passed into
|
|
110
|
+
* every per-entry call, so suggestions like `${packDomain}-${token}`
|
|
111
|
+
* are consistent across the report.
|
|
112
|
+
*/
|
|
113
|
+
export function detectGenericTokenFlags(inventory, auditId) {
|
|
114
|
+
const stoplist = GENERIC_TRIGGERS;
|
|
115
|
+
const tagBag = inventory.map((e) => ({ tags: e.meta?.tags }));
|
|
116
|
+
const packDomain = derivePackDomain(LOCAL_INVENTORY_PACK_NAME, tagBag, stoplist);
|
|
117
|
+
const flags = [];
|
|
118
|
+
for (const entry of inventory) {
|
|
119
|
+
const wordFlags = detectGenericTriggerWords(entry.meta?.description, entry.identifier, packDomain, stoplist);
|
|
120
|
+
for (const wf of wordFlags) {
|
|
121
|
+
flags.push({
|
|
122
|
+
kind: 'generic',
|
|
123
|
+
collisionId: deriveCollisionId(auditId, [entry]),
|
|
124
|
+
identifier: entry.identifier,
|
|
125
|
+
entry,
|
|
126
|
+
matchedTokens: [wf.token],
|
|
127
|
+
severity: 'warning',
|
|
128
|
+
reason: wf.reason,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Stable ordering for downstream consumers: identifier asc, then token asc.
|
|
133
|
+
flags.sort((a, b) => {
|
|
134
|
+
const byId = a.identifier.localeCompare(b.identifier);
|
|
135
|
+
if (byId !== 0)
|
|
136
|
+
return byId;
|
|
137
|
+
return (a.matchedTokens[0] ?? '').localeCompare(b.matchedTokens[0] ?? '');
|
|
138
|
+
});
|
|
139
|
+
return flags;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=collision-detector.helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collision-detector.helpers.js","sourceRoot":"","sources":["../../../src/audit/collision-detector.helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Three-pass collision detector for the consumer namespace
|
|
3
|
+
* audit. Wave 1 PR1+PR2 ship the exact + generic passes;
|
|
4
|
+
* PR #3 wires the semantic pass (gated by audit_mode) +
|
|
5
|
+
* unmanaged-skill bootstrap + audit-mode resolver dispatch.
|
|
6
|
+
* @module @skillsmith/mcp-server/audit/collision-detector
|
|
7
|
+
* @see SMI-4587
|
|
8
|
+
*
|
|
9
|
+
* The detector is detection-only — file mutation lives in Wave 2's
|
|
10
|
+
* rename engine. Each pass is independently invocable for testing.
|
|
11
|
+
*
|
|
12
|
+
* Audit-mode dispatch (plan §6b):
|
|
13
|
+
* - 'off' -> short-circuit, empty result, no telemetry
|
|
14
|
+
* - 'preventative' -> exact + generic only (no embedding service)
|
|
15
|
+
* - 'power_user' / 'governance' -> + semantic-overlap pass via OverlapDetector
|
|
16
|
+
*
|
|
17
|
+
* Latency invariant (plan §426): in `preventative` mode the
|
|
18
|
+
* `OverlapDetector` is **not instantiated** and `EmbeddingService` is
|
|
19
|
+
* **not touched**. Tests assert zero invocations.
|
|
20
|
+
*/
|
|
21
|
+
import { OverlapDetector } from '@skillsmith/core';
|
|
22
|
+
import { resolveAuditMode } from '@skillsmith/core/config/audit-mode';
|
|
23
|
+
import { detectExactCollisions, detectGenericTokenFlags } from './collision-detector.helpers.js';
|
|
24
|
+
import { newAuditId } from './audit-history.js';
|
|
25
|
+
import { bootstrapUnmanagedSkills } from './bootstrap-unmanaged.js';
|
|
26
|
+
import { detectSemanticCollisions } from './collision-detector.semantic.helpers.js';
|
|
27
|
+
import { emitAuditCompleteEvent } from '../tools/namespace-audit/telemetry.js';
|
|
28
|
+
/**
|
|
29
|
+
* Run the configured collision-detection passes over an inventory
|
|
30
|
+
* snapshot.
|
|
31
|
+
*
|
|
32
|
+
* Returns an `InventoryAuditResult` whose `summary.passDurations` records
|
|
33
|
+
* the wall-clock cost of each pass. The semantic pass duration is `0`
|
|
34
|
+
* when the resolved audit-mode short-circuits past it (preventative /
|
|
35
|
+
* off).
|
|
36
|
+
*/
|
|
37
|
+
export async function detectCollisions(inventory, opts = {}) {
|
|
38
|
+
const startedAt = process.hrtime.bigint();
|
|
39
|
+
const auditId = (opts.auditId ?? newAuditId());
|
|
40
|
+
// Step 6b: resolve the audit mode before any pass runs.
|
|
41
|
+
const auditMode = resolveAuditMode({
|
|
42
|
+
tier: opts.tier ?? 'community',
|
|
43
|
+
override: opts.auditModeOverride ?? null,
|
|
44
|
+
});
|
|
45
|
+
// Step 6b: 'off' short-circuits — empty result, zero passes, no
|
|
46
|
+
// telemetry. The orchestrator returns immediately so callers can
|
|
47
|
+
// safely no-op.
|
|
48
|
+
if (auditMode === 'off') {
|
|
49
|
+
return emptyResult(auditId, inventory);
|
|
50
|
+
}
|
|
51
|
+
// Bootstrap warnings flow into the audit result via the report writer
|
|
52
|
+
// in PR #4 (Step 8). Until then we collect them locally so the surface
|
|
53
|
+
// is stable; tests assert on the collected list via a helper.
|
|
54
|
+
const bootstrapWarnings = [];
|
|
55
|
+
// Step 6a: bootstrap unmanaged skills before the exact pass so any
|
|
56
|
+
// newly-discovered manifest data shows up as `meta.author` on
|
|
57
|
+
// subsequent re-scans (handled by the caller — this PR only plumbs).
|
|
58
|
+
const bootstrap = await bootstrapUnmanagedSkills(inventory, {
|
|
59
|
+
bootstrapFn: opts.bootstrapFn,
|
|
60
|
+
});
|
|
61
|
+
bootstrapWarnings.push(...bootstrap.warnings);
|
|
62
|
+
// Step 4: exact-name pass.
|
|
63
|
+
const exactStart = process.hrtime.bigint();
|
|
64
|
+
const exactCollisions = detectExactCollisions(inventory, auditId);
|
|
65
|
+
const exactDuration = nsToMs(process.hrtime.bigint() - exactStart);
|
|
66
|
+
// Step 5: generic-token pass.
|
|
67
|
+
const genericStart = process.hrtime.bigint();
|
|
68
|
+
const genericFlags = detectGenericTokenFlags(inventory, auditId);
|
|
69
|
+
const genericDuration = nsToMs(process.hrtime.bigint() - genericStart);
|
|
70
|
+
// Step 6: semantic-overlap pass — only when the resolved mode opts in.
|
|
71
|
+
// Latency invariant: instantiate `OverlapDetector` only when needed
|
|
72
|
+
// so `EmbeddingService` is never touched in `preventative` mode.
|
|
73
|
+
let semanticCollisions = [];
|
|
74
|
+
let semanticDuration = 0;
|
|
75
|
+
if (needsSemanticPass(auditMode)) {
|
|
76
|
+
const detector = new OverlapDetector();
|
|
77
|
+
try {
|
|
78
|
+
const semanticStart = process.hrtime.bigint();
|
|
79
|
+
semanticCollisions = await detectSemanticCollisions(inventory, exactCollisions, auditId, detector);
|
|
80
|
+
semanticDuration = nsToMs(process.hrtime.bigint() - semanticStart);
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
detector.close();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const totalDuration = nsToMs(process.hrtime.bigint() - startedAt);
|
|
87
|
+
const errorCount = exactCollisions.length;
|
|
88
|
+
const warningCount = genericFlags.length + semanticCollisions.length;
|
|
89
|
+
// bootstrapWarnings is collected for PR #4's report writer; emitted
|
|
90
|
+
// through `getLastBootstrapWarnings()` to avoid widening the public
|
|
91
|
+
// result shape ahead of Step 8.
|
|
92
|
+
lastBootstrapWarnings = bootstrapWarnings;
|
|
93
|
+
const result = {
|
|
94
|
+
auditId,
|
|
95
|
+
inventory: [...inventory],
|
|
96
|
+
exactCollisions,
|
|
97
|
+
genericFlags,
|
|
98
|
+
semanticCollisions,
|
|
99
|
+
summary: {
|
|
100
|
+
totalEntries: inventory.length,
|
|
101
|
+
totalFlags: errorCount + warningCount,
|
|
102
|
+
errorCount,
|
|
103
|
+
warningCount,
|
|
104
|
+
durationMs: totalDuration,
|
|
105
|
+
passDurations: {
|
|
106
|
+
exact: exactDuration,
|
|
107
|
+
generic: genericDuration,
|
|
108
|
+
semantic: semanticDuration,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
// Step 8a: aggregate-only server telemetry (decision #7). Never emits
|
|
113
|
+
// when audit_mode is 'off' (handled by both the short-circuit above and
|
|
114
|
+
// a defense-in-depth check inside `emitAuditCompleteEvent`). Wave 1
|
|
115
|
+
// ships zeroed resolution counters; Wave 2's rename engine wires real
|
|
116
|
+
// values when the apply path lands.
|
|
117
|
+
void emitAuditCompleteEvent(result, {
|
|
118
|
+
tier: opts.tier ?? 'community',
|
|
119
|
+
audit_mode: auditMode,
|
|
120
|
+
resolved_auto: 0,
|
|
121
|
+
resolved_manual: 0,
|
|
122
|
+
resolved_skipped: 0,
|
|
123
|
+
user_id: null,
|
|
124
|
+
});
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Module-private cache of the most recent bootstrap warnings. Tests
|
|
129
|
+
* (and PR #4's report writer) read this immediately after invoking
|
|
130
|
+
* `detectCollisions`. Module-scoped is acceptable because the detector
|
|
131
|
+
* is invoked sequentially per process — there is no concurrency on this
|
|
132
|
+
* surface in Wave 1.
|
|
133
|
+
*/
|
|
134
|
+
let lastBootstrapWarnings = [];
|
|
135
|
+
/**
|
|
136
|
+
* Internal hook used by tests + PR #4 report writer. Returns the
|
|
137
|
+
* bootstrap warnings produced by the most recent `detectCollisions`
|
|
138
|
+
* call. Returns an empty array when the most recent call short-circuited
|
|
139
|
+
* (`auditMode === 'off'`) or no unmanaged skills failed to bootstrap.
|
|
140
|
+
*/
|
|
141
|
+
export function getLastBootstrapWarnings() {
|
|
142
|
+
return lastBootstrapWarnings;
|
|
143
|
+
}
|
|
144
|
+
function needsSemanticPass(mode) {
|
|
145
|
+
return mode === 'power_user' || mode === 'governance';
|
|
146
|
+
}
|
|
147
|
+
function emptyResult(auditId, inventory) {
|
|
148
|
+
// 'off' short-circuit also clears any prior bootstrap warnings so
|
|
149
|
+
// the test-visible state matches the documented "no work" semantics.
|
|
150
|
+
lastBootstrapWarnings = [];
|
|
151
|
+
return {
|
|
152
|
+
auditId,
|
|
153
|
+
inventory: [...inventory],
|
|
154
|
+
exactCollisions: [],
|
|
155
|
+
genericFlags: [],
|
|
156
|
+
semanticCollisions: [],
|
|
157
|
+
summary: {
|
|
158
|
+
totalEntries: 0,
|
|
159
|
+
totalFlags: 0,
|
|
160
|
+
errorCount: 0,
|
|
161
|
+
warningCount: 0,
|
|
162
|
+
durationMs: 0,
|
|
163
|
+
passDurations: { exact: 0, generic: 0, semantic: 0 },
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function nsToMs(ns) {
|
|
168
|
+
return Number(ns) / 1_000_000;
|
|
169
|
+
}
|
|
170
|
+
export { detectExactCollisions, detectGenericTokenFlags } from './collision-detector.helpers.js';
|
|
171
|
+
export { bootstrapUnmanagedSkills, isUnmanagedSkill } from './bootstrap-unmanaged.js';
|
|
172
|
+
//# sourceMappingURL=collision-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collision-detector.js","sourceRoot":"","sources":["../../../src/audit/collision-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Semantic-overlap pass for SMI-4587 Wave 1 Step 6.
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/collision-detector.semantic.helpers
|
|
4
|
+
*
|
|
5
|
+
* Wraps the existing {@link OverlapDetector} from `@skillsmith/core` and
|
|
6
|
+
* adapts inventory entries to the `TriggerPhraseSkill` shape it expects.
|
|
7
|
+
*
|
|
8
|
+
* Latency invariant: this module is **only imported and exercised** when
|
|
9
|
+
* the resolved audit-mode is `power_user` or `governance`. In
|
|
10
|
+
* `preventative` mode the orchestrator skips this path entirely and
|
|
11
|
+
* therefore never instantiates `EmbeddingService` (the load-bearing
|
|
12
|
+
* 5 ms p95 invariant for the cheap mode).
|
|
13
|
+
*
|
|
14
|
+
* Intentional design: the orchestrator constructs `OverlapDetector` once
|
|
15
|
+
* per audit run and disposes it via `close()` after this helper returns.
|
|
16
|
+
* That keeps ONNX model lifetime bounded and avoids two concurrent model
|
|
17
|
+
* instances on memory-constrained machines (per plan §430).
|
|
18
|
+
*/
|
|
19
|
+
import type { OverlapDetector, TriggerPhraseSkill } from '@skillsmith/core';
|
|
20
|
+
import type { InventoryEntry } from '../utils/local-inventory.types.js';
|
|
21
|
+
import type { AuditId, ExactCollisionFlag, SemanticCollisionFlag } from './collision-detector.types.js';
|
|
22
|
+
/**
|
|
23
|
+
* Adapt an {@link InventoryEntry} to the `TriggerPhraseSkill` shape that
|
|
24
|
+
* `OverlapDetector` expects. Uses `source_path` as the stable id so we
|
|
25
|
+
* can map detector results back to the originating inventory entries
|
|
26
|
+
* via a Map keyed off `source_path`.
|
|
27
|
+
*
|
|
28
|
+
* Empty `triggerSurface[]` -> the entry is filtered out upstream because
|
|
29
|
+
* `OverlapDetector.detectOverlap` would produce a 0-overlap result anyway
|
|
30
|
+
* and the iteration cost (O(n^2)) isn't free.
|
|
31
|
+
*/
|
|
32
|
+
export declare function inventoryToTriggerPhraseSkill(entry: InventoryEntry): TriggerPhraseSkill;
|
|
33
|
+
/**
|
|
34
|
+
* Run the semantic-overlap pass over the inventory.
|
|
35
|
+
*
|
|
36
|
+
* Steps:
|
|
37
|
+
* 1. Build an O(1) lookup from `source_path` -> `InventoryEntry`.
|
|
38
|
+
* 2. Adapt entries with non-empty `triggerSurface[]` to
|
|
39
|
+
* `TriggerPhraseSkill[]`.
|
|
40
|
+
* 3. Call `OverlapDetector.findAllOverlaps` once.
|
|
41
|
+
* 4. Map each non-zero overlap result back to a `SemanticCollisionFlag`,
|
|
42
|
+
* skipping pairs already flagged by the exact pass.
|
|
43
|
+
*
|
|
44
|
+
* Disposal of the `OverlapDetector` is the **caller's** responsibility
|
|
45
|
+
* — the orchestrator does it after this function returns so it can
|
|
46
|
+
* also be skipped on the cheap path without double-construction.
|
|
47
|
+
*/
|
|
48
|
+
export declare function detectSemanticCollisions(inventory: ReadonlyArray<InventoryEntry>, exactCollisions: ReadonlyArray<ExactCollisionFlag>, auditId: AuditId, detector: OverlapDetector): Promise<SemanticCollisionFlag[]>;
|
|
49
|
+
//# sourceMappingURL=collision-detector.semantic.helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collision-detector.semantic.helpers.d.ts","sourceRoot":"","sources":["../../../src/audit/collision-detector.semantic.helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAE3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAEvE,OAAO,KAAK,EACV,OAAO,EACP,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,+BAA+B,CAAA;AAEtC;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,cAAc,GAAG,kBAAkB,CAMvF;AAqBD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,EACxC,eAAe,EAAE,aAAa,CAAC,kBAAkB,CAAC,EAClD,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAoDlC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Semantic-overlap pass for SMI-4587 Wave 1 Step 6.
|
|
3
|
+
* @module @skillsmith/mcp-server/audit/collision-detector.semantic.helpers
|
|
4
|
+
*
|
|
5
|
+
* Wraps the existing {@link OverlapDetector} from `@skillsmith/core` and
|
|
6
|
+
* adapts inventory entries to the `TriggerPhraseSkill` shape it expects.
|
|
7
|
+
*
|
|
8
|
+
* Latency invariant: this module is **only imported and exercised** when
|
|
9
|
+
* the resolved audit-mode is `power_user` or `governance`. In
|
|
10
|
+
* `preventative` mode the orchestrator skips this path entirely and
|
|
11
|
+
* therefore never instantiates `EmbeddingService` (the load-bearing
|
|
12
|
+
* 5 ms p95 invariant for the cheap mode).
|
|
13
|
+
*
|
|
14
|
+
* Intentional design: the orchestrator constructs `OverlapDetector` once
|
|
15
|
+
* per audit run and disposes it via `close()` after this helper returns.
|
|
16
|
+
* That keeps ONNX model lifetime bounded and avoids two concurrent model
|
|
17
|
+
* instances on memory-constrained machines (per plan §430).
|
|
18
|
+
*/
|
|
19
|
+
import { deriveCollisionId } from './audit-history.js';
|
|
20
|
+
/**
|
|
21
|
+
* Adapt an {@link InventoryEntry} to the `TriggerPhraseSkill` shape that
|
|
22
|
+
* `OverlapDetector` expects. Uses `source_path` as the stable id so we
|
|
23
|
+
* can map detector results back to the originating inventory entries
|
|
24
|
+
* via a Map keyed off `source_path`.
|
|
25
|
+
*
|
|
26
|
+
* Empty `triggerSurface[]` -> the entry is filtered out upstream because
|
|
27
|
+
* `OverlapDetector.detectOverlap` would produce a 0-overlap result anyway
|
|
28
|
+
* and the iteration cost (O(n^2)) isn't free.
|
|
29
|
+
*/
|
|
30
|
+
export function inventoryToTriggerPhraseSkill(entry) {
|
|
31
|
+
return {
|
|
32
|
+
id: entry.source_path,
|
|
33
|
+
name: entry.identifier,
|
|
34
|
+
triggerPhrases: entry.triggerSurface,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build a Set of "exactly-collided" path-pair keys so the semantic pass
|
|
39
|
+
* can skip pairs already flagged by Step 4. Key format is the sorted
|
|
40
|
+
* pair of source_paths joined by `\x00` (NUL — never appears in paths).
|
|
41
|
+
*/
|
|
42
|
+
function buildExactPairSet(exactCollisions) {
|
|
43
|
+
const pairs = new Set();
|
|
44
|
+
for (const flag of exactCollisions) {
|
|
45
|
+
const paths = flag.entries.map((e) => e.source_path).sort();
|
|
46
|
+
// For 3-way+ exact collisions, all sub-pairs are skipped.
|
|
47
|
+
for (let i = 0; i < paths.length; i++) {
|
|
48
|
+
for (let j = i + 1; j < paths.length; j++) {
|
|
49
|
+
pairs.add(`${paths[i]}\x00${paths[j]}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return pairs;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Run the semantic-overlap pass over the inventory.
|
|
57
|
+
*
|
|
58
|
+
* Steps:
|
|
59
|
+
* 1. Build an O(1) lookup from `source_path` -> `InventoryEntry`.
|
|
60
|
+
* 2. Adapt entries with non-empty `triggerSurface[]` to
|
|
61
|
+
* `TriggerPhraseSkill[]`.
|
|
62
|
+
* 3. Call `OverlapDetector.findAllOverlaps` once.
|
|
63
|
+
* 4. Map each non-zero overlap result back to a `SemanticCollisionFlag`,
|
|
64
|
+
* skipping pairs already flagged by the exact pass.
|
|
65
|
+
*
|
|
66
|
+
* Disposal of the `OverlapDetector` is the **caller's** responsibility
|
|
67
|
+
* — the orchestrator does it after this function returns so it can
|
|
68
|
+
* also be skipped on the cheap path without double-construction.
|
|
69
|
+
*/
|
|
70
|
+
export async function detectSemanticCollisions(inventory, exactCollisions, auditId, detector) {
|
|
71
|
+
// Build path -> entry lookup so result mapping is O(1) per overlap.
|
|
72
|
+
const byPath = new Map();
|
|
73
|
+
for (const entry of inventory) {
|
|
74
|
+
byPath.set(entry.source_path, entry);
|
|
75
|
+
}
|
|
76
|
+
// Filter to entries with at least one trigger phrase. Empty surfaces
|
|
77
|
+
// can't overlap with anything semantically.
|
|
78
|
+
const candidates = inventory
|
|
79
|
+
.filter((e) => e.triggerSurface.length > 0)
|
|
80
|
+
.map(inventoryToTriggerPhraseSkill);
|
|
81
|
+
if (candidates.length < 2) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
const exactPairs = buildExactPairSet(exactCollisions);
|
|
85
|
+
const overlaps = await detector.findAllOverlaps(candidates);
|
|
86
|
+
const flags = [];
|
|
87
|
+
for (const overlap of overlaps) {
|
|
88
|
+
if (overlap.overlappingPhrases.length === 0)
|
|
89
|
+
continue;
|
|
90
|
+
const sortedPair = [overlap.skillId1, overlap.skillId2].sort();
|
|
91
|
+
const pairKey = `${sortedPair[0]}\x00${sortedPair[1]}`;
|
|
92
|
+
if (exactPairs.has(pairKey))
|
|
93
|
+
continue;
|
|
94
|
+
const entryA = byPath.get(overlap.skillId1);
|
|
95
|
+
const entryB = byPath.get(overlap.skillId2);
|
|
96
|
+
if (!entryA || !entryB)
|
|
97
|
+
continue;
|
|
98
|
+
flags.push({
|
|
99
|
+
kind: 'semantic',
|
|
100
|
+
collisionId: deriveCollisionId(auditId, [entryA, entryB]),
|
|
101
|
+
entryA,
|
|
102
|
+
entryB,
|
|
103
|
+
cosineScore: overlap.overlapScore,
|
|
104
|
+
overlappingPhrases: overlap.overlappingPhrases,
|
|
105
|
+
severity: 'warning',
|
|
106
|
+
reason: buildReason(entryA, entryB, overlap.overlapScore),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// Stable ordering by entry-pair identifier for deterministic reports.
|
|
110
|
+
flags.sort((a, b) => {
|
|
111
|
+
const aKey = `${a.entryA.identifier}|${a.entryB.identifier}`;
|
|
112
|
+
const bKey = `${b.entryA.identifier}|${b.entryB.identifier}`;
|
|
113
|
+
return aKey.localeCompare(bKey);
|
|
114
|
+
});
|
|
115
|
+
return flags;
|
|
116
|
+
}
|
|
117
|
+
function buildReason(a, b, score) {
|
|
118
|
+
const pct = Math.round(score * 100);
|
|
119
|
+
return `"${a.identifier}" and "${b.identifier}" share semantically similar trigger phrases (${pct}% overlap)`;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=collision-detector.semantic.helpers.js.map
|