mstro-app 0.4.2 → 0.4.4

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 (342) hide show
  1. package/bin/mstro.js +119 -40
  2. package/dist/server/cli/headless/claude-invoker-process.d.ts +11 -0
  3. package/dist/server/cli/headless/claude-invoker-process.d.ts.map +1 -0
  4. package/dist/server/cli/headless/claude-invoker-process.js +140 -0
  5. package/dist/server/cli/headless/claude-invoker-process.js.map +1 -0
  6. package/dist/server/cli/headless/claude-invoker-stall.d.ts +40 -0
  7. package/dist/server/cli/headless/claude-invoker-stall.d.ts.map +1 -0
  8. package/dist/server/cli/headless/claude-invoker-stall.js +98 -0
  9. package/dist/server/cli/headless/claude-invoker-stall.js.map +1 -0
  10. package/dist/server/cli/headless/claude-invoker-stream.d.ts +44 -0
  11. package/dist/server/cli/headless/claude-invoker-stream.d.ts.map +1 -0
  12. package/dist/server/cli/headless/claude-invoker-stream.js +276 -0
  13. package/dist/server/cli/headless/claude-invoker-stream.js.map +1 -0
  14. package/dist/server/cli/headless/claude-invoker-tools.d.ts +21 -0
  15. package/dist/server/cli/headless/claude-invoker-tools.d.ts.map +1 -0
  16. package/dist/server/cli/headless/claude-invoker-tools.js +137 -0
  17. package/dist/server/cli/headless/claude-invoker-tools.js.map +1 -0
  18. package/dist/server/cli/headless/claude-invoker.d.ts +6 -4
  19. package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
  20. package/dist/server/cli/headless/claude-invoker.js +10 -804
  21. package/dist/server/cli/headless/claude-invoker.js.map +1 -1
  22. package/dist/server/cli/headless/haiku-assessments.d.ts +62 -0
  23. package/dist/server/cli/headless/haiku-assessments.d.ts.map +1 -0
  24. package/dist/server/cli/headless/haiku-assessments.js +281 -0
  25. package/dist/server/cli/headless/haiku-assessments.js.map +1 -0
  26. package/dist/server/cli/headless/headless-logger.d.ts +3 -2
  27. package/dist/server/cli/headless/headless-logger.d.ts.map +1 -1
  28. package/dist/server/cli/headless/headless-logger.js +28 -5
  29. package/dist/server/cli/headless/headless-logger.js.map +1 -1
  30. package/dist/server/cli/headless/native-timeout-detector.d.ts +44 -0
  31. package/dist/server/cli/headless/native-timeout-detector.d.ts.map +1 -0
  32. package/dist/server/cli/headless/native-timeout-detector.js +99 -0
  33. package/dist/server/cli/headless/native-timeout-detector.js.map +1 -0
  34. package/dist/server/cli/headless/stall-assessor.d.ts +2 -110
  35. package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
  36. package/dist/server/cli/headless/stall-assessor.js +65 -457
  37. package/dist/server/cli/headless/stall-assessor.js.map +1 -1
  38. package/dist/server/cli/headless/types.d.ts +4 -1
  39. package/dist/server/cli/headless/types.d.ts.map +1 -1
  40. package/dist/server/cli/improvisation-attachments.d.ts +21 -0
  41. package/dist/server/cli/improvisation-attachments.d.ts.map +1 -0
  42. package/dist/server/cli/improvisation-attachments.js +116 -0
  43. package/dist/server/cli/improvisation-attachments.js.map +1 -0
  44. package/dist/server/cli/improvisation-retry.d.ts +52 -0
  45. package/dist/server/cli/improvisation-retry.d.ts.map +1 -0
  46. package/dist/server/cli/improvisation-retry.js +434 -0
  47. package/dist/server/cli/improvisation-retry.js.map +1 -0
  48. package/dist/server/cli/improvisation-session-manager.d.ts +10 -266
  49. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
  50. package/dist/server/cli/improvisation-session-manager.js +117 -1079
  51. package/dist/server/cli/improvisation-session-manager.js.map +1 -1
  52. package/dist/server/cli/improvisation-types.d.ts +86 -0
  53. package/dist/server/cli/improvisation-types.d.ts.map +1 -0
  54. package/dist/server/cli/improvisation-types.js +10 -0
  55. package/dist/server/cli/improvisation-types.js.map +1 -0
  56. package/dist/server/cli/prompt-builders.d.ts +68 -0
  57. package/dist/server/cli/prompt-builders.d.ts.map +1 -0
  58. package/dist/server/cli/prompt-builders.js +312 -0
  59. package/dist/server/cli/prompt-builders.js.map +1 -0
  60. package/dist/server/index.js +33 -212
  61. package/dist/server/index.js.map +1 -1
  62. package/dist/server/mcp/bouncer-haiku.d.ts +10 -0
  63. package/dist/server/mcp/bouncer-haiku.d.ts.map +1 -0
  64. package/dist/server/mcp/bouncer-haiku.js +152 -0
  65. package/dist/server/mcp/bouncer-haiku.js.map +1 -0
  66. package/dist/server/mcp/bouncer-integration.d.ts +3 -4
  67. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
  68. package/dist/server/mcp/bouncer-integration.js +50 -196
  69. package/dist/server/mcp/bouncer-integration.js.map +1 -1
  70. package/dist/server/mcp/security-analysis.d.ts +38 -0
  71. package/dist/server/mcp/security-analysis.d.ts.map +1 -0
  72. package/dist/server/mcp/security-analysis.js +183 -0
  73. package/dist/server/mcp/security-analysis.js.map +1 -0
  74. package/dist/server/mcp/security-audit.d.ts +1 -1
  75. package/dist/server/mcp/security-audit.d.ts.map +1 -1
  76. package/dist/server/mcp/security-patterns.d.ts +1 -25
  77. package/dist/server/mcp/security-patterns.d.ts.map +1 -1
  78. package/dist/server/mcp/security-patterns.js +55 -260
  79. package/dist/server/mcp/security-patterns.js.map +1 -1
  80. package/dist/server/server-setup.d.ts +22 -0
  81. package/dist/server/server-setup.d.ts.map +1 -0
  82. package/dist/server/server-setup.js +101 -0
  83. package/dist/server/server-setup.js.map +1 -0
  84. package/dist/server/services/file-explorer-ops.d.ts +24 -0
  85. package/dist/server/services/file-explorer-ops.d.ts.map +1 -0
  86. package/dist/server/services/file-explorer-ops.js +211 -0
  87. package/dist/server/services/file-explorer-ops.js.map +1 -0
  88. package/dist/server/services/files.d.ts +2 -85
  89. package/dist/server/services/files.d.ts.map +1 -1
  90. package/dist/server/services/files.js +7 -427
  91. package/dist/server/services/files.js.map +1 -1
  92. package/dist/server/services/plan/composer.d.ts +1 -1
  93. package/dist/server/services/plan/composer.d.ts.map +1 -1
  94. package/dist/server/services/plan/composer.js +118 -32
  95. package/dist/server/services/plan/composer.js.map +1 -1
  96. package/dist/server/services/plan/config-installer.d.ts +25 -0
  97. package/dist/server/services/plan/config-installer.d.ts.map +1 -0
  98. package/dist/server/services/plan/config-installer.js +182 -0
  99. package/dist/server/services/plan/config-installer.js.map +1 -0
  100. package/dist/server/services/plan/dependency-resolver.d.ts +1 -1
  101. package/dist/server/services/plan/dependency-resolver.d.ts.map +1 -1
  102. package/dist/server/services/plan/dependency-resolver.js +4 -1
  103. package/dist/server/services/plan/dependency-resolver.js.map +1 -1
  104. package/dist/server/services/plan/executor.d.ts +38 -74
  105. package/dist/server/services/plan/executor.d.ts.map +1 -1
  106. package/dist/server/services/plan/executor.js +274 -460
  107. package/dist/server/services/plan/executor.js.map +1 -1
  108. package/dist/server/services/plan/front-matter.d.ts +18 -0
  109. package/dist/server/services/plan/front-matter.d.ts.map +1 -0
  110. package/dist/server/services/plan/front-matter.js +44 -0
  111. package/dist/server/services/plan/front-matter.js.map +1 -0
  112. package/dist/server/services/plan/output-manager.d.ts +22 -0
  113. package/dist/server/services/plan/output-manager.d.ts.map +1 -0
  114. package/dist/server/services/plan/output-manager.js +97 -0
  115. package/dist/server/services/plan/output-manager.js.map +1 -0
  116. package/dist/server/services/plan/parser-core.d.ts +20 -0
  117. package/dist/server/services/plan/parser-core.d.ts.map +1 -0
  118. package/dist/server/services/plan/parser-core.js +350 -0
  119. package/dist/server/services/plan/parser-core.js.map +1 -0
  120. package/dist/server/services/plan/parser-migration.d.ts +5 -0
  121. package/dist/server/services/plan/parser-migration.d.ts.map +1 -0
  122. package/dist/server/services/plan/parser-migration.js +124 -0
  123. package/dist/server/services/plan/parser-migration.js.map +1 -0
  124. package/dist/server/services/plan/parser.d.ts +11 -3
  125. package/dist/server/services/plan/parser.d.ts.map +1 -1
  126. package/dist/server/services/plan/parser.js +184 -369
  127. package/dist/server/services/plan/parser.js.map +1 -1
  128. package/dist/server/services/plan/prompt-builder.d.ts +17 -0
  129. package/dist/server/services/plan/prompt-builder.d.ts.map +1 -0
  130. package/dist/server/services/plan/prompt-builder.js +137 -0
  131. package/dist/server/services/plan/prompt-builder.js.map +1 -0
  132. package/dist/server/services/plan/review-gate.d.ts +28 -0
  133. package/dist/server/services/plan/review-gate.d.ts.map +1 -0
  134. package/dist/server/services/plan/review-gate.js +191 -0
  135. package/dist/server/services/plan/review-gate.js.map +1 -0
  136. package/dist/server/services/plan/state-reconciler.d.ts +1 -1
  137. package/dist/server/services/plan/state-reconciler.d.ts.map +1 -1
  138. package/dist/server/services/plan/state-reconciler.js +59 -7
  139. package/dist/server/services/plan/state-reconciler.js.map +1 -1
  140. package/dist/server/services/plan/types.d.ts +68 -0
  141. package/dist/server/services/plan/types.d.ts.map +1 -1
  142. package/dist/server/services/platform-credentials.d.ts +24 -0
  143. package/dist/server/services/platform-credentials.d.ts.map +1 -0
  144. package/dist/server/services/platform-credentials.js +68 -0
  145. package/dist/server/services/platform-credentials.js.map +1 -0
  146. package/dist/server/services/platform.d.ts +1 -31
  147. package/dist/server/services/platform.d.ts.map +1 -1
  148. package/dist/server/services/platform.js +11 -109
  149. package/dist/server/services/platform.js.map +1 -1
  150. package/dist/server/services/terminal/pty-manager.d.ts +7 -97
  151. package/dist/server/services/terminal/pty-manager.d.ts.map +1 -1
  152. package/dist/server/services/terminal/pty-manager.js +53 -266
  153. package/dist/server/services/terminal/pty-manager.js.map +1 -1
  154. package/dist/server/services/terminal/pty-utils.d.ts +57 -0
  155. package/dist/server/services/terminal/pty-utils.d.ts.map +1 -0
  156. package/dist/server/services/terminal/pty-utils.js +141 -0
  157. package/dist/server/services/terminal/pty-utils.js.map +1 -0
  158. package/dist/server/services/websocket/file-definition-handlers.d.ts +4 -0
  159. package/dist/server/services/websocket/file-definition-handlers.d.ts.map +1 -0
  160. package/dist/server/services/websocket/file-definition-handlers.js +153 -0
  161. package/dist/server/services/websocket/file-definition-handlers.js.map +1 -0
  162. package/dist/server/services/websocket/file-explorer-handlers.d.ts.map +1 -1
  163. package/dist/server/services/websocket/file-explorer-handlers.js +52 -391
  164. package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -1
  165. package/dist/server/services/websocket/file-search-handlers.d.ts +5 -0
  166. package/dist/server/services/websocket/file-search-handlers.d.ts.map +1 -0
  167. package/dist/server/services/websocket/file-search-handlers.js +238 -0
  168. package/dist/server/services/websocket/file-search-handlers.js.map +1 -0
  169. package/dist/server/services/websocket/file-utils.js +3 -3
  170. package/dist/server/services/websocket/file-utils.js.map +1 -1
  171. package/dist/server/services/websocket/git-branch-handlers.d.ts +7 -0
  172. package/dist/server/services/websocket/git-branch-handlers.d.ts.map +1 -0
  173. package/dist/server/services/websocket/git-branch-handlers.js +110 -0
  174. package/dist/server/services/websocket/git-branch-handlers.js.map +1 -0
  175. package/dist/server/services/websocket/git-diff-handlers.d.ts +6 -0
  176. package/dist/server/services/websocket/git-diff-handlers.d.ts.map +1 -0
  177. package/dist/server/services/websocket/git-diff-handlers.js +123 -0
  178. package/dist/server/services/websocket/git-diff-handlers.js.map +1 -0
  179. package/dist/server/services/websocket/git-handlers.d.ts +2 -31
  180. package/dist/server/services/websocket/git-handlers.d.ts.map +1 -1
  181. package/dist/server/services/websocket/git-handlers.js +35 -541
  182. package/dist/server/services/websocket/git-handlers.js.map +1 -1
  183. package/dist/server/services/websocket/git-log-handlers.d.ts +6 -0
  184. package/dist/server/services/websocket/git-log-handlers.d.ts.map +1 -0
  185. package/dist/server/services/websocket/git-log-handlers.js +128 -0
  186. package/dist/server/services/websocket/git-log-handlers.js.map +1 -0
  187. package/dist/server/services/websocket/git-pr-handlers.d.ts.map +1 -1
  188. package/dist/server/services/websocket/git-pr-handlers.js +13 -53
  189. package/dist/server/services/websocket/git-pr-handlers.js.map +1 -1
  190. package/dist/server/services/websocket/git-tag-handlers.d.ts +6 -0
  191. package/dist/server/services/websocket/git-tag-handlers.d.ts.map +1 -0
  192. package/dist/server/services/websocket/git-tag-handlers.js +76 -0
  193. package/dist/server/services/websocket/git-tag-handlers.js.map +1 -0
  194. package/dist/server/services/websocket/git-utils.d.ts +43 -0
  195. package/dist/server/services/websocket/git-utils.d.ts.map +1 -0
  196. package/dist/server/services/websocket/git-utils.js +201 -0
  197. package/dist/server/services/websocket/git-utils.js.map +1 -0
  198. package/dist/server/services/websocket/handler.d.ts +2 -0
  199. package/dist/server/services/websocket/handler.d.ts.map +1 -1
  200. package/dist/server/services/websocket/handler.js +37 -112
  201. package/dist/server/services/websocket/handler.js.map +1 -1
  202. package/dist/server/services/websocket/plan-board-handlers.d.ts +11 -0
  203. package/dist/server/services/websocket/plan-board-handlers.d.ts.map +1 -0
  204. package/dist/server/services/websocket/plan-board-handlers.js +218 -0
  205. package/dist/server/services/websocket/plan-board-handlers.js.map +1 -0
  206. package/dist/server/services/websocket/plan-execution-handlers.d.ts +9 -0
  207. package/dist/server/services/websocket/plan-execution-handlers.d.ts.map +1 -0
  208. package/dist/server/services/websocket/plan-execution-handlers.js +142 -0
  209. package/dist/server/services/websocket/plan-execution-handlers.js.map +1 -0
  210. package/dist/server/services/websocket/plan-handlers.d.ts +7 -2
  211. package/dist/server/services/websocket/plan-handlers.d.ts.map +1 -1
  212. package/dist/server/services/websocket/plan-handlers.js +21 -462
  213. package/dist/server/services/websocket/plan-handlers.js.map +1 -1
  214. package/dist/server/services/websocket/plan-helpers.d.ts +19 -0
  215. package/dist/server/services/websocket/plan-helpers.d.ts.map +1 -0
  216. package/dist/server/services/websocket/plan-helpers.js +199 -0
  217. package/dist/server/services/websocket/plan-helpers.js.map +1 -0
  218. package/dist/server/services/websocket/plan-issue-handlers.d.ts +12 -0
  219. package/dist/server/services/websocket/plan-issue-handlers.d.ts.map +1 -0
  220. package/dist/server/services/websocket/plan-issue-handlers.js +162 -0
  221. package/dist/server/services/websocket/plan-issue-handlers.js.map +1 -0
  222. package/dist/server/services/websocket/plan-sprint-handlers.d.ts +7 -0
  223. package/dist/server/services/websocket/plan-sprint-handlers.d.ts.map +1 -0
  224. package/dist/server/services/websocket/plan-sprint-handlers.js +206 -0
  225. package/dist/server/services/websocket/plan-sprint-handlers.js.map +1 -0
  226. package/dist/server/services/websocket/quality-complexity.d.ts +14 -0
  227. package/dist/server/services/websocket/quality-complexity.d.ts.map +1 -0
  228. package/dist/server/services/websocket/quality-complexity.js +262 -0
  229. package/dist/server/services/websocket/quality-complexity.js.map +1 -0
  230. package/dist/server/services/websocket/quality-fix-agent.d.ts +16 -0
  231. package/dist/server/services/websocket/quality-fix-agent.d.ts.map +1 -0
  232. package/dist/server/services/websocket/quality-fix-agent.js +140 -0
  233. package/dist/server/services/websocket/quality-fix-agent.js.map +1 -0
  234. package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -1
  235. package/dist/server/services/websocket/quality-handlers.js +34 -346
  236. package/dist/server/services/websocket/quality-handlers.js.map +1 -1
  237. package/dist/server/services/websocket/quality-linting.d.ts +9 -0
  238. package/dist/server/services/websocket/quality-linting.d.ts.map +1 -0
  239. package/dist/server/services/websocket/quality-linting.js +178 -0
  240. package/dist/server/services/websocket/quality-linting.js.map +1 -0
  241. package/dist/server/services/websocket/quality-review-agent.d.ts +19 -0
  242. package/dist/server/services/websocket/quality-review-agent.d.ts.map +1 -0
  243. package/dist/server/services/websocket/quality-review-agent.js +206 -0
  244. package/dist/server/services/websocket/quality-review-agent.js.map +1 -0
  245. package/dist/server/services/websocket/quality-service.d.ts +3 -51
  246. package/dist/server/services/websocket/quality-service.d.ts.map +1 -1
  247. package/dist/server/services/websocket/quality-service.js +9 -651
  248. package/dist/server/services/websocket/quality-service.js.map +1 -1
  249. package/dist/server/services/websocket/quality-tools.d.ts +23 -0
  250. package/dist/server/services/websocket/quality-tools.d.ts.map +1 -0
  251. package/dist/server/services/websocket/quality-tools.js +208 -0
  252. package/dist/server/services/websocket/quality-tools.js.map +1 -0
  253. package/dist/server/services/websocket/quality-types.d.ts +59 -0
  254. package/dist/server/services/websocket/quality-types.d.ts.map +1 -0
  255. package/dist/server/services/websocket/quality-types.js +101 -0
  256. package/dist/server/services/websocket/quality-types.js.map +1 -0
  257. package/dist/server/services/websocket/session-handlers.d.ts +3 -4
  258. package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
  259. package/dist/server/services/websocket/session-handlers.js +3 -378
  260. package/dist/server/services/websocket/session-handlers.js.map +1 -1
  261. package/dist/server/services/websocket/session-history.d.ts +4 -0
  262. package/dist/server/services/websocket/session-history.d.ts.map +1 -0
  263. package/dist/server/services/websocket/session-history.js +208 -0
  264. package/dist/server/services/websocket/session-history.js.map +1 -0
  265. package/dist/server/services/websocket/session-initialization.d.ts +5 -0
  266. package/dist/server/services/websocket/session-initialization.d.ts.map +1 -0
  267. package/dist/server/services/websocket/session-initialization.js +163 -0
  268. package/dist/server/services/websocket/session-initialization.js.map +1 -0
  269. package/dist/server/services/websocket/types.d.ts +12 -2
  270. package/dist/server/services/websocket/types.d.ts.map +1 -1
  271. package/package.json +1 -2
  272. package/server/cli/headless/claude-invoker-process.ts +204 -0
  273. package/server/cli/headless/claude-invoker-stall.ts +164 -0
  274. package/server/cli/headless/claude-invoker-stream.ts +353 -0
  275. package/server/cli/headless/claude-invoker-tools.ts +187 -0
  276. package/server/cli/headless/claude-invoker.ts +15 -1092
  277. package/server/cli/headless/haiku-assessments.ts +365 -0
  278. package/server/cli/headless/headless-logger.ts +26 -5
  279. package/server/cli/headless/native-timeout-detector.ts +117 -0
  280. package/server/cli/headless/stall-assessor.ts +65 -618
  281. package/server/cli/headless/types.ts +4 -1
  282. package/server/cli/improvisation-attachments.ts +148 -0
  283. package/server/cli/improvisation-retry.ts +602 -0
  284. package/server/cli/improvisation-session-manager.ts +140 -1349
  285. package/server/cli/improvisation-types.ts +98 -0
  286. package/server/cli/prompt-builders.ts +370 -0
  287. package/server/index.ts +35 -246
  288. package/server/mcp/bouncer-haiku.ts +182 -0
  289. package/server/mcp/bouncer-integration.ts +87 -248
  290. package/server/mcp/security-analysis.ts +217 -0
  291. package/server/mcp/security-audit.ts +1 -1
  292. package/server/mcp/security-patterns.ts +60 -283
  293. package/server/server-setup.ts +114 -0
  294. package/server/services/file-explorer-ops.ts +293 -0
  295. package/server/services/files.ts +20 -532
  296. package/server/services/plan/composer.ts +140 -35
  297. package/server/services/plan/config-installer.ts +187 -0
  298. package/server/services/plan/dependency-resolver.ts +4 -1
  299. package/server/services/plan/executor.ts +281 -488
  300. package/server/services/plan/front-matter.ts +48 -0
  301. package/server/services/plan/output-manager.ts +113 -0
  302. package/server/services/plan/parser-core.ts +406 -0
  303. package/server/services/plan/parser-migration.ts +128 -0
  304. package/server/services/plan/parser.ts +188 -394
  305. package/server/services/plan/prompt-builder.ts +161 -0
  306. package/server/services/plan/review-gate.ts +212 -0
  307. package/server/services/plan/state-reconciler.ts +68 -7
  308. package/server/services/plan/types.ts +101 -1
  309. package/server/services/platform-credentials.ts +83 -0
  310. package/server/services/platform.ts +16 -131
  311. package/server/services/terminal/pty-manager.ts +66 -313
  312. package/server/services/terminal/pty-utils.ts +176 -0
  313. package/server/services/websocket/file-definition-handlers.ts +165 -0
  314. package/server/services/websocket/file-explorer-handlers.ts +37 -452
  315. package/server/services/websocket/file-search-handlers.ts +291 -0
  316. package/server/services/websocket/file-utils.ts +3 -3
  317. package/server/services/websocket/git-branch-handlers.ts +130 -0
  318. package/server/services/websocket/git-diff-handlers.ts +140 -0
  319. package/server/services/websocket/git-handlers.ts +40 -625
  320. package/server/services/websocket/git-log-handlers.ts +149 -0
  321. package/server/services/websocket/git-pr-handlers.ts +17 -62
  322. package/server/services/websocket/git-tag-handlers.ts +91 -0
  323. package/server/services/websocket/git-utils.ts +230 -0
  324. package/server/services/websocket/handler.ts +39 -112
  325. package/server/services/websocket/plan-board-handlers.ts +277 -0
  326. package/server/services/websocket/plan-execution-handlers.ts +184 -0
  327. package/server/services/websocket/plan-handlers.ts +23 -544
  328. package/server/services/websocket/plan-helpers.ts +215 -0
  329. package/server/services/websocket/plan-issue-handlers.ts +204 -0
  330. package/server/services/websocket/plan-sprint-handlers.ts +252 -0
  331. package/server/services/websocket/quality-complexity.ts +294 -0
  332. package/server/services/websocket/quality-fix-agent.ts +181 -0
  333. package/server/services/websocket/quality-handlers.ts +36 -404
  334. package/server/services/websocket/quality-linting.ts +187 -0
  335. package/server/services/websocket/quality-review-agent.ts +246 -0
  336. package/server/services/websocket/quality-service.ts +11 -762
  337. package/server/services/websocket/quality-tools.ts +209 -0
  338. package/server/services/websocket/quality-types.ts +169 -0
  339. package/server/services/websocket/session-handlers.ts +5 -437
  340. package/server/services/websocket/session-history.ts +222 -0
  341. package/server/services/websocket/session-initialization.ts +209 -0
  342. package/server/services/websocket/types.ts +46 -2
@@ -15,7 +15,8 @@ import { runWithFileLogger } from '../../cli/headless/headless-logger.js';
15
15
  import { HeadlessRunner, type ToolUseEvent } from '../../cli/headless/index.js';
16
16
  import type { HandlerContext } from '../websocket/handler-context.js';
17
17
  import type { WSContext } from '../websocket/types.js';
18
- import { getNextId, parsePlanDirectory, resolvePmDir } from './parser.js';
18
+ import { defaultPmDir, getNextId, parseBoardDirectory, parsePlanDirectory, resolvePmDir } from './parser.js';
19
+ import type { Issue } from './types.js';
19
20
 
20
21
  const PROMPT_TOOL_MESSAGES: Record<string, string> = {
21
22
  Glob: 'Discovering project files...',
@@ -64,57 +65,159 @@ function readFileOrEmpty(path: string): string {
64
65
  return '';
65
66
  }
66
67
 
68
+ interface ComposerContext {
69
+ boardContext: string;
70
+ stateContent: string;
71
+ issues: Issue[];
72
+ idInfo: string;
73
+ epicContext: string;
74
+ issuesSummary: string;
75
+ boardDir: string;
76
+ backlogPath: string;
77
+ effectiveBoardId: string | null;
78
+ }
79
+
80
+ function buildComposerContext(pmDir: string, workingDir: string, boardId?: string): ComposerContext {
81
+ const fullState = parsePlanDirectory(workingDir);
82
+ const effectiveBoardId = boardId ?? fullState?.workspace?.activeBoardId ?? null;
83
+
84
+ let boardContext = '';
85
+ let stateContent = '';
86
+ let issues: Issue[] = [];
87
+
88
+ if (effectiveBoardId) {
89
+ const boardState = parseBoardDirectory(pmDir, effectiveBoardId);
90
+ if (boardState) {
91
+ stateContent = readFileOrEmpty(join(pmDir, 'boards', effectiveBoardId, 'STATE.md'));
92
+ issues = boardState.issues;
93
+ boardContext = `\nActive board: ${effectiveBoardId} — "${boardState.board.title}"
94
+ Board status: ${boardState.board.status}
95
+ Board goal: ${boardState.board.goal || '(none set)'}
96
+ Board directory: ${pmDir}/boards/${effectiveBoardId}/
97
+ Backlog directory: ${pmDir}/boards/${effectiveBoardId}/backlog/\n`;
98
+ }
99
+ }
100
+
101
+ if (!stateContent) stateContent = readFileOrEmpty(join(pmDir, 'STATE.md'));
102
+ if (issues.length === 0 && fullState) issues = fullState.issues;
103
+
104
+ const idInfo = (issues.length > 0 || fullState)
105
+ ? `Next available IDs: ${getNextId(issues, 'IS')}, ${getNextId(issues, 'BG')}, ${getNextId(issues, 'EP')}`
106
+ : '';
107
+
108
+ const existingEpics = issues.filter(i => i.type === 'epic');
109
+ const epicContext = existingEpics.length > 0
110
+ ? `\nExisting epics:\n${existingEpics.map(e => `- ${e.id}: ${e.title} (${e.path}, children: ${e.children.length})`).join('\n')}\n`
111
+ : '';
112
+
113
+ const nonEpicIssues = issues.filter(i => i.type !== 'epic');
114
+ const issuesSummary = nonEpicIssues.length > 0
115
+ ? `\nExisting issues on this board:\n${nonEpicIssues.map(i => `- ${i.id}: ${i.title} [${i.status}] (P${i.priority})`).join('\n')}\n`
116
+ : '';
117
+
118
+ const boardDir = effectiveBoardId ? `boards/${effectiveBoardId}` : '';
119
+ const backlogPath = effectiveBoardId
120
+ ? `${pmDir}/boards/${effectiveBoardId}/backlog/`
121
+ : `${pmDir}/backlog/`;
122
+
123
+ return { boardContext, stateContent, issues, idInfo, epicContext, issuesSummary, boardDir, backlogPath, effectiveBoardId };
124
+ }
125
+
67
126
  export async function handlePlanPrompt(
68
127
  ctx: HandlerContext,
69
128
  ws: WSContext,
70
129
  userPrompt: string,
71
130
  workingDir: string,
131
+ boardId?: string,
72
132
  ): Promise<void> {
73
- const pmDir = resolvePmDir(workingDir) ?? join(workingDir, '.pm');
74
- const stateContent = readFileOrEmpty(join(pmDir, 'STATE.md'));
133
+ const pmDir = resolvePmDir(workingDir) ?? defaultPmDir(workingDir);
75
134
  const projectContent = readFileOrEmpty(join(pmDir, 'project.md'));
135
+ const cc = buildComposerContext(pmDir, workingDir, boardId);
76
136
 
77
- // Compute next available IDs
78
- const fullState = parsePlanDirectory(workingDir);
79
- let idInfo = '';
80
- if (fullState) {
81
- const nextIS = getNextId(fullState.issues, 'IS');
82
- const nextBG = getNextId(fullState.issues, 'BG');
83
- const nextEP = getNextId(fullState.issues, 'EP');
84
- idInfo = `Next available IDs: ${nextIS}, ${nextBG}, ${nextEP}`;
85
- }
86
-
87
- // Read existing epic files to provide context
88
- let epicContext = '';
89
- if (fullState) {
90
- const existingEpics = fullState.issues.filter((i: { type: string }) => i.type === 'epic');
91
- if (existingEpics.length > 0) {
92
- epicContext = `\nExisting epics:\n${existingEpics.map((e: { id: string; title: string; path: string; children: string[] }) => `- ${e.id}: ${e.title} (${e.path}, children: ${e.children.length})`).join('\n')}\n`;
93
- }
94
- }
95
-
96
- const enrichedPrompt = `You are managing a project in the .pm/ directory format (Project Plan Spec).
97
- The project's current state is:
98
-
137
+ const enrichedPrompt = `You are managing a project using a board-centric PM system (Project Plan Spec v2).
138
+ All issues belong to a board. Each board has its own backlog/, STATE.md, and out/ directory.
139
+ ${cc.boardContext}
99
140
  <state>
100
- ${stateContent || 'No STATE.md exists yet'}
141
+ ${cc.stateContent || 'No STATE.md exists yet'}
101
142
  </state>
102
143
 
103
144
  <project>
104
145
  ${projectContent || 'No project.md yet'}
105
146
  </project>
106
147
 
107
- ${idInfo}
108
- ${epicContext}
148
+ ${cc.idInfo}
149
+ ${cc.epicContext}
150
+ ${cc.issuesSummary}
151
+
152
+ ## Directory structure
109
153
 
110
- Follow these rules:
111
- - When creating .pm/ files, use YAML front matter + markdown body
154
+ \`\`\`
155
+ ${pmDir}/
156
+ ├── project.md
157
+ ├── workspace.json
158
+ └── boards/
159
+ └── ${cc.effectiveBoardId || 'BOARD-NNN'}/
160
+ ├── board.md # Board metadata
161
+ ├── STATE.md # Board execution state
162
+ ├── backlog/ # Issues, epics, bugs
163
+ │ ├── EP-*.md
164
+ │ ├── IS-*.md
165
+ │ └── BG-*.md
166
+ ├── out/ # Output artifacts
167
+ ├── reviews/ # Review gate results
168
+ └── progress.md # Execution log
169
+ \`\`\`
170
+
171
+ ## Rules
172
+
173
+ - ALL new issue files MUST be created in \`${cc.backlogPath}\`
174
+ - Use YAML front matter + markdown body for all files
112
175
  - When modifying issues, preserve all existing YAML fields you don't change
113
- - After any state change, update STATE.md to reflect the new status
176
+ - After any state change, update the board's STATE.md at \`${pmDir}/${cc.boardDir}/STATE.md\`
114
177
  - Use the next available ID for new entities
178
+ - Set all new issue statuses to \`todo\` so they appear in the "Ready to Work" section
115
179
  - Respond briefly describing what you did
116
180
 
117
- Issue scoping rules (critical for execution quality):
181
+ ## Issue format
182
+
183
+ Each issue file must have this structure:
184
+ \`\`\`markdown
185
+ ---
186
+ id: IS-NNN
187
+ title: "Short descriptive title"
188
+ type: issue
189
+ status: todo
190
+ priority: P0|P1|P2|P3
191
+ estimate: 1-5
192
+ labels: []
193
+ epic: backlog/EP-NNN.md # if part of an epic
194
+ created: "YYYY-MM-DD"
195
+ blocked_by: [] # Use backlog-relative paths: backlog/IS-NNN.md
196
+ blocks: [] # Use backlog-relative paths: backlog/IS-NNN.md
197
+ review_gate: auto
198
+ output_file: null
199
+ ---
200
+
201
+ # IS-NNN: Title
202
+
203
+ ## Description
204
+ What needs to be done and why.
205
+
206
+ ## Acceptance Criteria
207
+ - [ ] Criterion 1
208
+ - [ ] Criterion 2
209
+
210
+ ## Technical Notes
211
+ Implementation guidance.
212
+
213
+ ## Files to Modify
214
+ - path/to/file.ts
215
+
216
+ ## Activity
217
+ \`\`\`
218
+
219
+ ## Issue scoping rules (critical for execution quality)
220
+
118
221
  - Each issue is executed by a single AI agent with its own context window
119
222
  - Issues estimated at 1-3 story points execute well (focused, single concern)
120
223
  - Issues at 5 story points are viable if scoped to one subsystem
@@ -124,8 +227,9 @@ Issue scoping rules (critical for execution quality):
124
227
  - If an issue requires work across multiple subsystems, split it into one issue per subsystem with blocked_by edges between them
125
228
  - Research/investigation issues should be separate from implementation issues
126
229
 
127
- Epic creation rules (when user asks for a feature with sub-tasks or an epic):
128
- - Create an EP-*.md file in .pm/backlog/ with type: epic and a children: [] field in front matter
230
+ ## Epic creation rules
231
+
232
+ - Create an EP-*.md file in ${cc.backlogPath} with type: epic and a children: [] field in front matter
129
233
  - Create individual IS-*.md (or BG-*.md) files for each child issue
130
234
  - Each child issue must have epic: backlog/EP-XXX.md in its front matter
131
235
  - The epic's children field must list all child paths: [backlog/IS-001.md, backlog/IS-002.md, ...]
@@ -169,7 +273,8 @@ User request: ${userPrompt}`;
169
273
  data: { message: 'Claude is planning your project...' },
170
274
  });
171
275
 
172
- const result = await runWithFileLogger('pm-compose', () => runner.run());
276
+ const boardLogDir = cc.effectiveBoardId ? join(pmDir, 'boards', cc.effectiveBoardId, 'logs') : undefined;
277
+ const result = await runWithFileLogger('pm-compose', () => runner.run(), boardLogDir);
173
278
 
174
279
  ctx.broadcastToAll({
175
280
  type: 'planPromptProgress',
@@ -0,0 +1,187 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+
4
+ /**
5
+ * Config Installer — Manages temporary config file modifications for Agent Teams.
6
+ *
7
+ * Installs teammate permissions in .claude/settings.json and bouncer MCP config
8
+ * in .mcp.json before wave execution, then restores originals afterward.
9
+ */
10
+
11
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
12
+ import { join } from 'node:path';
13
+ import { generateMcpConfig } from '../../cli/headless/mcp-config.js';
14
+
15
+ /** Tools that teammates may need during execution */
16
+ const REQUIRED_PERMISSIONS = [
17
+ 'Bash',
18
+ 'Read',
19
+ 'Edit',
20
+ 'Write',
21
+ 'Glob',
22
+ 'Grep',
23
+ 'WebFetch',
24
+ 'WebSearch',
25
+ 'Agent',
26
+ ];
27
+
28
+ /** Restore a file from a .pm-backup, handling the __NONE__ sentinel for files that didn't exist. */
29
+ function restoreFromBackup(backupPath: string, targetPath: string): void {
30
+ try {
31
+ if (!existsSync(backupPath)) return;
32
+ const backup = readFileSync(backupPath, 'utf-8');
33
+ if (backup === '__NONE__') {
34
+ if (existsSync(targetPath)) unlinkSync(targetPath);
35
+ } else {
36
+ writeFileSync(targetPath, backup);
37
+ }
38
+ unlinkSync(backupPath);
39
+ } catch { /* best effort */ }
40
+ }
41
+
42
+ export class ConfigInstaller {
43
+ private savedClaudeSettings: string | null = null;
44
+ private claudeSettingsInstalled = false;
45
+ private savedMcpJson: string | null = null;
46
+ private mcpJsonInstalled = false;
47
+
48
+ constructor(private workingDir: string) {
49
+ // Recover from prior crash: if backup files exist, restore them
50
+ this.recoverFromCrash();
51
+ }
52
+
53
+ /** Restore .claude/settings.json and .mcp.json from backups left by a previous crash. */
54
+ private recoverFromCrash(): void {
55
+ restoreFromBackup(
56
+ join(this.workingDir, '.claude', 'settings.json.pm-backup'),
57
+ join(this.workingDir, '.claude', 'settings.json'),
58
+ );
59
+ restoreFromBackup(
60
+ join(this.workingDir, '.mcp.json.pm-backup'),
61
+ join(this.workingDir, '.mcp.json'),
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Pre-approve tools in .claude/settings.json so Agent Teams
67
+ * teammates can work without interactive permission prompts.
68
+ */
69
+ installTeammatePermissions(): void {
70
+ const claudeDir = join(this.workingDir, '.claude');
71
+ const settingsPath = join(claudeDir, 'settings.json');
72
+
73
+ if (!existsSync(claudeDir)) {
74
+ mkdirSync(claudeDir, { recursive: true });
75
+ }
76
+
77
+ const backupPath = join(claudeDir, 'settings.json.pm-backup');
78
+ try {
79
+ if (existsSync(settingsPath)) {
80
+ this.savedClaudeSettings = readFileSync(settingsPath, 'utf-8');
81
+ writeFileSync(backupPath, this.savedClaudeSettings);
82
+ const existing = JSON.parse(this.savedClaudeSettings);
83
+
84
+ if (!existing.permissions) existing.permissions = {};
85
+ if (!existing.permissions.allow) existing.permissions.allow = [];
86
+
87
+ for (const tool of REQUIRED_PERMISSIONS) {
88
+ if (!existing.permissions.allow.includes(tool)) {
89
+ existing.permissions.allow.push(tool);
90
+ }
91
+ }
92
+
93
+ writeFileSync(settingsPath, JSON.stringify(existing, null, 2));
94
+ } else {
95
+ this.savedClaudeSettings = null;
96
+ writeFileSync(backupPath, '__NONE__');
97
+ writeFileSync(settingsPath, JSON.stringify({
98
+ permissions: { allow: REQUIRED_PERMISSIONS },
99
+ }, null, 2));
100
+ }
101
+ this.claudeSettingsInstalled = true;
102
+ } catch {
103
+ // Non-fatal — teammates may hit permission prompts
104
+ }
105
+ }
106
+
107
+ /** Restore original .claude/settings.json after wave execution. */
108
+ uninstallTeammatePermissions(): void {
109
+ if (!this.claudeSettingsInstalled) return;
110
+ const settingsPath = join(this.workingDir, '.claude', 'settings.json');
111
+ const backupPath = join(this.workingDir, '.claude', 'settings.json.pm-backup');
112
+
113
+ try {
114
+ if (this.savedClaudeSettings !== null) {
115
+ writeFileSync(settingsPath, this.savedClaudeSettings);
116
+ } else {
117
+ unlinkSync(settingsPath);
118
+ }
119
+ } catch {
120
+ // Best effort
121
+ }
122
+
123
+ // Remove backup — successful restore means crash recovery is no longer needed
124
+ try { if (existsSync(backupPath)) unlinkSync(backupPath); } catch { /* ok */ }
125
+
126
+ this.savedClaudeSettings = null;
127
+ this.claudeSettingsInstalled = false;
128
+ }
129
+
130
+ /**
131
+ * Write .mcp.json so Agent Teams teammates auto-discover the bouncer MCP server.
132
+ * Also generates ~/.mstro/mcp-config.json for the team lead (--mcp-config).
133
+ */
134
+ installBouncerForSubagents(): void {
135
+ const mcpJsonPath = join(this.workingDir, '.mcp.json');
136
+
137
+ const backupPath = join(this.workingDir, '.mcp.json.pm-backup');
138
+ try {
139
+ const generatedPath = generateMcpConfig(this.workingDir);
140
+ if (!generatedPath) return;
141
+
142
+ const mcpConfig = readFileSync(generatedPath, 'utf-8');
143
+
144
+ if (existsSync(mcpJsonPath)) {
145
+ this.savedMcpJson = readFileSync(mcpJsonPath, 'utf-8');
146
+ writeFileSync(backupPath, this.savedMcpJson);
147
+
148
+ const existing = JSON.parse(this.savedMcpJson);
149
+ const generated = JSON.parse(mcpConfig);
150
+ existing.mcpServers = {
151
+ ...existing.mcpServers,
152
+ 'mstro-bouncer': generated.mcpServers['mstro-bouncer'],
153
+ };
154
+ writeFileSync(mcpJsonPath, JSON.stringify(existing, null, 2));
155
+ } else {
156
+ writeFileSync(backupPath, '__NONE__');
157
+ writeFileSync(mcpJsonPath, mcpConfig);
158
+ }
159
+
160
+ this.mcpJsonInstalled = true;
161
+ } catch {
162
+ // Non-fatal: parent has MCP via --mcp-config, teammates fall back to PreToolUse hooks
163
+ }
164
+ }
165
+
166
+ /** Restore or remove .mcp.json after execution. */
167
+ uninstallBouncerForSubagents(): void {
168
+ if (!this.mcpJsonInstalled) return;
169
+ const mcpJsonPath = join(this.workingDir, '.mcp.json');
170
+ const backupPath = join(this.workingDir, '.mcp.json.pm-backup');
171
+
172
+ try {
173
+ if (this.savedMcpJson !== null) {
174
+ writeFileSync(mcpJsonPath, this.savedMcpJson);
175
+ } else {
176
+ unlinkSync(mcpJsonPath);
177
+ }
178
+ } catch {
179
+ // Best effort cleanup
180
+ }
181
+
182
+ try { if (existsSync(backupPath)) unlinkSync(backupPath); } catch { /* ok */ }
183
+
184
+ this.savedMcpJson = null;
185
+ this.mcpJsonInstalled = false;
186
+ }
187
+ }
@@ -84,7 +84,7 @@ function dfs(
84
84
  *
85
85
  * If epicScope is provided, only returns issues belonging to that epic.
86
86
  */
87
- export function resolveReadyToWork(issues: Issue[], epicScope?: string): Issue[] {
87
+ export function resolveReadyToWork(issues: Issue[], epicScope?: string, sprintScope?: string): Issue[] {
88
88
  const issueByPath = new Map<string, Issue>();
89
89
  for (const issue of issues) {
90
90
  issueByPath.set(issue.path, issue);
@@ -116,6 +116,9 @@ export function resolveReadyToWork(issues: Issue[], epicScope?: string): Issue[]
116
116
  // If scoped to an epic, only include that epic's children
117
117
  if (epicChildPaths && !epicChildPaths.has(issue.path)) return false;
118
118
 
119
+ // If scoped to a sprint, only include issues assigned to that sprint
120
+ if (sprintScope && issue.sprint !== sprintScope) return false;
121
+
119
122
  // Check all blockers are resolved
120
123
  if (issue.blockedBy.length > 0) {
121
124
  const allResolved = issue.blockedBy.every(bp => {