hammoc 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/README.md +422 -403
  2. package/bin/hammoc.js +0 -6
  3. package/package.json +100 -93
  4. package/packages/client/dist/assets/agentExampleHighlight-BgwTm15v.js +1 -0
  5. package/packages/client/dist/assets/commandTokenHighlight-BljHwnrK.js +1 -0
  6. package/packages/client/dist/assets/index-CjyjnXB8.css +32 -0
  7. package/packages/client/dist/assets/index-D3LxqW3f.js +2 -0
  8. package/packages/client/dist/assets/index-NqJdhlek.js +1498 -0
  9. package/packages/client/dist/assets/snippetTokenHighlight-DWsaQXX0.js +1 -0
  10. package/packages/client/dist/index.html +2 -2
  11. package/packages/client/dist/sw.js +1 -1
  12. package/packages/server/dist/app.d.ts.map +1 -1
  13. package/packages/server/dist/app.js +24 -24
  14. package/packages/server/dist/app.js.map +1 -1
  15. package/packages/server/dist/controllers/boardController.d.ts.map +1 -1
  16. package/packages/server/dist/controllers/boardController.js +0 -5
  17. package/packages/server/dist/controllers/boardController.js.map +1 -1
  18. package/packages/server/dist/controllers/claudeMdController.d.ts +26 -0
  19. package/packages/server/dist/controllers/claudeMdController.d.ts.map +1 -0
  20. package/packages/server/dist/controllers/claudeMdController.js +158 -0
  21. package/packages/server/dist/controllers/claudeMdController.js.map +1 -0
  22. package/packages/server/dist/controllers/fileSystemController.d.ts +4 -0
  23. package/packages/server/dist/controllers/fileSystemController.d.ts.map +1 -1
  24. package/packages/server/dist/controllers/fileSystemController.js +20 -2
  25. package/packages/server/dist/controllers/fileSystemController.js.map +1 -1
  26. package/packages/server/dist/controllers/harnessAgentController.d.ts +28 -0
  27. package/packages/server/dist/controllers/harnessAgentController.d.ts.map +1 -0
  28. package/packages/server/dist/controllers/harnessAgentController.js +339 -0
  29. package/packages/server/dist/controllers/harnessAgentController.js.map +1 -0
  30. package/packages/server/dist/controllers/harnessCommandController.d.ts +28 -0
  31. package/packages/server/dist/controllers/harnessCommandController.d.ts.map +1 -0
  32. package/packages/server/dist/controllers/harnessCommandController.js +382 -0
  33. package/packages/server/dist/controllers/harnessCommandController.js.map +1 -0
  34. package/packages/server/dist/controllers/harnessController.d.ts +21 -0
  35. package/packages/server/dist/controllers/harnessController.d.ts.map +1 -0
  36. package/packages/server/dist/controllers/harnessController.js +176 -0
  37. package/packages/server/dist/controllers/harnessController.js.map +1 -0
  38. package/packages/server/dist/controllers/harnessHookController.d.ts +32 -0
  39. package/packages/server/dist/controllers/harnessHookController.d.ts.map +1 -0
  40. package/packages/server/dist/controllers/harnessHookController.js +363 -0
  41. package/packages/server/dist/controllers/harnessHookController.js.map +1 -0
  42. package/packages/server/dist/controllers/harnessLintController.d.ts +18 -0
  43. package/packages/server/dist/controllers/harnessLintController.d.ts.map +1 -0
  44. package/packages/server/dist/controllers/harnessLintController.js +72 -0
  45. package/packages/server/dist/controllers/harnessLintController.js.map +1 -0
  46. package/packages/server/dist/controllers/harnessMcpController.d.ts +28 -0
  47. package/packages/server/dist/controllers/harnessMcpController.d.ts.map +1 -0
  48. package/packages/server/dist/controllers/harnessMcpController.js +310 -0
  49. package/packages/server/dist/controllers/harnessMcpController.js.map +1 -0
  50. package/packages/server/dist/controllers/harnessPluginController.d.ts +17 -0
  51. package/packages/server/dist/controllers/harnessPluginController.d.ts.map +1 -0
  52. package/packages/server/dist/controllers/harnessPluginController.js +115 -0
  53. package/packages/server/dist/controllers/harnessPluginController.js.map +1 -0
  54. package/packages/server/dist/controllers/harnessShareScopeController.d.ts +15 -0
  55. package/packages/server/dist/controllers/harnessShareScopeController.d.ts.map +1 -0
  56. package/packages/server/dist/controllers/harnessShareScopeController.js +73 -0
  57. package/packages/server/dist/controllers/harnessShareScopeController.js.map +1 -0
  58. package/packages/server/dist/controllers/harnessSkillController.d.ts +32 -0
  59. package/packages/server/dist/controllers/harnessSkillController.d.ts.map +1 -0
  60. package/packages/server/dist/controllers/harnessSkillController.js +453 -0
  61. package/packages/server/dist/controllers/harnessSkillController.js.map +1 -0
  62. package/packages/server/dist/controllers/projectController.d.ts.map +1 -1
  63. package/packages/server/dist/controllers/projectController.js +11 -0
  64. package/packages/server/dist/controllers/projectController.js.map +1 -1
  65. package/packages/server/dist/controllers/serverController.d.ts.map +1 -1
  66. package/packages/server/dist/controllers/serverController.js +84 -49
  67. package/packages/server/dist/controllers/serverController.js.map +1 -1
  68. package/packages/server/dist/controllers/snippetController.d.ts +35 -0
  69. package/packages/server/dist/controllers/snippetController.d.ts.map +1 -0
  70. package/packages/server/dist/controllers/snippetController.js +294 -0
  71. package/packages/server/dist/controllers/snippetController.js.map +1 -0
  72. package/packages/server/dist/handlers/websocket.d.ts +16 -0
  73. package/packages/server/dist/handlers/websocket.d.ts.map +1 -1
  74. package/packages/server/dist/handlers/websocket.js +221 -8
  75. package/packages/server/dist/handlers/websocket.js.map +1 -1
  76. package/packages/server/dist/index.js +66 -0
  77. package/packages/server/dist/index.js.map +1 -1
  78. package/packages/server/dist/locales/en/server.json +41 -6
  79. package/packages/server/dist/locales/es/server.json +3 -5
  80. package/packages/server/dist/locales/ja/server.json +3 -5
  81. package/packages/server/dist/locales/ko/server.json +4 -6
  82. package/packages/server/dist/locales/pt/server.json +3 -5
  83. package/packages/server/dist/locales/zh-CN/server.json +3 -5
  84. package/packages/server/dist/routes/account.d.ts +7 -0
  85. package/packages/server/dist/routes/account.d.ts.map +1 -0
  86. package/packages/server/dist/routes/account.js +35 -0
  87. package/packages/server/dist/routes/account.js.map +1 -0
  88. package/packages/server/dist/routes/debug.d.ts +1 -1
  89. package/packages/server/dist/routes/debug.d.ts.map +1 -1
  90. package/packages/server/dist/routes/debug.js +60 -1
  91. package/packages/server/dist/routes/debug.js.map +1 -1
  92. package/packages/server/dist/routes/harness.d.ts +8 -0
  93. package/packages/server/dist/routes/harness.d.ts.map +1 -0
  94. package/packages/server/dist/routes/harness.js +92 -0
  95. package/packages/server/dist/routes/harness.js.map +1 -0
  96. package/packages/server/dist/routes/preferences.d.ts.map +1 -1
  97. package/packages/server/dist/routes/preferences.js +11 -2
  98. package/packages/server/dist/routes/preferences.js.map +1 -1
  99. package/packages/server/dist/routes/projects.d.ts.map +1 -1
  100. package/packages/server/dist/routes/projects.js +5 -60
  101. package/packages/server/dist/routes/projects.js.map +1 -1
  102. package/packages/server/dist/routes/snippets.d.ts +14 -0
  103. package/packages/server/dist/routes/snippets.d.ts.map +1 -0
  104. package/packages/server/dist/routes/snippets.js +27 -0
  105. package/packages/server/dist/routes/snippets.js.map +1 -0
  106. package/packages/server/dist/services/accountInfoService.d.ts +38 -0
  107. package/packages/server/dist/services/accountInfoService.d.ts.map +1 -0
  108. package/packages/server/dist/services/accountInfoService.js +118 -0
  109. package/packages/server/dist/services/accountInfoService.js.map +1 -0
  110. package/packages/server/dist/services/bmadStatusService.d.ts +6 -2
  111. package/packages/server/dist/services/bmadStatusService.d.ts.map +1 -1
  112. package/packages/server/dist/services/bmadStatusService.js +88 -32
  113. package/packages/server/dist/services/bmadStatusService.js.map +1 -1
  114. package/packages/server/dist/services/chatService.d.ts +3 -0
  115. package/packages/server/dist/services/chatService.d.ts.map +1 -1
  116. package/packages/server/dist/services/chatService.js +36 -8
  117. package/packages/server/dist/services/chatService.js.map +1 -1
  118. package/packages/server/dist/services/claudeMdService.d.ts +48 -0
  119. package/packages/server/dist/services/claudeMdService.d.ts.map +1 -0
  120. package/packages/server/dist/services/claudeMdService.js +240 -0
  121. package/packages/server/dist/services/claudeMdService.js.map +1 -0
  122. package/packages/server/dist/services/commandService.d.ts +10 -0
  123. package/packages/server/dist/services/commandService.d.ts.map +1 -1
  124. package/packages/server/dist/services/commandService.js +129 -4
  125. package/packages/server/dist/services/commandService.js.map +1 -1
  126. package/packages/server/dist/services/fileSystemService.d.ts +7 -1
  127. package/packages/server/dist/services/fileSystemService.d.ts.map +1 -1
  128. package/packages/server/dist/services/fileSystemService.js +67 -8
  129. package/packages/server/dist/services/fileSystemService.js.map +1 -1
  130. package/packages/server/dist/services/fileWatcherService.d.ts +59 -0
  131. package/packages/server/dist/services/fileWatcherService.d.ts.map +1 -0
  132. package/packages/server/dist/services/fileWatcherService.js +329 -0
  133. package/packages/server/dist/services/fileWatcherService.js.map +1 -0
  134. package/packages/server/dist/services/gitService.d.ts.map +1 -1
  135. package/packages/server/dist/services/gitService.js +67 -7
  136. package/packages/server/dist/services/gitService.js.map +1 -1
  137. package/packages/server/dist/services/harnessAgentService.d.ts +79 -0
  138. package/packages/server/dist/services/harnessAgentService.d.ts.map +1 -0
  139. package/packages/server/dist/services/harnessAgentService.js +933 -0
  140. package/packages/server/dist/services/harnessAgentService.js.map +1 -0
  141. package/packages/server/dist/services/harnessCommandService.d.ts +60 -0
  142. package/packages/server/dist/services/harnessCommandService.d.ts.map +1 -0
  143. package/packages/server/dist/services/harnessCommandService.js +853 -0
  144. package/packages/server/dist/services/harnessCommandService.js.map +1 -0
  145. package/packages/server/dist/services/harnessHookService.d.ts +55 -0
  146. package/packages/server/dist/services/harnessHookService.d.ts.map +1 -0
  147. package/packages/server/dist/services/harnessHookService.js +1060 -0
  148. package/packages/server/dist/services/harnessHookService.js.map +1 -0
  149. package/packages/server/dist/services/harnessLintService.d.ts +49 -0
  150. package/packages/server/dist/services/harnessLintService.d.ts.map +1 -0
  151. package/packages/server/dist/services/harnessLintService.js +628 -0
  152. package/packages/server/dist/services/harnessLintService.js.map +1 -0
  153. package/packages/server/dist/services/harnessMcpService.d.ts +77 -0
  154. package/packages/server/dist/services/harnessMcpService.d.ts.map +1 -0
  155. package/packages/server/dist/services/harnessMcpService.js +814 -0
  156. package/packages/server/dist/services/harnessMcpService.js.map +1 -0
  157. package/packages/server/dist/services/harnessPluginService.d.ts +66 -0
  158. package/packages/server/dist/services/harnessPluginService.d.ts.map +1 -0
  159. package/packages/server/dist/services/harnessPluginService.js +559 -0
  160. package/packages/server/dist/services/harnessPluginService.js.map +1 -0
  161. package/packages/server/dist/services/harnessService.d.ts +40 -0
  162. package/packages/server/dist/services/harnessService.d.ts.map +1 -0
  163. package/packages/server/dist/services/harnessService.js +222 -0
  164. package/packages/server/dist/services/harnessService.js.map +1 -0
  165. package/packages/server/dist/services/harnessShareScopeService.d.ts +31 -0
  166. package/packages/server/dist/services/harnessShareScopeService.d.ts.map +1 -0
  167. package/packages/server/dist/services/harnessShareScopeService.js +93 -0
  168. package/packages/server/dist/services/harnessShareScopeService.js.map +1 -0
  169. package/packages/server/dist/services/harnessSkillService.d.ts +70 -0
  170. package/packages/server/dist/services/harnessSkillService.d.ts.map +1 -0
  171. package/packages/server/dist/services/harnessSkillService.js +636 -0
  172. package/packages/server/dist/services/harnessSkillService.js.map +1 -0
  173. package/packages/server/dist/services/historyParser.d.ts +4 -14
  174. package/packages/server/dist/services/historyParser.d.ts.map +1 -1
  175. package/packages/server/dist/services/historyParser.js +60 -5
  176. package/packages/server/dist/services/historyParser.js.map +1 -1
  177. package/packages/server/dist/services/issueService.d.ts.map +1 -1
  178. package/packages/server/dist/services/issueService.js +10 -2
  179. package/packages/server/dist/services/issueService.js.map +1 -1
  180. package/packages/server/dist/services/manualSyncService.d.ts +19 -0
  181. package/packages/server/dist/services/manualSyncService.d.ts.map +1 -0
  182. package/packages/server/dist/services/manualSyncService.js +110 -0
  183. package/packages/server/dist/services/manualSyncService.js.map +1 -0
  184. package/packages/server/dist/services/notificationService.d.ts.map +1 -1
  185. package/packages/server/dist/services/notificationService.js +34 -9
  186. package/packages/server/dist/services/notificationService.js.map +1 -1
  187. package/packages/server/dist/services/preferencesService.d.ts.map +1 -1
  188. package/packages/server/dist/services/preferencesService.js +8 -1
  189. package/packages/server/dist/services/preferencesService.js.map +1 -1
  190. package/packages/server/dist/services/projectService.d.ts +5 -0
  191. package/packages/server/dist/services/projectService.d.ts.map +1 -1
  192. package/packages/server/dist/services/projectService.js +42 -2
  193. package/packages/server/dist/services/projectService.js.map +1 -1
  194. package/packages/server/dist/services/ptyService.d.ts +1 -0
  195. package/packages/server/dist/services/ptyService.d.ts.map +1 -1
  196. package/packages/server/dist/services/ptyService.js +36 -5
  197. package/packages/server/dist/services/ptyService.js.map +1 -1
  198. package/packages/server/dist/services/queueService.d.ts.map +1 -1
  199. package/packages/server/dist/services/queueService.js +83 -14
  200. package/packages/server/dist/services/queueService.js.map +1 -1
  201. package/packages/server/dist/services/sessionBufferManager.d.ts.map +1 -1
  202. package/packages/server/dist/services/sessionBufferManager.js +26 -0
  203. package/packages/server/dist/services/sessionBufferManager.js.map +1 -1
  204. package/packages/server/dist/services/sessionService.d.ts +4 -3
  205. package/packages/server/dist/services/sessionService.d.ts.map +1 -1
  206. package/packages/server/dist/services/sessionService.js +5 -4
  207. package/packages/server/dist/services/sessionService.js.map +1 -1
  208. package/packages/server/dist/services/snippetService.d.ts +54 -0
  209. package/packages/server/dist/services/snippetService.d.ts.map +1 -0
  210. package/packages/server/dist/services/snippetService.js +371 -0
  211. package/packages/server/dist/services/snippetService.js.map +1 -0
  212. package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.d.ts +46 -0
  213. package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.d.ts.map +1 -0
  214. package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.js +125 -0
  215. package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.js.map +1 -0
  216. package/packages/server/dist/services/webPushService.d.ts.map +1 -1
  217. package/packages/server/dist/services/webPushService.js +8 -1
  218. package/packages/server/dist/services/webPushService.js.map +1 -1
  219. package/packages/server/dist/snippets/split-commit +9 -0
  220. package/packages/server/dist/utils/applySecretsPolicy.d.ts +53 -0
  221. package/packages/server/dist/utils/applySecretsPolicy.d.ts.map +1 -0
  222. package/packages/server/dist/utils/applySecretsPolicy.js +204 -0
  223. package/packages/server/dist/utils/applySecretsPolicy.js.map +1 -0
  224. package/packages/server/dist/utils/assertNoSecretOnShared.d.ts +40 -0
  225. package/packages/server/dist/utils/assertNoSecretOnShared.d.ts.map +1 -0
  226. package/packages/server/dist/utils/assertNoSecretOnShared.js +47 -0
  227. package/packages/server/dist/utils/assertNoSecretOnShared.js.map +1 -0
  228. package/packages/server/dist/utils/effortUtils.d.ts +21 -0
  229. package/packages/server/dist/utils/effortUtils.d.ts.map +1 -0
  230. package/packages/server/dist/utils/effortUtils.js +36 -0
  231. package/packages/server/dist/utils/effortUtils.js.map +1 -0
  232. package/packages/server/dist/utils/gitignoreFilter.d.ts +23 -0
  233. package/packages/server/dist/utils/gitignoreFilter.d.ts.map +1 -0
  234. package/packages/server/dist/utils/gitignoreFilter.js +42 -0
  235. package/packages/server/dist/utils/gitignoreFilter.js.map +1 -0
  236. package/packages/server/dist/utils/harnessBundleSchema.d.ts +105 -0
  237. package/packages/server/dist/utils/harnessBundleSchema.d.ts.map +1 -0
  238. package/packages/server/dist/utils/harnessBundleSchema.js +79 -0
  239. package/packages/server/dist/utils/harnessBundleSchema.js.map +1 -0
  240. package/packages/server/dist/utils/harnessPaths.d.ts +34 -0
  241. package/packages/server/dist/utils/harnessPaths.d.ts.map +1 -0
  242. package/packages/server/dist/utils/harnessPaths.js +124 -0
  243. package/packages/server/dist/utils/harnessPaths.js.map +1 -0
  244. package/packages/server/dist/utils/pathUtils.d.ts +3 -2
  245. package/packages/server/dist/utils/pathUtils.d.ts.map +1 -1
  246. package/packages/server/dist/utils/pathUtils.js +26 -2
  247. package/packages/server/dist/utils/pathUtils.js.map +1 -1
  248. package/packages/server/dist/utils/secretHeuristic.d.ts +72 -0
  249. package/packages/server/dist/utils/secretHeuristic.d.ts.map +1 -0
  250. package/packages/server/dist/utils/secretHeuristic.js +163 -0
  251. package/packages/server/dist/utils/secretHeuristic.js.map +1 -0
  252. package/packages/server/dist/utils/secretPlaceholderNamer.d.ts +41 -0
  253. package/packages/server/dist/utils/secretPlaceholderNamer.d.ts.map +1 -0
  254. package/packages/server/dist/utils/secretPlaceholderNamer.js +81 -0
  255. package/packages/server/dist/utils/secretPlaceholderNamer.js.map +1 -0
  256. package/packages/server/dist/utils/serverPathResolver.d.ts +29 -0
  257. package/packages/server/dist/utils/serverPathResolver.d.ts.map +1 -0
  258. package/packages/server/dist/utils/serverPathResolver.js +59 -0
  259. package/packages/server/dist/utils/serverPathResolver.js.map +1 -0
  260. package/packages/server/dist/utils/snippetPaths.d.ts +61 -0
  261. package/packages/server/dist/utils/snippetPaths.d.ts.map +1 -0
  262. package/packages/server/dist/utils/snippetPaths.js +123 -0
  263. package/packages/server/dist/utils/snippetPaths.js.map +1 -0
  264. package/packages/server/dist/utils/structuredEditor.d.ts +34 -0
  265. package/packages/server/dist/utils/structuredEditor.d.ts.map +1 -0
  266. package/packages/server/dist/utils/structuredEditor.js +111 -0
  267. package/packages/server/dist/utils/structuredEditor.js.map +1 -0
  268. package/packages/server/package.json +6 -2
  269. package/packages/server/resources/internals/INDEX.md +23 -0
  270. package/packages/server/resources/internals/harness-files.md +63 -0
  271. package/packages/server/resources/internals/image-storage.md +43 -0
  272. package/packages/server/resources/manual/01-getting-started.md +104 -0
  273. package/packages/server/resources/manual/02-chat.md +285 -0
  274. package/packages/server/resources/manual/03-sessions.md +48 -0
  275. package/packages/server/resources/manual/04-slash-commands-favorites.md +152 -0
  276. package/packages/server/resources/manual/05-projects.md +74 -0
  277. package/packages/server/resources/manual/06-file-explorer-editor.md +90 -0
  278. package/packages/server/resources/manual/07-git.md +94 -0
  279. package/packages/server/resources/manual/08-terminal.md +59 -0
  280. package/packages/server/resources/manual/09-queue-runner.md +262 -0
  281. package/packages/server/resources/manual/10-project-board.md +193 -0
  282. package/packages/server/resources/manual/11-bmad-method-integration.md +128 -0
  283. package/packages/server/resources/manual/12-harness-workbench.md +175 -0
  284. package/packages/server/resources/manual/13-settings.md +241 -0
  285. package/packages/server/resources/manual/14-keyboard-shortcuts.md +68 -0
  286. package/packages/server/resources/manual/15-environment-variables.md +28 -0
  287. package/packages/server/resources/manual/16-troubleshooting.md +110 -0
  288. package/packages/server/resources/manual/INDEX.md +60 -0
  289. package/packages/shared/dist/index.d.ts +3 -0
  290. package/packages/shared/dist/index.d.ts.map +1 -1
  291. package/packages/shared/dist/index.js +6 -0
  292. package/packages/shared/dist/index.js.map +1 -1
  293. package/packages/shared/dist/types/command.d.ts +3 -3
  294. package/packages/shared/dist/types/command.d.ts.map +1 -1
  295. package/packages/shared/dist/types/fileSystem.d.ts +19 -0
  296. package/packages/shared/dist/types/fileSystem.d.ts.map +1 -1
  297. package/packages/shared/dist/types/fileSystem.js +5 -0
  298. package/packages/shared/dist/types/fileSystem.js.map +1 -1
  299. package/packages/shared/dist/types/git.d.ts +6 -1
  300. package/packages/shared/dist/types/git.d.ts.map +1 -1
  301. package/packages/shared/dist/types/git.js.map +1 -1
  302. package/packages/shared/dist/types/harness.d.ts +1211 -0
  303. package/packages/shared/dist/types/harness.d.ts.map +1 -0
  304. package/packages/shared/dist/types/harness.js +107 -0
  305. package/packages/shared/dist/types/harness.js.map +1 -0
  306. package/packages/shared/dist/types/harnessBundle.d.ts +170 -0
  307. package/packages/shared/dist/types/harnessBundle.d.ts.map +1 -0
  308. package/packages/shared/dist/types/harnessBundle.js +18 -0
  309. package/packages/shared/dist/types/harnessBundle.js.map +1 -0
  310. package/packages/shared/dist/types/history.d.ts +7 -0
  311. package/packages/shared/dist/types/history.d.ts.map +1 -1
  312. package/packages/shared/dist/types/preferences.d.ts +4 -1
  313. package/packages/shared/dist/types/preferences.d.ts.map +1 -1
  314. package/packages/shared/dist/types/preferences.js +1 -0
  315. package/packages/shared/dist/types/preferences.js.map +1 -1
  316. package/packages/shared/dist/types/queue.d.ts +9 -0
  317. package/packages/shared/dist/types/queue.d.ts.map +1 -1
  318. package/packages/shared/dist/types/sdk.d.ts +42 -1
  319. package/packages/shared/dist/types/sdk.d.ts.map +1 -1
  320. package/packages/shared/dist/types/sdk.js +26 -2
  321. package/packages/shared/dist/types/sdk.js.map +1 -1
  322. package/packages/shared/dist/types/websocket.d.ts +24 -0
  323. package/packages/shared/dist/types/websocket.d.ts.map +1 -1
  324. package/packages/shared/dist/utils/markdownSections.d.ts +50 -0
  325. package/packages/shared/dist/utils/markdownSections.d.ts.map +1 -0
  326. package/packages/shared/dist/utils/markdownSections.js +111 -0
  327. package/packages/shared/dist/utils/markdownSections.js.map +1 -0
  328. package/packages/shared/dist/utils/queueParser.d.ts.map +1 -1
  329. package/packages/shared/dist/utils/queueParser.js +104 -0
  330. package/packages/shared/dist/utils/queueParser.js.map +1 -1
  331. package/scripts/build-manual-shards.mjs +100 -0
  332. package/scripts/mock-telegram.mjs +172 -0
  333. package/scripts/run-integration-test.mjs +362 -0
  334. package/packages/client/dist/assets/index-Bf0D9oVJ.css +0 -32
  335. package/packages/client/dist/assets/index-CRmzoqHy.js +0 -2
  336. package/packages/client/dist/assets/index-CszGQ29O.js +0 -1432
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Story 28.0.5: Harness workbench service.
3
+ *
4
+ * Domain: the project's `.claude/` subtree and the global `~/.claude/` subtree
5
+ * — the files that drive plugins, skills, MCP servers, hooks, commands, and
6
+ * subagents. Responsibilities are intentionally separated from
7
+ * `fileSystemService` (which serves arbitrary project files) so that path
8
+ * resolution, scope routing, and the structured-edit surface can evolve
9
+ * independently for harness consumers.
10
+ *
11
+ * Method contract surfaces (all throw typed errors from `HARNESS_ERRORS`):
12
+ * list — directory contents for a `.claude/` subtree
13
+ * read — single file read with binary detection + 1MB truncation
14
+ * write — raw write with expectedMtime / STALE_WRITE guard
15
+ * patchStructured — YAML/JSONC AST-level patch preserving comments & order
16
+ */
17
+ import fs from 'fs/promises';
18
+ import path from 'path';
19
+ import { HARNESS_ERRORS, } from '@hammoc/shared';
20
+ import { resolveHarnessPath } from '../utils/harnessPaths.js';
21
+ import { isBinaryFile, getMimeType, MAX_FILE_SIZE } from '../utils/pathUtils.js';
22
+ import { applyYamlPatch, applyJsoncPatch } from '../utils/structuredEditor.js';
23
+ import { fileWatcherService } from './fileWatcherService.js';
24
+ function throwMapped(code, message, extras) {
25
+ const err = new Error(message);
26
+ err.code = code;
27
+ if (extras)
28
+ Object.assign(err, extras);
29
+ throw err;
30
+ }
31
+ class HarnessService {
32
+ /** List entries of a harness subtree. Missing root → empty list (AC1/AC2). */
33
+ async list(ref) {
34
+ const { resolvedRoot, absolutePath } = await resolveHarnessPath(ref);
35
+ let stat;
36
+ try {
37
+ stat = await fs.stat(absolutePath);
38
+ }
39
+ catch (error) {
40
+ const code = error.code;
41
+ if (code === 'ENOENT') {
42
+ // Harness root (or any subdir) that has never been created yet —
43
+ // return an empty list instead of 404 so the UI can render an empty
44
+ // state without a blocking error.
45
+ return {
46
+ scope: ref.scope,
47
+ projectSlug: ref.projectSlug,
48
+ resolvedRoot,
49
+ path: ref.relativePath ?? '',
50
+ entries: [],
51
+ };
52
+ }
53
+ if (code === 'EACCES') {
54
+ throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
55
+ }
56
+ throw error;
57
+ }
58
+ if (!stat.isDirectory()) {
59
+ throwMapped(HARNESS_ERRORS.HARNESS_NOT_A_FILE.code, 'path is not a directory');
60
+ }
61
+ const names = await fs.readdir(absolutePath);
62
+ const entries = [];
63
+ for (const name of names) {
64
+ try {
65
+ const entryPath = path.join(absolutePath, name);
66
+ const entryStat = await fs.stat(entryPath);
67
+ entries.push({
68
+ name,
69
+ type: entryStat.isDirectory() ? 'directory' : 'file',
70
+ size: entryStat.isDirectory() ? 0 : entryStat.size,
71
+ modifiedAt: entryStat.mtime.toISOString(),
72
+ });
73
+ }
74
+ catch {
75
+ // Skip broken symlinks / unstat-able entries — same policy as fileSystemService.
76
+ continue;
77
+ }
78
+ }
79
+ return {
80
+ scope: ref.scope,
81
+ projectSlug: ref.projectSlug,
82
+ resolvedRoot,
83
+ path: ref.relativePath ?? '',
84
+ entries,
85
+ };
86
+ }
87
+ /** Read a single harness file. Binary → content:null, >1MB → truncated. */
88
+ async read(ref) {
89
+ const { absolutePath } = await resolveHarnessPath(ref);
90
+ let stat;
91
+ try {
92
+ stat = await fs.stat(absolutePath);
93
+ }
94
+ catch (error) {
95
+ const code = error.code;
96
+ if (code === 'ENOENT') {
97
+ throwMapped(HARNESS_ERRORS.HARNESS_FILE_NOT_FOUND.code, 'file not found');
98
+ }
99
+ if (code === 'EACCES') {
100
+ throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
101
+ }
102
+ throw error;
103
+ }
104
+ if (!stat.isFile()) {
105
+ throwMapped(HARNESS_ERRORS.HARNESS_NOT_A_FILE.code, 'path is not a file');
106
+ }
107
+ const size = stat.size;
108
+ const mtime = stat.mtime.toISOString();
109
+ const mimeType = getMimeType(absolutePath);
110
+ const base = {
111
+ scope: ref.scope,
112
+ projectSlug: ref.projectSlug,
113
+ path: ref.relativePath ?? '',
114
+ size,
115
+ mtime,
116
+ mimeType,
117
+ };
118
+ if (size > 0) {
119
+ const binary = await isBinaryFile(absolutePath);
120
+ if (binary) {
121
+ return { ...base, content: null, isBinary: true, isTruncated: false };
122
+ }
123
+ }
124
+ if (size > MAX_FILE_SIZE) {
125
+ const handle = await fs.open(absolutePath, 'r');
126
+ try {
127
+ const buffer = Buffer.alloc(MAX_FILE_SIZE);
128
+ await handle.read(buffer, 0, MAX_FILE_SIZE, 0);
129
+ return { ...base, content: buffer.toString('utf-8'), isBinary: false, isTruncated: true };
130
+ }
131
+ finally {
132
+ await handle.close();
133
+ }
134
+ }
135
+ const content = await fs.readFile(absolutePath, 'utf-8');
136
+ return { ...base, content, isBinary: false, isTruncated: false };
137
+ }
138
+ /**
139
+ * Write a harness file with optional ETag/mtime conflict check.
140
+ * - expectedMtime present + file exists + mtime differs → STALE_WRITE
141
+ * - expectedMtime present + file missing → STALE_WRITE (currentMtime: '')
142
+ * - expectedMtime absent → force overwrite/create
143
+ * - parent directory missing → HARNESS_PARENT_NOT_FOUND (no auto-mkdir)
144
+ */
145
+ async write(ref, body) {
146
+ const { absolutePath } = await resolveHarnessPath(ref);
147
+ const parentDir = path.dirname(absolutePath);
148
+ try {
149
+ const parentStat = await fs.stat(parentDir);
150
+ if (!parentStat.isDirectory()) {
151
+ throwMapped(HARNESS_ERRORS.HARNESS_PARENT_NOT_FOUND.code, 'parent is not a directory');
152
+ }
153
+ }
154
+ catch (error) {
155
+ const code = error.code;
156
+ if (code === HARNESS_ERRORS.HARNESS_PARENT_NOT_FOUND.code)
157
+ throw error;
158
+ if (code === 'ENOENT') {
159
+ throwMapped(HARNESS_ERRORS.HARNESS_PARENT_NOT_FOUND.code, 'parent directory not found');
160
+ }
161
+ if (code === 'EACCES') {
162
+ throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied on parent');
163
+ }
164
+ throwMapped(HARNESS_ERRORS.HARNESS_WRITE_ERROR.code, 'failed to stat parent directory');
165
+ }
166
+ if (body.expectedMtime !== undefined) {
167
+ try {
168
+ const existing = await fs.stat(absolutePath);
169
+ const currentMtime = existing.mtime.toISOString();
170
+ if (currentMtime !== body.expectedMtime) {
171
+ throwMapped(HARNESS_ERRORS.HARNESS_STALE_WRITE.code, 'file changed on disk', { currentMtime });
172
+ }
173
+ }
174
+ catch (error) {
175
+ const code = error.code;
176
+ if (code === 'ENOENT') {
177
+ // Caller asserted a specific mtime but the file is gone — treat as stale.
178
+ throwMapped(HARNESS_ERRORS.HARNESS_STALE_WRITE.code, 'file missing on disk', { currentMtime: '' });
179
+ }
180
+ if (code === HARNESS_ERRORS.HARNESS_STALE_WRITE.code)
181
+ throw error;
182
+ if (code === 'EACCES') {
183
+ throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
184
+ }
185
+ // Any other stat failure: fall through and let writeFile surface it.
186
+ }
187
+ }
188
+ try {
189
+ await fs.writeFile(absolutePath, body.content, 'utf-8');
190
+ }
191
+ catch (error) {
192
+ const code = error.code;
193
+ if (code === 'EACCES') {
194
+ throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
195
+ }
196
+ throwMapped(HARNESS_ERRORS.HARNESS_WRITE_ERROR.code, 'failed to write file');
197
+ }
198
+ const stat = await fs.stat(absolutePath);
199
+ // Share the existing self-write suppression map so the harness watcher
200
+ // (Task 7) swallows our own-write echo on the same path.
201
+ fileWatcherService.noteLocalWrite(absolutePath);
202
+ return { success: true, size: stat.size, mtime: stat.mtime.toISOString() };
203
+ }
204
+ /**
205
+ * Read-patch-write an AST-level edit. Running the round trip through
206
+ * `write` means an external mutation that sneaks in between our read and
207
+ * write will surface as STALE_WRITE (AC5).
208
+ */
209
+ async patchStructured(ref, body) {
210
+ const current = await this.read(ref);
211
+ if (current.isBinary || current.content == null) {
212
+ throwMapped(HARNESS_ERRORS.HARNESS_PARSE_ERROR.code, 'cannot patch binary file');
213
+ }
214
+ const patched = body.format === 'yaml'
215
+ ? applyYamlPatch(current.content, body.ops)
216
+ : applyJsoncPatch(current.content, body.ops);
217
+ const expectedMtime = body.expectedMtime ?? current.mtime;
218
+ return this.write(ref, { content: patched, expectedMtime });
219
+ }
220
+ }
221
+ export const harnessService = new HarnessService();
222
+ //# sourceMappingURL=harnessService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harnessService.js","sourceRoot":"","sources":["../../src/services/harnessService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Story 30.1 (Task 2.1): share-scope evaluator.
3
+ *
4
+ * Given a project slug and a set of project-relative POSIX paths, classify
5
+ * each path as `shared` / `local` / `fullyIgnored` based on the project's
6
+ * `.gitignore`. Also derives the project-level Mode A / Mode B classification
7
+ * by evaluating the virtual path `.claude/settings.json` (file may not exist
8
+ * physically — `isIgnored()` is a pattern test, not a stat call).
9
+ *
10
+ * Single source of truth: `gitignoreFilter.loadGitignore` + `isIgnored`. No
11
+ * direct `.gitignore` parsing.
12
+ */
13
+ import { type HarnessShareScopeResponse } from '@hammoc/shared';
14
+ export interface EvaluateShareScopeRequest {
15
+ projectSlug: string;
16
+ /** Project-relative POSIX paths. May include sibling files outside `.claude/` (e.g. `.mcp.json`). */
17
+ relativePaths: string[];
18
+ }
19
+ declare class HarnessShareScopeService {
20
+ /**
21
+ * Evaluate share-scope for each path + the project-level mode in one
22
+ * `.gitignore` load. Returns `cards: {}` if no paths were requested but
23
+ * still computes `mode` (so a freshly mounted workbench can render the
24
+ * banner before any file is asked about).
25
+ */
26
+ evaluate(req: EvaluateShareScopeRequest): Promise<HarnessShareScopeResponse>;
27
+ }
28
+ export declare const harnessShareScopeService: HarnessShareScopeService;
29
+ export declare function getProjectRootForShareScope(projectSlug: string): Promise<string>;
30
+ export {};
31
+ //# sourceMappingURL=harnessShareScopeService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harnessShareScopeService.d.ts","sourceRoot":"","sources":["../../src/services/harnessShareScopeService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAkB,KAAK,yBAAyB,EAAmB,MAAM,gBAAgB,CAAC;AAkBjG,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,cAAM,wBAAwB;IAC5B;;;;;OAKG;IACG,QAAQ,CAAC,GAAG,EAAE,yBAAyB,GAAG,OAAO,CAAC,yBAAyB,CAAC;CAqCnF;AA6BD,eAAO,MAAM,wBAAwB,0BAAiC,CAAC;AAIvE,wBAAsB,2BAA2B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGtF"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Story 30.1 (Task 2.1): share-scope evaluator.
3
+ *
4
+ * Given a project slug and a set of project-relative POSIX paths, classify
5
+ * each path as `shared` / `local` / `fullyIgnored` based on the project's
6
+ * `.gitignore`. Also derives the project-level Mode A / Mode B classification
7
+ * by evaluating the virtual path `.claude/settings.json` (file may not exist
8
+ * physically — `isIgnored()` is a pattern test, not a stat call).
9
+ *
10
+ * Single source of truth: `gitignoreFilter.loadGitignore` + `isIgnored`. No
11
+ * direct `.gitignore` parsing.
12
+ */
13
+ import path from 'path';
14
+ import { HARNESS_ERRORS } from '@hammoc/shared';
15
+ import { projectService } from './projectService.js';
16
+ import { loadGitignore, isIgnored } from '../utils/gitignoreFilter.js';
17
+ const CLAUDE_DIR = '.claude';
18
+ /**
19
+ * Virtual path used for Mode A/B classification. The file may not exist on
20
+ * disk — `isIgnored()` evaluates the pattern alone, so a brand-new project
21
+ * with an empty `.claude/` still gets a deterministic mode verdict.
22
+ */
23
+ const MODE_PROBE_PATH = `${CLAUDE_DIR}/settings.json`;
24
+ /**
25
+ * Probe used to detect "directory itself ignored" patterns like `.claude/`
26
+ * (which auto-propagates to descendants). When the directory itself is
27
+ * matched, every leaf gets the `fullyIgnored` verdict.
28
+ */
29
+ const FULL_IGNORE_PROBE_PATH = `${CLAUDE_DIR}/`;
30
+ class HarnessShareScopeService {
31
+ /**
32
+ * Evaluate share-scope for each path + the project-level mode in one
33
+ * `.gitignore` load. Returns `cards: {}` if no paths were requested but
34
+ * still computes `mode` (so a freshly mounted workbench can render the
35
+ * banner before any file is asked about).
36
+ */
37
+ async evaluate(req) {
38
+ if (!req.projectSlug) {
39
+ const err = new Error('projectSlug is required');
40
+ err.code = HARNESS_ERRORS.HARNESS_ROOT_MISSING.code;
41
+ throw err;
42
+ }
43
+ let projectRoot;
44
+ try {
45
+ projectRoot = await projectService.resolveOriginalPath(req.projectSlug);
46
+ }
47
+ catch (cause) {
48
+ const wrapped = new Error(`Unable to resolve project root for "${req.projectSlug}": ${cause.message}`);
49
+ wrapped.code = HARNESS_ERRORS.HARNESS_ROOT_MISSING.code;
50
+ throw wrapped;
51
+ }
52
+ const matcher = await loadGitignore(projectRoot);
53
+ // Mode A/B verdict: probe `.claude/settings.json`. The file may be missing
54
+ // — `isIgnored` is a pattern test that returns the same verdict either way.
55
+ const mode = isIgnored(matcher, MODE_PROBE_PATH) ? 'B' : 'A';
56
+ // When `.claude/` itself is matched, the directory's children all become
57
+ // `fullyIgnored` regardless of their own paths. We still evaluate each
58
+ // requested path individually so callers can mix in sibling files
59
+ // (e.g. `.mcp.json`) that escape the directory pattern.
60
+ const claudeDirIgnored = isIgnored(matcher, FULL_IGNORE_PROBE_PATH);
61
+ const cards = {};
62
+ for (const rel of req.relativePaths) {
63
+ cards[rel] = classifyPath(matcher, rel, claudeDirIgnored);
64
+ }
65
+ return { mode, cards };
66
+ }
67
+ }
68
+ function classifyPath(matcher, relativePath, claudeDirIgnored) {
69
+ // Normalize separators so Windows callers don't accidentally bypass `ignore`.
70
+ const posix = relativePath.replace(/\\/g, '/');
71
+ const fileIgnored = isIgnored(matcher, posix);
72
+ if (!fileIgnored) {
73
+ return 'shared';
74
+ }
75
+ // The path is ignored. If `.claude/` itself is the source of the rule, treat
76
+ // the verdict as the project-wide `fullyIgnored` state so Mode B projects
77
+ // get a coherent badge across every harness file.
78
+ if (claudeDirIgnored && isUnderClaudeDir(posix)) {
79
+ return 'fullyIgnored';
80
+ }
81
+ return 'local';
82
+ }
83
+ function isUnderClaudeDir(posixPath) {
84
+ return posixPath === CLAUDE_DIR || posixPath.startsWith(`${CLAUDE_DIR}/`);
85
+ }
86
+ export const harnessShareScopeService = new HarnessShareScopeService();
87
+ // Re-export so consumers (e.g. the .gitignore append fallback in Task 6.4)
88
+ // can also resolve the standard project-root path the matcher was built from.
89
+ export async function getProjectRootForShareScope(projectSlug) {
90
+ const root = await projectService.resolveOriginalPath(projectSlug);
91
+ return path.resolve(root);
92
+ }
93
+ //# sourceMappingURL=harnessShareScopeService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harnessShareScopeService.js","sourceRoot":"","sources":["../../src/services/harnessShareScopeService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,cAAc,EAAmD,MAAM,gBAAgB,CAAC;AACjG,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAEvE,MAAM,UAAU,GAAG,SAAS,CAAC;AAC7B;;;;GAIG;AACH,MAAM,eAAe,GAAG,GAAG,UAAU,gBAAgB,CAAC;AACtD;;;;GAIG;AACH,MAAM,sBAAsB,GAAG,GAAG,UAAU,GAAG,CAAC;AAQhD,MAAM,wBAAwB;IAC5B;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAC,GAA8B;QAC3C,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,yBAAyB,CAA0B,CAAC;YAC1E,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,oBAAoB,CAAC,IAAI,CAAC;YACpD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,IAAI,WAAmB,CAAC;QACxB,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,cAAc,CAAC,mBAAmB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,IAAI,KAAK,CACvB,uCAAuC,GAAG,CAAC,WAAW,MAAO,KAAe,CAAC,OAAO,EAAE,CAC9D,CAAC;YAC3B,OAAO,CAAC,IAAI,GAAG,cAAc,CAAC,oBAAoB,CAAC,IAAI,CAAC;YACxD,MAAM,OAAO,CAAC;QAChB,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;QAEjD,2EAA2E;QAC3E,4EAA4E;QAC5E,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAE7D,yEAAyE;QACzE,uEAAuE;QACvE,kEAAkE;QAClE,wDAAwD;QACxD,MAAM,gBAAgB,GAAG,SAAS,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC;QAEpE,MAAM,KAAK,GAA+B,EAAE,CAAC;QAC7C,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;YACpC,KAAK,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,OAAO,EAAE,GAAG,EAAE,gBAAgB,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACzB,CAAC;CACF;AAED,SAAS,YAAY,CACnB,OAAe,EACf,YAAoB,EACpB,gBAAyB;IAEzB,8EAA8E;IAC9E,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE9C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,6EAA6E;IAC7E,0EAA0E;IAC1E,kDAAkD;IAClD,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAiB;IACzC,OAAO,SAAS,KAAK,UAAU,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC;AAEvE,2EAA2E;AAC3E,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,WAAmB;IACnE,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Story 28.2: Harness skill service.
3
+ *
4
+ * Combines three sources of `<root>/skills/<name>/` directories — the active
5
+ * project, the user-scope home, and every installed plugin bundle — into a
6
+ * single card list used by the "Harness Workbench → Skills" panel. File I/O,
7
+ * traversal guards, STALE_WRITE detection, and binary detection are delegated
8
+ * to `harnessService`. The plugin source enumerates from
9
+ * `installed_plugins.json` and supports both in-tree (~/.claude/plugins/...)
10
+ * and dev-installed (out-of-tree) install paths — the latter goes through a
11
+ * direct `fs` read after a manual containment check so it never escapes its
12
+ * own `installPath`.
13
+ *
14
+ * frontmatter parsing uses the `yaml` (eemeli) parser so the round-trip story
15
+ * stays consistent with `structuredEditor.ts` (no `js-yaml` for harness code).
16
+ */
17
+ import { type HarnessSkillCopyRequest, type HarnessSkillCopyResponse, type HarnessSkillListResponse, type HarnessSkillReadResponse, type HarnessSkillSourceLocation, type HarnessSkillUpdateRequest } from '@hammoc/shared';
18
+ declare class HarnessSkillService {
19
+ /**
20
+ * Enumerate skills across project / user / plugin sources and merge entries
21
+ * sharing the same directory name into a single card.
22
+ */
23
+ listCards(currentProjectSlug?: string): Promise<HarnessSkillListResponse>;
24
+ /**
25
+ * Read a single skill's SKILL.md plus the bundle file tree. Returns the
26
+ * frontmatter, the body separately, the raw text (for the Raw editor) and a
27
+ * flat list of bundle entries with binary / truncation flags pre-resolved.
28
+ */
29
+ readSkill(source: HarnessSkillSourceLocation): Promise<HarnessSkillReadResponse>;
30
+ /**
31
+ * Apply a frontmatter / body / raw update against an existing SKILL.md.
32
+ * Plugin scope is read-only — any update against a plugin source is denied
33
+ * with HARNESS_FORBIDDEN.
34
+ */
35
+ updateSkill(source: HarnessSkillSourceLocation, body: HarnessSkillUpdateRequest): Promise<{
36
+ success: true;
37
+ mtime: string;
38
+ }>;
39
+ /**
40
+ * Recursively copy a skill folder. The destination is always a project or
41
+ * user scope — copies *into* a plugin bundle are blocked by Zod at the
42
+ * controller layer, but we re-assert here as a defensive belt.
43
+ */
44
+ copySkill(req: HarnessSkillCopyRequest): Promise<HarnessSkillCopyResponse>;
45
+ private enumerateProjectSkills;
46
+ private enumerateUserSkills;
47
+ private enumeratePluginSkills;
48
+ private collectSourceFromRoot;
49
+ private malformedEntry;
50
+ private countBundle;
51
+ private collectBundleEntries;
52
+ /**
53
+ * Build the harnessService path reference for an editable (project or user)
54
+ * source. Plugin scope is rejected by the caller before this runs.
55
+ */
56
+ private refForEditableSource;
57
+ /**
58
+ * Apply a frontmatter form patch by routing through the YAML round-trip
59
+ * editor on the frontmatter block alone. Comments / quoting / key order are
60
+ * preserved exactly the same way `harnessService.patchStructured` would for
61
+ * a pure-YAML file — but since SKILL.md is a hybrid file, we run the patch
62
+ * on the extracted block and recompose the full text afterwards.
63
+ */
64
+ private applyFrontmatterPatch;
65
+ private resolveSkillRoot;
66
+ private resolvePluginInstallPath;
67
+ }
68
+ export declare const harnessSkillService: HarnessSkillService;
69
+ export {};
70
+ //# sourceMappingURL=harnessSkillService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harnessSkillService.d.ts","sourceRoot":"","sources":["../../src/services/harnessSkillService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,EAML,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAE7B,KAAK,wBAAwB,EAE7B,KAAK,wBAAwB,EAE7B,KAAK,0BAA0B,EAE/B,KAAK,yBAAyB,EAC/B,MAAM,gBAAgB,CAAC;AAmCxB,cAAM,mBAAmB;IAGvB;;;OAGG;IACG,SAAS,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IA8C/E;;;;OAIG;IACG,SAAS,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAiDtF;;;;OAIG;IACG,WAAW,CACf,MAAM,EAAE,0BAA0B,EAClC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IA+C5C;;;;OAIG;IACG,SAAS,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,wBAAwB,CAAC;YAmFlE,sBAAsB;YAsBtB,mBAAmB;YAiBnB,qBAAqB;YA0DrB,qBAAqB;IAqDnC,OAAO,CAAC,cAAc;YAeR,WAAW;YAaX,oBAAoB;IAyDlC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA2B5B;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;YAyBf,gBAAgB;YAiChB,wBAAwB;CAmBvC;AA2FD,eAAO,MAAM,mBAAmB,qBAA4B,CAAC"}