specrails-desktop 2.36.0 → 2.42.2

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 (510) hide show
  1. package/README.md +94 -247
  2. package/client/dist/assets/ActivityFeedPage-DoEMumQS.js +1 -0
  3. package/client/dist/assets/AgentBrowserCapture-DIh4K0gh.js +1 -0
  4. package/client/dist/assets/AgentModeAnalyticsPane-mbq4WEoO.js +2 -0
  5. package/client/dist/assets/AgentModeCodePane-CKh7zuA4.js +2 -0
  6. package/client/dist/assets/AgentModeJobsPane-BDokPiLJ.js +1 -0
  7. package/client/dist/assets/AgentsPage-BFVAZbBj.js +87 -0
  8. package/client/dist/assets/AnalyticsPage-3Y9LuWwz.js +1 -0
  9. package/client/dist/assets/CodePage-C9KyuV_C.js +3 -0
  10. package/client/dist/assets/DesktopAnalyticsPage-Bhi54bXQ.js +1 -0
  11. package/client/dist/assets/{DocsDialog-C76VdBJC.js → DocsDialog-Dj6mt4ga.js} +2 -2
  12. package/client/dist/assets/{DocsPage-ziMlj6B6.js → DocsPage-24yWglNI.js} +1 -1
  13. package/client/dist/assets/ExportDropdown-ophapHrT.js +1 -0
  14. package/client/dist/assets/InteractiveJobComposer-C1ucmxQh.js +19 -0
  15. package/client/dist/assets/JobDetailModal-DNWmgVHD.js +1 -0
  16. package/client/dist/assets/JobDetailPage-BcajZyuu.js +1 -0
  17. package/client/dist/assets/JobsPage-B9nTZw6e.js +1 -0
  18. package/client/dist/assets/LoopBuilderPage-Oc48iOFW.js +7 -0
  19. package/client/dist/assets/LoopPreviewModal-ae0Fr6SU.js +1 -0
  20. package/client/dist/assets/LoopsPage-CUEqzUBI.js +1 -0
  21. package/client/dist/assets/MinimizedChatsContext-Deg39peL.js +1 -0
  22. package/client/dist/assets/PluginsPage-C1xtARIx.js +2 -0
  23. package/client/dist/assets/ProjectSettingsDialog-JZzrXFBN.js +1 -0
  24. package/client/dist/assets/RepositoryDeliveries-CSDsiVUz.js +5 -0
  25. package/client/dist/assets/RepositoryScopeSelector-D-RCaknl.js +1 -0
  26. package/client/dist/assets/ReviewPacketPage-x5EfGTiL.js +1 -0
  27. package/client/dist/assets/TemplatePreviewModal-BSyuZxGq.js +1 -0
  28. package/client/dist/assets/TicketDetailModalContext-DqyF0so-.js +14 -0
  29. package/client/dist/assets/Trans-SnMX4MhW.js +1 -0
  30. package/client/dist/assets/agent-BdT0SB1D.js +1 -0
  31. package/client/dist/assets/agent-Bh9K7iEt.js +1 -0
  32. package/client/dist/assets/agent-C4ibdFk9.js +1 -0
  33. package/client/dist/assets/agent-CSFY22Zo.js +1 -0
  34. package/client/dist/assets/agent-DAnqxUn8.js +1 -0
  35. package/client/dist/assets/agent-DTQiu0Mi.js +1 -0
  36. package/client/dist/assets/agent-T54WuR_Y.js +1 -0
  37. package/client/dist/assets/agent-i75WDZOA.js +1 -0
  38. package/client/dist/assets/browser-05vRDg_y.js +1 -0
  39. package/client/dist/assets/browser-Bulb-cB1.js +1 -0
  40. package/client/dist/assets/browser-C7f-Jsg1.js +1 -0
  41. package/client/dist/assets/browser-CG0PE1j_.js +1 -0
  42. package/client/dist/assets/browser-CMzaqAjo.js +1 -0
  43. package/client/dist/assets/browser-DMajYdNX.js +1 -0
  44. package/client/dist/assets/browser-DxcOHrdP.js +1 -0
  45. package/client/dist/assets/browser-ObE7xVo3.js +1 -0
  46. package/client/dist/assets/builder-765NeYTp.js +1 -0
  47. package/client/dist/assets/builder-8MG3V6ea.js +1 -0
  48. package/client/dist/assets/builder-B-1UBs5K.js +1 -0
  49. package/client/dist/assets/builder-BTiGnPT0.js +1 -0
  50. package/client/dist/assets/builder-Cx9Rz-7u.js +1 -0
  51. package/client/dist/assets/builder-DKFMELBl.js +1 -0
  52. package/client/dist/assets/builder-OcmKrC0h.js +1 -0
  53. package/client/dist/assets/builder-P9qVBXFZ.js +1 -0
  54. package/client/dist/assets/{button-CJqFnUOL.js → button-DCBqEaZl.js} +1 -1
  55. package/client/dist/assets/{code-CkUuW4m9.js → code-B37GRg9C.js} +1 -1
  56. package/client/dist/assets/{code-B0O8-p8k.js → code-BBOEZbf9.js} +1 -1
  57. package/client/dist/assets/{code-B1VLZDhS.js → code-BRm-jcyx.js} +1 -1
  58. package/client/dist/assets/{code-Bpj4Ddml.js → code-CF7w62CR.js} +1 -1
  59. package/client/dist/assets/{code-BykBZ5-e.js → code-CLuvJt2r.js} +1 -1
  60. package/client/dist/assets/{code-B86IMAfz.js → code-D0RCm59f.js} +1 -1
  61. package/client/dist/assets/code-DaZ-ZwCT.js +1 -0
  62. package/client/dist/assets/{code-cAqaqMTx.js → code-iIHkGaCL.js} +1 -1
  63. package/client/dist/assets/commands-0XjAftla.js +1 -0
  64. package/client/dist/assets/commands-BAWSYHjQ.js +1 -0
  65. package/client/dist/assets/commands-BBwowgiE.js +1 -0
  66. package/client/dist/assets/commands-BacjIZLN.js +1 -0
  67. package/client/dist/assets/commands-Bs62IAZ3.js +1 -0
  68. package/client/dist/assets/commands-CLPdh-Hh.js +1 -0
  69. package/client/dist/assets/commands-DlbFzgrp.js +1 -0
  70. package/client/dist/assets/commands-LjPSsi5F.js +1 -0
  71. package/client/dist/assets/common-B5AZNYMH.js +1 -0
  72. package/client/dist/assets/common-BFZ0c_vN.js +1 -0
  73. package/client/dist/assets/common-BrlwEnL7.js +1 -0
  74. package/client/dist/assets/common-BttQx3z4.js +1 -0
  75. package/client/dist/assets/common-CM65k_-e.js +1 -0
  76. package/client/dist/assets/common-D4mvFFlu.js +1 -0
  77. package/client/dist/assets/common-TZ9Ny96S.js +1 -0
  78. package/client/dist/assets/common-nFpSF4GC.js +1 -0
  79. package/client/dist/assets/dashboard-B14uYXkG.js +1 -0
  80. package/client/dist/assets/dashboard-BK_mez-z.js +1 -0
  81. package/client/dist/assets/dashboard-BfBir_6o.js +1 -0
  82. package/client/dist/assets/dashboard-Bt0cCzeG.js +1 -0
  83. package/client/dist/assets/dashboard-BwkjxI6H.js +1 -0
  84. package/client/dist/assets/{dashboard-C8WOEiPu.js → dashboard-C3bDKf7s.js} +1 -1
  85. package/client/dist/assets/dashboard-CdvjGfog.js +1 -0
  86. package/client/dist/assets/dashboard-fRrP0Kv0.js +1 -0
  87. package/client/dist/assets/dialog-SRw01_QU.js +45 -0
  88. package/client/dist/assets/dist-js-CJ_2XX1Y.js +1 -0
  89. package/client/dist/assets/formatDistanceToNow-DSj5DprF.js +1 -0
  90. package/client/dist/assets/getTimezoneOffsetInMilliseconds-YhD8rIEs.js +1 -0
  91. package/client/dist/assets/index-DwAmL7m5.css +2 -0
  92. package/client/dist/assets/index-EzrkUb8B.js +76 -0
  93. package/client/dist/assets/{jira-api-B1-MUehg.js → jira-api-CSCqGr-Q.js} +1 -1
  94. package/client/dist/assets/{jobs-CN_zv4Gr.js → jobs-B8rrzfyZ.js} +1 -1
  95. package/client/dist/assets/{jobs-DUlWSYq2.js → jobs-BS6RTurf.js} +1 -1
  96. package/client/dist/assets/{jobs-Bpks6doU.js → jobs-BTT0Bsks.js} +1 -1
  97. package/client/dist/assets/{jobs-Bgq-PZkC.js → jobs-CezU69AE.js} +1 -1
  98. package/client/dist/assets/{jobs-SwYS2M-B.js → jobs-ClFJae0s.js} +1 -1
  99. package/client/dist/assets/{jobs-BAls3bWq.js → jobs-DJSFIFVy.js} +1 -1
  100. package/client/dist/assets/{jobs-DhxKgWFq.js → jobs-DhgGr8vm.js} +1 -1
  101. package/client/dist/assets/{jobs-B_TeSQxb.js → jobs-DzMjUcaN.js} +1 -1
  102. package/client/dist/assets/mcp-6rMoZfEO.js +1 -0
  103. package/client/dist/assets/mcp-BD8sL5mP.js +1 -0
  104. package/client/dist/assets/mcp-BkcA3I5s.js +1 -0
  105. package/client/dist/assets/mcp-CCpSelOh.js +1 -0
  106. package/client/dist/assets/mcp-CUAN6ORK.js +1 -0
  107. package/client/dist/assets/mcp-CqbRxRTE.js +1 -0
  108. package/client/dist/assets/mcp-DP2YfVhO.js +1 -0
  109. package/client/dist/assets/mcp-DUVQamDz.js +1 -0
  110. package/client/dist/assets/narration-B-ynWTpn.js +1 -0
  111. package/client/dist/assets/narration-Bj_laZwg.js +1 -0
  112. package/client/dist/assets/narration-BxHpmMv_.js +1 -0
  113. package/client/dist/assets/narration-C1Px0-0j.js +1 -0
  114. package/client/dist/assets/narration-CAXhGbzM.js +1 -0
  115. package/client/dist/assets/narration-DQ1l_Kq6.js +1 -0
  116. package/client/dist/assets/narration-XISXwqZd.js +1 -0
  117. package/client/dist/assets/narration-kwzfglQo.js +1 -0
  118. package/client/dist/assets/nav-1-Hh2kOz.js +1 -0
  119. package/client/dist/assets/nav-B34QkESm.js +1 -0
  120. package/client/dist/assets/nav-Bap_UXAq.js +1 -0
  121. package/client/dist/assets/{nav-pYuXq7sf.js → nav-BwxXIB24.js} +1 -1
  122. package/client/dist/assets/nav-Ch-zHBG5.js +1 -0
  123. package/client/dist/assets/nav-CygC_WN-.js +1 -0
  124. package/client/dist/assets/{nav-iwjCg5FR.js → nav-KnnLQtOQ.js} +1 -1
  125. package/client/dist/assets/nav-m00uxYUG.js +1 -0
  126. package/client/dist/assets/packet-BQ2tXfJI.js +1 -0
  127. package/client/dist/assets/packet-BdpOJ1Cy.js +1 -0
  128. package/client/dist/assets/packet-C3Ievb9R.js +1 -0
  129. package/client/dist/assets/packet-C4zJIG0Y.js +1 -0
  130. package/client/dist/assets/packet-Cx-zRuWn.js +1 -0
  131. package/client/dist/assets/packet-DUTGX52M.js +1 -0
  132. package/client/dist/assets/packet-DhsKtUPB.js +1 -0
  133. package/client/dist/assets/packet-z3LJ8Zyy.js +1 -0
  134. package/client/dist/assets/project-repositories-DYhTvwQ1.js +1 -0
  135. package/client/dist/assets/provider-capabilities-B-wOHfLP.js +1 -0
  136. package/client/dist/assets/settings-BBt2xtDQ.js +1 -0
  137. package/client/dist/assets/settings-BJB9RKJj.js +1 -0
  138. package/client/dist/assets/settings-CHwQR2rB.js +1 -0
  139. package/client/dist/assets/settings-CrMi3kSi.js +1 -0
  140. package/client/dist/assets/settings-DKyhDGD1.js +1 -0
  141. package/client/dist/assets/settings-Deupji9c.js +1 -0
  142. package/client/dist/assets/settings-DqRMmwAM.js +1 -0
  143. package/client/dist/assets/settings-J4rj6vo-.js +1 -0
  144. package/client/dist/assets/setup-2xGgu4Sk.js +1 -0
  145. package/client/dist/assets/setup-Ba11l2JA.js +1 -0
  146. package/client/dist/assets/setup-BzW4kMok.js +1 -0
  147. package/client/dist/assets/setup-COzwYhkJ.js +1 -0
  148. package/client/dist/assets/setup-CRVULhtF.js +1 -0
  149. package/client/dist/assets/setup-DgvlxwpE.js +1 -0
  150. package/client/dist/assets/setup-Dw_wYeEY.js +1 -0
  151. package/client/dist/assets/setup-ZPtEeJPW.js +1 -0
  152. package/client/dist/assets/spending-BqbdPm_4.js +1 -0
  153. package/client/dist/assets/square-Ci-PFcFe.js +1 -0
  154. package/client/dist/assets/{terminal-BFRZnMPP.js → terminal-BAzpHtpY.js} +1 -1
  155. package/client/dist/assets/{terminal-IahE4LW9.js → terminal-C7dHeR3x.js} +1 -1
  156. package/client/dist/assets/{terminal-tITa81iz.js → terminal-CMla5Qsz.js} +1 -1
  157. package/client/dist/assets/{terminal-BZiIu3rf.js → terminal-CdNXH-n9.js} +1 -1
  158. package/client/dist/assets/{terminal-ScjyXNxQ.js → terminal-Cw5bZsmV.js} +1 -1
  159. package/client/dist/assets/{terminal-C2NAd7BW.js → terminal-DFUP4eNv.js} +1 -1
  160. package/client/dist/assets/{terminal-d7GadXbN.js → terminal-DGqljeK_.js} +1 -1
  161. package/client/dist/assets/{terminal-QpXZU2Bn.js → terminal-cU70NodO.js} +1 -1
  162. package/client/dist/assets/useDesktop-RSMTyy7V.js +1 -0
  163. package/client/dist/assets/useSharedWebSocket-BOdS5_Iz.js +2 -0
  164. package/client/dist/index.html +34 -35
  165. package/docs/README.md +3 -0
  166. package/docs/agent-live-steering.md +57 -0
  167. package/docs/ci-cd.md +57 -0
  168. package/docs/code-explorer.md +48 -0
  169. package/docs/codex.md +12 -1
  170. package/docs/features/detachable-mission-windows.md +59 -0
  171. package/docs/guide/de/integrations/5-mcp-server.md +13 -9
  172. package/docs/guide/de/integrations/6-agent-chat.md +1 -0
  173. package/docs/guide/en/integrations/5-mcp-server.md +13 -9
  174. package/docs/guide/en/integrations/6-agent-chat.md +1 -0
  175. package/docs/guide/es/integrations/5-mcp-server.md +13 -9
  176. package/docs/guide/es/integrations/6-agent-chat.md +1 -0
  177. package/docs/guide/fr/integrations/5-mcp-server.md +13 -9
  178. package/docs/guide/fr/integrations/6-agent-chat.md +1 -0
  179. package/docs/guide/it/integrations/5-mcp-server.md +13 -9
  180. package/docs/guide/it/integrations/6-agent-chat.md +1 -0
  181. package/docs/guide/ja/integrations/5-mcp-server.md +13 -9
  182. package/docs/guide/ja/integrations/6-agent-chat.md +1 -0
  183. package/docs/guide/pt/integrations/5-mcp-server.md +13 -9
  184. package/docs/guide/pt/integrations/6-agent-chat.md +1 -0
  185. package/docs/guide/zh/integrations/5-mcp-server.md +13 -9
  186. package/docs/guide/zh/integrations/6-agent-chat.md +1 -0
  187. package/docs/internals/README.md +1 -0
  188. package/docs/internals/browser-capture-performance.md +55 -3
  189. package/docs/internals/browser-login-popups.md +45 -0
  190. package/docs/internals/browser-native-retina-audit.md +39 -0
  191. package/docs/internals/ci-cd-audit.md +39 -0
  192. package/docs/internals/core-runtime-updates.md +68 -0
  193. package/docs/internals/embedded-browser-native-webview-evaluation.md +2 -0
  194. package/docs/internals/implementation-reliability-audit.md +93 -0
  195. package/docs/internals/interactive-jobs.md +110 -6
  196. package/docs/internals/mcp-mission-audit.md +76 -0
  197. package/docs/internals/project-builder.md +404 -42
  198. package/docs/internals/safe-pr-review-flow.md +52 -10
  199. package/docs/internals/startup-recovery-audit.md +58 -0
  200. package/docs/mcp.md +74 -41
  201. package/docs/mission-processes.md +59 -0
  202. package/docs/multi-repo-projects.md +51 -0
  203. package/docs/platforms/windows-parity.md +70 -0
  204. package/docs/platforms/windows.md +13 -11
  205. package/docs/running-pipelines.md +14 -0
  206. package/mcp-bridge/dist/specrails-mcp.js +7186 -0
  207. package/package.json +9 -4
  208. package/server/dist/agent-chat-manager.js +537 -68
  209. package/server/dist/agent-chat-router.js +87 -6
  210. package/server/dist/agent-context-resolver.js +129 -25
  211. package/server/dist/agent-defaults.js +19 -11
  212. package/server/dist/agent-input-store.js +206 -0
  213. package/server/dist/agent-mcp-config.js +54 -15
  214. package/server/dist/agent-operator-prompt.js +255 -65
  215. package/server/dist/agent-spec-framing.js +202 -0
  216. package/server/dist/agent-steering.js +218 -0
  217. package/server/dist/agent-store.js +153 -0
  218. package/server/dist/api-not-found.js +8 -0
  219. package/server/dist/background-process-control.js +164 -0
  220. package/server/dist/background-process-service.js +61 -0
  221. package/server/dist/background-process-store.js +242 -0
  222. package/server/dist/background-windows-bootstrap.js +238 -0
  223. package/server/dist/blueprint-chat-manager.js +476 -62
  224. package/server/dist/blueprint-commit.js +21 -1
  225. package/server/dist/blueprint-draft-parser.js +122 -17
  226. package/server/dist/blueprint-generation.js +238 -0
  227. package/server/dist/blueprint-operator-prompt.js +91 -63
  228. package/server/dist/blueprint-router.js +55 -3
  229. package/server/dist/blueprint-spec-fixtures.js +85 -0
  230. package/server/dist/blueprint-spec-quality.js +57 -16
  231. package/server/dist/blueprint-store.js +92 -1
  232. package/server/dist/browser-capture-manager.js +86 -30
  233. package/server/dist/browser-playwright.js +168 -45
  234. package/server/dist/browser-viewport.js +26 -0
  235. package/server/dist/chat-manager.js +23 -15
  236. package/server/dist/chromium-archive.cjs +83 -0
  237. package/server/dist/chromium-resolver.js +72 -64
  238. package/server/dist/code-activity.js +145 -0
  239. package/server/dist/code-explorer-router.js +714 -114
  240. package/server/dist/core-compat.js +28 -1
  241. package/server/dist/core-execution.js +111 -0
  242. package/server/dist/core-package.js +4 -16
  243. package/server/dist/core-runtime.js +202 -0
  244. package/server/dist/core-update-manager.js +161 -60
  245. package/server/dist/core-update-state.js +29 -0
  246. package/server/dist/db.js +66 -35
  247. package/server/dist/delivery-evidence.js +142 -39
  248. package/server/dist/desktop-db.js +239 -43
  249. package/server/dist/desktop-router.js +109 -9
  250. package/server/dist/dev-ports.js +8 -3
  251. package/server/dist/file-provenance.js +34 -22
  252. package/server/dist/file-story-manager.js +62 -64
  253. package/server/dist/file-story.js +118 -35
  254. package/server/dist/file-summary-generator.js +46 -5
  255. package/server/dist/file-summary-manager.js +355 -106
  256. package/server/dist/framework-manager.js +98 -110
  257. package/server/dist/framework-reseed.js +76 -10
  258. package/server/dist/git-diagnostics.js +2 -2
  259. package/server/dist/headroom-manager.js +38 -3
  260. package/server/dist/host-control.js +52 -0
  261. package/server/dist/index.js +43 -2
  262. package/server/dist/interactive-job-session.js +149 -16
  263. package/server/dist/internal-api.js +48 -0
  264. package/server/dist/jira/jira-materializer.js +1 -0
  265. package/server/dist/json-tolerant.js +174 -0
  266. package/server/dist/legacy-migration.js +4 -2
  267. package/server/dist/loop-command-catalog.js +83 -21
  268. package/server/dist/loop-constants.js +6 -1
  269. package/server/dist/loop-decider.js +11 -1
  270. package/server/dist/loop-executors.js +194 -45
  271. package/server/dist/loop-factory.js +11 -4
  272. package/server/dist/loop-graph.js +90 -4
  273. package/server/dist/loop-run-manager.js +301 -69
  274. package/server/dist/loop-shell-invocation.js +21 -0
  275. package/server/dist/loop-step-idle.js +55 -0
  276. package/server/dist/loop-templates.js +31 -7
  277. package/server/dist/mcp/agent-capability.js +37 -4
  278. package/server/dist/mcp/guide.js +149 -36
  279. package/server/dist/mcp/mcp-admin-router.js +20 -4
  280. package/server/dist/mcp/mcp-server.js +89 -43
  281. package/server/dist/mcp/mcp-tiers.js +6 -5
  282. package/server/dist/mcp/mcp-token.js +3 -1
  283. package/server/dist/mcp/resources.js +5 -4
  284. package/server/dist/mcp/tools/catalog.js +4 -0
  285. package/server/dist/mcp/tools/code.js +125 -14
  286. package/server/dist/mcp/tools/context.js +153 -0
  287. package/server/dist/mcp/tools/git.js +15 -5
  288. package/server/dist/mcp/tools/jobs.js +84 -71
  289. package/server/dist/mcp/tools/loops.js +17 -6
  290. package/server/dist/mcp/tools/meta.js +74 -27
  291. package/server/dist/mcp/tools/mission.js +29 -0
  292. package/server/dist/mcp/tools/projects.js +22 -6
  293. package/server/dist/mcp/tools/rails.js +48 -11
  294. package/server/dist/mcp/tools/specs.js +86 -14
  295. package/server/dist/mcp/tools/support.js +1 -1
  296. package/server/dist/mcp/tools/types.js +117 -43
  297. package/server/dist/mcp/tools/watch.js +144 -51
  298. package/server/dist/milestone-chain-store.js +164 -0
  299. package/server/dist/milestone-chain.js +487 -0
  300. package/server/dist/milestone-progress.js +348 -0
  301. package/server/dist/mobile/mobile-devices.js +10 -7
  302. package/server/dist/mobile/mobile-gateway.js +2 -0
  303. package/server/dist/mobile/mobile-missions.js +214 -0
  304. package/server/dist/mobile/mobile-redact.js +17 -3
  305. package/server/dist/mobile/mobile-router.js +46 -4
  306. package/server/dist/mobile/mobile-ws.js +49 -4
  307. package/server/dist/multi-repo-bases.js +56 -0
  308. package/server/dist/multi-repo-checkout.js +101 -0
  309. package/server/dist/multi-repo-delivery.js +100 -0
  310. package/server/dist/multi-repo-execution-store.js +65 -0
  311. package/server/dist/multi-repo-execution.js +453 -0
  312. package/server/dist/offline-assemble.js +10 -8
  313. package/server/dist/openspec-runtime-plugin-commands.json +18 -0
  314. package/server/dist/openspec-runtime-plugin.js +120 -0
  315. package/server/dist/plugins/codex-spawn.js +49 -0
  316. package/server/dist/plugins/serena/manifest.js +2 -2
  317. package/server/dist/plugins/serena/templates/instructions.md +16 -0
  318. package/server/dist/pr-publisher.js +1 -1
  319. package/server/dist/profiles-router.js +3 -18
  320. package/server/dist/project-code-discovery.js +142 -0
  321. package/server/dist/project-git.js +19 -21
  322. package/server/dist/project-registry.js +272 -20
  323. package/server/dist/project-repositories.js +157 -0
  324. package/server/dist/project-repository-provenance.js +31 -0
  325. package/server/dist/project-router-background-processes.js +105 -0
  326. package/server/dist/project-router-git.js +75 -16
  327. package/server/dist/project-router-jobs.js +2 -126
  328. package/server/dist/project-router-loop-runs.js +72 -2
  329. package/server/dist/project-router-tickets.js +53 -8
  330. package/server/dist/project-router.js +239 -38
  331. package/server/dist/provider-detection.js +18 -6
  332. package/server/dist/provider-limit.js +64 -0
  333. package/server/dist/providers/claude-adapter.js +26 -1
  334. package/server/dist/providers/claude-background-tasks.js +18 -0
  335. package/server/dist/providers/claude-live-session.js +383 -0
  336. package/server/dist/providers/codex-adapter.js +19 -0
  337. package/server/dist/providers/codex-live-session.js +545 -0
  338. package/server/dist/providers/gemini-adapter.js +1 -0
  339. package/server/dist/providers/live-session-types.js +12 -0
  340. package/server/dist/providers/live-session.js +13 -0
  341. package/server/dist/providers/terminal-result.js +24 -0
  342. package/server/dist/queue-manager.js +2 -0
  343. package/server/dist/rail-isolated-launch.js +141 -16
  344. package/server/dist/rail-pr-decision.js +364 -99
  345. package/server/dist/rail-pr-store.js +24 -10
  346. package/server/dist/rail-worktree-release.js +34 -2
  347. package/server/dist/rail-worktrees-store.js +4 -4
  348. package/server/dist/rails-router.js +249 -55
  349. package/server/dist/repo-lock.js +92 -17
  350. package/server/dist/review-packet.js +23 -13
  351. package/server/dist/schemas/file-summary.v1.json +59 -59
  352. package/server/dist/schemas/profile.v1.json +137 -137
  353. package/server/dist/setup-manager.js +52 -8
  354. package/server/dist/shell-integration/bash-shim.bash +45 -0
  355. package/server/dist/shell-integration/fish-shim.fish +36 -0
  356. package/server/dist/shell-integration/powershell-shim.ps1 +48 -0
  357. package/server/dist/shell-integration/zsh-shim.zsh +47 -0
  358. package/server/dist/smash-runner.js +1 -0
  359. package/server/dist/spawn-lifecycle.js +44 -27
  360. package/server/dist/spec-contract-prompt.js +143 -0
  361. package/server/dist/spec-draft-parser.js +6 -1
  362. package/server/dist/spec-models.js +1 -0
  363. package/server/dist/stuck-run-detector.js +1 -0
  364. package/server/dist/terminal-manager.js +21 -1
  365. package/server/dist/terminal-shell-integration.js +4 -1
  366. package/server/dist/transient-children.js +619 -230
  367. package/server/dist/util/cli-prompt.js +78 -5
  368. package/server/dist/util/sqlite-migrations.js +20 -0
  369. package/server/dist/util/win-spawn.js +18 -3
  370. package/server/dist/util/windows-provider-shell.js +29 -0
  371. package/server/dist/verification-sentinel.js +14 -0
  372. package/server/dist/vitest-setup.js +2 -0
  373. package/server/dist/windows-job-supervisor.js +133 -0
  374. package/server/dist/workspace-manager.js +9 -30
  375. package/server/dist/worktree-manager.js +17 -2
  376. package/server/dist/worktree-overlay.js +3 -1
  377. package/client/dist/assets/ActivityFeedPage-tAQcWs1R.js +0 -1
  378. package/client/dist/assets/AgentBrowserCapture-BX8BNae5.js +0 -1
  379. package/client/dist/assets/AgentModeAnalyticsPane-BVAqCL0K.js +0 -2
  380. package/client/dist/assets/AgentModeCodePane-9XfqQc9c.js +0 -2
  381. package/client/dist/assets/AgentModeJobsPane-BCjLsPhc.js +0 -1
  382. package/client/dist/assets/AgentsPage-C8J_42sm.js +0 -87
  383. package/client/dist/assets/AnalyticsPage-BtQuyfJm.js +0 -1
  384. package/client/dist/assets/CodePage-BZ2MwdCu.js +0 -2
  385. package/client/dist/assets/DesktopAnalyticsPage-Bh_29V4g.js +0 -1
  386. package/client/dist/assets/ExportDropdown-BrtfWzEG.js +0 -1
  387. package/client/dist/assets/InteractiveJobComposer-BCZiSfzc.js +0 -19
  388. package/client/dist/assets/JobDetailModal-NAJmuYIT.js +0 -1
  389. package/client/dist/assets/JobDetailPage-fE0ZycUX.js +0 -1
  390. package/client/dist/assets/JobsPage-z5M_HVJG.js +0 -1
  391. package/client/dist/assets/LoopBuilderPage-j1FQS47c.js +0 -7
  392. package/client/dist/assets/LoopPreviewModal-DhDJjdCe.js +0 -1
  393. package/client/dist/assets/LoopsPage-Ll7zORZb.js +0 -1
  394. package/client/dist/assets/MinimizedChatsContext-Bd3OqR_S.js +0 -1
  395. package/client/dist/assets/PluginsPage-DN4kGvJt.js +0 -2
  396. package/client/dist/assets/ProjectSettingsDialog-OgsgxjzF.js +0 -1
  397. package/client/dist/assets/ReviewPacketPage-DFog4sXn.js +0 -1
  398. package/client/dist/assets/TemplatePreviewModal-L2XxqiOD.js +0 -1
  399. package/client/dist/assets/TicketDetailModal-CsF-AWZX.js +0 -14
  400. package/client/dist/assets/Trans-Bsz9_gyq.js +0 -1
  401. package/client/dist/assets/agent-BQgKv_2F.js +0 -1
  402. package/client/dist/assets/agent-C1NRDJqL.js +0 -1
  403. package/client/dist/assets/agent-CLNleiy6.js +0 -1
  404. package/client/dist/assets/agent-CmceArkQ.js +0 -1
  405. package/client/dist/assets/agent-D3UxQ3SR.js +0 -1
  406. package/client/dist/assets/agent-DB1JeE64.js +0 -1
  407. package/client/dist/assets/agent-DXkHcQ-D.js +0 -1
  408. package/client/dist/assets/agent-DjJJJ2M8.js +0 -1
  409. package/client/dist/assets/auth-D_5bQv5W.js +0 -1
  410. package/client/dist/assets/ban-E4EaZe3a.js +0 -1
  411. package/client/dist/assets/bot-DzuuuC5R.js +0 -1
  412. package/client/dist/assets/browser-BgqHDMXP.js +0 -1
  413. package/client/dist/assets/browser-CsKJtrpv.js +0 -1
  414. package/client/dist/assets/browser-Cu58EpZU.js +0 -1
  415. package/client/dist/assets/browser-CvXOJm-j.js +0 -1
  416. package/client/dist/assets/browser-DOrFh1c7.js +0 -1
  417. package/client/dist/assets/browser-DQv_Jo7x.js +0 -1
  418. package/client/dist/assets/browser-LPgxvJu2.js +0 -1
  419. package/client/dist/assets/browser-eL-3MIEI.js +0 -1
  420. package/client/dist/assets/builder-0IWtosUm.js +0 -1
  421. package/client/dist/assets/builder-Bf2N6XWn.js +0 -1
  422. package/client/dist/assets/builder-BnqaaBkT.js +0 -1
  423. package/client/dist/assets/builder-BxxfGgAO.js +0 -1
  424. package/client/dist/assets/builder-C5IIgWsq.js +0 -1
  425. package/client/dist/assets/builder-CHuahItu.js +0 -1
  426. package/client/dist/assets/builder-CjWosXL_.js +0 -1
  427. package/client/dist/assets/builder-CpCIOoKj.js +0 -1
  428. package/client/dist/assets/code-CHPkOkDS.js +0 -1
  429. package/client/dist/assets/commands-6tYQih5m.js +0 -1
  430. package/client/dist/assets/commands-BK2QinXN.js +0 -1
  431. package/client/dist/assets/commands-C2Nca76h.js +0 -1
  432. package/client/dist/assets/commands-CKdLihNX.js +0 -1
  433. package/client/dist/assets/commands-CYIBTAlc.js +0 -1
  434. package/client/dist/assets/commands-CjUtYJIM.js +0 -1
  435. package/client/dist/assets/commands-Cq_u_8y9.js +0 -1
  436. package/client/dist/assets/commands-D_ZHYQug.js +0 -1
  437. package/client/dist/assets/common-6MLbD-jM.js +0 -1
  438. package/client/dist/assets/common-BKGEu4rm.js +0 -1
  439. package/client/dist/assets/common-BNbnv8cE.js +0 -1
  440. package/client/dist/assets/common-BqGWtDbt.js +0 -1
  441. package/client/dist/assets/common-DBtTzeYm.js +0 -1
  442. package/client/dist/assets/common-DEW3Nr8n.js +0 -1
  443. package/client/dist/assets/common-DHsv9N5d.js +0 -1
  444. package/client/dist/assets/common-mkrEcW-Y.js +0 -1
  445. package/client/dist/assets/dashboard-B9GhC5ku.js +0 -1
  446. package/client/dist/assets/dashboard-CBnv6zOI.js +0 -1
  447. package/client/dist/assets/dashboard-CaP0fU87.js +0 -1
  448. package/client/dist/assets/dashboard-D4ZZ4x84.js +0 -1
  449. package/client/dist/assets/dashboard-DmuTQBX8.js +0 -1
  450. package/client/dist/assets/dashboard-DynLYj3d.js +0 -1
  451. package/client/dist/assets/dashboard-zj4gGFJ1.js +0 -1
  452. package/client/dist/assets/dialog-CdWCb02j.js +0 -45
  453. package/client/dist/assets/dist-bVqfYmby.js +0 -1
  454. package/client/dist/assets/dist-js-CWeUdf5Z.js +0 -1
  455. package/client/dist/assets/formatDistanceToNow-DQCvMgUc.js +0 -1
  456. package/client/dist/assets/getTimezoneOffsetInMilliseconds-C16cxSe1.js +0 -1
  457. package/client/dist/assets/git-refresh-wTW0rO0Z.js +0 -1
  458. package/client/dist/assets/i18n-hnX2DPmo.js +0 -2
  459. package/client/dist/assets/index-DIhMEAVw.js +0 -66
  460. package/client/dist/assets/index-DwygcU7s.css +0 -2
  461. package/client/dist/assets/mcp-B8X8wBLu.js +0 -1
  462. package/client/dist/assets/mcp-C2AojZZN.js +0 -1
  463. package/client/dist/assets/mcp-D8BT78_L.js +0 -1
  464. package/client/dist/assets/mcp-Df5RWBNk.js +0 -1
  465. package/client/dist/assets/mcp-Dj7BgMQW.js +0 -1
  466. package/client/dist/assets/mcp-Q7iT7rcz.js +0 -1
  467. package/client/dist/assets/mcp-YlvNvJbW.js +0 -1
  468. package/client/dist/assets/mcp-mKFpTSRb.js +0 -1
  469. package/client/dist/assets/narration-4Z2VUhZw.js +0 -1
  470. package/client/dist/assets/narration-BGuiEDj3.js +0 -1
  471. package/client/dist/assets/narration-BuSoqRmv.js +0 -1
  472. package/client/dist/assets/narration-CB9t29fy.js +0 -1
  473. package/client/dist/assets/narration-CU3x8FHD.js +0 -1
  474. package/client/dist/assets/narration-CWeXhfP5.js +0 -1
  475. package/client/dist/assets/narration-DRaDnhT5.js +0 -1
  476. package/client/dist/assets/narration-DtEbQgCw.js +0 -1
  477. package/client/dist/assets/nav-ApJVg3xu.js +0 -1
  478. package/client/dist/assets/nav-BKNky1Bg.js +0 -1
  479. package/client/dist/assets/nav-C6vWWKYx.js +0 -1
  480. package/client/dist/assets/nav-CXJ6Aw89.js +0 -1
  481. package/client/dist/assets/nav-CsmFBIDf.js +0 -1
  482. package/client/dist/assets/nav-DjkmQJjd.js +0 -1
  483. package/client/dist/assets/packet-B1IxaL5f.js +0 -1
  484. package/client/dist/assets/packet-Bh5kkbiB.js +0 -1
  485. package/client/dist/assets/packet-By8fqYxW.js +0 -1
  486. package/client/dist/assets/packet-CZdvA44E.js +0 -1
  487. package/client/dist/assets/packet-CrjHRQCP.js +0 -1
  488. package/client/dist/assets/packet-Dwi2pTtx.js +0 -1
  489. package/client/dist/assets/packet-_-ZIa0IR.js +0 -1
  490. package/client/dist/assets/packet-n0W6E1Hn.js +0 -1
  491. package/client/dist/assets/play-DNlrawbS.js +0 -1
  492. package/client/dist/assets/provider-capabilities-Doej9lfa.js +0 -1
  493. package/client/dist/assets/settings-Bd0x4TBa.js +0 -1
  494. package/client/dist/assets/settings-C1-7cXzC.js +0 -1
  495. package/client/dist/assets/settings-CAFaT38b.js +0 -1
  496. package/client/dist/assets/settings-Ct3v1nW2.js +0 -1
  497. package/client/dist/assets/settings-DHh7_IF5.js +0 -1
  498. package/client/dist/assets/settings-DQXAmdcv.js +0 -1
  499. package/client/dist/assets/settings-guzlhpup.js +0 -1
  500. package/client/dist/assets/settings-sZfTPMEH.js +0 -1
  501. package/client/dist/assets/setup-3jWaoVUO.js +0 -1
  502. package/client/dist/assets/setup-BjgRneb2.js +0 -1
  503. package/client/dist/assets/setup-BzFIjv-f.js +0 -1
  504. package/client/dist/assets/setup-C4VfQsxE.js +0 -1
  505. package/client/dist/assets/setup-DfUkpDbN.js +0 -1
  506. package/client/dist/assets/setup-ECe90Pmu.js +0 -1
  507. package/client/dist/assets/setup-dlqC4Jmm.js +0 -1
  508. package/client/dist/assets/setup-jwfLMiM2.js +0 -1
  509. package/client/dist/assets/spending-EC9xqio-.js +0 -1
  510. package/client/dist/assets/useDesktop-BQVt8lFd.js +0 -1
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AgentInputLimitError = exports.AgentInputConflictError = exports.MAX_PENDING_AGENT_INPUTS = void 0;
4
+ exports.getAgentInput = getAgentInput;
5
+ exports.enqueueAgentInput = enqueueAgentInput;
6
+ exports.listPendingAgentInputs = listPendingAgentInputs;
7
+ exports.editPendingAgentInput = editPendingAgentInput;
8
+ exports.steerPendingAgentInput = steerPendingAgentInput;
9
+ exports.deletePendingAgentInput = deletePendingAgentInput;
10
+ exports.setAgentInputReceipt = setAgentInputReceipt;
11
+ exports.deliverAgentInput = deliverAgentInput;
12
+ exports.interruptAgentInput = interruptAgentInput;
13
+ exports.cancelPendingAgentInputs = cancelPendingAgentInputs;
14
+ exports.recoverPendingAgentInputs = recoverPendingAgentInputs;
15
+ exports.decorateAgentInputMessages = decorateAgentInputMessages;
16
+ const crypto_1 = require("crypto");
17
+ const agent_store_1 = require("./agent-store");
18
+ exports.MAX_PENDING_AGENT_INPUTS = 50;
19
+ class AgentInputConflictError extends Error {
20
+ code = 'agent_input_conflict';
21
+ constructor() { super('This message ID was already used for different content.'); this.name = 'AgentInputConflictError'; }
22
+ }
23
+ exports.AgentInputConflictError = AgentInputConflictError;
24
+ class AgentInputLimitError extends Error {
25
+ code = 'agent_input_limit';
26
+ constructor() { super(`A conversation can have at most ${exports.MAX_PENDING_AGENT_INPUTS} pending messages.`); this.name = 'AgentInputLimitError'; }
27
+ }
28
+ exports.AgentInputLimitError = AgentInputLimitError;
29
+ function mapInput(row) {
30
+ return {
31
+ id: row.id, conversationId: row.conversation_id, queueId: row.queue_id, text: row.text,
32
+ options: JSON.parse(row.options_json),
33
+ status: row.status, receipt: row.receipt, createdAt: row.created_at, messageId: row.message_id,
34
+ };
35
+ }
36
+ /** Stable key ordering makes equivalent HTTP retries independent of JSON key order. */
37
+ function canonicalJson(value) {
38
+ const sort = (entry) => Array.isArray(entry)
39
+ ? entry.map(sort)
40
+ : entry && typeof entry === 'object'
41
+ ? Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => [key, sort(item)]))
42
+ : entry;
43
+ return JSON.stringify(sort(value));
44
+ }
45
+ function readRaw(db, conversationId, queueId) {
46
+ return db.prepare('SELECT * FROM agent_inputs WHERE conversation_id = ? AND queue_id = ?').get(conversationId, queueId);
47
+ }
48
+ function getAgentInput(db, conversationId, queueId) {
49
+ const row = readRaw(db, conversationId, queueId);
50
+ return row ? mapInput(row) : undefined;
51
+ }
52
+ function enqueueAgentInput(db, input) {
53
+ const queueId = input.queueId ?? (0, crypto_1.randomUUID)();
54
+ if (typeof queueId !== 'string' || queueId.trim().length === 0)
55
+ throw new Error('A message ID must be a nonempty string.');
56
+ if (typeof input.text !== 'string')
57
+ throw new Error('A message must contain text.');
58
+ if (input.options?.deliveryMode !== undefined && input.options.deliveryMode !== 'queue' && input.options.deliveryMode !== 'steer') {
59
+ throw new Error('Message deliveryMode must be queue or steer.');
60
+ }
61
+ // Copy only the supported options. Persist arrays even when empty so absent
62
+ // and explicitly empty metadata have the same idempotency semantics.
63
+ const options = {
64
+ ...(input.options?.tierLevel !== undefined ? { tierLevel: input.options.tierLevel } : {}),
65
+ ...(input.options?.model !== undefined ? { model: input.options.model } : {}),
66
+ ...(input.options?.deliveryMode !== undefined ? { deliveryMode: input.options.deliveryMode } : {}),
67
+ attachmentIds: input.options?.attachmentIds ?? [], contextRefs: input.options?.contextRefs ?? [],
68
+ };
69
+ const optionsJson = canonicalJson(options);
70
+ const payload = canonicalJson({ text: input.text, options });
71
+ return db.transaction(() => {
72
+ const existing = readRaw(db, input.conversationId, queueId);
73
+ if (existing) {
74
+ if (existing.enqueue_payload !== payload)
75
+ throw new AgentInputConflictError();
76
+ return { input: mapInput(existing), created: false };
77
+ }
78
+ const count = db.prepare("SELECT COUNT(*) AS n FROM agent_inputs WHERE conversation_id = ? AND status = 'pending'").get(input.conversationId);
79
+ if (count.n >= exports.MAX_PENDING_AGENT_INPUTS)
80
+ throw new AgentInputLimitError();
81
+ db.prepare(`INSERT INTO agent_inputs (id, conversation_id, queue_id, text, options_json, enqueue_payload)
82
+ VALUES (?, ?, ?, ?, ?, ?)`).run((0, crypto_1.randomUUID)(), input.conversationId, queueId, input.text, optionsJson, payload);
83
+ return { input: mapInput(readRaw(db, input.conversationId, queueId)), created: true };
84
+ })();
85
+ }
86
+ function listPendingAgentInputs(db, conversationId) {
87
+ return db.prepare("SELECT * FROM agent_inputs WHERE conversation_id = ? AND status = 'pending' ORDER BY created_at, rowid").all(conversationId).map(mapInput);
88
+ }
89
+ /** Editing changes the pending intent, never its original HTTP dedup fingerprint. */
90
+ function editPendingAgentInput(db, conversationId, queueId, text) {
91
+ if (typeof text !== 'string')
92
+ throw new Error('A message must contain text.');
93
+ return db.transaction(() => {
94
+ const update = db.prepare("UPDATE agent_inputs SET text = ? WHERE conversation_id = ? AND queue_id = ? AND status = 'pending'").run(text, conversationId, queueId);
95
+ return update.changes ? getAgentInput(db, conversationId, queueId) : undefined;
96
+ })();
97
+ }
98
+ /** Promote pending input without rewriting its original HTTP identity. The
99
+ * manager owns the synchronous in-flight claim and must reject a claimed row. */
100
+ function steerPendingAgentInput(db, conversationId, queueId) {
101
+ return db.transaction(() => {
102
+ const row = readRaw(db, conversationId, queueId);
103
+ if (!row || row.status !== 'pending')
104
+ return undefined;
105
+ const options = { ...JSON.parse(row.options_json), deliveryMode: 'steer' };
106
+ db.prepare("UPDATE agent_inputs SET options_json = ? WHERE id = ? AND status = 'pending'").run(canonicalJson(options), row.id);
107
+ return getAgentInput(db, conversationId, queueId);
108
+ })();
109
+ }
110
+ /** Removing a queue chip is an explicit deletion of unsent input. Keep its
111
+ * dedup tombstone, but do not add the removed text to conversation history. */
112
+ function deletePendingAgentInput(db, conversationId, queueId) {
113
+ return db.prepare("UPDATE agent_inputs SET status = 'cancelled' WHERE conversation_id = ? AND queue_id = ? AND status = 'pending'")
114
+ .run(conversationId, queueId).changes > 0;
115
+ }
116
+ const receiptOrder = { sent: 0, received: 1, read: 2 };
117
+ function validateReceipt(receipt) {
118
+ if (receipt !== 'sent' && receipt !== 'received' && receipt !== 'read')
119
+ throw new Error('Message receipt must be sent, received or read.');
120
+ }
121
+ function latestReceipt(existing, incoming) {
122
+ return receiptOrder[incoming] > receiptOrder[existing] ? incoming : existing;
123
+ }
124
+ /** The caller must hold a transaction while moving a pending row and user message together. */
125
+ function settleInput(db, row, status, receipt = row.receipt) {
126
+ const options = JSON.parse(row.options_json);
127
+ const message = (0, agent_store_1.addAgentMessage)(db, {
128
+ conversationId: row.conversation_id, role: 'user', content: row.text,
129
+ attachmentIds: options.attachmentIds, contextRefs: options.contextRefs,
130
+ });
131
+ const nextReceipt = latestReceipt(row.receipt, receipt);
132
+ db.prepare("UPDATE agent_inputs SET status = ?, message_id = ?, receipt = ? WHERE id = ? AND status = 'pending'").run(status, message.id, nextReceipt, row.id);
133
+ return {
134
+ input: mapInput(readRaw(db, row.conversation_id, row.queue_id)),
135
+ message: { ...message, delivery_status: status, delivery_receipt: nextReceipt },
136
+ };
137
+ }
138
+ /** Provider acknowledgements can arrive out of order or after a reconnect. Only
139
+ * advance receipt state, retaining the same transcript identity and metadata. */
140
+ function setAgentInputReceipt(db, conversationId, queueId, receipt) {
141
+ validateReceipt(receipt);
142
+ return db.transaction(() => {
143
+ const row = readRaw(db, conversationId, queueId);
144
+ if (!row || (row.status !== 'pending' && row.status !== 'delivered'))
145
+ return undefined;
146
+ const nextReceipt = latestReceipt(row.receipt, receipt);
147
+ if (nextReceipt !== row.receipt)
148
+ db.prepare('UPDATE agent_inputs SET receipt = ? WHERE id = ?').run(nextReceipt, row.id);
149
+ const updated = { ...row, receipt: nextReceipt };
150
+ const message = row.message_id ? (0, agent_store_1.listAgentMessages)(db, conversationId).find((entry) => entry.id === row.message_id) : undefined;
151
+ return {
152
+ input: mapInput(updated),
153
+ ...(message ? { message: { ...message, delivery_status: row.status, delivery_receipt: nextReceipt } } : {}),
154
+ };
155
+ })();
156
+ }
157
+ function deliverAgentInput(db, conversationId, queueId, receipt = 'received') {
158
+ validateReceipt(receipt);
159
+ return db.transaction(() => {
160
+ const row = readRaw(db, conversationId, queueId);
161
+ if (!row)
162
+ return undefined;
163
+ if (row.status === 'delivered') {
164
+ return setAgentInputReceipt(db, conversationId, queueId, receipt)?.message;
165
+ }
166
+ if (row.status !== 'pending')
167
+ return undefined;
168
+ return settleInput(db, row, 'delivered', receipt).message;
169
+ })();
170
+ }
171
+ /** A native write whose acknowledgement was lost must not be replayed. */
172
+ function interruptAgentInput(db, conversationId, queueId) {
173
+ return db.transaction(() => {
174
+ const row = readRaw(db, conversationId, queueId);
175
+ if (!row || row.status !== 'pending')
176
+ return undefined;
177
+ return settleInput(db, row, 'interrupted').message;
178
+ })();
179
+ }
180
+ function settlePending(db, status, conversationId) {
181
+ return db.transaction(() => {
182
+ const rows = conversationId === undefined
183
+ ? db.prepare("SELECT * FROM agent_inputs WHERE status = 'pending' ORDER BY created_at, rowid").all()
184
+ : db.prepare("SELECT * FROM agent_inputs WHERE conversation_id = ? AND status = 'pending' ORDER BY created_at, rowid").all(conversationId);
185
+ return rows.map((row) => settleInput(db, row, status));
186
+ })();
187
+ }
188
+ function cancelPendingAgentInputs(db, conversationId) {
189
+ return settlePending(db, 'cancelled', conversationId);
190
+ }
191
+ /** Startup preserves unsent messages for review; it never silently replays them. */
192
+ function recoverPendingAgentInputs(db, conversationId) {
193
+ return settlePending(db, 'interrupted', conversationId);
194
+ }
195
+ function decorateAgentInputMessages(db, messages) {
196
+ if (messages.length === 0)
197
+ return [];
198
+ const ids = messages.map((message) => message.id);
199
+ const rows = db.prepare(`SELECT message_id, status, receipt FROM agent_inputs
200
+ WHERE message_id IN (SELECT value FROM json_each(?)) AND status <> 'pending'`).all(JSON.stringify(ids));
201
+ const statuses = new Map(rows.map((row) => [row.message_id, row]));
202
+ return messages.map((message) => {
203
+ const status = statuses.get(message.id);
204
+ return status ? { ...message, delivery_status: status.status, delivery_receipt: status.receipt } : message;
205
+ });
206
+ }
@@ -21,6 +21,13 @@ const agent_tier_1 = require("./agent-tier");
21
21
  const providers_1 = require("./providers");
22
22
  const external_mcp_1 = require("./external-mcp");
23
23
  const AGENT_CONVERSATION_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
24
+ const AGENT_INVOCATION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
25
+ function invocationFileName(extension, invocationId) {
26
+ if (invocationId !== undefined && !AGENT_INVOCATION_ID_RE.test(invocationId)) {
27
+ throw new Error('Unsafe agent invocation id: expected a UUID.');
28
+ }
29
+ return invocationId === undefined ? `mcp.${extension}` : `mcp.${invocationId}.${extension}`;
30
+ }
24
31
  // ─── Agent MCP wiring (design D8 / D1) ────────────────────────────────────────
25
32
  //
26
33
  // The in-app agent drives the app by talking to its OWN embedded MCP server. We
@@ -142,14 +149,14 @@ function buildAgentMcpArgs(opts) {
142
149
  if (!entry)
143
150
  return [];
144
151
  const dir = agentDir(opts.conversationId);
145
- const file = path_1.default.join(dir, 'mcp.json');
152
+ const file = path_1.default.join(dir, invocationFileName('json', opts.invocationId));
146
153
  const mcpServers = { specrails: entry };
147
154
  for (const server of opts.external ?? []) {
148
155
  if (server.name === 'specrails')
149
156
  continue;
150
157
  mcpServers[server.name] = server.config;
151
158
  }
152
- fs_1.default.writeFileSync(file, JSON.stringify({ mcpServers }, null, 2), { mode: 0o600 });
159
+ fs_1.default.writeFileSync(file, JSON.stringify({ mcpServers }, null, 2), { mode: 0o600, flag: opts.invocationId === undefined ? 'w' : 'wx' });
153
160
  try {
154
161
  fs_1.default.chmodSync(file, 0o600);
155
162
  }
@@ -170,14 +177,35 @@ function agentDir(conversationId) {
170
177
  catch { /* best-effort on platforms without chmod */ }
171
178
  return dir;
172
179
  }
173
- function capabilityFilePath(conversationId) {
174
- return path_1.default.join(agentDir(conversationId), 'mcp.capability');
180
+ function capabilityFilePath(conversationId, invocationId) {
181
+ const fileName = invocationFileName('capability', invocationId);
182
+ return path_1.default.join(agentDir(conversationId), fileName);
175
183
  }
176
184
  function buildAgentTurnEntry(opts) {
177
- const capabilityFile = capabilityFilePath(opts.conversationId);
185
+ const capabilityFile = capabilityFilePath(opts.conversationId, opts.invocationId);
178
186
  const entry = buildSpecrailsMcpEntry({ port: opts.port, capabilityFile });
179
187
  if (!entry)
180
188
  return null;
189
+ if (opts.invocationId !== undefined) {
190
+ // Never replace an invocation's bearer, even if a stale process has not
191
+ // opened it yet. Publish the config/argv only after this synchronous write.
192
+ // Exclusive creation also rejects a pre-planted file or symlink.
193
+ const fd = fs_1.default.openSync(capabilityFile, 'wx', 0o600);
194
+ try {
195
+ fs_1.default.writeFileSync(fd, opts.capability, { encoding: 'utf8' });
196
+ }
197
+ catch (err) {
198
+ try {
199
+ fs_1.default.unlinkSync(capabilityFile);
200
+ }
201
+ catch { /* only our newly-created file */ }
202
+ throw err;
203
+ }
204
+ finally {
205
+ fs_1.default.closeSync(fd);
206
+ }
207
+ return entry;
208
+ }
181
209
  const tmp = `${capabilityFile}.tmp-${process.pid}-${(0, crypto_1.randomBytes)(8).toString('hex')}`;
182
210
  try {
183
211
  // `wx` prevents a pre-planted symlink from redirecting the bearer write.
@@ -208,14 +236,22 @@ function buildAgentTurnEntry(opts) {
208
236
  return entry;
209
237
  }
210
238
  /** Delete the on-disk bearer as soon as its owning agent turn settles. */
211
- function removeAgentCapabilityFile(conversationId) {
212
- if (!AGENT_CONVERSATION_ID_RE.test(conversationId))
239
+ function removeAgentCapabilityFile(conversationId, invocationId) {
240
+ if (!AGENT_CONVERSATION_ID_RE.test(conversationId) ||
241
+ (invocationId !== undefined && !AGENT_INVOCATION_ID_RE.test(invocationId)))
213
242
  return;
214
- const file = path_1.default.join(homeDir(), '.specrails', 'agent', conversationId, 'mcp.capability');
215
- try {
216
- fs_1.default.unlinkSync(file);
243
+ const dir = path_1.default.join(homeDir(), '.specrails', 'agent', conversationId);
244
+ const files = [invocationFileName('capability', invocationId)];
245
+ // The invocation-owned Claude config is no longer needed either. Preserve
246
+ // the legacy shared config and every other invocation's files.
247
+ if (invocationId !== undefined)
248
+ files.push(invocationFileName('json', invocationId));
249
+ for (const file of files) {
250
+ try {
251
+ fs_1.default.unlinkSync(path_1.default.join(dir, file));
252
+ }
253
+ catch { /* absent/already removed */ }
217
254
  }
218
- catch { /* absent/already removed */ }
219
255
  }
220
256
  /**
221
257
  * Codex registers the specrails MCP via inline `-c mcp_servers.specrails.*`
@@ -259,18 +295,21 @@ function codexExternalOverrides(server) {
259
295
  }
260
296
  /**
261
297
  * Prepares the specrails MCP for the given provider and returns the spawn
262
- * extraArgs + env to merge. Returns empty wiring when the bridge is unavailable
263
- * (agent then runs tool-less / degraded).
298
+ * extraArgs + env to merge. A missing bridge is an actionable failure: never
299
+ * launch a paid operator turn while silently omitting its primary tools.
264
300
  */
265
301
  function prepareAgentMcp(opts) {
266
302
  const adapter = (0, providers_1.getAdapter)(opts.adapterId);
267
303
  const external = (opts.external ?? []).filter((s) => s.name !== 'specrails');
268
304
  if (adapter.id === 'claude') {
269
- return { extraArgs: buildAgentMcpArgs(opts), env: {} };
305
+ const extraArgs = buildAgentMcpArgs(opts);
306
+ if (!extraArgs.length)
307
+ throw new Error('The bundled Specrails MCP bridge is unavailable.');
308
+ return { extraArgs, env: {} };
270
309
  }
271
310
  const entry = buildAgentTurnEntry(opts);
272
311
  if (!entry)
273
- return { extraArgs: [], env: {} };
312
+ throw new Error('The bundled Specrails MCP bridge is unavailable.');
274
313
  if (adapter.mcpRegistration === 'cli-add') {
275
314
  // Inline -c overrides contain only the capability FILE PATH, never its secret.
276
315
  const externalArgs = external.filter(external_mcp_1.isCodexInjectable).flatMap(codexExternalOverrides);