@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.
Files changed (391) hide show
  1. package/CHANGELOG.md +32 -4
  2. package/README.md +89 -13
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/__tests__/compare.test.js +5 -5
  5. package/dist/src/__tests__/compare.test.js.map +1 -1
  6. package/dist/src/__tests__/context-listeners.test.d.ts +12 -0
  7. package/dist/src/__tests__/context-listeners.test.d.ts.map +1 -0
  8. package/dist/src/__tests__/context-listeners.test.js +87 -0
  9. package/dist/src/__tests__/context-listeners.test.js.map +1 -0
  10. package/dist/src/__tests__/context.test.js +84 -82
  11. package/dist/src/__tests__/context.test.js.map +1 -1
  12. package/dist/src/__tests__/get-skill.api-path.test.js +21 -14
  13. package/dist/src/__tests__/get-skill.api-path.test.js.map +1 -1
  14. package/dist/src/__tests__/get-skill.test.js +5 -5
  15. package/dist/src/__tests__/get-skill.test.js.map +1 -1
  16. package/dist/src/__tests__/index-local.test.js +5 -5
  17. package/dist/src/__tests__/index-local.test.js.map +1 -1
  18. package/dist/src/__tests__/recommend-online-path.test.js +5 -5
  19. package/dist/src/__tests__/recommend-online-path.test.js.map +1 -1
  20. package/dist/src/__tests__/recommend.test.js +9 -9
  21. package/dist/src/__tests__/recommend.test.js.map +1 -1
  22. package/dist/src/__tests__/search-compatible-with.test.d.ts +10 -0
  23. package/dist/src/__tests__/search-compatible-with.test.d.ts.map +1 -0
  24. package/dist/src/__tests__/search-compatible-with.test.js +96 -0
  25. package/dist/src/__tests__/search-compatible-with.test.js.map +1 -0
  26. package/dist/src/__tests__/search-online-path.test.js +5 -5
  27. package/dist/src/__tests__/search-online-path.test.js.map +1 -1
  28. package/dist/src/__tests__/search.test.js +16 -101
  29. package/dist/src/__tests__/search.test.js.map +1 -1
  30. package/dist/src/__tests__/test-utils.d.ts +18 -3
  31. package/dist/src/__tests__/test-utils.d.ts.map +1 -1
  32. package/dist/src/__tests__/test-utils.js +24 -7
  33. package/dist/src/__tests__/test-utils.js.map +1 -1
  34. package/dist/src/audit/audit-history.d.ts +77 -0
  35. package/dist/src/audit/audit-history.d.ts.map +1 -0
  36. package/dist/src/audit/audit-history.js +98 -0
  37. package/dist/src/audit/audit-history.js.map +1 -0
  38. package/dist/src/audit/audit-report-writer.d.ts +82 -0
  39. package/dist/src/audit/audit-report-writer.d.ts.map +1 -0
  40. package/dist/src/audit/audit-report-writer.js +241 -0
  41. package/dist/src/audit/audit-report-writer.js.map +1 -0
  42. package/dist/src/audit/audit-suggestions.d.ts +52 -0
  43. package/dist/src/audit/audit-suggestions.d.ts.map +1 -0
  44. package/dist/src/audit/audit-suggestions.js +90 -0
  45. package/dist/src/audit/audit-suggestions.js.map +1 -0
  46. package/dist/src/audit/bootstrap-unmanaged.d.ts +66 -0
  47. package/dist/src/audit/bootstrap-unmanaged.d.ts.map +1 -0
  48. package/dist/src/audit/bootstrap-unmanaged.js +91 -0
  49. package/dist/src/audit/bootstrap-unmanaged.js.map +1 -0
  50. package/dist/src/audit/collision-detector.d.ts +72 -0
  51. package/dist/src/audit/collision-detector.d.ts.map +1 -0
  52. package/dist/src/audit/collision-detector.helpers.d.ts +63 -0
  53. package/dist/src/audit/collision-detector.helpers.d.ts.map +1 -0
  54. package/dist/src/audit/collision-detector.helpers.js +141 -0
  55. package/dist/src/audit/collision-detector.helpers.js.map +1 -0
  56. package/dist/src/audit/collision-detector.js +172 -0
  57. package/dist/src/audit/collision-detector.js.map +1 -0
  58. package/dist/src/audit/collision-detector.semantic.helpers.d.ts +49 -0
  59. package/dist/src/audit/collision-detector.semantic.helpers.d.ts.map +1 -0
  60. package/dist/src/audit/collision-detector.semantic.helpers.js +121 -0
  61. package/dist/src/audit/collision-detector.semantic.helpers.js.map +1 -0
  62. package/dist/src/audit/collision-detector.types.d.ts +70 -0
  63. package/dist/src/audit/collision-detector.types.d.ts.map +1 -0
  64. package/dist/src/audit/collision-detector.types.js +9 -0
  65. package/dist/src/audit/collision-detector.types.js.map +1 -0
  66. package/dist/src/audit/edit-applier.d.ts +64 -0
  67. package/dist/src/audit/edit-applier.d.ts.map +1 -0
  68. package/dist/src/audit/edit-applier.js +233 -0
  69. package/dist/src/audit/edit-applier.js.map +1 -0
  70. package/dist/src/audit/edit-applier.types.d.ts +72 -0
  71. package/dist/src/audit/edit-applier.types.d.ts.map +1 -0
  72. package/dist/src/audit/edit-applier.types.js +13 -0
  73. package/dist/src/audit/edit-applier.types.js.map +1 -0
  74. package/dist/src/audit/edit-suggester.d.ts +63 -0
  75. package/dist/src/audit/edit-suggester.d.ts.map +1 -0
  76. package/dist/src/audit/edit-suggester.js +326 -0
  77. package/dist/src/audit/edit-suggester.js.map +1 -0
  78. package/dist/src/audit/edit-suggester.types.d.ts +148 -0
  79. package/dist/src/audit/edit-suggester.types.d.ts.map +1 -0
  80. package/dist/src/audit/edit-suggester.types.js +17 -0
  81. package/dist/src/audit/edit-suggester.types.js.map +1 -0
  82. package/dist/src/audit/framework-adapter.d.ts +54 -0
  83. package/dist/src/audit/framework-adapter.d.ts.map +1 -0
  84. package/dist/src/audit/framework-adapter.js +251 -0
  85. package/dist/src/audit/framework-adapter.js.map +1 -0
  86. package/dist/src/audit/framework-adapter.types.d.ts +162 -0
  87. package/dist/src/audit/framework-adapter.types.d.ts.map +1 -0
  88. package/dist/src/audit/framework-adapter.types.js +31 -0
  89. package/dist/src/audit/framework-adapter.types.js.map +1 -0
  90. package/dist/src/audit/index.d.ts +46 -0
  91. package/dist/src/audit/index.d.ts.map +1 -0
  92. package/dist/src/audit/index.js +44 -0
  93. package/dist/src/audit/index.js.map +1 -0
  94. package/dist/src/audit/install-preflight.d.ts +99 -0
  95. package/dist/src/audit/install-preflight.d.ts.map +1 -0
  96. package/dist/src/audit/install-preflight.js +320 -0
  97. package/dist/src/audit/install-preflight.js.map +1 -0
  98. package/dist/src/audit/namespace-audit.types.d.ts +100 -0
  99. package/dist/src/audit/namespace-audit.types.d.ts.map +1 -0
  100. package/dist/src/audit/namespace-audit.types.js +20 -0
  101. package/dist/src/audit/namespace-audit.types.js.map +1 -0
  102. package/dist/src/audit/namespace-overrides.d.ts +79 -0
  103. package/dist/src/audit/namespace-overrides.d.ts.map +1 -0
  104. package/dist/src/audit/namespace-overrides.js +228 -0
  105. package/dist/src/audit/namespace-overrides.js.map +1 -0
  106. package/dist/src/audit/namespace-overrides.types.d.ts +115 -0
  107. package/dist/src/audit/namespace-overrides.types.d.ts.map +1 -0
  108. package/dist/src/audit/namespace-overrides.types.js +26 -0
  109. package/dist/src/audit/namespace-overrides.types.js.map +1 -0
  110. package/dist/src/audit/rename-engine.apply-paths.d.ts +54 -0
  111. package/dist/src/audit/rename-engine.apply-paths.d.ts.map +1 -0
  112. package/dist/src/audit/rename-engine.apply-paths.js +126 -0
  113. package/dist/src/audit/rename-engine.apply-paths.js.map +1 -0
  114. package/dist/src/audit/rename-engine.d.ts +59 -0
  115. package/dist/src/audit/rename-engine.d.ts.map +1 -0
  116. package/dist/src/audit/rename-engine.helpers.d.ts +63 -0
  117. package/dist/src/audit/rename-engine.helpers.d.ts.map +1 -0
  118. package/dist/src/audit/rename-engine.helpers.js +224 -0
  119. package/dist/src/audit/rename-engine.helpers.js.map +1 -0
  120. package/dist/src/audit/rename-engine.js +393 -0
  121. package/dist/src/audit/rename-engine.js.map +1 -0
  122. package/dist/src/audit/rename-engine.types.d.ts +157 -0
  123. package/dist/src/audit/rename-engine.types.d.ts.map +1 -0
  124. package/dist/src/audit/rename-engine.types.js +15 -0
  125. package/dist/src/audit/rename-engine.types.js.map +1 -0
  126. package/dist/src/audit/run-inventory-audit.d.ts +95 -0
  127. package/dist/src/audit/run-inventory-audit.d.ts.map +1 -0
  128. package/dist/src/audit/run-inventory-audit.js +245 -0
  129. package/dist/src/audit/run-inventory-audit.js.map +1 -0
  130. package/dist/src/audit/suggestion-chain.d.ts +89 -0
  131. package/dist/src/audit/suggestion-chain.d.ts.map +1 -0
  132. package/dist/src/audit/suggestion-chain.js +121 -0
  133. package/dist/src/audit/suggestion-chain.js.map +1 -0
  134. package/dist/src/audit-tool-dispatch.d.ts +61 -0
  135. package/dist/src/audit-tool-dispatch.d.ts.map +1 -0
  136. package/dist/src/audit-tool-dispatch.js +114 -0
  137. package/dist/src/audit-tool-dispatch.js.map +1 -0
  138. package/dist/src/index.js +1 -1
  139. package/dist/src/index.js.map +1 -1
  140. package/dist/src/indexer/LocalIndexer.d.ts +8 -1
  141. package/dist/src/indexer/LocalIndexer.d.ts.map +1 -1
  142. package/dist/src/indexer/LocalIndexer.js +42 -38
  143. package/dist/src/indexer/LocalIndexer.js.map +1 -1
  144. package/dist/src/middleware/__tests__/license.gate.test.js +21 -2
  145. package/dist/src/middleware/__tests__/license.gate.test.js.map +1 -1
  146. package/dist/src/middleware/license.gate.d.ts +14 -0
  147. package/dist/src/middleware/license.gate.d.ts.map +1 -1
  148. package/dist/src/middleware/license.gate.js +52 -1
  149. package/dist/src/middleware/license.gate.js.map +1 -1
  150. package/dist/src/onboarding/install-assets.d.ts.map +1 -1
  151. package/dist/src/onboarding/install-assets.js +11 -5
  152. package/dist/src/onboarding/install-assets.js.map +1 -1
  153. package/dist/src/tool-dispatch.d.ts.map +1 -1
  154. package/dist/src/tool-dispatch.js +6 -4
  155. package/dist/src/tool-dispatch.js.map +1 -1
  156. package/dist/src/tools/analytics.service.test.js +6 -4
  157. package/dist/src/tools/analytics.service.test.js.map +1 -1
  158. package/dist/src/tools/apply-namespace-rename.d.ts +71 -0
  159. package/dist/src/tools/apply-namespace-rename.d.ts.map +1 -0
  160. package/dist/src/tools/apply-namespace-rename.js +137 -0
  161. package/dist/src/tools/apply-namespace-rename.js.map +1 -0
  162. package/dist/src/tools/apply-namespace-rename.types.d.ts +46 -0
  163. package/dist/src/tools/apply-namespace-rename.types.d.ts.map +1 -0
  164. package/dist/src/tools/apply-namespace-rename.types.js +9 -0
  165. package/dist/src/tools/apply-namespace-rename.types.js.map +1 -0
  166. package/dist/src/tools/apply-recommended-edit.d.ts +50 -0
  167. package/dist/src/tools/apply-recommended-edit.d.ts.map +1 -0
  168. package/dist/src/tools/apply-recommended-edit.js +112 -0
  169. package/dist/src/tools/apply-recommended-edit.js.map +1 -0
  170. package/dist/src/tools/apply-recommended-edit.types.d.ts +49 -0
  171. package/dist/src/tools/apply-recommended-edit.types.d.ts.map +1 -0
  172. package/dist/src/tools/apply-recommended-edit.types.js +14 -0
  173. package/dist/src/tools/apply-recommended-edit.types.js.map +1 -0
  174. package/dist/src/tools/audit-tools.d.ts +4 -4
  175. package/dist/src/tools/compliance-tools.service.test.js +6 -4
  176. package/dist/src/tools/compliance-tools.service.test.js.map +1 -1
  177. package/dist/src/tools/install.backup-gc.d.ts +61 -0
  178. package/dist/src/tools/install.backup-gc.d.ts.map +1 -0
  179. package/dist/src/tools/install.backup-gc.js +166 -0
  180. package/dist/src/tools/install.backup-gc.js.map +1 -0
  181. package/dist/src/tools/install.conflict-helpers.d.ts +29 -2
  182. package/dist/src/tools/install.conflict-helpers.d.ts.map +1 -1
  183. package/dist/src/tools/install.conflict-helpers.js +37 -4
  184. package/dist/src/tools/install.conflict-helpers.js.map +1 -1
  185. package/dist/src/tools/install.d.ts +15 -1
  186. package/dist/src/tools/install.d.ts.map +1 -1
  187. package/dist/src/tools/install.js +162 -7
  188. package/dist/src/tools/install.js.map +1 -1
  189. package/dist/src/tools/install.ledger-replay.d.ts +52 -0
  190. package/dist/src/tools/install.ledger-replay.d.ts.map +1 -0
  191. package/dist/src/tools/install.ledger-replay.js +88 -0
  192. package/dist/src/tools/install.ledger-replay.js.map +1 -0
  193. package/dist/src/tools/install.namespace-gate.d.ts +68 -0
  194. package/dist/src/tools/install.namespace-gate.d.ts.map +1 -0
  195. package/dist/src/tools/install.namespace-gate.js +129 -0
  196. package/dist/src/tools/install.namespace-gate.js.map +1 -0
  197. package/dist/src/tools/install.test.js +71 -1
  198. package/dist/src/tools/install.test.js.map +1 -1
  199. package/dist/src/tools/install.tool.d.ts +17 -0
  200. package/dist/src/tools/install.tool.d.ts.map +1 -1
  201. package/dist/src/tools/install.tool.js +19 -1
  202. package/dist/src/tools/install.tool.js.map +1 -1
  203. package/dist/src/tools/install.types.d.ts +35 -1
  204. package/dist/src/tools/install.types.d.ts.map +1 -1
  205. package/dist/src/tools/install.types.js +24 -2
  206. package/dist/src/tools/install.types.js.map +1 -1
  207. package/dist/src/tools/namespace-audit/telemetry.d.ts +80 -0
  208. package/dist/src/tools/namespace-audit/telemetry.d.ts.map +1 -0
  209. package/dist/src/tools/namespace-audit/telemetry.js +129 -0
  210. package/dist/src/tools/namespace-audit/telemetry.js.map +1 -0
  211. package/dist/src/tools/outdated.test.js +2 -2
  212. package/dist/src/tools/outdated.test.js.map +1 -1
  213. package/dist/src/tools/publish-private.test.js +2 -2
  214. package/dist/src/tools/publish-private.test.js.map +1 -1
  215. package/dist/src/tools/recommend.types.d.ts +2 -2
  216. package/dist/src/tools/search.d.ts +2 -2
  217. package/dist/src/tools/search.js +3 -3
  218. package/dist/src/tools/search.js.map +1 -1
  219. package/dist/src/tools/skill-audit.test.js +2 -2
  220. package/dist/src/tools/skill-audit.test.js.map +1 -1
  221. package/dist/src/tools/skill-diff.d.ts +1 -1
  222. package/dist/src/tools/skill-inventory-audit.d.ts +67 -0
  223. package/dist/src/tools/skill-inventory-audit.d.ts.map +1 -0
  224. package/dist/src/tools/skill-inventory-audit.js +112 -0
  225. package/dist/src/tools/skill-inventory-audit.js.map +1 -0
  226. package/dist/src/tools/skill-inventory-audit.types.d.ts +67 -0
  227. package/dist/src/tools/skill-inventory-audit.types.d.ts.map +1 -0
  228. package/dist/src/tools/skill-inventory-audit.types.js +14 -0
  229. package/dist/src/tools/skill-inventory-audit.types.js.map +1 -0
  230. package/dist/src/tools/skill-pack-audit.d.ts.map +1 -1
  231. package/dist/src/tools/skill-pack-audit.helpers.d.ts.map +1 -1
  232. package/dist/src/tools/skill-pack-audit.helpers.js +15 -2
  233. package/dist/src/tools/skill-pack-audit.helpers.js.map +1 -1
  234. package/dist/src/tools/skill-pack-audit.js +15 -1
  235. package/dist/src/tools/skill-pack-audit.js.map +1 -1
  236. package/dist/src/tools/skill-rescan.d.ts.map +1 -1
  237. package/dist/src/tools/skill-rescan.js +4 -2
  238. package/dist/src/tools/skill-rescan.js.map +1 -1
  239. package/dist/src/tools/suggest.d.ts +2 -2
  240. package/dist/src/tools/uninstall.d.ts +1 -1
  241. package/dist/src/tools/uninstall.d.ts.map +1 -1
  242. package/dist/src/tools/uninstall.js +17 -3
  243. package/dist/src/tools/uninstall.js.map +1 -1
  244. package/dist/src/tools/validate.types.d.ts +10 -1
  245. package/dist/src/tools/validate.types.d.ts.map +1 -1
  246. package/dist/src/tools/validate.types.js +10 -1
  247. package/dist/src/tools/validate.types.js.map +1 -1
  248. package/dist/src/utils/installed-skills.d.ts.map +1 -1
  249. package/dist/src/utils/installed-skills.js +8 -6
  250. package/dist/src/utils/installed-skills.js.map +1 -1
  251. package/dist/src/utils/local-inventory.d.ts +29 -0
  252. package/dist/src/utils/local-inventory.d.ts.map +1 -0
  253. package/dist/src/utils/local-inventory.helpers.d.ts +96 -0
  254. package/dist/src/utils/local-inventory.helpers.d.ts.map +1 -0
  255. package/dist/src/utils/local-inventory.helpers.js +279 -0
  256. package/dist/src/utils/local-inventory.helpers.js.map +1 -0
  257. package/dist/src/utils/local-inventory.js +202 -0
  258. package/dist/src/utils/local-inventory.js.map +1 -0
  259. package/dist/src/utils/local-inventory.types.d.ts +100 -0
  260. package/dist/src/utils/local-inventory.types.d.ts.map +1 -0
  261. package/dist/src/utils/local-inventory.types.js +9 -0
  262. package/dist/src/utils/local-inventory.types.js.map +1 -0
  263. package/dist/src/webhooks/stripe-webhook-endpoint.d.ts +12 -0
  264. package/dist/src/webhooks/stripe-webhook-endpoint.d.ts.map +1 -1
  265. package/dist/src/webhooks/stripe-webhook-endpoint.js +30 -9
  266. package/dist/src/webhooks/stripe-webhook-endpoint.js.map +1 -1
  267. package/dist/src/webhooks/webhook-endpoint.d.ts +13 -0
  268. package/dist/src/webhooks/webhook-endpoint.d.ts.map +1 -1
  269. package/dist/src/webhooks/webhook-endpoint.js +31 -9
  270. package/dist/src/webhooks/webhook-endpoint.js.map +1 -1
  271. package/dist/tests/compare.test.js +5 -5
  272. package/dist/tests/compare.test.js.map +1 -1
  273. package/dist/tests/context-async-listeners.test.d.ts +12 -0
  274. package/dist/tests/context-async-listeners.test.d.ts.map +1 -0
  275. package/dist/tests/context-async-listeners.test.js +62 -0
  276. package/dist/tests/context-async-listeners.test.js.map +1 -0
  277. package/dist/tests/e2e/compare.e2e.test.js +9 -3
  278. package/dist/tests/e2e/compare.e2e.test.js.map +1 -1
  279. package/dist/tests/e2e/install-flow.e2e.test.js +9 -3
  280. package/dist/tests/e2e/install-flow.e2e.test.js.map +1 -1
  281. package/dist/tests/e2e/recommend.e2e.test.js +9 -3
  282. package/dist/tests/e2e/recommend.e2e.test.js.map +1 -1
  283. package/dist/tests/e2e/skill-flow.e2e.test.js +17 -5
  284. package/dist/tests/e2e/skill-flow.e2e.test.js.map +1 -1
  285. package/dist/tests/e2e/suggest.e2e.test.js +11 -3
  286. package/dist/tests/e2e/suggest.e2e.test.js.map +1 -1
  287. package/dist/tests/integration/audit-roundtrip.test.d.ts +29 -0
  288. package/dist/tests/integration/audit-roundtrip.test.d.ts.map +1 -0
  289. package/dist/tests/integration/audit-roundtrip.test.js +214 -0
  290. package/dist/tests/integration/audit-roundtrip.test.js.map +1 -0
  291. package/dist/tests/integration/install-namespace.integration.test.d.ts +14 -0
  292. package/dist/tests/integration/install-namespace.integration.test.d.ts.map +1 -0
  293. package/dist/tests/integration/install-namespace.integration.test.js +414 -0
  294. package/dist/tests/integration/install-namespace.integration.test.js.map +1 -0
  295. package/dist/tests/performance/search-performance.test.js +9 -3
  296. package/dist/tests/performance/search-performance.test.js.map +1 -1
  297. package/dist/tests/tools.test.js +5 -5
  298. package/dist/tests/tools.test.js.map +1 -1
  299. package/dist/tests/unit/apply-namespace-rename.test.d.ts +24 -0
  300. package/dist/tests/unit/apply-namespace-rename.test.d.ts.map +1 -0
  301. package/dist/tests/unit/apply-namespace-rename.test.js +205 -0
  302. package/dist/tests/unit/apply-namespace-rename.test.js.map +1 -0
  303. package/dist/tests/unit/apply-recommended-edit.test.d.ts +28 -0
  304. package/dist/tests/unit/apply-recommended-edit.test.d.ts.map +1 -0
  305. package/dist/tests/unit/apply-recommended-edit.test.js +229 -0
  306. package/dist/tests/unit/apply-recommended-edit.test.js.map +1 -0
  307. package/dist/tests/unit/audit-history.test.d.ts +11 -0
  308. package/dist/tests/unit/audit-history.test.d.ts.map +1 -0
  309. package/dist/tests/unit/audit-history.test.js +183 -0
  310. package/dist/tests/unit/audit-history.test.js.map +1 -0
  311. package/dist/tests/unit/audit-report-writer.test.d.ts +7 -0
  312. package/dist/tests/unit/audit-report-writer.test.d.ts.map +1 -0
  313. package/dist/tests/unit/audit-report-writer.test.js +249 -0
  314. package/dist/tests/unit/audit-report-writer.test.js.map +1 -0
  315. package/dist/tests/unit/audit-tool-dispatch.test.d.ts +17 -0
  316. package/dist/tests/unit/audit-tool-dispatch.test.d.ts.map +1 -0
  317. package/dist/tests/unit/audit-tool-dispatch.test.js +133 -0
  318. package/dist/tests/unit/audit-tool-dispatch.test.js.map +1 -0
  319. package/dist/tests/unit/collision-detector.semantic.test.d.ts +12 -0
  320. package/dist/tests/unit/collision-detector.semantic.test.d.ts.map +1 -0
  321. package/dist/tests/unit/collision-detector.semantic.test.js +281 -0
  322. package/dist/tests/unit/collision-detector.semantic.test.js.map +1 -0
  323. package/dist/tests/unit/collision-detector.test.d.ts +8 -0
  324. package/dist/tests/unit/collision-detector.test.d.ts.map +1 -0
  325. package/dist/tests/unit/collision-detector.test.js +266 -0
  326. package/dist/tests/unit/collision-detector.test.js.map +1 -0
  327. package/dist/tests/unit/edit-applier.test.d.ts +17 -0
  328. package/dist/tests/unit/edit-applier.test.d.ts.map +1 -0
  329. package/dist/tests/unit/edit-applier.test.js +165 -0
  330. package/dist/tests/unit/edit-applier.test.js.map +1 -0
  331. package/dist/tests/unit/edit-suggester.fixtures.d.ts +38 -0
  332. package/dist/tests/unit/edit-suggester.fixtures.d.ts.map +1 -0
  333. package/dist/tests/unit/edit-suggester.fixtures.js +84 -0
  334. package/dist/tests/unit/edit-suggester.fixtures.js.map +1 -0
  335. package/dist/tests/unit/edit-suggester.test.d.ts +17 -0
  336. package/dist/tests/unit/edit-suggester.test.d.ts.map +1 -0
  337. package/dist/tests/unit/edit-suggester.test.js +356 -0
  338. package/dist/tests/unit/edit-suggester.test.js.map +1 -0
  339. package/dist/tests/unit/framework-adapter.test.d.ts +30 -0
  340. package/dist/tests/unit/framework-adapter.test.d.ts.map +1 -0
  341. package/dist/tests/unit/framework-adapter.test.js +221 -0
  342. package/dist/tests/unit/framework-adapter.test.js.map +1 -0
  343. package/dist/tests/unit/install-preflight.test.d.ts +17 -0
  344. package/dist/tests/unit/install-preflight.test.d.ts.map +1 -0
  345. package/dist/tests/unit/install-preflight.test.js +270 -0
  346. package/dist/tests/unit/install-preflight.test.js.map +1 -0
  347. package/dist/tests/unit/install.backup-gc.test.d.ts +18 -0
  348. package/dist/tests/unit/install.backup-gc.test.d.ts.map +1 -0
  349. package/dist/tests/unit/install.backup-gc.test.js +177 -0
  350. package/dist/tests/unit/install.backup-gc.test.js.map +1 -0
  351. package/dist/tests/unit/install.ledger-replay.test.d.ts +12 -0
  352. package/dist/tests/unit/install.ledger-replay.test.d.ts.map +1 -0
  353. package/dist/tests/unit/install.ledger-replay.test.js +98 -0
  354. package/dist/tests/unit/install.ledger-replay.test.js.map +1 -0
  355. package/dist/tests/unit/local-inventory.test.d.ts +8 -0
  356. package/dist/tests/unit/local-inventory.test.d.ts.map +1 -0
  357. package/dist/tests/unit/local-inventory.test.js +165 -0
  358. package/dist/tests/unit/local-inventory.test.js.map +1 -0
  359. package/dist/tests/unit/namespace-audit-telemetry.test.d.ts +10 -0
  360. package/dist/tests/unit/namespace-audit-telemetry.test.d.ts.map +1 -0
  361. package/dist/tests/unit/namespace-audit-telemetry.test.js +215 -0
  362. package/dist/tests/unit/namespace-audit-telemetry.test.js.map +1 -0
  363. package/dist/tests/unit/namespace-overrides.test.d.ts +18 -0
  364. package/dist/tests/unit/namespace-overrides.test.d.ts.map +1 -0
  365. package/dist/tests/unit/namespace-overrides.test.js +210 -0
  366. package/dist/tests/unit/namespace-overrides.test.js.map +1 -0
  367. package/dist/tests/unit/rename-engine.test.d.ts +26 -0
  368. package/dist/tests/unit/rename-engine.test.d.ts.map +1 -0
  369. package/dist/tests/unit/rename-engine.test.js +367 -0
  370. package/dist/tests/unit/rename-engine.test.js.map +1 -0
  371. package/dist/tests/unit/skill-inventory-audit.test.d.ts +20 -0
  372. package/dist/tests/unit/skill-inventory-audit.test.d.ts.map +1 -0
  373. package/dist/tests/unit/skill-inventory-audit.test.js +299 -0
  374. package/dist/tests/unit/skill-inventory-audit.test.js.map +1 -0
  375. package/dist/tests/unit/skill-pack-audit.helpers.test.d.ts +11 -0
  376. package/dist/tests/unit/skill-pack-audit.helpers.test.d.ts.map +1 -0
  377. package/dist/tests/unit/skill-pack-audit.helpers.test.js +61 -0
  378. package/dist/tests/unit/skill-pack-audit.helpers.test.js.map +1 -0
  379. package/dist/tests/unit/skill-pack-audit.test.js +1 -1
  380. package/dist/tests/unit/skill-pack-audit.test.js.map +1 -1
  381. package/dist/tests/unit/suggestion-chain.test.d.ts +17 -0
  382. package/dist/tests/unit/suggestion-chain.test.d.ts.map +1 -0
  383. package/dist/tests/unit/suggestion-chain.test.js +191 -0
  384. package/dist/tests/unit/suggestion-chain.test.js.map +1 -0
  385. package/dist/tests/webhooks/standalone-shutdown.test.d.ts +12 -0
  386. package/dist/tests/webhooks/standalone-shutdown.test.d.ts.map +1 -0
  387. package/dist/tests/webhooks/standalone-shutdown.test.js +91 -0
  388. package/dist/tests/webhooks/standalone-shutdown.test.js.map +1 -0
  389. package/package.json +17 -4
  390. package/server.json +3 -3
  391. 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