mstro-app 0.4.4 → 0.4.11

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 (80) hide show
  1. package/dist/server/server-setup.js +1 -1
  2. package/dist/server/server-setup.js.map +1 -1
  3. package/dist/server/services/auth.d.ts.map +1 -1
  4. package/dist/server/services/auth.js +4 -2
  5. package/dist/server/services/auth.js.map +1 -1
  6. package/dist/server/services/instances.js +1 -1
  7. package/dist/server/services/instances.js.map +1 -1
  8. package/dist/server/services/plan/config-installer.d.ts +5 -14
  9. package/dist/server/services/plan/config-installer.d.ts.map +1 -1
  10. package/dist/server/services/plan/config-installer.js +14 -72
  11. package/dist/server/services/plan/config-installer.js.map +1 -1
  12. package/dist/server/services/plan/executor.d.ts +15 -8
  13. package/dist/server/services/plan/executor.d.ts.map +1 -1
  14. package/dist/server/services/plan/executor.js +95 -59
  15. package/dist/server/services/plan/executor.js.map +1 -1
  16. package/dist/server/services/plan/issue-prompt-builder.d.ts +17 -0
  17. package/dist/server/services/plan/issue-prompt-builder.d.ts.map +1 -0
  18. package/dist/server/services/plan/issue-prompt-builder.js +73 -0
  19. package/dist/server/services/plan/issue-prompt-builder.js.map +1 -0
  20. package/dist/server/services/plan/parser-core.d.ts.map +1 -1
  21. package/dist/server/services/plan/parser-core.js +9 -0
  22. package/dist/server/services/plan/parser-core.js.map +1 -1
  23. package/dist/server/services/plan/types.d.ts +2 -0
  24. package/dist/server/services/plan/types.d.ts.map +1 -1
  25. package/dist/server/services/platform.d.ts +1 -0
  26. package/dist/server/services/platform.d.ts.map +1 -1
  27. package/dist/server/services/platform.js +3 -7
  28. package/dist/server/services/platform.js.map +1 -1
  29. package/dist/server/services/websocket/file-explorer-handlers.d.ts.map +1 -1
  30. package/dist/server/services/websocket/file-explorer-handlers.js +5 -4
  31. package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -1
  32. package/dist/server/services/websocket/git-handlers.js +2 -2
  33. package/dist/server/services/websocket/git-handlers.js.map +1 -1
  34. package/dist/server/services/websocket/git-pr-handlers.d.ts +1 -1
  35. package/dist/server/services/websocket/git-pr-handlers.d.ts.map +1 -1
  36. package/dist/server/services/websocket/git-pr-handlers.js +2 -2
  37. package/dist/server/services/websocket/git-pr-handlers.js.map +1 -1
  38. package/dist/server/services/websocket/handler.d.ts.map +1 -1
  39. package/dist/server/services/websocket/handler.js +12 -0
  40. package/dist/server/services/websocket/handler.js.map +1 -1
  41. package/dist/server/services/websocket/quality-complexity.d.ts.map +1 -1
  42. package/dist/server/services/websocket/quality-complexity.js +5 -7
  43. package/dist/server/services/websocket/quality-complexity.js.map +1 -1
  44. package/dist/server/services/websocket/quality-linting.d.ts +1 -1
  45. package/dist/server/services/websocket/quality-linting.d.ts.map +1 -1
  46. package/dist/server/services/websocket/quality-linting.js +16 -11
  47. package/dist/server/services/websocket/quality-linting.js.map +1 -1
  48. package/dist/server/services/websocket/quality-review-agent.d.ts +14 -3
  49. package/dist/server/services/websocket/quality-review-agent.d.ts.map +1 -1
  50. package/dist/server/services/websocket/quality-review-agent.js +87 -23
  51. package/dist/server/services/websocket/quality-review-agent.js.map +1 -1
  52. package/dist/server/services/websocket/quality-service.d.ts.map +1 -1
  53. package/dist/server/services/websocket/quality-service.js +62 -39
  54. package/dist/server/services/websocket/quality-service.js.map +1 -1
  55. package/dist/server/services/websocket/quality-types.d.ts +2 -0
  56. package/dist/server/services/websocket/quality-types.d.ts.map +1 -1
  57. package/dist/server/services/websocket/quality-types.js.map +1 -1
  58. package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
  59. package/dist/server/services/websocket/session-handlers.js +3 -0
  60. package/dist/server/services/websocket/session-handlers.js.map +1 -1
  61. package/package.json +1 -1
  62. package/server/server-setup.ts +1 -1
  63. package/server/services/auth.ts +3 -2
  64. package/server/services/instances.ts +1 -1
  65. package/server/services/plan/config-installer.ts +13 -72
  66. package/server/services/plan/executor.ts +105 -61
  67. package/server/services/plan/issue-prompt-builder.ts +92 -0
  68. package/server/services/plan/parser-core.ts +8 -0
  69. package/server/services/plan/types.ts +2 -0
  70. package/server/services/platform.ts +3 -8
  71. package/server/services/websocket/file-explorer-handlers.ts +7 -3
  72. package/server/services/websocket/git-handlers.ts +3 -3
  73. package/server/services/websocket/git-pr-handlers.ts +3 -3
  74. package/server/services/websocket/handler.ts +12 -0
  75. package/server/services/websocket/quality-complexity.ts +5 -7
  76. package/server/services/websocket/quality-linting.ts +17 -10
  77. package/server/services/websocket/quality-review-agent.ts +95 -23
  78. package/server/services/websocket/quality-service.ts +70 -39
  79. package/server/services/websocket/quality-types.ts +2 -0
  80. package/server/services/websocket/session-handlers.ts +3 -0
@@ -1 +1 @@
1
- {"version":3,"file":"session-handlers.d.ts","sourceRoot":"","sources":["../../../../server/services/websocket/session-handlers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAkB,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AAE9G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AA+ErF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,2BAA2B,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAGvG;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CA4DnI;AAyBD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CA+CpJ"}
1
+ {"version":3,"file":"session-handlers.d.ts","sourceRoot":"","sources":["../../../../server/services/websocket/session-handlers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAkB,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AAE9G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AA+ErF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,2BAA2B,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAGvG;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CA4DnI;AAyBD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAkDpJ"}
@@ -173,7 +173,10 @@ export function handleSessionMessage(ctx, ws, msg, tabId, permission) {
173
173
  }
174
174
  case 'new': {
175
175
  const oldSession = requireSession(ctx, ws, tabId);
176
+ const oldSessionId = oldSession.getSessionInfo().sessionId;
176
177
  const newSession = oldSession.startNewSession({ model: getModel() });
178
+ oldSession.destroy();
179
+ ctx.sessions.delete(oldSessionId);
177
180
  setupSessionListeners(ctx, newSession, ws, tabId);
178
181
  const newSessionId = newSession.getSessionInfo().sessionId;
179
182
  ctx.sessions.set(newSessionId, newSession);
@@ -1 +1 @@
1
- {"version":3,"file":"session-handlers.js","sourceRoot":"","sources":["../../../../server/services/websocket/session-handlers.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAGhE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,8DAA8D;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAErF,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;AAEjF,SAAS,iBAAiB,CAAC,QAAiC;IAC1D,MAAM,OAAO,GAAG,QAAQ,CAAC,cAA6F,CAAC;IACvH,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AACvG,CAAC;AAED,SAAS,6BAA6B,CAAC,GAAmB,EAAE,UAAkB;IAC5E,cAAc,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QAC1C,GAAG,CAAC,cAAc,CAAC;YACjB,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE;SAC7B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;QACZ,sDAAsD;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,oEAAoE;AACpE,SAAS,yBAAyB,CAAC,KAA2G,EAAE,EAAU;IACxJ,MAAM,KAAK,GAAmC,EAAE,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QACrH,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,IAAI,WAAW,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QACvJ,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,0EAA0E;AAC1E,SAAS,sBAAsB,CAAC,QAA8R;IAC5T,MAAM,KAAK,GAAmC,EAAE,CAAC;IACjD,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IAElD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IAEvE,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,cAAc,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,GAAG,yBAAyB,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,QAAQ,CAAC,iBAAiB,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,CAAC,iBAAiB,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,QAAQ,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU;QACtC,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAC5D,CAAC,CAAC,WAAW,CAAC;IAChB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IAClE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CAAC,GAAmB,EAAE,EAAa,EAAE,KAAa;IACvE,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,EAAE,CAAC,CAAC;IACnE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,UAAU,CAAC,GAAmB,EAAE,EAAa,EAAE,KAAa;IACnE,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAE5B,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAoC;IACrE,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IACrC,OAAO,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAmB,EAAE,OAAoC,EAAE,EAAa,EAAE,KAAa;IAC3H,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAE7B,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,IAAY,EAAE,EAAE;QACtC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,IAAY,EAAE,EAAE;QACxC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,cAAsB,EAAE,MAAc,EAAE,EAAE;QACvE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,uBAAuB,EAAE,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;QAClK,GAAG,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;IAChJ,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,QAAiC,EAAE,EAAE;QACrE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAElE,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACrC,4FAA4F;QAC5F,IAAI,CAAC;YAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAE/D,GAAG,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,qBAAqB,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAElH,IAAI,GAAG,CAAC,aAAa,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YAC7C,GAAG,CAAC,aAAa,CAAC;gBAChB,UAAU,EAAE,QAAQ,CAAC,UAAoB;gBACzC,SAAS,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,SAAS;gBAC7C,UAAU,EAAE,GAAG,QAAQ,CAAC,cAAc,EAAE;aACzC,CAAC,CAAC;QACL,CAAC;QAED,wEAAwE;QACxE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC;YACrF,6BAA6B,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,KAAY,EAAE,EAAE;QAC7C,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACjF,GAAG,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,OAAgC,EAAE,EAAE;QACjE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,IAA6B,EAAE,EAAE;QACtE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,KAA8B,EAAE,EAAE;QACzD,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,KAAoD,EAAE,EAAE;QAClF,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iFAAiF;AACjF,SAAS,2BAA2B,CAAC,GAAmB,EAAE,KAAa,EAAE,iBAAoC;IAC3G,IAAI,CAAC,GAAG,CAAC,iBAAiB;QAAE,OAAO,iBAAiB,CAAC;IACrD,MAAM,WAAW,GAAG,GAAG,CAAC,iBAAiB,CAAC,2BAA2B,CAAC,KAAK,CAAC,CAAC;IAC7E,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,iBAAiB,CAAC;IAEvD,MAAM,MAAM,GAAoD,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/F,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzE,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,OAAO,EAAE,EAAE;gBACX,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAmB,EAAE,EAAa,EAAE,GAAqB,EAAE,KAAa,EAAE,UAA+B;IAC5I,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;YAC7D,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YAC/C,MAAM,SAAS,GAAG,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,MAAM,CAAC;YACpE,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAClD,MAAM,WAAW,GAAG,2BAA2B,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAClF,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;YAC5F,MAAM;QACR,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YAC/C,OAAO,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM;QACR,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACrE,MAAM;QACR,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,UAAU,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;YACrE,qBAAqB,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YAClD,MAAM,YAAY,GAAG,UAAU,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC;YAC3D,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACvC,IAAI,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;YAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;YACrC,IAAI,CAAC;gBAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YAC9E,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;YAC/E,MAAM;QACR,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YAC/C,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAChC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,4CAA4C,EAAE,EAAE,CAAC,CAAC;YACtG,MAAM;QACR,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YAC/C,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACjC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,uCAAuC,EAAE,EAAE,CAAC,CAAC;YACjG,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"session-handlers.js","sourceRoot":"","sources":["../../../../server/services/websocket/session-handlers.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mstro-app",
3
- "version": "0.4.4",
3
+ "version": "0.4.11",
4
4
  "description": "Run Claude Code from any browser - streams live sessions from your machine to mstro.app",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -81,7 +81,7 @@ export function wrapWebSocket(ws: NodeWebSocket, workingDir: string): WSContext
81
81
  return {
82
82
  send: (data: string | Buffer) => ws.send(data),
83
83
  close: () => ws.close(),
84
- readyState: ws.readyState,
84
+ get readyState() { return ws.readyState },
85
85
  _workingDir: workingDir,
86
86
  _ws: ws
87
87
  } as WSContext
@@ -9,7 +9,7 @@
9
9
  * The token is created once (by `mstro login` or first server start) and reused.
10
10
  */
11
11
 
12
- import { randomBytes } from 'node:crypto'
12
+ import { randomBytes, timingSafeEqual } from 'node:crypto'
13
13
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
14
14
  import { homedir } from 'node:os'
15
15
  import { join } from 'node:path'
@@ -53,7 +53,8 @@ export class AuthService {
53
53
  * Validate the local session token (used for localhost API/WS auth)
54
54
  */
55
55
  validateLocalToken(token: string): boolean {
56
- return token === this.localToken
56
+ if (token.length !== this.localToken.length) return false
57
+ return timingSafeEqual(Buffer.from(token), Buffer.from(this.localToken))
57
58
  }
58
59
 
59
60
  /**
@@ -81,7 +81,7 @@ export class InstanceRegistry {
81
81
  */
82
82
  register(port: number, workingDirectory: string): MstroInstance {
83
83
  const instance: MstroInstance = {
84
- id: `mstro-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
84
+ id: `mstro-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
85
85
  port,
86
86
  url: `http://localhost:${port}`,
87
87
  workingDirectory,
@@ -2,17 +2,17 @@
2
2
  // Licensed under the MIT License. See LICENSE file for details.
3
3
 
4
4
  /**
5
- * Config Installer — Manages temporary config file modifications for Agent Teams.
5
+ * Config Installer — Manages temporary .claude/settings.json modifications
6
+ * for headless execution.
6
7
  *
7
- * Installs teammate permissions in .claude/settings.json and bouncer MCP config
8
- * in .mcp.json before wave execution, then restores originals afterward.
8
+ * Pre-approves tools so headless Claude Code instances can work without
9
+ * interactive permission prompts, then restores the original settings afterward.
9
10
  */
10
11
 
11
12
  import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
12
13
  import { join } from 'node:path';
13
- import { generateMcpConfig } from '../../cli/headless/mcp-config.js';
14
14
 
15
- /** Tools that teammates may need during execution */
15
+ /** Tools that headless instances may need during execution */
16
16
  const REQUIRED_PERMISSIONS = [
17
17
  'Bash',
18
18
  'Read',
@@ -22,7 +22,6 @@ const REQUIRED_PERMISSIONS = [
22
22
  'Grep',
23
23
  'WebFetch',
24
24
  'WebSearch',
25
- 'Agent',
26
25
  ];
27
26
 
28
27
  /** Restore a file from a .pm-backup, handling the __NONE__ sentinel for files that didn't exist. */
@@ -42,20 +41,19 @@ function restoreFromBackup(backupPath: string, targetPath: string): void {
42
41
  export class ConfigInstaller {
43
42
  private savedClaudeSettings: string | null = null;
44
43
  private claudeSettingsInstalled = false;
45
- private savedMcpJson: string | null = null;
46
- private mcpJsonInstalled = false;
47
44
 
48
45
  constructor(private workingDir: string) {
49
46
  // Recover from prior crash: if backup files exist, restore them
50
47
  this.recoverFromCrash();
51
48
  }
52
49
 
53
- /** Restore .claude/settings.json and .mcp.json from backups left by a previous crash. */
50
+ /** Restore .claude/settings.json from backups left by a previous crash. */
54
51
  private recoverFromCrash(): void {
55
52
  restoreFromBackup(
56
53
  join(this.workingDir, '.claude', 'settings.json.pm-backup'),
57
54
  join(this.workingDir, '.claude', 'settings.json'),
58
55
  );
56
+ // Legacy: clean up .mcp.json backup from previous Agent Teams implementation
59
57
  restoreFromBackup(
60
58
  join(this.workingDir, '.mcp.json.pm-backup'),
61
59
  join(this.workingDir, '.mcp.json'),
@@ -63,10 +61,11 @@ export class ConfigInstaller {
63
61
  }
64
62
 
65
63
  /**
66
- * Pre-approve tools in .claude/settings.json so Agent Teams
67
- * teammates can work without interactive permission prompts.
64
+ * Pre-approve tools in .claude/settings.json so headless instances
65
+ * can work without interactive permission prompts.
68
66
  */
69
- installTeammatePermissions(): void {
67
+ installPermissions(): void {
68
+ if (this.claudeSettingsInstalled) return;
70
69
  const claudeDir = join(this.workingDir, '.claude');
71
70
  const settingsPath = join(claudeDir, 'settings.json');
72
71
 
@@ -100,12 +99,12 @@ export class ConfigInstaller {
100
99
  }
101
100
  this.claudeSettingsInstalled = true;
102
101
  } catch {
103
- // Non-fatal — teammates may hit permission prompts
102
+ // Non-fatal — headless instances may hit permission prompts
104
103
  }
105
104
  }
106
105
 
107
106
  /** Restore original .claude/settings.json after wave execution. */
108
- uninstallTeammatePermissions(): void {
107
+ uninstallPermissions(): void {
109
108
  if (!this.claudeSettingsInstalled) return;
110
109
  const settingsPath = join(this.workingDir, '.claude', 'settings.json');
111
110
  const backupPath = join(this.workingDir, '.claude', 'settings.json.pm-backup');
@@ -126,62 +125,4 @@ export class ConfigInstaller {
126
125
  this.savedClaudeSettings = null;
127
126
  this.claudeSettingsInstalled = false;
128
127
  }
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
128
  }
@@ -2,17 +2,18 @@
2
2
  // Licensed under the MIT License. See LICENSE file for details.
3
3
 
4
4
  /**
5
- * Plan Executor — Wave-based execution with Claude Code Agent Teams.
5
+ * Plan Executor — Wave-based execution with parallel headless Claude Code instances.
6
6
  *
7
- * Orchestrates the execution loop: picks ready issues, executes waves,
8
- * runs AI review gate, reconciles state, and repeats.
7
+ * Orchestrates the execution loop: picks ready issues, executes waves of
8
+ * parallel headless runners (one per issue), runs AI review gate,
9
+ * reconciles state, and repeats.
9
10
  *
10
11
  * Implementation is split across focused modules:
11
- * - config-installer.ts teammate permissions + bouncer MCP install/uninstall
12
- * - prompt-builder.ts Agent Teams coordinator prompt construction
13
- * - output-manager.ts — output path resolution, listing, publishing
14
- * - review-gate.ts — AI-powered quality gate (review, parse, persist)
15
- * - front-matter.ts — YAML front matter field editing utility
12
+ * - config-installer.ts tool permissions install/uninstall
13
+ * - issue-prompt-builder.ts per-issue prompt construction
14
+ * - output-manager.ts — output path resolution, listing, publishing
15
+ * - review-gate.ts — AI-powered quality gate (review, parse, persist)
16
+ * - front-matter.ts — YAML front matter field editing utility
16
17
  */
17
18
 
18
19
  import { EventEmitter } from 'node:events';
@@ -23,26 +24,26 @@ import { HeadlessRunner } from '../../cli/headless/index.js';
23
24
  import { ConfigInstaller } from './config-installer.js';
24
25
  import { resolveReadyToWork } from './dependency-resolver.js';
25
26
  import { replaceFrontMatterField, setFrontMatterField } from './front-matter.js';
27
+ import { buildIssuePrompt } from './issue-prompt-builder.js';
26
28
  import { listExistingDocs, publishOutputs, resolveOutputPath } from './output-manager.js';
27
29
  import { parseBoardDirectory, parsePlanDirectory, resolvePmDir } from './parser.js';
28
- import { buildCoordinatorPrompt } from './prompt-builder.js';
29
30
  import { appendReviewFeedback, getReviewAttemptCount, MAX_REVIEW_ATTEMPTS, persistReviewResult, reviewIssue } from './review-gate.js';
30
31
  import { reconcileState } from './state-reconciler.js';
31
32
  import type { Issue } from './types.js';
32
33
 
33
34
  export type ExecutionStatus = 'idle' | 'starting' | 'executing' | 'paused' | 'stopping' | 'complete' | 'error';
34
35
 
35
- /** Max teammates per wave. Agent Teams docs recommend 3-5; beyond 5-6 returns diminish. */
36
- const MAX_WAVE_SIZE = 5;
36
+ /** Default max parallel agents when board doesn't specify. */
37
+ const DEFAULT_MAX_PARALLEL_AGENTS = 3;
37
38
 
38
39
  /** Stop after this many consecutive waves with zero completions. */
39
40
  const MAX_CONSECUTIVE_EMPTY_WAVES = 3;
40
41
 
41
- /** Wave execution stall timeouts (ms) */
42
- const WAVE_STALL_WARNING_MS = 1_800_000; // 30 min — Agent Teams leads are silent while teammates work
43
- const WAVE_STALL_KILL_MS = 3_600_000; // 60 min — waves run longer
44
- const WAVE_STALL_HARD_CAP_MS = 7_200_000; // 2 hr hard cap
45
- const WAVE_STALL_MAX_EXTENSIONS = 10;
42
+ /** Per-issue stall timeouts (ms) — shorter than Agent Teams wave timeouts */
43
+ const ISSUE_STALL_WARNING_MS = 900_000; // 15 min
44
+ const ISSUE_STALL_KILL_MS = 1_800_000; // 30 min
45
+ const ISSUE_STALL_HARD_CAP_MS = 3_600_000; // 1 hr hard cap
46
+ const ISSUE_STALL_MAX_EXTENSIONS = 10;
46
47
 
47
48
  export interface ExecutionMetrics {
48
49
  issuesCompleted: number;
@@ -59,6 +60,8 @@ export class PlanExecutor extends EventEmitter {
59
60
  private shouldStop = false;
60
61
  private shouldPause = false;
61
62
  private epicScope: string | null = null;
63
+ /** Cached PM directory path — resolved once per start(). */
64
+ private pmDir: string | null = null;
62
65
  /** Board directory path (e.g. /path/.pm/boards/BOARD-001). Used for outputs, reviews, progress. */
63
66
  private boardDir: string | null = null;
64
67
  /** Board ID being executed (e.g. "BOARD-001") */
@@ -114,6 +117,7 @@ export class PlanExecutor extends EventEmitter {
114
117
  this.status = 'executing';
115
118
  this.emit('statusChanged', this.status);
116
119
 
120
+ this.pmDir = resolvePmDir(this.workingDir);
117
121
  this.boardDir = this.resolveBoardDir();
118
122
 
119
123
  const stallResult = await this.runWaveLoop();
@@ -136,12 +140,13 @@ export class PlanExecutor extends EventEmitter {
136
140
  /** Run waves until done, paused, stopped, or stalled. Returns 'stalled' if zero-completion cap hit. */
137
141
  private async runWaveLoop(): Promise<'done' | 'stalled'> {
138
142
  let consecutiveZeroCompletions = 0;
143
+ const maxParallel = this.getBoardMaxParallelAgents();
139
144
 
140
145
  while (!this.shouldStop && !this.shouldPause) {
141
146
  const readyIssues = this.pickReadyIssues();
142
147
  if (readyIssues.length === 0) break;
143
148
 
144
- const completedCount = await this.executeWave(readyIssues.slice(0, MAX_WAVE_SIZE));
149
+ const completedCount = await this.executeWave(readyIssues.slice(0, maxParallel));
145
150
 
146
151
  if (completedCount > 0) {
147
152
  consecutiveZeroCompletions = 0;
@@ -175,50 +180,31 @@ export class PlanExecutor extends EventEmitter {
175
180
  this.emit('waveStarted', { issueIds: waveIds });
176
181
 
177
182
  this.ensureOutputDirs();
178
- this.configInstaller.installTeammatePermissions();
179
- this.configInstaller.installBouncerForSubagents();
183
+ this.configInstaller.installPermissions();
180
184
 
181
185
  for (const issue of issues) {
182
186
  this.updateIssueFrontMatter(issue.path, 'in_progress');
183
187
  }
184
188
 
185
189
  const existingDocs = listExistingDocs(this.workingDir, this.boardDir);
186
- const pmDir = resolvePmDir(this.workingDir);
187
- const prompt = buildCoordinatorPrompt({
188
- issues,
189
- workingDir: this.workingDir,
190
- pmDir,
191
- boardDir: this.boardDir,
192
- existingDocs,
193
- resolveOutputPath: (issue) => resolveOutputPath(issue, this.workingDir, this.boardDir),
194
- });
190
+ const pmDir = this.pmDir;
195
191
 
196
192
  let completedCount = 0;
197
193
 
198
194
  try {
199
- const runner = new HeadlessRunner({
200
- workingDir: this.workingDir,
201
- directPrompt: prompt,
202
- stallWarningMs: WAVE_STALL_WARNING_MS,
203
- stallKillMs: WAVE_STALL_KILL_MS,
204
- stallHardCapMs: WAVE_STALL_HARD_CAP_MS,
205
- stallMaxExtensions: WAVE_STALL_MAX_EXTENSIONS,
206
- verbose: process.env.MSTRO_VERBOSE === '1',
207
- disallowedTools: ['TeamCreate', 'TeamDelete', 'TaskCreate', 'TaskUpdate', 'TaskList'],
208
- extraEnv: { CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: '1' },
209
- outputCallback: (text: string) => {
210
- this.emit('output', { issueId: waveLabel, text });
211
- },
212
- });
213
-
214
- const boardLogDir = this.boardDir ? join(this.boardDir, 'logs') : undefined;
215
- const result = await runWithFileLogger('pm-execute-wave', () => runner.run(), boardLogDir);
216
-
217
- if (!result.completed || result.error) {
218
- this.emit('waveError', {
219
- issueIds: waveIds,
220
- error: result.error || 'Wave did not complete successfully',
221
- });
195
+ // Spawn one HeadlessRunner per issue in parallel
196
+ const runnerPromises = issues.map(issue => this.runSingleIssue(issue, pmDir, existingDocs, waveLabel));
197
+ const results = await Promise.allSettled(runnerPromises);
198
+
199
+ // Log any rejected promises
200
+ for (let i = 0; i < results.length; i++) {
201
+ const result = results[i];
202
+ if (result.status === 'rejected') {
203
+ this.emit('issueError', {
204
+ issueId: issues[i].id,
205
+ error: result.reason instanceof Error ? result.reason.message : String(result.reason),
206
+ });
207
+ }
222
208
  }
223
209
 
224
210
  completedCount = await this.reconcileWaveResults(issues);
@@ -229,8 +215,7 @@ export class PlanExecutor extends EventEmitter {
229
215
  });
230
216
  this.revertIncompleteIssues(issues);
231
217
  } finally {
232
- this.configInstaller.uninstallBouncerForSubagents();
233
- this.configInstaller.uninstallTeammatePermissions();
218
+ this.configInstaller.uninstallPermissions();
234
219
  }
235
220
 
236
221
  this.finalizeWave(issues, waveStart, waveLabel);
@@ -238,6 +223,44 @@ export class PlanExecutor extends EventEmitter {
238
223
  return completedCount;
239
224
  }
240
225
 
226
+ /** Run a single issue via its own headless Claude Code instance. */
227
+ private async runSingleIssue(
228
+ issue: Issue,
229
+ pmDir: string | null,
230
+ existingDocs: string[],
231
+ waveLabel: string,
232
+ ): Promise<void> {
233
+ const outputPath = resolveOutputPath(issue, this.workingDir, this.boardDir);
234
+ const prompt = buildIssuePrompt({
235
+ issue,
236
+ workingDir: this.workingDir,
237
+ pmDir,
238
+ boardDir: this.boardDir,
239
+ existingDocs,
240
+ outputPath,
241
+ });
242
+
243
+ const runner = new HeadlessRunner({
244
+ workingDir: this.workingDir,
245
+ directPrompt: prompt,
246
+ stallWarningMs: ISSUE_STALL_WARNING_MS,
247
+ stallKillMs: ISSUE_STALL_KILL_MS,
248
+ stallHardCapMs: ISSUE_STALL_HARD_CAP_MS,
249
+ stallMaxExtensions: ISSUE_STALL_MAX_EXTENSIONS,
250
+ verbose: process.env.MSTRO_VERBOSE === '1',
251
+ outputCallback: (text: string) => {
252
+ this.emit('output', { issueId: issue.id, text });
253
+ },
254
+ });
255
+
256
+ const boardLogDir = this.boardDir ? join(this.boardDir, 'logs') : undefined;
257
+ const result = await runWithFileLogger(`pm-issue-${issue.id}`, () => runner.run(), boardLogDir);
258
+
259
+ if (!result.completed || result.error) {
260
+ this.emit('output', { issueId: waveLabel, text: `Issue ${issue.id}: ${result.error || 'did not complete'}` });
261
+ }
262
+ }
263
+
241
264
  /**
242
265
  * Post-wave operations wrapped individually so a failure in one
243
266
  * doesn't prevent the others or kill the while loop in start().
@@ -282,7 +305,7 @@ export class PlanExecutor extends EventEmitter {
282
305
  * and either confirmed `done` (passed) or reverted to `todo` (failed).
283
306
  */
284
307
  private async reconcileWaveResults(issues: Issue[]): Promise<number> {
285
- const pmDir = resolvePmDir(this.workingDir);
308
+ const pmDir = this.pmDir;
286
309
  if (!pmDir) return 0;
287
310
 
288
311
  let completed = 0;
@@ -363,8 +386,29 @@ export class PlanExecutor extends EventEmitter {
363
386
 
364
387
  // ── Helpers ──────────────────────────────────────────────────
365
388
 
389
+ /** Read the board's maxParallelAgents setting, falling back to default. */
390
+ private getBoardMaxParallelAgents(): number {
391
+ const pmDir = this.pmDir;
392
+ if (!pmDir) return DEFAULT_MAX_PARALLEL_AGENTS;
393
+
394
+ const effectiveBoardId = this.boardId ?? this.resolveActiveBoardId();
395
+ if (!effectiveBoardId) return DEFAULT_MAX_PARALLEL_AGENTS;
396
+
397
+ // Read only board.md — avoids parsing STATE.md and all backlog issues just for one setting
398
+ const boardMdPath = join(pmDir, 'boards', effectiveBoardId, 'board.md');
399
+ if (!existsSync(boardMdPath)) return DEFAULT_MAX_PARALLEL_AGENTS;
400
+
401
+ try {
402
+ const content = readFileSync(boardMdPath, 'utf-8');
403
+ const match = content.match(/^max_parallel_agents:\s*(\d+)/m);
404
+ return match ? Math.max(1, Math.min(Number(match[1]), 10)) : DEFAULT_MAX_PARALLEL_AGENTS;
405
+ } catch {
406
+ return DEFAULT_MAX_PARALLEL_AGENTS;
407
+ }
408
+ }
409
+
366
410
  private pickReadyIssues(): Issue[] {
367
- const pmDir = resolvePmDir(this.workingDir);
411
+ const pmDir = this.pmDir;
368
412
  if (!pmDir) {
369
413
  this.emit('error', 'No PM directory found');
370
414
  return [];
@@ -448,7 +492,7 @@ export class PlanExecutor extends EventEmitter {
448
492
  }
449
493
 
450
494
  private resolveActiveBoardId(): string | null {
451
- const pmDir = resolvePmDir(this.workingDir);
495
+ const pmDir = this.pmDir;
452
496
  if (!pmDir) return null;
453
497
  try {
454
498
  const workspacePath = join(pmDir, 'workspace.json');
@@ -461,7 +505,7 @@ export class PlanExecutor extends EventEmitter {
461
505
  }
462
506
 
463
507
  private revertIncompleteIssues(issues: Issue[]): void {
464
- const pmDir = resolvePmDir(this.workingDir);
508
+ const pmDir = this.pmDir;
465
509
  if (!pmDir) return;
466
510
  for (const issue of issues) {
467
511
  const fullPath = join(pmDir, issue.path);
@@ -475,7 +519,7 @@ export class PlanExecutor extends EventEmitter {
475
519
  }
476
520
 
477
521
  private updateIssueFrontMatter(issuePath: string, newStatus: string): void {
478
- const pmDir = resolvePmDir(this.workingDir);
522
+ const pmDir = this.pmDir;
479
523
  if (!pmDir) return;
480
524
  try {
481
525
  setFrontMatterField(join(pmDir, issuePath), 'status', newStatus);
@@ -487,7 +531,7 @@ export class PlanExecutor extends EventEmitter {
487
531
  const boardOutDir = join(this.boardDir, 'out');
488
532
  if (!existsSync(boardOutDir)) mkdirSync(boardOutDir, { recursive: true });
489
533
  } else {
490
- const pmDir = resolvePmDir(this.workingDir);
534
+ const pmDir = this.pmDir;
491
535
  if (pmDir) {
492
536
  const outDir = join(pmDir, 'out');
493
537
  if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
@@ -496,7 +540,7 @@ export class PlanExecutor extends EventEmitter {
496
540
  }
497
541
 
498
542
  private appendProgressEntry(issues: Issue[], waveStart: number): void {
499
- const pmDir = resolvePmDir(this.workingDir);
543
+ const pmDir = this.pmDir;
500
544
  if (!pmDir) return;
501
545
 
502
546
  // Board-scoped progress log
@@ -551,7 +595,7 @@ export class PlanExecutor extends EventEmitter {
551
595
 
552
596
  /** Resolve the active board's directory path for outputs, reviews, and progress. */
553
597
  private resolveBoardDir(): string | null {
554
- const pmDir = resolvePmDir(this.workingDir);
598
+ const pmDir = this.pmDir;
555
599
  if (!pmDir) return null;
556
600
 
557
601
  const effectiveBoardId = this.boardId ?? this.resolveActiveBoardId();
@@ -0,0 +1,92 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+
4
+ /**
5
+ * Issue Prompt Builder — Constructs a prompt for a single headless Claude Code instance.
6
+ *
7
+ * Each issue gets its own independent Claude Code session. No Agent Teams,
8
+ * no coordinator/teammate model — just one prompt per issue.
9
+ */
10
+
11
+ import { join } from 'node:path';
12
+ import type { Issue } from './types.js';
13
+
14
+ export interface IssuePromptOptions {
15
+ issue: Issue;
16
+ workingDir: string;
17
+ pmDir: string | null;
18
+ /** Board directory path (e.g. /path/.pm/boards/BOARD-001). */
19
+ boardDir: string | null;
20
+ existingDocs: string[];
21
+ outputPath: string;
22
+ }
23
+
24
+ /**
25
+ * Build a self-contained prompt for one issue.
26
+ * The resulting Claude Code session will work independently —
27
+ * read the issue spec, execute acceptance criteria, write output, update status.
28
+ */
29
+ export function buildIssuePrompt(options: IssuePromptOptions): string {
30
+ const { issue, workingDir, pmDir, boardDir, existingDocs, outputPath } = options;
31
+
32
+ const criteria = issue.acceptanceCriteria
33
+ .map(c => `- [${c.checked ? 'x' : ' '}] ${c.text}`)
34
+ .join('\n');
35
+
36
+ const files = issue.filesToModify.length > 0
37
+ ? `\n## Files to Modify\n${issue.filesToModify.map(f => `- ${f}`).join('\n')}`
38
+ : '';
39
+
40
+ const predecessorDocs = resolvePredecessorDocs(issue, existingDocs);
41
+ const predecessorSection = predecessorDocs.length > 0
42
+ ? `\n## Predecessor Outputs\nRead these before starting — they contain context from upstream issues:\n${predecessorDocs.map(d => `- ${d}`).join('\n')}`
43
+ : '';
44
+
45
+ const outDir = boardDir ? join(boardDir, 'out') : pmDir ? join(pmDir, 'out') : join(workingDir, '.mstro', 'pm', 'out');
46
+
47
+ return `You are executing issue ${issue.id}: ${issue.title}.
48
+
49
+ ## Project Directory
50
+ Working directory: ${workingDir}
51
+ Plan directory: ${pmDir || '.mstro/pm/'}
52
+
53
+ ## Issue Specification
54
+
55
+ **ID**: ${issue.id}
56
+ **Title**: ${issue.title}
57
+ **Type**: ${issue.type} | **Priority**: ${issue.priority} | **Estimate**: ${issue.estimate ?? 'unestimated'}
58
+
59
+ ### Description
60
+ ${issue.description}
61
+
62
+ ### Acceptance Criteria
63
+ ${criteria || 'No specific criteria defined.'}
64
+
65
+ ### Technical Notes
66
+ ${issue.technicalNotes || 'None'}
67
+ ${files}${predecessorSection}
68
+
69
+ ## Your Task
70
+
71
+ 1. Read the full issue spec at ${pmDir ? join(pmDir, issue.path) : issue.path}
72
+ 2. Execute all acceptance criteria listed above
73
+ 3. Write your output and results to **${outputPath}** — this is the handoff artifact for downstream issues
74
+ 4. After writing output, update the issue front matter: change \`status: in_progress\` to \`status: done\`
75
+
76
+ ## Rules
77
+
78
+ - Stay within this issue's scope. Do not modify files outside your assigned scope.
79
+ - The orchestrator manages STATE.md separately — do not edit STATE.md.
80
+ - Write all significant output to ${outDir}/ so downstream issues can reference it.
81
+ - If you cannot complete the issue, leave status as \`in_progress\` and document what blocked you in the output file.`;
82
+ }
83
+
84
+ /** Find predecessor output docs based on blockedBy dependencies. */
85
+ function resolvePredecessorDocs(issue: Issue, existingDocs: string[]): string[] {
86
+ return issue.blockedBy
87
+ .map(bp => {
88
+ const blockerId = bp.replace(/^backlog\//, '').replace(/\.md$/, '');
89
+ return existingDocs.find(d => d.toLowerCase().includes(blockerId.toLowerCase()));
90
+ })
91
+ .filter(Boolean) as string[];
92
+ }