hammoc 1.4.0 → 1.6.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 (353) hide show
  1. package/README.md +428 -405
  2. package/bin/hammoc.js +0 -6
  3. package/package.json +100 -94
  4. package/packages/client/dist/assets/agentExampleHighlight-ltj9ce0U.js +1 -0
  5. package/packages/client/dist/assets/commandTokenHighlight-ji_ViMb4.js +1 -0
  6. package/packages/client/dist/assets/index-B-DiRGuz.js +2 -0
  7. package/packages/client/dist/assets/index-B09doO8H.js +139 -0
  8. package/packages/client/dist/assets/index-BT4RIi0U.js +1523 -0
  9. package/packages/client/dist/assets/index-DyNJ5jEW.css +32 -0
  10. package/packages/client/dist/assets/snippetTokenHighlight-CP3v4o2g.js +1 -0
  11. package/packages/client/dist/index.html +2 -2
  12. package/packages/client/dist/sw.js +1 -1
  13. package/packages/server/dist/app.d.ts.map +1 -1
  14. package/packages/server/dist/app.js +13 -21
  15. package/packages/server/dist/app.js.map +1 -1
  16. package/packages/server/dist/controllers/bmadCoreConfigController.d.ts +41 -0
  17. package/packages/server/dist/controllers/bmadCoreConfigController.d.ts.map +1 -0
  18. package/packages/server/dist/controllers/bmadCoreConfigController.js +172 -0
  19. package/packages/server/dist/controllers/bmadCoreConfigController.js.map +1 -0
  20. package/packages/server/dist/controllers/claudeMdController.d.ts +26 -0
  21. package/packages/server/dist/controllers/claudeMdController.d.ts.map +1 -0
  22. package/packages/server/dist/controllers/claudeMdController.js +158 -0
  23. package/packages/server/dist/controllers/claudeMdController.js.map +1 -0
  24. package/packages/server/dist/controllers/contextBuilderController.d.ts +43 -0
  25. package/packages/server/dist/controllers/contextBuilderController.d.ts.map +1 -0
  26. package/packages/server/dist/controllers/contextBuilderController.js +159 -0
  27. package/packages/server/dist/controllers/contextBuilderController.js.map +1 -0
  28. package/packages/server/dist/controllers/harnessAgentController.d.ts +35 -0
  29. package/packages/server/dist/controllers/harnessAgentController.d.ts.map +1 -0
  30. package/packages/server/dist/controllers/harnessAgentController.js +372 -0
  31. package/packages/server/dist/controllers/harnessAgentController.js.map +1 -0
  32. package/packages/server/dist/controllers/harnessBundleController.d.ts +37 -0
  33. package/packages/server/dist/controllers/harnessBundleController.d.ts.map +1 -0
  34. package/packages/server/dist/controllers/harnessBundleController.js +312 -0
  35. package/packages/server/dist/controllers/harnessBundleController.js.map +1 -0
  36. package/packages/server/dist/controllers/harnessCommandController.d.ts +35 -0
  37. package/packages/server/dist/controllers/harnessCommandController.d.ts.map +1 -0
  38. package/packages/server/dist/controllers/harnessCommandController.js +415 -0
  39. package/packages/server/dist/controllers/harnessCommandController.js.map +1 -0
  40. package/packages/server/dist/controllers/harnessController.d.ts +21 -0
  41. package/packages/server/dist/controllers/harnessController.d.ts.map +1 -0
  42. package/packages/server/dist/controllers/harnessController.js +176 -0
  43. package/packages/server/dist/controllers/harnessController.js.map +1 -0
  44. package/packages/server/dist/controllers/harnessHookController.d.ts +32 -0
  45. package/packages/server/dist/controllers/harnessHookController.d.ts.map +1 -0
  46. package/packages/server/dist/controllers/harnessHookController.js +406 -0
  47. package/packages/server/dist/controllers/harnessHookController.js.map +1 -0
  48. package/packages/server/dist/controllers/harnessLintController.d.ts +18 -0
  49. package/packages/server/dist/controllers/harnessLintController.d.ts.map +1 -0
  50. package/packages/server/dist/controllers/harnessLintController.js +72 -0
  51. package/packages/server/dist/controllers/harnessLintController.js.map +1 -0
  52. package/packages/server/dist/controllers/harnessMcpController.d.ts +28 -0
  53. package/packages/server/dist/controllers/harnessMcpController.d.ts.map +1 -0
  54. package/packages/server/dist/controllers/harnessMcpController.js +371 -0
  55. package/packages/server/dist/controllers/harnessMcpController.js.map +1 -0
  56. package/packages/server/dist/controllers/harnessPluginController.d.ts +17 -0
  57. package/packages/server/dist/controllers/harnessPluginController.d.ts.map +1 -0
  58. package/packages/server/dist/controllers/harnessPluginController.js +115 -0
  59. package/packages/server/dist/controllers/harnessPluginController.js.map +1 -0
  60. package/packages/server/dist/controllers/harnessShareScopeController.d.ts +24 -0
  61. package/packages/server/dist/controllers/harnessShareScopeController.d.ts.map +1 -0
  62. package/packages/server/dist/controllers/harnessShareScopeController.js +120 -0
  63. package/packages/server/dist/controllers/harnessShareScopeController.js.map +1 -0
  64. package/packages/server/dist/controllers/harnessSkillController.d.ts +32 -0
  65. package/packages/server/dist/controllers/harnessSkillController.d.ts.map +1 -0
  66. package/packages/server/dist/controllers/harnessSkillController.js +453 -0
  67. package/packages/server/dist/controllers/harnessSkillController.js.map +1 -0
  68. package/packages/server/dist/controllers/marketplaceController.d.ts +19 -0
  69. package/packages/server/dist/controllers/marketplaceController.d.ts.map +1 -0
  70. package/packages/server/dist/controllers/marketplaceController.js +74 -0
  71. package/packages/server/dist/controllers/marketplaceController.js.map +1 -0
  72. package/packages/server/dist/controllers/observabilityController.d.ts +32 -0
  73. package/packages/server/dist/controllers/observabilityController.d.ts.map +1 -0
  74. package/packages/server/dist/controllers/observabilityController.js +148 -0
  75. package/packages/server/dist/controllers/observabilityController.js.map +1 -0
  76. package/packages/server/dist/controllers/projectController.d.ts.map +1 -1
  77. package/packages/server/dist/controllers/projectController.js +11 -0
  78. package/packages/server/dist/controllers/projectController.js.map +1 -1
  79. package/packages/server/dist/controllers/snippetController.d.ts +35 -0
  80. package/packages/server/dist/controllers/snippetController.d.ts.map +1 -0
  81. package/packages/server/dist/controllers/snippetController.js +294 -0
  82. package/packages/server/dist/controllers/snippetController.js.map +1 -0
  83. package/packages/server/dist/handlers/streamCallbacks.d.ts +8 -0
  84. package/packages/server/dist/handlers/streamCallbacks.d.ts.map +1 -1
  85. package/packages/server/dist/handlers/streamCallbacks.js +8 -0
  86. package/packages/server/dist/handlers/streamCallbacks.js.map +1 -1
  87. package/packages/server/dist/handlers/websocket.d.ts +15 -0
  88. package/packages/server/dist/handlers/websocket.d.ts.map +1 -1
  89. package/packages/server/dist/handlers/websocket.js +103 -2
  90. package/packages/server/dist/handlers/websocket.js.map +1 -1
  91. package/packages/server/dist/index.js +5 -0
  92. package/packages/server/dist/index.js.map +1 -1
  93. package/packages/server/dist/locales/en/server.json +37 -4
  94. package/packages/server/dist/locales/es/server.json +0 -4
  95. package/packages/server/dist/locales/ja/server.json +0 -4
  96. package/packages/server/dist/locales/ko/server.json +0 -4
  97. package/packages/server/dist/locales/pt/server.json +0 -4
  98. package/packages/server/dist/locales/zh-CN/server.json +0 -4
  99. package/packages/server/dist/routes/harness.d.ts +8 -0
  100. package/packages/server/dist/routes/harness.d.ts.map +1 -0
  101. package/packages/server/dist/routes/harness.js +150 -0
  102. package/packages/server/dist/routes/harness.js.map +1 -0
  103. package/packages/server/dist/routes/projects.d.ts.map +1 -1
  104. package/packages/server/dist/routes/projects.js +5 -60
  105. package/packages/server/dist/routes/projects.js.map +1 -1
  106. package/packages/server/dist/routes/snippets.d.ts +14 -0
  107. package/packages/server/dist/routes/snippets.d.ts.map +1 -0
  108. package/packages/server/dist/routes/snippets.js +27 -0
  109. package/packages/server/dist/routes/snippets.js.map +1 -0
  110. package/packages/server/dist/services/bmadCoreConfigService.d.ts +86 -0
  111. package/packages/server/dist/services/bmadCoreConfigService.d.ts.map +1 -0
  112. package/packages/server/dist/services/bmadCoreConfigService.js +175 -0
  113. package/packages/server/dist/services/bmadCoreConfigService.js.map +1 -0
  114. package/packages/server/dist/services/bmadStatusService.d.ts +15 -2
  115. package/packages/server/dist/services/bmadStatusService.d.ts.map +1 -1
  116. package/packages/server/dist/services/bmadStatusService.js +146 -37
  117. package/packages/server/dist/services/bmadStatusService.js.map +1 -1
  118. package/packages/server/dist/services/chatService.d.ts +3 -0
  119. package/packages/server/dist/services/chatService.d.ts.map +1 -1
  120. package/packages/server/dist/services/chatService.js +28 -7
  121. package/packages/server/dist/services/chatService.js.map +1 -1
  122. package/packages/server/dist/services/claudeMdService.d.ts +48 -0
  123. package/packages/server/dist/services/claudeMdService.d.ts.map +1 -0
  124. package/packages/server/dist/services/claudeMdService.js +240 -0
  125. package/packages/server/dist/services/claudeMdService.js.map +1 -0
  126. package/packages/server/dist/services/commandService.d.ts +10 -0
  127. package/packages/server/dist/services/commandService.d.ts.map +1 -1
  128. package/packages/server/dist/services/commandService.js +129 -4
  129. package/packages/server/dist/services/commandService.js.map +1 -1
  130. package/packages/server/dist/services/contextBuilderScriptTemplate.d.ts +24 -0
  131. package/packages/server/dist/services/contextBuilderScriptTemplate.d.ts.map +1 -0
  132. package/packages/server/dist/services/contextBuilderScriptTemplate.js +181 -0
  133. package/packages/server/dist/services/contextBuilderScriptTemplate.js.map +1 -0
  134. package/packages/server/dist/services/contextBuilderService.d.ts +68 -0
  135. package/packages/server/dist/services/contextBuilderService.d.ts.map +1 -0
  136. package/packages/server/dist/services/contextBuilderService.js +345 -0
  137. package/packages/server/dist/services/contextBuilderService.js.map +1 -0
  138. package/packages/server/dist/services/fileWatcherService.d.ts +24 -0
  139. package/packages/server/dist/services/fileWatcherService.d.ts.map +1 -1
  140. package/packages/server/dist/services/fileWatcherService.js +232 -1
  141. package/packages/server/dist/services/fileWatcherService.js.map +1 -1
  142. package/packages/server/dist/services/harnessAgentService.d.ts +97 -0
  143. package/packages/server/dist/services/harnessAgentService.d.ts.map +1 -0
  144. package/packages/server/dist/services/harnessAgentService.js +988 -0
  145. package/packages/server/dist/services/harnessAgentService.js.map +1 -0
  146. package/packages/server/dist/services/harnessBundleService.d.ts +145 -0
  147. package/packages/server/dist/services/harnessBundleService.d.ts.map +1 -0
  148. package/packages/server/dist/services/harnessBundleService.js +1318 -0
  149. package/packages/server/dist/services/harnessBundleService.js.map +1 -0
  150. package/packages/server/dist/services/harnessCommandService.d.ts +81 -0
  151. package/packages/server/dist/services/harnessCommandService.d.ts.map +1 -0
  152. package/packages/server/dist/services/harnessCommandService.js +917 -0
  153. package/packages/server/dist/services/harnessCommandService.js.map +1 -0
  154. package/packages/server/dist/services/harnessHookService.d.ts +82 -0
  155. package/packages/server/dist/services/harnessHookService.d.ts.map +1 -0
  156. package/packages/server/dist/services/harnessHookService.js +1112 -0
  157. package/packages/server/dist/services/harnessHookService.js.map +1 -0
  158. package/packages/server/dist/services/harnessLintService.d.ts +49 -0
  159. package/packages/server/dist/services/harnessLintService.d.ts.map +1 -0
  160. package/packages/server/dist/services/harnessLintService.js +628 -0
  161. package/packages/server/dist/services/harnessLintService.js.map +1 -0
  162. package/packages/server/dist/services/harnessMcpService.d.ts +100 -0
  163. package/packages/server/dist/services/harnessMcpService.d.ts.map +1 -0
  164. package/packages/server/dist/services/harnessMcpService.js +884 -0
  165. package/packages/server/dist/services/harnessMcpService.js.map +1 -0
  166. package/packages/server/dist/services/harnessPluginService.d.ts +66 -0
  167. package/packages/server/dist/services/harnessPluginService.d.ts.map +1 -0
  168. package/packages/server/dist/services/harnessPluginService.js +559 -0
  169. package/packages/server/dist/services/harnessPluginService.js.map +1 -0
  170. package/packages/server/dist/services/harnessService.d.ts +40 -0
  171. package/packages/server/dist/services/harnessService.d.ts.map +1 -0
  172. package/packages/server/dist/services/harnessService.js +222 -0
  173. package/packages/server/dist/services/harnessService.js.map +1 -0
  174. package/packages/server/dist/services/harnessShareScopeService.d.ts +50 -0
  175. package/packages/server/dist/services/harnessShareScopeService.d.ts.map +1 -0
  176. package/packages/server/dist/services/harnessShareScopeService.js +158 -0
  177. package/packages/server/dist/services/harnessShareScopeService.js.map +1 -0
  178. package/packages/server/dist/services/harnessSkillService.d.ts +70 -0
  179. package/packages/server/dist/services/harnessSkillService.d.ts.map +1 -0
  180. package/packages/server/dist/services/harnessSkillService.js +636 -0
  181. package/packages/server/dist/services/harnessSkillService.js.map +1 -0
  182. package/packages/server/dist/services/issueService.d.ts.map +1 -1
  183. package/packages/server/dist/services/issueService.js +3 -1
  184. package/packages/server/dist/services/issueService.js.map +1 -1
  185. package/packages/server/dist/services/manualSyncService.d.ts +19 -0
  186. package/packages/server/dist/services/manualSyncService.d.ts.map +1 -0
  187. package/packages/server/dist/services/manualSyncService.js +110 -0
  188. package/packages/server/dist/services/manualSyncService.js.map +1 -0
  189. package/packages/server/dist/services/marketplaceService.d.ts +50 -0
  190. package/packages/server/dist/services/marketplaceService.d.ts.map +1 -0
  191. package/packages/server/dist/services/marketplaceService.js +326 -0
  192. package/packages/server/dist/services/marketplaceService.js.map +1 -0
  193. package/packages/server/dist/services/observabilityService.d.ts +87 -0
  194. package/packages/server/dist/services/observabilityService.d.ts.map +1 -0
  195. package/packages/server/dist/services/observabilityService.js +0 -0
  196. package/packages/server/dist/services/observabilityService.js.map +1 -0
  197. package/packages/server/dist/services/queueService.d.ts.map +1 -1
  198. package/packages/server/dist/services/queueService.js +48 -2
  199. package/packages/server/dist/services/queueService.js.map +1 -1
  200. package/packages/server/dist/services/sessionService.d.ts +16 -0
  201. package/packages/server/dist/services/sessionService.d.ts.map +1 -1
  202. package/packages/server/dist/services/sessionService.js +125 -0
  203. package/packages/server/dist/services/sessionService.js.map +1 -1
  204. package/packages/server/dist/services/snippetService.d.ts +54 -0
  205. package/packages/server/dist/services/snippetService.d.ts.map +1 -0
  206. package/packages/server/dist/services/snippetService.js +371 -0
  207. package/packages/server/dist/services/snippetService.js.map +1 -0
  208. package/packages/server/dist/services/tokenCountService.d.ts +71 -0
  209. package/packages/server/dist/services/tokenCountService.d.ts.map +1 -0
  210. package/packages/server/dist/services/tokenCountService.js +313 -0
  211. package/packages/server/dist/services/tokenCountService.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/snippets/apply-qa-fixes +7 -5
  217. package/packages/server/dist/snippets/qa-review +5 -1
  218. package/packages/server/dist/snippets/split-commit +9 -0
  219. package/packages/server/dist/utils/applySecretsPolicy.d.ts +53 -0
  220. package/packages/server/dist/utils/applySecretsPolicy.d.ts.map +1 -0
  221. package/packages/server/dist/utils/applySecretsPolicy.js +204 -0
  222. package/packages/server/dist/utils/applySecretsPolicy.js.map +1 -0
  223. package/packages/server/dist/utils/assertNoSecretOnShared.d.ts +40 -0
  224. package/packages/server/dist/utils/assertNoSecretOnShared.d.ts.map +1 -0
  225. package/packages/server/dist/utils/assertNoSecretOnShared.js +47 -0
  226. package/packages/server/dist/utils/assertNoSecretOnShared.js.map +1 -0
  227. package/packages/server/dist/utils/assertSafeBundlePath.d.ts +29 -0
  228. package/packages/server/dist/utils/assertSafeBundlePath.d.ts.map +1 -0
  229. package/packages/server/dist/utils/assertSafeBundlePath.js +53 -0
  230. package/packages/server/dist/utils/assertSafeBundlePath.js.map +1 -0
  231. package/packages/server/dist/utils/bundledBinaryModelSupport.d.ts +7 -0
  232. package/packages/server/dist/utils/bundledBinaryModelSupport.d.ts.map +1 -0
  233. package/packages/server/dist/utils/bundledBinaryModelSupport.js +107 -0
  234. package/packages/server/dist/utils/bundledBinaryModelSupport.js.map +1 -0
  235. package/packages/server/dist/utils/effortUtils.d.ts +2 -2
  236. package/packages/server/dist/utils/effortUtils.js +5 -5
  237. package/packages/server/dist/utils/effortUtils.js.map +1 -1
  238. package/packages/server/dist/utils/errors.d.ts +1 -0
  239. package/packages/server/dist/utils/errors.d.ts.map +1 -1
  240. package/packages/server/dist/utils/errors.js +17 -0
  241. package/packages/server/dist/utils/errors.js.map +1 -1
  242. package/packages/server/dist/utils/gitignoreFilter.d.ts +23 -0
  243. package/packages/server/dist/utils/gitignoreFilter.d.ts.map +1 -0
  244. package/packages/server/dist/utils/gitignoreFilter.js +42 -0
  245. package/packages/server/dist/utils/gitignoreFilter.js.map +1 -0
  246. package/packages/server/dist/utils/harnessBundleSchema.d.ts +107 -0
  247. package/packages/server/dist/utils/harnessBundleSchema.d.ts.map +1 -0
  248. package/packages/server/dist/utils/harnessBundleSchema.js +89 -0
  249. package/packages/server/dist/utils/harnessBundleSchema.js.map +1 -0
  250. package/packages/server/dist/utils/harnessPaths.d.ts +74 -0
  251. package/packages/server/dist/utils/harnessPaths.d.ts.map +1 -0
  252. package/packages/server/dist/utils/harnessPaths.js +247 -0
  253. package/packages/server/dist/utils/harnessPaths.js.map +1 -0
  254. package/packages/server/dist/utils/secretHeuristic.d.ts +72 -0
  255. package/packages/server/dist/utils/secretHeuristic.d.ts.map +1 -0
  256. package/packages/server/dist/utils/secretHeuristic.js +163 -0
  257. package/packages/server/dist/utils/secretHeuristic.js.map +1 -0
  258. package/packages/server/dist/utils/secretPlaceholderNamer.d.ts +41 -0
  259. package/packages/server/dist/utils/secretPlaceholderNamer.d.ts.map +1 -0
  260. package/packages/server/dist/utils/secretPlaceholderNamer.js +81 -0
  261. package/packages/server/dist/utils/secretPlaceholderNamer.js.map +1 -0
  262. package/packages/server/dist/utils/serverPathResolver.d.ts +29 -0
  263. package/packages/server/dist/utils/serverPathResolver.d.ts.map +1 -0
  264. package/packages/server/dist/utils/serverPathResolver.js +59 -0
  265. package/packages/server/dist/utils/serverPathResolver.js.map +1 -0
  266. package/packages/server/dist/utils/snippetPaths.d.ts +61 -0
  267. package/packages/server/dist/utils/snippetPaths.d.ts.map +1 -0
  268. package/packages/server/dist/utils/snippetPaths.js +123 -0
  269. package/packages/server/dist/utils/snippetPaths.js.map +1 -0
  270. package/packages/server/dist/utils/structuredEditor.d.ts +34 -0
  271. package/packages/server/dist/utils/structuredEditor.d.ts.map +1 -0
  272. package/packages/server/dist/utils/structuredEditor.js +111 -0
  273. package/packages/server/dist/utils/structuredEditor.js.map +1 -0
  274. package/packages/server/package.json +6 -2
  275. package/packages/server/resources/internals/INDEX.md +25 -0
  276. package/packages/server/resources/internals/bmad-qa-fix-marker.md +32 -0
  277. package/packages/server/resources/internals/harness-files.md +85 -0
  278. package/packages/server/resources/internals/image-storage.md +43 -0
  279. package/packages/server/resources/internals/observability-storage.md +23 -0
  280. package/packages/server/resources/manual/01-getting-started.md +104 -0
  281. package/packages/server/resources/manual/02-chat.md +285 -0
  282. package/packages/server/resources/manual/03-sessions.md +48 -0
  283. package/packages/server/resources/manual/04-slash-commands-favorites.md +152 -0
  284. package/packages/server/resources/manual/05-projects.md +76 -0
  285. package/packages/server/resources/manual/06-file-explorer-editor.md +90 -0
  286. package/packages/server/resources/manual/07-git.md +94 -0
  287. package/packages/server/resources/manual/08-terminal.md +59 -0
  288. package/packages/server/resources/manual/09-queue-runner.md +262 -0
  289. package/packages/server/resources/manual/10-project-board.md +194 -0
  290. package/packages/server/resources/manual/11-bmad-method-integration.md +130 -0
  291. package/packages/server/resources/manual/12-harness-workbench.md +256 -0
  292. package/packages/server/resources/manual/13-settings.md +241 -0
  293. package/packages/server/resources/manual/14-keyboard-shortcuts.md +68 -0
  294. package/packages/server/resources/manual/15-environment-variables.md +28 -0
  295. package/packages/server/resources/manual/16-troubleshooting.md +110 -0
  296. package/packages/server/resources/manual/INDEX.md +60 -0
  297. package/packages/shared/dist/index.d.ts +7 -0
  298. package/packages/shared/dist/index.d.ts.map +1 -1
  299. package/packages/shared/dist/index.js +14 -0
  300. package/packages/shared/dist/index.js.map +1 -1
  301. package/packages/shared/dist/types/bmadCoreConfig.d.ts +71 -0
  302. package/packages/shared/dist/types/bmadCoreConfig.d.ts.map +1 -0
  303. package/packages/shared/dist/types/bmadCoreConfig.js +30 -0
  304. package/packages/shared/dist/types/bmadCoreConfig.js.map +1 -0
  305. package/packages/shared/dist/types/bmadStatus.d.ts +10 -0
  306. package/packages/shared/dist/types/bmadStatus.d.ts.map +1 -1
  307. package/packages/shared/dist/types/bmadStatus.js.map +1 -1
  308. package/packages/shared/dist/types/board.d.ts +6 -0
  309. package/packages/shared/dist/types/board.d.ts.map +1 -1
  310. package/packages/shared/dist/types/command.d.ts +3 -3
  311. package/packages/shared/dist/types/command.d.ts.map +1 -1
  312. package/packages/shared/dist/types/contextBuilder.d.ts +102 -0
  313. package/packages/shared/dist/types/contextBuilder.d.ts.map +1 -0
  314. package/packages/shared/dist/types/contextBuilder.js +55 -0
  315. package/packages/shared/dist/types/contextBuilder.js.map +1 -0
  316. package/packages/shared/dist/types/harness.d.ts +1211 -0
  317. package/packages/shared/dist/types/harness.d.ts.map +1 -0
  318. package/packages/shared/dist/types/harness.js +107 -0
  319. package/packages/shared/dist/types/harness.js.map +1 -0
  320. package/packages/shared/dist/types/harnessBundle.d.ts +205 -0
  321. package/packages/shared/dist/types/harnessBundle.d.ts.map +1 -0
  322. package/packages/shared/dist/types/harnessBundle.js +18 -0
  323. package/packages/shared/dist/types/harnessBundle.js.map +1 -0
  324. package/packages/shared/dist/types/marketplace.d.ts +83 -0
  325. package/packages/shared/dist/types/marketplace.d.ts.map +1 -0
  326. package/packages/shared/dist/types/marketplace.js +18 -0
  327. package/packages/shared/dist/types/marketplace.js.map +1 -0
  328. package/packages/shared/dist/types/observability.d.ts +148 -0
  329. package/packages/shared/dist/types/observability.d.ts.map +1 -0
  330. package/packages/shared/dist/types/observability.js +24 -0
  331. package/packages/shared/dist/types/observability.js.map +1 -0
  332. package/packages/shared/dist/types/preferences.d.ts +4 -0
  333. package/packages/shared/dist/types/preferences.d.ts.map +1 -1
  334. package/packages/shared/dist/types/preferences.js.map +1 -1
  335. package/packages/shared/dist/types/queue.d.ts +9 -0
  336. package/packages/shared/dist/types/queue.d.ts.map +1 -1
  337. package/packages/shared/dist/types/sdk.d.ts +1 -1
  338. package/packages/shared/dist/types/sdk.d.ts.map +1 -1
  339. package/packages/shared/dist/types/sdk.js +1 -1
  340. package/packages/shared/dist/types/sdk.js.map +1 -1
  341. package/packages/shared/dist/types/websocket.d.ts +10 -0
  342. package/packages/shared/dist/types/websocket.d.ts.map +1 -1
  343. package/packages/shared/dist/utils/markdownSections.d.ts +50 -0
  344. package/packages/shared/dist/utils/markdownSections.d.ts.map +1 -0
  345. package/packages/shared/dist/utils/markdownSections.js +111 -0
  346. package/packages/shared/dist/utils/markdownSections.js.map +1 -0
  347. package/packages/shared/dist/utils/queueParser.d.ts.map +1 -1
  348. package/packages/shared/dist/utils/queueParser.js +104 -0
  349. package/packages/shared/dist/utils/queueParser.js.map +1 -1
  350. package/scripts/build-manual-shards.mjs +100 -0
  351. package/packages/client/dist/assets/index-6jREnVYd.js +0 -2
  352. package/packages/client/dist/assets/index-BFF0iqyW.css +0 -32
  353. package/packages/client/dist/assets/index-BcI4y-fU.js +0 -1454
@@ -318,10 +318,6 @@
318
318
  "invalidChatId": "유효하지 않은 Chat ID입니다.",
319
319
  "writeError": "Telegram 설정 저장에 실패했습니다.",
320
320
  "testError": "테스트 알림 전송 중 서버 오류가 발생했습니다."
321
- },
322
- "rateLimit": {
323
- "projectCreate": "프로젝트 생성 요청이 너무 많습니다. 잠시 후 다시 시도해 주세요.",
324
- "pathValidation": "경로 검증 요청이 너무 많습니다. 잠시 후 다시 시도해 주세요."
325
321
  }
326
322
  }
327
323
  }
@@ -307,10 +307,6 @@
307
307
  "invalidChatId": "Chat ID inválido.",
308
308
  "writeError": "Erro ao salvar configurações do Telegram.",
309
309
  "testError": "Erro do servidor ao enviar notificação de teste."
310
- },
311
- "rateLimit": {
312
- "projectCreate": "Muitas solicitações de criação de projeto. Tente novamente mais tarde.",
313
- "pathValidation": "Muitas solicitações de validação de caminho. Tente novamente mais tarde."
314
310
  }
315
311
  }
316
312
  }
@@ -307,10 +307,6 @@
307
307
  "invalidChatId": "无效的Chat ID。",
308
308
  "writeError": "保存Telegram设置失败。",
309
309
  "testError": "发送测试通知时服务器出错。"
310
- },
311
- "rateLimit": {
312
- "projectCreate": "项目创建请求过多。请稍后再试。",
313
- "pathValidation": "路径验证请求过多。请稍后再试。"
314
310
  }
315
311
  }
316
312
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Story 28.0.5: Harness workbench routes.
3
+ * Mounted at /api/harness — independent of /api/projects because the user
4
+ * scope (~/.claude) is not nested under any project.
5
+ */
6
+ declare const router: import("express-serve-static-core").Router;
7
+ export default router;
8
+ //# sourceMappingURL=harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/routes/harness.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,QAAA,MAAM,MAAM,4CAAW,CAAC;AA2JxB,eAAe,MAAM,CAAC"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Story 28.0.5: Harness workbench routes.
3
+ * Mounted at /api/harness — independent of /api/projects because the user
4
+ * scope (~/.claude) is not nested under any project.
5
+ */
6
+ import { Router } from 'express';
7
+ import express from 'express';
8
+ import { harnessController } from '../controllers/harnessController.js';
9
+ import { harnessPluginController } from '../controllers/harnessPluginController.js';
10
+ import { harnessSkillController } from '../controllers/harnessSkillController.js';
11
+ import { harnessMcpController } from '../controllers/harnessMcpController.js';
12
+ import { harnessHookController } from '../controllers/harnessHookController.js';
13
+ import { harnessCommandController } from '../controllers/harnessCommandController.js';
14
+ import { harnessAgentController } from '../controllers/harnessAgentController.js';
15
+ import { claudeMdController } from '../controllers/claudeMdController.js';
16
+ import { harnessShareScopeController } from '../controllers/harnessShareScopeController.js';
17
+ import { harnessLintController } from '../controllers/harnessLintController.js';
18
+ import { harnessBundleController, handleBundleUpload } from '../controllers/harnessBundleController.js';
19
+ import { bmadCoreConfigController } from '../controllers/bmadCoreConfigController.js';
20
+ import { contextBuilderController } from '../controllers/contextBuilderController.js';
21
+ import { observabilityController } from '../controllers/observabilityController.js';
22
+ import { marketplaceController } from '../controllers/marketplaceController.js';
23
+ const router = Router();
24
+ // Same body size as fileSystem routes (JSON envelopes can carry ~1MB source files).
25
+ const largeBodyParser = express.json({ limit: '5mb' });
26
+ router.get('/list', harnessController.list);
27
+ router.get('/read', harnessController.read);
28
+ router.put('/write', largeBodyParser, harnessController.write);
29
+ router.post('/patch-structured', largeBodyParser, harnessController.patchStructured);
30
+ // Story 28.1 — plugin list / toggle (user scope only)
31
+ router.get('/plugins', harnessPluginController.list);
32
+ router.post('/plugins/toggle', express.json({ limit: '32kb' }), harnessPluginController.toggle);
33
+ // Story 28.2 — skill list / read / update / copy + per-skill bundle file edit.
34
+ // The bundle routes are mounted *before* `/skills/:name` so the splat segment
35
+ // (`/bundle/*`) is matched first; otherwise Express would treat "bundle" as a
36
+ // `:name` value.
37
+ router.post('/skills/copy', largeBodyParser, harnessSkillController.copy);
38
+ router.get('/skills', harnessSkillController.list);
39
+ router.get('/skills/:name/bundle/*', harnessSkillController.readBundle);
40
+ router.put('/skills/:name/bundle/*', largeBodyParser, harnessSkillController.writeBundle);
41
+ router.get('/skills/:name', harnessSkillController.read);
42
+ router.put('/skills/:name', largeBodyParser, harnessSkillController.update);
43
+ // Story 28.3 — MCP list / read / update / copy / delete.
44
+ // `copy` lives above `/mcps/:name` so Express prefers the literal segment.
45
+ router.post('/mcps/copy', largeBodyParser, harnessMcpController.copy);
46
+ router.get('/mcps', harnessMcpController.list);
47
+ router.get('/mcps/:name', harnessMcpController.read);
48
+ router.put('/mcps/:name', largeBodyParser, harnessMcpController.update);
49
+ router.delete('/mcps/:name', largeBodyParser, harnessMcpController.delete);
50
+ // Story 28.4 — Hook list / read / create / update / copy / delete.
51
+ // `copy` and the splat-free POST live above `/hooks/:event/...` so Express
52
+ // prefers the literal segments.
53
+ router.post('/hooks/copy', largeBodyParser, harnessHookController.copy);
54
+ router.post('/hooks', largeBodyParser, harnessHookController.create);
55
+ router.get('/hooks', harnessHookController.list);
56
+ router.get('/hooks/:event/:groupIndex/:hookIndex', harnessHookController.read);
57
+ router.put('/hooks/:event/:groupIndex/:hookIndex', largeBodyParser, harnessHookController.update);
58
+ router.delete('/hooks/:event/:groupIndex/:hookIndex', largeBodyParser, harnessHookController.delete);
59
+ // Story 28.5 — Slash command list / read / create / update / copy / copy-directory / delete.
60
+ // path-as-glob — params[0] holds the full relative path (e.g. "BMad/agents/sm.md").
61
+ // Literal segments (`/commands/copy`, `/commands/copy-directory`) live above the
62
+ // splat so Express prefers them.
63
+ router.post('/commands/copy-directory', largeBodyParser, harnessCommandController.copyDirectory);
64
+ router.post('/commands/copy', largeBodyParser, harnessCommandController.copy);
65
+ // Story 30.7 (Task B.2) — env-ref replace endpoint. Must live above the
66
+ // splat so Express does not treat `replace-secret-with-env-ref` as a
67
+ // command relative path.
68
+ router.post('/commands/replace-secret-with-env-ref', largeBodyParser, harnessCommandController.replaceSecretWithEnvRef);
69
+ router.post('/commands', largeBodyParser, harnessCommandController.create);
70
+ router.get('/commands', harnessCommandController.list);
71
+ router.get('/commands/*', harnessCommandController.read);
72
+ router.put('/commands/*', largeBodyParser, harnessCommandController.update);
73
+ router.delete('/commands/*', largeBodyParser, harnessCommandController.delete);
74
+ // Story 28.6 — Sub-agent list / read / create / update / copy / delete.
75
+ // Single-segment :name path param (flat-only — no recursive subdirectories per AC1.a).
76
+ // Literal `/agents/copy` and the splat-free POST live above the dynamic
77
+ // `:name` segment so Express prefers them.
78
+ router.post('/agents/copy', largeBodyParser, harnessAgentController.copy);
79
+ // Story 30.7 (Task B.2) — env-ref replace endpoint. Lives above the dynamic
80
+ // `:name` so Express does not match the literal as an agent name.
81
+ router.post('/agents/replace-secret-with-env-ref', largeBodyParser, harnessAgentController.replaceSecretWithEnvRef);
82
+ router.post('/agents', largeBodyParser, harnessAgentController.create);
83
+ router.get('/agents', harnessAgentController.list);
84
+ router.get('/agents/:name', harnessAgentController.read);
85
+ router.put('/agents/:name', largeBodyParser, harnessAgentController.update);
86
+ router.delete('/agents/:name', largeBodyParser, harnessAgentController.delete);
87
+ // Story 29.1 — CLAUDE.md (free-edit memory layer): two files only
88
+ // (project root + global). POST is a distinct create-empty path that fails
89
+ // with 409 if the file already exists (PUT-with-empty-content overwrite is
90
+ // intentionally a separate code path so client intent is preserved).
91
+ router.get('/claude-md', claudeMdController.read);
92
+ router.put('/claude-md', largeBodyParser, claudeMdController.write);
93
+ router.post('/claude-md', largeBodyParser, claudeMdController.create);
94
+ // Story 30.1 — Share-scope evaluator: classifies harness files as
95
+ // shared / local / fullyIgnored from `.gitignore` and derives the project
96
+ // Mode A/B verdict. Project scope only — `.gitignore` is irrelevant for
97
+ // the user-scope (`~/.claude`) tree.
98
+ router.get('/share-scope', harnessShareScopeController.evaluate);
99
+ // Story 30.7 (Task D.3) — append a pattern to the project `.gitignore`
100
+ // (idempotent). Used by the `SecretOnSharedDialog → Move to local` flow
101
+ // when the sibling pre-check detects `**/.claude/**/*.local.*` is missing.
102
+ router.post('/share-scope/:projectSlug/append-gitignore', express.json({ limit: '4kb' }), harnessShareScopeController.appendGitignore);
103
+ // Story 30.2 — Static harness lint: 7 rules across the 5 harness domains
104
+ // (skill / mcp / hook / command / agent). Returns LintIssue[] + the user's
105
+ // effective rule preferences (defaults merged with ~/.hammoc/preferences.json).
106
+ router.get('/lint', harnessLintController.evaluate);
107
+ // Story 30.5 — Harness Export/Import bundle: 4 endpoints providing the
108
+ // server-side single source of truth for serializing a project's harness
109
+ // surface into a ZIP + manifest.json and back. Multipart upload is only
110
+ // required by the import-preview endpoint; the other three use JSON bodies.
111
+ router.post('/bundle/export', largeBodyParser, harnessBundleController.export);
112
+ router.post('/bundle/import/preview', handleBundleUpload, harnessBundleController.importPreview);
113
+ router.post('/bundle/import/apply', largeBodyParser, harnessBundleController.importApply);
114
+ router.get('/bundle/plugin-deps', harnessBundleController.pluginDeps);
115
+ // Story 31.1 — BMad core-config editor: read / AST-patch / raw-overwrite of a
116
+ // single project's `.bmad-core/core-config.yaml` (BMad projects only — the nav
117
+ // gate is client-side via `isBmadProject`). The `/raw` segment lives above the
118
+ // bare `:projectSlug` PATCH so Express does not treat `raw` as a slug value.
119
+ router.get('/bmad-config/:projectSlug', bmadCoreConfigController.read);
120
+ router.put('/bmad-config/:projectSlug/raw', largeBodyParser, bmadCoreConfigController.writeRaw);
121
+ router.patch('/bmad-config/:projectSlug', largeBodyParser, bmadCoreConfigController.patch);
122
+ // Story 31.2 — SessionStart context-builder: read / save+generate / disable the
123
+ // `.hammoc/context-builder.json` manifest and its generated `.mjs` + settings
124
+ // entry. Available on ALL projects (no BMad gate). The `/disable` segment lives
125
+ // above the bare `:projectSlug` PUT so Express does not treat `disable` as a
126
+ // slug value.
127
+ router.get('/context-builder/:projectSlug', contextBuilderController.read);
128
+ router.post('/context-builder/:projectSlug/disable', largeBodyParser, contextBuilderController.disable);
129
+ router.put('/context-builder/:projectSlug', largeBodyParser, contextBuilderController.write);
130
+ // Story 31.3 — Observability: MCP call log (read-only aggregates + timeline) +
131
+ // token attribution + count_tokens proxy + global tokenizer preference.
132
+ // Available on ALL projects (no gate). The global `/tokenizer-pref` (no
133
+ // projectSlug) is mounted ABOVE the `:projectSlug` routes so Express does not
134
+ // treat `tokenizer-pref` as a slug. The MCP log has no write endpoint —
135
+ // records are appended by the streamCallbacks recorder.
136
+ const smallBodyParser = express.json({ limit: '32kb' });
137
+ router.get('/observability/tokenizer-pref', observabilityController.getTokenizerPref);
138
+ router.put('/observability/tokenizer-pref', smallBodyParser, observabilityController.setTokenizerPref);
139
+ router.get('/observability/:projectSlug/mcp-calls', observabilityController.mcpCalls);
140
+ router.get('/observability/:projectSlug/token-attribution', observabilityController.tokenAttribution);
141
+ router.post('/observability/:projectSlug/exact-count', smallBodyParser, observabilityController.exactCount);
142
+ // Story 31.4 — Plugin marketplace catalog (read-only). Single GET endpoint:
143
+ // the unified `plugins[]` catalog across registered marketplaces + installed
144
+ // join + per-market partial failures + installed_plugins.json format warning.
145
+ // No install/add POST — direct-install automation was dropped after spike #2
146
+ // (negative); installs are copy-only command guides (see sdk-upstream-issues.md
147
+ // §17·§18).
148
+ router.get('/marketplace/:projectSlug/catalog', marketplaceController.catalog);
149
+ export default router;
150
+ //# sourceMappingURL=harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/routes/harness.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,QAAA,MAAM,MAAM,4CAAW,CAAC;AA2GxB,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,QAAA,MAAM,MAAM,4CAAW,CAAC;AAgCxB,eAAe,MAAM,CAAC"}
@@ -7,69 +7,14 @@
7
7
  import { Router } from 'express';
8
8
  import { projectController } from '../controllers/projectController.js';
9
9
  const router = Router();
10
- const rateLimitStore = new Map();
11
- /**
12
- * Cleanup expired rate limit records periodically
13
- * Runs every 5 minutes to prevent memory growth
14
- */
15
- const CLEANUP_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
16
- const RECORD_TTL_MS = 2 * 60 * 1000; // Keep records for 2 minutes after window expires
17
- function cleanupExpiredRecords() {
18
- const now = Date.now();
19
- for (const [ip, record] of rateLimitStore.entries()) {
20
- // Remove records that are older than TTL
21
- if (now - record.windowStart > RECORD_TTL_MS) {
22
- rateLimitStore.delete(ip);
23
- }
24
- }
25
- }
26
- // Start periodic cleanup
27
- const cleanupInterval = setInterval(cleanupExpiredRecords, CLEANUP_INTERVAL_MS);
28
- // Cleanup on process exit (for graceful shutdown)
29
- if (typeof process !== 'undefined' && process.on) {
30
- process.on('beforeExit', () => {
31
- clearInterval(cleanupInterval);
32
- });
33
- }
34
- function createRateLimiter(maxRequests, windowMs) {
35
- return (req, res, next) => {
36
- const ip = req.ip || req.socket.remoteAddress || 'unknown';
37
- const now = Date.now();
38
- const record = rateLimitStore.get(ip);
39
- if (!record || now - record.windowStart > windowMs) {
40
- // New window
41
- rateLimitStore.set(ip, { count: 1, windowStart: now });
42
- next();
43
- return;
44
- }
45
- if (record.count >= maxRequests) {
46
- const retryAfter = Math.ceil((record.windowStart + windowMs - now) / 1000);
47
- res.status(429).json({
48
- error: {
49
- code: 'RATE_LIMIT_EXCEEDED',
50
- message: maxRequests === 10
51
- ? req.t('preferences.rateLimit.projectCreate')
52
- : req.t('preferences.rateLimit.pathValidation'),
53
- details: { retryAfter },
54
- },
55
- });
56
- return;
57
- }
58
- record.count++;
59
- next();
60
- };
61
- }
62
- // Rate limiters
63
- const createProjectLimiter = createRateLimiter(10, 60 * 1000); // 10 requests per minute
64
- const validatePathLimiter = createRateLimiter(30, 60 * 1000); // 30 requests per minute
65
10
  // GET /api/projects - List all projects
66
11
  router.get('/', projectController.list);
67
- // POST /api/projects - Create new project (rate limited)
68
- router.post('/', createProjectLimiter, projectController.create);
12
+ // POST /api/projects - Create new project
13
+ router.post('/', projectController.create);
69
14
  // GET /api/projects/bmad-versions - List available BMad method versions
70
15
  router.get('/bmad-versions', projectController.bmadVersions);
71
16
  // POST /api/projects/:projectSlug/setup-bmad - Setup BMad for existing project
72
- router.post('/:projectSlug/setup-bmad', createProjectLimiter, projectController.setupBmad);
17
+ router.post('/:projectSlug/setup-bmad', projectController.setupBmad);
73
18
  // DELETE /api/projects/:projectSlug - Delete a project
74
19
  router.delete('/:projectSlug', projectController.delete);
75
20
  // GET /api/projects/:projectSlug/settings - Get project settings with effective values
@@ -80,7 +25,7 @@ router.patch('/:projectSlug/settings', projectController.updateSettings);
80
25
  router.get('/:projectSlug/system-prompt', projectController.getSystemPrompt);
81
26
  // POST /api/projects/:projectSlug/open-explorer - Open project in system file explorer (localhost only)
82
27
  router.post('/:projectSlug/open-explorer', projectController.openExplorer);
83
- // POST /api/projects/validate-path - Validate directory path (rate limited)
84
- router.post('/validate-path', validatePathLimiter, projectController.validatePath);
28
+ // POST /api/projects/validate-path - Validate directory path
29
+ router.post('/validate-path', projectController.validatePath);
85
30
  export default router;
86
31
  //# sourceMappingURL=projects.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAExE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,wCAAwC;AACxC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAExC,0CAA0C;AAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE3C,wEAAwE;AACxE,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;AAE7D,+EAA+E;AAC/E,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAErE,uDAAuD;AACvD,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAEzD,uFAAuF;AACvF,MAAM,CAAC,GAAG,CAAC,wBAAwB,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;AAEpE,sEAAsE;AACtE,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;AAEzE,2EAA2E;AAC3E,MAAM,CAAC,GAAG,CAAC,6BAA6B,EAAE,iBAAiB,CAAC,eAAe,CAAC,CAAC;AAE7E,wGAAwG;AACxG,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;AAE3E,6DAA6D;AAC7D,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;AAE9D,eAAe,MAAM,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Story 29.2: Snippet management routes.
3
+ *
4
+ * Mounted at `/api/snippets`. Intentionally distinct from `/api/harness/*`
5
+ * because snippets are Hammoc-native (`%name%` chat-input expansion via
6
+ * `snippetResolver`), not a Claude Code harness primitive — keeping the
7
+ * namespaces separate makes the system-of-record obvious at the URL boundary.
8
+ *
9
+ * Route ordering: literal segments (`/copy`) live above the dynamic
10
+ * `/:scope/:name` so Express prefers them.
11
+ */
12
+ declare const router: import("express-serve-static-core").Router;
13
+ export default router;
14
+ //# sourceMappingURL=snippets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snippets.d.ts","sourceRoot":"","sources":["../../src/routes/snippets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,QAAA,MAAM,MAAM,4CAAW,CAAC;AAgBxB,eAAe,MAAM,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Story 29.2: Snippet management routes.
3
+ *
4
+ * Mounted at `/api/snippets`. Intentionally distinct from `/api/harness/*`
5
+ * because snippets are Hammoc-native (`%name%` chat-input expansion via
6
+ * `snippetResolver`), not a Claude Code harness primitive — keeping the
7
+ * namespaces separate makes the system-of-record obvious at the URL boundary.
8
+ *
9
+ * Route ordering: literal segments (`/copy`) live above the dynamic
10
+ * `/:scope/:name` so Express prefers them.
11
+ */
12
+ import { Router } from 'express';
13
+ import express from 'express';
14
+ import { snippetController } from '../controllers/snippetController.js';
15
+ const router = Router();
16
+ const largeBodyParser = express.json({ limit: '5mb' });
17
+ const smallBodyParser = express.json({ limit: '64kb' });
18
+ router.get('/', snippetController.list);
19
+ // Literal-segment endpoints first.
20
+ router.post('/copy', smallBodyParser, snippetController.copy);
21
+ // Dynamic `:scope/:name` endpoints.
22
+ router.get('/:scope/:name', snippetController.read);
23
+ router.post('/:scope/:name', largeBodyParser, snippetController.create);
24
+ router.put('/:scope/:name', largeBodyParser, snippetController.update);
25
+ router.delete('/:scope/:name', smallBodyParser, snippetController.delete);
26
+ export default router;
27
+ //# sourceMappingURL=snippets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snippets.js","sourceRoot":"","sources":["../../src/routes/snippets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAExE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AACvD,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AAExD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAExC,mCAAmC;AACnC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAE9D,oCAAoC;AACpC,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACpD,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACxE,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,eAAe,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACvE,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,eAAe,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE1E,eAAe,MAAM,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Story 31.1: BMad core-config editor service (Epic 31).
3
+ *
4
+ * Domain: the single `<projectRoot>/.bmad-core/core-config.yaml` file that
5
+ * drives downstream BMad agents (`/dev` · `/sm` · `/qa`). This file is the
6
+ * SIBLING of `.claude/` (it lives under `.bmad-core/`, outside the harness
7
+ * whitelist), so it gets a dedicated canonical-path resolver
8
+ * (`resolveBmadCoreConfigPath`) exactly like Story 29.1's CLAUDE.md and Story
9
+ * 30.7's `.gitignore`.
10
+ *
11
+ * Separation from `bmadStatusService`: that service SCANS the whole BMad
12
+ * project (epics, stories, QA, documents) and returns a status snapshot;
13
+ * this service does single-file R/W on the config itself. They read the same
14
+ * file but expose different shapes (status snapshot vs raw config + AST ops),
15
+ * so they stay separate.
16
+ *
17
+ * YAML parser single source of truth: `yaml` (eemeli) via
18
+ * `structuredEditor.applyYamlPatch`, which preserves comments, key order,
19
+ * quoting, and blank-line metadata across a patch. `js-yaml@4` (used by
20
+ * `bmadStatusService` for a lossy status read) must NOT be used here — it has
21
+ * no comment-preservation path (see structuredEditor.ts header).
22
+ *
23
+ * Method contract (all throw typed errors from `HARNESS_ERRORS`):
24
+ * read — content + mtime; missing file → HARNESS_FILE_NOT_FOUND
25
+ * patchKey — AST patch preserving comments/order; STALE_WRITE guard
26
+ * writeRaw — raw text overwrite (Raw editor); same STALE_WRITE guard
27
+ * parseUnknownKeys — partition parsed YAML into known/unknown top-level keys
28
+ */
29
+ import { type HarnessStructuredPatchOp, type BmadCoreConfigKnownKeys } from '@hammoc/shared';
30
+ export interface BmadCoreConfigReadResult {
31
+ content: string;
32
+ mtime: string;
33
+ }
34
+ export interface BmadCoreConfigParsed {
35
+ knownKeys: BmadCoreConfigKnownKeys;
36
+ unknownKeys: Record<string, unknown>;
37
+ }
38
+ declare class BmadCoreConfigService {
39
+ /**
40
+ * Read the raw config text + mtime. Missing file →
41
+ * HARNESS_FILE_NOT_FOUND: the BMad-project gate means this service is only
42
+ * ever called for projects that have `.bmad-core/`, so a missing
43
+ * core-config.yaml is an abnormal state, not an empty-state.
44
+ */
45
+ read(projectSlug: string): Promise<BmadCoreConfigReadResult>;
46
+ /**
47
+ * Partition a parsed config into the 10 known top-level keys vs everything
48
+ * else. Known nested groups (`qa`/`prd`/`architecture`/`brownfieldEpic`)
49
+ * pass through whole; their leaves are the 18-key matrix the form renders.
50
+ * Unknown top-level keys are surfaced read-only (AC4). Unparseable input →
51
+ * HARNESS_PARSE_ERROR so the client can fall back to raw editing.
52
+ */
53
+ parseUnknownKeys(content: string): BmadCoreConfigParsed;
54
+ /**
55
+ * Apply AST-level patches to the config, preserving comments/order/quoting
56
+ * for every untouched node — including unknown keys (AC4.b). Running through
57
+ * a read → patch → write round trip means an external mutation that slipped
58
+ * in between read and write surfaces as STALE_WRITE.
59
+ *
60
+ * `expectedMtime` semantics mirror `harnessService.patchStructured`: when the
61
+ * client supplies it, that value is the guard; otherwise the freshly-read
62
+ * mtime guards against a concurrent write during our own round trip.
63
+ */
64
+ patchKey(projectSlug: string, ops: HarnessStructuredPatchOp[], expectedMtime?: string): Promise<{
65
+ mtime: string;
66
+ }>;
67
+ /**
68
+ * Raw-mode overwrite: write the supplied text verbatim, bypassing the AST
69
+ * patch (the user intentionally took control of the whole file). The
70
+ * STALE_WRITE guard still applies so a raw save cannot silently clobber an
71
+ * external edit (AC5.b).
72
+ */
73
+ writeRaw(projectSlug: string, content: string, expectedMtime?: string): Promise<{
74
+ mtime: string;
75
+ }>;
76
+ /**
77
+ * Shared write tail: STALE_WRITE guard + writeFile + self-write echo
78
+ * suppression. Mirrors `harnessService.write` / `claudeMdService.write`.
79
+ * The parent `.bmad-core/` directory is guaranteed to exist (BMad-project
80
+ * gate), so there is no auto-mkdir path here.
81
+ */
82
+ private writeInternal;
83
+ }
84
+ export declare const bmadCoreConfigService: BmadCoreConfigService;
85
+ export {};
86
+ //# sourceMappingURL=bmadCoreConfigService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bmadCoreConfigService.d.ts","sourceRoot":"","sources":["../../src/services/bmadCoreConfigService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC7B,MAAM,gBAAgB,CAAC;AAcxB,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,uBAAuB,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,cAAM,qBAAqB;IACzB;;;;;OAKG;IACG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAyBlE;;;;;;OAMG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB;IA4BvD;;;;;;;;;OASG;IACG,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,wBAAwB,EAAE,EAC/B,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAS7B;;;;;OAKG;IACG,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAK7B;;;;;OAKG;YACW,aAAa;CA0C5B;AAED,eAAO,MAAM,qBAAqB,uBAA8B,CAAC"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Story 31.1: BMad core-config editor service (Epic 31).
3
+ *
4
+ * Domain: the single `<projectRoot>/.bmad-core/core-config.yaml` file that
5
+ * drives downstream BMad agents (`/dev` · `/sm` · `/qa`). This file is the
6
+ * SIBLING of `.claude/` (it lives under `.bmad-core/`, outside the harness
7
+ * whitelist), so it gets a dedicated canonical-path resolver
8
+ * (`resolveBmadCoreConfigPath`) exactly like Story 29.1's CLAUDE.md and Story
9
+ * 30.7's `.gitignore`.
10
+ *
11
+ * Separation from `bmadStatusService`: that service SCANS the whole BMad
12
+ * project (epics, stories, QA, documents) and returns a status snapshot;
13
+ * this service does single-file R/W on the config itself. They read the same
14
+ * file but expose different shapes (status snapshot vs raw config + AST ops),
15
+ * so they stay separate.
16
+ *
17
+ * YAML parser single source of truth: `yaml` (eemeli) via
18
+ * `structuredEditor.applyYamlPatch`, which preserves comments, key order,
19
+ * quoting, and blank-line metadata across a patch. `js-yaml@4` (used by
20
+ * `bmadStatusService` for a lossy status read) must NOT be used here — it has
21
+ * no comment-preservation path (see structuredEditor.ts header).
22
+ *
23
+ * Method contract (all throw typed errors from `HARNESS_ERRORS`):
24
+ * read — content + mtime; missing file → HARNESS_FILE_NOT_FOUND
25
+ * patchKey — AST patch preserving comments/order; STALE_WRITE guard
26
+ * writeRaw — raw text overwrite (Raw editor); same STALE_WRITE guard
27
+ * parseUnknownKeys — partition parsed YAML into known/unknown top-level keys
28
+ */
29
+ import fs from 'fs/promises';
30
+ import { parse as parseYaml } from 'yaml';
31
+ import { HARNESS_ERRORS, BMAD_CORE_CONFIG_KNOWN_TOP_LEVEL_KEYS, } from '@hammoc/shared';
32
+ import { resolveBmadCoreConfigPath } from '../utils/harnessPaths.js';
33
+ import { applyYamlPatch } from '../utils/structuredEditor.js';
34
+ import { fileWatcherService } from './fileWatcherService.js';
35
+ function throwMapped(code, message, extras) {
36
+ const err = new Error(message);
37
+ err.code = code;
38
+ if (extras)
39
+ Object.assign(err, extras);
40
+ throw err;
41
+ }
42
+ const KNOWN_TOP_LEVEL = new Set(BMAD_CORE_CONFIG_KNOWN_TOP_LEVEL_KEYS);
43
+ class BmadCoreConfigService {
44
+ /**
45
+ * Read the raw config text + mtime. Missing file →
46
+ * HARNESS_FILE_NOT_FOUND: the BMad-project gate means this service is only
47
+ * ever called for projects that have `.bmad-core/`, so a missing
48
+ * core-config.yaml is an abnormal state, not an empty-state.
49
+ */
50
+ async read(projectSlug) {
51
+ const { absolutePath } = await resolveBmadCoreConfigPath(projectSlug);
52
+ let stat;
53
+ try {
54
+ stat = await fs.stat(absolutePath);
55
+ }
56
+ catch (error) {
57
+ const code = error.code;
58
+ if (code === 'ENOENT') {
59
+ throwMapped(HARNESS_ERRORS.HARNESS_FILE_NOT_FOUND.code, 'core-config.yaml not found', { absolutePath });
60
+ }
61
+ if (code === 'EACCES') {
62
+ throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
63
+ }
64
+ throw error;
65
+ }
66
+ if (!stat.isFile()) {
67
+ throwMapped(HARNESS_ERRORS.HARNESS_NOT_A_FILE.code, 'path is not a file');
68
+ }
69
+ const content = await fs.readFile(absolutePath, 'utf-8');
70
+ return { content, mtime: stat.mtime.toISOString() };
71
+ }
72
+ /**
73
+ * Partition a parsed config into the 10 known top-level keys vs everything
74
+ * else. Known nested groups (`qa`/`prd`/`architecture`/`brownfieldEpic`)
75
+ * pass through whole; their leaves are the 18-key matrix the form renders.
76
+ * Unknown top-level keys are surfaced read-only (AC4). Unparseable input →
77
+ * HARNESS_PARSE_ERROR so the client can fall back to raw editing.
78
+ */
79
+ parseUnknownKeys(content) {
80
+ let parsed;
81
+ try {
82
+ parsed = parseYaml(content);
83
+ }
84
+ catch (cause) {
85
+ throwMapped(HARNESS_ERRORS.HARNESS_PARSE_ERROR.code, `failed to parse core-config.yaml: ${cause?.message ?? String(cause)}`);
86
+ }
87
+ const knownKeys = {};
88
+ const unknownKeys = {};
89
+ // A comment-only / empty file parses to null or a scalar — treat as no keys.
90
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
91
+ for (const [key, value] of Object.entries(parsed)) {
92
+ if (KNOWN_TOP_LEVEL.has(key)) {
93
+ knownKeys[key] = value;
94
+ }
95
+ else {
96
+ unknownKeys[key] = value;
97
+ }
98
+ }
99
+ }
100
+ return { knownKeys: knownKeys, unknownKeys };
101
+ }
102
+ /**
103
+ * Apply AST-level patches to the config, preserving comments/order/quoting
104
+ * for every untouched node — including unknown keys (AC4.b). Running through
105
+ * a read → patch → write round trip means an external mutation that slipped
106
+ * in between read and write surfaces as STALE_WRITE.
107
+ *
108
+ * `expectedMtime` semantics mirror `harnessService.patchStructured`: when the
109
+ * client supplies it, that value is the guard; otherwise the freshly-read
110
+ * mtime guards against a concurrent write during our own round trip.
111
+ */
112
+ async patchKey(projectSlug, ops, expectedMtime) {
113
+ const { absolutePath } = await resolveBmadCoreConfigPath(projectSlug);
114
+ const current = await this.read(projectSlug);
115
+ const patched = applyYamlPatch(current.content, ops);
116
+ const guardMtime = expectedMtime ?? current.mtime;
117
+ return this.writeInternal(absolutePath, patched, guardMtime);
118
+ }
119
+ /**
120
+ * Raw-mode overwrite: write the supplied text verbatim, bypassing the AST
121
+ * patch (the user intentionally took control of the whole file). The
122
+ * STALE_WRITE guard still applies so a raw save cannot silently clobber an
123
+ * external edit (AC5.b).
124
+ */
125
+ async writeRaw(projectSlug, content, expectedMtime) {
126
+ const { absolutePath } = await resolveBmadCoreConfigPath(projectSlug);
127
+ return this.writeInternal(absolutePath, content, expectedMtime);
128
+ }
129
+ /**
130
+ * Shared write tail: STALE_WRITE guard + writeFile + self-write echo
131
+ * suppression. Mirrors `harnessService.write` / `claudeMdService.write`.
132
+ * The parent `.bmad-core/` directory is guaranteed to exist (BMad-project
133
+ * gate), so there is no auto-mkdir path here.
134
+ */
135
+ async writeInternal(absolutePath, content, expectedMtime) {
136
+ if (expectedMtime !== undefined) {
137
+ try {
138
+ const existing = await fs.stat(absolutePath);
139
+ const currentMtime = existing.mtime.toISOString();
140
+ if (currentMtime !== expectedMtime) {
141
+ throwMapped(HARNESS_ERRORS.HARNESS_STALE_WRITE.code, 'file changed on disk', { currentMtime });
142
+ }
143
+ }
144
+ catch (error) {
145
+ const code = error.code;
146
+ if (code === 'ENOENT') {
147
+ throwMapped(HARNESS_ERRORS.HARNESS_STALE_WRITE.code, 'file missing on disk', { currentMtime: '' });
148
+ }
149
+ if (code === HARNESS_ERRORS.HARNESS_STALE_WRITE.code)
150
+ throw error;
151
+ if (code === 'EACCES') {
152
+ throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
153
+ }
154
+ // Any other stat failure: fall through and let writeFile surface it.
155
+ }
156
+ }
157
+ try {
158
+ await fs.writeFile(absolutePath, content, 'utf-8');
159
+ }
160
+ catch (error) {
161
+ const code = error.code;
162
+ if (code === 'EACCES') {
163
+ throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
164
+ }
165
+ throwMapped(HARNESS_ERRORS.HARNESS_WRITE_ERROR.code, 'failed to write file');
166
+ }
167
+ const stat = await fs.stat(absolutePath);
168
+ // Share the harness self-write suppression map so the `.bmad-core/`
169
+ // watcher (Task A.4) swallows our own-write echo on the same path.
170
+ fileWatcherService.noteLocalWrite(absolutePath);
171
+ return { mtime: stat.mtime.toISOString() };
172
+ }
173
+ }
174
+ export const bmadCoreConfigService = new BmadCoreConfigService();
175
+ //# sourceMappingURL=bmadCoreConfigService.js.map