@skillsmith/core 0.12.0 → 0.12.2

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 (290) hide show
  1. package/CHANGELOG.md +166 -1
  2. package/README.md +7 -8
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/api/client.d.ts +5 -3
  5. package/dist/src/api/client.d.ts.map +1 -1
  6. package/dist/src/api/client.js +23 -33
  7. package/dist/src/api/client.js.map +1 -1
  8. package/dist/src/api/client.registry-sync.d.ts +28 -0
  9. package/dist/src/api/client.registry-sync.d.ts.map +1 -0
  10. package/dist/src/api/client.registry-sync.js +36 -0
  11. package/dist/src/api/client.registry-sync.js.map +1 -0
  12. package/dist/src/api/client.test.js +185 -0
  13. package/dist/src/api/client.test.js.map +1 -1
  14. package/dist/src/api/client.toSkill.d.ts +16 -0
  15. package/dist/src/api/client.toSkill.d.ts.map +1 -0
  16. package/dist/src/api/client.toSkill.js +46 -0
  17. package/dist/src/api/client.toSkill.js.map +1 -0
  18. package/dist/src/api/client.types.d.ts +22 -0
  19. package/dist/src/api/client.types.d.ts.map +1 -1
  20. package/dist/src/api/index.d.ts +1 -1
  21. package/dist/src/api/index.d.ts.map +1 -1
  22. package/dist/src/api/index.js.map +1 -1
  23. package/dist/src/api/schemas.d.ts +28 -0
  24. package/dist/src/api/schemas.d.ts.map +1 -1
  25. package/dist/src/api/schemas.js +13 -0
  26. package/dist/src/api/schemas.js.map +1 -1
  27. package/dist/src/audit/remote-audit.d.ts +85 -0
  28. package/dist/src/audit/remote-audit.d.ts.map +1 -1
  29. package/dist/src/audit/remote-audit.js +126 -3
  30. package/dist/src/audit/remote-audit.js.map +1 -1
  31. package/dist/src/audit/remote-audit.test.js +217 -1
  32. package/dist/src/audit/remote-audit.test.js.map +1 -1
  33. package/dist/src/config/index.d.ts +1 -0
  34. package/dist/src/config/index.d.ts.map +1 -1
  35. package/dist/src/config/index.js.map +1 -1
  36. package/dist/src/config/token-credentials.d.ts +20 -0
  37. package/dist/src/config/token-credentials.d.ts.map +1 -1
  38. package/dist/src/config/token-credentials.js +59 -0
  39. package/dist/src/config/token-credentials.js.map +1 -1
  40. package/dist/src/config/token-credentials.test.d.ts +3 -0
  41. package/dist/src/config/token-credentials.test.d.ts.map +1 -1
  42. package/dist/src/config/token-credentials.test.js +68 -0
  43. package/dist/src/config/token-credentials.test.js.map +1 -1
  44. package/dist/src/db/migration-runner.d.ts.map +1 -1
  45. package/dist/src/db/migration-runner.js +6 -0
  46. package/dist/src/db/migration-runner.js.map +1 -1
  47. package/dist/src/db/migrations/v18-skill-versions-real-content-hash.d.ts +36 -0
  48. package/dist/src/db/migrations/v18-skill-versions-real-content-hash.d.ts.map +1 -0
  49. package/dist/src/db/migrations/v18-skill-versions-real-content-hash.js +38 -0
  50. package/dist/src/db/migrations/v18-skill-versions-real-content-hash.js.map +1 -0
  51. package/dist/src/db/schema.d.ts +1 -1
  52. package/dist/src/db/schema.d.ts.map +1 -1
  53. package/dist/src/db/schema.js +3 -1
  54. package/dist/src/db/schema.js.map +1 -1
  55. package/dist/src/exports/services.d.ts +3 -7
  56. package/dist/src/exports/services.d.ts.map +1 -1
  57. package/dist/src/exports/services.install.d.ts +18 -0
  58. package/dist/src/exports/services.install.d.ts.map +1 -0
  59. package/dist/src/exports/services.install.js +62 -0
  60. package/dist/src/exports/services.install.js.map +1 -0
  61. package/dist/src/exports/services.js +12 -32
  62. package/dist/src/exports/services.js.map +1 -1
  63. package/dist/src/exports/types.d.ts +1 -1
  64. package/dist/src/exports/types.d.ts.map +1 -1
  65. package/dist/src/index.d.ts +6 -6
  66. package/dist/src/index.d.ts.map +1 -1
  67. package/dist/src/index.js +8 -5
  68. package/dist/src/index.js.map +1 -1
  69. package/dist/src/install/agent-config-merge.json.d.ts +5 -4
  70. package/dist/src/install/agent-config-merge.json.d.ts.map +1 -1
  71. package/dist/src/install/agent-config-merge.json.js +10 -9
  72. package/dist/src/install/agent-config-merge.json.js.map +1 -1
  73. package/dist/src/install/agent-config-merge.types.d.ts +11 -1
  74. package/dist/src/install/agent-config-merge.types.d.ts.map +1 -1
  75. package/dist/src/install/agent-config-merge.types.js.map +1 -1
  76. package/dist/src/install/agent-harness-targets.d.ts +30 -2
  77. package/dist/src/install/agent-harness-targets.d.ts.map +1 -1
  78. package/dist/src/install/agent-harness-targets.js +17 -0
  79. package/dist/src/install/agent-harness-targets.js.map +1 -1
  80. package/dist/src/install/agent-manifest-path-guard.d.ts +28 -3
  81. package/dist/src/install/agent-manifest-path-guard.d.ts.map +1 -1
  82. package/dist/src/install/agent-manifest-path-guard.js +59 -3
  83. package/dist/src/install/agent-manifest-path-guard.js.map +1 -1
  84. package/dist/src/install/agent-manifest-path-guard.test.js +27 -1
  85. package/dist/src/install/agent-manifest-path-guard.test.js.map +1 -1
  86. package/dist/src/install/agent-pack-installer.antigravity-mcp.d.ts +74 -0
  87. package/dist/src/install/agent-pack-installer.antigravity-mcp.d.ts.map +1 -0
  88. package/dist/src/install/agent-pack-installer.antigravity-mcp.js +106 -0
  89. package/dist/src/install/agent-pack-installer.antigravity-mcp.js.map +1 -0
  90. package/dist/src/install/agent-pack-installer.antigravity-mcp.test.d.ts +2 -0
  91. package/dist/src/install/agent-pack-installer.antigravity-mcp.test.d.ts.map +1 -0
  92. package/dist/src/install/agent-pack-installer.antigravity-mcp.test.js +157 -0
  93. package/dist/src/install/agent-pack-installer.antigravity-mcp.test.js.map +1 -0
  94. package/dist/src/install/agent-pack-installer.cursor-mcp.d.ts +53 -0
  95. package/dist/src/install/agent-pack-installer.cursor-mcp.d.ts.map +1 -0
  96. package/dist/src/install/agent-pack-installer.cursor-mcp.js +207 -0
  97. package/dist/src/install/agent-pack-installer.cursor-mcp.js.map +1 -0
  98. package/dist/src/install/agent-pack-installer.cursor-mcp.test.d.ts +2 -0
  99. package/dist/src/install/agent-pack-installer.cursor-mcp.test.d.ts.map +1 -0
  100. package/dist/src/install/agent-pack-installer.cursor-mcp.test.js +285 -0
  101. package/dist/src/install/agent-pack-installer.cursor-mcp.test.js.map +1 -0
  102. package/dist/src/install/agent-pack-installer.d.ts +8 -0
  103. package/dist/src/install/agent-pack-installer.d.ts.map +1 -1
  104. package/dist/src/install/agent-pack-installer.entry.d.ts +120 -3
  105. package/dist/src/install/agent-pack-installer.entry.d.ts.map +1 -1
  106. package/dist/src/install/agent-pack-installer.entry.js +166 -3
  107. package/dist/src/install/agent-pack-installer.entry.js.map +1 -1
  108. package/dist/src/install/agent-pack-installer.js +97 -3
  109. package/dist/src/install/agent-pack-installer.js.map +1 -1
  110. package/dist/src/install/agent-pack-installer.types.d.ts +27 -0
  111. package/dist/src/install/agent-pack-installer.types.d.ts.map +1 -1
  112. package/dist/src/install/agent-pack-installer.types.js +6 -0
  113. package/dist/src/install/agent-pack-installer.types.js.map +1 -1
  114. package/dist/src/install/agent-pack-installer.workspace-scope.test.d.ts +2 -0
  115. package/dist/src/install/agent-pack-installer.workspace-scope.test.d.ts.map +1 -0
  116. package/dist/src/install/agent-pack-installer.workspace-scope.test.js +148 -0
  117. package/dist/src/install/agent-pack-installer.workspace-scope.test.js.map +1 -0
  118. package/dist/src/install/agent-pack-uninstaller.d.ts +18 -7
  119. package/dist/src/install/agent-pack-uninstaller.d.ts.map +1 -1
  120. package/dist/src/install/agent-pack-uninstaller.js +59 -9
  121. package/dist/src/install/agent-pack-uninstaller.js.map +1 -1
  122. package/dist/src/install/agent-pack-uninstaller.test.js +74 -1
  123. package/dist/src/install/agent-pack-uninstaller.test.js.map +1 -1
  124. package/dist/src/install/fan-out.d.ts.map +1 -1
  125. package/dist/src/install/fan-out.js +6 -0
  126. package/dist/src/install/fan-out.js.map +1 -1
  127. package/dist/src/install/index.d.ts +2 -0
  128. package/dist/src/install/index.d.ts.map +1 -1
  129. package/dist/src/install/index.js +2 -0
  130. package/dist/src/install/index.js.map +1 -1
  131. package/dist/src/install/workspace-scope.d.ts +207 -0
  132. package/dist/src/install/workspace-scope.d.ts.map +1 -0
  133. package/dist/src/install/workspace-scope.js +275 -0
  134. package/dist/src/install/workspace-scope.js.map +1 -0
  135. package/dist/src/install/workspace-scope.test.d.ts +2 -0
  136. package/dist/src/install/workspace-scope.test.d.ts.map +1 -0
  137. package/dist/src/install/workspace-scope.test.js +378 -0
  138. package/dist/src/install/workspace-scope.test.js.map +1 -0
  139. package/dist/src/security/__tests__/pathValidation.test.js +30 -1
  140. package/dist/src/security/__tests__/pathValidation.test.js.map +1 -1
  141. package/dist/src/services/SubagentGenerator.client-profiles.d.ts +258 -0
  142. package/dist/src/services/SubagentGenerator.client-profiles.d.ts.map +1 -0
  143. package/dist/src/services/SubagentGenerator.client-profiles.js +260 -0
  144. package/dist/src/services/SubagentGenerator.client-profiles.js.map +1 -0
  145. package/dist/src/services/SubagentGenerator.d.ts +19 -41
  146. package/dist/src/services/SubagentGenerator.d.ts.map +1 -1
  147. package/dist/src/services/SubagentGenerator.helpers.d.ts +64 -0
  148. package/dist/src/services/SubagentGenerator.helpers.d.ts.map +1 -0
  149. package/dist/src/services/SubagentGenerator.helpers.js +228 -0
  150. package/dist/src/services/SubagentGenerator.helpers.js.map +1 -0
  151. package/dist/src/services/SubagentGenerator.js +66 -208
  152. package/dist/src/services/SubagentGenerator.js.map +1 -1
  153. package/dist/src/services/SubagentGenerator.types.d.ts +45 -0
  154. package/dist/src/services/SubagentGenerator.types.d.ts.map +1 -0
  155. package/dist/src/services/SubagentGenerator.types.js +14 -0
  156. package/dist/src/services/SubagentGenerator.types.js.map +1 -0
  157. package/dist/src/services/TransformationService.d.ts +18 -61
  158. package/dist/src/services/TransformationService.d.ts.map +1 -1
  159. package/dist/src/services/TransformationService.js +29 -17
  160. package/dist/src/services/TransformationService.js.map +1 -1
  161. package/dist/src/services/TransformationService.types.d.ts +74 -0
  162. package/dist/src/services/TransformationService.types.d.ts.map +1 -0
  163. package/dist/src/services/TransformationService.types.js +8 -0
  164. package/dist/src/services/TransformationService.types.js.map +1 -0
  165. package/dist/src/services/__tests__/SubagentGenerator.client-profiles.test.d.ts +5 -0
  166. package/dist/src/services/__tests__/SubagentGenerator.client-profiles.test.d.ts.map +1 -0
  167. package/dist/src/services/__tests__/SubagentGenerator.client-profiles.test.js +72 -0
  168. package/dist/src/services/__tests__/SubagentGenerator.client-profiles.test.js.map +1 -0
  169. package/dist/src/services/__tests__/SubagentGenerator.helpers.test.d.ts +2 -0
  170. package/dist/src/services/__tests__/SubagentGenerator.helpers.test.d.ts.map +1 -0
  171. package/dist/src/services/__tests__/SubagentGenerator.helpers.test.js +61 -0
  172. package/dist/src/services/__tests__/SubagentGenerator.helpers.test.js.map +1 -0
  173. package/dist/src/services/__tests__/SubagentGenerator.test.js +155 -0
  174. package/dist/src/services/__tests__/SubagentGenerator.test.js.map +1 -1
  175. package/dist/src/services/__tests__/TransformationService.test.js +48 -0
  176. package/dist/src/services/__tests__/TransformationService.test.js.map +1 -1
  177. package/dist/src/services/agent-pack/agent-pack.test.js +1 -0
  178. package/dist/src/services/agent-pack/agent-pack.test.js.map +1 -1
  179. package/dist/src/services/agent-pack/prompt-source.d.ts +1 -1
  180. package/dist/src/services/agent-pack/prompt-source.d.ts.map +1 -1
  181. package/dist/src/services/agent-pack/prompt-source.js +10 -3
  182. package/dist/src/services/agent-pack/prompt-source.js.map +1 -1
  183. package/dist/src/services/agent-pack/types.d.ts +26 -2
  184. package/dist/src/services/agent-pack/types.d.ts.map +1 -1
  185. package/dist/src/services/agent-pack/types.js +13 -0
  186. package/dist/src/services/agent-pack/types.js.map +1 -1
  187. package/dist/src/services/agent-tool-profile.d.ts.map +1 -1
  188. package/dist/src/services/agent-tool-profile.js +7 -0
  189. package/dist/src/services/agent-tool-profile.js.map +1 -1
  190. package/dist/src/services/agent-tool-profile.test.js +2 -2
  191. package/dist/src/services/skill-content-comparison.d.ts +71 -0
  192. package/dist/src/services/skill-content-comparison.d.ts.map +1 -0
  193. package/dist/src/services/skill-content-comparison.js +90 -0
  194. package/dist/src/services/skill-content-comparison.js.map +1 -0
  195. package/dist/src/services/skill-content-comparison.test.d.ts +6 -0
  196. package/dist/src/services/skill-content-comparison.test.d.ts.map +1 -0
  197. package/dist/src/services/skill-content-comparison.test.js +83 -0
  198. package/dist/src/services/skill-content-comparison.test.js.map +1 -0
  199. package/dist/src/services/skill-identity-classification.d.ts +202 -0
  200. package/dist/src/services/skill-identity-classification.d.ts.map +1 -0
  201. package/dist/src/services/skill-identity-classification.js +295 -0
  202. package/dist/src/services/skill-identity-classification.js.map +1 -0
  203. package/dist/src/services/skill-identity-classification.test.d.ts +6 -0
  204. package/dist/src/services/skill-identity-classification.test.d.ts.map +1 -0
  205. package/dist/src/services/skill-identity-classification.test.js +314 -0
  206. package/dist/src/services/skill-identity-classification.test.js.map +1 -0
  207. package/dist/src/services/skill-installation.content.d.ts.map +1 -1
  208. package/dist/src/services/skill-installation.content.js +6 -1
  209. package/dist/src/services/skill-installation.content.js.map +1 -1
  210. package/dist/src/services/skill-installation.helpers.d.ts +8 -15
  211. package/dist/src/services/skill-installation.helpers.d.ts.map +1 -1
  212. package/dist/src/services/skill-installation.helpers.js +11 -105
  213. package/dist/src/services/skill-installation.helpers.js.map +1 -1
  214. package/dist/src/services/skill-installation.helpers.test.js +106 -1
  215. package/dist/src/services/skill-installation.helpers.test.js.map +1 -1
  216. package/dist/src/services/skill-installation.service.js +1 -1
  217. package/dist/src/services/skill-installation.service.js.map +1 -1
  218. package/dist/src/services/skill-installation.types.d.ts +33 -0
  219. package/dist/src/services/skill-installation.types.d.ts.map +1 -1
  220. package/dist/src/services/skill-installation.types.js.map +1 -1
  221. package/dist/src/services/skill-installation.uninstall.d.ts +84 -0
  222. package/dist/src/services/skill-installation.uninstall.d.ts.map +1 -0
  223. package/dist/src/services/skill-installation.uninstall.js +252 -0
  224. package/dist/src/services/skill-installation.uninstall.js.map +1 -0
  225. package/dist/src/services/skill-manifest.d.ts +41 -0
  226. package/dist/src/services/skill-manifest.d.ts.map +1 -1
  227. package/dist/src/services/skill-manifest.js +93 -0
  228. package/dist/src/services/skill-manifest.js.map +1 -1
  229. package/dist/src/services/skill-manifest.test.js +27 -0
  230. package/dist/src/services/skill-manifest.test.js.map +1 -1
  231. package/dist/src/sync/SyncEngine.d.ts.map +1 -1
  232. package/dist/src/sync/SyncEngine.js +69 -77
  233. package/dist/src/sync/SyncEngine.js.map +1 -1
  234. package/dist/src/telemetry/agent-marker.d.ts +8 -0
  235. package/dist/src/telemetry/agent-marker.d.ts.map +1 -1
  236. package/dist/src/telemetry/agent-marker.js +7 -0
  237. package/dist/src/telemetry/agent-marker.js.map +1 -1
  238. package/dist/src/telemetry/agent-marker.test.js +7 -1
  239. package/dist/src/telemetry/agent-marker.test.js.map +1 -1
  240. package/dist/src/telemetry/index.d.ts +1 -1
  241. package/dist/src/telemetry/index.d.ts.map +1 -1
  242. package/dist/src/telemetry/index.js +1 -1
  243. package/dist/src/telemetry/index.js.map +1 -1
  244. package/dist/src/telemetry/wrap.d.ts +6 -0
  245. package/dist/src/telemetry/wrap.d.ts.map +1 -1
  246. package/dist/src/telemetry/wrap.js +65 -10
  247. package/dist/src/telemetry/wrap.js.map +1 -1
  248. package/dist/src/telemetry/wrap.test.js +81 -1
  249. package/dist/src/telemetry/wrap.test.js.map +1 -1
  250. package/dist/src/telemetry/wrap.tool-call-sink.test.d.ts +26 -0
  251. package/dist/src/telemetry/wrap.tool-call-sink.test.d.ts.map +1 -0
  252. package/dist/src/telemetry/wrap.tool-call-sink.test.js +162 -0
  253. package/dist/src/telemetry/wrap.tool-call-sink.test.js.map +1 -0
  254. package/dist/src/types/skill.d.ts +9 -1
  255. package/dist/src/types/skill.d.ts.map +1 -1
  256. package/dist/src/utils/index.d.ts +1 -1
  257. package/dist/src/utils/index.d.ts.map +1 -1
  258. package/dist/src/utils/index.js +1 -1
  259. package/dist/src/utils/index.js.map +1 -1
  260. package/dist/src/utils/version-check.d.ts +61 -0
  261. package/dist/src/utils/version-check.d.ts.map +1 -1
  262. package/dist/src/utils/version-check.js +78 -1
  263. package/dist/src/utils/version-check.js.map +1 -1
  264. package/dist/src/utils/version-check.test.js +130 -1
  265. package/dist/src/utils/version-check.test.js.map +1 -1
  266. package/dist/tests/db/migration-runner-race.test.js +19 -9
  267. package/dist/tests/db/migration-runner-race.test.js.map +1 -1
  268. package/dist/tests/install/fan-out.test.js +27 -0
  269. package/dist/tests/install/fan-out.test.js.map +1 -1
  270. package/dist/tests/skill-scanner/allowlist.test.js +7 -1
  271. package/dist/tests/skill-scanner/allowlist.test.js.map +1 -1
  272. package/dist/tests/sync/SyncEngine.abort.test.js +15 -11
  273. package/dist/tests/sync/SyncEngine.abort.test.js.map +1 -1
  274. package/dist/tests/sync/SyncEngine.status.test.js +1 -1
  275. package/dist/tests/sync/SyncEngine.status.test.js.map +1 -1
  276. package/dist/tests/sync/SyncEngine.test.d.ts +11 -2
  277. package/dist/tests/sync/SyncEngine.test.d.ts.map +1 -1
  278. package/dist/tests/sync/SyncEngine.test.js +164 -13
  279. package/dist/tests/sync/SyncEngine.test.js.map +1 -1
  280. package/dist/tests/unit/migrations/migration-v18.test.d.ts +16 -0
  281. package/dist/tests/unit/migrations/migration-v18.test.d.ts.map +1 -0
  282. package/dist/tests/unit/migrations/migration-v18.test.js +192 -0
  283. package/dist/tests/unit/migrations/migration-v18.test.js.map +1 -0
  284. package/dist/tests/unit/services/skill-installation.content.test.js +65 -1
  285. package/dist/tests/unit/services/skill-installation.content.test.js.map +1 -1
  286. package/dist/tests/unit/services/skill-installation.service.test.js +9 -8
  287. package/dist/tests/unit/services/skill-installation.service.test.js.map +1 -1
  288. package/dist/tests/unit/sync-engine.source-aware.test.js +5 -5
  289. package/dist/tests/unit/sync-engine.source-aware.test.js.map +1 -1
  290. package/package.json +3 -3
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Cursor-specific MCP registration step for `sklx agent install`
3
+ * (SMI-6279 Wave 9).
4
+ *
5
+ * Split out of `agent-pack-installer.harness.ts`'s generic `installMcpConfig`
6
+ * — mirrors the existing `agent-pack-installer.cursor-hooks.ts` split
7
+ * (SMI-5893 Wave 8a) for the same reason: Cursor's on-disk shape/resolution
8
+ * needs diverge structurally from the other 6 MCP-capable harnesses, so
9
+ * folding cursor-only logic into the shared function would either bloat it
10
+ * past the 500-line gate or force every other harness through cursor-only
11
+ * branches it doesn't need.
12
+ *
13
+ * Two independent, confirmed-broken things this fixes (GH#2368 V3 repro —
14
+ * see the SMI-6266 Wave 9 plan doc):
15
+ * 1. `buildAgentMcpEntryValue()` wrote the `npx`/`args` form into Cursor's
16
+ * `mcp.json` — the exact shape two live UAT passes proved ENOENTs
17
+ * inside Cursor's bundled Node (GH#2368 C-01) — and never set
18
+ * `SKILLSMITH_CLIENT`, so re-running `agent install` (the very
19
+ * remediation `formatUpdateNotification()` tells a user to run)
20
+ * silently rewrote the SAME broken entry, even after the website docs
21
+ * snippet was corrected (SMI-5893 Wave 11). {@link installCursorMcpConfig}
22
+ * now writes `buildCursorMcpEntryValue()` instead — resolved binary
23
+ * path (or the documented paste-here placeholder) plus
24
+ * `SKILLSMITH_CLIENT=cursor`.
25
+ * 2. The installer wrote its entry under the JSON key `skillsmith`, while
26
+ * the website/CLI-template docs snippet (which users are told to
27
+ * hand-paste) uses the package-scoped key `@skillsmith/mcp-server` — a
28
+ * user who did both ended up with TWO different server entries
29
+ * coexisting in the same file, neither ever recognized as "the
30
+ * other's" by the installer's own conflict-detection (which matches
31
+ * purely on key). {@link installCursorMcpConfig} now writes under
32
+ * `CURSOR_MCP_ENTRY_KEY` (`'@skillsmith/mcp-server'`) so a docs-paste
33
+ * and an `agent install` reconcile as ONE entry, and
34
+ * {@link stripStaleLegacyMcpKey} removes a pre-fix install's stale
35
+ * `'skillsmith'`-keyed entry (mirroring the cursor-hooks legacy-key
36
+ * cleanup precedent) so a re-install doesn't leave both keys present.
37
+ *
38
+ * Scoped to Cursor ONLY — `mergeJsonMcpEntry`'s default `entryKey`
39
+ * (`'skillsmith'`) and `buildAgentMcpEntryValue()`'s `npx` form are
40
+ * UNCHANGED for claude-code/copilot/windsurf/opencode/codex/hermes; nothing
41
+ * in this module is reachable from any other harness's install path.
42
+ *
43
+ * @module @skillsmith/core/install/agent-pack-installer.cursor-mcp
44
+ */
45
+ import type { HarnessInstallCtx } from './agent-pack-installer.harness.js';
46
+ import type { HarnessInstallReport } from './agent-pack-installer.types.js';
47
+ /**
48
+ * Merge Cursor's `skillsmith` MCP server registration into `~/.cursor/mcp.json`
49
+ * under {@link CURSOR_MCP_ENTRY_KEY}, then clean up a stale legacy-keyed
50
+ * entry from a pre-SMI-6279 install (see module header).
51
+ */
52
+ export declare function installCursorMcpConfig(ctx: HarnessInstallCtx, report: HarnessInstallReport): void;
53
+ //# sourceMappingURL=agent-pack-installer.cursor-mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-pack-installer.cursor-mcp.d.ts","sourceRoot":"","sources":["../../../src/install/agent-pack-installer.cursor-mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAeH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAQ3E;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAqDjG"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Cursor-specific MCP registration step for `sklx agent install`
3
+ * (SMI-6279 Wave 9).
4
+ *
5
+ * Split out of `agent-pack-installer.harness.ts`'s generic `installMcpConfig`
6
+ * — mirrors the existing `agent-pack-installer.cursor-hooks.ts` split
7
+ * (SMI-5893 Wave 8a) for the same reason: Cursor's on-disk shape/resolution
8
+ * needs diverge structurally from the other 6 MCP-capable harnesses, so
9
+ * folding cursor-only logic into the shared function would either bloat it
10
+ * past the 500-line gate or force every other harness through cursor-only
11
+ * branches it doesn't need.
12
+ *
13
+ * Two independent, confirmed-broken things this fixes (GH#2368 V3 repro —
14
+ * see the SMI-6266 Wave 9 plan doc):
15
+ * 1. `buildAgentMcpEntryValue()` wrote the `npx`/`args` form into Cursor's
16
+ * `mcp.json` — the exact shape two live UAT passes proved ENOENTs
17
+ * inside Cursor's bundled Node (GH#2368 C-01) — and never set
18
+ * `SKILLSMITH_CLIENT`, so re-running `agent install` (the very
19
+ * remediation `formatUpdateNotification()` tells a user to run)
20
+ * silently rewrote the SAME broken entry, even after the website docs
21
+ * snippet was corrected (SMI-5893 Wave 11). {@link installCursorMcpConfig}
22
+ * now writes `buildCursorMcpEntryValue()` instead — resolved binary
23
+ * path (or the documented paste-here placeholder) plus
24
+ * `SKILLSMITH_CLIENT=cursor`.
25
+ * 2. The installer wrote its entry under the JSON key `skillsmith`, while
26
+ * the website/CLI-template docs snippet (which users are told to
27
+ * hand-paste) uses the package-scoped key `@skillsmith/mcp-server` — a
28
+ * user who did both ended up with TWO different server entries
29
+ * coexisting in the same file, neither ever recognized as "the
30
+ * other's" by the installer's own conflict-detection (which matches
31
+ * purely on key). {@link installCursorMcpConfig} now writes under
32
+ * `CURSOR_MCP_ENTRY_KEY` (`'@skillsmith/mcp-server'`) so a docs-paste
33
+ * and an `agent install` reconcile as ONE entry, and
34
+ * {@link stripStaleLegacyMcpKey} removes a pre-fix install's stale
35
+ * `'skillsmith'`-keyed entry (mirroring the cursor-hooks legacy-key
36
+ * cleanup precedent) so a re-install doesn't leave both keys present.
37
+ *
38
+ * Scoped to Cursor ONLY — `mergeJsonMcpEntry`'s default `entryKey`
39
+ * (`'skillsmith'`) and `buildAgentMcpEntryValue()`'s `npx` form are
40
+ * UNCHANGED for claude-code/copilot/windsurf/opencode/codex/hermes; nothing
41
+ * in this module is reachable from any other harness's install path.
42
+ *
43
+ * @module @skillsmith/core/install/agent-pack-installer.cursor-mcp
44
+ */
45
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
46
+ import { AGENT_MCP_TARGETS } from './agent-harness-targets.js';
47
+ import { mergeJsonMcpEntry } from './agent-config-merge.json.js';
48
+ import { writeBackup } from './agent-config-merge.json-array.js';
49
+ import { deepEqualJson, markBackedUp, shouldBackup } from './agent-config-merge.types.js';
50
+ import { CURSOR_MCP_ENTRY_KEY, LEGACY_MCP_ENTRY_KEY, buildAgentMcpEntryValue, buildCursorMcpEntryValue, } from './agent-pack-installer.entry.js';
51
+ import { relocateUnderHome } from './agent-home-relocate.js';
52
+ /** Same predicate as `agent-pack-installer.harness.ts`'s private `mergeSucceeded` — duplicated rather than exported to keep that module's helper private. */
53
+ function mergeSucceeded(status) {
54
+ return status === 'created' || status === 'updated' || status === 'unchanged';
55
+ }
56
+ /**
57
+ * Merge Cursor's `skillsmith` MCP server registration into `~/.cursor/mcp.json`
58
+ * under {@link CURSOR_MCP_ENTRY_KEY}, then clean up a stale legacy-keyed
59
+ * entry from a pre-SMI-6279 install (see module header).
60
+ */
61
+ export function installCursorMcpConfig(ctx, report) {
62
+ const target = AGENT_MCP_TARGETS.cursor;
63
+ const path = relocateUnderHome(target.path, ctx.homeDir);
64
+ const entryValue = buildCursorMcpEntryValue();
65
+ const result = mergeJsonMcpEntry({
66
+ path,
67
+ keyPath: target.keyPath,
68
+ entryKey: CURSOR_MCP_ENTRY_KEY,
69
+ entryValue,
70
+ backupDir: ctx.backupDir,
71
+ force: ctx.force,
72
+ alreadyBackedUpPaths: ctx.backedUpPaths,
73
+ });
74
+ report.mcpConfig = result;
75
+ if (result.status === 'conflict') {
76
+ report.notes.push(`MCP config at ${path} already has a '${CURSOR_MCP_ENTRY_KEY}' entry that doesn't look like ours — left untouched. Re-run with --force to overwrite, or edit ${path} manually.`);
77
+ }
78
+ if (result.status === 'error') {
79
+ report.notes.push(`MCP config merge failed at ${path}: ${result.errorMessage}`);
80
+ }
81
+ // Only attempt the legacy-key cleanup once our own write succeeded (or was
82
+ // already correct) — same data-loss guard as the cursor-hooks precedent:
83
+ // a 'conflict'/'error' write means we deliberately left the file alone (or
84
+ // couldn't touch it), so removing the legacy key too would still mutate a
85
+ // file the real merge just refused to touch.
86
+ const cleanup = mergeSucceeded(result.status)
87
+ ? stripStaleLegacyMcpKey(path, target.keyPath, ctx)
88
+ : null;
89
+ if (cleanup?.status === 'updated') {
90
+ report.notes.push(`Removed stale legacy '${LEGACY_MCP_ENTRY_KEY}' MCP entry at ${path} — superseded by '${CURSOR_MCP_ENTRY_KEY}' (aligns with the website/CLI docs snippet key, SMI-6279 Wave 9).`);
91
+ }
92
+ if (cleanup?.status === 'error') {
93
+ report.notes.push(`Found a stale legacy '${LEGACY_MCP_ENTRY_KEY}' MCP entry at ${path} but could not remove it: ${cleanup.errorMessage}. The new '${CURSOR_MCP_ENTRY_KEY}' entry above was written successfully; the stale entry was left in place — remove it manually.`);
94
+ }
95
+ if (mergeSucceeded(result.status) || cleanup?.status === 'updated') {
96
+ ctx.entries.push({
97
+ path,
98
+ kind: 'mcp-config',
99
+ harness: 'cursor',
100
+ backupPath: result.backupPath ?? cleanup?.backupPath ?? null,
101
+ executable: false,
102
+ });
103
+ }
104
+ }
105
+ /**
106
+ * Strict, purpose-built ownership fingerprint for the destructive delete in
107
+ * {@link stripStaleLegacyMcpKey} — deliberately NOT the shared
108
+ * `looksLikeOurMcpEntry` heuristic (`agent-config-merge.types.ts`).
109
+ *
110
+ * `looksLikeOurMcpEntry` is intentionally loose (substring-matches an
111
+ * `args` element, or merely checks a `SKILLSMITH_TOOL_PROFILE` key is
112
+ * PRESENT regardless of its value) because its only job is gating a
113
+ * same-key OVERWRITE — a false positive there is non-destructive, the
114
+ * entry we'd write next replaces whatever was there either way. Deleting a
115
+ * DIFFERENT key entirely (this function) is a strictly higher-risk
116
+ * operation: a false positive here permanently removes a user's config
117
+ * with nothing to replace it — e.g. a custom wrapper script whose `args`
118
+ * happen to reference the package name in one element among several, or a
119
+ * user's own hand-authored `skillsmith`-keyed entry that happens to set a
120
+ * `SKILLSMITH_TOOL_PROFILE` env var with a DIFFERENT value for unrelated
121
+ * reasons (code-review finding, GPT-5.6-Sol / SMI-6279).
122
+ *
123
+ * The bar here is "structurally identical to exactly what
124
+ * `buildAgentMcpEntryValue()` itself would have written" — checked via
125
+ * `deepEqualJson` against that function's actual return value (not a
126
+ * hand-duplicated literal, so this can never drift out of sync with the
127
+ * real shape): exact `command`, exact `args` sequence (not "contains"),
128
+ * exact `env` key SET (not just key presence) and exact value.
129
+ */
130
+ function looksLikeExactLegacyNpxEntry(value) {
131
+ return deepEqualJson(value, buildAgentMcpEntryValue());
132
+ }
133
+ /**
134
+ * Remove a stale `LEGACY_MCP_ENTRY_KEY` (`'skillsmith'`)-keyed MCP entry
135
+ * left behind by a pre-SMI-6279 `agent install` run, but ONLY when it is
136
+ * structurally IDENTICAL to what that installer itself would have written
137
+ * (`looksLikeExactLegacyNpxEntry` above). A user's own hand-written
138
+ * `skillsmith`-named entry — even one that superficially resembles ours —
139
+ * is left completely untouched — this never silently deletes a foreign or
140
+ * near-miss entry just because it shares the old key name.
141
+ *
142
+ * Read-modify-write is scoped to exactly the `mcpServers.skillsmith` key —
143
+ * every other key in the file (including the entry this function's caller
144
+ * just wrote under `CURSOR_MCP_ENTRY_KEY`) is preserved byte-for-byte.
145
+ *
146
+ * @returns `null` when there's genuinely nothing to clean up (file missing,
147
+ * no `mcpServers` object, no legacy key, or the legacy key isn't an EXACT
148
+ * match for our own legacy shape) — a real no-op, not surfaced as a report
149
+ * entry. A `MergeResult` with `status: 'updated'` when the legacy key was
150
+ * removed, or `status: 'error'` when a match WAS found but reading,
151
+ * backing up, or writing the file failed — this must reach the caller as
152
+ * a reported failure, not collapse into the same `null` "nothing to do"
153
+ * return as the routine no-match case (PR-07 finding, GPT-5.6-Sol /
154
+ * SMI-6279): a swallowed write failure here would silently leave a
155
+ * confirmed-stale, confirmed-broken legacy entry in place with no
156
+ * indication anything went wrong.
157
+ */
158
+ function stripStaleLegacyMcpKey(path, keyPath, ctx) {
159
+ if (!existsSync(path))
160
+ return null;
161
+ let doc;
162
+ try {
163
+ const parsed = JSON.parse(readFileSync(path, 'utf-8'));
164
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
165
+ return null;
166
+ doc = parsed;
167
+ }
168
+ catch {
169
+ // Unparsable/unreadable — not a match we can act on either way; the
170
+ // main merge above already succeeded reading+writing this same file
171
+ // moments earlier, so this is a genuine no-op, not a swallowed failure.
172
+ return null;
173
+ }
174
+ const containerKey = keyPath[0];
175
+ if (containerKey === undefined)
176
+ return null;
177
+ const container = doc[containerKey];
178
+ if (!container || typeof container !== 'object' || Array.isArray(container))
179
+ return null;
180
+ const containerObj = container;
181
+ const legacyEntry = containerObj[LEGACY_MCP_ENTRY_KEY];
182
+ if (legacyEntry === undefined)
183
+ return null;
184
+ // Foreign OR near-miss — never touch, even if named 'skillsmith'.
185
+ if (!looksLikeExactLegacyNpxEntry(legacyEntry))
186
+ return null;
187
+ // Past this point we've confirmed a real match to delete — any failure
188
+ // from here on is a genuine error, not a no-op, and must be reported.
189
+ try {
190
+ delete containerObj[LEGACY_MCP_ENTRY_KEY];
191
+ const backupPath = shouldBackup(path, ctx.backedUpPaths)
192
+ ? writeBackup(path, ctx.backupDir)
193
+ : null;
194
+ markBackedUp(path, ctx.backedUpPaths);
195
+ writeFileSync(path, JSON.stringify(doc, null, 2) + '\n', { mode: 0o600 });
196
+ return { status: 'updated', path, backupPath };
197
+ }
198
+ catch (error) {
199
+ return {
200
+ status: 'error',
201
+ path,
202
+ backupPath: null,
203
+ errorMessage: error instanceof Error ? error.message : String(error),
204
+ };
205
+ }
206
+ }
207
+ //# sourceMappingURL=agent-pack-installer.cursor-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-pack-installer.cursor-mcp.js","sourceRoot":"","sources":["../../../src/install/agent-pack-installer.cursor-mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-pack-installer.cursor-mcp.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-pack-installer.cursor-mcp.test.d.ts","sourceRoot":"","sources":["../../../src/install/agent-pack-installer.cursor-mcp.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Cursor `mcp.json` entry-shape + key-alignment regression coverage
3
+ * (SMI-6279 Wave 9, GH#2368 V3).
4
+ *
5
+ * Split from agent-pack-installer.test.ts, mirroring the existing
6
+ * agent-pack-installer.cursor-hooks.test.ts split (same temp-HOME +
7
+ * manifest-env fixture shape). Covers the two independent things
8
+ * `agent-pack-installer.cursor-mcp.ts` fixes:
9
+ * 1. Entry SHAPE: a resolved `skillsmith-mcp` binary path (or the
10
+ * documented paste-here placeholder when resolution fails) instead of
11
+ * the `npx`/`args` form two live UAT passes proved ENOENTs inside
12
+ * Cursor's bundled Node, plus `SKILLSMITH_CLIENT=cursor`.
13
+ * 2. Entry KEY: `@skillsmith/mcp-server` (matching the website/CLI docs
14
+ * snippet) instead of `skillsmith`, with a legacy-key cleanup step for
15
+ * a pre-fix install that still has the old key.
16
+ *
17
+ * `node:child_process`'s `execFileSync` is mocked so `resolveSkillsmithMcpBinPath`
18
+ * never depends on whether `skillsmith-mcp` happens to be on the test
19
+ * runner's real PATH.
20
+ *
21
+ * @module @skillsmith/core/install/agent-pack-installer.cursor-mcp.test
22
+ */
23
+ import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
24
+ import { tmpdir } from 'node:os';
25
+ import { join } from 'node:path';
26
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
27
+ const { execFileSyncMock } = vi.hoisted(() => ({ execFileSyncMock: vi.fn() }));
28
+ vi.mock('node:child_process', async (importOriginal) => {
29
+ const actual = await importOriginal();
30
+ return { ...actual, execFileSync: execFileSyncMock };
31
+ });
32
+ // Defaults to the real writeFileSync so every test in this file gets real
33
+ // disk writes unmodified; only the one PR-07-regression test below swaps in
34
+ // a conditional throw, keyed by path so it can't accidentally intercept the
35
+ // unrelated skill-pack-file writes installAgentPack also performs in the
36
+ // same run (confirmed necessary: a naive call-order-based override fired on
37
+ // one of those instead, on the first pass at writing this test).
38
+ const { writeFileSyncMock, realWriteFileSyncRef } = vi.hoisted(() => ({
39
+ writeFileSyncMock: vi.fn(),
40
+ realWriteFileSyncRef: { current: null },
41
+ }));
42
+ vi.mock('node:fs', async (importOriginal) => {
43
+ const actual = await importOriginal();
44
+ realWriteFileSyncRef.current = actual.writeFileSync;
45
+ writeFileSyncMock.mockImplementation(actual.writeFileSync);
46
+ return { ...actual, writeFileSync: writeFileSyncMock };
47
+ });
48
+ import { installAgentPack } from './agent-pack-installer.js';
49
+ import { AGENT_INSTALL_DIR_ENV_VAR } from './agent-manifest.js';
50
+ let homeDir;
51
+ let manifestDir;
52
+ let prevInstallDirEnv;
53
+ const RESOLVED_BIN_PATH = '/usr/local/bin/skillsmith-mcp';
54
+ function mcpJsonPath(home) {
55
+ return join(home, '.cursor', 'mcp.json');
56
+ }
57
+ function readCursorMcpJson(home) {
58
+ return JSON.parse(readFileSync(mcpJsonPath(home), 'utf-8'));
59
+ }
60
+ function seedCursorPresent() {
61
+ mkdirSync(join(homeDir, '.cursor', 'skills'), { recursive: true });
62
+ }
63
+ beforeEach(() => {
64
+ homeDir = mkdtempSync(join(tmpdir(), 'skillsmith-agent-install-home-'));
65
+ manifestDir = mkdtempSync(join(tmpdir(), 'skillsmith-agent-install-manifest-'));
66
+ prevInstallDirEnv = process.env[AGENT_INSTALL_DIR_ENV_VAR];
67
+ process.env[AGENT_INSTALL_DIR_ENV_VAR] = manifestDir;
68
+ execFileSyncMock.mockReset();
69
+ // Reset to the real passthrough (see the vi.mock('node:fs', ...) setup
70
+ // above) in case a prior test overrode it to simulate a write failure.
71
+ writeFileSyncMock.mockClear();
72
+ });
73
+ afterEach(() => {
74
+ rmSync(homeDir, { recursive: true, force: true });
75
+ rmSync(manifestDir, { recursive: true, force: true });
76
+ if (prevInstallDirEnv !== undefined)
77
+ process.env[AGENT_INSTALL_DIR_ENV_VAR] = prevInstallDirEnv;
78
+ else
79
+ delete process.env[AGENT_INSTALL_DIR_ENV_VAR];
80
+ vi.restoreAllMocks();
81
+ });
82
+ describe('installAgentPack — cursor mcp.json entry shape (SMI-6279 Wave 9)', () => {
83
+ it('writes the entry under the @skillsmith/mcp-server key with a resolved binary path + SKILLSMITH_CLIENT=cursor', () => {
84
+ execFileSyncMock.mockReturnValue(`${RESOLVED_BIN_PATH}\n`);
85
+ seedCursorPresent();
86
+ const result = installAgentPack({ homeDir });
87
+ const doc = readCursorMcpJson(homeDir);
88
+ const entry = doc.mcpServers['@skillsmith/mcp-server'];
89
+ expect(entry?.command).toBe(RESOLVED_BIN_PATH);
90
+ expect(entry?.env?.SKILLSMITH_CLIENT).toBe('cursor');
91
+ expect(entry?.env?.SKILLSMITH_TOOL_PROFILE).toBe('agent');
92
+ // No `args` — unlike the broken npx form, Cursor's entry invokes the
93
+ // resolved binary directly.
94
+ expect(entry?.args).toBeUndefined();
95
+ // No stray legacy key on a first-ever install.
96
+ expect(doc.mcpServers.skillsmith).toBeUndefined();
97
+ const report = result.harnessReports.find((r) => r.harness === 'cursor');
98
+ expect(report?.mcpConfig?.status).toBe('created');
99
+ });
100
+ it('falls back to the documented paste-here placeholder when the binary cannot be resolved', () => {
101
+ execFileSyncMock.mockImplementation(() => {
102
+ throw new Error('not found');
103
+ });
104
+ seedCursorPresent();
105
+ installAgentPack({ homeDir });
106
+ const doc = readCursorMcpJson(homeDir);
107
+ const entry = doc.mcpServers['@skillsmith/mcp-server'];
108
+ expect(entry?.command).toContain('which skillsmith-mcp');
109
+ expect(entry?.command).toContain('where skillsmith-mcp');
110
+ });
111
+ it('falls back to the placeholder (never hangs) when the which/where lookup times out — code-review finding, GPT-5.6-Sol / SMI-6279', () => {
112
+ // execFileSync throws a synchronous ETIMEDOUT-shaped error when its own
113
+ // `timeout` option elapses — the existing blanket catch already handles
114
+ // this the same as "not found", so simulating that error is sufficient
115
+ // to prove the timeout-case fallback without an actual hung process.
116
+ const timeoutError = Object.assign(new Error('spawnSync which ETIMEDOUT'), {
117
+ code: 'ETIMEDOUT',
118
+ killed: true,
119
+ signal: 'SIGTERM',
120
+ });
121
+ execFileSyncMock.mockImplementation(() => {
122
+ throw timeoutError;
123
+ });
124
+ seedCursorPresent();
125
+ installAgentPack({ homeDir });
126
+ const doc = readCursorMcpJson(homeDir);
127
+ const entry = doc.mcpServers['@skillsmith/mcp-server'];
128
+ expect(entry?.command).toContain('which skillsmith-mcp');
129
+ // And the bound is actually wired to the real execFileSync call, not
130
+ // just documented — a `timeout` option keeps a hung/substituted
131
+ // which/where from blocking `agent install` indefinitely.
132
+ expect(execFileSyncMock).toHaveBeenCalledWith(expect.any(String), ['skillsmith-mcp'], expect.objectContaining({ timeout: expect.any(Number) }));
133
+ const [, , options] = execFileSyncMock.mock.calls[0];
134
+ expect(options.timeout).toBeGreaterThan(0);
135
+ // A few seconds is plenty for a local PATH lookup — not a network call.
136
+ expect(options.timeout).toBeLessThanOrEqual(5000);
137
+ });
138
+ it('does not regress claude-code’s own entry — still the npx form under the "skillsmith" key', () => {
139
+ execFileSyncMock.mockReturnValue(`${RESOLVED_BIN_PATH}\n`);
140
+ seedCursorPresent();
141
+ installAgentPack({ homeDir });
142
+ const claudeDoc = JSON.parse(readFileSync(join(homeDir, '.claude', 'settings.json'), 'utf-8'));
143
+ expect(claudeDoc.mcpServers.skillsmith?.command).toBe('npx');
144
+ expect(claudeDoc.mcpServers.skillsmith?.env?.SKILLSMITH_TOOL_PROFILE).toBe('agent');
145
+ expect(claudeDoc.mcpServers.skillsmith?.env?.SKILLSMITH_CLIENT).toBeUndefined();
146
+ });
147
+ });
148
+ describe('installAgentPack — cursor mcp.json idempotency (SMI-6279 Wave 9)', () => {
149
+ it('re-install does not create a duplicate second server entry', () => {
150
+ execFileSyncMock.mockReturnValue(`${RESOLVED_BIN_PATH}\n`);
151
+ seedCursorPresent();
152
+ installAgentPack({ homeDir });
153
+ const second = installAgentPack({ homeDir });
154
+ const doc = readCursorMcpJson(homeDir);
155
+ expect(Object.keys(doc.mcpServers)).toEqual(['@skillsmith/mcp-server']);
156
+ const report = second.harnessReports.find((r) => r.harness === 'cursor');
157
+ expect(report?.mcpConfig?.status).toBe('unchanged');
158
+ });
159
+ });
160
+ describe('installAgentPack — cursor mcp.json stale legacy-key cleanup (SMI-6279 Wave 9)', () => {
161
+ it('removes a stale "skillsmith"-keyed entry from a pre-fix install, leaving exactly one entry', () => {
162
+ execFileSyncMock.mockReturnValue(`${RESOLVED_BIN_PATH}\n`);
163
+ seedCursorPresent();
164
+ writeFileSync(mcpJsonPath(homeDir), JSON.stringify({
165
+ mcpServers: {
166
+ skillsmith: {
167
+ command: 'npx',
168
+ args: ['-y', '@skillsmith/mcp-server'],
169
+ env: { SKILLSMITH_TOOL_PROFILE: 'agent' },
170
+ },
171
+ },
172
+ }, null, 2));
173
+ installAgentPack({ homeDir });
174
+ const doc = readCursorMcpJson(homeDir);
175
+ expect(doc.mcpServers.skillsmith).toBeUndefined();
176
+ expect(doc.mcpServers['@skillsmith/mcp-server']?.command).toBe(RESOLVED_BIN_PATH);
177
+ expect(Object.keys(doc.mcpServers)).toEqual(['@skillsmith/mcp-server']);
178
+ });
179
+ it('preserves a foreign entry under the legacy "skillsmith" key — never deletes a user-owned unrelated entry', () => {
180
+ execFileSyncMock.mockReturnValue(`${RESOLVED_BIN_PATH}\n`);
181
+ seedCursorPresent();
182
+ const foreignEntry = { command: 'some-other-tool', args: ['--flag'] };
183
+ writeFileSync(mcpJsonPath(homeDir), JSON.stringify({ mcpServers: { skillsmith: foreignEntry } }, null, 2));
184
+ installAgentPack({ homeDir });
185
+ const doc = readCursorMcpJson(homeDir);
186
+ expect(doc.mcpServers.skillsmith).toEqual(foreignEntry);
187
+ expect(doc.mcpServers['@skillsmith/mcp-server']?.command).toBe(RESOLVED_BIN_PATH);
188
+ });
189
+ it('preserves a near-miss entry that references the package name in an extra description field (code-review finding, GPT-5.6-Sol / SMI-6279)', () => {
190
+ execFileSyncMock.mockReturnValue(`${RESOLVED_BIN_PATH}\n`);
191
+ seedCursorPresent();
192
+ // Structurally close to our own legacy shape (same command/args/env
193
+ // value) but NOT byte-identical — one extra key. The old loose
194
+ // `looksLikeOurMcpEntry` heuristic (substring-matches args, checks only
195
+ // key presence) would have matched this and deleted it; the tightened
196
+ // exact-shape check must not.
197
+ const nearMissEntry = {
198
+ command: 'npx',
199
+ args: ['-y', '@skillsmith/mcp-server'],
200
+ env: { SKILLSMITH_TOOL_PROFILE: 'agent' },
201
+ description: 'Custom wrapper — see @skillsmith/mcp-server docs for context',
202
+ };
203
+ writeFileSync(mcpJsonPath(homeDir), JSON.stringify({ mcpServers: { skillsmith: nearMissEntry } }, null, 2));
204
+ installAgentPack({ homeDir });
205
+ const doc = readCursorMcpJson(homeDir);
206
+ expect(doc.mcpServers.skillsmith).toEqual(nearMissEntry);
207
+ expect(doc.mcpServers['@skillsmith/mcp-server']?.command).toBe(RESOLVED_BIN_PATH);
208
+ });
209
+ it('preserves a near-miss "skillsmith"-keyed entry whose SKILLSMITH_TOOL_PROFILE value differs from what we would have written (code-review finding, GPT-5.6-Sol / SMI-6279)', () => {
210
+ execFileSyncMock.mockReturnValue(`${RESOLVED_BIN_PATH}\n`);
211
+ seedCursorPresent();
212
+ // Same command/args/key SET as our legacy shape, but a different env
213
+ // VALUE — the old loose heuristic only checked key presence, not value,
214
+ // and would have matched+deleted this too.
215
+ const nearMissEntry = {
216
+ command: 'npx',
217
+ args: ['-y', '@skillsmith/mcp-server'],
218
+ env: { SKILLSMITH_TOOL_PROFILE: 'debug' },
219
+ };
220
+ writeFileSync(mcpJsonPath(homeDir), JSON.stringify({ mcpServers: { skillsmith: nearMissEntry } }, null, 2));
221
+ installAgentPack({ homeDir });
222
+ const doc = readCursorMcpJson(homeDir);
223
+ expect(doc.mcpServers.skillsmith).toEqual(nearMissEntry);
224
+ expect(doc.mcpServers['@skillsmith/mcp-server']?.command).toBe(RESOLVED_BIN_PATH);
225
+ });
226
+ it('is idempotent: a second install run on an already-migrated file makes no further legacy-key change', () => {
227
+ execFileSyncMock.mockReturnValue(`${RESOLVED_BIN_PATH}\n`);
228
+ seedCursorPresent();
229
+ writeFileSync(mcpJsonPath(homeDir), JSON.stringify({
230
+ mcpServers: {
231
+ skillsmith: {
232
+ command: 'npx',
233
+ args: ['-y', '@skillsmith/mcp-server'],
234
+ env: { SKILLSMITH_TOOL_PROFILE: 'agent' },
235
+ },
236
+ },
237
+ }, null, 2));
238
+ installAgentPack({ homeDir }); // first run: writes the new key, cleans the legacy one
239
+ const afterFirst = readFileSync(mcpJsonPath(homeDir), 'utf-8');
240
+ const second = installAgentPack({ homeDir }); // second run: nothing left to clean
241
+ const afterSecond = readFileSync(mcpJsonPath(homeDir), 'utf-8');
242
+ expect(afterSecond).toBe(afterFirst);
243
+ const report = second.harnessReports.find((r) => r.harness === 'cursor');
244
+ expect(report?.mcpConfig?.status).toBe('unchanged');
245
+ });
246
+ it('reports a cleanup write failure via report.notes instead of swallowing it as "nothing to clean up" (PR-07 finding, GPT-5.6-Sol / SMI-6279)', () => {
247
+ execFileSyncMock.mockReturnValue(`${RESOLVED_BIN_PATH}\n`);
248
+ seedCursorPresent();
249
+ // Seed BOTH the already-correct new entry and the stale legacy entry, so
250
+ // the main merge sees 'unchanged' (no write attempted there) and only
251
+ // the cleanup step's own write is exercised below.
252
+ writeFileSync(mcpJsonPath(homeDir), JSON.stringify({
253
+ mcpServers: {
254
+ skillsmith: {
255
+ command: 'npx',
256
+ args: ['-y', '@skillsmith/mcp-server'],
257
+ env: { SKILLSMITH_TOOL_PROFILE: 'agent' },
258
+ },
259
+ '@skillsmith/mcp-server': {
260
+ command: RESOLVED_BIN_PATH,
261
+ env: { SKILLSMITH_TOOL_PROFILE: 'agent', SKILLSMITH_CLIENT: 'cursor' },
262
+ },
263
+ },
264
+ }, null, 2));
265
+ // Target only the cleanup's write to THIS file — installAgentPack also
266
+ // writes several unrelated skill-pack files earlier in the same run, and
267
+ // must keep writing those for real.
268
+ const targetPath = mcpJsonPath(homeDir);
269
+ writeFileSyncMock.mockImplementation((...args) => {
270
+ if (args[0] === targetPath) {
271
+ throw new Error('EACCES: permission denied (simulated)');
272
+ }
273
+ return realWriteFileSyncRef.current(...args);
274
+ });
275
+ const result = installAgentPack({ homeDir });
276
+ // The legacy key must still be on disk — the failed write must not have
277
+ // corrupted or partially applied the delete.
278
+ const doc = readCursorMcpJson(homeDir);
279
+ expect(doc.mcpServers.skillsmith).toBeDefined();
280
+ const report = result.harnessReports.find((r) => r.harness === 'cursor');
281
+ expect(report?.notes.some((n) => n.includes('could not remove it'))).toBe(true);
282
+ expect(report?.notes.some((n) => n.includes('EACCES'))).toBe(true);
283
+ });
284
+ });
285
+ //# sourceMappingURL=agent-pack-installer.cursor-mcp.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-pack-installer.cursor-mcp.test.js","sourceRoot":"","sources":["../../../src/install/agent-pack-installer.cursor-mcp.test.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,14 @@
24
24
  * - The `skillsmith` MCP server registration (`SKILLSMITH_TOOL_PROFILE=agent`)
25
25
  * for every detected MCP-capable harness (all 7), backup-first,
26
26
  * idempotent, preserve-and-prompt on a foreign entry.
27
+ * - AntiGravity (SMI-6275 Wave 5): a workspace-scoped 8th target, handled
28
+ * OUTSIDE the 7-harness loop above — see the `antigravity` block near
29
+ * the end of `installAgentPack`. Whenever its workspace scope resolves
30
+ * (an existing `.agents/` marker auto-detects, or `--scope workspace`
31
+ * creates one), writes the skill pack AND `.agents/mcp_config.json`
32
+ * (`installAntigravityMcpConfig`, `agent-pack-installer.antigravity-mcp.ts`)
33
+ * — MCP config only, no hooks/shim this wave (stated decision, see
34
+ * `HOOK_HARNESSES`'s doc comment in `services/agent-pack/types.ts`).
27
35
  *
28
36
  * Every write funnels through `writeOwnedArtifactFile` (owned files) or the
29
37
  * `agent-config-merge.*` helpers (shared config files), both of which record
@@ -1 +1 @@
1
- {"version":3,"file":"agent-pack-installer.d.ts","sourceRoot":"","sources":["../../../src/install/agent-pack-installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAWH,OAAO,EAGL,iBAAiB,EAGlB,MAAM,qBAAqB,CAAA;AAU5B,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EAExB,MAAM,iCAAiC,CAAA;AA4FxC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,mBAAwB,GAAG,kBAAkB,CAqInF;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAA"}
1
+ {"version":3,"file":"agent-pack-installer.d.ts","sourceRoot":"","sources":["../../../src/install/agent-pack-installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAYH,OAAO,EAGL,iBAAiB,EAGlB,MAAM,qBAAqB,CAAA;AAY5B,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EAExB,MAAM,iCAAiC,CAAA;AA4FxC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,mBAAwB,GAAG,kBAAkB,CA0NnF;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAA"}