specrails-desktop 2.58.1 → 2.59.1

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 (438) hide show
  1. package/README.md +2 -5
  2. package/client/dist/assets/{ActivityFeedPage-BQGppIR0.js → ActivityFeedPage-vAY9C71W.js} +1 -1
  3. package/client/dist/assets/AgentBrowserCapture-CpwjGXQm.js +1 -0
  4. package/client/dist/assets/AgentModeAnalyticsPane-BHeoJVxQ.js +2 -0
  5. package/client/dist/assets/AgentModeCodePane-B0Nf3YkN.js +2 -0
  6. package/client/dist/assets/{AgentModeJobsPane-DR_06oqH.js → AgentModeJobsPane-CpbIItY_.js} +1 -1
  7. package/client/dist/assets/{AgentsPage-BKIKjm_1.js → AgentsPage-BVJAFXn3.js} +3 -3
  8. package/client/dist/assets/{AnalyticsPage-069npRVo.js → AnalyticsPage-DDWees-K.js} +1 -1
  9. package/client/dist/assets/CodePage-CzV5tkvS.js +3 -0
  10. package/client/dist/assets/{DesktopAnalyticsPage-qtWAPM47.js → DesktopAnalyticsPage-DfRHNK7i.js} +1 -1
  11. package/client/dist/assets/DocsDialog-BxduBYbh.js +11 -0
  12. package/client/dist/assets/DocsPage-DOVeRJn_.js +11 -0
  13. package/client/dist/assets/{ExportDropdown-BcMpvV89.js → ExportDropdown-BnKVV8UK.js} +1 -1
  14. package/client/dist/assets/InteractiveJobComposer-Da9dvM-0.js +19 -0
  15. package/client/dist/assets/JobDetailModal-DhwKbZGe.js +1 -0
  16. package/client/dist/assets/JobDetailPage-MtPE-E_1.js +1 -0
  17. package/client/dist/assets/JobsPage-0vdlbNik.js +1 -0
  18. package/client/dist/assets/LoopBuilderPage-DCUHozXh.js +1 -0
  19. package/client/dist/assets/{LoopPreviewModal-je5pSCf-.js → LoopPreviewModal-Df-S8NGf.js} +1 -1
  20. package/client/dist/assets/LoopWindowSurface-sdb7QbSo.js +1 -0
  21. package/client/dist/assets/LoopsPage-CDfCC9Px.js +2 -0
  22. package/client/dist/assets/MinimizedChatsContext-DKlPf54Y.js +1 -0
  23. package/client/dist/assets/PluginsPage-iL0G3rQQ.js +2 -0
  24. package/client/dist/assets/ProjectSettingsDialog-DOkjT7xv.js +1 -0
  25. package/client/dist/assets/{RepositoryDeliveries-BiwJuS8r.js → RepositoryDeliveries-CJVpOUpZ.js} +1 -1
  26. package/client/dist/assets/RepositoryScopeSelector-BeM-2gIZ.js +2 -0
  27. package/client/dist/assets/ReviewPacketPage-EBCim2w_.js +4 -0
  28. package/client/dist/assets/TemplatePreviewModal-1-92UGwN.js +1 -0
  29. package/client/dist/assets/TicketDetailModalContext-CkVXuHxU.js +16 -0
  30. package/client/dist/assets/{Trans-D3AfDylf.js → Trans-CzhPjnjB.js} +1 -1
  31. package/client/dist/assets/agent--8QAfoXL.js +1 -0
  32. package/client/dist/assets/agent-3HxXkIWX.js +1 -0
  33. package/client/dist/assets/agent-BjttZLIl.js +1 -0
  34. package/client/dist/assets/agent-CpFCz32T.js +1 -0
  35. package/client/dist/assets/agent-DVnw6ybO.js +1 -0
  36. package/client/dist/assets/agent-Z5s_GTP0.js +1 -0
  37. package/client/dist/assets/agent-hv57-zyG.js +1 -0
  38. package/client/dist/assets/agent-xGrZ_aN1.js +1 -0
  39. package/client/dist/assets/{agentRuntime-DGz_IqKW.js → agentRuntime-15Pkk6we.js} +1 -1
  40. package/client/dist/assets/agentRuntime-Bpx3yWHK.js +1 -0
  41. package/client/dist/assets/{agentRuntime-Bg9tbmqm.js → agentRuntime-C78n13To.js} +1 -1
  42. package/client/dist/assets/{agentRuntime-D-GJVGkj.js → agentRuntime-CCI7XF4c.js} +1 -1
  43. package/client/dist/assets/{agentRuntime-D2__CVI_.js → agentRuntime-CKDHe2-a.js} +1 -1
  44. package/client/dist/assets/{agentRuntime-D35dGVOP.js → agentRuntime-Ddqvp2bP.js} +1 -1
  45. package/client/dist/assets/{agentRuntime-hInH9Fzj.js → agentRuntime-TXPQowKJ.js} +1 -1
  46. package/client/dist/assets/{agentRuntime-O1liDt6G.js → agentRuntime-hqZRy08E.js} +1 -1
  47. package/client/dist/assets/{builder-DGETbtZj.js → builder-B9gorTnT.js} +1 -1
  48. package/client/dist/assets/{builder-DyQperXU.js → builder-Bvw5s3Mi.js} +1 -1
  49. package/client/dist/assets/{builder-C1neIYGR.js → builder-CL5l4dU3.js} +1 -1
  50. package/client/dist/assets/{builder-DXEJUlC0.js → builder-CVDTVrQX.js} +1 -1
  51. package/client/dist/assets/{builder-CzW5ovyI.js → builder-CpS9liE9.js} +1 -1
  52. package/client/dist/assets/{builder-CvnFm0im.js → builder-DNctIL9Q.js} +1 -1
  53. package/client/dist/assets/{builder-D06L7iPy.js → builder-De2NxX6o.js} +1 -1
  54. package/client/dist/assets/{builder-C0FyvM83.js → builder-DeYT7Y-m.js} +1 -1
  55. package/client/dist/assets/{button-Ccc9Dc-D.js → button-D1xExSTF.js} +1 -1
  56. package/client/dist/assets/{common-DmsclwjP.js → common-Bdi0qN4S.js} +1 -1
  57. package/client/dist/assets/{common-C4Yvvhp6.js → common-Bhb9zN1P.js} +1 -1
  58. package/client/dist/assets/{common-od8WThlf.js → common-BykKlZg1.js} +1 -1
  59. package/client/dist/assets/{common-C0BOdeNi.js → common-CvnNNSJA.js} +1 -1
  60. package/client/dist/assets/{common-BCK7c9Pv.js → common-D5zk_mqq.js} +1 -1
  61. package/client/dist/assets/{common-DpLWwgI1.js → common-DQNO_al5.js} +1 -1
  62. package/client/dist/assets/{common-OCvl3c8t.js → common-Dax30Vmp.js} +1 -1
  63. package/client/dist/assets/{common-c0aujEZC.js → common-DkllpVSb.js} +1 -1
  64. package/client/dist/assets/{dialog-xXB2q5HJ.js → dialog-CMgps2MY.js} +1 -1
  65. package/client/dist/assets/external-link-D6XxC_Cu.js +1 -0
  66. package/client/dist/assets/file-text-BcLCfcWZ.js +1 -0
  67. package/client/dist/assets/{formatDistanceToNow-aBss1Nai.js → formatDistanceToNow-DlQaXc7c.js} +1 -1
  68. package/client/dist/assets/{getTimezoneOffsetInMilliseconds-DOGj1Mfz.js → getTimezoneOffsetInMilliseconds-DxUFGcVq.js} +1 -1
  69. package/client/dist/assets/index-Bfunvi6w.css +2 -0
  70. package/client/dist/assets/index-Czov72g7.js +83 -0
  71. package/client/dist/assets/integrations-BkpRUbvp.js +1 -0
  72. package/client/dist/assets/integrations-Bo8qbJf4.js +1 -0
  73. package/client/dist/assets/integrations-CmSrKzZb.js +1 -0
  74. package/client/dist/assets/integrations-DGtq26Rr.js +1 -0
  75. package/client/dist/assets/integrations-De38GFnQ.js +1 -0
  76. package/client/dist/assets/integrations-Dw6zdtb-.js +1 -0
  77. package/client/dist/assets/integrations-Dwl9KQp0.js +1 -0
  78. package/client/dist/assets/integrations-Refg_d2I.js +1 -0
  79. package/client/dist/assets/jira-api-CbJvbRYx.js +1 -0
  80. package/client/dist/assets/{jobs-KG4Sn12X.js → jobs-1G3wodhl.js} +1 -1
  81. package/client/dist/assets/{jobs-6_-r75yC.js → jobs-B4pu8TdF.js} +1 -1
  82. package/client/dist/assets/{jobs-pPv4KWjb.js → jobs-BD47Ov11.js} +1 -1
  83. package/client/dist/assets/{jobs-B1yqyId5.js → jobs-BLOoVRRl.js} +1 -1
  84. package/client/dist/assets/{jobs-BKiK-ZWh.js → jobs-CSrRx5lD.js} +1 -1
  85. package/client/dist/assets/{jobs-BFuV7ttH.js → jobs-DZAbh1m2.js} +1 -1
  86. package/client/dist/assets/{jobs-DmKV7b7d.js → jobs-epP7gt8W.js} +1 -1
  87. package/client/dist/assets/{jobs-BKa8LuwA.js → jobs-tWjcDF_6.js} +1 -1
  88. package/client/dist/assets/loops--KWr0X-w.js +1 -0
  89. package/client/dist/assets/{loops-BO3V8244.js → loops-3IutojWt.js} +1 -1
  90. package/client/dist/assets/{loops-C-hZK8pf.js → loops-BAosWtXE.js} +1 -1
  91. package/client/dist/assets/{loops-eUnCfLjC.js → loops-BISDssL5.js} +1 -1
  92. package/client/dist/assets/{loops-Dv849ckF.js → loops-Cm55CXJ4.js} +1 -1
  93. package/client/dist/assets/{loops-CDOWZ0ci.js → loops-D7tL_Saw.js} +1 -1
  94. package/client/dist/assets/{loops-BJDY9FTh.js → loops-DHQtnfze.js} +1 -1
  95. package/client/dist/assets/{loops-Q9LIgGkq.js → loops-kIJJkaxf.js} +1 -1
  96. package/client/dist/assets/nav--u7iPYlS.js +1 -0
  97. package/client/dist/assets/nav-C5Jgfaby.js +1 -0
  98. package/client/dist/assets/nav-CAna_Wpt.js +1 -0
  99. package/client/dist/assets/nav-CCLqeyHo.js +1 -0
  100. package/client/dist/assets/nav-Cf3c90Jk.js +1 -0
  101. package/client/dist/assets/nav-DMYQaQjR.js +1 -0
  102. package/client/dist/assets/nav-Df_PkZ9F.js +1 -0
  103. package/client/dist/assets/nav-VyNGBJwj.js +1 -0
  104. package/client/dist/assets/{project-repositories-CSnfzUpg.js → project-repositories-BkBD3rxx.js} +1 -1
  105. package/client/dist/assets/provider-capabilities-lePfeT_Y.js +1 -0
  106. package/client/dist/assets/save-OsUqVn99.js +1 -0
  107. package/client/dist/assets/settings-B5Hy_Kol.js +1 -0
  108. package/client/dist/assets/settings-BBj_kZaD.js +1 -0
  109. package/client/dist/assets/settings-ByVE7jdZ.js +1 -0
  110. package/client/dist/assets/settings-COlH_P33.js +1 -0
  111. package/client/dist/assets/settings-D77mC_Lb.js +1 -0
  112. package/client/dist/assets/settings-DZKy7MqN.js +1 -0
  113. package/client/dist/assets/settings-Dbyd6gmj.js +1 -0
  114. package/client/dist/assets/settings-Dn-pXukr.js +1 -0
  115. package/client/dist/assets/setup-Be485n2u.js +1 -0
  116. package/client/dist/assets/setup-CKGUxKr-.js +1 -0
  117. package/client/dist/assets/setup-Ck1Uwd7_.js +1 -0
  118. package/client/dist/assets/setup-Cm774a6v.js +1 -0
  119. package/client/dist/assets/setup-DIqMQpxt.js +1 -0
  120. package/client/dist/assets/setup-DfCsoNFL.js +1 -0
  121. package/client/dist/assets/setup-DkeE8mP0.js +1 -0
  122. package/client/dist/assets/setup-xVntVaz1.js +1 -0
  123. package/client/dist/assets/{spending-HBSk-6jv.js → spending-CYotH-9N.js} +1 -1
  124. package/client/dist/assets/subscriptionUsage-BH73RO86.js +1 -0
  125. package/client/dist/assets/subscriptionUsage-BWTeWlHx.js +1 -0
  126. package/client/dist/assets/subscriptionUsage-CBh82zVa.js +1 -0
  127. package/client/dist/assets/subscriptionUsage-CHcQ7lLe.js +1 -0
  128. package/client/dist/assets/subscriptionUsage-CdlE5Mg1.js +1 -0
  129. package/client/dist/assets/subscriptionUsage-DUPBmSQi.js +1 -0
  130. package/client/dist/assets/subscriptionUsage-DrlwrJ17.js +1 -0
  131. package/client/dist/assets/subscriptionUsage-EFu0mIK3.js +1 -0
  132. package/client/dist/assets/tauri-shell-DE6LfGPw.js +2 -0
  133. package/client/dist/assets/{useDesktop-0unHDBJJ.js → useDesktop-DpxVGfUC.js} +1 -1
  134. package/client/dist/assets/{useRuntimeRuns-BN1rhyEm.js → useRuntimeRuns-CfGRbhr9.js} +1 -1
  135. package/client/dist/assets/useSharedWebSocket-C17TGqT8.js +2 -0
  136. package/client/dist/index.html +33 -32
  137. package/docs/README.md +1 -9
  138. package/docs/agent-live-steering.md +0 -6
  139. package/docs/agents/README.md +0 -2
  140. package/docs/agents/mcp.md +1 -14
  141. package/docs/cli.md +0 -13
  142. package/docs/codex.md +2 -75
  143. package/docs/creating-specs.md +0 -39
  144. package/docs/customizing.md +1 -15
  145. package/docs/getting-started.md +0 -23
  146. package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +0 -8
  147. package/docs/guide/de/agents/4-custom-agents-catalog.md +0 -15
  148. package/docs/guide/de/getting-started/1-what-is-specrails.md +0 -2
  149. package/docs/guide/de/getting-started/2-installing-and-first-run.md +0 -2
  150. package/docs/guide/de/getting-started/3-adding-your-first-project.md +0 -4
  151. package/docs/guide/de/getting-started/4-the-dashboard-tour.md +0 -5
  152. package/docs/guide/de/integrations/1-ai-providers.md +2 -50
  153. package/docs/guide/de/integrations/2-plugins.md +0 -8
  154. package/docs/guide/de/integrations/5-mcp-server.md +1 -14
  155. package/docs/guide/de/integrations/6-agent-chat.md +0 -11
  156. package/docs/guide/de/integrations/7-local-engines.md +0 -4
  157. package/docs/guide/de/pipeline/1-rails-and-jobs.md +0 -13
  158. package/docs/guide/de/pipeline/2-the-job-detail-view.md +0 -3
  159. package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +0 -20
  160. package/docs/guide/de/pipeline/5-the-loop-builder.md +0 -6
  161. package/docs/guide/de/specs/2-add-spec-quick-mode.md +0 -7
  162. package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +0 -10
  163. package/docs/guide/en/agents/4-custom-agents-catalog.md +0 -25
  164. package/docs/guide/en/getting-started/1-what-is-specrails.md +0 -2
  165. package/docs/guide/en/getting-started/2-installing-and-first-run.md +0 -2
  166. package/docs/guide/en/getting-started/3-adding-your-first-project.md +0 -4
  167. package/docs/guide/en/getting-started/4-the-dashboard-tour.md +0 -5
  168. package/docs/guide/en/insights/3-code-explorer.md +0 -5
  169. package/docs/guide/en/integrations/1-ai-providers.md +10 -99
  170. package/docs/guide/en/integrations/2-plugins.md +0 -8
  171. package/docs/guide/en/integrations/5-mcp-server.md +1 -1
  172. package/docs/guide/en/integrations/6-agent-chat.md +0 -17
  173. package/docs/guide/en/integrations/7-local-engines.md +0 -4
  174. package/docs/guide/en/pipeline/1-rails-and-jobs.md +2 -24
  175. package/docs/guide/en/pipeline/2-the-job-detail-view.md +0 -3
  176. package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +10 -65
  177. package/docs/guide/en/pipeline/5-the-loop-builder.md +0 -7
  178. package/docs/guide/en/specs/2-add-spec-quick-mode.md +0 -11
  179. package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +0 -8
  180. package/docs/guide/es/agents/4-custom-agents-catalog.md +0 -15
  181. package/docs/guide/es/getting-started/1-what-is-specrails.md +0 -2
  182. package/docs/guide/es/getting-started/2-installing-and-first-run.md +0 -2
  183. package/docs/guide/es/getting-started/3-adding-your-first-project.md +0 -4
  184. package/docs/guide/es/getting-started/4-the-dashboard-tour.md +0 -5
  185. package/docs/guide/es/integrations/1-ai-providers.md +10 -75
  186. package/docs/guide/es/integrations/2-plugins.md +0 -8
  187. package/docs/guide/es/integrations/5-mcp-server.md +1 -1
  188. package/docs/guide/es/integrations/6-agent-chat.md +0 -11
  189. package/docs/guide/es/integrations/7-local-engines.md +0 -4
  190. package/docs/guide/es/pipeline/1-rails-and-jobs.md +3 -13
  191. package/docs/guide/es/pipeline/2-the-job-detail-view.md +0 -3
  192. package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +10 -53
  193. package/docs/guide/es/pipeline/5-the-loop-builder.md +1 -6
  194. package/docs/guide/es/specs/2-add-spec-quick-mode.md +0 -7
  195. package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +0 -8
  196. package/docs/guide/fr/agents/4-custom-agents-catalog.md +0 -15
  197. package/docs/guide/fr/getting-started/1-what-is-specrails.md +0 -2
  198. package/docs/guide/fr/getting-started/2-installing-and-first-run.md +0 -2
  199. package/docs/guide/fr/getting-started/3-adding-your-first-project.md +0 -4
  200. package/docs/guide/fr/getting-started/4-the-dashboard-tour.md +0 -5
  201. package/docs/guide/fr/integrations/1-ai-providers.md +2 -50
  202. package/docs/guide/fr/integrations/2-plugins.md +0 -8
  203. package/docs/guide/fr/integrations/5-mcp-server.md +1 -14
  204. package/docs/guide/fr/integrations/6-agent-chat.md +0 -11
  205. package/docs/guide/fr/integrations/7-local-engines.md +0 -4
  206. package/docs/guide/fr/pipeline/1-rails-and-jobs.md +0 -13
  207. package/docs/guide/fr/pipeline/2-the-job-detail-view.md +0 -3
  208. package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +0 -22
  209. package/docs/guide/fr/pipeline/5-the-loop-builder.md +0 -6
  210. package/docs/guide/fr/specs/2-add-spec-quick-mode.md +0 -7
  211. package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +0 -8
  212. package/docs/guide/it/agents/4-custom-agents-catalog.md +0 -15
  213. package/docs/guide/it/getting-started/1-what-is-specrails.md +0 -2
  214. package/docs/guide/it/getting-started/2-installing-and-first-run.md +0 -2
  215. package/docs/guide/it/getting-started/3-adding-your-first-project.md +0 -4
  216. package/docs/guide/it/getting-started/4-the-dashboard-tour.md +0 -5
  217. package/docs/guide/it/integrations/1-ai-providers.md +2 -48
  218. package/docs/guide/it/integrations/2-plugins.md +0 -8
  219. package/docs/guide/it/integrations/5-mcp-server.md +1 -14
  220. package/docs/guide/it/integrations/6-agent-chat.md +0 -11
  221. package/docs/guide/it/integrations/7-local-engines.md +0 -4
  222. package/docs/guide/it/pipeline/1-rails-and-jobs.md +2 -13
  223. package/docs/guide/it/pipeline/2-the-job-detail-view.md +0 -3
  224. package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +0 -20
  225. package/docs/guide/it/pipeline/5-the-loop-builder.md +1 -6
  226. package/docs/guide/it/specs/2-add-spec-quick-mode.md +0 -7
  227. package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +0 -9
  228. package/docs/guide/ja/agents/4-custom-agents-catalog.md +0 -15
  229. package/docs/guide/ja/getting-started/1-what-is-specrails.md +0 -2
  230. package/docs/guide/ja/getting-started/2-installing-and-first-run.md +0 -2
  231. package/docs/guide/ja/getting-started/3-adding-your-first-project.md +0 -4
  232. package/docs/guide/ja/getting-started/4-the-dashboard-tour.md +0 -5
  233. package/docs/guide/ja/integrations/1-ai-providers.md +1 -69
  234. package/docs/guide/ja/integrations/2-plugins.md +0 -8
  235. package/docs/guide/ja/integrations/5-mcp-server.md +1 -14
  236. package/docs/guide/ja/integrations/6-agent-chat.md +0 -10
  237. package/docs/guide/ja/integrations/7-local-engines.md +0 -4
  238. package/docs/guide/ja/pipeline/1-rails-and-jobs.md +0 -13
  239. package/docs/guide/ja/pipeline/2-the-job-detail-view.md +0 -3
  240. package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +0 -21
  241. package/docs/guide/ja/pipeline/5-the-loop-builder.md +0 -6
  242. package/docs/guide/ja/specs/2-add-spec-quick-mode.md +0 -7
  243. package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +0 -8
  244. package/docs/guide/pt/agents/4-custom-agents-catalog.md +0 -15
  245. package/docs/guide/pt/getting-started/1-what-is-specrails.md +0 -2
  246. package/docs/guide/pt/getting-started/2-installing-and-first-run.md +0 -2
  247. package/docs/guide/pt/getting-started/3-adding-your-first-project.md +0 -4
  248. package/docs/guide/pt/getting-started/4-the-dashboard-tour.md +0 -5
  249. package/docs/guide/pt/integrations/1-ai-providers.md +2 -48
  250. package/docs/guide/pt/integrations/2-plugins.md +0 -8
  251. package/docs/guide/pt/integrations/5-mcp-server.md +1 -14
  252. package/docs/guide/pt/integrations/6-agent-chat.md +0 -10
  253. package/docs/guide/pt/integrations/7-local-engines.md +0 -4
  254. package/docs/guide/pt/pipeline/1-rails-and-jobs.md +0 -13
  255. package/docs/guide/pt/pipeline/2-the-job-detail-view.md +0 -2
  256. package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +0 -21
  257. package/docs/guide/pt/pipeline/5-the-loop-builder.md +0 -6
  258. package/docs/guide/pt/specs/2-add-spec-quick-mode.md +0 -7
  259. package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +0 -7
  260. package/docs/guide/zh/agents/4-custom-agents-catalog.md +0 -15
  261. package/docs/guide/zh/getting-started/1-what-is-specrails.md +0 -2
  262. package/docs/guide/zh/getting-started/2-installing-and-first-run.md +0 -2
  263. package/docs/guide/zh/getting-started/3-adding-your-first-project.md +0 -4
  264. package/docs/guide/zh/getting-started/4-the-dashboard-tour.md +0 -5
  265. package/docs/guide/zh/integrations/1-ai-providers.md +1 -67
  266. package/docs/guide/zh/integrations/2-plugins.md +0 -8
  267. package/docs/guide/zh/integrations/5-mcp-server.md +1 -14
  268. package/docs/guide/zh/integrations/6-agent-chat.md +0 -9
  269. package/docs/guide/zh/integrations/7-local-engines.md +0 -4
  270. package/docs/guide/zh/pipeline/1-rails-and-jobs.md +0 -13
  271. package/docs/guide/zh/pipeline/2-the-job-detail-view.md +0 -2
  272. package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +0 -20
  273. package/docs/guide/zh/pipeline/5-the-loop-builder.md +0 -6
  274. package/docs/guide/zh/specs/2-add-spec-quick-mode.md +0 -7
  275. package/docs/internals/adding-a-provider.md +7 -0
  276. package/docs/internals/api-reference.md +1 -0
  277. package/docs/internals/core-runtime-updates.md +9 -2
  278. package/docs/internals/desktop-owned-workflows.md +144 -0
  279. package/docs/internals/mission-rail-cards.md +15 -0
  280. package/docs/internals/operations-runbook.md +26 -0
  281. package/docs/internals/programmatic-agent-runtime.md +34 -28
  282. package/docs/internals/project-builder.md +34 -11
  283. package/docs/internals/safe-pr-review-flow.md +25 -7
  284. package/docs/internals/source-map.md +53 -3
  285. package/docs/internals/spec-addenda.md +11 -5
  286. package/docs/internals/visual-design-audit.md +5 -0
  287. package/docs/local-providers.md +8 -13
  288. package/docs/mcp.md +1 -17
  289. package/docs/platforms/macos.md +0 -40
  290. package/docs/platforms/windows-parity.md +1 -1
  291. package/docs/platforms/windows.md +0 -8
  292. package/docs/running-pipelines.md +1 -46
  293. package/docs/subscription-usage.md +19 -0
  294. package/docs/terminal.md +0 -2
  295. package/docs/tracking-cost.md +2 -33
  296. package/package.json +1 -1
  297. package/server/dist/core-execution.js +24 -15
  298. package/server/dist/core-update-manager.js +1 -1
  299. package/server/dist/db/migrations.js +9 -0
  300. package/server/dist/desktop-db.js +23 -10
  301. package/server/dist/desktop-router.js +8 -4
  302. package/server/dist/index.js +10 -5
  303. package/server/dist/mcp/guide.js +1 -0
  304. package/server/dist/mcp/tools/jobs.js +1 -1
  305. package/server/dist/mcp/tools/loops.js +2 -0
  306. package/server/dist/mcp/tools/meta.js +6 -7
  307. package/server/dist/mcp/tools/projects.js +31 -6
  308. package/server/dist/mcp/tools/rails.js +6 -3
  309. package/server/dist/mcp/tools/setup.js +10 -0
  310. package/server/dist/mcp/tools/specs.js +1 -1
  311. package/server/dist/modules/accounting/runtime/pricing.js +6 -1
  312. package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +169 -17
  313. package/server/dist/modules/agent-runtime/runtime/agent-runtime-metrics.js +1 -1
  314. package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings-router.js +1 -1
  315. package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings.js +42 -0
  316. package/server/dist/modules/agent-runtime/runtime/agent-runtime-verification-suggestions.js +10 -4
  317. package/server/dist/modules/builder/runtime/milestone-chain.js +76 -10
  318. package/server/dist/modules/delivery/runtime/delivery-evidence.js +3 -2
  319. package/server/dist/modules/delivery/runtime/multi-repo-execution.js +10 -5
  320. package/server/dist/modules/delivery/runtime/rail-isolated-launch.js +66 -30
  321. package/server/dist/modules/delivery/runtime/rail-launch-parser.js +8 -0
  322. package/server/dist/modules/delivery/runtime/rail-pr-store.js +3 -3
  323. package/server/dist/modules/delivery/runtime/rail-relaunch.js +154 -0
  324. package/server/dist/modules/delivery/runtime/rails-router.js +157 -36
  325. package/server/dist/modules/delivery/runtime/review-packet.js +1 -1
  326. package/server/dist/modules/execution/runtime/revision-seed.js +6 -2
  327. package/server/dist/modules/loops/runtime/loop-agent-defaults.json +6 -0
  328. package/server/dist/modules/loops/runtime/loop-agents.js +21 -0
  329. package/server/dist/modules/loops/runtime/loop-command-catalog.js +1 -1
  330. package/server/dist/modules/loops/runtime/loop-core-factory.js +19 -3
  331. package/server/dist/modules/loops/runtime/loop-definition-events.js +1 -1
  332. package/server/dist/modules/loops/runtime/loop-definition.js +79 -12
  333. package/server/dist/modules/loops/runtime/loop-effect.js +1 -1
  334. package/server/dist/modules/loops/runtime/loop-executors.js +24 -9
  335. package/server/dist/modules/loops/runtime/loop-factory.js +1 -1
  336. package/server/dist/modules/loops/runtime/loop-graph.js +5 -14
  337. package/server/dist/modules/loops/runtime/loop-implement-recipe.js +53 -0
  338. package/server/dist/modules/loops/runtime/loop-run-manager.js +30 -20
  339. package/server/dist/modules/loops/runtime/loop-templates.js +29 -5
  340. package/server/dist/modules/loops/runtime/loops-router.js +17 -0
  341. package/server/dist/modules/missions/runtime/agent-context-resolver.js +1 -1
  342. package/server/dist/modules/missions/runtime/agent-operator-prompt.js +17 -8
  343. package/server/dist/modules/specs/runtime/spec-models.js +4 -7
  344. package/server/dist/modules/subscription-usage/adapters/claude.js +123 -0
  345. package/server/dist/modules/subscription-usage/adapters/codex.js +164 -0
  346. package/server/dist/modules/subscription-usage/adapters/errors.js +15 -0
  347. package/server/dist/modules/subscription-usage/adapters/http.js +20 -0
  348. package/server/dist/modules/subscription-usage/adapters/local-auth.js +61 -0
  349. package/server/dist/modules/subscription-usage/application.js +12 -0
  350. package/server/dist/modules/subscription-usage/domain.js +104 -0
  351. package/server/dist/modules/subscription-usage/index.js +2 -0
  352. package/server/dist/modules/subscription-usage/ports.js +2 -0
  353. package/server/dist/modules/subscription-usage/runtime/composition.js +20 -0
  354. package/server/dist/modules/subscription-usage/runtime/usage-service.js +111 -0
  355. package/server/dist/project-registry.js +16 -1
  356. package/server/dist/project-repositories.js +51 -2
  357. package/server/dist/project-router-helpers.js +1 -1
  358. package/server/dist/project-router-loop-runs.js +4 -1
  359. package/server/dist/providers/claude-adapter.js +6 -4
  360. package/server/dist/providers/codex-adapter.js +4 -5
  361. package/server/dist/schemas/workflow-definition.schema.json +2 -0
  362. package/server/dist/worktree-manager.js +114 -6
  363. package/server/dist/worktree-overlay.js +4 -4
  364. package/client/dist/assets/AgentBrowserCapture-PI-cxyxi.js +0 -1
  365. package/client/dist/assets/AgentModeAnalyticsPane-mQsOqdXx.js +0 -2
  366. package/client/dist/assets/AgentModeCodePane-BL-vpmlY.js +0 -2
  367. package/client/dist/assets/CodePage-Alitorrv.js +0 -3
  368. package/client/dist/assets/DocsDialog-DwL6rgcT.js +0 -11
  369. package/client/dist/assets/DocsPage-BA1hiJZ-.js +0 -11
  370. package/client/dist/assets/InteractiveJobComposer-B3H1YHr6.js +0 -19
  371. package/client/dist/assets/JobDetailModal-XZQ9eAAy.js +0 -1
  372. package/client/dist/assets/JobDetailPage-B-SIaq_q.js +0 -1
  373. package/client/dist/assets/JobsPage-iQXAv2mx.js +0 -1
  374. package/client/dist/assets/LoopBuilderPage-B_gbFAHn.js +0 -1
  375. package/client/dist/assets/LoopsPage-BZwcY5cu.js +0 -2
  376. package/client/dist/assets/MinimizedChatsContext-CNx_0bZu.js +0 -1
  377. package/client/dist/assets/PluginsPage-DFocnoHX.js +0 -2
  378. package/client/dist/assets/ProjectSettingsDialog-Bh3S6EBB.js +0 -1
  379. package/client/dist/assets/RepositoryScopeSelector-C2mvWBQ6.js +0 -1
  380. package/client/dist/assets/ReviewPacketPage-CrAf-WDy.js +0 -4
  381. package/client/dist/assets/TemplatePreviewModal-C7DordpN.js +0 -1
  382. package/client/dist/assets/TicketDetailModalContext-B-DySpKL.js +0 -16
  383. package/client/dist/assets/agent-BaG10AN6.js +0 -1
  384. package/client/dist/assets/agent-CH4aJ884.js +0 -1
  385. package/client/dist/assets/agent-CLc9fA7v.js +0 -1
  386. package/client/dist/assets/agent-DHh9-AdL.js +0 -1
  387. package/client/dist/assets/agent-DkKnd6Wv.js +0 -1
  388. package/client/dist/assets/agent-aiVhqFW1.js +0 -1
  389. package/client/dist/assets/agent-dbznD3eO.js +0 -1
  390. package/client/dist/assets/agent-sMVFcPwL.js +0 -1
  391. package/client/dist/assets/agentRuntime-BeUb3g9g.js +0 -1
  392. package/client/dist/assets/file-text-CFT-xXKN.js +0 -1
  393. package/client/dist/assets/index-BS7KCWkV.css +0 -2
  394. package/client/dist/assets/index-C4Mv6tV6.js +0 -80
  395. package/client/dist/assets/integrations-CH0zy1Mw.js +0 -1
  396. package/client/dist/assets/integrations-CIAjhd7L.js +0 -1
  397. package/client/dist/assets/integrations-CZdwOe8A.js +0 -1
  398. package/client/dist/assets/integrations-Ct7omMld.js +0 -1
  399. package/client/dist/assets/integrations-D6MSxy3-.js +0 -1
  400. package/client/dist/assets/integrations-DbZa-Zyc.js +0 -1
  401. package/client/dist/assets/integrations-b8pH-vfl.js +0 -1
  402. package/client/dist/assets/integrations-mB-7zoyT.js +0 -1
  403. package/client/dist/assets/jira-api-BYbEPlkr.js +0 -1
  404. package/client/dist/assets/layers-eDMjG41I.js +0 -1
  405. package/client/dist/assets/loops-B4_D-nbg.js +0 -1
  406. package/client/dist/assets/nav-B-tpjyc2.js +0 -1
  407. package/client/dist/assets/nav-BJNXGg29.js +0 -1
  408. package/client/dist/assets/nav-BdhtRLP7.js +0 -1
  409. package/client/dist/assets/nav-ByYgyN5T.js +0 -1
  410. package/client/dist/assets/nav-DA0Mva2c.js +0 -1
  411. package/client/dist/assets/nav-DcJm_Jg_.js +0 -1
  412. package/client/dist/assets/nav-DhMPtAXc.js +0 -1
  413. package/client/dist/assets/nav-DhPb-Isc.js +0 -1
  414. package/client/dist/assets/provider-capabilities-Vi1ZGvAK.js +0 -1
  415. package/client/dist/assets/save-B6wGWwBR.js +0 -1
  416. package/client/dist/assets/settings-3o4Ntzi5.js +0 -1
  417. package/client/dist/assets/settings-B97jlkwD.js +0 -1
  418. package/client/dist/assets/settings-BTaT_bsS.js +0 -1
  419. package/client/dist/assets/settings-CT8w7WiC.js +0 -1
  420. package/client/dist/assets/settings-Cvr8_tvh.js +0 -1
  421. package/client/dist/assets/settings-Dn1qgAC8.js +0 -1
  422. package/client/dist/assets/settings-EShDdg4J.js +0 -1
  423. package/client/dist/assets/settings-tfLhQZRN.js +0 -1
  424. package/client/dist/assets/setup-CBMu3tqH.js +0 -1
  425. package/client/dist/assets/setup-CPh-e6J2.js +0 -1
  426. package/client/dist/assets/setup-CRKLp_ke.js +0 -1
  427. package/client/dist/assets/setup-Cy302v4J.js +0 -1
  428. package/client/dist/assets/setup-D681vTPf.js +0 -1
  429. package/client/dist/assets/setup-DYK0VBkE.js +0 -1
  430. package/client/dist/assets/setup-KAuiIiVs.js +0 -1
  431. package/client/dist/assets/setup-OGX-oCfI.js +0 -1
  432. package/client/dist/assets/useSharedWebSocket-BZMrX4jr.js +0 -2
  433. package/client/dist/assets/wrench-BfmNO9Vw.js +0 -1
  434. package/docs/agy-cli-provider-study.md +0 -257
  435. package/docs/gemini-cli-provider-study.md +0 -301
  436. package/docs/gemini-core-support-evaluation.md +0 -160
  437. package/docs/gemini.md +0 -257
  438. package/docs/kimi.md +0 -291
@@ -163,21 +163,21 @@ function buildRevisionSeedForLaunch(db, revision, ticketIds, includeSpecBody = t
163
163
  depth += 1;
164
164
  cursor = (0, rail_pr_store_1.getPrDelivery)(db, cursor.revision_of) ?? undefined;
165
165
  }
166
- return (0, revision_seed_1.buildRevisionSeed)({
167
- note: revision.note,
168
- includeSpecBody,
169
- specSnapshot: previous ? (0, rail_pr_store_1.readSpecSnapshot)(previous.spec_snapshot) : null,
170
- ticketIds: [...ticketIds],
171
- branches,
172
- baseBranch: previous?.base_branch ?? 'the integration branch',
173
- branchDiffSummary: null,
174
- evidence: previous ? (0, delivery_evidence_1.readSettleEvidence)(previous.settle_evidence) : null,
175
- revisionNumber: depth,
176
- });
166
+ return { number: depth, briefing: (0, revision_seed_1.buildRevisionSeed)({
167
+ note: revision.note,
168
+ includeSpecBody,
169
+ specSnapshot: previous ? (0, rail_pr_store_1.readSpecSnapshot)(previous.spec_snapshot) : null,
170
+ ticketIds: [...ticketIds],
171
+ branches,
172
+ baseBranch: previous?.base_branch ?? 'the integration branch',
173
+ branchDiffSummary: null,
174
+ evidence: previous ? (0, delivery_evidence_1.readSettleEvidence)(previous.settle_evidence) : null,
175
+ revisionNumber: depth,
176
+ }) };
177
177
  }
178
178
  catch {
179
179
  // Absolute floor: the user's instruction still reaches the run.
180
- return revision.note;
180
+ return { briefing: revision.note, number: 1 };
181
181
  }
182
182
  }
183
183
  /**
@@ -473,7 +473,7 @@ function createIsolatedRunSettlement(ports) {
473
473
  }
474
474
  let commit;
475
475
  try {
476
- commit = await (0, worktree_manager_1.commitWorktreeAndVerify)(git, a.handle.worktreePath, commitMessage(a, implementationOutcome === 'failed'), a.overlayExcludes);
476
+ commit = await (0, worktree_manager_1.commitWorktreeAndVerify)(git, a.handle.worktreePath, commitMessage(a, implementationOutcome === 'failed'), a.overlayExcludes, a.hygieneBaseSha ?? a.initialSha ?? a.baseRef);
477
477
  }
478
478
  catch (err) {
479
479
  commit = { staged: false, committed: false, clean: false, dirty: [], error: errorDetail(err) };
@@ -638,10 +638,13 @@ async function launchIsolatedRail(input, io = {}) {
638
638
  // provider session by contract, so durable context is the only thing it has.
639
639
  // Per-RUN data, so it is layered over the project's constant map for this
640
640
  // launch only and never persisted as a constant.
641
- const constants = input.revision
641
+ const revisionSeed = input.revision ? buildRevisionSeedForLaunch(ctx.db, input.revision, ticketIds, !['factory:sdd-quick-openspec', 'factory:openspec', 'factory:revision'].includes(loopId)) : undefined;
642
+ const constants = input.revision && revisionSeed
642
643
  ? {
643
644
  ...(0, loop_constants_1.loadConstantMap)(ctx.desktopDb),
644
- REVISION_REQUEST: buildRevisionSeedForLaunch(ctx.db, input.revision, ticketIds, !['factory:sdd-quick-openspec', 'factory:openspec', 'factory:revision'].includes(loopId)),
645
+ REVISION_REQUEST: revisionSeed.briefing,
646
+ REVISION_NUMBER: String(revisionSeed.number),
647
+ REVISION_OF_DELIVERY_ID: input.revision.ofDeliveryId,
645
648
  }
646
649
  : (0, loop_constants_1.loadConstantMap)(ctx.desktopDb);
647
650
  // Spec addenda (spec-addenda): the iteration notes the specs carry are
@@ -650,6 +653,7 @@ async function launchIsolatedRail(input, io = {}) {
650
653
  // briefing every AI step of the run receives.
651
654
  const addendaStorePath = (0, spec_addenda_1.ticketStorePathForProject)(ctx.project);
652
655
  const addendaPlan = (0, spec_addenda_1.planSpecAddendaAt)(addendaStorePath, ticketIds);
656
+ const claimedAddendaByRun = new Map();
653
657
  // Capture the PR-delivery mode ONCE at launch entry so a mid-flight env flip
654
658
  // can never split one launch across the two delivery paths.
655
659
  const prMode = Boolean(input.repositoryExecution) || (0, rail_isolation_1.isRailPrDeliveryEnabled)();
@@ -921,6 +925,7 @@ async function launchIsolatedRail(input, io = {}) {
921
925
  }
922
926
  if (prMode) {
923
927
  const generation = (0, rail_pr_store_1.createPrDeliveryGeneration)(ctx.db, {
928
+ launchConfig: input.launchConfig,
924
929
  parentDeliveryId: input.repositoryExecution?.parentDeliveryId,
925
930
  repositoryId: input.repositoryExecution?.repositoryId,
926
931
  repositoryPath: input.repositoryExecution ? baseRepo : undefined,
@@ -947,7 +952,9 @@ async function launchIsolatedRail(input, io = {}) {
947
952
  // predecessor through the shipped rollback path.
948
953
  : input.revision
949
954
  ? { id: input.revision.ofDeliveryId, decision: input.revision.decision }
950
- : null);
955
+ : input.retryOfDelivery
956
+ ? { id: input.retryOfDelivery.deliveryId, decision: input.retryOfDelivery.decision }
957
+ : null);
951
958
  prDeliveryId = generation.delivery.id;
952
959
  supersededDelivery = generation.superseded;
953
960
  input.onPrDeliveryCreated?.(prDeliveryId);
@@ -983,15 +990,28 @@ async function launchIsolatedRail(input, io = {}) {
983
990
  }
984
991
  // Conventional branch naming (pr-naming): `<type>/<ref>-<kebab-title>`, the
985
992
  // Jira key prevailing over the local id when linked. Collisions with foreign
986
- // branches suffix `-2`… (bounded); a branch a PRIOR rail run allocated for
987
- // the SAME ticket is ours to resume, so it is NOT treated as a collision.
993
+ // branches suffix `-2`… (bounded). Ordinary launches start a new sibling;
994
+ // only exact recorded revision/PR branches can be reused.
988
995
  // The integration branch is never used; exhaustion falls back to the legacy
989
996
  // `sr/<slug>/ticket-<id>` name. Snapshot under the lock so concurrent
990
997
  // launches see each other's just-created branches.
991
998
  const takenBranches = await (0, worktree_manager_1.listLocalBranches)(git, baseRepo);
992
999
  const preexistingBranches = new Set(takenBranches);
1000
+ const hygieneBase = await git.run(['rev-parse', '--verify', `${worktreeBaseRef.baseRef}^{commit}`], baseRepo);
1001
+ if (hygieneBase.code !== 0)
1002
+ throw new Error('Could not freeze the OpenSpec delivery baseline');
1003
+ const hygieneBaseSha = /^[a-f0-9]{40,64}$/i.test(hygieneBase.stdout.trim()) ? hygieneBase.stdout.trim() : null;
1004
+ const revisionBranches = input.repositoryExecution?.revisionBranches ?? new Map();
1005
+ if (input.revision && !input.repositoryExecution && !launchContinuation) {
1006
+ const previous = (0, rail_pr_store_1.getPrDelivery)(ctx.db, input.revision.ofDeliveryId);
1007
+ for (const unit of previous ? (0, rail_pr_store_1.toPrDeliverySnapshot)(previous).branches : []) {
1008
+ if (unit.succeeded && unit.finalSha && unit.implementationOutcome !== 'failed' && unit.deliveryOutcome !== 'blocked') {
1009
+ revisionBranches.set(unit.ticketId, { branch: unit.branch, sha: unit.finalSha });
1010
+ }
1011
+ }
1012
+ }
993
1013
  const unitBranchName = (ticketId) => {
994
- const revisionBranch = input.repositoryExecution?.revisionBranches?.get(ticketId);
1014
+ const revisionBranch = revisionBranches.get(ticketId);
995
1015
  if (revisionBranch)
996
1016
  return { branch: revisionBranch.branch, ownership: 'preexisting' };
997
1017
  const continuation = launchContinuation && continuationTargets.get(ticketId);
@@ -1001,10 +1021,10 @@ async function launchIsolatedRail(input, io = {}) {
1001
1021
  }
1002
1022
  const preferred = (0, pr_naming_1.ticketBranchName)(unitNamingInput(ctx, ticketId));
1003
1023
  const branch = (0, pr_naming_1.resolveCollisionFreeName)(preferred, {
1004
- // A grouped run can reuse a branch only through the exact revision/PR
1024
+ // A run can reuse a branch only through the exact revision/PR
1005
1025
  // evidence above. An accepted predecessor may now lag the integration
1006
1026
  // branch, so ordinary grouped allocations must start a fresh branch.
1007
- taken: (name) => takenBranches.has(name) && (Boolean(input.repositoryExecution) || !(0, rail_worktrees_store_1.railWorktreeBranchExistsForTicket)(ctx.db, ticketId, name)),
1027
+ taken: (name) => takenBranches.has(name),
1008
1028
  reserved: [integration.branch],
1009
1029
  }) ?? (0, worktree_manager_1.worktreeBranch)(slug, ticketId);
1010
1030
  takenBranches.add(branch);
@@ -1012,6 +1032,7 @@ async function launchIsolatedRail(input, io = {}) {
1012
1032
  };
1013
1033
  try {
1014
1034
  for (const unit of units) {
1035
+ const runId = input.repositoryExecution?.runIds.get(unit.ticketId) ?? (0, ids_1.newId)();
1015
1036
  const continuationTarget = launchContinuation ? continuationTargets.get(unit.ticketId) ?? null : null;
1016
1037
  const branchPlan = unitBranchName(unit.ticketId);
1017
1038
  let handle = null;
@@ -1019,7 +1040,9 @@ async function launchIsolatedRail(input, io = {}) {
1019
1040
  let worktreeOwnership = 'created';
1020
1041
  let initialSha = null;
1021
1042
  try {
1022
- const revisionBranch = input.repositoryExecution?.revisionBranches?.get(unit.ticketId);
1043
+ const revisionBranch = revisionBranches.get(unit.ticketId);
1044
+ if (input.revision && !input.repositoryExecution && !launchContinuation && !revisionBranch)
1045
+ throw new Error('Revision requires a recorded delivered branch for every ticket');
1023
1046
  if (revisionBranch) {
1024
1047
  const observed = await git.run(['rev-parse', '--verify', `refs/heads/${revisionBranch.branch}`], baseRepo);
1025
1048
  if (observed.code !== 0 || observed.stdout.trim() !== revisionBranch.sha) {
@@ -1028,12 +1051,14 @@ async function launchIsolatedRail(input, io = {}) {
1028
1051
  }
1029
1052
  handle = await create(git, {
1030
1053
  repoDir: baseRepo,
1031
- worktreesRoot,
1054
+ worktreesRoot: path.join(worktreesRoot, runId),
1032
1055
  slug,
1033
1056
  ticketId: unit.ticketId,
1034
1057
  baseRef: revisionBranch?.sha ?? continuationTarget?.baseRef ?? worktreeBaseRef.baseRef,
1035
1058
  branch: branchPlan.branch,
1036
1059
  refreshFromBaseRef: Boolean(continuationTarget?.baseRef),
1060
+ fresh: !revisionBranch && !continuationTarget,
1061
+ reuseBranchWorktree: Boolean(revisionBranch || continuationTarget),
1037
1062
  });
1038
1063
  worktreeOwnership = handle.worktreeCreated === false ? 'preexisting' : 'created';
1039
1064
  if (!continuationTarget && (handle.branch !== branchPlan.branch || handle.branchCreated === false)) {
@@ -1106,7 +1131,6 @@ async function launchIsolatedRail(input, io = {}) {
1106
1131
  console.warn(`[rail-isolated] provenance snapshot failed: ${err.message}`);
1107
1132
  }
1108
1133
  }
1109
- const runId = input.repositoryExecution?.runIds.get(unit.ticketId) ?? (0, ids_1.newId)();
1110
1134
  const ledgerId = (0, ids_1.newId)();
1111
1135
  (0, rail_worktrees_store_1.createRailWorktree)(ctx.db, {
1112
1136
  id: ledgerId, railIndex, ticketId: unit.ticketId, runId,
@@ -1126,6 +1150,7 @@ async function launchIsolatedRail(input, io = {}) {
1126
1150
  provenanceSnapshot,
1127
1151
  continuationTarget,
1128
1152
  baseRef: continuationTarget?.baseRef ?? worktreeBaseRef.baseRef,
1153
+ hygieneBaseSha,
1129
1154
  initialSha,
1130
1155
  branchOwnership,
1131
1156
  worktreeOwnership,
@@ -1158,9 +1183,23 @@ async function launchIsolatedRail(input, io = {}) {
1158
1183
  partialCommitMessage: worktreeCommitMessage(ctx, run.ticketId, run.runId, true), run,
1159
1184
  });
1160
1185
  })();
1186
+ // Freeze every addendum claim before any sibling can start Core. A missing
1187
+ // store or failed claim must never silently turn a delta into an unbriefed run.
1188
+ for (const run of allocated) {
1189
+ const plan = addendaPlan.filter(entry => run.ticketIds.includes(entry.ticketId)).map(entry => input.retryOfDelivery ? { ...entry, status: null } : launchContinuation || input.revision || input.repositoryContinuation ? { ...entry, status: 'on_review' } : entry);
1190
+ const claimed = (0, spec_addenda_1.claimSpecAddendaForRun)(addendaStorePath, run.ticketIds, run.runId, { plan });
1191
+ claimedAddendaByRun.set(run.runId, claimed);
1192
+ const expected = (0, spec_addenda_1.snapshotSpecAddenda)(plan);
1193
+ if (expected.some(entry => !claimed.snapshot.some(actual => actual.ticketId === entry.ticketId && actual.id === entry.id && actual.hash === entry.hash)) || (expected.length && !claimed.briefing)) {
1194
+ throw new Error('Could not claim the complete frozen spec addenda; no implementation was started. Restore ticket storage and retry.');
1195
+ }
1196
+ (0, spec_addenda_1.broadcastSpecAddendaChange)(msg => ctx.broadcast(msg), ctx.project.id, claimed);
1197
+ }
1161
1198
  }
1162
1199
  catch (err) {
1163
1200
  for (const a of allocated) {
1201
+ if (claimedAddendaByRun.has(a.runId))
1202
+ (0, spec_addenda_1.broadcastSpecAddendaChange)(msg => ctx.broadcast(msg), ctx.project.id, (0, spec_addenda_1.settleSpecAddendaAt)(addendaStorePath, a.ticketIds, a.runId, 'failed'));
1164
1203
  if (a.worktreeOwnership === 'created') {
1165
1204
  await remove(git, {
1166
1205
  repoDir: baseRepo,
@@ -1265,16 +1304,13 @@ async function launchIsolatedRail(input, io = {}) {
1265
1304
  requiresTerminalIntent: true,
1266
1305
  });
1267
1306
  const spec = ctx.getTicketSpec(a.ticketId);
1268
- const claimedAddenda = (0, spec_addenda_1.claimSpecAddendaForRun)(addendaStorePath, a.ticketIds, a.runId, {
1269
- plan: addendaPlan.filter((e) => a.ticketIds.includes(e.ticketId)).map((entry) => launchContinuation || input.revision || input.repositoryContinuation
1270
- ? { ...entry, status: 'on_review' } : entry),
1271
- });
1272
- (0, spec_addenda_1.broadcastSpecAddendaChange)((msg) => ctx.broadcast(msg), ctx.project.id, claimedAddenda);
1307
+ const claimedAddenda = claimedAddendaByRun.get(a.runId);
1273
1308
  const enginePromise = ctx.loopRunManager.run({
1274
1309
  runtimeProviderOverride: input.runtimeProviderOverride,
1275
- runId: a.runId, loopId, loopName, graph: loopGraph, projectId: ctx.project.id,
1310
+ runId: a.runId, loopId, loopName, graph: loopGraph, projectId: ctx.project.id, launchConfig: input.launchConfig,
1276
1311
  cwd: a.handle.worktreePath, repoDir: a.handle.worktreePath,
1277
1312
  repositoryId: singleRepositoryId,
1313
+ workspacePaths: singleRepositoryId ? input.workspaceSelection?.[singleRepositoryId] : undefined,
1278
1314
  isolation: { branch: a.handle.branch, worktreePath: a.handle.worktreePath },
1279
1315
  railIndex, ticketId: a.ticketIds.length ? a.ticketId : null,
1280
1316
  spec: {
@@ -75,6 +75,12 @@ function coerceRailLaunchProposal(value) {
75
75
  const mode = modeRaw === 'batch' || modeRaw === 'batch-implement' ? 'implement' : modeRaw;
76
76
  if (!exports.RAIL_LAUNCH_MODES.includes(mode))
77
77
  return { ok: false, reason: 'invalid_mode' };
78
+ const repositoryIds = value.repositoryIds;
79
+ const workspaceSelection = value.workspaceSelection;
80
+ if (repositoryIds !== undefined && (!Array.isArray(repositoryIds) || !repositoryIds.length || repositoryIds.length > 50 || repositoryIds.some(id => typeof id !== 'string' || !id.trim()) || new Set(repositoryIds).size !== repositoryIds.length))
81
+ return { ok: false, reason: 'invalid_workspace_selection' };
82
+ if (workspaceSelection !== undefined && (!isRecord(workspaceSelection) || !Object.keys(workspaceSelection).length || Object.keys(workspaceSelection).length > 50 || Object.entries(workspaceSelection).some(([id, paths]) => !id.trim() || !Array.isArray(paths) || !paths.length || paths.length > 50 || paths.some(item => typeof item !== 'string' || !item.trim() || item.length > 4096) || new Set(paths).size !== paths.length)))
83
+ return { ok: false, reason: 'invalid_workspace_selection' };
78
84
  const newRailRaw = value.newRail;
79
85
  const newRail = newRailRaw === true
80
86
  ? { name: null }
@@ -89,6 +95,8 @@ function coerceRailLaunchProposal(value) {
89
95
  railIndex,
90
96
  newRail,
91
97
  ticketIds,
98
+ ...(repositoryIds !== undefined ? { repositoryIds: repositoryIds } : {}),
99
+ ...(workspaceSelection !== undefined ? { workspaceSelection: workspaceSelection } : {}),
92
100
  mode: mode,
93
101
  loopId: optString(value.loopId, 120),
94
102
  aiEngine: optString(value.aiEngine ?? value.provider ?? value.engine, 80),
@@ -101,11 +101,11 @@ function createPrDelivery(db, input) {
101
101
  loop_name, origin_surface, origin_conversation_id,
102
102
  implementation_outcome, delivery_outcome, status_code,
103
103
  is_continuation, supersedes_delivery_id, spec_snapshot,
104
- revision_note, revision_of, parent_delivery_id, repository_id, repository_path, follow_up, spec_addenda
104
+ revision_note, revision_of, parent_delivery_id, repository_id, repository_path, follow_up, spec_addenda, launch_config_json
105
105
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'running', 'pending',
106
- 'implementation_running', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.railIndex, input.loopId ?? null, input.railKey, JSON.stringify(input.ticketIds), input.baseBranch, input.loopName, input.originSurface, input.originConversationId ?? null, input.isContinuation ? 1 : 0, input.supersedesDeliveryId ?? null, input.specSnapshot && input.specSnapshot.length > 0
106
+ 'implementation_running', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.railIndex, input.loopId ?? null, input.railKey, JSON.stringify(input.ticketIds), input.baseBranch, input.loopName, input.originSurface, input.originConversationId ?? null, input.isContinuation ? 1 : 0, input.supersedesDeliveryId ?? null, input.specSnapshot && input.specSnapshot.length > 0
107
107
  ? JSON.stringify(boundSpecSnapshot(input.specSnapshot))
108
- : null, input.revisionNote ? boundRevisionNote(input.revisionNote) : null, input.revisionOf ?? null, input.parentDeliveryId ?? null, input.repositoryId ?? null, input.repositoryPath ?? null, input.followUp ? JSON.stringify(input.followUp) : null, input.specAddenda && input.specAddenda.length > 0 ? JSON.stringify(input.specAddenda) : null);
108
+ : null, input.revisionNote ? boundRevisionNote(input.revisionNote) : null, input.revisionOf ?? null, input.parentDeliveryId ?? null, input.repositoryId ?? null, input.repositoryPath ?? null, input.followUp ? JSON.stringify(input.followUp) : null, input.specAddenda && input.specAddenda.length > 0 ? JSON.stringify(input.specAddenda) : null, input.launchConfig ? JSON.stringify(input.launchConfig) : null);
109
109
  return getPrDelivery(db, id);
110
110
  }
111
111
  /**
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RailRelaunchError = void 0;
4
+ exports.resolveRailRelaunch = resolveRailRelaunch;
5
+ exports.assertRelaunchRail = assertRelaunchRail;
6
+ exports.restoreRelaunchRail = restoreRelaunchRail;
7
+ const loop_runs_store_1 = require("../../loops/runtime/loop-runs-store");
8
+ const rail_pr_store_1 = require("./rail-pr-store");
9
+ const rails_store_1 = require("./rails-store");
10
+ class RailRelaunchError extends Error {
11
+ code;
12
+ action;
13
+ constructor(code, detail, action) {
14
+ super(detail);
15
+ this.code = code;
16
+ this.action = action;
17
+ }
18
+ }
19
+ exports.RailRelaunchError = RailRelaunchError;
20
+ function jsonObject(raw) {
21
+ if (!raw)
22
+ return undefined;
23
+ const value = JSON.parse(raw);
24
+ if (!value || typeof value !== 'object' || Array.isArray(value))
25
+ throw new Error('Invalid saved launch configuration');
26
+ return value;
27
+ }
28
+ function historicalConfig(run) {
29
+ if (!run)
30
+ return {};
31
+ const request = jsonObject(run.run_request_json);
32
+ return {
33
+ mode: 'loop',
34
+ ...(run.loop_id ? { loopId: run.loop_id } : {}),
35
+ ...(run.provider ? { aiEngine: run.provider } : {}),
36
+ ...(run.model ? { model: run.model } : {}),
37
+ ...(run.reasoning_effort ? { reasoning_effort: run.reasoning_effort } : {}),
38
+ // These are launch options, not the old cwd, worktree, graph or run id.
39
+ ...(request?.profileName !== undefined ? { profileName: request.profileName } : {}),
40
+ ...(request?.runtimeProviderOverride ? { runtimeProviderOverride: request.runtimeProviderOverride } : {}),
41
+ ...(request?.repositoryId ? { repositoryIds: [request.repositoryId] } : {}),
42
+ ...(request?.repositoryId && request.workspacePaths ? { workspaceSelection: { [String(request.repositoryId)]: request.workspacePaths } } : {}),
43
+ };
44
+ }
45
+ function unavailable(code, detail) {
46
+ throw new RailRelaunchError(code, detail, 'Refresh the mission and configure a fresh launch on a free rail.');
47
+ }
48
+ /** Per-ticket launches share a rail but settle independently. A later sibling
49
+ * is not a replacement; only a run covering one of this source's specs is. */
50
+ function latestOverlappingRun(c, railIndex, ticketIds) {
51
+ const ids = JSON.stringify(ticketIds);
52
+ return c.db.prepare(`SELECT id, status FROM loop_runs
53
+ WHERE rail_index = ? AND (ticket_id IN (SELECT value FROM json_each(?))
54
+ OR EXISTS (SELECT 1 FROM json_each(COALESCE(ticket_ids_json, '[]')) AS ticket
55
+ WHERE ticket.value IN (SELECT value FROM json_each(?))))
56
+ ORDER BY rowid DESC LIMIT 1`).get(railIndex, ids, ids);
57
+ }
58
+ /** Resolve the source in this project's database. A card never authorizes the
59
+ * current contents of its mutable rail slot, or arbitrary launch overrides. */
60
+ function resolveRailRelaunch(c, railIndex, sourceId) {
61
+ if (typeof sourceId !== 'string' || !/^(?:run:)?[A-Za-z0-9-]{1,128}$/.test(sourceId)) {
62
+ unavailable('invalid_relaunch_source', 'Relaunch requires the original delivery or run id.');
63
+ }
64
+ let ticketIds, config, delivery;
65
+ if (sourceId.startsWith('run:')) {
66
+ const run = (0, loop_runs_store_1.getLoopRun)(c.db, sourceId.slice(4));
67
+ if (!run || run.project_id !== c.project.id || run.rail_index !== railIndex)
68
+ unavailable('relaunch_source_missing', 'The original run is unavailable in this project and rail.');
69
+ if (run.status !== 'completed')
70
+ unavailable('relaunch_source_active', 'The original run is still active or paused.');
71
+ ticketIds = JSON.parse(run.ticket_ids_json ?? '[]');
72
+ if (!ticketIds.length && run.ticket_id != null)
73
+ ticketIds = [run.ticket_id];
74
+ config = jsonObject(run.launch_config_json) ?? historicalConfig(run);
75
+ const newer = latestOverlappingRun(c, railIndex, ticketIds);
76
+ if (newer?.id !== run.id || (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex))
77
+ unavailable('relaunch_source_stale', 'Another attempt has already replaced this run on the rail.');
78
+ }
79
+ else {
80
+ const row = (0, rail_pr_store_1.getPrDelivery)(c.db, sourceId);
81
+ if (!row || row.rail_index !== railIndex || row.parent_delivery_id)
82
+ unavailable('relaunch_source_missing', 'The original delivery is unavailable in this project and rail.');
83
+ delivery = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
84
+ if (!['implementation_failed', 'pr_failed'].includes(row.decision) && !(row.decision === 'discarded' && ['delivery_failed', 'cancelled'].includes(row.status_code ?? ''))) {
85
+ unavailable('relaunch_source_stale', 'The original delivery is no longer a failed attempt awaiting relaunch.');
86
+ }
87
+ if (row.operation_token)
88
+ unavailable('relaunch_source_busy', 'A delivery operation is still in progress.');
89
+ const active = (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex);
90
+ const latest = c.db.prepare('SELECT id FROM rail_pr_deliveries WHERE rail_index = ? AND parent_delivery_id IS NULL ORDER BY rowid DESC LIMIT 1').get(railIndex);
91
+ if (active ? active.id !== sourceId : latest?.id !== sourceId)
92
+ unavailable('relaunch_source_stale', 'Another delivery has already replaced this attempt on the rail.');
93
+ ticketIds = delivery.ticketIds;
94
+ const run = delivery.runIds.map(id => (0, loop_runs_store_1.getLoopRun)(c.db, id)).find(Boolean);
95
+ const savedConfig = jsonObject(row.launch_config_json);
96
+ config = savedConfig ?? {
97
+ mode: 'loop',
98
+ ...historicalConfig(run),
99
+ ...(row.loop_id ? { loopId: row.loop_id } : {}),
100
+ ...(delivery.followUp ? { targetPrNumber: delivery.prNumber, followUp: delivery.followUp } : {}),
101
+ };
102
+ // Always retain the admitted base; ordinary launch defaults may have changed.
103
+ if (!config.baseBranch && row.base_branch)
104
+ config.baseBranch = row.base_branch;
105
+ if (delivery.executionManifest) {
106
+ config.repositoryIds = delivery.executionManifest.selectedRepositoryIds;
107
+ config.workspaceSelection = savedConfig?.workspaceSelection ?? Object.fromEntries(delivery.executionManifest.repositories
108
+ .filter(repo => repo.selectedWorkspacePaths).map(repo => [repo.repositoryId, repo.selectedWorkspacePaths]));
109
+ }
110
+ }
111
+ if (!Array.isArray(ticketIds) || !ticketIds.length || ticketIds.some(id => !Number.isSafeInteger(id) || id <= 0))
112
+ unavailable('relaunch_specs_unavailable', 'The original spec set is unavailable.');
113
+ if (typeof config.loopId !== 'string' || !config.loopId)
114
+ unavailable('relaunch_config_unavailable', 'The original workflow was not recorded; Relaunch cannot safely choose a replacement.');
115
+ // Revision identity belongs to the old generation. Retry uses the original
116
+ // complete spec set and the separate atomic retryOfDelivery contract.
117
+ const { revisionOfDeliveryId: _revisionId, revisionNote: _revisionNote, ...retryConfig } = config;
118
+ const source = { sourceId, ticketIds, config: retryConfig, delivery };
119
+ assertRelaunchRail(c, railIndex, source);
120
+ return source;
121
+ }
122
+ function assertRelaunchRail(c, railIndex, source) {
123
+ if (!(0, rails_store_1.railExists)(c.db, railIndex))
124
+ unavailable('relaunch_rail_missing', 'The original rail was removed.');
125
+ const rail = (0, rails_store_1.getRail)(c.db, railIndex);
126
+ if (rail.ticketIds.length && (rail.ticketIds.length !== source.ticketIds.length || rail.ticketIds.some(id => !source.ticketIds.includes(id)))) {
127
+ unavailable('relaunch_rail_changed', 'This rail now contains different specs. Relaunch has not changed or launched them.');
128
+ }
129
+ if (source.delivery) {
130
+ const current = (0, rail_pr_store_1.getPrDelivery)(c.db, source.sourceId);
131
+ const active = (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex);
132
+ const latest = c.db.prepare('SELECT id FROM rail_pr_deliveries WHERE rail_index = ? AND parent_delivery_id IS NULL ORDER BY rowid DESC LIMIT 1').get(railIndex);
133
+ if (!current || current.decision !== source.delivery.decision || current.operation_token || (active ? active.id !== current.id : latest?.id !== current.id)) {
134
+ unavailable('relaunch_source_stale', 'The original delivery changed while Relaunch was being prepared.');
135
+ }
136
+ }
137
+ else {
138
+ const latest = latestOverlappingRun(c, railIndex, source.ticketIds);
139
+ if (latest?.id !== source.sourceId.slice(4) || latest.status !== 'completed' || (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex)) {
140
+ unavailable('relaunch_source_stale', 'The original run changed while Relaunch was being prepared.');
141
+ }
142
+ }
143
+ return rail;
144
+ }
145
+ /** Called after preflight, immediately before admission. Empty assignment is
146
+ * terminal cleanup; a different assignment remains the user's current work. */
147
+ function restoreRelaunchRail(c, railIndex, source) {
148
+ const rail = assertRelaunchRail(c, railIndex, source);
149
+ if (!rail.ticketIds.length) {
150
+ (0, rails_store_1.setRailTickets)(c.db, railIndex, source.ticketIds, String(source.config.mode ?? 'implement'), typeof source.config.profileName === 'string' ? source.config.profileName : null, typeof source.config.aiEngine === 'string' ? source.config.aiEngine : null);
151
+ return true;
152
+ }
153
+ return false;
154
+ }