hammoc 1.5.0 → 1.7.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 (372) hide show
  1. package/README.md +12 -4
  2. package/package.json +2 -2
  3. package/packages/client/dist/assets/{agentExampleHighlight-BgwTm15v.js → agentExampleHighlight-7Olvqdpf.js} +1 -1
  4. package/packages/client/dist/assets/{commandTokenHighlight-BljHwnrK.js → commandTokenHighlight-DtKwh4lx.js} +1 -1
  5. package/packages/client/dist/assets/index-B09doO8H.js +139 -0
  6. package/packages/client/dist/assets/index-Bee52CKG.js +1569 -0
  7. package/packages/client/dist/assets/index-CVy582lU.css +32 -0
  8. package/packages/client/dist/assets/{index-D3LxqW3f.js → index-DLHBUw8c.js} +1 -1
  9. package/packages/client/dist/assets/{snippetTokenHighlight-DWsaQXX0.js → snippetTokenHighlight-C8O688f4.js} +1 -1
  10. package/packages/client/dist/index.html +2 -2
  11. package/packages/client/dist/sw.js +2 -2
  12. package/packages/server/dist/_dbg_agent_rows.d.ts +2 -0
  13. package/packages/server/dist/_dbg_agent_rows.d.ts.map +1 -0
  14. package/packages/server/dist/_dbg_agent_rows.js +60 -0
  15. package/packages/server/dist/_dbg_agent_rows.js.map +1 -0
  16. package/packages/server/dist/_dbg_flicker.d.ts +2 -0
  17. package/packages/server/dist/_dbg_flicker.d.ts.map +1 -0
  18. package/packages/server/dist/_dbg_flicker.js +38 -0
  19. package/packages/server/dist/_dbg_flicker.js.map +1 -0
  20. package/packages/server/dist/_harness_cli.d.ts +2 -0
  21. package/packages/server/dist/_harness_cli.d.ts.map +1 -0
  22. package/packages/server/dist/_harness_cli.js +81 -0
  23. package/packages/server/dist/_harness_cli.js.map +1 -0
  24. package/packages/server/dist/_harness_provcard.d.ts +2 -0
  25. package/packages/server/dist/_harness_provcard.d.ts.map +1 -0
  26. package/packages/server/dist/_harness_provcard.js +67 -0
  27. package/packages/server/dist/_harness_provcard.js.map +1 -0
  28. package/packages/server/dist/_replay_dump.d.ts +2 -0
  29. package/packages/server/dist/_replay_dump.d.ts.map +1 -0
  30. package/packages/server/dist/_replay_dump.js +62 -0
  31. package/packages/server/dist/_replay_dump.js.map +1 -0
  32. package/packages/server/dist/app.d.ts.map +1 -1
  33. package/packages/server/dist/app.js +6 -0
  34. package/packages/server/dist/app.js.map +1 -1
  35. package/packages/server/dist/config/index.d.ts.map +1 -1
  36. package/packages/server/dist/config/index.js.map +1 -1
  37. package/packages/server/dist/controllers/bmadCoreConfigController.d.ts +41 -0
  38. package/packages/server/dist/controllers/bmadCoreConfigController.d.ts.map +1 -0
  39. package/packages/server/dist/controllers/bmadCoreConfigController.js +172 -0
  40. package/packages/server/dist/controllers/bmadCoreConfigController.js.map +1 -0
  41. package/packages/server/dist/controllers/contextBuilderController.d.ts +43 -0
  42. package/packages/server/dist/controllers/contextBuilderController.d.ts.map +1 -0
  43. package/packages/server/dist/controllers/contextBuilderController.js +159 -0
  44. package/packages/server/dist/controllers/contextBuilderController.js.map +1 -0
  45. package/packages/server/dist/controllers/harnessAgentController.d.ts +7 -0
  46. package/packages/server/dist/controllers/harnessAgentController.d.ts.map +1 -1
  47. package/packages/server/dist/controllers/harnessAgentController.js +33 -0
  48. package/packages/server/dist/controllers/harnessAgentController.js.map +1 -1
  49. package/packages/server/dist/controllers/harnessBundleController.d.ts +37 -0
  50. package/packages/server/dist/controllers/harnessBundleController.d.ts.map +1 -0
  51. package/packages/server/dist/controllers/harnessBundleController.js +312 -0
  52. package/packages/server/dist/controllers/harnessBundleController.js.map +1 -0
  53. package/packages/server/dist/controllers/harnessCommandController.d.ts +7 -0
  54. package/packages/server/dist/controllers/harnessCommandController.d.ts.map +1 -1
  55. package/packages/server/dist/controllers/harnessCommandController.js +33 -0
  56. package/packages/server/dist/controllers/harnessCommandController.js.map +1 -1
  57. package/packages/server/dist/controllers/harnessHookController.d.ts.map +1 -1
  58. package/packages/server/dist/controllers/harnessHookController.js +44 -1
  59. package/packages/server/dist/controllers/harnessHookController.js.map +1 -1
  60. package/packages/server/dist/controllers/harnessMcpController.d.ts.map +1 -1
  61. package/packages/server/dist/controllers/harnessMcpController.js +62 -1
  62. package/packages/server/dist/controllers/harnessMcpController.js.map +1 -1
  63. package/packages/server/dist/controllers/harnessShareScopeController.d.ts +9 -0
  64. package/packages/server/dist/controllers/harnessShareScopeController.d.ts.map +1 -1
  65. package/packages/server/dist/controllers/harnessShareScopeController.js +48 -1
  66. package/packages/server/dist/controllers/harnessShareScopeController.js.map +1 -1
  67. package/packages/server/dist/controllers/marketplaceController.d.ts +19 -0
  68. package/packages/server/dist/controllers/marketplaceController.d.ts.map +1 -0
  69. package/packages/server/dist/controllers/marketplaceController.js +74 -0
  70. package/packages/server/dist/controllers/marketplaceController.js.map +1 -0
  71. package/packages/server/dist/controllers/observabilityController.d.ts +32 -0
  72. package/packages/server/dist/controllers/observabilityController.d.ts.map +1 -0
  73. package/packages/server/dist/controllers/observabilityController.js +148 -0
  74. package/packages/server/dist/controllers/observabilityController.js.map +1 -0
  75. package/packages/server/dist/controllers/projectController.d.ts.map +1 -1
  76. package/packages/server/dist/controllers/projectController.js +7 -1
  77. package/packages/server/dist/controllers/projectController.js.map +1 -1
  78. package/packages/server/dist/controllers/sessionController.d.ts.map +1 -1
  79. package/packages/server/dist/controllers/sessionController.js +16 -4
  80. package/packages/server/dist/controllers/sessionController.js.map +1 -1
  81. package/packages/server/dist/controllers/systemBrowseController.d.ts +33 -0
  82. package/packages/server/dist/controllers/systemBrowseController.d.ts.map +1 -0
  83. package/packages/server/dist/controllers/systemBrowseController.js +105 -0
  84. package/packages/server/dist/controllers/systemBrowseController.js.map +1 -0
  85. package/packages/server/dist/handlers/streamCallbacks.d.ts +10 -0
  86. package/packages/server/dist/handlers/streamCallbacks.d.ts.map +1 -1
  87. package/packages/server/dist/handlers/streamCallbacks.js +25 -4
  88. package/packages/server/dist/handlers/streamCallbacks.js.map +1 -1
  89. package/packages/server/dist/handlers/websocket.d.ts +43 -3
  90. package/packages/server/dist/handlers/websocket.d.ts.map +1 -1
  91. package/packages/server/dist/handlers/websocket.js +385 -93
  92. package/packages/server/dist/handlers/websocket.js.map +1 -1
  93. package/packages/server/dist/index.js +2 -0
  94. package/packages/server/dist/index.js.map +1 -1
  95. package/packages/server/dist/locales/en/server.json +17 -0
  96. package/packages/server/dist/locales/es/server.json +17 -0
  97. package/packages/server/dist/locales/ja/server.json +17 -0
  98. package/packages/server/dist/locales/ko/server.json +17 -0
  99. package/packages/server/dist/locales/pt/server.json +17 -0
  100. package/packages/server/dist/locales/zh-CN/server.json +17 -0
  101. package/packages/server/dist/routes/harness.d.ts.map +1 -1
  102. package/packages/server/dist/routes/harness.js +58 -0
  103. package/packages/server/dist/routes/harness.js.map +1 -1
  104. package/packages/server/dist/routes/preferences.d.ts.map +1 -1
  105. package/packages/server/dist/routes/preferences.js +12 -2
  106. package/packages/server/dist/routes/preferences.js.map +1 -1
  107. package/packages/server/dist/routes/systemBrowse.d.ts +17 -0
  108. package/packages/server/dist/routes/systemBrowse.d.ts.map +1 -0
  109. package/packages/server/dist/routes/systemBrowse.js +22 -0
  110. package/packages/server/dist/routes/systemBrowse.js.map +1 -0
  111. package/packages/server/dist/services/bmadCoreConfigService.d.ts +86 -0
  112. package/packages/server/dist/services/bmadCoreConfigService.d.ts.map +1 -0
  113. package/packages/server/dist/services/bmadCoreConfigService.js +175 -0
  114. package/packages/server/dist/services/bmadCoreConfigService.js.map +1 -0
  115. package/packages/server/dist/services/bmadStatusService.d.ts +9 -0
  116. package/packages/server/dist/services/bmadStatusService.d.ts.map +1 -1
  117. package/packages/server/dist/services/bmadStatusService.js +77 -13
  118. package/packages/server/dist/services/bmadStatusService.js.map +1 -1
  119. package/packages/server/dist/services/chatEngine.d.ts +81 -0
  120. package/packages/server/dist/services/chatEngine.d.ts.map +1 -0
  121. package/packages/server/dist/services/chatEngine.js +2 -0
  122. package/packages/server/dist/services/chatEngine.js.map +1 -0
  123. package/packages/server/dist/services/chatEngineFactory.d.ts +15 -0
  124. package/packages/server/dist/services/chatEngineFactory.d.ts.map +1 -0
  125. package/packages/server/dist/services/chatEngineFactory.js +28 -0
  126. package/packages/server/dist/services/chatEngineFactory.js.map +1 -0
  127. package/packages/server/dist/services/chatService.d.ts +34 -26
  128. package/packages/server/dist/services/chatService.d.ts.map +1 -1
  129. package/packages/server/dist/services/chatService.js +44 -104
  130. package/packages/server/dist/services/chatService.js.map +1 -1
  131. package/packages/server/dist/services/cliChatEngine.d.ts +198 -0
  132. package/packages/server/dist/services/cliChatEngine.d.ts.map +1 -0
  133. package/packages/server/dist/services/cliChatEngine.js +2977 -0
  134. package/packages/server/dist/services/cliChatEngine.js.map +1 -0
  135. package/packages/server/dist/services/cliGridCards.d.ts +87 -0
  136. package/packages/server/dist/services/cliGridCards.d.ts.map +1 -0
  137. package/packages/server/dist/services/cliGridCards.js +298 -0
  138. package/packages/server/dist/services/cliGridCards.js.map +1 -0
  139. package/packages/server/dist/services/cliGridRegion.d.ts +44 -0
  140. package/packages/server/dist/services/cliGridRegion.d.ts.map +1 -0
  141. package/packages/server/dist/services/cliGridRegion.js +94 -0
  142. package/packages/server/dist/services/cliGridRegion.js.map +1 -0
  143. package/packages/server/dist/services/cliModalDetect.d.ts +299 -0
  144. package/packages/server/dist/services/cliModalDetect.d.ts.map +1 -0
  145. package/packages/server/dist/services/cliModalDetect.js +583 -0
  146. package/packages/server/dist/services/cliModalDetect.js.map +1 -0
  147. package/packages/server/dist/services/cliScreenCache.d.ts +33 -0
  148. package/packages/server/dist/services/cliScreenCache.d.ts.map +1 -0
  149. package/packages/server/dist/services/cliScreenCache.js +48 -0
  150. package/packages/server/dist/services/cliScreenCache.js.map +1 -0
  151. package/packages/server/dist/services/cliScreenModel.d.ts +141 -0
  152. package/packages/server/dist/services/cliScreenModel.d.ts.map +1 -0
  153. package/packages/server/dist/services/cliScreenModel.js +196 -0
  154. package/packages/server/dist/services/cliScreenModel.js.map +1 -0
  155. package/packages/server/dist/services/cliScreenStallWatchdog.d.ts +41 -0
  156. package/packages/server/dist/services/cliScreenStallWatchdog.d.ts.map +1 -0
  157. package/packages/server/dist/services/cliScreenStallWatchdog.js +45 -0
  158. package/packages/server/dist/services/cliScreenStallWatchdog.js.map +1 -0
  159. package/packages/server/dist/services/cliSessionPool.d.ts +97 -0
  160. package/packages/server/dist/services/cliSessionPool.d.ts.map +1 -0
  161. package/packages/server/dist/services/cliSessionPool.js +278 -0
  162. package/packages/server/dist/services/cliSessionPool.js.map +1 -0
  163. package/packages/server/dist/services/cliSpinnerProgress.d.ts +41 -0
  164. package/packages/server/dist/services/cliSpinnerProgress.d.ts.map +1 -0
  165. package/packages/server/dist/services/cliSpinnerProgress.js +131 -0
  166. package/packages/server/dist/services/cliSpinnerProgress.js.map +1 -0
  167. package/packages/server/dist/services/contextBuilderScriptTemplate.d.ts +24 -0
  168. package/packages/server/dist/services/contextBuilderScriptTemplate.d.ts.map +1 -0
  169. package/packages/server/dist/services/contextBuilderScriptTemplate.js +181 -0
  170. package/packages/server/dist/services/contextBuilderScriptTemplate.js.map +1 -0
  171. package/packages/server/dist/services/contextBuilderService.d.ts +68 -0
  172. package/packages/server/dist/services/contextBuilderService.d.ts.map +1 -0
  173. package/packages/server/dist/services/contextBuilderService.js +345 -0
  174. package/packages/server/dist/services/contextBuilderService.js.map +1 -0
  175. package/packages/server/dist/services/fileRewind.d.ts +46 -0
  176. package/packages/server/dist/services/fileRewind.d.ts.map +1 -0
  177. package/packages/server/dist/services/fileRewind.js +77 -0
  178. package/packages/server/dist/services/fileRewind.js.map +1 -0
  179. package/packages/server/dist/services/fileWatcherService.d.ts.map +1 -1
  180. package/packages/server/dist/services/fileWatcherService.js +40 -0
  181. package/packages/server/dist/services/fileWatcherService.js.map +1 -1
  182. package/packages/server/dist/services/harnessAgentService.d.ts +18 -0
  183. package/packages/server/dist/services/harnessAgentService.d.ts.map +1 -1
  184. package/packages/server/dist/services/harnessAgentService.js +55 -0
  185. package/packages/server/dist/services/harnessAgentService.js.map +1 -1
  186. package/packages/server/dist/services/harnessBundleService.d.ts +145 -0
  187. package/packages/server/dist/services/harnessBundleService.d.ts.map +1 -0
  188. package/packages/server/dist/services/harnessBundleService.js +1318 -0
  189. package/packages/server/dist/services/harnessBundleService.js.map +1 -0
  190. package/packages/server/dist/services/harnessCommandService.d.ts +21 -0
  191. package/packages/server/dist/services/harnessCommandService.d.ts.map +1 -1
  192. package/packages/server/dist/services/harnessCommandService.js +64 -0
  193. package/packages/server/dist/services/harnessCommandService.js.map +1 -1
  194. package/packages/server/dist/services/harnessHookService.d.ts +27 -0
  195. package/packages/server/dist/services/harnessHookService.d.ts.map +1 -1
  196. package/packages/server/dist/services/harnessHookService.js +52 -0
  197. package/packages/server/dist/services/harnessHookService.js.map +1 -1
  198. package/packages/server/dist/services/harnessMcpService.d.ts +24 -1
  199. package/packages/server/dist/services/harnessMcpService.d.ts.map +1 -1
  200. package/packages/server/dist/services/harnessMcpService.js +70 -0
  201. package/packages/server/dist/services/harnessMcpService.js.map +1 -1
  202. package/packages/server/dist/services/harnessShareScopeService.d.ts +19 -0
  203. package/packages/server/dist/services/harnessShareScopeService.d.ts.map +1 -1
  204. package/packages/server/dist/services/harnessShareScopeService.js +65 -0
  205. package/packages/server/dist/services/harnessShareScopeService.js.map +1 -1
  206. package/packages/server/dist/services/historyParser.d.ts +11 -0
  207. package/packages/server/dist/services/historyParser.d.ts.map +1 -1
  208. package/packages/server/dist/services/historyParser.js +10 -8
  209. package/packages/server/dist/services/historyParser.js.map +1 -1
  210. package/packages/server/dist/services/imageStorageService.d.ts +12 -0
  211. package/packages/server/dist/services/imageStorageService.d.ts.map +1 -1
  212. package/packages/server/dist/services/imageStorageService.js +22 -0
  213. package/packages/server/dist/services/imageStorageService.js.map +1 -1
  214. package/packages/server/dist/services/issueService.d.ts.map +1 -1
  215. package/packages/server/dist/services/issueService.js +1 -0
  216. package/packages/server/dist/services/issueService.js.map +1 -1
  217. package/packages/server/dist/services/marketplaceService.d.ts +50 -0
  218. package/packages/server/dist/services/marketplaceService.d.ts.map +1 -0
  219. package/packages/server/dist/services/marketplaceService.js +326 -0
  220. package/packages/server/dist/services/marketplaceService.js.map +1 -0
  221. package/packages/server/dist/services/observabilityService.d.ts +87 -0
  222. package/packages/server/dist/services/observabilityService.d.ts.map +1 -0
  223. package/packages/server/dist/services/observabilityService.js +0 -0
  224. package/packages/server/dist/services/observabilityService.js.map +1 -0
  225. package/packages/server/dist/services/projectService.d.ts +13 -1
  226. package/packages/server/dist/services/projectService.d.ts.map +1 -1
  227. package/packages/server/dist/services/projectService.js +32 -0
  228. package/packages/server/dist/services/projectService.js.map +1 -1
  229. package/packages/server/dist/services/queueService.d.ts.map +1 -1
  230. package/packages/server/dist/services/queueService.js +12 -3
  231. package/packages/server/dist/services/queueService.js.map +1 -1
  232. package/packages/server/dist/services/rateLimitProbeService.d.ts +15 -0
  233. package/packages/server/dist/services/rateLimitProbeService.d.ts.map +1 -1
  234. package/packages/server/dist/services/rateLimitProbeService.js +48 -19
  235. package/packages/server/dist/services/rateLimitProbeService.js.map +1 -1
  236. package/packages/server/dist/services/sessionService.d.ts +16 -0
  237. package/packages/server/dist/services/sessionService.d.ts.map +1 -1
  238. package/packages/server/dist/services/sessionService.js +125 -0
  239. package/packages/server/dist/services/sessionService.js.map +1 -1
  240. package/packages/server/dist/services/streamHandler.d.ts +8 -1
  241. package/packages/server/dist/services/streamHandler.d.ts.map +1 -1
  242. package/packages/server/dist/services/streamHandler.js +12 -5
  243. package/packages/server/dist/services/streamHandler.js.map +1 -1
  244. package/packages/server/dist/services/systemBrowseService.d.ts +91 -0
  245. package/packages/server/dist/services/systemBrowseService.d.ts.map +1 -0
  246. package/packages/server/dist/services/systemBrowseService.js +372 -0
  247. package/packages/server/dist/services/systemBrowseService.js.map +1 -0
  248. package/packages/server/dist/services/tokenCountService.d.ts +71 -0
  249. package/packages/server/dist/services/tokenCountService.d.ts.map +1 -0
  250. package/packages/server/dist/services/tokenCountService.js +313 -0
  251. package/packages/server/dist/services/tokenCountService.js.map +1 -0
  252. package/packages/server/dist/services/workspaceContext.d.ts +24 -0
  253. package/packages/server/dist/services/workspaceContext.d.ts.map +1 -0
  254. package/packages/server/dist/services/workspaceContext.js +109 -0
  255. package/packages/server/dist/services/workspaceContext.js.map +1 -0
  256. package/packages/server/dist/snippets/apply-qa-fixes +7 -5
  257. package/packages/server/dist/snippets/qa-review +7 -1
  258. package/packages/server/dist/utils/assertSafeBundlePath.d.ts +29 -0
  259. package/packages/server/dist/utils/assertSafeBundlePath.d.ts.map +1 -0
  260. package/packages/server/dist/utils/assertSafeBundlePath.js +53 -0
  261. package/packages/server/dist/utils/assertSafeBundlePath.js.map +1 -0
  262. package/packages/server/dist/utils/backgroundBlock.d.ts +29 -0
  263. package/packages/server/dist/utils/backgroundBlock.d.ts.map +1 -0
  264. package/packages/server/dist/utils/backgroundBlock.js +33 -0
  265. package/packages/server/dist/utils/backgroundBlock.js.map +1 -0
  266. package/packages/server/dist/utils/backgroundTaskTracker.d.ts +20 -0
  267. package/packages/server/dist/utils/backgroundTaskTracker.d.ts.map +1 -0
  268. package/packages/server/dist/utils/backgroundTaskTracker.js +40 -0
  269. package/packages/server/dist/utils/backgroundTaskTracker.js.map +1 -0
  270. package/packages/server/dist/utils/bundledBinaryModelSupport.d.ts +14 -0
  271. package/packages/server/dist/utils/bundledBinaryModelSupport.d.ts.map +1 -0
  272. package/packages/server/dist/utils/bundledBinaryModelSupport.js +112 -0
  273. package/packages/server/dist/utils/bundledBinaryModelSupport.js.map +1 -0
  274. package/packages/server/dist/utils/cliDebugLog.d.ts +38 -0
  275. package/packages/server/dist/utils/cliDebugLog.d.ts.map +1 -0
  276. package/packages/server/dist/utils/cliDebugLog.js +65 -0
  277. package/packages/server/dist/utils/cliDebugLog.js.map +1 -0
  278. package/packages/server/dist/utils/cliEngineUtils.d.ts +35 -0
  279. package/packages/server/dist/utils/cliEngineUtils.d.ts.map +1 -0
  280. package/packages/server/dist/utils/cliEngineUtils.js +38 -0
  281. package/packages/server/dist/utils/cliEngineUtils.js.map +1 -0
  282. package/packages/server/dist/utils/effortUtils.d.ts +2 -2
  283. package/packages/server/dist/utils/effortUtils.d.ts.map +1 -1
  284. package/packages/server/dist/utils/effortUtils.js +7 -5
  285. package/packages/server/dist/utils/effortUtils.js.map +1 -1
  286. package/packages/server/dist/utils/errors.d.ts +1 -0
  287. package/packages/server/dist/utils/errors.d.ts.map +1 -1
  288. package/packages/server/dist/utils/errors.js +17 -0
  289. package/packages/server/dist/utils/errors.js.map +1 -1
  290. package/packages/server/dist/utils/harnessBundleSchema.d.ts +14 -12
  291. package/packages/server/dist/utils/harnessBundleSchema.d.ts.map +1 -1
  292. package/packages/server/dist/utils/harnessBundleSchema.js +11 -1
  293. package/packages/server/dist/utils/harnessBundleSchema.js.map +1 -1
  294. package/packages/server/dist/utils/harnessPaths.d.ts +40 -0
  295. package/packages/server/dist/utils/harnessPaths.d.ts.map +1 -1
  296. package/packages/server/dist/utils/harnessPaths.js +123 -0
  297. package/packages/server/dist/utils/harnessPaths.js.map +1 -1
  298. package/packages/server/dist/utils/trailingThrottle.d.ts +21 -0
  299. package/packages/server/dist/utils/trailingThrottle.d.ts.map +1 -0
  300. package/packages/server/dist/utils/trailingThrottle.js +36 -0
  301. package/packages/server/dist/utils/trailingThrottle.js.map +1 -0
  302. package/packages/server/package.json +61 -58
  303. package/packages/server/resources/internals/INDEX.md +3 -1
  304. package/packages/server/resources/internals/bmad-qa-fix-marker.md +32 -0
  305. package/packages/server/resources/internals/harness-files.md +22 -0
  306. package/packages/server/resources/internals/image-storage.md +9 -0
  307. package/packages/server/resources/internals/observability-storage.md +23 -0
  308. package/packages/server/resources/manual/02-chat.md +23 -4
  309. package/packages/server/resources/manual/03-sessions.md +1 -0
  310. package/packages/server/resources/manual/05-projects.md +15 -2
  311. package/packages/server/resources/manual/10-project-board.md +4 -3
  312. package/packages/server/resources/manual/11-bmad-method-integration.md +12 -8
  313. package/packages/server/resources/manual/12-harness-workbench.md +82 -1
  314. package/packages/server/resources/manual/13-settings.md +61 -9
  315. package/packages/shared/dist/index.d.ts +7 -0
  316. package/packages/shared/dist/index.d.ts.map +1 -1
  317. package/packages/shared/dist/index.js +14 -0
  318. package/packages/shared/dist/index.js.map +1 -1
  319. package/packages/shared/dist/types/bmadCoreConfig.d.ts +71 -0
  320. package/packages/shared/dist/types/bmadCoreConfig.d.ts.map +1 -0
  321. package/packages/shared/dist/types/bmadCoreConfig.js +30 -0
  322. package/packages/shared/dist/types/bmadCoreConfig.js.map +1 -0
  323. package/packages/shared/dist/types/bmadStatus.d.ts +26 -0
  324. package/packages/shared/dist/types/bmadStatus.d.ts.map +1 -1
  325. package/packages/shared/dist/types/bmadStatus.js.map +1 -1
  326. package/packages/shared/dist/types/board.d.ts +6 -0
  327. package/packages/shared/dist/types/board.d.ts.map +1 -1
  328. package/packages/shared/dist/types/contextBuilder.d.ts +102 -0
  329. package/packages/shared/dist/types/contextBuilder.d.ts.map +1 -0
  330. package/packages/shared/dist/types/contextBuilder.js +55 -0
  331. package/packages/shared/dist/types/contextBuilder.js.map +1 -0
  332. package/packages/shared/dist/types/harnessBundle.d.ts +35 -0
  333. package/packages/shared/dist/types/harnessBundle.d.ts.map +1 -1
  334. package/packages/shared/dist/types/marketplace.d.ts +83 -0
  335. package/packages/shared/dist/types/marketplace.d.ts.map +1 -0
  336. package/packages/shared/dist/types/marketplace.js +18 -0
  337. package/packages/shared/dist/types/marketplace.js.map +1 -0
  338. package/packages/shared/dist/types/observability.d.ts +148 -0
  339. package/packages/shared/dist/types/observability.d.ts.map +1 -0
  340. package/packages/shared/dist/types/observability.js +24 -0
  341. package/packages/shared/dist/types/observability.js.map +1 -0
  342. package/packages/shared/dist/types/preferences.d.ts +16 -2
  343. package/packages/shared/dist/types/preferences.d.ts.map +1 -1
  344. package/packages/shared/dist/types/preferences.js +1 -0
  345. package/packages/shared/dist/types/preferences.js.map +1 -1
  346. package/packages/shared/dist/types/project.d.ts +7 -1
  347. package/packages/shared/dist/types/project.d.ts.map +1 -1
  348. package/packages/shared/dist/types/project.js.map +1 -1
  349. package/packages/shared/dist/types/sdk.d.ts +124 -12
  350. package/packages/shared/dist/types/sdk.d.ts.map +1 -1
  351. package/packages/shared/dist/types/sdk.js +64 -19
  352. package/packages/shared/dist/types/sdk.js.map +1 -1
  353. package/packages/shared/dist/types/streaming.d.ts +2 -2
  354. package/packages/shared/dist/types/streaming.d.ts.map +1 -1
  355. package/packages/shared/dist/types/streaming.js.map +1 -1
  356. package/packages/shared/dist/types/systemBrowse.d.ts +120 -0
  357. package/packages/shared/dist/types/systemBrowse.d.ts.map +1 -0
  358. package/packages/shared/dist/types/systemBrowse.js +57 -0
  359. package/packages/shared/dist/types/systemBrowse.js.map +1 -0
  360. package/packages/shared/dist/types/websocket.d.ts +38 -0
  361. package/packages/shared/dist/types/websocket.d.ts.map +1 -1
  362. package/packages/shared/dist/utils/interruptFiller.d.ts +30 -0
  363. package/packages/shared/dist/utils/interruptFiller.d.ts.map +1 -0
  364. package/packages/shared/dist/utils/interruptFiller.js +38 -0
  365. package/packages/shared/dist/utils/interruptFiller.js.map +1 -0
  366. package/packages/shared/dist/utils/toolResultContent.d.ts +22 -0
  367. package/packages/shared/dist/utils/toolResultContent.d.ts.map +1 -0
  368. package/packages/shared/dist/utils/toolResultContent.js +29 -0
  369. package/packages/shared/dist/utils/toolResultContent.js.map +1 -0
  370. package/scripts/run-integration-test.mjs +362 -362
  371. package/packages/client/dist/assets/index-CjyjnXB8.css +0 -32
  372. package/packages/client/dist/assets/index-NqJdhlek.js +0 -1498
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Story 31.3 (Task A.3 / A.5): token attribution + exact count_tokens proxy.
3
+ *
4
+ * Two responsibilities, sharing one text-resolution path so the "exact count"
5
+ * input and the "approximation" input are always the same bytes (N-1):
6
+ *
7
+ * 1. listTokenAttribution(projectSlug) — enumerate the measured harness
8
+ * elements (project/global CLAUDE.md · each skill's SKILL.md · the
9
+ * Hammoc-managed context-builder injection) and report UTF-8 byte size +
10
+ * `approxTokens = ceil(bytes/4)` + a sha256 content hash (AC-B1 / AC-B2).
11
+ *
12
+ * 2. exactCount(projectSlug, req) — proxy the official `count_tokens` via the
13
+ * already-installed `@anthropic-ai/sdk` `messages.countTokens` (spike #2,
14
+ * §15 — no new dependency), keyed by a server-recomputed content hash
15
+ * (N-B: the request hash is only an optimistic hint). Failures are
16
+ * non-blocking (`failed: true`) so the client keeps the approximation
17
+ * (AC-B3.c).
18
+ *
19
+ * Enumeration REUSES existing controllers/services (claudeMdService,
20
+ * harnessSkillService, contextBuilderService) — no new file scanner (S-2). The
21
+ * context-builder injection is estimated from the Story 31.2 manifest WITHOUT
22
+ * executing the hook (dynamic variable / command values are placeholders).
23
+ *
24
+ * Per spike #1 (§14) the SERVER approximation tier is byte `size/4` only — the
25
+ * `@anthropic-ai/tokenizer` tier was NOT adopted (Task A.4 skipped).
26
+ */
27
+ import fs from 'node:fs/promises';
28
+ import { readFileSync } from 'node:fs';
29
+ import path from 'node:path';
30
+ import os from 'node:os';
31
+ import { createHash } from 'node:crypto';
32
+ import Anthropic from '@anthropic-ai/sdk';
33
+ import { createLogger } from '../utils/logger.js';
34
+ import { claudeMdService } from './claudeMdService.js';
35
+ import { harnessSkillService } from './harnessSkillService.js';
36
+ import { contextBuilderService } from './contextBuilderService.js';
37
+ import { projectService } from './projectService.js';
38
+ const log = createLogger('tokenCountService');
39
+ /**
40
+ * Model passed to count_tokens. The count is tokenizer-family stable across
41
+ * Claude 4.x, so any current model works; overridable via env in case the
42
+ * default is later deprecated. spike #2 verified the call live.
43
+ */
44
+ const COUNT_TOKENS_MODEL = process.env.OBSERVABILITY_COUNT_TOKENS_MODEL || 'claude-sonnet-4-6';
45
+ function sha256(text) {
46
+ return createHash('sha256').update(text, 'utf8').digest('hex');
47
+ }
48
+ function utf8Bytes(text) {
49
+ return Buffer.byteLength(text, 'utf8');
50
+ }
51
+ /** ceil(bytes / 4) — the size-based heuristic (§14). */
52
+ export function approxTokensFromBytes(bytes) {
53
+ return Math.ceil(Math.max(0, bytes) / 4);
54
+ }
55
+ function samePath(a, b) {
56
+ const na = path.normalize(a);
57
+ const nb = path.normalize(b);
58
+ return process.platform === 'win32' ? na.toLowerCase() === nb.toLowerCase() : na === nb;
59
+ }
60
+ /**
61
+ * Construct an Anthropic client for count_tokens (spike #2). Priority:
62
+ * `ANTHROPIC_API_KEY` → the Claude Code OAuth access token from
63
+ * `~/.claude/.credentials.json` (verified live). Returns null when neither is
64
+ * available — the caller degrades gracefully.
65
+ */
66
+ function getAnthropicClient() {
67
+ if (process.env.ANTHROPIC_API_KEY)
68
+ return new Anthropic();
69
+ try {
70
+ const credPath = path.join(os.homedir(), '.claude', '.credentials.json');
71
+ const cred = JSON.parse(readFileSync(credPath, 'utf8'));
72
+ const token = cred?.claudeAiOauth?.accessToken;
73
+ if (token)
74
+ return new Anthropic({ authToken: token });
75
+ }
76
+ catch {
77
+ // no credentials — fall through.
78
+ }
79
+ return null;
80
+ }
81
+ class TokenCountService {
82
+ /** sha256(text) → token count. In-memory; persisted best-effort to disk. */
83
+ cache = new Map();
84
+ cacheLoaded = false;
85
+ cacheFilePath() {
86
+ return path.join(os.homedir(), '.hammoc', 'observability', 'token-count-cache.json');
87
+ }
88
+ async loadCache() {
89
+ if (this.cacheLoaded)
90
+ return;
91
+ this.cacheLoaded = true;
92
+ try {
93
+ const text = await fs.readFile(this.cacheFilePath(), 'utf8');
94
+ const obj = JSON.parse(text);
95
+ for (const [k, v] of Object.entries(obj)) {
96
+ if (typeof v === 'number')
97
+ this.cache.set(k, v);
98
+ }
99
+ }
100
+ catch {
101
+ // missing/corrupt — start empty.
102
+ }
103
+ }
104
+ async persistCache() {
105
+ try {
106
+ const file = this.cacheFilePath();
107
+ await fs.mkdir(path.dirname(file), { recursive: true });
108
+ await fs.writeFile(file, JSON.stringify(Object.fromEntries(this.cache)), 'utf8');
109
+ }
110
+ catch (err) {
111
+ log.warn(`token cache persist failed: ${err.message}`);
112
+ }
113
+ }
114
+ /**
115
+ * Enumerate measured harness elements (AC-B1.a). Missing CLAUDE.md files and a
116
+ * disabled/empty context builder are omitted (they contribute no tokens).
117
+ */
118
+ async listTokenAttribution(projectSlug) {
119
+ const items = [];
120
+ // project / global CLAUDE.md
121
+ const projectMd = await this.readClaudeMd({ scope: 'project', projectSlug });
122
+ if (projectMd)
123
+ items.push(this.makeItem('claudeMd-project', 'CLAUDE.md (project)', projectMd.text, projectMd.path));
124
+ const globalMd = await this.readClaudeMd({ scope: 'user' });
125
+ if (globalMd)
126
+ items.push(this.makeItem('claudeMd-global', 'CLAUDE.md (global)', globalMd.text, globalMd.path));
127
+ // each skill's SKILL.md (active source only)
128
+ try {
129
+ const { cards } = await harnessSkillService.listCards(projectSlug);
130
+ for (const card of cards) {
131
+ const root = card.sources[0]?.absoluteRoot;
132
+ if (!root)
133
+ continue;
134
+ const skillMd = path.join(root, 'SKILL.md');
135
+ try {
136
+ const text = await fs.readFile(skillMd, 'utf8');
137
+ items.push(this.makeItem('skill', `skill: ${card.name}`, text, skillMd));
138
+ }
139
+ catch {
140
+ // SKILL.md unreadable — skip this card.
141
+ }
142
+ }
143
+ }
144
+ catch (err) {
145
+ log.warn(`skill enumeration failed: ${err.message}`);
146
+ }
147
+ // Hammoc-managed context builder injection (manifest-assembled, no execution)
148
+ const cbText = await this.assembleContextBuilderText(projectSlug);
149
+ if (cbText)
150
+ items.push(this.makeItem('contextBuilder', 'Context builder injection', cbText));
151
+ return items;
152
+ }
153
+ /**
154
+ * Exact count for one element (AC-B3). The text is re-resolved server-side and
155
+ * its sha256 is the AUTHORITATIVE cache key (N-B) — the request `contentHash`
156
+ * is only an optimistic hint. count_tokens failures return `failed: true`.
157
+ */
158
+ async exactCount(projectSlug, req) {
159
+ const text = await this.resolveElementText(projectSlug, req.kind, req.path);
160
+ if (text == null)
161
+ return { tokens: 0, cached: false, failed: true };
162
+ const key = sha256(text);
163
+ await this.loadCache();
164
+ const hit = this.cache.get(key);
165
+ if (hit !== undefined)
166
+ return { tokens: hit, cached: true };
167
+ const tokens = await this.callCountTokens(text);
168
+ if (tokens == null)
169
+ return { tokens: 0, cached: false, failed: true };
170
+ this.cache.set(key, tokens);
171
+ void this.persistCache();
172
+ return { tokens, cached: false };
173
+ }
174
+ // -------------------------------------------------------------------------
175
+ // internals
176
+ // -------------------------------------------------------------------------
177
+ makeItem(kind, label, text, filePath) {
178
+ const bytes = utf8Bytes(text);
179
+ return {
180
+ kind,
181
+ label,
182
+ ...(filePath ? { path: filePath } : {}),
183
+ bytes,
184
+ approxTokens: approxTokensFromBytes(bytes),
185
+ contentHash: sha256(text),
186
+ };
187
+ }
188
+ /** Resolve the text used for BOTH attribution and exact-count (N-1). */
189
+ async resolveElementText(projectSlug, kind, elementPath) {
190
+ switch (kind) {
191
+ case 'claudeMd-project':
192
+ return (await this.readClaudeMd({ scope: 'project', projectSlug }))?.text ?? null;
193
+ case 'claudeMd-global':
194
+ return (await this.readClaudeMd({ scope: 'user' }))?.text ?? null;
195
+ case 'contextBuilder': {
196
+ const t = await this.assembleContextBuilderText(projectSlug);
197
+ return t || null;
198
+ }
199
+ case 'skill':
200
+ return this.readSkillTextByPath(projectSlug, elementPath);
201
+ default:
202
+ return null;
203
+ }
204
+ }
205
+ async readClaudeMd(ref) {
206
+ try {
207
+ const res = await claudeMdService.read(ref);
208
+ return { text: res.content ?? '', path: res.absolutePath ?? 'CLAUDE.md' };
209
+ }
210
+ catch {
211
+ return null; // missing / not-a-file → omit.
212
+ }
213
+ }
214
+ /**
215
+ * Read a skill's SKILL.md, validating `elementPath` against the enumerated
216
+ * skills so an arbitrary client path can never be read (the path must be one
217
+ * the server itself vouched for in listTokenAttribution).
218
+ */
219
+ async readSkillTextByPath(projectSlug, elementPath) {
220
+ if (!elementPath)
221
+ return null;
222
+ try {
223
+ const { cards } = await harnessSkillService.listCards(projectSlug);
224
+ for (const card of cards) {
225
+ const root = card.sources[0]?.absoluteRoot;
226
+ if (!root)
227
+ continue;
228
+ const skillMd = path.join(root, 'SKILL.md');
229
+ if (samePath(skillMd, elementPath)) {
230
+ return await fs.readFile(skillMd, 'utf8');
231
+ }
232
+ }
233
+ }
234
+ catch {
235
+ // fall through.
236
+ }
237
+ return null;
238
+ }
239
+ /**
240
+ * Assemble the context-builder `additionalContext` text WITHOUT executing the
241
+ * hook (N-1). Reference files are read (their content dominates the size);
242
+ * dynamic variables / acknowledged commands contribute only their block
243
+ * headers with a `(dynamic)` placeholder. Mirrors the block format of
244
+ * `contextBuilderScriptTemplate` for the statically-knowable parts. Returns ''
245
+ * when the builder is disabled or empty.
246
+ */
247
+ async assembleContextBuilderText(projectSlug) {
248
+ let manifest;
249
+ try {
250
+ ({ manifest } = await contextBuilderService.readManifest(projectSlug));
251
+ }
252
+ catch {
253
+ return '';
254
+ }
255
+ if (!manifest.enabled)
256
+ return '';
257
+ let projectRoot;
258
+ try {
259
+ projectRoot = await projectService.resolveOriginalPath(projectSlug);
260
+ }
261
+ catch {
262
+ return '';
263
+ }
264
+ const blocks = [];
265
+ for (const rel of manifest.files) {
266
+ const abs = path.resolve(projectRoot, rel);
267
+ try {
268
+ const content = await fs.readFile(abs, 'utf8');
269
+ blocks.push(`## Reference file: ${rel}\n\n${content}`);
270
+ }
271
+ catch {
272
+ blocks.push(`## Reference file: ${rel}\n\n(파일을 찾을 수 없음: ${rel})`);
273
+ }
274
+ }
275
+ // Dynamic variable headers (values are computed at hook runtime — placeholder here).
276
+ if (manifest.variables.gitBranch)
277
+ blocks.push('## Current git branch\n\n(dynamic)');
278
+ if (manifest.variables.recentCommits) {
279
+ blocks.push(`## Recent ${manifest.recentCommitsCount ?? 5} commit(s)\n\n(dynamic)`);
280
+ }
281
+ if (manifest.variables.uncommittedCount)
282
+ blocks.push('## Uncommitted file count\n\n(dynamic)');
283
+ if (manifest.variables.today)
284
+ blocks.push('## Today\n\n(dynamic)');
285
+ if (manifest.variables.activeBmadStory)
286
+ blocks.push('## Active BMad story\n\n(dynamic)');
287
+ for (const cc of manifest.customCommands) {
288
+ if (cc.acknowledged)
289
+ blocks.push(`## Command: ${cc.command}\n\n(dynamic)`);
290
+ }
291
+ return blocks.join('\n\n');
292
+ }
293
+ async callCountTokens(text) {
294
+ const client = getAnthropicClient();
295
+ if (!client) {
296
+ log.warn('count_tokens unavailable — no ANTHROPIC_API_KEY and no OAuth credentials');
297
+ return null;
298
+ }
299
+ try {
300
+ const res = await client.messages.countTokens({
301
+ model: COUNT_TOKENS_MODEL,
302
+ messages: [{ role: 'user', content: text }],
303
+ });
304
+ return res.input_tokens;
305
+ }
306
+ catch (err) {
307
+ log.warn(`count_tokens failed: ${err.message}`);
308
+ return null;
309
+ }
310
+ }
311
+ }
312
+ export const tokenCountService = new TokenCountService();
313
+ //# sourceMappingURL=tokenCountService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenCountService.js","sourceRoot":"","sources":["../../src/services/tokenCountService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Default workspace context template with system variables.
3
+ * Variables like {gitBranch} are resolved at runtime via resolveTemplateVariables().
4
+ */
5
+ export declare const DEFAULT_WORKSPACE_TEMPLATE: string;
6
+ /** Available template variables and their descriptions */
7
+ export declare const TEMPLATE_VARIABLES: readonly [{
8
+ readonly name: "gitBranch";
9
+ readonly description: "Current git branch name";
10
+ }, {
11
+ readonly name: "gitMainBranch";
12
+ readonly description: "Main branch name (main or master)";
13
+ }, {
14
+ readonly name: "gitStatus";
15
+ readonly description: "git status --short output (truncated to 30 lines)";
16
+ }, {
17
+ readonly name: "homeDir";
18
+ readonly description: "Absolute path to the user home directory";
19
+ }];
20
+ /**
21
+ * Resolve template variables like {gitBranch} using the project CWD.
22
+ */
23
+ export declare function resolveTemplateVariables(template: string, cwd: string): string;
24
+ //# sourceMappingURL=workspaceContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceContext.d.ts","sourceRoot":"","sources":["../../src/services/workspaceContext.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,eAAO,MAAM,0BAA0B,QAqC3B,CAAC;AAEb,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;EAKrB,CAAC;AAEX;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CA2C9E"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Workspace Context — the Hammoc system-prompt augmentation shared by BOTH chat engines.
3
+ *
4
+ * SDK mode (`chatService`) appends `DEFAULT_WORKSPACE_TEMPLATE` to the `claude_code` system-prompt
5
+ * preset; CLI mode (`cliChatEngine`) reaches the SAME preset via the interactive `claude` binary and
6
+ * appends the identical resolved template through `--append-system-prompt`. This is the single source
7
+ * of truth for "what makes the agent Hammoc-aware" (identity, clickable-link convention, feature
8
+ * pointers, manual/internals locations).
9
+ *
10
+ * Extracted out of `chatService` on purpose: that module pulls in the Agent SDK, so anything that
11
+ * only needs the template (the CLI engine, the preferences/project routes that surface the default)
12
+ * would otherwise drag the SDK in transitively. This file is light — only `os` + `git` (execSync).
13
+ */
14
+ import os from 'os';
15
+ import { execSync } from 'child_process';
16
+ /**
17
+ * Default workspace context template with system variables.
18
+ * Variables like {gitBranch} are resolved at runtime via resolveTemplateVariables().
19
+ */
20
+ export const DEFAULT_WORKSPACE_TEMPLATE = [
21
+ '',
22
+ '# Hammoc Context',
23
+ '',
24
+ 'You are running inside Hammoc, a web-based IDE for AI-driven development workflows. Hammoc is built on Claude Code with first-class BMAD-METHOD V4 support, fully responsive (the user may instruct from a phone with very short messages), and delegates implementation work to you while the user reviews via the UI.',
25
+ '',
26
+ '## Code References in Text',
27
+ 'IMPORTANT: When referencing files or code locations, use markdown link syntax to make them clickable:',
28
+ '- For files: [filename.ts](src/filename.ts)',
29
+ '- For specific lines: [filename.ts:42](src/filename.ts#L42)',
30
+ '- For a range of lines: [filename.ts:42-51](src/filename.ts#L42-L51)',
31
+ '- For folders: [src/utils/](src/utils/)',
32
+ 'Unless explicitly asked for by the user, DO NOT USE backticks ` or HTML tags like code for file references - always use markdown [text](link) format.',
33
+ "The URL links should be relative paths from the root of the user's workspace.",
34
+ '',
35
+ '## Hammoc-Specific Features the User May Invoke',
36
+ 'When the user mentions any of these Hammoc concepts and you are unsure how the feature behaves, read the matching manual chapter (see Manual Reference below) before guessing:',
37
+ '- **Snippets** (`%name`) — reusable prompt templates with arguments. Files in <project-root>/.hammoc/snippets/ and {homeDir}/.hammoc/snippets/',
38
+ '- **Queue Runner** — batch script of prompts with `@`-prefixed commands (@new, @save, @load, @pause, @model, @delay, @pauseword, @loop/@end, @(/@), # comments)',
39
+ '- **Project Board** — Kanban with Bug/Improvement issues, severity Low/Medium/High/Critical, status workflow Open → Draft → Approved → In Progress → Blocked → Review → Done → Closed',
40
+ '- **BMAD-METHOD V4** — agile workflow with agents (SM, PM, Architect, Dev, QA, PO, etc.); .bmad-core directory holds the methodology files',
41
+ '- **Permission Modes** — Plan / Ask (default) / Auto / Bypass, per-project overridable',
42
+ '- **Sessions** — fork, rewind, summarize & continue, conversation branching',
43
+ '',
44
+ '## Manual Reference',
45
+ 'The full Hammoc user manual is sharded by chapter and synced to:',
46
+ ' {homeDir}/.hammoc/docs/manual/',
47
+ 'Always start by reading the index — it maps each chapter to its trigger keywords and tags chapters as [agent] (worth reading) or [user-setup] (skip):',
48
+ ' {homeDir}/.hammoc/docs/manual/INDEX.md',
49
+ 'Read only the chapters you actually need. Do not load the full manual at once. The Read tool does not expand `~` so always use the absolute path above.',
50
+ '',
51
+ '## Internals Reference',
52
+ 'Hammoc internal mechanisms that the user does not need to see but the agent may need to read or correlate (e.g. on-disk location of attached images) live separately at:',
53
+ ' {homeDir}/.hammoc/docs/internals/',
54
+ 'Index:',
55
+ ' {homeDir}/.hammoc/docs/internals/INDEX.md',
56
+ 'Read individual files only when the user request requires the underlying mechanism. Do not pre-load.',
57
+ ].join('\n');
58
+ /** Available template variables and their descriptions */
59
+ export const TEMPLATE_VARIABLES = [
60
+ { name: 'gitBranch', description: 'Current git branch name' },
61
+ { name: 'gitMainBranch', description: 'Main branch name (main or master)' },
62
+ { name: 'gitStatus', description: 'git status --short output (truncated to 30 lines)' },
63
+ { name: 'homeDir', description: 'Absolute path to the user home directory' },
64
+ ];
65
+ /**
66
+ * Resolve template variables like {gitBranch} using the project CWD.
67
+ */
68
+ export function resolveTemplateVariables(template, cwd) {
69
+ const vars = {};
70
+ // Home directory is OS-level and always resolvable, independent of git state.
71
+ // The agent needs the absolute path to read ~/.hammoc/docs/manual/INDEX.md
72
+ // via Read/Edit tools, which do not perform shell-style ~ expansion.
73
+ vars.homeDir = os.homedir();
74
+ try {
75
+ const stdio = ['pipe', 'pipe', 'pipe'];
76
+ const execOpts = { cwd, encoding: 'utf-8', timeout: 3000, stdio };
77
+ vars.gitBranch = execSync('git rev-parse --abbrev-ref HEAD', execOpts).toString().trim();
78
+ let mainBranch = 'main';
79
+ try {
80
+ execSync('git rev-parse --verify refs/heads/main', execOpts);
81
+ mainBranch = 'main';
82
+ }
83
+ catch {
84
+ try {
85
+ execSync('git rev-parse --verify refs/heads/master', execOpts);
86
+ mainBranch = 'master';
87
+ }
88
+ catch {
89
+ // fallback
90
+ }
91
+ }
92
+ vars.gitMainBranch = mainBranch;
93
+ const gitStatus = execSync('git status --short', { ...execOpts, timeout: 5000 }).toString().trim();
94
+ const statusLines = gitStatus ? gitStatus.split('\n') : [];
95
+ vars.gitStatus = statusLines.length > 30
96
+ ? [...statusLines.slice(0, 30), `... and ${statusLines.length - 30} more files`].join('\n')
97
+ : (gitStatus || '(clean)');
98
+ }
99
+ catch {
100
+ // Not a git repo or git not available
101
+ vars.gitBranch = '(unknown)';
102
+ vars.gitMainBranch = 'main';
103
+ vars.gitStatus = '(not a git repo)';
104
+ }
105
+ return template.replace(/\{(\w+)\}/g, (match, varName) => {
106
+ return vars[varName] ?? match;
107
+ });
108
+ }
109
+ //# sourceMappingURL=workspaceContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceContext.js","sourceRoot":"","sources":["../../src/services/workspaceContext.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
- /BMad:agents:dev
2
- ---
3
- *review-qa {arg1}
4
-
5
- After completing QA fixes, update the gate YAML file's gate field to 'FIXED'.
1
+ /BMad:agents:dev
2
+ ---
3
+ *review-qa {arg1}
4
+
5
+ After the fixes are applied and you update the story's Dev Agent Record, record which QA gate you addressed so Hammoc can track it. Read the `updated:` value from this story's QA gate YAML, then append this exact line inside the Completion Notes — replace the placeholder with that value. Do NOT change Status and do NOT edit the gate file:
6
+ <!-- hammoc:qa-fix gate="<paste the gate's updated value>" applied="true" -->
7
+ This flips the story from "apply QA fixes" to "request QA re-review" in Hammoc.
@@ -1,3 +1,9 @@
1
1
  /BMad:agents:qa
2
2
  ---
3
- *review {arg1}
3
+ *review {arg1}
4
+
5
+ CRITICAL — the gate YAML must parse. Write every free-text field (status_reason, finding, fix_recommendation, notes, etc.) as a block scalar (e.g. `status_reason: |`) on its own indented lines, NOT as a quoted string. Free text here routinely contains backticks, colons, apostrophes and SQL/code snippets, and quoting them has repeatedly produced invalid YAML that silently breaks Hammoc's gate detection. Block scalars need no escaping. After writing the gate file, re-read it and confirm it loads as valid YAML (e.g. run a quick parse); if it fails, fix and rewrite before finishing.
6
+
7
+ When you write the quality gate, if the gate decision is CONCERNS or FAIL, also record it in the story so Hammoc tracks that a fix is pending. Append this exact line inside the story's QA Results section, replacing the placeholder with the gate's `updated:` value you just wrote:
8
+ <!-- hammoc:qa-fix gate="<paste the gate's updated value>" applied="false" -->
9
+ For a PASS or WAIVED gate, do not add this marker.
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Story 30.5 (AC9): single-source guard against ZIP-slip / path-traversal
3
+ * during harness bundle import.
4
+ *
5
+ * `jszip` does not normalise entry paths — a malicious bundle can ship an
6
+ * entry called `../../etc/passwd` or `C:\Windows\System32\evil.dll` and naive
7
+ * code that joins it to the project root would write outside the target.
8
+ * Every entry path read from an import ZIP must therefore pass through this
9
+ * function before the bundle service touches disk.
10
+ *
11
+ * Rejected shapes:
12
+ * - absolute POSIX (`/etc/...`)
13
+ * - absolute Windows (`C:\...`, `C:/...`)
14
+ * - UNC (`\\server\share`, `//server/share`)
15
+ * - any traversal component (`..` segment anywhere in the path)
16
+ * - embedded null byte (would terminate the path early in fs APIs)
17
+ *
18
+ * Accepted shapes:
19
+ * - POSIX-style relative paths (`skills/foo/SKILL.md`)
20
+ * - Windows-style backslashes are normalised, then validated
21
+ * - the empty string (the zip "/" root) is rejected as it carries no entry
22
+ */
23
+ export declare class UnsafeBundlePathError extends Error {
24
+ readonly code = "HARNESS_BUNDLE_UNSAFE_PATH";
25
+ readonly relativePath: string;
26
+ constructor(relativePath: string, reason: string);
27
+ }
28
+ export declare function assertSafeBundlePath(relativePath: string): void;
29
+ //# sourceMappingURL=assertSafeBundlePath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertSafeBundlePath.d.ts","sourceRoot":"","sources":["../../src/utils/assertSafeBundlePath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,gCAAgC;IAC7C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;gBAClB,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAIjD;AAED,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAmB/D"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Story 30.5 (AC9): single-source guard against ZIP-slip / path-traversal
3
+ * during harness bundle import.
4
+ *
5
+ * `jszip` does not normalise entry paths — a malicious bundle can ship an
6
+ * entry called `../../etc/passwd` or `C:\Windows\System32\evil.dll` and naive
7
+ * code that joins it to the project root would write outside the target.
8
+ * Every entry path read from an import ZIP must therefore pass through this
9
+ * function before the bundle service touches disk.
10
+ *
11
+ * Rejected shapes:
12
+ * - absolute POSIX (`/etc/...`)
13
+ * - absolute Windows (`C:\...`, `C:/...`)
14
+ * - UNC (`\\server\share`, `//server/share`)
15
+ * - any traversal component (`..` segment anywhere in the path)
16
+ * - embedded null byte (would terminate the path early in fs APIs)
17
+ *
18
+ * Accepted shapes:
19
+ * - POSIX-style relative paths (`skills/foo/SKILL.md`)
20
+ * - Windows-style backslashes are normalised, then validated
21
+ * - the empty string (the zip "/" root) is rejected as it carries no entry
22
+ */
23
+ const ABSOLUTE_WIN_RE = /^[A-Za-z]:[\\/]/;
24
+ const TRAVERSAL_SEGMENT_RE = /(^|[\\/])\.\.([\\/]|$)/;
25
+ export class UnsafeBundlePathError extends Error {
26
+ code = 'HARNESS_BUNDLE_UNSAFE_PATH';
27
+ relativePath;
28
+ constructor(relativePath, reason) {
29
+ super(`unsafe bundle entry "${relativePath}": ${reason}`);
30
+ this.relativePath = relativePath;
31
+ }
32
+ }
33
+ export function assertSafeBundlePath(relativePath) {
34
+ if (typeof relativePath !== 'string' || relativePath.length === 0) {
35
+ throw new UnsafeBundlePathError(String(relativePath), 'empty entry path');
36
+ }
37
+ if (relativePath.includes('\0')) {
38
+ throw new UnsafeBundlePathError(relativePath, 'null byte in entry path');
39
+ }
40
+ if (relativePath.startsWith('/') || relativePath.startsWith('\\')) {
41
+ throw new UnsafeBundlePathError(relativePath, 'absolute path not allowed');
42
+ }
43
+ if (ABSOLUTE_WIN_RE.test(relativePath)) {
44
+ throw new UnsafeBundlePathError(relativePath, 'Windows-absolute path not allowed');
45
+ }
46
+ if (relativePath.startsWith('\\\\') || relativePath.startsWith('//')) {
47
+ throw new UnsafeBundlePathError(relativePath, 'UNC path not allowed');
48
+ }
49
+ if (TRAVERSAL_SEGMENT_RE.test(relativePath)) {
50
+ throw new UnsafeBundlePathError(relativePath, 'parent-directory traversal not allowed');
51
+ }
52
+ }
53
+ //# sourceMappingURL=assertSafeBundlePath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertSafeBundlePath.js","sourceRoot":"","sources":["../../src/utils/assertSafeBundlePath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAC1C,MAAM,oBAAoB,GAAG,wBAAwB,CAAC;AAEtD,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IACrC,IAAI,GAAG,4BAA4B,CAAC;IACpC,YAAY,CAAS;IAC9B,YAAY,YAAoB,EAAE,MAAc;QAC9C,KAAK,CAAC,wBAAwB,YAAY,MAAM,MAAM,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;CACF;AAED,MAAM,UAAU,oBAAoB,CAAC,YAAoB;IACvD,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,qBAAqB,CAAC,YAAY,EAAE,yBAAyB,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,qBAAqB,CAAC,YAAY,EAAE,2BAA2B,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,qBAAqB,CAAC,YAAY,EAAE,mCAAmC,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,qBAAqB,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,oBAAoB,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,qBAAqB,CAAC,YAAY,EAAE,wCAAwC,CAAC,CAAC;IAC1F,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Background-execution block policy shared by both chat engines (Story 36.1).
3
+ *
4
+ * Hammoc runs one CLI/SDK process per turn (turn-per-process) and kills it when
5
+ * the turn ends, so a backgrounded tool call (`run_in_background: true`) would be
6
+ * orphaned/killed and only leaves side effects (e.g. task-notification files).
7
+ * A PreToolUse hook denies such calls before they reach the shell — and unlike
8
+ * canUseTool, a PreToolUse deny also covers auto-approved tools (bypass/auto modes).
9
+ *
10
+ * SDK mode wires the check as an inline hook callback (see chatService); CLI mode
11
+ * runs it as an external command hook (resources/hooks/block-background.cjs). The
12
+ * two runtimes differ, so only the predicate + reason are shared here.
13
+ *
14
+ * ⚠️ The .cjs script duplicates BACKGROUND_BLOCK_REASON as a literal (it cannot
15
+ * import a TS module); keep the two strings in sync.
16
+ */
17
+ export declare const BACKGROUND_BLOCK_REASON = "Background execution is disabled in Hammoc: it runs one process per turn, so a backgrounded task is killed when the turn ends. Re-run without run_in_background (foreground).";
18
+ /**
19
+ * True when a tool call requests background execution (`run_in_background: true`) — which
20
+ * must be blocked regardless of WHICH tool it is. Hammoc is turn-per-process, so ANY
21
+ * backgrounded call is orphaned at turn end. We key off the INPUT FLAG, not the tool name:
22
+ * a tool-name allow-list silently misses tools (that was the earlier Windows PowerShell gap),
23
+ * whereas the flag is the actual thing that makes the call doomed.
24
+ *
25
+ * Crucially this does NOT touch foreground execution: several foreground tools launched in
26
+ * parallel within one turn and awaited carry no `run_in_background` flag, so they pass through.
27
+ */
28
+ export declare function isBlockedBackgroundCall(toolInput: unknown): boolean;
29
+ //# sourceMappingURL=backgroundBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backgroundBlock.d.ts","sourceRoot":"","sources":["../../src/utils/backgroundBlock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,uBAAuB,kLAC6I,CAAC;AAElL;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAMnE"}