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
@@ -7,6 +7,7 @@ exports.readFrozenRuntimeHost = readFrozenRuntimeHost;
7
7
  exports.runAgentRuntimeInvocation = runAgentRuntimeInvocation;
8
8
  exports.assertRetainedForkSupport = assertRetainedForkSupport;
9
9
  exports.runAgentRuntimeControl = runAgentRuntimeControl;
10
+ const agent_runtime_verification_suggestions_1 = require("./agent-runtime-verification-suggestions");
10
11
  const agent_runtime_history_1 = require("./agent-runtime-history");
11
12
  const agent_runtime_repositories_1 = require("./agent-runtime-repositories");
12
13
  const node_util_1 = require("node:util");
@@ -32,15 +33,126 @@ function runtimeChangeName(runId) {
32
33
  * cwd is relative to the registered directory; one already inside the scope is kept.
33
34
  */
34
35
  function scopedHostChecks(checks, repositories = []) {
35
- return checks.map(check => {
36
- const scope = repositories.find(repository => repository.id === check.repositoryId)?.scope?.[0];
37
- if (!scope || (check.cwd !== undefined && (0, node_path_1.isAbsolute)(check.cwd)))
38
- return check;
39
- const cwd = (check.cwd ?? '.').replace(/\\/g, '/');
40
- const inside = cwd === scope || cwd.startsWith(scope + '/');
41
- return { ...check, cwd: inside ? cwd : node_path_1.posix.normalize(node_path_1.posix.join(scope, cwd)) };
36
+ return checks.flatMap(check => {
37
+ const repository = repositories.find(repository => repository.id === check.repositoryId);
38
+ const scopes = repository?.scope;
39
+ if (!repository || !scopes?.length)
40
+ return [check];
41
+ if (check.cwd === undefined)
42
+ return scopes.map((scope, index) => ({ ...check, cwd: scope,
43
+ ...(check.key && scopes.length > 1 ? { key: check.key.slice(0, 90) + '-workspace-' + index } : {}),
44
+ }));
45
+ const declared = repository.registeredScope;
46
+ const inputCwd = check.cwd.replace(/\\/g, '/');
47
+ const rawCwd = (0, node_path_1.isAbsolute)(inputCwd) && repository.path ? (0, node_path_1.relative)(repository.path, inputCwd).split(node_path_1.sep).join('/') : inputCwd;
48
+ if (!(0, node_path_1.isAbsolute)(rawCwd) && declared?.some(root => rawCwd === root || rawCwd.startsWith(root + '/')) && !scopes.some(root => rawCwd === root || rawCwd.startsWith(root + '/')))
49
+ return [];
50
+ let cwd = check.cwd.replace(/\\/g, '/');
51
+ if ((0, node_path_1.isAbsolute)(cwd)) {
52
+ if (!repository.path)
53
+ throw new Error('Verification workspace root is unavailable');
54
+ cwd = (0, node_path_1.relative)(repository.path, cwd).split(node_path_1.sep).join('/');
55
+ }
56
+ else {
57
+ const normalized = node_path_1.posix.normalize(cwd);
58
+ if (scopes.some(scope => cwd === scope || cwd.startsWith(scope + '/')))
59
+ cwd = normalized;
60
+ else if (scopes.length === 1)
61
+ cwd = node_path_1.posix.join(scopes[0], normalized);
62
+ else
63
+ throw new Error('Verification must select an explicit workspace cwd when several scopes are configured');
64
+ }
65
+ cwd = node_path_1.posix.normalize(cwd);
66
+ if (!scopes.some(root => cwd === root || cwd.startsWith(root + '/')))
67
+ throw new Error(`Verification cwd ${JSON.stringify(check.cwd)} escapes the selected code workspace ${scopes.join(', ')}`);
68
+ return [{ ...check, cwd }];
42
69
  });
43
70
  }
71
+ /** Discover only checks belonging to the admitted worktrees. Explicit host
72
+ * checks win; inferred commands are frozen per run, never saved to project settings. */
73
+ function completeHostChecks(config, repositories) {
74
+ for (const repository of repositories) {
75
+ if (config.verification.some(check => check.repositoryId === repository.id) || !repository.path)
76
+ continue;
77
+ const workspacePaths = (repository.scope?.length ? repository.scope.map(scope => (0, node_path_1.resolve)(repository.path, scope)) : [repository.path]).filter(workspace => (0, node_fs_1.existsSync)(workspace));
78
+ const root = (0, node_fs_1.realpathSync)(repository.path);
79
+ for (const workspace of workspacePaths) {
80
+ const inside = (0, node_path_1.relative)(root, (0, node_fs_1.realpathSync)(workspace));
81
+ if ((0, node_path_1.isAbsolute)(inside) || inside === '..' || inside.startsWith('..' + node_path_1.sep))
82
+ throw new Error('Verification workspace escapes its admitted repository');
83
+ }
84
+ const suggestions = (0, agent_runtime_verification_suggestions_1.suggestVerificationCommands)([{ id: repository.id, path: repository.path, workspacePaths }]);
85
+ config.verification.push(...suggestions.map(({ reason: _reason, ...check }) => check));
86
+ }
87
+ }
88
+ /** Configured-only gates cannot obtain missing checks from an agent later. */
89
+ function requiresConfiguredChecks(value) {
90
+ if (!value || typeof value !== 'object')
91
+ return false;
92
+ const body = value;
93
+ return Object.values(body.nodes ?? {}).some(node => node.kind === 'verify' && node.params?.commands === 'configured' && !node.params.additionalCommandsFrom && node.params.unverified !== true)
94
+ || Object.values(body.components ?? {}).some(requiresConfiguredChecks);
95
+ }
96
+ /** Keep TAP failure diagnostics and totals in the readable log. The unfiltered
97
+ * event stream remains available as runtime evidence. State is invocation-local. */
98
+ function verificationLogFilter() {
99
+ const streams = new Map();
100
+ return text => (0, node_util_1.stripVTControlCharacters)(text).split(/(?<=\n)/).flatMap(line => {
101
+ const match = line.match(/^(\[verification [^\]]+\] )?(.*?)(?:\n)?$/);
102
+ if (!match)
103
+ return [line];
104
+ const key = match[1] ?? '', body = match[2].trim();
105
+ const state = streams.get(key) ?? { tap: false, failed: false, yaml: false, inputLines: null };
106
+ streams.set(key, state);
107
+ if (/AssertionError\b.*\bInput:\s*$/.test(body))
108
+ state.inputLines = 0;
109
+ else if (state.inputLines !== null) {
110
+ // Node prints assert.match's entire source input as quoted concatenation
111
+ // lines. Bound only that block; stacks, expected values and other streams
112
+ // remain visible and original events remain intact.
113
+ if (/^["'`]/.test(body)) {
114
+ state.inputLines++;
115
+ if (state.inputLines > 2)
116
+ return state.inputLines === 3 ? [key + '[Assertion input shortened; inspect raw evidence]\n'] : [];
117
+ }
118
+ else if (!body)
119
+ return [];
120
+ else
121
+ state.inputLines = null;
122
+ }
123
+ if (/^[✔✓]\s/.test(body))
124
+ return [];
125
+ if (/^[✖✗]\s/.test(body)) {
126
+ state.failed = true;
127
+ return [line];
128
+ }
129
+ if (/^TAP version |^# Subtest:/.test(body)) {
130
+ state.tap = true;
131
+ return [];
132
+ }
133
+ if (/^(?:not )?ok \d+\b/.test(body)) {
134
+ state.tap = true;
135
+ state.failed = body.startsWith('not ok');
136
+ state.yaml = false;
137
+ return state.failed ? [line] : [];
138
+ }
139
+ if (!state.tap)
140
+ return [line];
141
+ if (body === '---') {
142
+ state.yaml = true;
143
+ return state.failed ? [line] : [];
144
+ }
145
+ if (body === '...') {
146
+ state.yaml = false;
147
+ return state.failed ? [line] : [];
148
+ }
149
+ if (state.yaml)
150
+ return state.failed ? [line] : [];
151
+ if (/^1\.\.\d+$/.test(body) || !body)
152
+ return [];
153
+ return [line];
154
+ }).map(line => line.length > 2_000 ? line.slice(0, 1_900) + '\n[Long diagnostic line shortened; inspect raw evidence]\n' : line).join('');
155
+ }
44
156
  exports.RUNTIME_HOST_ENV_KEYS = [
45
157
  'SPECRAILS_REPO_DIR', 'SPECRAILS_GIT_AUTO', 'SPECRAILS_REPO_MAP_PATH',
46
158
  'SPECRAILS_EXECUTION_CONTEXT', 'SPECRAILS_EXECUTION_MANIFEST', 'SPECRAILS_REPOSITORIES',
@@ -80,7 +192,7 @@ function readFrozenRuntimeHost(contextPath, baseEnv, runId) {
80
192
  * rail's cancellation and worktree ownership remain in Desktop. */
81
193
  async function runAgentRuntimeInvocation(options) {
82
194
  const definitionEngine = options.engineVersion === 2 || options.definitionPath !== undefined || options.prepareDefinition !== undefined;
83
- if (options.resume && (options.definitionPath || options.prepareDefinition || options.workflowRoleBindings))
195
+ if (options.resume && (options.definitionPath || options.prepareDefinition || options.workflowRoleBindings || options.loopConfig))
84
196
  throw new Error('Resume must use the frozen workflow definition and role bindings');
85
197
  const selectedCli = options.resume ? (0, agent_runtime_package_1.resolveRetainedAgentRuntime)(options.contextPath) : (0, agent_runtime_loader_1.findCoreAgentRuntimeCli)();
86
198
  let cli = selectedCli;
@@ -96,11 +208,14 @@ async function runAgentRuntimeInvocation(options) {
96
208
  if (!Array.isArray(admittedContext.repositories) || !admittedContext.repositories.length || admittedContext.repositories.some(repo => !repo || typeof repo.id !== 'string' || !repo.id))
97
209
  throw new Error('Core context is missing its repository scope');
98
210
  const source = (0, node_fs_1.existsSync)(options.configPath) ? 'project-role' : 'default';
99
- const { config, origins } = (0, agent_runtime_effective_config_1.resolveEffectiveRuntimeConfig)((0, agent_runtime_settings_1.loadRuntimeConfigFile)(options.configPath, options.defaultProvider), {
100
- repositoryIds: admittedContext.repositories.map(repo => repo.id), source, providerOverride: options.providerOverride,
211
+ const { config, origins } = (0, agent_runtime_effective_config_1.resolveEffectiveRuntimeConfig)(options.loopConfig ? (0, agent_runtime_settings_1.loadLoopRuntimeConfig)(options.configPath, options.loopConfig, options.providerOverride ?? { provider: options.defaultProvider ?? 'claude' }) : (0, agent_runtime_settings_1.loadRuntimeConfigFile)(options.configPath, options.defaultProvider), {
212
+ repositoryIds: admittedContext.repositories.map(repo => repo.id), source: options.loopConfig ? 'loop-role' : source, providerOverride: options.loopConfig ? undefined : options.providerOverride,
101
213
  });
102
214
  config.verification = scopedHostChecks(config.verification, admittedContext.repositories);
103
- config.rolePrompts = { ...(await (0, agent_runtime_loader_1.loadCoreAgentRuntime)()).rolePromptDefaults(), ...(0, agent_runtime_settings_1.loadRuntimeRolePrompts)(), ...config.rolePrompts };
215
+ if (definitionEngine)
216
+ completeHostChecks(config, admittedContext.repositories);
217
+ if (!options.loopConfig)
218
+ config.rolePrompts = { ...(await (0, agent_runtime_loader_1.loadCoreAgentRuntime)()).rolePromptDefaults(), ...(0, agent_runtime_settings_1.loadRuntimeRolePrompts)(), ...config.rolePrompts };
104
219
  // Core rejects unknown connection keys: drop the desktop-only local-engine
105
220
  // fields (label/defaultModel/rates/supportsReasoningEffort) before Core sees it.
106
221
  const runtime = await (0, agent_runtime_loader_1.loadCoreAgentRuntime)();
@@ -119,9 +234,21 @@ async function runAgentRuntimeInvocation(options) {
119
234
  : options.definitionPath ? JSON.parse((0, node_fs_1.readFileSync)(options.definitionPath, 'utf8')) : undefined : undefined;
120
235
  if (definitionEngine && !draft)
121
236
  throw new Error('A new Core workflow requires a definition');
237
+ if (requiresConfiguredChecks(draft)) {
238
+ const missing = admittedContext.repositories.filter(repository => !config.verification.some(check => check.repositoryId === repository.id));
239
+ if (missing.length)
240
+ throw new Error(`verification_checks_missing: No configured or detected verification commands for ${missing.map(repository => repository.name ?? repository.id).join(', ')}. Configure checks in project agent-runtime settings before starting this workflow.`);
241
+ if (config.verification.length > 100)
242
+ throw new Error('verification_checks_limit: This workflow supports at most 100 verification commands. Reduce the configured checks before starting it.');
243
+ }
122
244
  const selectedOrigins = (0, agent_runtime_effective_config_1.bindWorkflowRoleSelections)(config, draft, options.workflowRoleBindings);
245
+ if (options.loopConfig && draft?.roles?.includes('loop-decider') && !config.roles?.['loop-decider'])
246
+ throw new Error('The loop must define its loop-decider agent');
123
247
  const workflowOrigins = { ...(0, agent_runtime_effective_config_1.bindWorkflowRoleDefaults)(config, draft), ...selectedOrigins };
124
- const override = options.providerOverride;
248
+ if (options.loopConfig)
249
+ for (const role of Object.keys(config.roles ?? {}))
250
+ workflowOrigins[role] = 'loop-role';
251
+ const override = options.loopConfig ? undefined : options.providerOverride;
125
252
  runtime.validateRuntimeConfig(JSON.parse(JSON.stringify(config)));
126
253
  (0, agent_runtime_loader_1.validateRequestedRoleEfforts)(runtime, config);
127
254
  cli = (0, agent_runtime_package_1.retainAgentRuntime)(cli, options.contextPath);
@@ -169,6 +296,17 @@ async function runAgentRuntimeInvocation(options) {
169
296
  const definitionFile = (0, node_path_1.join)((0, node_path_1.dirname)(options.contextPath), 'desktop-workflow-definition.json');
170
297
  const requiresVerified = definitionEngine && JSON.parse((0, node_fs_1.readFileSync)(definitionFile, 'utf8')).delivery?.requiresVerified === true;
171
298
  const frozenPath = (0, node_path_1.join)((0, node_path_1.dirname)(options.contextPath), 'desktop-runtime-config.json');
299
+ if ((0, node_fs_1.existsSync)(frozenPath)) {
300
+ const checks = JSON.parse((0, node_fs_1.readFileSync)(frozenPath, 'utf8')).verification;
301
+ for (const check of checks) {
302
+ const repository = admittedContext.repositories?.find(repo => repo.id === check.repositoryId);
303
+ const cwd = repository?.path ? (0, node_path_1.resolve)(repository.path, check.cwd ?? repository.scope?.[0] ?? '.') : check.cwd;
304
+ try {
305
+ options.onLine?.(`[verification scope] ${JSON.stringify({ repositoryId: check.repositoryId, workspace: repository?.name, cwd, command: check.command, args: check.args })}\n`);
306
+ }
307
+ catch { /* Advisory log observer. */ }
308
+ }
309
+ }
172
310
  if ((0, node_fs_1.existsSync)(frozenPath)) {
173
311
  const frozen = JSON.parse((0, node_fs_1.readFileSync)(frozenPath, 'utf8'));
174
312
  for (const [role, assignment] of [...Object.entries(frozen.agents), ...(frozen.fixer ? [['fixer', frozen.fixer]] : [])]) {
@@ -198,6 +336,7 @@ async function runAgentRuntimeInvocation(options) {
198
336
  let result;
199
337
  let graph;
200
338
  let stderr = '', summary = '', invalidProtocol = false, timedOut = false;
339
+ const stepFailures = new Map();
201
340
  let timer;
202
341
  const child = (0, node_child_process_1.spawn)((0, core_node_runtime_1.resolveCoreNodeRuntime)(), args, {
203
342
  cwd: options.cwd, env: (0, win_spawn_1.windowsSpawnEnv)(options.env), shell: false, windowsHide: true,
@@ -217,6 +356,7 @@ async function runAgentRuntimeInvocation(options) {
217
356
  callback?.();
218
357
  }
219
358
  catch { /* Logging cannot replay a workflow. */ } };
359
+ const readableVerification = verificationLogFilter();
220
360
  const lines = (0, node_readline_1.createInterface)({ input: child.stdout });
221
361
  lines.on('line', line => {
222
362
  if (line.length > 2_000_000) {
@@ -267,8 +407,17 @@ async function runAgentRuntimeInvocation(options) {
267
407
  }
268
408
  else if (event.type === 'workflow-event') {
269
409
  const payload = event.event;
270
- if (payload?.type)
271
- observe(() => options.onLine?.(`[runtime] ${payload.type}${payload.stepId ? ': ' + payload.stepId : ''}${payload.message ? ' — ' + payload.message : ''}\n`));
410
+ const kind = payload?.type === 'step_succeeded' && payload.outcome === 'fail' ? 'verification_failed' : payload?.type;
411
+ const detail = payload?.error?.message ?? payload?.message;
412
+ const stepKey = JSON.stringify([payload?.scopeId ?? null, payload?.nodePath ?? payload?.stepId ?? null]);
413
+ if (payload?.type === 'step_failed' && typeof detail === 'string' && detail.trim()) {
414
+ stepFailures.delete(stepKey);
415
+ stepFailures.set(stepKey, detail.trim().slice(0, 4_000));
416
+ }
417
+ else if (payload?.type === 'step_succeeded')
418
+ stepFailures.delete(stepKey);
419
+ if (kind)
420
+ observe(() => options.onLine?.(`[runtime] ${kind}${payload.stepId ? ': ' + payload.stepId : ''}${detail ? ' — ' + detail : ''}\n`));
272
421
  }
273
422
  else if (event.type === 'agent-event') {
274
423
  const payload = event.event;
@@ -285,7 +434,9 @@ async function runAgentRuntimeInvocation(options) {
285
434
  }
286
435
  }
287
436
  else if (event.type === 'verification-output' && typeof event.text === 'string') {
288
- observe(() => options.onLine?.((0, node_util_1.stripVTControlCharacters)(String(event.text))));
437
+ const readable = readableVerification(String(event.text));
438
+ if (readable)
439
+ observe(() => options.onLine?.(readable));
289
440
  }
290
441
  else if (event.type === 'span') {
291
442
  // Trace spans are telemetry; the raw line is already recorded for diagnostics.
@@ -321,6 +472,7 @@ async function runAgentRuntimeInvocation(options) {
321
472
  const validPause = definitionEngine && code === 2 && result?.status === 'paused';
322
473
  const failed = (!validPause && (code !== 0 || result?.status !== 'succeeded')) || invalidProtocol || timedOut || Boolean(observerError) || Boolean(acceptanceBlocked);
323
474
  const runtimeError = typeof result?.error === 'string' ? result.error : result?.error?.message;
475
+ const completionError = Array.isArray(result?.completion?.reasons) ? result.completion.reasons.filter(reason => typeof reason === 'string' && reason.trim()).join('; ').slice(0, 4_000) : '';
324
476
  const runtimeStatus = invalidProtocol || timedOut || observerError || (result?.status === 'paused' && !validPause) || (result?.status === 'succeeded' && code !== 0) ? 'failed' : acceptanceBlocked ? 'blocked' : ['succeeded', 'paused', 'failed', 'blocked', 'cancelled'].includes(result?.status ?? '') ? result.status : 'failed';
325
477
  const errorText = observerError ?? (timedOut ? 'Programmatic workflow timed out; inspect its checkpoint before recovery'
326
478
  : invalidProtocol ? 'Core returned an invalid runtime event stream'
@@ -328,9 +480,9 @@ async function runAgentRuntimeInvocation(options) {
328
480
  : runtimeError ?? (result?.status === 'paused' ? (typeof result.pendingQuestion?.question === 'string' && result.pendingQuestion.question.trim()
329
481
  ? `Workflow awaits an answer in Agent Runtime settings: ${result.pendingQuestion.question.trim().slice(0, 500)}`
330
482
  : 'Workflow awaits approval in Agent Runtime settings')
331
- : failed ? stderr || 'Core exited without a successful programmatic workflow result' : undefined));
483
+ : failed ? completionError || [...stepFailures.values()].at(-1) || stderr || 'Core exited without a successful programmatic workflow result' : undefined));
332
484
  try {
333
- (0, agent_runtime_history_1.writeRuntimeHistory)(options.contextPath, invalidProtocol || timedOut || observerError || !result ? { status: 'failed', error: errorText } : { ...result });
485
+ (0, agent_runtime_history_1.writeRuntimeHistory)(options.contextPath, invalidProtocol || timedOut || observerError || !result ? { status: 'failed', error: errorText } : { ...result, ...(failed && errorText ? { error: errorText } : {}) });
334
486
  }
335
487
  catch { /* Projection failure cannot replay a completed execution. */ }
336
488
  resolve({
@@ -121,7 +121,7 @@ function applyRuntimeSelectionOrigins(summary, selection, runId) {
121
121
  const record = object(selection), origins = object(record?.origins);
122
122
  if (!summary || record?.schemaVersion !== 1 || record.runId !== runId || !origins)
123
123
  return summary;
124
- if (!['architect', 'developer', 'reviewer'].every(role => ['project-role', 'default', ...(role === 'developer' ? ['explicit-launch-override'] : [])].includes(String(origins[role]))))
124
+ if (!['architect', 'developer', 'reviewer'].every(role => ['loop-role', 'project-role', 'default', ...(role === 'developer' ? ['explicit-launch-override'] : [])].includes(String(origins[role]))))
125
125
  return summary;
126
126
  return { ...summary, roles: summary.roles.map(role => {
127
127
  const origin = origins[role.role];
@@ -84,7 +84,7 @@ function registerAgentRuntimeSettingsRoutes({ router, ctx }) {
84
84
  router.get('/:projectId/agent-runtime/verification-suggestions', (req, res) => {
85
85
  try {
86
86
  const project = ctx(req).project;
87
- const repositories = (0, project_repositories_1.getProjectRepositories)(project).map((repository) => ({ id: repository.id, name: repository.name, path: repository.path }));
87
+ const repositories = (0, project_repositories_1.getProjectRepositories)(project).map((repository) => ({ id: repository.id, name: repository.name, path: repository.path, workspacePath: repository.workspacePath, workspacePaths: repository.workspacePaths }));
88
88
  res.json({ repositories: repositories.map(({ id, name }) => ({ id, name })), suggestions: (0, agent_runtime_verification_suggestions_1.suggestVerificationCommands)(repositories) });
89
89
  }
90
90
  catch {
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.AgentRuntimeConfigError = exports.REVIEW_THRESHOLD_FLOORS = exports.MAX_OUTPUT_TOKENS_MAX = exports.MAX_OUTPUT_TOKENS_MIN = exports.CONTEXT_WINDOW_TOKENS_MAX = exports.CONTEXT_WINDOW_TOKENS_MIN = exports.RUNTIME_ROLE_ID = void 0;
7
7
  exports.stripDesktopConnectionFields = stripDesktopConnectionFields;
8
8
  exports.coreConnectionFieldGates = coreConnectionFieldGates;
9
+ exports.validateLoopRuntimeSettings = validateLoopRuntimeSettings;
10
+ exports.loadLoopRuntimeConfig = loadLoopRuntimeConfig;
9
11
  exports.validateAgentRuntimeConfig = validateAgentRuntimeConfig;
10
12
  exports.defaultAgentRuntimeConfig = defaultAgentRuntimeConfig;
11
13
  exports.agentRuntimeConfigPath = agentRuntimeConfigPath;
@@ -121,6 +123,46 @@ exports.REVIEW_THRESHOLD_FLOORS = {
121
123
  minScore: 70,
122
124
  aspects: { type_correctness: 60, pattern_adherence: 60, test_coverage: 60, security: 75, architectural_alignment: 60 },
123
125
  };
126
+ /** Validate a portable recipe without accepting host-owned fields or project fallbacks. */
127
+ function validateLoopRuntimeSettings(input, providers = loadRuntimeProviders()) {
128
+ if (!input || typeof input !== 'object' || Array.isArray(input) || Object.keys(input).some(key => ![
129
+ 'schemaVersion', 'agents', 'fixer', 'roles', 'rolePrompts', 'limits', 'review', 'architect', 'approvalBeforeArchive', 'efficiency', 'guardrails',
130
+ ].includes(key)))
131
+ throw new AgentRuntimeConfigError('Invalid loop agent configuration');
132
+ // "inherit" is a recipe-only assignment, resolved before Core sees it.
133
+ const portableProviders = [...providers, { id: 'inherit', kind: 'cli', cli: 'claude' }];
134
+ const config = validateAgentRuntimeConfig({ ...input, enabled: true, providers: portableProviders, verification: [] });
135
+ if (['architect', 'developer', 'reviewer', 'fixer'].some(role => !config.rolePrompts?.[role]?.trim()))
136
+ throw new AgentRuntimeConfigError('Loop agents require an explicit definition for architect, developer, reviewer and fixer');
137
+ const { enabled: _enabled, providers: _providers, verification: _checks, ...settings } = config;
138
+ return settings;
139
+ }
140
+ /** Read only repository checks from the old project file. Role migration is explicit. */
141
+ function loadLoopRuntimeConfig(file, input, selection = { provider: 'claude' }) {
142
+ let verification = [];
143
+ try {
144
+ const saved = JSON.parse(node_fs_1.default.readFileSync(file, 'utf8'));
145
+ if (!saved || typeof saved !== 'object' || Array.isArray(saved))
146
+ throw new AgentRuntimeConfigError('Saved runtime configuration must be an object');
147
+ verification = saved.verification ?? [];
148
+ }
149
+ catch (error) {
150
+ if (error.code !== 'ENOENT')
151
+ throw error;
152
+ }
153
+ const providers = loadRuntimeProviders();
154
+ const settings = validateLoopRuntimeSettings(input, providers);
155
+ const inherit = (agent) => agent.provider !== 'inherit' ? agent : {
156
+ ...agent, provider: selection.provider, model: agent.model ?? selection.model, effort: agent.effort ?? selection.effort,
157
+ };
158
+ for (const role of ROLES)
159
+ settings.agents[role] = inherit(settings.agents[role]);
160
+ if (settings.fixer)
161
+ settings.fixer = inherit(settings.fixer);
162
+ for (const [role, agent] of Object.entries(settings.roles ?? {}))
163
+ settings.roles[role] = inherit(agent);
164
+ return validateAgentRuntimeConfig({ ...settings, providers, enabled: true, verification });
165
+ }
124
166
  const CLI_PROVIDERS = ['claude', 'codex', 'gemini', 'kimi'];
125
167
  const ROLES = ['architect', 'developer', 'reviewer'];
126
168
  const schemaValidator = new ajv_1.default({ allErrors: true }).compile(agent_runtime_schema_json_1.default);
@@ -110,10 +110,16 @@ function otherSuggestions(repository) {
110
110
  function suggestVerificationCommands(repositories) {
111
111
  const out = [];
112
112
  for (const repository of repositories) {
113
- if (!repository.path || !node_fs_1.default.existsSync(repository.path))
114
- continue;
115
- const node = nodeSuggestions(repository);
116
- out.push(...(node.length ? node : otherSuggestions(repository)));
113
+ const workspaces = repository.workspacePaths ?? (repository.workspacePath ? [repository.workspacePath] : [repository.path]);
114
+ for (const workspace of workspaces) {
115
+ if (!workspace || !node_fs_1.default.existsSync(workspace))
116
+ continue;
117
+ const member = { ...repository, path: workspace };
118
+ const node = nodeSuggestions(member);
119
+ const checks = node.length ? node : otherSuggestions(member);
120
+ const cwd = node_path_1.default.relative(repository.path, workspace).split(node_path_1.default.sep).join('/');
121
+ out.push(...checks.map(check => cwd ? { ...check, cwd, reason: `${cwd}: ${check.reason}` } : check));
122
+ }
117
123
  }
118
124
  return out;
119
125
  }
@@ -4,14 +4,11 @@
4
4
  // "Launch Milestone N": order the milestone's todo specs by their declared
5
5
  // dependencies (prerequisites, then execution_order), put ONE spec on each
6
6
  // rail (mode `implement`), launch the first through the ORDINARY rails launch
7
- // route, and — when that spec's delivery settles — launch the next one STACKED
8
- // on the delivered branch, so a greenfield walking skeleton accumulates without
9
- // waiting for a merge. Launches are always sequential (the Parallel option was
10
- // removed); auto-continue is on by default and a failure always pauses. The plan lives in SQLite (survives window close, app
11
- // restart, machine sleep), advances from the delivery-settle chokepoint (the
12
- // `rail.pr_state` broadcast tapped in the project's bound broadcast — the
13
- // engine's `onLoopRunFinished` fires BEFORE the delivery row leaves
14
- // `building`, so it is only a fallback for delivery-less shared-cwd runs),
7
+ // route, and integrate each completed delivery through the guarded local decision
8
+ // path BEFORE allocating the next worktree from the integration branch. Older
9
+ // adapters without integration retain their historical stacking behavior.
10
+ // Launches are sequential; auto-continue is on by default. The plan lives in
11
+ // SQLite and retains the current delivery through integration and recovery.
15
12
  // pauses with a typed reason on any failure (never skips ahead), and is
16
13
  // visible/controllable (resume / cancel) from every surface.
17
14
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -77,6 +74,7 @@ class MilestoneChainManager {
77
74
  db;
78
75
  projectId;
79
76
  io;
77
+ integrating = new Set();
80
78
  constructor(db, projectId, io) {
81
79
  this.db = db;
82
80
  this.projectId = projectId;
@@ -218,7 +216,7 @@ class MilestoneChainManager {
218
216
  }
219
217
  /**
220
218
  * Launch a milestone. Always sequential: one spec per rail, each stacked on
221
- * the previous delivered branch. `autoAdvance` defaults to ON; turning it off
219
+ * the accumulated integration branch when integration is bound. `autoAdvance` defaults to ON; turning it off
222
220
  * parks the chain at a checkpoint after every delivered rail.
223
221
  */
224
222
  async start(n, opts = {}) {
@@ -308,7 +306,7 @@ class MilestoneChainManager {
308
306
  return;
309
307
  }
310
308
  const earlierDeliveries = (0, milestone_chain_store_1.parseLaunched)(row).filter((entry) => entry.chunk <= chunkIndex && entry.deliveryId).map((entry) => entry.deliveryId);
311
- const multiRepositoryHistory = earlierDeliveries.some((id) => this.io.getDelivery(id)?.executionManifest);
309
+ const multiRepositoryHistory = !this.io.integrateDelivery && earlierDeliveries.some((id) => this.io.getDelivery(id)?.executionManifest);
312
310
  if (!multiRepositoryHistory && head && !(await this.branchExistsSafe(head))) {
313
311
  this.pause(row, 'head_missing', { headBranch: head });
314
312
  return;
@@ -371,6 +369,56 @@ class MilestoneChainManager {
371
369
  return 'chunk_stopped';
372
370
  return 'chunk_failed';
373
371
  }
372
+ completeIntegrated(row) {
373
+ if (!row.current_delivery_id || !(0, milestone_chain_store_1.isActiveChainStatus)(row.status))
374
+ return;
375
+ (0, milestone_chain_store_1.updateChain)(this.db, row.id, row.status, { status: 'waiting', currentDeliveryId: null, currentRunIds: [], headBranch: row.integration_branch, pauseReason: 'integration_complete' }, this.now());
376
+ this.afterChunkSuccess(row.id, row.integration_branch);
377
+ }
378
+ /** Keep the delivery attached until its guarded integration is durably confirmed. */
379
+ async integrateChunk(chainId) {
380
+ if (!this.io.integrateDelivery || this.integrating.has(chainId))
381
+ return;
382
+ const row = (0, milestone_chain_store_1.getChain)(this.db, chainId);
383
+ if (!row?.current_delivery_id || !(0, milestone_chain_store_1.isActiveChainStatus)(row.status))
384
+ return;
385
+ const snap = this.io.getDelivery(row.current_delivery_id);
386
+ if (!snap) {
387
+ this.pause(row, 'integration_failed:delivery_missing');
388
+ return;
389
+ }
390
+ if (snap.implementationOutcome === 'partially_succeeded' || snap.implementationOutcome === 'failed') {
391
+ this.pauseFailedChunk(row, 'chunk_failed');
392
+ return;
393
+ }
394
+ if (snap.decision === 'merged' || snap.decision === 'completed') {
395
+ this.completeIntegrated(row);
396
+ return;
397
+ }
398
+ this.integrating.add(chainId);
399
+ (0, milestone_chain_store_1.updateChain)(this.db, row.id, row.status, { status: 'waiting', pauseReason: 'integration_pending' }, this.now());
400
+ const pending = (0, milestone_chain_store_1.getChain)(this.db, chainId);
401
+ this.emit(pending);
402
+ try {
403
+ const result = await this.io.integrateDelivery(snap);
404
+ const current = (0, milestone_chain_store_1.getChain)(this.db, chainId);
405
+ if (!current || !(0, milestone_chain_store_1.isActiveChainStatus)(current.status) || current.current_delivery_id !== snap.id)
406
+ return;
407
+ const settled = this.io.getDelivery(snap.id);
408
+ if (settled?.decision === 'merged' || settled?.decision === 'completed')
409
+ this.completeIntegrated(current);
410
+ else
411
+ this.pause(current, 'integration_failed:' + (result.ok ? 'not_confirmed' : result.error));
412
+ }
413
+ catch {
414
+ const current = (0, milestone_chain_store_1.getChain)(this.db, chainId);
415
+ if (current && (0, milestone_chain_store_1.isActiveChainStatus)(current.status) && current.current_delivery_id === snap.id)
416
+ this.pause(current, 'integration_failed:unavailable');
417
+ }
418
+ finally {
419
+ this.integrating.delete(chainId);
420
+ }
421
+ }
374
422
  /** The delivery-settle chokepoint: a `rail.pr_state` for the in-flight chunk. */
375
423
  handleDeliveryState(snap) {
376
424
  for (const row of (0, milestone_chain_store_1.listActiveChains)(this.db)) {
@@ -378,6 +426,13 @@ class MilestoneChainManager {
378
426
  continue;
379
427
  if (snap.decision === 'building')
380
428
  continue;
429
+ if (this.io.integrateDelivery && SUCCESS_DECISIONS.has(snap.decision)) {
430
+ if (row.status === 'running' || row.status === 'waiting' && row.pause_reason === 'integration_pending')
431
+ void this.integrateChunk(row.id);
432
+ else if (row.pause_reason?.startsWith('integration_') && ['merged', 'completed'].includes(snap.decision))
433
+ this.completeIntegrated(row);
434
+ continue;
435
+ }
381
436
  if (SUCCESS_DECISIONS.has(snap.decision)) {
382
437
  const delivered = snap.executionManifest ? null : snap.decision === 'no_changes'
383
438
  ? row.head_branch
@@ -457,6 +512,10 @@ class MilestoneChainManager {
457
512
  return { ok: false, status: 404, error: 'chain_not_found' };
458
513
  if (row.status !== 'paused' && row.status !== 'awaiting_approval')
459
514
  return { ok: false, status: 409, error: 'chain_not_paused', detail: `chain is ${row.status}` };
515
+ if (this.io.integrateDelivery && row.current_delivery_id && row.pause_reason?.startsWith('integration_')) {
516
+ await this.integrateChunk(id);
517
+ return { ok: true, status: 202, chain: (0, milestone_chain_store_1.toChainSnapshot)((0, milestone_chain_store_1.getChain)(this.db, id)) };
518
+ }
460
519
  if (row.head_branch && !(await this.branchExistsSafe(row.head_branch))) {
461
520
  (0, milestone_chain_store_1.updateChain)(this.db, row.id, row.status, { status: 'paused', pauseReason: 'head_missing' }, this.now());
462
521
  const fresh = (0, milestone_chain_store_1.getChain)(this.db, row.id);
@@ -503,6 +562,13 @@ class MilestoneChainManager {
503
562
  */
504
563
  async recoverOnStartup() {
505
564
  for (const row of (0, milestone_chain_store_1.listActiveChains)(this.db)) {
565
+ if (this.io.integrateDelivery && row.status === 'waiting' && row.pause_reason?.startsWith('integration_')) {
566
+ if (row.current_delivery_id)
567
+ await this.integrateChunk(row.id);
568
+ else if (row.pause_reason === 'integration_complete')
569
+ this.afterChunkSuccess(row.id, row.integration_branch);
570
+ continue;
571
+ }
506
572
  if (row.status !== 'running')
507
573
  continue;
508
574
  if (row.current_delivery_id) {
@@ -475,7 +475,7 @@ function projectDefinitionRuntimeEvidence(status, reviewerStepId) {
475
475
  if (!['succeeded', 'failed'].includes(scope.status) || !scope.attemptId || !isRecord(scope.output))
476
476
  continue;
477
477
  const output = scope.output;
478
- if (scope.kind === 'verify' && typeof output.receiptId === 'string' && Array.isArray(output.commands)) {
478
+ if ((scope.kind === 'verify' || scope.kind === 'implementation-step' && output.phase === 'verify') && typeof output.receiptId === 'string' && Array.isArray(output.commands)) {
479
479
  for (const raw of output.commands) {
480
480
  if (commands.length >= RUNTIME_LIST_CAP)
481
481
  break;
@@ -487,7 +487,8 @@ function projectDefinitionRuntimeEvidence(status, reviewerStepId) {
487
487
  }
488
488
  }
489
489
  const review = scope.status !== 'succeeded' ? null : scope.kind === 'implementation' ? parseRuntimeReview(output.review)
490
- : reviewerStepId === scope.nodePath && scope.kind === 'role-turn' ? parseRuntimeReview(output.structured ?? output) : null;
490
+ : scope.kind === 'implementation-step' && output.phase === 'reviewer' ? parseRuntimeReview(output)
491
+ : reviewerStepId === scope.nodePath && scope.kind === 'role-turn' ? parseRuntimeReview(output.structured ?? output) : null;
491
492
  if (review)
492
493
  scopedReviews.push({ nodePath: scope.nodePath, scopeId: scope.scopeId, attemptId: scope.attemptId, review });
493
494
  }
@@ -231,7 +231,7 @@ async function launchMultiRepositoryRail(input, io = {}) {
231
231
  integrationBranches.set(repo.id, target.branch);
232
232
  }
233
233
  }
234
- const previousParentId = input.revision?.ofDeliveryId ?? input.repositoryContinuation?.deliveryId;
234
+ const previousParentId = input.revision?.ofDeliveryId ?? input.repositoryContinuation?.deliveryId ?? input.retryOfDelivery?.deliveryId;
235
235
  const previousParent = previousParentId ? (0, rail_pr_store_1.getPrDelivery)(ctx.db, previousParentId) : undefined;
236
236
  const previousManifest = (0, multi_repo_execution_store_1.readExecutionManifest)(previousParent?.execution_manifest);
237
237
  const previousChildren = previousParentId ? listRepositoryDeliveries(ctx.db, previousParentId) : [];
@@ -268,12 +268,13 @@ async function launchMultiRepositoryRail(input, io = {}) {
268
268
  artifactRepositoryId, selectedRepositoryIds: selected.map((repo) => repo.id), repositories: [],
269
269
  };
270
270
  const generation = (0, rail_pr_store_1.createPrDeliveryGeneration)(ctx.db, {
271
+ launchConfig: input.launchConfig,
271
272
  id: parentId, railIndex: input.railIndex, loopId: input.loopId, railKey: `${input.railIndex}-${input.loopId}`,
272
273
  ticketIds: input.ticketIds, baseBranch: input.baseBranch ?? '', loopName: input.loopName,
273
274
  originSurface: input.originSurface ?? 'dashboard', originConversationId: input.originConversationId,
274
275
  specSnapshot: (0, rail_isolated_launch_1.buildSpecSnapshot)(ctx, input.ticketIds),
275
276
  ...(input.revision ? { revisionNote: input.revision.note, revisionOf: input.revision.ofDeliveryId } : {}),
276
- }, input.revision ? { id: input.revision.ofDeliveryId, decision: input.revision.decision } : input.repositoryContinuation ? { id: input.repositoryContinuation.deliveryId, decision: input.repositoryContinuation.decision } : null);
277
+ }, input.revision ? { id: input.revision.ofDeliveryId, decision: input.revision.decision } : input.repositoryContinuation ? { id: input.repositoryContinuation.deliveryId, decision: input.repositoryContinuation.decision } : input.retryOfDelivery ? { id: input.retryOfDelivery.deliveryId, decision: input.retryOfDelivery.decision } : null);
277
278
  for (const child of previousChildren) {
278
279
  if (!['merged', 'completed', 'discarded', 'superseded'].includes(child.decision))
279
280
  (0, rail_pr_store_1.transitionDecision)(ctx.db, child.id, child.decision, 'superseded');
@@ -315,14 +316,14 @@ async function launchMultiRepositoryRail(input, io = {}) {
315
316
  const childSettlement = deferred();
316
317
  const previous = previousChildren.find((row) => row.repository_id === repository.id);
317
318
  const previousRepository = previousManifest?.repositories.find((row) => row.repositoryId === repository.id);
318
- const previousBaseBranch = previous && ['merged', 'completed'].includes(previous.decision)
319
+ const previousBaseBranch = input.retryOfDelivery ? undefined : previous && ['merged', 'completed'].includes(previous.decision)
319
320
  ? previousRepository?.integrationBranch ?? previous.base_branch
320
321
  : previous?.base_branch;
321
322
  const oldSnapshot = previous ? (0, rail_pr_store_1.toPrDeliverySnapshot)(previous) : null;
322
323
  const revisionBranches = new Map();
323
- if (oldSnapshot && !['merged', 'completed', 'discarded'].includes(oldSnapshot.decision) && !previous?.pr_url) {
324
+ if (!input.retryOfDelivery && oldSnapshot && !['merged', 'completed', 'discarded'].includes(oldSnapshot.decision) && !previous?.pr_url) {
324
325
  for (const unit of oldSnapshot.branches) {
325
- if (unit.finalSha)
326
+ if (unit.succeeded && unit.finalSha && unit.implementationOutcome !== 'failed' && unit.deliveryOutcome !== 'blocked')
326
327
  revisionBranches.set(unit.ticketId, { branch: unit.branch, sha: unit.finalSha });
327
328
  }
328
329
  }
@@ -355,6 +356,7 @@ async function launchMultiRepositoryRail(input, io = {}) {
355
356
  ...input, ctx: childCtx, scope: effectiveScope, loopGraph: graph,
356
357
  runtimeStateProject: ctx.project,
357
358
  revision: input.revision && previous ? { ...input.revision, ofDeliveryId: previous.id, decision: previous.decision } : undefined,
359
+ retryOfDelivery: input.retryOfDelivery && previous ? { deliveryId: previous.id, decision: previous.decision } : undefined,
358
360
  requiredPrContinuation: continuation,
359
361
  explicitPrTarget: continuation?.prNumber ? { prNumber: continuation.prNumber } : input.explicitPrTarget,
360
362
  originConversationId: undefined,
@@ -389,6 +391,9 @@ async function launchMultiRepositoryRail(input, io = {}) {
389
391
  if (head.code !== 0 || !/^[a-f0-9]{40,64}$/i.test(head.stdout.trim()))
390
392
  throw new Error(`Cannot freeze HEAD for ${repository.name}`);
391
393
  manifest.repositories.push({ repositoryId: repository.id, name: repository.name, sourcePath: repository.path,
394
+ ...(repository.workspacePath ? { workspacePath: repository.workspacePath } : {}),
395
+ ...(repository.workspacePaths ? { workspacePaths: [...repository.workspacePaths] } : {}),
396
+ ...((input.workspaceSelection?.[repository.id] ?? previousRepository?.selectedWorkspacePaths) ? { selectedWorkspacePaths: [...(input.workspaceSelection?.[repository.id] ?? previousRepository.selectedWorkspacePaths)] } : {}),
392
397
  gitCommonDir: (0, repo_lock_1.repositoryLockKey)(repository.path), baseBranch: child.base_branch, integrationBranch: integrationBranches.get(repository.id) ?? previousRepository?.integrationBranch ?? child.base_branch, baseSha: head.stdout.trim(),
393
398
  worktreePath: worktree.worktree_path, branch: worktree.branch, worktreeId: worktree.id });
394
399
  }