@skillsmith/core 0.8.2 → 0.10.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 (347) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/api/client.d.ts.map +1 -1
  4. package/dist/src/api/client.js +6 -0
  5. package/dist/src/api/client.js.map +1 -1
  6. package/dist/src/api/client.test.d.ts +9 -0
  7. package/dist/src/api/client.test.d.ts.map +1 -0
  8. package/dist/src/api/client.test.js +81 -0
  9. package/dist/src/api/client.test.js.map +1 -0
  10. package/dist/src/config/device-identity.d.ts +113 -0
  11. package/dist/src/config/device-identity.d.ts.map +1 -0
  12. package/dist/src/config/device-identity.js +171 -0
  13. package/dist/src/config/device-identity.js.map +1 -0
  14. package/dist/src/config/device-identity.test.d.ts +10 -0
  15. package/dist/src/config/device-identity.test.d.ts.map +1 -0
  16. package/dist/src/config/device-identity.test.js +213 -0
  17. package/dist/src/config/device-identity.test.js.map +1 -0
  18. package/dist/src/config/index.d.ts +9 -0
  19. package/dist/src/config/index.d.ts.map +1 -1
  20. package/dist/src/config/index.js.map +1 -1
  21. package/dist/src/exports/services.d.ts +3 -1
  22. package/dist/src/exports/services.d.ts.map +1 -1
  23. package/dist/src/exports/services.js +11 -1
  24. package/dist/src/exports/services.js.map +1 -1
  25. package/dist/src/index.d.ts +4 -3
  26. package/dist/src/index.d.ts.map +1 -1
  27. package/dist/src/index.js +7 -2
  28. package/dist/src/index.js.map +1 -1
  29. package/dist/src/install/agent-config-merge.json-array.d.ts +29 -0
  30. package/dist/src/install/agent-config-merge.json-array.d.ts.map +1 -0
  31. package/dist/src/install/agent-config-merge.json-array.js +100 -0
  32. package/dist/src/install/agent-config-merge.json-array.js.map +1 -0
  33. package/dist/src/install/agent-config-merge.json.d.ts +37 -0
  34. package/dist/src/install/agent-config-merge.json.d.ts.map +1 -0
  35. package/dist/src/install/agent-config-merge.json.js +134 -0
  36. package/dist/src/install/agent-config-merge.json.js.map +1 -0
  37. package/dist/src/install/agent-config-merge.toml-block.d.ts +48 -0
  38. package/dist/src/install/agent-config-merge.toml-block.d.ts.map +1 -0
  39. package/dist/src/install/agent-config-merge.toml-block.js +107 -0
  40. package/dist/src/install/agent-config-merge.toml-block.js.map +1 -0
  41. package/dist/src/install/agent-config-merge.types.d.ts +87 -0
  42. package/dist/src/install/agent-config-merge.types.d.ts.map +1 -0
  43. package/dist/src/install/agent-config-merge.types.js +83 -0
  44. package/dist/src/install/agent-config-merge.types.js.map +1 -0
  45. package/dist/src/install/agent-config-merge.yaml.d.ts +46 -0
  46. package/dist/src/install/agent-config-merge.yaml.d.ts.map +1 -0
  47. package/dist/src/install/agent-config-merge.yaml.js +133 -0
  48. package/dist/src/install/agent-config-merge.yaml.js.map +1 -0
  49. package/dist/src/install/agent-config-merge.yaml.test.d.ts +2 -0
  50. package/dist/src/install/agent-config-merge.yaml.test.d.ts.map +1 -0
  51. package/dist/src/install/agent-config-merge.yaml.test.js +210 -0
  52. package/dist/src/install/agent-config-merge.yaml.test.js.map +1 -0
  53. package/dist/src/install/agent-harness-targets.d.ts +98 -0
  54. package/dist/src/install/agent-harness-targets.d.ts.map +1 -0
  55. package/dist/src/install/agent-harness-targets.js +154 -0
  56. package/dist/src/install/agent-harness-targets.js.map +1 -0
  57. package/dist/src/install/agent-home-relocate.d.ts +29 -0
  58. package/dist/src/install/agent-home-relocate.d.ts.map +1 -0
  59. package/dist/src/install/agent-home-relocate.js +38 -0
  60. package/dist/src/install/agent-home-relocate.js.map +1 -0
  61. package/dist/src/install/agent-manifest-path-guard.d.ts +55 -0
  62. package/dist/src/install/agent-manifest-path-guard.d.ts.map +1 -0
  63. package/dist/src/install/agent-manifest-path-guard.js +109 -0
  64. package/dist/src/install/agent-manifest-path-guard.js.map +1 -0
  65. package/dist/src/install/agent-manifest-path-guard.test.d.ts +2 -0
  66. package/dist/src/install/agent-manifest-path-guard.test.d.ts.map +1 -0
  67. package/dist/src/install/agent-manifest-path-guard.test.js +72 -0
  68. package/dist/src/install/agent-manifest-path-guard.test.js.map +1 -0
  69. package/dist/src/install/agent-manifest.d.ts +58 -0
  70. package/dist/src/install/agent-manifest.d.ts.map +1 -0
  71. package/dist/src/install/agent-manifest.js +103 -0
  72. package/dist/src/install/agent-manifest.js.map +1 -0
  73. package/dist/src/install/agent-pack-installer.d.ts +39 -0
  74. package/dist/src/install/agent-pack-installer.d.ts.map +1 -0
  75. package/dist/src/install/agent-pack-installer.entry.d.ts +55 -0
  76. package/dist/src/install/agent-pack-installer.entry.d.ts.map +1 -0
  77. package/dist/src/install/agent-pack-installer.entry.js +90 -0
  78. package/dist/src/install/agent-pack-installer.entry.js.map +1 -0
  79. package/dist/src/install/agent-pack-installer.fs-helpers.d.ts +33 -0
  80. package/dist/src/install/agent-pack-installer.fs-helpers.d.ts.map +1 -0
  81. package/dist/src/install/agent-pack-installer.fs-helpers.js +59 -0
  82. package/dist/src/install/agent-pack-installer.fs-helpers.js.map +1 -0
  83. package/dist/src/install/agent-pack-installer.harness.d.ts +66 -0
  84. package/dist/src/install/agent-pack-installer.harness.d.ts.map +1 -0
  85. package/dist/src/install/agent-pack-installer.harness.js +310 -0
  86. package/dist/src/install/agent-pack-installer.harness.js.map +1 -0
  87. package/dist/src/install/agent-pack-installer.js +221 -0
  88. package/dist/src/install/agent-pack-installer.js.map +1 -0
  89. package/dist/src/install/agent-pack-installer.preserve.test.d.ts +11 -0
  90. package/dist/src/install/agent-pack-installer.preserve.test.d.ts.map +1 -0
  91. package/dist/src/install/agent-pack-installer.preserve.test.js +72 -0
  92. package/dist/src/install/agent-pack-installer.preserve.test.js.map +1 -0
  93. package/dist/src/install/agent-pack-installer.test.d.ts +2 -0
  94. package/dist/src/install/agent-pack-installer.test.d.ts.map +1 -0
  95. package/dist/src/install/agent-pack-installer.test.js +350 -0
  96. package/dist/src/install/agent-pack-installer.test.js.map +1 -0
  97. package/dist/src/install/agent-pack-installer.types.d.ts +51 -0
  98. package/dist/src/install/agent-pack-installer.types.d.ts.map +1 -0
  99. package/dist/src/install/agent-pack-installer.types.js +16 -0
  100. package/dist/src/install/agent-pack-installer.types.js.map +1 -0
  101. package/dist/src/install/agent-pack-uninstaller.d.ts +43 -0
  102. package/dist/src/install/agent-pack-uninstaller.d.ts.map +1 -0
  103. package/dist/src/install/agent-pack-uninstaller.js +113 -0
  104. package/dist/src/install/agent-pack-uninstaller.js.map +1 -0
  105. package/dist/src/install/agent-pack-uninstaller.test.d.ts +2 -0
  106. package/dist/src/install/agent-pack-uninstaller.test.d.ts.map +1 -0
  107. package/dist/src/install/agent-pack-uninstaller.test.js +212 -0
  108. package/dist/src/install/agent-pack-uninstaller.test.js.map +1 -0
  109. package/dist/src/install/index.d.ts +8 -1
  110. package/dist/src/install/index.d.ts.map +1 -1
  111. package/dist/src/install/index.js +8 -1
  112. package/dist/src/install/index.js.map +1 -1
  113. package/dist/src/install/paths.d.ts +17 -1
  114. package/dist/src/install/paths.d.ts.map +1 -1
  115. package/dist/src/install/paths.js +26 -0
  116. package/dist/src/install/paths.js.map +1 -1
  117. package/dist/src/install/paths.test.d.ts +2 -0
  118. package/dist/src/install/paths.test.d.ts.map +1 -0
  119. package/dist/src/install/paths.test.js +76 -0
  120. package/dist/src/install/paths.test.js.map +1 -0
  121. package/dist/src/journal/hash.d.ts +13 -0
  122. package/dist/src/journal/hash.d.ts.map +1 -0
  123. package/dist/src/journal/hash.js +16 -0
  124. package/dist/src/journal/hash.js.map +1 -0
  125. package/dist/src/journal/index.d.ts +15 -0
  126. package/dist/src/journal/index.d.ts.map +1 -0
  127. package/dist/src/journal/index.js +15 -0
  128. package/dist/src/journal/index.js.map +1 -0
  129. package/dist/src/journal/journal.test.d.ts +16 -0
  130. package/dist/src/journal/journal.test.d.ts.map +1 -0
  131. package/dist/src/journal/journal.test.js +171 -0
  132. package/dist/src/journal/journal.test.js.map +1 -0
  133. package/dist/src/journal/path.d.ts +44 -0
  134. package/dist/src/journal/path.d.ts.map +1 -0
  135. package/dist/src/journal/path.js +61 -0
  136. package/dist/src/journal/path.js.map +1 -0
  137. package/dist/src/journal/reader.d.ts +38 -0
  138. package/dist/src/journal/reader.d.ts.map +1 -0
  139. package/dist/src/journal/reader.js +93 -0
  140. package/dist/src/journal/reader.js.map +1 -0
  141. package/dist/src/journal/types.d.ts +87 -0
  142. package/dist/src/journal/types.d.ts.map +1 -0
  143. package/dist/src/journal/types.js +21 -0
  144. package/dist/src/journal/types.js.map +1 -0
  145. package/dist/src/journal/writer.d.ts +52 -0
  146. package/dist/src/journal/writer.d.ts.map +1 -0
  147. package/dist/src/journal/writer.js +125 -0
  148. package/dist/src/journal/writer.js.map +1 -0
  149. package/dist/src/paywall-triggers/index.d.ts +13 -0
  150. package/dist/src/paywall-triggers/index.d.ts.map +1 -0
  151. package/dist/src/paywall-triggers/index.js +13 -0
  152. package/dist/src/paywall-triggers/index.js.map +1 -0
  153. package/dist/src/paywall-triggers/path.d.ts +47 -0
  154. package/dist/src/paywall-triggers/path.d.ts.map +1 -0
  155. package/dist/src/paywall-triggers/path.js +73 -0
  156. package/dist/src/paywall-triggers/path.js.map +1 -0
  157. package/dist/src/paywall-triggers/store.d.ts +75 -0
  158. package/dist/src/paywall-triggers/store.d.ts.map +1 -0
  159. package/dist/src/paywall-triggers/store.js +122 -0
  160. package/dist/src/paywall-triggers/store.js.map +1 -0
  161. package/dist/src/paywall-triggers/store.test.d.ts +2 -0
  162. package/dist/src/paywall-triggers/store.test.d.ts.map +1 -0
  163. package/dist/src/paywall-triggers/store.test.js +121 -0
  164. package/dist/src/paywall-triggers/store.test.js.map +1 -0
  165. package/dist/src/paywall-triggers/types.d.ts +24 -0
  166. package/dist/src/paywall-triggers/types.d.ts.map +1 -0
  167. package/dist/src/paywall-triggers/types.js +13 -0
  168. package/dist/src/paywall-triggers/types.js.map +1 -0
  169. package/dist/src/security/scanner/SecurityScanner.compound.d.ts +13 -0
  170. package/dist/src/security/scanner/SecurityScanner.compound.d.ts.map +1 -0
  171. package/dist/src/security/scanner/SecurityScanner.compound.js +127 -0
  172. package/dist/src/security/scanner/SecurityScanner.compound.js.map +1 -0
  173. package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
  174. package/dist/src/security/scanner/SecurityScanner.js +10 -1
  175. package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
  176. package/dist/src/security/scanner/SecurityScanner.pii.d.ts +23 -0
  177. package/dist/src/security/scanner/SecurityScanner.pii.d.ts.map +1 -0
  178. package/dist/src/security/scanner/SecurityScanner.pii.js +152 -0
  179. package/dist/src/security/scanner/SecurityScanner.pii.js.map +1 -0
  180. package/dist/src/security/scanner/SecurityScanner.scanners.d.ts +5 -2
  181. package/dist/src/security/scanner/SecurityScanner.scanners.d.ts.map +1 -1
  182. package/dist/src/security/scanner/SecurityScanner.scanners.js +63 -70
  183. package/dist/src/security/scanner/SecurityScanner.scanners.js.map +1 -1
  184. package/dist/src/security/scanner/patterns.d.ts +2 -0
  185. package/dist/src/security/scanner/patterns.d.ts.map +1 -1
  186. package/dist/src/security/scanner/patterns.js +79 -11
  187. package/dist/src/security/scanner/patterns.js.map +1 -1
  188. package/dist/src/security/scanner/types.d.ts +2 -0
  189. package/dist/src/security/scanner/types.d.ts.map +1 -1
  190. package/dist/src/services/agent-pack/agent-pack.test.d.ts +18 -0
  191. package/dist/src/services/agent-pack/agent-pack.test.d.ts.map +1 -0
  192. package/dist/src/services/agent-pack/agent-pack.test.js +344 -0
  193. package/dist/src/services/agent-pack/agent-pack.test.js.map +1 -0
  194. package/dist/src/services/agent-pack/hooks.d.ts +29 -0
  195. package/dist/src/services/agent-pack/hooks.d.ts.map +1 -0
  196. package/dist/src/services/agent-pack/hooks.js +139 -0
  197. package/dist/src/services/agent-pack/hooks.js.map +1 -0
  198. package/dist/src/services/agent-pack/index.d.ts +26 -0
  199. package/dist/src/services/agent-pack/index.d.ts.map +1 -0
  200. package/dist/src/services/agent-pack/index.js +109 -0
  201. package/dist/src/services/agent-pack/index.js.map +1 -0
  202. package/dist/src/services/agent-pack/prompt-source.d.ts +47 -0
  203. package/dist/src/services/agent-pack/prompt-source.d.ts.map +1 -0
  204. package/dist/src/services/agent-pack/prompt-source.js +182 -0
  205. package/dist/src/services/agent-pack/prompt-source.js.map +1 -0
  206. package/dist/src/services/agent-pack/shims.d.ts +40 -0
  207. package/dist/src/services/agent-pack/shims.d.ts.map +1 -0
  208. package/dist/src/services/agent-pack/shims.js +96 -0
  209. package/dist/src/services/agent-pack/shims.js.map +1 -0
  210. package/dist/src/services/agent-pack/skill-md.d.ts +35 -0
  211. package/dist/src/services/agent-pack/skill-md.d.ts.map +1 -0
  212. package/dist/src/services/agent-pack/skill-md.js +89 -0
  213. package/dist/src/services/agent-pack/skill-md.js.map +1 -0
  214. package/dist/src/services/agent-pack/types.d.ts +118 -0
  215. package/dist/src/services/agent-pack/types.d.ts.map +1 -0
  216. package/dist/src/services/agent-pack/types.js +61 -0
  217. package/dist/src/services/agent-pack/types.js.map +1 -0
  218. package/dist/src/services/agent-tool-profile.d.ts +59 -0
  219. package/dist/src/services/agent-tool-profile.d.ts.map +1 -0
  220. package/dist/src/services/agent-tool-profile.js +76 -0
  221. package/dist/src/services/agent-tool-profile.js.map +1 -0
  222. package/dist/src/services/agent-tool-profile.test.d.ts +2 -0
  223. package/dist/src/services/agent-tool-profile.test.d.ts.map +1 -0
  224. package/dist/src/services/agent-tool-profile.test.js +28 -0
  225. package/dist/src/services/agent-tool-profile.test.js.map +1 -0
  226. package/dist/src/services/bundled-sibling-scan.d.ts +111 -0
  227. package/dist/src/services/bundled-sibling-scan.d.ts.map +1 -0
  228. package/dist/src/services/bundled-sibling-scan.js +170 -0
  229. package/dist/src/services/bundled-sibling-scan.js.map +1 -0
  230. package/dist/src/services/skill-installation.io.d.ts +16 -5
  231. package/dist/src/services/skill-installation.io.d.ts.map +1 -1
  232. package/dist/src/services/skill-installation.io.js +44 -20
  233. package/dist/src/services/skill-installation.io.js.map +1 -1
  234. package/dist/src/services/skill-installation.policy.d.ts +96 -0
  235. package/dist/src/services/skill-installation.policy.d.ts.map +1 -0
  236. package/dist/src/services/skill-installation.policy.js +144 -0
  237. package/dist/src/services/skill-installation.policy.js.map +1 -0
  238. package/dist/src/services/skill-installation.service.d.ts.map +1 -1
  239. package/dist/src/services/skill-installation.service.js +9 -3
  240. package/dist/src/services/skill-installation.service.js.map +1 -1
  241. package/dist/src/sources/index.d.ts +1 -0
  242. package/dist/src/sources/index.d.ts.map +1 -1
  243. package/dist/src/sources/index.js +4 -0
  244. package/dist/src/sources/index.js.map +1 -1
  245. package/dist/src/sync/index.d.ts +6 -0
  246. package/dist/src/sync/index.d.ts.map +1 -1
  247. package/dist/src/sync/index.js +8 -0
  248. package/dist/src/sync/index.js.map +1 -1
  249. package/dist/src/sync/inventory-builder.d.ts +21 -0
  250. package/dist/src/sync/inventory-builder.d.ts.map +1 -0
  251. package/dist/src/sync/inventory-builder.js +26 -0
  252. package/dist/src/sync/inventory-builder.js.map +1 -0
  253. package/dist/src/sync/inventory-client.d.ts +80 -0
  254. package/dist/src/sync/inventory-client.d.ts.map +1 -0
  255. package/dist/src/sync/inventory-client.js +204 -0
  256. package/dist/src/sync/inventory-client.js.map +1 -0
  257. package/dist/src/sync/inventory-client.test.d.ts +14 -0
  258. package/dist/src/sync/inventory-client.test.d.ts.map +1 -0
  259. package/dist/src/sync/inventory-client.test.js +212 -0
  260. package/dist/src/sync/inventory-client.test.js.map +1 -0
  261. package/dist/src/sync/inventory-collector.d.ts +35 -0
  262. package/dist/src/sync/inventory-collector.d.ts.map +1 -0
  263. package/dist/src/sync/inventory-collector.js +176 -0
  264. package/dist/src/sync/inventory-collector.js.map +1 -0
  265. package/dist/src/sync/inventory-collector.test.d.ts +14 -0
  266. package/dist/src/sync/inventory-collector.test.d.ts.map +1 -0
  267. package/dist/src/sync/inventory-collector.test.js +156 -0
  268. package/dist/src/sync/inventory-collector.test.js.map +1 -0
  269. package/dist/src/sync/inventory-device.d.ts +36 -0
  270. package/dist/src/sync/inventory-device.d.ts.map +1 -0
  271. package/dist/src/sync/inventory-device.js +58 -0
  272. package/dist/src/sync/inventory-device.js.map +1 -0
  273. package/dist/src/sync/inventory-push.d.ts +45 -0
  274. package/dist/src/sync/inventory-push.d.ts.map +1 -0
  275. package/dist/src/sync/inventory-push.js +62 -0
  276. package/dist/src/sync/inventory-push.js.map +1 -0
  277. package/dist/src/sync/inventory-push.test.d.ts +16 -0
  278. package/dist/src/sync/inventory-push.test.d.ts.map +1 -0
  279. package/dist/src/sync/inventory-push.test.js +104 -0
  280. package/dist/src/sync/inventory-push.test.js.map +1 -0
  281. package/dist/src/sync/inventory-types.d.ts +110 -0
  282. package/dist/src/sync/inventory-types.d.ts.map +1 -0
  283. package/dist/src/sync/inventory-types.js +45 -0
  284. package/dist/src/sync/inventory-types.js.map +1 -0
  285. package/dist/src/telemetry/agent-marker.d.ts +137 -0
  286. package/dist/src/telemetry/agent-marker.d.ts.map +1 -0
  287. package/dist/src/telemetry/agent-marker.js +242 -0
  288. package/dist/src/telemetry/agent-marker.js.map +1 -0
  289. package/dist/src/telemetry/agent-marker.test.d.ts +13 -0
  290. package/dist/src/telemetry/agent-marker.test.d.ts.map +1 -0
  291. package/dist/src/telemetry/agent-marker.test.js +202 -0
  292. package/dist/src/telemetry/agent-marker.test.js.map +1 -0
  293. package/dist/src/telemetry/index.d.ts +2 -1
  294. package/dist/src/telemetry/index.d.ts.map +1 -1
  295. package/dist/src/telemetry/index.js +6 -1
  296. package/dist/src/telemetry/index.js.map +1 -1
  297. package/dist/src/telemetry/posthog.d.ts +10 -0
  298. package/dist/src/telemetry/posthog.d.ts.map +1 -1
  299. package/dist/src/telemetry/posthog.js +5 -1
  300. package/dist/src/telemetry/posthog.js.map +1 -1
  301. package/dist/src/telemetry/wrap.d.ts +28 -7
  302. package/dist/src/telemetry/wrap.d.ts.map +1 -1
  303. package/dist/src/telemetry/wrap.gate.test.d.ts +22 -0
  304. package/dist/src/telemetry/wrap.gate.test.d.ts.map +1 -0
  305. package/dist/src/telemetry/wrap.gate.test.js +197 -0
  306. package/dist/src/telemetry/wrap.gate.test.js.map +1 -0
  307. package/dist/src/telemetry/wrap.js +111 -26
  308. package/dist/src/telemetry/wrap.js.map +1 -1
  309. package/dist/src/telemetry/wrap.marker.test.d.ts +16 -0
  310. package/dist/src/telemetry/wrap.marker.test.d.ts.map +1 -0
  311. package/dist/src/telemetry/wrap.marker.test.js +185 -0
  312. package/dist/src/telemetry/wrap.marker.test.js.map +1 -0
  313. package/dist/src/telemetry/wrap.test.js +4 -0
  314. package/dist/src/telemetry/wrap.test.js.map +1 -1
  315. package/dist/tests/SecurityScanner.exec.test.js +60 -0
  316. package/dist/tests/SecurityScanner.exec.test.js.map +1 -1
  317. package/dist/tests/security/ContinuousSecurity.test.js +10 -4
  318. package/dist/tests/security/ContinuousSecurity.test.js.map +1 -1
  319. package/dist/tests/security/SecurityScanner.chmod-evasion.test.d.ts +2 -0
  320. package/dist/tests/security/SecurityScanner.chmod-evasion.test.d.ts.map +1 -0
  321. package/dist/tests/security/SecurityScanner.chmod-evasion.test.js +126 -0
  322. package/dist/tests/security/SecurityScanner.chmod-evasion.test.js.map +1 -0
  323. package/dist/tests/security/chmod-compound.test.d.ts +2 -0
  324. package/dist/tests/security/chmod-compound.test.d.ts.map +1 -0
  325. package/dist/tests/security/chmod-compound.test.js +188 -0
  326. package/dist/tests/security/chmod-compound.test.js.map +1 -0
  327. package/dist/tests/security/pii-detection.test.js +131 -0
  328. package/dist/tests/security/pii-detection.test.js.map +1 -1
  329. package/dist/tests/security/scanner-regression-guard.test.d.ts +23 -7
  330. package/dist/tests/security/scanner-regression-guard.test.d.ts.map +1 -1
  331. package/dist/tests/security/scanner-regression-guard.test.js +27 -11
  332. package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
  333. package/dist/tests/security/sensitive-path-fp.test.d.ts +2 -0
  334. package/dist/tests/security/sensitive-path-fp.test.d.ts.map +1 -0
  335. package/dist/tests/security/sensitive-path-fp.test.js +142 -0
  336. package/dist/tests/security/sensitive-path-fp.test.js.map +1 -0
  337. package/dist/tests/services/bundled-sibling-scan.test.d.ts +2 -0
  338. package/dist/tests/services/bundled-sibling-scan.test.d.ts.map +1 -0
  339. package/dist/tests/services/bundled-sibling-scan.test.js +139 -0
  340. package/dist/tests/services/bundled-sibling-scan.test.js.map +1 -0
  341. package/dist/tests/unit/services/skill-installation.io.test.js +166 -0
  342. package/dist/tests/unit/services/skill-installation.io.test.js.map +1 -1
  343. package/dist/tests/unit/services/skill-installation.policy.test.d.ts +8 -0
  344. package/dist/tests/unit/services/skill-installation.policy.test.d.ts.map +1 -0
  345. package/dist/tests/unit/services/skill-installation.policy.test.js +151 -0
  346. package/dist/tests/unit/services/skill-installation.policy.test.js.map +1 -0
  347. package/package.json +23 -3
@@ -0,0 +1,133 @@
1
+ /**
2
+ * YAML config-merge helper for Hermes (SMI-5456 Wave 1 Step 5).
3
+ *
4
+ * Hermes is the one target harness whose MCP config is YAML
5
+ * (`~/.hermes/config.yaml`, key `mcp_servers:` — spike report §(b),
6
+ * well-verified against three independent official doc pages). The repo
7
+ * already carries a real `yaml` dependency (`packages/core/package.json` /
8
+ * root `package.json`, `"yaml": "^2.8.3"` — also already used by
9
+ * `packages/core/src/services/agent-pack/agent-pack.test.ts`), so this uses
10
+ * the library's structured Document API (`parseDocument`/`Document#setIn`)
11
+ * rather than the textual delimited-block scheme the task brief allowed as a
12
+ * fallback for "no YAML dep" — that fallback does not apply here since the
13
+ * dependency exists.
14
+ *
15
+ * GOVERNANCE FIX (SMI-5456 code review, 2026-07-01): this module originally
16
+ * used the library's plain `parse`/`stringify` functions. Those DISCARD
17
+ * every comment in the source file on round-trip (verified: `# top comment`
18
+ * + `# a server` + a trailing inline `# inline comment` all vanish after a
19
+ * `parse` → mutate → `stringify` cycle) — a straightforward
20
+ * preserve-user-content violation for anyone who annotates their own
21
+ * `~/.hermes/config.yaml`. `yaml`'s `Document`/`parseDocument`/`setIn` API
22
+ * operates on the CST and round-trips comments, anchors, and key ordering
23
+ * untouched, only rewriting the one path this module actually sets — see the
24
+ * in-container verification in the SMI-5456 code review report. One
25
+ * documented gap remains: a source file whose root is YAML-null (`~`/`null`,
26
+ * or a fully empty document) with a comment attached to that null node loses
27
+ * that specific comment when the null root is replaced with a fresh mapping
28
+ * (there is no collection node for `setIn` to attach into) — an edge case for
29
+ * a config file that carries no actual config, accepted rather than adding a
30
+ * bespoke CST-splicing path for it.
31
+ *
32
+ * @module @skillsmith/core/install/agent-config-merge.yaml
33
+ */
34
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
35
+ import { dirname, join } from 'node:path';
36
+ import { Document, isMap, isScalar, parseDocument } from 'yaml';
37
+ import { deepEqualJson, looksLikeOurMcpEntry, markBackedUp, shouldBackup, } from './agent-config-merge.types.js';
38
+ function writeBackup(sourcePath, backupDir) {
39
+ mkdirSync(backupDir, { recursive: true, mode: 0o700 });
40
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
41
+ const baseName = sourcePath.split('/').pop() ?? 'config';
42
+ const backupPath = join(backupDir, `${stamp}-${baseName}.bak`);
43
+ writeFileSync(backupPath, readFileSync(sourcePath, 'utf-8'), { mode: 0o600 });
44
+ return backupPath;
45
+ }
46
+ /** Unwrap a `yaml` Document node (or plain value) into a plain JS value for comparison. */
47
+ function toPlainValue(node) {
48
+ if (node &&
49
+ typeof node === 'object' &&
50
+ 'toJSON' in node &&
51
+ typeof node.toJSON === 'function') {
52
+ return node.toJSON();
53
+ }
54
+ return node;
55
+ }
56
+ /**
57
+ * Merge a `skillsmith` entry into `mcp_servers:` of a YAML config file.
58
+ * Same created/updated/unchanged/conflict/error contract as
59
+ * {@link import('./agent-config-merge.json.js').mergeJsonMcpEntry}. Uses the
60
+ * `yaml` package's `Document` (CST-backed) API so every comment, anchor, and
61
+ * unrelated key in the user's file survives the merge byte-for-byte except
62
+ * for the one path this function actually sets — see module header.
63
+ */
64
+ export function mergeYamlMcpEntry(opts) {
65
+ const { path, entryValue, backupDir, force = false, mcpServersKey, alreadyBackedUpPaths } = opts;
66
+ let doc;
67
+ const existed = existsSync(path);
68
+ if (existed) {
69
+ let raw;
70
+ try {
71
+ raw = readFileSync(path, 'utf-8');
72
+ }
73
+ catch (e) {
74
+ return { status: 'error', path, backupPath: null, errorMessage: e.message };
75
+ }
76
+ if (raw.trim().length === 0) {
77
+ doc = new Document({});
78
+ }
79
+ else {
80
+ const parsed = parseDocument(raw);
81
+ if (parsed.errors.length > 0) {
82
+ return {
83
+ status: 'error',
84
+ path,
85
+ backupPath: null,
86
+ errorMessage: parsed.errors[0]?.message ?? 'YAML parse error',
87
+ };
88
+ }
89
+ if (parsed.contents !== null && isScalar(parsed.contents) && parsed.contents.value === null) {
90
+ // YAML-null root (`~`, `null`, or comments-only-then-null) — treat as
91
+ // an empty mapping, matching the JSON merge helper's "missing file is
92
+ // treated as {}" behavior. A fresh `Document` (rather than mutating
93
+ // `parsed.contents` in place) sidesteps `Document.Parsed`'s stricter
94
+ // `ParsedNode`-only contents typing; behaviorally identical either
95
+ // way since a bare null-root file carries no salvageable structure.
96
+ // Documented CST-comment-loss edge case for this specific shape —
97
+ // see module header.
98
+ doc = new Document({});
99
+ }
100
+ else if (parsed.contents !== null && !isMap(parsed.contents)) {
101
+ return { status: 'error', path, backupPath: null, errorMessage: 'not a YAML mapping' };
102
+ }
103
+ else {
104
+ doc = parsed;
105
+ }
106
+ }
107
+ }
108
+ else {
109
+ doc = new Document({});
110
+ }
111
+ const existingEntry = toPlainValue(doc.getIn([mcpServersKey, 'skillsmith']));
112
+ if (existingEntry !== undefined) {
113
+ if (deepEqualJson(existingEntry, entryValue)) {
114
+ return { status: 'unchanged', path, backupPath: null };
115
+ }
116
+ if (!looksLikeOurMcpEntry(existingEntry) && !force) {
117
+ return { status: 'conflict', path, backupPath: null };
118
+ }
119
+ const backupPath = existed && shouldBackup(path, alreadyBackedUpPaths) ? writeBackup(path, backupDir) : null;
120
+ markBackedUp(path, alreadyBackedUpPaths);
121
+ doc.setIn([mcpServersKey, 'skillsmith'], entryValue);
122
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
123
+ writeFileSync(path, doc.toString(), { mode: 0o600 });
124
+ return { status: 'updated', path, backupPath };
125
+ }
126
+ const backupPath = existed && shouldBackup(path, alreadyBackedUpPaths) ? writeBackup(path, backupDir) : null;
127
+ markBackedUp(path, alreadyBackedUpPaths);
128
+ doc.setIn([mcpServersKey, 'skillsmith'], entryValue);
129
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
130
+ writeFileSync(path, doc.toString(), { mode: 0o600 });
131
+ return { status: 'created', path, backupPath };
132
+ }
133
+ //# sourceMappingURL=agent-config-merge.yaml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-config-merge.yaml.js","sourceRoot":"","sources":["../../../src/install/agent-config-merge.yaml.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-config-merge.yaml.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-config-merge.yaml.test.d.ts","sourceRoot":"","sources":["../../../src/install/agent-config-merge.yaml.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * @fileoverview Unit tests for `mergeYamlMcpEntry` (SMI-5456 governance
3
+ * follow-up, code review 2026-07-01).
4
+ * @module @skillsmith/core/install/agent-config-merge.yaml.test
5
+ *
6
+ * Added because this module previously had ZERO direct test coverage — the
7
+ * only harness exercising the YAML config format (Hermes) is never
8
+ * "detected" in `agent-pack-installer.test.ts` (no test creates `~/.hermes`),
9
+ * so the plain-`parse`/`stringify` comment-loss bug this file's governance
10
+ * fix addresses shipped with no test that could have caught it. Covers the
11
+ * created/updated/unchanged/conflict/error contract plus the comment-
12
+ * preservation regression itself.
13
+ */
14
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
15
+ import { tmpdir } from 'node:os';
16
+ import { join } from 'node:path';
17
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
18
+ import { mergeYamlMcpEntry } from './agent-config-merge.yaml.js';
19
+ let dir;
20
+ let configPath;
21
+ let backupDir;
22
+ beforeEach(() => {
23
+ dir = mkdtempSync(join(tmpdir(), 'skillsmith-yaml-merge-'));
24
+ configPath = join(dir, 'config.yaml');
25
+ backupDir = join(dir, 'backups');
26
+ });
27
+ afterEach(() => {
28
+ rmSync(dir, { recursive: true, force: true });
29
+ });
30
+ const ENTRY = {
31
+ command: 'npx',
32
+ args: ['-y', '@skillsmith/mcp-server'],
33
+ env: { SKILLSMITH_TOOL_PROFILE: 'agent' },
34
+ };
35
+ describe('mergeYamlMcpEntry', () => {
36
+ it('creates the file + mcp_servers.skillsmith key when absent', () => {
37
+ const result = mergeYamlMcpEntry({
38
+ path: configPath,
39
+ mcpServersKey: 'mcp_servers',
40
+ entryValue: ENTRY,
41
+ backupDir,
42
+ });
43
+ expect(result.status).toBe('created');
44
+ expect(result.backupPath).toBeNull();
45
+ expect(existsSync(configPath)).toBe(true);
46
+ const content = readFileSync(configPath, 'utf-8');
47
+ expect(content).toContain('mcp_servers:');
48
+ expect(content).toContain('skillsmith:');
49
+ });
50
+ it('is idempotent: a second merge with the same entryValue reports unchanged and writes no backup', () => {
51
+ mergeYamlMcpEntry({
52
+ path: configPath,
53
+ mcpServersKey: 'mcp_servers',
54
+ entryValue: ENTRY,
55
+ backupDir,
56
+ });
57
+ const second = mergeYamlMcpEntry({
58
+ path: configPath,
59
+ mcpServersKey: 'mcp_servers',
60
+ entryValue: ENTRY,
61
+ backupDir,
62
+ });
63
+ expect(second.status).toBe('unchanged');
64
+ expect(second.backupPath).toBeNull();
65
+ expect(existsSync(backupDir)).toBe(false);
66
+ });
67
+ it('PRESERVES comments, unrelated keys, and key order on merge (governance regression test)', () => {
68
+ const src = [
69
+ '# top-of-file comment',
70
+ 'some_other_tool:',
71
+ ' # a nested comment',
72
+ ' enabled: true # inline comment',
73
+ 'mcp_servers:',
74
+ ' # an existing server',
75
+ ' other_server:',
76
+ ' command: bar',
77
+ '',
78
+ ].join('\n');
79
+ writeFileSync(configPath, src);
80
+ const result = mergeYamlMcpEntry({
81
+ path: configPath,
82
+ mcpServersKey: 'mcp_servers',
83
+ entryValue: ENTRY,
84
+ backupDir,
85
+ });
86
+ expect(result.status).toBe('created');
87
+ const out = readFileSync(configPath, 'utf-8');
88
+ expect(out).toContain('# top-of-file comment');
89
+ expect(out).toContain('# a nested comment');
90
+ expect(out).toContain('# inline comment');
91
+ expect(out).toContain('# an existing server');
92
+ expect(out).toContain('other_server:');
93
+ expect(out).toContain('enabled: true');
94
+ expect(out).toContain('skillsmith:');
95
+ });
96
+ it('does not clobber a foreign non-Skillsmith skillsmith entry (conflict, no force)', () => {
97
+ writeFileSync(configPath, 'mcp_servers:\n skillsmith:\n command: some-other-tool\n');
98
+ const result = mergeYamlMcpEntry({
99
+ path: configPath,
100
+ mcpServersKey: 'mcp_servers',
101
+ entryValue: ENTRY,
102
+ backupDir,
103
+ });
104
+ expect(result.status).toBe('conflict');
105
+ const out = readFileSync(configPath, 'utf-8');
106
+ expect(out).toContain('some-other-tool');
107
+ });
108
+ it('force: true overwrites a foreign entry and backs up the pre-existing file first', () => {
109
+ writeFileSync(configPath, 'mcp_servers:\n skillsmith:\n command: some-other-tool\n');
110
+ const result = mergeYamlMcpEntry({
111
+ path: configPath,
112
+ mcpServersKey: 'mcp_servers',
113
+ entryValue: ENTRY,
114
+ backupDir,
115
+ force: true,
116
+ });
117
+ expect(result.status).toBe('updated');
118
+ expect(result.backupPath).not.toBeNull();
119
+ expect(existsSync(result.backupPath)).toBe(true);
120
+ expect(readFileSync(result.backupPath, 'utf-8')).toContain('some-other-tool');
121
+ });
122
+ it('recognizes a prior skillsmith-owned entry (by structural fingerprint) and updates without --force', () => {
123
+ writeFileSync(configPath, 'mcp_servers:\n skillsmith:\n command: node\n args:\n - old/path/@skillsmith/mcp-server\n');
124
+ const result = mergeYamlMcpEntry({
125
+ path: configPath,
126
+ mcpServersKey: 'mcp_servers',
127
+ entryValue: ENTRY,
128
+ backupDir,
129
+ });
130
+ expect(result.status).toBe('updated');
131
+ });
132
+ it('never backs up twice for the same path in one run (alreadyBackedUpPaths)', () => {
133
+ writeFileSync(configPath, 'mcp_servers:\n skillsmith:\n command: node\n args: ["@skillsmith/mcp-server"]\n');
134
+ const alreadyBackedUpPaths = new Set();
135
+ const first = mergeYamlMcpEntry({
136
+ path: configPath,
137
+ mcpServersKey: 'mcp_servers',
138
+ entryValue: ENTRY,
139
+ backupDir,
140
+ alreadyBackedUpPaths,
141
+ });
142
+ expect(first.backupPath).not.toBeNull();
143
+ // Merge into a DIFFERENT key path in the same file — simulates a second
144
+ // merge call touching the same shared config file within one install run.
145
+ const second = mergeYamlMcpEntry({
146
+ path: configPath,
147
+ mcpServersKey: 'other_servers',
148
+ entryValue: ENTRY,
149
+ backupDir,
150
+ alreadyBackedUpPaths,
151
+ });
152
+ expect(second.backupPath).toBeNull();
153
+ expect(existsSync(backupDir)).toBe(true);
154
+ });
155
+ it('returns an error status (never throws) for malformed YAML', () => {
156
+ writeFileSync(configPath, ': not: valid: yaml: [');
157
+ const result = mergeYamlMcpEntry({
158
+ path: configPath,
159
+ mcpServersKey: 'mcp_servers',
160
+ entryValue: ENTRY,
161
+ backupDir,
162
+ });
163
+ expect(result.status).toBe('error');
164
+ expect(result.errorMessage).toBeTruthy();
165
+ });
166
+ it('returns an error status for a non-mapping YAML root (a list)', () => {
167
+ writeFileSync(configPath, '- one\n- two\n');
168
+ const result = mergeYamlMcpEntry({
169
+ path: configPath,
170
+ mcpServersKey: 'mcp_servers',
171
+ entryValue: ENTRY,
172
+ backupDir,
173
+ });
174
+ expect(result.status).toBe('error');
175
+ });
176
+ it('treats a YAML-null root (~) as an empty mapping, matching the "missing file" behavior', () => {
177
+ writeFileSync(configPath, '~\n');
178
+ const result = mergeYamlMcpEntry({
179
+ path: configPath,
180
+ mcpServersKey: 'mcp_servers',
181
+ entryValue: ENTRY,
182
+ backupDir,
183
+ });
184
+ expect(result.status).toBe('created');
185
+ expect(readFileSync(configPath, 'utf-8')).toContain('skillsmith:');
186
+ });
187
+ it('treats an empty file the same as a missing one', () => {
188
+ writeFileSync(configPath, '');
189
+ const result = mergeYamlMcpEntry({
190
+ path: configPath,
191
+ mcpServersKey: 'mcp_servers',
192
+ entryValue: ENTRY,
193
+ backupDir,
194
+ });
195
+ expect(result.status).toBe('created');
196
+ });
197
+ it('creates the parent directory when it does not exist', () => {
198
+ const nestedPath = join(dir, 'nested', 'dir', 'config.yaml');
199
+ mkdirSync(join(dir, 'nested'), { recursive: false });
200
+ const result = mergeYamlMcpEntry({
201
+ path: nestedPath,
202
+ mcpServersKey: 'mcp_servers',
203
+ entryValue: ENTRY,
204
+ backupDir,
205
+ });
206
+ expect(result.status).toBe('created');
207
+ expect(existsSync(nestedPath)).toBe(true);
208
+ });
209
+ });
210
+ //# sourceMappingURL=agent-config-merge.yaml.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-config-merge.yaml.test.js","sourceRoot":"","sources":["../../../src/install/agent-config-merge.yaml.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Per-harness on-disk targets for the `sklx agent install` / `uninstall`
3
+ * commands (SMI-5456 Wave 1 Step 5).
4
+ *
5
+ * This module is pure data (no filesystem access) — it says WHERE each
6
+ * harness's MCP config and hook config live and in what format, so
7
+ * `agent-config-merge*.ts` can merge into them generically and
8
+ * `agent-pack-installer.ts` doesn't hard-code per-harness path logic inline.
9
+ *
10
+ * Confidence levels (documented per plan's own Validation Ladder philosophy —
11
+ * Level 2a/3 in docs/internal/implementation/smi-5456-skillsmith-agent-wave1.md
12
+ * is explicitly where per-harness wire formats get confirmed against real
13
+ * harness binaries; Step-6 eval-worker web-verification 2026-07-01 upgraded
14
+ * three rows from the original Step-5 estimates):
15
+ * - claude-code, cursor, windsurf: HIGH — MCP config path/shape verified
16
+ * against `packages/cli/src/templates/mcp-server.template.snippets.ts`
17
+ * (SMI-4580, already shipped and used in docs/website).
18
+ * - hermes: HIGH for the skill path + YAML config shape (spike report §(b),
19
+ * 3 independent official doc pages agree); hooks are spike-verified
20
+ * ABSENT (no SessionStart equivalent) — {@link AGENT_HOOK_TARGETS}
21
+ * therefore carries no hook target for hermes.
22
+ * - codex: HIGH for the config file path (`~/.codex/config.toml`, same
23
+ * snippet table) AND — per Step-6 verification of
24
+ * developers.openai.com/codex/hooks — HIGH for the hook-registration
25
+ * shape: inline `[[hooks.SessionStart]]` / `[[hooks.SessionStart.hooks]]`
26
+ * array-of-tables carrying `{type, command, timeout, statusMessage}`.
27
+ * Codex has NO SessionEnd event, and its Stop event fires PER-TURN (not
28
+ * per-session) — see `installCodexHooks` in
29
+ * `agent-pack-installer.harness.ts` for why nothing is wired for cleanup.
30
+ * - copilot: HIGH — `~/.copilot/mcp-config.json`, top-level `mcpServers`
31
+ * key (Step-6 verified; the earlier `mcp.json` guess was wrong). Global,
32
+ * not VS Code's workspace `.vscode/mcp.json`, remains correct: Copilot
33
+ * CLI removed `.vscode/mcp.json` support, and `sklx agent install` is a
34
+ * global (not per-project) command.
35
+ * - opencode: HIGH — `~/.config/opencode/opencode.json` under the `mcp`
36
+ * key, entries typed `local|remote` (Step-6 verified against
37
+ * opencode.ai/docs; entry VALUE shape differs from the mcpServers
38
+ * convention — see `buildOpenCodeMcpEntryValue` in
39
+ * `agent-pack-installer.entry.ts`). Agent markdown lives at
40
+ * `~/.config/opencode/agents/` — plural (opencode.ai/docs/agents/; the
41
+ * earlier singular `agent/` guess was wrong).
42
+ */
43
+ import type { HarnessId } from '../services/agent-pack/index.js';
44
+ /** Harnesses that can receive an MCP server registration (all 7 targets). */
45
+ export type McpHarnessId = HarnessId | 'windsurf' | 'hermes';
46
+ /** Config-file format the merge helper must speak for a given target. */
47
+ export type ConfigFormat = 'json' | 'yaml' | 'toml-block';
48
+ /**
49
+ * Where + how to merge the Skillsmith MCP server registration for one harness.
50
+ *
51
+ * `keyPath` is only meaningful for `format: 'json'` — the property path (from
52
+ * the parsed document root) to the object the merge helper inserts
53
+ * `skillsmith: {...}` into, creating intermediate objects as needed.
54
+ * `format: 'toml-block'` targets ignore `keyPath` — see
55
+ * `agent-config-merge.toml-block.ts` for the marker-delimited scheme.
56
+ */
57
+ export interface McpConfigTarget {
58
+ harness: McpHarnessId;
59
+ path: string;
60
+ format: ConfigFormat;
61
+ keyPath: string[];
62
+ }
63
+ /** Where to write a named-agent shim file for a harness that has one. */
64
+ export interface ShimTarget {
65
+ harness: HarnessId;
66
+ /** Absolute file path the rendered shim content is written to verbatim. */
67
+ path: string;
68
+ }
69
+ /**
70
+ * Where to install a hook SCRIPT and how to wire it into that harness's hook
71
+ * config. `configFormat`/`configPath`/`keyPath` follow the same shape as
72
+ * {@link McpConfigTarget} so hook wiring reuses the same merge helpers.
73
+ */
74
+ export interface HookInstallTarget {
75
+ harness: 'claude-code' | 'cursor' | 'codex';
76
+ /** Directory the hook script itself is copied into (chmod 0755). */
77
+ scriptDir: string;
78
+ configPath: string;
79
+ configFormat: ConfigFormat;
80
+ /** Key path to the array this hook's command entry is appended to. */
81
+ sessionStartKeyPath: string[];
82
+ sessionEndKeyPath: string[];
83
+ }
84
+ /** MCP registration targets for every harness the pack supports (PRD §3.1). */
85
+ export declare const AGENT_MCP_TARGETS: Readonly<Record<McpHarnessId, McpConfigTarget>>;
86
+ /**
87
+ * Named-agent shim file targets, per {@link HarnessId} (PRD §3.1 constraint
88
+ * 2 / architecture doc artifacts A2-A5). Cursor and (VS Code's) Copilot both
89
+ * read `.claude/agents/*.md` natively per the constraint matrix, so they
90
+ * share the claude-code shim file rather than getting a second copy — only
91
+ * harnesses with their OWN native shim format get a dedicated target here.
92
+ */
93
+ export declare const AGENT_SHIM_TARGETS: Readonly<Record<HarnessId, ShimTarget | null>>;
94
+ /** Hook install targets — only harnesses with a real SessionStart hook (HOOK_HARNESSES). */
95
+ export declare const AGENT_HOOK_TARGETS: Readonly<Record<'claude-code' | 'cursor' | 'codex', HookInstallTarget>>;
96
+ /** Codex's `[agents.skillsmith-agent]` TOML entry lives in the same config file as its MCP registration. */
97
+ export declare const CODEX_CONFIG_TOML_PATH: string;
98
+ //# sourceMappingURL=agent-harness-targets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-harness-targets.d.ts","sourceRoot":"","sources":["../../../src/install/agent-harness-targets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAEhE,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAA;AAE5D,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,CAAA;AAEzD;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,YAAY,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,YAAY,CAAA;IACpB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,yEAAyE;AACzE,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,SAAS,CAAA;IAClB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,aAAa,GAAG,QAAQ,GAAG,OAAO,CAAA;IAC3C,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,YAAY,CAAA;IAC1B,sEAAsE;IACtE,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAC5B;AAID,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,CA2C7E,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC,CAqB7E,CAAA;AAED,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CACvC,MAAM,CAAC,aAAa,GAAG,QAAQ,GAAG,OAAO,EAAE,iBAAiB,CAAC,CA+B9D,CAAA;AAED,4GAA4G;AAC5G,eAAO,MAAM,sBAAsB,QAA+B,CAAA"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Per-harness on-disk targets for the `sklx agent install` / `uninstall`
3
+ * commands (SMI-5456 Wave 1 Step 5).
4
+ *
5
+ * This module is pure data (no filesystem access) — it says WHERE each
6
+ * harness's MCP config and hook config live and in what format, so
7
+ * `agent-config-merge*.ts` can merge into them generically and
8
+ * `agent-pack-installer.ts` doesn't hard-code per-harness path logic inline.
9
+ *
10
+ * Confidence levels (documented per plan's own Validation Ladder philosophy —
11
+ * Level 2a/3 in docs/internal/implementation/smi-5456-skillsmith-agent-wave1.md
12
+ * is explicitly where per-harness wire formats get confirmed against real
13
+ * harness binaries; Step-6 eval-worker web-verification 2026-07-01 upgraded
14
+ * three rows from the original Step-5 estimates):
15
+ * - claude-code, cursor, windsurf: HIGH — MCP config path/shape verified
16
+ * against `packages/cli/src/templates/mcp-server.template.snippets.ts`
17
+ * (SMI-4580, already shipped and used in docs/website).
18
+ * - hermes: HIGH for the skill path + YAML config shape (spike report §(b),
19
+ * 3 independent official doc pages agree); hooks are spike-verified
20
+ * ABSENT (no SessionStart equivalent) — {@link AGENT_HOOK_TARGETS}
21
+ * therefore carries no hook target for hermes.
22
+ * - codex: HIGH for the config file path (`~/.codex/config.toml`, same
23
+ * snippet table) AND — per Step-6 verification of
24
+ * developers.openai.com/codex/hooks — HIGH for the hook-registration
25
+ * shape: inline `[[hooks.SessionStart]]` / `[[hooks.SessionStart.hooks]]`
26
+ * array-of-tables carrying `{type, command, timeout, statusMessage}`.
27
+ * Codex has NO SessionEnd event, and its Stop event fires PER-TURN (not
28
+ * per-session) — see `installCodexHooks` in
29
+ * `agent-pack-installer.harness.ts` for why nothing is wired for cleanup.
30
+ * - copilot: HIGH — `~/.copilot/mcp-config.json`, top-level `mcpServers`
31
+ * key (Step-6 verified; the earlier `mcp.json` guess was wrong). Global,
32
+ * not VS Code's workspace `.vscode/mcp.json`, remains correct: Copilot
33
+ * CLI removed `.vscode/mcp.json` support, and `sklx agent install` is a
34
+ * global (not per-project) command.
35
+ * - opencode: HIGH — `~/.config/opencode/opencode.json` under the `mcp`
36
+ * key, entries typed `local|remote` (Step-6 verified against
37
+ * opencode.ai/docs; entry VALUE shape differs from the mcpServers
38
+ * convention — see `buildOpenCodeMcpEntryValue` in
39
+ * `agent-pack-installer.entry.ts`). Agent markdown lives at
40
+ * `~/.config/opencode/agents/` — plural (opencode.ai/docs/agents/; the
41
+ * earlier singular `agent/` guess was wrong).
42
+ */
43
+ import { homedir } from 'node:os';
44
+ import { join } from 'node:path';
45
+ const home = homedir();
46
+ /** MCP registration targets for every harness the pack supports (PRD §3.1). */
47
+ export const AGENT_MCP_TARGETS = {
48
+ 'claude-code': {
49
+ harness: 'claude-code',
50
+ path: join(home, '.claude', 'settings.json'),
51
+ format: 'json',
52
+ keyPath: ['mcpServers'],
53
+ },
54
+ cursor: {
55
+ harness: 'cursor',
56
+ path: join(home, '.cursor', 'mcp.json'),
57
+ format: 'json',
58
+ keyPath: ['mcpServers'],
59
+ },
60
+ copilot: {
61
+ harness: 'copilot',
62
+ path: join(home, '.copilot', 'mcp-config.json'),
63
+ format: 'json',
64
+ keyPath: ['mcpServers'],
65
+ },
66
+ windsurf: {
67
+ harness: 'windsurf',
68
+ path: join(home, '.codeium', 'windsurf', 'mcp_config.json'),
69
+ format: 'json',
70
+ keyPath: ['mcpServers'],
71
+ },
72
+ opencode: {
73
+ harness: 'opencode',
74
+ path: join(home, '.config', 'opencode', 'opencode.json'),
75
+ format: 'json',
76
+ keyPath: ['mcp'],
77
+ },
78
+ codex: {
79
+ harness: 'codex',
80
+ path: join(home, '.codex', 'config.toml'),
81
+ format: 'toml-block',
82
+ keyPath: [],
83
+ },
84
+ hermes: {
85
+ harness: 'hermes',
86
+ path: join(home, '.hermes', 'config.yaml'),
87
+ format: 'yaml',
88
+ keyPath: ['mcp_servers'],
89
+ },
90
+ };
91
+ /**
92
+ * Named-agent shim file targets, per {@link HarnessId} (PRD §3.1 constraint
93
+ * 2 / architecture doc artifacts A2-A5). Cursor and (VS Code's) Copilot both
94
+ * read `.claude/agents/*.md` natively per the constraint matrix, so they
95
+ * share the claude-code shim file rather than getting a second copy — only
96
+ * harnesses with their OWN native shim format get a dedicated target here.
97
+ */
98
+ export const AGENT_SHIM_TARGETS = {
99
+ 'claude-code': {
100
+ harness: 'claude-code',
101
+ path: join(home, '.claude', 'agents', 'skillsmith-agent.md'),
102
+ },
103
+ // Cursor 2.4+ reads `.claude/agents/` natively — no separate shim file.
104
+ cursor: null,
105
+ copilot: {
106
+ harness: 'copilot',
107
+ path: join(home, '.copilot', 'agents', 'skillsmith-agent.agent.md'),
108
+ },
109
+ opencode: {
110
+ harness: 'opencode',
111
+ // Step-6 verified (opencode.ai/docs/agents/): global agent markdown
112
+ // lives at ~/.config/opencode/agents/ — plural.
113
+ path: join(home, '.config', 'opencode', 'agents', 'skillsmith-agent.md'),
114
+ },
115
+ // Codex's shim is a TOML `[agents.*]` table entry merged into
116
+ // ~/.codex/config.toml, not a standalone file — see AGENT_MCP_TARGETS.codex
117
+ // and agent-config-merge.toml-block.ts. No separate ShimTarget.
118
+ codex: null,
119
+ };
120
+ /** Hook install targets — only harnesses with a real SessionStart hook (HOOK_HARNESSES). */
121
+ export const AGENT_HOOK_TARGETS = {
122
+ 'claude-code': {
123
+ harness: 'claude-code',
124
+ scriptDir: join(home, '.claude', 'hooks'),
125
+ configPath: join(home, '.claude', 'settings.json'),
126
+ configFormat: 'json',
127
+ sessionStartKeyPath: ['hooks', 'SessionStart'],
128
+ sessionEndKeyPath: ['hooks', 'SessionEnd'],
129
+ },
130
+ cursor: {
131
+ harness: 'cursor',
132
+ scriptDir: join(home, '.cursor', 'hooks'),
133
+ configPath: join(home, '.cursor', 'hooks.json'),
134
+ configFormat: 'json',
135
+ // Cursor's hooks.json is Claude-compatible (PRD §3.1) but is itself the
136
+ // hooks map (no wrapping "hooks" key) — see module header confidence note.
137
+ sessionStartKeyPath: ['SessionStart'],
138
+ sessionEndKeyPath: ['SessionEnd'],
139
+ },
140
+ codex: {
141
+ harness: 'codex',
142
+ scriptDir: join(home, '.codex', 'hooks'),
143
+ configPath: join(home, '.codex', 'config.toml'),
144
+ configFormat: 'toml-block',
145
+ // Unused for toml-block wiring (the block text carries its own
146
+ // `[[hooks.SessionStart]]` headers); SessionEnd does not exist as a
147
+ // Codex event at all — see `installCodexHooks`.
148
+ sessionStartKeyPath: [],
149
+ sessionEndKeyPath: [],
150
+ },
151
+ };
152
+ /** Codex's `[agents.skillsmith-agent]` TOML entry lives in the same config file as its MCP registration. */
153
+ export const CODEX_CONFIG_TOML_PATH = AGENT_MCP_TARGETS.codex.path;
154
+ //# sourceMappingURL=agent-harness-targets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-harness-targets.js","sourceRoot":"","sources":["../../../src/install/agent-harness-targets.ts"],"names":[],"mappings":"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"}