specrails-desktop 2.64.2 → 2.65.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 (1116) hide show
  1. package/README.md +1 -1
  2. package/cli/dist/status.js +3 -0
  3. package/client/dist/assets/ActivityFeedPage-ByVKYII-.js +1 -0
  4. package/client/dist/assets/AgentBrowserCapture-BGUTjhUr.js +1 -0
  5. package/client/dist/assets/AgentModeAnalyticsPane-CtOLDDjB.js +2 -0
  6. package/client/dist/assets/AgentModeCodePane-CDhUKarT.js +2 -0
  7. package/client/dist/assets/AgentModeJobsPane-BAa_oEHJ.js +1 -0
  8. package/client/dist/assets/AgentsPage-D32hG4Ve.js +120 -0
  9. package/client/dist/assets/AnalyticsPage-BU50zeG6.js +5 -0
  10. package/client/dist/assets/BudgetCard-DP_jxwaD.js +55 -0
  11. package/client/dist/assets/CodePage-jiYnKGpp.js +3 -0
  12. package/client/dist/assets/CostValue-Bvn8674q.js +1 -0
  13. package/client/dist/assets/DesktopAnalyticsPage-CF__H4e3.js +1 -0
  14. package/client/dist/assets/DocView-RrAp70zp.js +11 -0
  15. package/client/dist/assets/DocsDialog-DkqHU-JF.js +1 -0
  16. package/client/dist/assets/DocsPage-C6X089zC.js +1 -0
  17. package/client/dist/assets/ExportDropdown-C5-o8y3K.js +1 -0
  18. package/client/dist/assets/HelpHint-Crf9_uoR.js +1 -0
  19. package/client/dist/assets/IntegrationsPage-aflU3KHK.js +1 -0
  20. package/client/dist/assets/InteractiveJobComposer-CEMMhyyJ.js +19 -0
  21. package/client/dist/assets/JobDetailModal-BVJ6hyRs.js +1 -0
  22. package/client/dist/assets/JobDetailPage-DHzBUmox.js +1 -0
  23. package/client/dist/assets/JobsPage-o-LAqkwC.js +1 -0
  24. package/client/dist/assets/LoopBuilderPage-DbSVmXBM.js +1 -0
  25. package/client/dist/assets/LoopPreviewModal-DbJcVyN1.js +1 -0
  26. package/client/dist/assets/{LoopWindowSurface-DE0v2K1p.js → LoopWindowSurface-Co1ZK26V.js} +1 -1
  27. package/client/dist/assets/LoopsPage-C4lgkPXB.js +2 -0
  28. package/client/dist/assets/MinimizedChatsContext-742ypO8n.js +1 -0
  29. package/client/dist/assets/PluginsPage-Acks9ges.js +2 -0
  30. package/client/dist/assets/RailTrack-BfLmBzBh.js +1 -0
  31. package/client/dist/assets/{RepositoryScopeSelector-2eSqR9WK.js → RepositoryScopeSelector-DcxbKI9w.js} +1 -1
  32. package/client/dist/assets/ReviewPacketPage-CAVSIOAJ.js +7 -0
  33. package/client/dist/assets/TemplatePreviewModal-C23SYCTm.js +1 -0
  34. package/client/dist/assets/TicketDetailModalContext-B-Gtm6Ob.js +23 -0
  35. package/client/dist/assets/Trans-C6J0cLyh.js +1 -0
  36. package/client/dist/assets/a11y-prefs-BqoP5goK.js +1 -0
  37. package/client/dist/assets/activity-BBWfoUOG.js +1 -0
  38. package/client/dist/assets/activity-BM_skann.js +1 -0
  39. package/client/dist/assets/activity-Cevl82ke.js +1 -0
  40. package/client/dist/assets/activity-CmACk5W5.js +1 -0
  41. package/client/dist/assets/activity-D9LBw3PQ.js +1 -0
  42. package/client/dist/assets/activity-Dspbb9lz.js +1 -0
  43. package/client/dist/assets/activity-FPjYIjv9.js +1 -0
  44. package/client/dist/assets/activity-nLCKMUKt.js +1 -0
  45. package/client/dist/assets/addspec-BI4jDMhA.js +1 -0
  46. package/client/dist/assets/addspec-BldTv7Tl.js +1 -0
  47. package/client/dist/assets/addspec-Cdq-2EcC.js +1 -0
  48. package/client/dist/assets/addspec-DH5M16BQ.js +1 -0
  49. package/client/dist/assets/addspec-DOFo9pD5.js +1 -0
  50. package/client/dist/assets/addspec-DPkwhdmL.js +1 -0
  51. package/client/dist/assets/addspec-Dzy12Pv3.js +1 -0
  52. package/client/dist/assets/addspec-skTs6EEW.js +1 -0
  53. package/client/dist/assets/agent-B_UEUy7Y.js +1 -0
  54. package/client/dist/assets/agent-BarjlhTA.js +1 -0
  55. package/client/dist/assets/agent-BfqIITo5.js +1 -0
  56. package/client/dist/assets/agent-Bt9a7Kyj.js +1 -0
  57. package/client/dist/assets/agent-C3689RwP.js +1 -0
  58. package/client/dist/assets/agent-CrmboTAi.js +1 -0
  59. package/client/dist/assets/agent-DcsoTnuE.js +1 -0
  60. package/client/dist/assets/agent-GDZoYwd4.js +1 -0
  61. package/client/dist/assets/{agentRuntime-es2ymSl-.js → agentRuntime-BYH70bKY.js} +1 -1
  62. package/client/dist/assets/agentRuntime-BijLh8I9.js +1 -0
  63. package/client/dist/assets/{agentRuntime-BzuwQQgn.js → agentRuntime-BvyuETPe.js} +1 -1
  64. package/client/dist/assets/{agentRuntime-BDvbJMmS.js → agentRuntime-C2WI6HQh.js} +1 -1
  65. package/client/dist/assets/{agentRuntime-BKJfv5YD.js → agentRuntime-CZPIlQsr.js} +1 -1
  66. package/client/dist/assets/{agentRuntime-DiCldqGG.js → agentRuntime-D2dDvCyJ.js} +1 -1
  67. package/client/dist/assets/agentRuntime-DWZedEbn.js +1 -0
  68. package/client/dist/assets/agentRuntime-DkIruUNw.js +1 -0
  69. package/client/dist/assets/agents-35_PDKx9.js +1 -0
  70. package/client/dist/assets/agents-8fZnHhEQ.js +1 -0
  71. package/client/dist/assets/agents-Bgimtw8z.js +1 -0
  72. package/client/dist/assets/agents-C4P160Us.js +1 -0
  73. package/client/dist/assets/agents-Clg67zbp.js +1 -0
  74. package/client/dist/assets/agents-DJfF4o6G.js +1 -0
  75. package/client/dist/assets/agents-Dc9-Y5cw.js +1 -0
  76. package/client/dist/assets/agents-EN1Zl4YZ.js +1 -0
  77. package/client/dist/assets/agentstudio-Bm4-NYaG.js +1 -0
  78. package/client/dist/assets/agentstudio-CD1fuj2o.js +1 -0
  79. package/client/dist/assets/agentstudio-CQGWFSst.js +1 -0
  80. package/client/dist/assets/agentstudio-CqVSb65S.js +1 -0
  81. package/client/dist/assets/agentstudio-DIE_HjsX.js +1 -0
  82. package/client/dist/assets/agentstudio-D_OmQK-k.js +1 -0
  83. package/client/dist/assets/agentstudio-Djz9aUfb.js +1 -0
  84. package/client/dist/assets/agentstudio-Qa3v9o5J.js +1 -0
  85. package/client/dist/assets/{aiedit-DNXxq_Dr.js → aiedit-1VzLs37W.js} +1 -1
  86. package/client/dist/assets/{aiedit-DCjA7jLJ.js → aiedit-BNp6GSik.js} +1 -1
  87. package/client/dist/assets/{aiedit-BoG24nlg.js → aiedit-BOY5xRPi.js} +1 -1
  88. package/client/dist/assets/{aiedit-iIjz2_Qk.js → aiedit-BrqMZvbc.js} +1 -1
  89. package/client/dist/assets/{aiedit-CjlSRQVP.js → aiedit-CVgtl7hm.js} +1 -1
  90. package/client/dist/assets/{aiedit-DQ-0_pvE.js → aiedit-CrFW9Jd2.js} +1 -1
  91. package/client/dist/assets/{aiedit-olnv3QSt.js → aiedit-YE2lILp7.js} +1 -1
  92. package/client/dist/assets/{aiedit-B0KUbpB6.js → aiedit-iA_R1AVQ.js} +1 -1
  93. package/client/dist/assets/analytics-3w0t-4ic.js +1 -0
  94. package/client/dist/assets/analytics-BRi4KQD6.js +1 -0
  95. package/client/dist/assets/analytics-BtjAqzke.js +1 -0
  96. package/client/dist/assets/analytics-COSQ1h47.js +1 -0
  97. package/client/dist/assets/analytics-CP2HjESk.js +1 -0
  98. package/client/dist/assets/analytics-DY65TC62.js +1 -0
  99. package/client/dist/assets/analytics-Den_vvxn.js +1 -0
  100. package/client/dist/assets/analytics-LmBS96O8.js +1 -0
  101. package/client/dist/assets/api-DOGbyfTO.js +2 -0
  102. package/client/dist/assets/builder-BMVvSr4v.js +1 -0
  103. package/client/dist/assets/builder-BN-MuLZt.js +1 -0
  104. package/client/dist/assets/builder-BQOZi4CF.js +1 -0
  105. package/client/dist/assets/builder-BjUPjsyu.js +1 -0
  106. package/client/dist/assets/builder-BoBtN18T.js +1 -0
  107. package/client/dist/assets/builder-C5g5NhxL.js +1 -0
  108. package/client/dist/assets/builder-RUHXw3yx.js +1 -0
  109. package/client/dist/assets/builder-fyS_AiyC.js +1 -0
  110. package/client/dist/assets/button-CHPkroew.js +1 -0
  111. package/client/dist/assets/chat-C9L5T7KI.js +1 -0
  112. package/client/dist/assets/chevron-right-CwMAj0w_.js +1 -0
  113. package/client/dist/assets/chevron-up-BAMuP0XD.js +1 -0
  114. package/client/dist/assets/chunk-OB3PAWPO-BBaq6pUk.js +3 -0
  115. package/client/dist/assets/code-4le5IIbf.js +1 -0
  116. package/client/dist/assets/code-B-jCVIbm.js +1 -0
  117. package/client/dist/assets/code-BRfrn5ix.js +1 -0
  118. package/client/dist/assets/code-CC9NCrDM.js +1 -0
  119. package/client/dist/assets/code-CK6pm8wY.js +1 -0
  120. package/client/dist/assets/code-DDiOzd6c.js +1 -0
  121. package/client/dist/assets/code-tGifiyf5.js +1 -0
  122. package/client/dist/assets/code-xkn8kQTg.js +1 -0
  123. package/client/dist/assets/commands-Bv1QshHR.js +1 -0
  124. package/client/dist/assets/commands-BvxTxboW.js +1 -0
  125. package/client/dist/assets/commands-C5ORR0fO.js +1 -0
  126. package/client/dist/assets/commands-CBKMFSTV.js +1 -0
  127. package/client/dist/assets/commands-CFJIRsJv.js +1 -0
  128. package/client/dist/assets/commands-D9o3ZcXl.js +1 -0
  129. package/client/dist/assets/commands-DNox0Edk.js +1 -0
  130. package/client/dist/assets/commands-DmIUMLdV.js +1 -0
  131. package/client/dist/assets/common-5H4TkaoI.js +1 -0
  132. package/client/dist/assets/common-9S3OdPjx.js +1 -0
  133. package/client/dist/assets/common-BqnwIcjs.js +1 -0
  134. package/client/dist/assets/common-CQP3VafS.js +1 -0
  135. package/client/dist/assets/common-CZnAfkB2.js +1 -0
  136. package/client/dist/assets/common-D5sNttV4.js +1 -0
  137. package/client/dist/assets/common-k_qX9nlv.js +1 -0
  138. package/client/dist/assets/common-s4HIi9XI.js +1 -0
  139. package/client/dist/assets/compass-B7guwBlY.js +1 -0
  140. package/client/dist/assets/confirm-dialog-ChZdHL3Q.js +1 -0
  141. package/client/dist/assets/copy-DOPlLymH.js +1 -0
  142. package/client/dist/assets/core-BozBzB6Y.js +1 -0
  143. package/client/dist/assets/dashboard-6zGLGcEz.js +1 -0
  144. package/client/dist/assets/dashboard-8Gi0FBDq.js +1 -0
  145. package/client/dist/assets/dashboard-B7E5YrSy.js +1 -0
  146. package/client/dist/assets/dashboard-BhdKV8xK.js +1 -0
  147. package/client/dist/assets/dashboard-Bu3zzH_s.js +1 -0
  148. package/client/dist/assets/dashboard-Ce_6rELA.js +1 -0
  149. package/client/dist/assets/dashboard-DWY-oz8P.js +1 -0
  150. package/client/dist/assets/dashboard-gUzlWk0o.js +1 -0
  151. package/client/dist/assets/date-input-Cdlr8kHz.js +1 -0
  152. package/client/dist/assets/dialog-C23lB2iP.js +5 -0
  153. package/client/dist/assets/dist-Di-oOFkX.js +1 -0
  154. package/client/dist/assets/dist-js-CBmS6MsJ.js +1 -0
  155. package/client/dist/assets/{dist-js-Rlh4FLH5.js → dist-js-DaJmKapi.js} +1 -1
  156. package/client/dist/assets/dropdown-menu-Bfp2CK6H.js +1 -0
  157. package/client/dist/assets/empty-state-D5w9OWj-.js +1 -0
  158. package/client/dist/assets/es2015-DfnECntk.js +41 -0
  159. package/client/dist/assets/esm-BKF6CE7v.js +1 -0
  160. package/client/dist/assets/event-BEnMLqAi.js +1 -0
  161. package/client/dist/assets/explore--NOz9LCN.js +1 -0
  162. package/client/dist/assets/explore-B2ulH6dO.js +1 -0
  163. package/client/dist/assets/explore-BD-QiLdg.js +1 -0
  164. package/client/dist/assets/explore-BOqd4_1j.js +1 -0
  165. package/client/dist/assets/explore-Be_Zh5zu.js +1 -0
  166. package/client/dist/assets/explore-CLjzPSKo.js +1 -0
  167. package/client/dist/assets/explore-D_-vHm29.js +1 -0
  168. package/client/dist/assets/explore-yEQTF6ro.js +1 -0
  169. package/client/dist/assets/file-text-CNXzL3wj.js +1 -0
  170. package/client/dist/assets/format-BODoFIw6.js +1 -0
  171. package/client/dist/assets/formatDistanceToNow-DLMIOS0N.js +1 -0
  172. package/client/dist/assets/getTimezoneOffsetInMilliseconds-O61feXch.js +1 -0
  173. package/client/dist/assets/git-compare-arrows-Cu6tICCq.js +1 -0
  174. package/client/dist/assets/humanise-command-CB4ybLwq.js +1 -0
  175. package/client/dist/assets/inbox-BLZ8cm6_.js +1 -0
  176. package/client/dist/assets/inbox-BQ3VmNYY.js +1 -0
  177. package/client/dist/assets/inbox-BdcXWCuT.js +1 -0
  178. package/client/dist/assets/inbox-CF1PHjns.js +1 -0
  179. package/client/dist/assets/inbox-CFNPDhso.js +1 -0
  180. package/client/dist/assets/inbox-DIttK_NW.js +1 -0
  181. package/client/dist/assets/inbox-Dfdv1Ykl.js +1 -0
  182. package/client/dist/assets/inbox-JS1inmeO.js +1 -0
  183. package/client/dist/assets/index-4UWY7Xyz.css +2 -0
  184. package/client/dist/assets/index-DHzB0T26.js +120 -0
  185. package/client/dist/assets/integrations-BcKgzgPD.js +1 -0
  186. package/client/dist/assets/integrations-BmX_XyJq.js +1 -0
  187. package/client/dist/assets/integrations-CHpwMjlY.js +1 -0
  188. package/client/dist/assets/integrations-CT3kr8e-.js +1 -0
  189. package/client/dist/assets/integrations-C_5XAkgz.js +1 -0
  190. package/client/dist/assets/integrations-Ct9zLX7N.js +1 -0
  191. package/client/dist/assets/integrations-DEYemxUv.js +1 -0
  192. package/client/dist/assets/integrations-DWvsB_WB.js +1 -0
  193. package/client/dist/assets/{jira-Cq6yvN4q.js → jira-B_ERkFRv.js} +1 -1
  194. package/client/dist/assets/jira-Bn-A5lwD.js +1 -0
  195. package/client/dist/assets/jira-C71Ybnhp.js +1 -0
  196. package/client/dist/assets/jira-CkwjeJz6.js +1 -0
  197. package/client/dist/assets/jira-D9pSLXjI.js +1 -0
  198. package/client/dist/assets/jira-DBRS_lcp.js +1 -0
  199. package/client/dist/assets/jira-DHS6CsKh.js +1 -0
  200. package/client/dist/assets/jira-MInHRUb1.js +1 -0
  201. package/client/dist/assets/jira-api-DHme7Upx.js +1 -0
  202. package/client/dist/assets/jobs-BMLTDo63.js +1 -0
  203. package/client/dist/assets/jobs-BO8q4Mi1.js +1 -0
  204. package/client/dist/assets/jobs-Ck8uOWMM.js +1 -0
  205. package/client/dist/assets/jobs-CyFfPCpg.js +1 -0
  206. package/client/dist/assets/jobs-DT5s4fZ6.js +1 -0
  207. package/client/dist/assets/jobs-DZAgVPcD.js +1 -0
  208. package/client/dist/assets/jobs-b5gPYaKr.js +1 -0
  209. package/client/dist/assets/jobs-xsZK1440.js +1 -0
  210. package/client/dist/assets/launch-forecast-BTa-p3RP.js +1 -0
  211. package/client/dist/assets/{loop-layout-DtxX27Jz.css → loop-layout-DLioOiRN.css} +1 -1
  212. package/client/dist/assets/loop-layout-Sl9cfTvs.js +7 -0
  213. package/client/dist/assets/loops-BEEOVJDR.js +1 -0
  214. package/client/dist/assets/loops-BcrQ2vk7.js +1 -0
  215. package/client/dist/assets/loops-BjWxzJIZ.js +1 -0
  216. package/client/dist/assets/loops-BogV595N.js +1 -0
  217. package/client/dist/assets/loops-CU0BLZiz.js +1 -0
  218. package/client/dist/assets/loops-CrNBgi1G.js +1 -0
  219. package/client/dist/assets/loops-CwalwS_i.js +1 -0
  220. package/client/dist/assets/loops-_TDVN-fX.js +1 -0
  221. package/client/dist/assets/mcp-BNs8gxoL.js +1 -0
  222. package/client/dist/assets/mcp-BvRh_xO5.js +1 -0
  223. package/client/dist/assets/mcp-C2F1pghi.js +1 -0
  224. package/client/dist/assets/mcp-D9RLKAs2.js +1 -0
  225. package/client/dist/assets/mcp-DAghcsR0.js +1 -0
  226. package/client/dist/assets/mcp-DWWAPi1G.js +1 -0
  227. package/client/dist/assets/mcp-DbGSFC3f.js +1 -0
  228. package/client/dist/assets/mcp-FelCicrv.js +1 -0
  229. package/client/dist/assets/narration-C3NBkAR4.js +1 -0
  230. package/client/dist/assets/narration-CkoJq-Lf.js +1 -0
  231. package/client/dist/assets/narration-Cr0NeW9K.js +1 -0
  232. package/client/dist/assets/narration-DJUXOs-W.js +1 -0
  233. package/client/dist/assets/narration-DgL8TMvN.js +1 -0
  234. package/client/dist/assets/narration-DjBafgv0.js +1 -0
  235. package/client/dist/assets/narration-Dle6Iv0c.js +1 -0
  236. package/client/dist/assets/narration-MYlfktga.js +1 -0
  237. package/client/dist/assets/nav-BSQ8KW1c.js +1 -0
  238. package/client/dist/assets/nav-BauVof8Z.js +1 -0
  239. package/client/dist/assets/nav-BfOAH1se.js +1 -0
  240. package/client/dist/assets/nav-D3bOsipX.js +1 -0
  241. package/client/dist/assets/nav-DOMMhlLx.js +1 -0
  242. package/client/dist/assets/nav-DPzVlgZU.js +1 -0
  243. package/client/dist/assets/nav-DZJbFbah.js +1 -0
  244. package/client/dist/assets/nav-D_5aojd2.js +1 -0
  245. package/client/dist/assets/notify-error-BsWANx1T.js +1 -0
  246. package/client/dist/assets/onboarding-BdZQnNm3.js +1 -0
  247. package/client/dist/assets/onboarding-CJQEv1vp.js +1 -0
  248. package/client/dist/assets/onboarding-CWJGYUW3.js +1 -0
  249. package/client/dist/assets/onboarding-ChfYN7dA.js +1 -0
  250. package/client/dist/assets/onboarding-CjvDUR3V.js +1 -0
  251. package/client/dist/assets/onboarding-I6vS-zTB.js +1 -0
  252. package/client/dist/assets/onboarding-dgC_9dTB.js +1 -0
  253. package/client/dist/assets/onboarding-mlXSyKzX.js +1 -0
  254. package/client/dist/assets/origin-03nTuaOb.js +1 -0
  255. package/client/dist/assets/packet-BjpyRnZr.js +1 -0
  256. package/client/dist/assets/packet-BwgG5mBt.js +1 -0
  257. package/client/dist/assets/packet-C3eAUFkV.js +1 -0
  258. package/client/dist/assets/packet-C8wZuSld.js +1 -0
  259. package/client/dist/assets/packet-CNXEy_85.js +1 -0
  260. package/client/dist/assets/packet-DsV5Aa_8.js +1 -0
  261. package/client/dist/assets/packet-aasskOE7.js +1 -0
  262. package/client/dist/assets/packet-phxCc2gJ.js +1 -0
  263. package/client/dist/assets/page-header-BStSHkP8.js +1 -0
  264. package/client/dist/assets/project-repositories-DJPeAVBK.js +1 -0
  265. package/client/dist/assets/{provider-capabilities-lePfeT_Y.js → provider-capabilities-DtwcTme4.js} +1 -1
  266. package/client/dist/assets/recovery-BPDOsC92.js +1 -0
  267. package/client/dist/assets/recovery-BluNHoXM.js +1 -0
  268. package/client/dist/assets/recovery-CRvEmB0C.js +1 -0
  269. package/client/dist/assets/recovery-CeIoRnkR.js +1 -0
  270. package/client/dist/assets/recovery-DHCo8KGi.js +1 -0
  271. package/client/dist/assets/recovery-OxAIpbBF.js +1 -0
  272. package/client/dist/assets/recovery-XXexYGOJ.js +1 -0
  273. package/client/dist/assets/recovery-pITlc--v.js +1 -0
  274. package/client/dist/assets/refresh-cw-DfyTkbsf.js +1 -0
  275. package/client/dist/assets/select-xA3pSmqE.js +1 -0
  276. package/client/dist/assets/settings--yzDbX9r.js +1 -0
  277. package/client/dist/assets/settings-5_heTv8s.js +1 -0
  278. package/client/dist/assets/settings-BSf27MDg.js +1 -0
  279. package/client/dist/assets/settings-BSj6FakR.js +1 -0
  280. package/client/dist/assets/settings-BZDo_8Nn.js +1 -0
  281. package/client/dist/assets/settings-BdWgmNc0.js +1 -0
  282. package/client/dist/assets/settings-DRouxKqb.js +1 -0
  283. package/client/dist/assets/settings-DnWFoY-F.js +1 -0
  284. package/client/dist/assets/setup-BJWy62ri.js +1 -0
  285. package/client/dist/assets/setup-BgKOIuzc.js +1 -0
  286. package/client/dist/assets/setup-BvVIyUlz.js +1 -0
  287. package/client/dist/assets/setup-BxCk2pe1.js +1 -0
  288. package/client/dist/assets/setup-C-xQTL7R.js +1 -0
  289. package/client/dist/assets/setup-CbaVoiwV.js +1 -0
  290. package/client/dist/assets/setup-DxTBkX3P.js +1 -0
  291. package/client/dist/assets/setup-oGoVAzOD.js +1 -0
  292. package/client/dist/assets/specs-7tAb4IKr.js +1 -0
  293. package/client/dist/assets/specs-BUcY4s5v.js +1 -0
  294. package/client/dist/assets/specs-Bk5LeBAA.js +1 -0
  295. package/client/dist/assets/specs-CAA4Lrlg.js +1 -0
  296. package/client/dist/assets/specs-CS091AnA.js +1 -0
  297. package/client/dist/assets/specs-DJ6gmFcK.js +1 -0
  298. package/client/dist/assets/specs-GfCcrBSC.js +1 -0
  299. package/client/dist/assets/specs-xQgyc7WL.js +1 -0
  300. package/client/dist/assets/spending-CVH8VREb.js +1 -0
  301. package/client/dist/assets/square-Co6h5vZg.js +1 -0
  302. package/client/dist/assets/tauri-shell-43ixPGfa.js +2 -0
  303. package/client/dist/assets/terminal-0v9sBylD.js +1 -0
  304. package/client/dist/assets/terminal-AbUAmCxE.js +1 -0
  305. package/client/dist/assets/terminal-BJayIbIP.js +1 -0
  306. package/client/dist/assets/terminal-C2RUlXyi.js +1 -0
  307. package/client/dist/assets/terminal-CMmSb_Nj.js +1 -0
  308. package/client/dist/assets/terminal-DKWjj7HJ.js +1 -0
  309. package/client/dist/assets/terminal-KlFu7_pV.js +1 -0
  310. package/client/dist/assets/terminal-i99yqFvm.js +1 -0
  311. package/client/dist/assets/tickets-846Oq3i3.js +1 -0
  312. package/client/dist/assets/tickets-B5LJTe_b.js +1 -0
  313. package/client/dist/assets/tickets-Bfo2GGmH.js +1 -0
  314. package/client/dist/assets/tickets-BhdZ1yY2.js +1 -0
  315. package/client/dist/assets/tickets-CgjWJHAW.js +1 -0
  316. package/client/dist/assets/tickets-Ct9DbDUR.js +1 -0
  317. package/client/dist/assets/tickets-rptLEJB1.js +1 -0
  318. package/client/dist/assets/tickets-xQ6DpYdu.js +1 -0
  319. package/client/dist/assets/trending-up-BGvb4zZt.js +1 -0
  320. package/client/dist/assets/undo-6zuS4-sL.js +1 -0
  321. package/client/dist/assets/undo-BeM4gDOP.js +1 -0
  322. package/client/dist/assets/undo-BeppX8xS.js +1 -0
  323. package/client/dist/assets/undo-BqvNZ5MG.js +1 -0
  324. package/client/dist/assets/undo-BzwEPf_k.js +1 -0
  325. package/client/dist/assets/undo-CJ9Cu1NN.js +1 -0
  326. package/client/dist/assets/undo-ds8nMFbX.js +1 -0
  327. package/client/dist/assets/undo-x_gA-knG.js +1 -0
  328. package/client/dist/assets/useDesktop-BuOp2-MR.js +1 -0
  329. package/client/dist/assets/useRuntimeRuns-BRS6ncnO.js +1 -0
  330. package/client/dist/assets/utils-ELimjS2Y.js +1 -0
  331. package/client/dist/assets/wrench-Br2n1Lxd.js +1 -0
  332. package/client/dist/index.html +75 -60
  333. package/docs/ci-cd.md +29 -1
  334. package/docs/cli.md +10 -31
  335. package/docs/codex.md +1 -1
  336. package/docs/creating-specs.md +15 -12
  337. package/docs/customizing.md +16 -13
  338. package/docs/getting-started.md +12 -11
  339. package/docs/guide/de/agents/1-meet-the-agents.md +1 -1
  340. package/docs/guide/de/getting-started/2-installing-and-first-run.md +2 -0
  341. package/docs/guide/de/getting-started/3-try-the-sample-project.md +35 -0
  342. package/docs/guide/de/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
  343. package/docs/guide/de/getting-started/6-universal-search.md +34 -0
  344. package/docs/guide/de/insights/1-analytics-and-cost-tracking.md +20 -6
  345. package/docs/guide/de/insights/2-the-integrated-terminal.md +1 -1
  346. package/docs/guide/de/insights/3-code-explorer.md +1 -1
  347. package/docs/guide/de/integrations/1-ai-providers.md +1 -1
  348. package/docs/guide/de/integrations/2-plugins.md +1 -1
  349. package/docs/guide/de/integrations/3-jira-integration.md +3 -3
  350. package/docs/guide/de/integrations/4-mobile-companion.md +1 -1
  351. package/docs/guide/de/integrations/5-mcp-server.md +1 -1
  352. package/docs/guide/de/integrations/6-agent-chat.md +12 -5
  353. package/docs/guide/de/integrations/8-flow-mode.md +69 -0
  354. package/docs/guide/de/pipeline/1-rails-and-jobs.md +21 -1
  355. package/docs/guide/de/pipeline/2-the-job-detail-view.md +12 -0
  356. package/docs/guide/de/pipeline/3-reviewing-a-delivery.md +43 -0
  357. package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +2 -2
  358. package/docs/guide/de/pipeline/5-the-loop-builder.md +1 -1
  359. package/docs/guide/de/settings/1-themes.md +1 -1
  360. package/docs/guide/de/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
  361. package/docs/guide/de/settings/5-project-environment.md +1 -1
  362. package/docs/guide/de/settings/6-updates.md +24 -0
  363. package/docs/guide/de/settings/7-existing-projects.md +33 -0
  364. package/docs/guide/de/settings/8-accessibility.md +23 -0
  365. package/docs/guide/de/specs/1-specs-and-the-backlog.md +41 -3
  366. package/docs/guide/de/specs/2-add-spec-quick-mode.md +1 -1
  367. package/docs/guide/de/specs/3-add-spec-explore-mode.md +1 -1
  368. package/docs/guide/en/agents/1-meet-the-agents.md +1 -1
  369. package/docs/guide/en/getting-started/1-what-is-specrails.md +1 -1
  370. package/docs/guide/en/getting-started/2-installing-and-first-run.md +2 -0
  371. package/docs/guide/en/getting-started/3-try-the-sample-project.md +35 -0
  372. package/docs/guide/en/getting-started/5-the-dashboard-tour.md +52 -0
  373. package/docs/guide/en/getting-started/6-universal-search.md +34 -0
  374. package/docs/guide/en/insights/1-analytics-and-cost-tracking.md +24 -10
  375. package/docs/guide/en/insights/2-the-integrated-terminal.md +1 -1
  376. package/docs/guide/en/insights/3-code-explorer.md +5 -5
  377. package/docs/guide/en/integrations/1-ai-providers.md +1 -1
  378. package/docs/guide/en/integrations/2-plugins.md +1 -1
  379. package/docs/guide/en/integrations/3-jira-integration.md +4 -4
  380. package/docs/guide/en/integrations/4-mobile-companion.md +1 -1
  381. package/docs/guide/en/integrations/5-mcp-server.md +4 -4
  382. package/docs/guide/en/integrations/6-agent-chat.md +12 -5
  383. package/docs/guide/en/integrations/8-flow-mode.md +69 -0
  384. package/docs/guide/en/pipeline/1-rails-and-jobs.md +22 -3
  385. package/docs/guide/en/pipeline/2-the-job-detail-view.md +19 -7
  386. package/docs/guide/en/pipeline/3-reviewing-a-delivery.md +43 -0
  387. package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +2 -2
  388. package/docs/guide/en/pipeline/5-the-loop-builder.md +2 -2
  389. package/docs/guide/en/settings/1-themes.md +1 -1
  390. package/docs/guide/en/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
  391. package/docs/guide/en/settings/5-project-environment.md +1 -1
  392. package/docs/guide/en/settings/6-updates.md +24 -0
  393. package/docs/guide/en/settings/7-existing-projects.md +33 -0
  394. package/docs/guide/en/settings/8-accessibility.md +23 -0
  395. package/docs/guide/en/specs/1-specs-and-the-backlog.md +42 -6
  396. package/docs/guide/en/specs/2-add-spec-quick-mode.md +1 -1
  397. package/docs/guide/en/specs/3-add-spec-explore-mode.md +2 -2
  398. package/docs/guide/es/agents/1-meet-the-agents.md +1 -1
  399. package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +1 -1
  400. package/docs/guide/es/agents/3-customizing-models-per-agent.md +2 -2
  401. package/docs/guide/es/agents/4-custom-agents-catalog.md +1 -1
  402. package/docs/guide/es/getting-started/1-what-is-specrails.md +3 -3
  403. package/docs/guide/es/getting-started/2-installing-and-first-run.md +2 -0
  404. package/docs/guide/es/getting-started/3-try-the-sample-project.md +35 -0
  405. package/docs/guide/es/getting-started/5-the-dashboard-tour.md +52 -0
  406. package/docs/guide/es/getting-started/6-universal-search.md +34 -0
  407. package/docs/guide/es/insights/1-analytics-and-cost-tracking.md +26 -12
  408. package/docs/guide/es/insights/2-the-integrated-terminal.md +1 -1
  409. package/docs/guide/es/insights/3-code-explorer.md +5 -5
  410. package/docs/guide/es/integrations/1-ai-providers.md +1 -1
  411. package/docs/guide/es/integrations/2-plugins.md +1 -1
  412. package/docs/guide/es/integrations/3-jira-integration.md +4 -4
  413. package/docs/guide/es/integrations/4-mobile-companion.md +1 -1
  414. package/docs/guide/es/integrations/5-mcp-server.md +4 -4
  415. package/docs/guide/es/integrations/6-agent-chat.md +14 -7
  416. package/docs/guide/es/integrations/7-local-engines.md +1 -1
  417. package/docs/guide/es/integrations/8-flow-mode.md +69 -0
  418. package/docs/guide/es/pipeline/1-rails-and-jobs.md +33 -13
  419. package/docs/guide/es/pipeline/2-the-job-detail-view.md +38 -26
  420. package/docs/guide/es/pipeline/3-reviewing-a-delivery.md +43 -0
  421. package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +2 -2
  422. package/docs/guide/es/pipeline/5-the-loop-builder.md +4 -4
  423. package/docs/guide/es/settings/1-themes.md +1 -1
  424. package/docs/guide/es/settings/3-pipeline-telemetry-and-diagnostics.md +10 -10
  425. package/docs/guide/es/settings/5-project-environment.md +1 -1
  426. package/docs/guide/es/settings/6-updates.md +24 -0
  427. package/docs/guide/es/settings/7-existing-projects.md +33 -0
  428. package/docs/guide/es/settings/8-accessibility.md +23 -0
  429. package/docs/guide/es/specs/1-specs-and-the-backlog.md +43 -7
  430. package/docs/guide/es/specs/2-add-spec-quick-mode.md +1 -1
  431. package/docs/guide/es/specs/3-add-spec-explore-mode.md +3 -3
  432. package/docs/guide/fr/agents/1-meet-the-agents.md +1 -1
  433. package/docs/guide/fr/getting-started/2-installing-and-first-run.md +2 -0
  434. package/docs/guide/fr/getting-started/3-try-the-sample-project.md +35 -0
  435. package/docs/guide/fr/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
  436. package/docs/guide/fr/getting-started/6-universal-search.md +34 -0
  437. package/docs/guide/fr/insights/1-analytics-and-cost-tracking.md +18 -4
  438. package/docs/guide/fr/insights/2-the-integrated-terminal.md +1 -1
  439. package/docs/guide/fr/insights/3-code-explorer.md +1 -1
  440. package/docs/guide/fr/integrations/1-ai-providers.md +1 -1
  441. package/docs/guide/fr/integrations/2-plugins.md +1 -1
  442. package/docs/guide/fr/integrations/3-jira-integration.md +3 -3
  443. package/docs/guide/fr/integrations/4-mobile-companion.md +1 -1
  444. package/docs/guide/fr/integrations/5-mcp-server.md +1 -1
  445. package/docs/guide/fr/integrations/6-agent-chat.md +11 -4
  446. package/docs/guide/fr/integrations/8-flow-mode.md +69 -0
  447. package/docs/guide/fr/pipeline/1-rails-and-jobs.md +21 -1
  448. package/docs/guide/fr/pipeline/2-the-job-detail-view.md +12 -0
  449. package/docs/guide/fr/pipeline/3-reviewing-a-delivery.md +43 -0
  450. package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +2 -2
  451. package/docs/guide/fr/pipeline/5-the-loop-builder.md +1 -1
  452. package/docs/guide/fr/settings/1-themes.md +1 -1
  453. package/docs/guide/fr/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
  454. package/docs/guide/fr/settings/5-project-environment.md +1 -1
  455. package/docs/guide/fr/settings/6-updates.md +24 -0
  456. package/docs/guide/fr/settings/7-existing-projects.md +33 -0
  457. package/docs/guide/fr/settings/8-accessibility.md +23 -0
  458. package/docs/guide/fr/specs/1-specs-and-the-backlog.md +41 -3
  459. package/docs/guide/fr/specs/2-add-spec-quick-mode.md +1 -1
  460. package/docs/guide/fr/specs/3-add-spec-explore-mode.md +1 -1
  461. package/docs/guide/it/agents/1-meet-the-agents.md +1 -1
  462. package/docs/guide/it/getting-started/2-installing-and-first-run.md +2 -0
  463. package/docs/guide/it/getting-started/3-try-the-sample-project.md +35 -0
  464. package/docs/guide/it/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
  465. package/docs/guide/it/getting-started/6-universal-search.md +34 -0
  466. package/docs/guide/it/insights/1-analytics-and-cost-tracking.md +18 -4
  467. package/docs/guide/it/insights/2-the-integrated-terminal.md +1 -1
  468. package/docs/guide/it/insights/3-code-explorer.md +1 -1
  469. package/docs/guide/it/integrations/1-ai-providers.md +1 -1
  470. package/docs/guide/it/integrations/2-plugins.md +1 -1
  471. package/docs/guide/it/integrations/3-jira-integration.md +3 -3
  472. package/docs/guide/it/integrations/4-mobile-companion.md +1 -1
  473. package/docs/guide/it/integrations/5-mcp-server.md +1 -1
  474. package/docs/guide/it/integrations/6-agent-chat.md +11 -4
  475. package/docs/guide/it/integrations/8-flow-mode.md +69 -0
  476. package/docs/guide/it/pipeline/1-rails-and-jobs.md +21 -1
  477. package/docs/guide/it/pipeline/2-the-job-detail-view.md +12 -0
  478. package/docs/guide/it/pipeline/3-reviewing-a-delivery.md +43 -0
  479. package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +2 -2
  480. package/docs/guide/it/pipeline/5-the-loop-builder.md +1 -1
  481. package/docs/guide/it/settings/1-themes.md +1 -1
  482. package/docs/guide/it/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
  483. package/docs/guide/it/settings/5-project-environment.md +1 -1
  484. package/docs/guide/it/settings/6-updates.md +24 -0
  485. package/docs/guide/it/settings/7-existing-projects.md +33 -0
  486. package/docs/guide/it/settings/8-accessibility.md +23 -0
  487. package/docs/guide/it/specs/1-specs-and-the-backlog.md +41 -3
  488. package/docs/guide/it/specs/2-add-spec-quick-mode.md +1 -1
  489. package/docs/guide/it/specs/3-add-spec-explore-mode.md +1 -1
  490. package/docs/guide/ja/agents/1-meet-the-agents.md +1 -1
  491. package/docs/guide/ja/getting-started/2-installing-and-first-run.md +2 -0
  492. package/docs/guide/ja/getting-started/3-try-the-sample-project.md +35 -0
  493. package/docs/guide/ja/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
  494. package/docs/guide/ja/getting-started/6-universal-search.md +34 -0
  495. package/docs/guide/ja/insights/1-analytics-and-cost-tracking.md +18 -4
  496. package/docs/guide/ja/insights/2-the-integrated-terminal.md +1 -1
  497. package/docs/guide/ja/insights/3-code-explorer.md +1 -1
  498. package/docs/guide/ja/integrations/1-ai-providers.md +1 -1
  499. package/docs/guide/ja/integrations/2-plugins.md +1 -1
  500. package/docs/guide/ja/integrations/3-jira-integration.md +3 -3
  501. package/docs/guide/ja/integrations/4-mobile-companion.md +1 -1
  502. package/docs/guide/ja/integrations/5-mcp-server.md +1 -1
  503. package/docs/guide/ja/integrations/6-agent-chat.md +11 -4
  504. package/docs/guide/ja/integrations/8-flow-mode.md +69 -0
  505. package/docs/guide/ja/pipeline/1-rails-and-jobs.md +21 -1
  506. package/docs/guide/ja/pipeline/2-the-job-detail-view.md +12 -0
  507. package/docs/guide/ja/pipeline/3-reviewing-a-delivery.md +43 -0
  508. package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +2 -2
  509. package/docs/guide/ja/pipeline/5-the-loop-builder.md +1 -1
  510. package/docs/guide/ja/settings/1-themes.md +1 -1
  511. package/docs/guide/ja/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
  512. package/docs/guide/ja/settings/5-project-environment.md +1 -1
  513. package/docs/guide/ja/settings/6-updates.md +24 -0
  514. package/docs/guide/ja/settings/7-existing-projects.md +33 -0
  515. package/docs/guide/ja/settings/8-accessibility.md +23 -0
  516. package/docs/guide/ja/specs/1-specs-and-the-backlog.md +41 -3
  517. package/docs/guide/ja/specs/2-add-spec-quick-mode.md +1 -1
  518. package/docs/guide/ja/specs/3-add-spec-explore-mode.md +1 -1
  519. package/docs/guide/pt/agents/1-meet-the-agents.md +1 -1
  520. package/docs/guide/pt/getting-started/2-installing-and-first-run.md +2 -0
  521. package/docs/guide/pt/getting-started/3-try-the-sample-project.md +35 -0
  522. package/docs/guide/pt/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
  523. package/docs/guide/pt/getting-started/6-universal-search.md +34 -0
  524. package/docs/guide/pt/insights/1-analytics-and-cost-tracking.md +18 -4
  525. package/docs/guide/pt/insights/2-the-integrated-terminal.md +1 -1
  526. package/docs/guide/pt/insights/3-code-explorer.md +1 -1
  527. package/docs/guide/pt/integrations/1-ai-providers.md +1 -1
  528. package/docs/guide/pt/integrations/2-plugins.md +1 -1
  529. package/docs/guide/pt/integrations/3-jira-integration.md +3 -3
  530. package/docs/guide/pt/integrations/4-mobile-companion.md +1 -1
  531. package/docs/guide/pt/integrations/5-mcp-server.md +1 -1
  532. package/docs/guide/pt/integrations/6-agent-chat.md +12 -5
  533. package/docs/guide/pt/integrations/8-flow-mode.md +69 -0
  534. package/docs/guide/pt/pipeline/1-rails-and-jobs.md +21 -1
  535. package/docs/guide/pt/pipeline/2-the-job-detail-view.md +12 -0
  536. package/docs/guide/pt/pipeline/3-reviewing-a-delivery.md +43 -0
  537. package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +2 -2
  538. package/docs/guide/pt/pipeline/5-the-loop-builder.md +1 -1
  539. package/docs/guide/pt/settings/1-themes.md +1 -1
  540. package/docs/guide/pt/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
  541. package/docs/guide/pt/settings/5-project-environment.md +1 -1
  542. package/docs/guide/pt/settings/6-updates.md +24 -0
  543. package/docs/guide/pt/settings/7-existing-projects.md +33 -0
  544. package/docs/guide/pt/settings/8-accessibility.md +23 -0
  545. package/docs/guide/pt/specs/1-specs-and-the-backlog.md +41 -3
  546. package/docs/guide/pt/specs/2-add-spec-quick-mode.md +1 -1
  547. package/docs/guide/pt/specs/3-add-spec-explore-mode.md +1 -1
  548. package/docs/guide/zh/agents/1-meet-the-agents.md +1 -1
  549. package/docs/guide/zh/getting-started/2-installing-and-first-run.md +2 -0
  550. package/docs/guide/zh/getting-started/3-try-the-sample-project.md +35 -0
  551. package/docs/guide/zh/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
  552. package/docs/guide/zh/getting-started/6-universal-search.md +34 -0
  553. package/docs/guide/zh/insights/1-analytics-and-cost-tracking.md +18 -4
  554. package/docs/guide/zh/insights/2-the-integrated-terminal.md +1 -1
  555. package/docs/guide/zh/insights/3-code-explorer.md +1 -1
  556. package/docs/guide/zh/integrations/1-ai-providers.md +1 -1
  557. package/docs/guide/zh/integrations/2-plugins.md +1 -1
  558. package/docs/guide/zh/integrations/3-jira-integration.md +3 -3
  559. package/docs/guide/zh/integrations/4-mobile-companion.md +1 -1
  560. package/docs/guide/zh/integrations/5-mcp-server.md +1 -1
  561. package/docs/guide/zh/integrations/6-agent-chat.md +11 -4
  562. package/docs/guide/zh/integrations/8-flow-mode.md +69 -0
  563. package/docs/guide/zh/pipeline/1-rails-and-jobs.md +21 -1
  564. package/docs/guide/zh/pipeline/2-the-job-detail-view.md +12 -0
  565. package/docs/guide/zh/pipeline/3-reviewing-a-delivery.md +43 -0
  566. package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +2 -2
  567. package/docs/guide/zh/pipeline/5-the-loop-builder.md +1 -1
  568. package/docs/guide/zh/settings/1-themes.md +1 -1
  569. package/docs/guide/zh/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
  570. package/docs/guide/zh/settings/5-project-environment.md +1 -1
  571. package/docs/guide/zh/settings/6-updates.md +24 -0
  572. package/docs/guide/zh/settings/7-existing-projects.md +33 -0
  573. package/docs/guide/zh/settings/8-accessibility.md +23 -0
  574. package/docs/guide/zh/specs/1-specs-and-the-backlog.md +41 -3
  575. package/docs/guide/zh/specs/2-add-spec-quick-mode.md +1 -1
  576. package/docs/guide/zh/specs/3-add-spec-explore-mode.md +1 -1
  577. package/docs/internals/README.md +8 -0
  578. package/docs/internals/adding-a-provider.md +19 -2
  579. package/docs/internals/agent-actions-audit.md +101 -0
  580. package/docs/internals/agent-sessions.md +36 -1
  581. package/docs/internals/api-reference.md +190 -45
  582. package/docs/internals/architecture.md +53 -47
  583. package/docs/internals/companion-inbox-decisions.md +42 -0
  584. package/docs/internals/companion-rails-as-loops-contract.md +17 -6
  585. package/docs/internals/configuration.md +140 -9
  586. package/docs/internals/core-runtime-updates.md +4 -4
  587. package/docs/internals/existing-project-anchoring.md +168 -0
  588. package/docs/internals/flow-mode.md +668 -0
  589. package/docs/internals/legacy-implementation-notes.md +13 -0
  590. package/docs/internals/local-testing-feedback-2026-10.md +210 -0
  591. package/docs/internals/mcp-mission-audit.md +4 -0
  592. package/docs/internals/mission-rail-cards.md +10 -5
  593. package/docs/internals/mission-read-only-policy.md +152 -0
  594. package/docs/internals/modal-standard.md +181 -0
  595. package/docs/internals/openspec-workflow.md +32 -0
  596. package/docs/internals/operations-runbook.md +30 -0
  597. package/docs/internals/profiles.md +6 -3
  598. package/docs/internals/programmatic-agent-runtime.md +8 -0
  599. package/docs/internals/project-builder.md +1 -1
  600. package/docs/internals/review-packet.md +161 -9
  601. package/docs/internals/safe-pr-review-flow.md +135 -6
  602. package/docs/internals/source-map.md +413 -18
  603. package/docs/internals/spec-addenda.md +10 -0
  604. package/docs/internals/spec-triage.md +140 -0
  605. package/docs/internals/visual-design-audit.md +15 -2
  606. package/docs/local-providers.md +3 -0
  607. package/docs/mcp.md +21 -3
  608. package/docs/platforms/macos.md +1 -1
  609. package/docs/platforms/windows.md +2 -2
  610. package/docs/running-pipelines.md +22 -6
  611. package/docs/tracking-cost.md +54 -10
  612. package/local-runner/dist/specrails-local-runner.js +3851 -1178
  613. package/mcp-bridge/dist/specrails-mcp.js +3864 -1143
  614. package/package.json +10 -9
  615. package/server/dist/agent-mcp-config.js +37 -1
  616. package/server/dist/api-version.js +19 -0
  617. package/server/dist/command-resolver.js +4 -2
  618. package/server/dist/core-compat.js +1 -1
  619. package/server/dist/core-execution.js +2 -1
  620. package/server/dist/core-update-manager.js +71 -13
  621. package/server/dist/db/job-search.js +248 -0
  622. package/server/dist/db/jobs.js +6 -0
  623. package/server/dist/db/migrations.js +239 -0
  624. package/server/dist/db.js +9 -2
  625. package/server/dist/desktop-db.js +99 -5
  626. package/server/dist/desktop-router.js +126 -13
  627. package/server/dist/docs-router.js +67 -1
  628. package/server/dist/feature-flags.js +22 -0
  629. package/server/dist/index.js +30 -15
  630. package/server/dist/jira/jira-adf.js +13 -1
  631. package/server/dist/jira/jira-clarifications.js +146 -0
  632. package/server/dist/jira/jira-client.js +8 -1
  633. package/server/dist/jira/jira-db.js +41 -0
  634. package/server/dist/jira/jira-sync-manager.js +328 -25
  635. package/server/dist/mcp/guide.js +17 -7
  636. package/server/dist/mcp/tools/agents.js +1 -1
  637. package/server/dist/mcp/tools/analytics.js +15 -3
  638. package/server/dist/mcp/tools/app-settings.js +14 -1
  639. package/server/dist/mcp/tools/chat.js +1 -1
  640. package/server/dist/mcp/tools/env.js +4 -2
  641. package/server/dist/mcp/tools/jobs.js +96 -7
  642. package/server/dist/mcp/tools/loops.js +1 -1
  643. package/server/dist/mcp/tools/meta.js +10 -13
  644. package/server/dist/mcp/tools/rails.js +15 -1
  645. package/server/dist/mcp/tools/setup.js +1 -1
  646. package/server/dist/mcp/tools/specs.js +8 -5
  647. package/server/dist/mcp/tools/support.js +6 -3
  648. package/server/dist/mcp/tools/types.js +38 -1
  649. package/server/dist/mobile/mobile-admin-router.js +0 -16
  650. package/server/dist/mobile/mobile-gateway.js +0 -18
  651. package/server/dist/mobile/mobile-inbox.js +240 -0
  652. package/server/dist/mobile/mobile-missions.js +6 -8
  653. package/server/dist/mobile/mobile-router.js +9 -9
  654. package/server/dist/mobile/mobile-webrtc-peer.js +4 -54
  655. package/server/dist/mobile/mobile-ws.js +27 -4
  656. package/server/dist/modules/accounting/runtime/ai-invocations.js +4 -0
  657. package/server/dist/modules/accounting/runtime/decision-times.js +102 -0
  658. package/server/dist/modules/accounting/runtime/loop-economics.js +284 -0
  659. package/server/dist/modules/accounting/runtime/spending.js +7 -2
  660. package/server/dist/modules/accounting/runtime/what-if.js +87 -0
  661. package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +86 -5
  662. package/server/dist/modules/agent-runtime/runtime/agent-runtime-controls.js +28 -2
  663. package/server/dist/modules/agent-runtime/runtime/agent-runtime-metrics.js +15 -2
  664. package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings-router.js +21 -2
  665. package/server/dist/modules/agent-runtime/runtime/core-capabilities.js +55 -0
  666. package/server/dist/modules/agent-sessions/adapters/host-process.js +1 -1
  667. package/server/dist/modules/agent-sessions/domain/availability.js +16 -0
  668. package/server/dist/modules/agent-sessions/domain/protocol.js +8 -1
  669. package/server/dist/modules/agent-sessions/index.js +3 -1
  670. package/server/dist/modules/agent-sessions/runtime/core-sessions-availability.js +16 -0
  671. package/server/dist/modules/agents/runtime/agent-refine-manager.js +3 -1
  672. package/server/dist/modules/agents/runtime/agent-store.js +60 -73
  673. package/server/dist/modules/audit/adapters/http.js +66 -0
  674. package/server/dist/modules/audit/adapters/runtime.js +60 -0
  675. package/server/dist/modules/audit/adapters/sqlite.js +73 -0
  676. package/server/dist/modules/audit/application.js +190 -0
  677. package/server/dist/modules/audit/domain.js +434 -0
  678. package/server/dist/modules/audit/index.js +27 -0
  679. package/server/dist/modules/audit/ports.js +2 -0
  680. package/server/dist/modules/browser/runtime/browser-capture-manager.js +18 -141
  681. package/server/dist/modules/browser/runtime/browser-capture-types.js +1 -10
  682. package/server/dist/modules/browser/runtime/browser-playwright.js +0 -19
  683. package/server/dist/modules/code/runtime/file-provenance.js +23 -0
  684. package/server/dist/modules/conversations/runtime/chat-manager.js +5 -2
  685. package/server/dist/modules/delivery/adapters/decisions/chains.js +1 -0
  686. package/server/dist/modules/delivery/adapters/decisions/create.js +19 -1
  687. package/server/dist/modules/delivery/adapters/decisions/discard.js +2 -0
  688. package/server/dist/modules/delivery/adapters/decisions/local-changes.js +427 -0
  689. package/server/dist/modules/delivery/adapters/decisions/merge-local.js +80 -6
  690. package/server/dist/modules/delivery/adapters/decisions/observations.js +5 -0
  691. package/server/dist/modules/delivery/adapters/decisions/ownership.js +2 -1
  692. package/server/dist/modules/delivery/adapters/decisions/transitions.js +9 -0
  693. package/server/dist/modules/delivery/adapters/review-wip-store.js +37 -0
  694. package/server/dist/modules/delivery/domain/review-wip.js +71 -0
  695. package/server/dist/modules/delivery/index.js +9 -1
  696. package/server/dist/modules/delivery/runtime/delivery-changes.js +355 -0
  697. package/server/dist/modules/delivery/runtime/delivery-evidence.js +249 -8
  698. package/server/dist/modules/delivery/runtime/flow-review-legacy.js +99 -0
  699. package/server/dist/modules/delivery/runtime/flow-review-outcome.js +107 -0
  700. package/server/dist/modules/delivery/runtime/flow-worktree-handoff.js +32 -0
  701. package/server/dist/modules/delivery/runtime/flow-worktree-return.js +87 -0
  702. package/server/dist/modules/delivery/runtime/isolated-worktree.js +380 -0
  703. package/server/dist/modules/delivery/runtime/local-restore-branch.js +325 -0
  704. package/server/dist/modules/delivery/runtime/local-restore-resolver.js +48 -0
  705. package/server/dist/modules/delivery/runtime/local-stash.js +423 -0
  706. package/server/dist/modules/delivery/runtime/multi-repo-execution.js +27 -1
  707. package/server/dist/modules/delivery/runtime/phase3-harvest.js +40 -0
  708. package/server/dist/modules/delivery/runtime/pr-body.js +50 -0
  709. package/server/dist/modules/delivery/runtime/rail-isolated-launch.js +169 -166
  710. package/server/dist/modules/delivery/runtime/rail-launch-parser.js +5 -2
  711. package/server/dist/modules/delivery/runtime/rail-pr-decision.js +7 -1
  712. package/server/dist/modules/delivery/runtime/rail-pr-store.js +193 -12
  713. package/server/dist/modules/delivery/runtime/rails-router.js +267 -5
  714. package/server/dist/modules/delivery/runtime/review-brief.js +208 -0
  715. package/server/dist/modules/delivery/runtime/review-packet.js +41 -2
  716. package/server/dist/modules/delivery/runtime/review-wip-gate.js +67 -0
  717. package/server/dist/modules/delivery/runtime/run-records.js +267 -0
  718. package/server/dist/modules/delivery/runtime/run-review-diagnosis.js +102 -0
  719. package/server/dist/modules/execution/adapters/budget-storage.js +76 -0
  720. package/server/dist/modules/execution/application/enforce-budget.js +17 -2
  721. package/server/dist/modules/execution/domain/agent-env.js +98 -0
  722. package/server/dist/modules/execution/domain/daily-budget.js +36 -0
  723. package/server/dist/modules/execution/domain/spend-caps.js +166 -0
  724. package/server/dist/modules/execution/index.js +34 -1
  725. package/server/dist/modules/execution/runtime/budget-overview.js +76 -0
  726. package/server/dist/modules/execution/runtime/daily-budget-gate.js +86 -0
  727. package/server/dist/modules/execution/runtime/interactive-job-session.js +8 -0
  728. package/server/dist/modules/execution/runtime/launch-forecast.js +33 -0
  729. package/server/dist/modules/execution/runtime/queue-manager.js +54 -15
  730. package/server/dist/modules/execution/runtime/run-duration-stats.js +31 -13
  731. package/server/dist/modules/flow/adapters/bindings.js +1089 -0
  732. package/server/dist/modules/flow/adapters/http.js +147 -0
  733. package/server/dist/modules/flow/adapters/sqlite.js +121 -0
  734. package/server/dist/modules/flow/application.js +805 -0
  735. package/server/dist/modules/flow/domain.js +790 -0
  736. package/server/dist/modules/flow/index.js +34 -0
  737. package/server/dist/modules/flow/ports.js +2 -0
  738. package/server/dist/modules/inbox/adapters/http.js +21 -0
  739. package/server/dist/modules/inbox/adapters/project-source.js +233 -0
  740. package/server/dist/modules/inbox/application.js +28 -0
  741. package/server/dist/modules/inbox/domain.js +43 -0
  742. package/server/dist/modules/inbox/index.js +10 -0
  743. package/server/dist/modules/inbox/ports.js +2 -0
  744. package/server/dist/modules/loops/runtime/loop-definition-run.js +9 -0
  745. package/server/dist/modules/loops/runtime/loop-definition.js +5 -2
  746. package/server/dist/modules/loops/runtime/loop-executors.js +90 -9
  747. package/server/dist/modules/loops/runtime/loop-factory.js +30 -2
  748. package/server/dist/modules/loops/runtime/loop-flow-spec-recipe.js +166 -0
  749. package/server/dist/modules/loops/runtime/loop-graph.js +1 -1
  750. package/server/dist/modules/loops/runtime/loop-role-engines.js +4 -1
  751. package/server/dist/modules/loops/runtime/loop-run-manager.js +267 -10
  752. package/server/dist/modules/loops/runtime/loop-runs-store.js +21 -5
  753. package/server/dist/modules/loops/runtime/loop-templates.js +55 -12
  754. package/server/dist/modules/missions/runtime/agent-chat-manager.js +283 -20
  755. package/server/dist/modules/missions/runtime/agent-chat-router.js +96 -21
  756. package/server/dist/modules/missions/runtime/agent-failure-briefing.js +11 -3
  757. package/server/dist/modules/missions/runtime/agent-fence-promotion.js +9 -1
  758. package/server/dist/modules/missions/runtime/agent-flow-prompt.js +64 -0
  759. package/server/dist/modules/missions/runtime/agent-input-store.js +9 -4
  760. package/server/dist/modules/missions/runtime/agent-operator-prompt.js +100 -14
  761. package/server/dist/modules/missions/runtime/agent-session-store.js +88 -27
  762. package/server/dist/modules/missions/runtime/core-session-runner.js +89 -9
  763. package/server/dist/modules/missions/runtime/flow-turn-context.js +17 -0
  764. package/server/dist/modules/missions/runtime/mission-core-sessions.js +295 -55
  765. package/server/dist/modules/missions/runtime/mission-run-notify.js +2 -0
  766. package/server/dist/modules/missions/runtime/mission-session-projector.js +56 -19
  767. package/server/dist/modules/missions/runtime/mission-tool-policy.js +47 -0
  768. package/server/dist/modules/onboarding/adapters/http.js +78 -0
  769. package/server/dist/modules/onboarding/adapters/providers.js +41 -0
  770. package/server/dist/modules/onboarding/adapters/runtime.js +130 -0
  771. package/server/dist/modules/onboarding/application.js +133 -0
  772. package/server/dist/modules/onboarding/catalog.js +217 -0
  773. package/server/dist/modules/onboarding/domain.js +102 -0
  774. package/server/dist/modules/onboarding/index.js +20 -0
  775. package/server/dist/modules/onboarding/ports.js +2 -0
  776. package/server/dist/modules/project-rules/adapters/http.js +91 -0
  777. package/server/dist/modules/project-rules/domain.js +122 -0
  778. package/server/dist/modules/project-rules/runtime/rules-inventory-runs.js +97 -0
  779. package/server/dist/modules/project-rules/runtime/rules-store.js +109 -0
  780. package/server/dist/modules/project-settings/adapters/http.js +13 -0
  781. package/server/dist/modules/project-settings/adapters/sqlite.js +78 -8
  782. package/server/dist/modules/project-settings/domain.js +47 -1
  783. package/server/dist/modules/project-settings/index.js +7 -1
  784. package/server/dist/modules/recovery/adapters/sqlite.js +28 -0
  785. package/server/dist/modules/recovery/domain.js +162 -0
  786. package/server/dist/modules/recovery/index.js +16 -0
  787. package/server/dist/modules/specs/adapters/timeline-http.js +101 -0
  788. package/server/dist/modules/specs/domain/handoff-labels.js +371 -0
  789. package/server/dist/modules/specs/domain/handoff.js +260 -0
  790. package/server/dist/modules/specs/domain/non-goals.js +101 -0
  791. package/server/dist/modules/specs/domain/timeline.js +164 -0
  792. package/server/dist/modules/specs/domain/triage.js +320 -0
  793. package/server/dist/modules/specs/runtime/contract-refine-runner.js +3 -2
  794. package/server/dist/modules/specs/runtime/generated-spec-parser.js +75 -0
  795. package/server/dist/modules/specs/runtime/proposal-manager.js +4 -3
  796. package/server/dist/modules/specs/runtime/smash-runner.js +2 -1
  797. package/server/dist/modules/specs/runtime/spec-addenda.js +31 -0
  798. package/server/dist/modules/specs/runtime/spec-draft-parser.js +6 -1
  799. package/server/dist/modules/specs/runtime/spec-generation.js +431 -0
  800. package/server/dist/modules/specs/runtime/spec-handoff.js +103 -0
  801. package/server/dist/modules/specs/runtime/spec-history.js +376 -0
  802. package/server/dist/modules/specs/runtime/spec-launcher-manager.js +4 -3
  803. package/server/dist/modules/specs/runtime/spec-search.js +117 -0
  804. package/server/dist/modules/specs/runtime/ticket-store.js +47 -2
  805. package/server/dist/modules/specs/runtime/ticket-trash-service.js +62 -0
  806. package/server/dist/modules/specs/runtime/ticket-trash.js +193 -0
  807. package/server/dist/modules/specs/runtime/triage-runner.js +171 -0
  808. package/server/dist/modules/specs/runtime/triage.js +365 -0
  809. package/server/dist/modules/terminals/domain/app-urls.js +96 -0
  810. package/server/dist/modules/terminals/runtime/app-urls.js +77 -0
  811. package/server/dist/modules/terminals/runtime/background-process-service.js +25 -28
  812. package/server/dist/project-env.js +60 -0
  813. package/server/dist/project-git.js +65 -0
  814. package/server/dist/project-registry.js +264 -27
  815. package/server/dist/project-router-background-processes.js +27 -3
  816. package/server/dist/project-router-git.js +30 -0
  817. package/server/dist/project-router-helpers.js +5 -30
  818. package/server/dist/project-router-jobs.js +49 -1
  819. package/server/dist/project-router-loop-runs.js +72 -2
  820. package/server/dist/project-router-rules.js +54 -0
  821. package/server/dist/project-router-search.js +52 -0
  822. package/server/dist/project-router-settings.js +6 -0
  823. package/server/dist/project-router-setup.js +1 -1
  824. package/server/dist/project-router-spending.js +138 -0
  825. package/server/dist/project-router-tickets.js +246 -427
  826. package/server/dist/project-router.js +7 -0
  827. package/server/dist/providers/claude-adapter.js +25 -3
  828. package/server/dist/providers/codex-adapter.js +9 -1
  829. package/server/dist/providers/gemini-adapter.js +6 -1
  830. package/server/dist/providers/kimi-adapter.js +2 -0
  831. package/server/dist/providers/local-adapter.js +2 -0
  832. package/server/dist/providers/runtime.js +8 -0
  833. package/server/dist/schemas/agent-runtime.schema.json +3 -1
  834. package/server/dist/schemas/workflow-definition.schema.json +1 -0
  835. package/server/dist/setup-manager.js +19 -1
  836. package/server/dist/transient-children.js +25 -8
  837. package/server/dist/update-channel.js +21 -0
  838. package/server/dist/util/search-snippet.js +74 -0
  839. package/server/dist/worktree-manager.js +19 -8
  840. package/client/dist/assets/ActivityFeedPage-Dtp7EyHc.js +0 -1
  841. package/client/dist/assets/AgentBrowserCapture-CLqlEFw8.js +0 -1
  842. package/client/dist/assets/AgentModeAnalyticsPane-B8_hM3Tw.js +0 -2
  843. package/client/dist/assets/AgentModeCodePane-CNF8ZNjE.js +0 -2
  844. package/client/dist/assets/AgentModeJobsPane-CJpJbO9m.js +0 -1
  845. package/client/dist/assets/AgentsPage-BC8XSR79.js +0 -120
  846. package/client/dist/assets/AnalyticsPage-Cdv4jLtW.js +0 -1
  847. package/client/dist/assets/BarChart-BDMqVFJy.js +0 -55
  848. package/client/dist/assets/CodePage-DI1kegAr.js +0 -3
  849. package/client/dist/assets/DesktopAnalyticsPage-Bdp8E8U6.js +0 -1
  850. package/client/dist/assets/DocsDialog-Bm4RS7FX.js +0 -11
  851. package/client/dist/assets/DocsPage-DihYcU8r.js +0 -11
  852. package/client/dist/assets/ExportDropdown-Bb1lHx3r.js +0 -1
  853. package/client/dist/assets/IntegrationsPage-EAipiDWm.js +0 -1
  854. package/client/dist/assets/InteractiveJobComposer-BO6ASN-2.js +0 -19
  855. package/client/dist/assets/JobDetailModal-CuPYq7tP.js +0 -1
  856. package/client/dist/assets/JobDetailPage-BusMjJi9.js +0 -1
  857. package/client/dist/assets/JobsPage-C0QbsF2d.js +0 -1
  858. package/client/dist/assets/LoopBuilderPage-B7TlU4iS.js +0 -1
  859. package/client/dist/assets/LoopPreviewModal-BRWtXOD2.js +0 -1
  860. package/client/dist/assets/LoopsPage-C4q1DmCE.js +0 -2
  861. package/client/dist/assets/MinimizedChatsContext-DHfigjHS.js +0 -1
  862. package/client/dist/assets/PluginsPage-Z1JHSMdR.js +0 -2
  863. package/client/dist/assets/ProjectSettingsDialog-BUNj0tvN.js +0 -1
  864. package/client/dist/assets/RepositoryDeliveries-B4ybHOyB.js +0 -5
  865. package/client/dist/assets/ReviewPacketPage-hwfPNjyy.js +0 -4
  866. package/client/dist/assets/TemplatePreviewModal-V7FpMWuw.js +0 -1
  867. package/client/dist/assets/TicketDetailModalContext-Dkwo2cDs.js +0 -16
  868. package/client/dist/assets/Trans-BbFxRFtR.js +0 -1
  869. package/client/dist/assets/activity-B-rp4h_v.js +0 -1
  870. package/client/dist/assets/activity-C6kJpm9q.js +0 -1
  871. package/client/dist/assets/activity-CGx4kb_j.js +0 -1
  872. package/client/dist/assets/activity-CnoX2bH7.js +0 -1
  873. package/client/dist/assets/activity-DAyekdlt.js +0 -1
  874. package/client/dist/assets/activity-DCxtpT7j.js +0 -1
  875. package/client/dist/assets/activity-DiyjsgQV.js +0 -1
  876. package/client/dist/assets/activity-JzwRaWPD.js +0 -1
  877. package/client/dist/assets/addspec-BOvgmcgk.js +0 -1
  878. package/client/dist/assets/addspec-Clmyfn_R.js +0 -1
  879. package/client/dist/assets/addspec-CsNaBpHp.js +0 -1
  880. package/client/dist/assets/addspec-D2tvWmmV.js +0 -1
  881. package/client/dist/assets/addspec-D3nFwvD0.js +0 -1
  882. package/client/dist/assets/addspec-DVLEhK3w.js +0 -1
  883. package/client/dist/assets/addspec-DXbK-tb0.js +0 -1
  884. package/client/dist/assets/addspec-OHG8DFEn.js +0 -1
  885. package/client/dist/assets/agent-5bSixVzz.js +0 -1
  886. package/client/dist/assets/agent-BR4EHfhq.js +0 -1
  887. package/client/dist/assets/agent-C0IKkJP8.js +0 -1
  888. package/client/dist/assets/agent-C7li9ayC.js +0 -1
  889. package/client/dist/assets/agent-D0dRmEen.js +0 -1
  890. package/client/dist/assets/agent-DZVGHm7H.js +0 -1
  891. package/client/dist/assets/agent-Dip4h2YE.js +0 -1
  892. package/client/dist/assets/agent-Pp-P-n1p.js +0 -1
  893. package/client/dist/assets/agentRuntime-BxF81z52.js +0 -1
  894. package/client/dist/assets/agentRuntime-BxYS5V7u.js +0 -1
  895. package/client/dist/assets/agentRuntime-Dc9HG3BA.js +0 -1
  896. package/client/dist/assets/agents-B6ZsnARo.js +0 -1
  897. package/client/dist/assets/agents-BORdhe0K.js +0 -1
  898. package/client/dist/assets/agents-C6aq9Oqs.js +0 -1
  899. package/client/dist/assets/agents-Cbsc4bcX.js +0 -1
  900. package/client/dist/assets/agents-D0uYR6hq.js +0 -1
  901. package/client/dist/assets/agents-Doe1sHY5.js +0 -1
  902. package/client/dist/assets/agents-DyNi_I9m.js +0 -1
  903. package/client/dist/assets/agents-StKxiTg0.js +0 -1
  904. package/client/dist/assets/agentstudio-7cYCXn-L.js +0 -1
  905. package/client/dist/assets/agentstudio-BHWQh8G3.js +0 -1
  906. package/client/dist/assets/agentstudio-BjnWHyRs.js +0 -1
  907. package/client/dist/assets/agentstudio-BkV8vcK4.js +0 -1
  908. package/client/dist/assets/agentstudio-BzugqB_N.js +0 -1
  909. package/client/dist/assets/agentstudio-CWbp7KvH.js +0 -1
  910. package/client/dist/assets/agentstudio-DG6plf5o.js +0 -1
  911. package/client/dist/assets/agentstudio-DkZVF-Cc.js +0 -1
  912. package/client/dist/assets/analytics-B1DIQd4m.js +0 -1
  913. package/client/dist/assets/analytics-BAIZ9vE_.js +0 -1
  914. package/client/dist/assets/analytics-BTqgmgBd.js +0 -1
  915. package/client/dist/assets/analytics-BWynXPEm.js +0 -1
  916. package/client/dist/assets/analytics-DGcUsQ44.js +0 -1
  917. package/client/dist/assets/analytics-GnSnpJ4W.js +0 -1
  918. package/client/dist/assets/analytics-TWgYaoO0.js +0 -1
  919. package/client/dist/assets/analytics-kJy6Tuko.js +0 -1
  920. package/client/dist/assets/atom-one-dark-qiGhVQxg.js +0 -1
  921. package/client/dist/assets/builder-B9gorTnT.js +0 -1
  922. package/client/dist/assets/builder-Bvw5s3Mi.js +0 -1
  923. package/client/dist/assets/builder-CL5l4dU3.js +0 -1
  924. package/client/dist/assets/builder-CVDTVrQX.js +0 -1
  925. package/client/dist/assets/builder-CpS9liE9.js +0 -1
  926. package/client/dist/assets/builder-DNctIL9Q.js +0 -1
  927. package/client/dist/assets/builder-De2NxX6o.js +0 -1
  928. package/client/dist/assets/builder-DeYT7Y-m.js +0 -1
  929. package/client/dist/assets/button-4FS1ZDTp.js +0 -1
  930. package/client/dist/assets/chat-D_I7nU5K.js +0 -1
  931. package/client/dist/assets/chevron-up-6EFqEHBj.js +0 -1
  932. package/client/dist/assets/chunk-OB3PAWPO-B1EMk45A.js +0 -3
  933. package/client/dist/assets/clsx-CjueKrWZ.js +0 -1
  934. package/client/dist/assets/code-B37GRg9C.js +0 -1
  935. package/client/dist/assets/code-BBOEZbf9.js +0 -1
  936. package/client/dist/assets/code-BRm-jcyx.js +0 -1
  937. package/client/dist/assets/code-CF7w62CR.js +0 -1
  938. package/client/dist/assets/code-CLuvJt2r.js +0 -1
  939. package/client/dist/assets/code-D0RCm59f.js +0 -1
  940. package/client/dist/assets/code-DaZ-ZwCT.js +0 -1
  941. package/client/dist/assets/code-iIHkGaCL.js +0 -1
  942. package/client/dist/assets/commands-0XjAftla.js +0 -1
  943. package/client/dist/assets/commands-BAWSYHjQ.js +0 -1
  944. package/client/dist/assets/commands-BBwowgiE.js +0 -1
  945. package/client/dist/assets/commands-BacjIZLN.js +0 -1
  946. package/client/dist/assets/commands-Bs62IAZ3.js +0 -1
  947. package/client/dist/assets/commands-CLPdh-Hh.js +0 -1
  948. package/client/dist/assets/commands-DlbFzgrp.js +0 -1
  949. package/client/dist/assets/commands-LjPSsi5F.js +0 -1
  950. package/client/dist/assets/common-Bdi0qN4S.js +0 -1
  951. package/client/dist/assets/common-Bhb9zN1P.js +0 -1
  952. package/client/dist/assets/common-BykKlZg1.js +0 -1
  953. package/client/dist/assets/common-CvnNNSJA.js +0 -1
  954. package/client/dist/assets/common-D5zk_mqq.js +0 -1
  955. package/client/dist/assets/common-DQNO_al5.js +0 -1
  956. package/client/dist/assets/common-Dax30Vmp.js +0 -1
  957. package/client/dist/assets/common-DkllpVSb.js +0 -1
  958. package/client/dist/assets/core-B3mKBIh5.js +0 -1
  959. package/client/dist/assets/dashboard-B1ndRHuC.js +0 -1
  960. package/client/dist/assets/dashboard-BX7KXiqA.js +0 -1
  961. package/client/dist/assets/dashboard-B_BSNxcN.js +0 -1
  962. package/client/dist/assets/dashboard-CCeFN7-V.js +0 -1
  963. package/client/dist/assets/dashboard-CRl0WtFJ.js +0 -1
  964. package/client/dist/assets/dashboard-XGdQ5mjw.js +0 -1
  965. package/client/dist/assets/dashboard-_oltA6Jd.js +0 -1
  966. package/client/dist/assets/dashboard-bAuf5KVk.js +0 -1
  967. package/client/dist/assets/dialog-DtdR05v1.js +0 -45
  968. package/client/dist/assets/dist-js-CJ_2XX1Y.js +0 -1
  969. package/client/dist/assets/event-Bt7f3wXe.js +0 -1
  970. package/client/dist/assets/explore-BG99VGpL.js +0 -1
  971. package/client/dist/assets/explore-C0TjprJW.js +0 -1
  972. package/client/dist/assets/explore-C2dgEo7q.js +0 -1
  973. package/client/dist/assets/explore-C8NDHbob.js +0 -1
  974. package/client/dist/assets/explore-CWWgzQGR.js +0 -1
  975. package/client/dist/assets/explore-CcQXpdtS.js +0 -1
  976. package/client/dist/assets/explore-DgBACn39.js +0 -1
  977. package/client/dist/assets/explore-DsXAgnmJ.js +0 -1
  978. package/client/dist/assets/file-text-C0blZHLh.js +0 -1
  979. package/client/dist/assets/formatDistanceToNow-NjPHBLfB.js +0 -1
  980. package/client/dist/assets/getTimezoneOffsetInMilliseconds-vJ7qUoqN.js +0 -1
  981. package/client/dist/assets/git-branch-yf6LE1Bw.js +0 -1
  982. package/client/dist/assets/index-BgbCbIua.css +0 -2
  983. package/client/dist/assets/index-Ce4yZtKf.js +0 -83
  984. package/client/dist/assets/integrations-BkpRUbvp.js +0 -1
  985. package/client/dist/assets/integrations-Bo8qbJf4.js +0 -1
  986. package/client/dist/assets/integrations-CmSrKzZb.js +0 -1
  987. package/client/dist/assets/integrations-DGtq26Rr.js +0 -1
  988. package/client/dist/assets/integrations-De38GFnQ.js +0 -1
  989. package/client/dist/assets/integrations-Dw6zdtb-.js +0 -1
  990. package/client/dist/assets/integrations-Dwl9KQp0.js +0 -1
  991. package/client/dist/assets/integrations-Refg_d2I.js +0 -1
  992. package/client/dist/assets/jira-B6OYw4CJ.js +0 -1
  993. package/client/dist/assets/jira-BTF6RaOe.js +0 -1
  994. package/client/dist/assets/jira-CEetIB2q.js +0 -1
  995. package/client/dist/assets/jira-CIzsZLw5.js +0 -1
  996. package/client/dist/assets/jira-Daw9tmpI.js +0 -1
  997. package/client/dist/assets/jira-FXr7u2lh.js +0 -1
  998. package/client/dist/assets/jira-LaNQn7yl.js +0 -1
  999. package/client/dist/assets/jira-api-Cabj-H0J.js +0 -1
  1000. package/client/dist/assets/job-time-BCL7wee9.js +0 -1
  1001. package/client/dist/assets/jobs-ARwD85B9.js +0 -1
  1002. package/client/dist/assets/jobs-BMF1w4WT.js +0 -1
  1003. package/client/dist/assets/jobs-CBfzGLwm.js +0 -1
  1004. package/client/dist/assets/jobs-CPjiluBY.js +0 -1
  1005. package/client/dist/assets/jobs-CQQd58pY.js +0 -1
  1006. package/client/dist/assets/jobs-De3EqaO0.js +0 -1
  1007. package/client/dist/assets/jobs-Du9-Ei9a.js +0 -1
  1008. package/client/dist/assets/jobs-qMHbnxwC.js +0 -1
  1009. package/client/dist/assets/layers-BCLTgHXO.js +0 -1
  1010. package/client/dist/assets/loader-circle-BqV9xYGf.js +0 -1
  1011. package/client/dist/assets/loop-layout-CyXj9223.js +0 -7
  1012. package/client/dist/assets/loops-B2PhQLKR.js +0 -1
  1013. package/client/dist/assets/loops-BqbF46st.js +0 -1
  1014. package/client/dist/assets/loops-CINnHbfI.js +0 -1
  1015. package/client/dist/assets/loops-D-3XhH04.js +0 -1
  1016. package/client/dist/assets/loops-DKkEEjZ_.js +0 -1
  1017. package/client/dist/assets/loops-DzWR5-v6.js +0 -1
  1018. package/client/dist/assets/loops-WyWDkhok.js +0 -1
  1019. package/client/dist/assets/loops-scD5fIBf.js +0 -1
  1020. package/client/dist/assets/mcp-6rMoZfEO.js +0 -1
  1021. package/client/dist/assets/mcp-BD8sL5mP.js +0 -1
  1022. package/client/dist/assets/mcp-BkcA3I5s.js +0 -1
  1023. package/client/dist/assets/mcp-CCpSelOh.js +0 -1
  1024. package/client/dist/assets/mcp-CUAN6ORK.js +0 -1
  1025. package/client/dist/assets/mcp-CqbRxRTE.js +0 -1
  1026. package/client/dist/assets/mcp-DP2YfVhO.js +0 -1
  1027. package/client/dist/assets/mcp-DUVQamDz.js +0 -1
  1028. package/client/dist/assets/narration-BEKMVxGm.js +0 -1
  1029. package/client/dist/assets/narration-CjLwGKap.js +0 -1
  1030. package/client/dist/assets/narration-DANWuGsW.js +0 -1
  1031. package/client/dist/assets/narration-DGeEDWiT.js +0 -1
  1032. package/client/dist/assets/narration-DJgpGwIP.js +0 -1
  1033. package/client/dist/assets/narration-DbHnz0qV.js +0 -1
  1034. package/client/dist/assets/narration-bZSsTZG8.js +0 -1
  1035. package/client/dist/assets/narration-i6aKJKEc.js +0 -1
  1036. package/client/dist/assets/nav--u7iPYlS.js +0 -1
  1037. package/client/dist/assets/nav-C5Jgfaby.js +0 -1
  1038. package/client/dist/assets/nav-CAna_Wpt.js +0 -1
  1039. package/client/dist/assets/nav-CCLqeyHo.js +0 -1
  1040. package/client/dist/assets/nav-Cf3c90Jk.js +0 -1
  1041. package/client/dist/assets/nav-DMYQaQjR.js +0 -1
  1042. package/client/dist/assets/nav-Df_PkZ9F.js +0 -1
  1043. package/client/dist/assets/nav-VyNGBJwj.js +0 -1
  1044. package/client/dist/assets/packet-8nn9RsU7.js +0 -1
  1045. package/client/dist/assets/packet-B0H15elv.js +0 -1
  1046. package/client/dist/assets/packet-BQvBgrwh.js +0 -1
  1047. package/client/dist/assets/packet-BR7mO0-a.js +0 -1
  1048. package/client/dist/assets/packet-BgcQ6q_K.js +0 -1
  1049. package/client/dist/assets/packet-D2s92Jnn.js +0 -1
  1050. package/client/dist/assets/packet-YbtcD1HS.js +0 -1
  1051. package/client/dist/assets/packet-c0Qj_9eX.js +0 -1
  1052. package/client/dist/assets/project-repositories-Cnnuj9Ia.js +0 -1
  1053. package/client/dist/assets/rotate-ccw-DalJAQQX.js +0 -1
  1054. package/client/dist/assets/settings-B1NV8Ow9.js +0 -1
  1055. package/client/dist/assets/settings-BQ8XFZeE.js +0 -1
  1056. package/client/dist/assets/settings-BRkxfBbO.js +0 -1
  1057. package/client/dist/assets/settings-C_CcU1dP.js +0 -1
  1058. package/client/dist/assets/settings-Cto9n0eL.js +0 -1
  1059. package/client/dist/assets/settings-Pyw8uYtL.js +0 -1
  1060. package/client/dist/assets/settings-b3HVCNNd.js +0 -1
  1061. package/client/dist/assets/settings-hdive4u6.js +0 -1
  1062. package/client/dist/assets/setup-Be485n2u.js +0 -1
  1063. package/client/dist/assets/setup-CKGUxKr-.js +0 -1
  1064. package/client/dist/assets/setup-Ck1Uwd7_.js +0 -1
  1065. package/client/dist/assets/setup-Cm774a6v.js +0 -1
  1066. package/client/dist/assets/setup-DIqMQpxt.js +0 -1
  1067. package/client/dist/assets/setup-DfCsoNFL.js +0 -1
  1068. package/client/dist/assets/setup-DkeE8mP0.js +0 -1
  1069. package/client/dist/assets/setup-xVntVaz1.js +0 -1
  1070. package/client/dist/assets/specs-Bqvtz2kz.js +0 -1
  1071. package/client/dist/assets/specs-CKes-kz6.js +0 -1
  1072. package/client/dist/assets/specs-CfXxPDNB.js +0 -1
  1073. package/client/dist/assets/specs-CyF9HuTI.js +0 -1
  1074. package/client/dist/assets/specs-DMj035Mt.js +0 -1
  1075. package/client/dist/assets/specs-DfIdoU5L.js +0 -1
  1076. package/client/dist/assets/specs-j5pGLQeU.js +0 -1
  1077. package/client/dist/assets/specs-xW5pkkB7.js +0 -1
  1078. package/client/dist/assets/spending-CQnrWiR3.js +0 -1
  1079. package/client/dist/assets/square-D0JTbRSR.js +0 -1
  1080. package/client/dist/assets/tauri-shell-DE6LfGPw.js +0 -2
  1081. package/client/dist/assets/terminal-BAzpHtpY.js +0 -1
  1082. package/client/dist/assets/terminal-C7dHeR3x.js +0 -1
  1083. package/client/dist/assets/terminal-CMla5Qsz.js +0 -1
  1084. package/client/dist/assets/terminal-CdNXH-n9.js +0 -1
  1085. package/client/dist/assets/terminal-Cw5bZsmV.js +0 -1
  1086. package/client/dist/assets/terminal-DFUP4eNv.js +0 -1
  1087. package/client/dist/assets/terminal-DGqljeK_.js +0 -1
  1088. package/client/dist/assets/terminal-cU70NodO.js +0 -1
  1089. package/client/dist/assets/tickets--tiSOCcn.js +0 -1
  1090. package/client/dist/assets/tickets-BUJ3DMWU.js +0 -1
  1091. package/client/dist/assets/tickets-C1WNPODq.js +0 -1
  1092. package/client/dist/assets/tickets-CDjhWmiE.js +0 -1
  1093. package/client/dist/assets/tickets-CLgPC3uO.js +0 -1
  1094. package/client/dist/assets/tickets-D41ZMQpf.js +0 -1
  1095. package/client/dist/assets/tickets-DEaQC06P.js +0 -1
  1096. package/client/dist/assets/tickets-kcMzbLCp.js +0 -1
  1097. package/client/dist/assets/trash-D8zYUmTg.js +0 -1
  1098. package/client/dist/assets/useDesktop-BjLT0_EE.js +0 -1
  1099. package/client/dist/assets/useRuntimeRuns-C97qEqMg.js +0 -1
  1100. package/client/dist/assets/useSharedWebSocket-Bj4LMp7b.js +0 -2
  1101. package/client/dist/assets/utils-BC4DHlz2.js +0 -1
  1102. package/docs/guide/en/getting-started/4-the-dashboard-tour.md +0 -48
  1103. package/docs/guide/es/getting-started/4-the-dashboard-tour.md +0 -48
  1104. package/server/dist/mobile/mobile-preview-channel.js +0 -179
  1105. package/server/dist/mobile/mobile-preview.js +0 -366
  1106. package/server/dist/modules/browser/domain/preview-origins.js +0 -117
  1107. package/server/dist/modules/browser/runtime/preview-targets.js +0 -80
  1108. /package/client/dist/assets/{atom-one-dark-B-oHczHB.css → DocView-B-oHczHB.css} +0 -0
  1109. /package/docs/guide/de/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1110. /package/docs/guide/en/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1111. /package/docs/guide/es/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1112. /package/docs/guide/fr/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1113. /package/docs/guide/it/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1114. /package/docs/guide/ja/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1115. /package/docs/guide/pt/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1116. /package/docs/guide/zh/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
@@ -0,0 +1,1089 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.systemClock = exports.FLOW_FAILURE_RETURN_TURN_TEXT = exports.FLOW_RETURN_TURN_TEXT = void 0;
37
+ exports.deliveryFailureOf = deliveryFailureOf;
38
+ exports.isCrashedFlowDelivery = isCrashedFlowDelivery;
39
+ exports.railOfTicket = railOfTicket;
40
+ exports.createFlowTickets = createFlowTickets;
41
+ exports.launchOptionsOf = launchOptionsOf;
42
+ exports.createFlowWorktrees = createFlowWorktrees;
43
+ exports.createFlowPorts = createFlowPorts;
44
+ exports.createFlowHandOffAuthority = createFlowHandOffAuthority;
45
+ exports.createFlowTurnContext = createFlowTurnContext;
46
+ exports.flowConversationSummary = flowConversationSummary;
47
+ exports.changeNameFromArchive = changeNameFromArchive;
48
+ exports.readDerivedChange = readDerivedChange;
49
+ exports.createFlowPublication = createFlowPublication;
50
+ exports.startFlowSettlementScheduler = startFlowSettlementScheduler;
51
+ /**
52
+ * Production bindings of the Flow ports onto the other capabilities: delivery
53
+ * (worktree machinery, rail launch), specs (placeholder ticket), missions/Core
54
+ * agent sessions, accounting and the project's WebSocket. Bound to ONE project
55
+ * context at composition (project-registry); the application never sees them.
56
+ */
57
+ const fs = __importStar(require("node:fs"));
58
+ const path = __importStar(require("node:path"));
59
+ const ids_1 = require("../../../ids");
60
+ const internal_api_1 = require("../../../internal-api");
61
+ const desktop_db_1 = require("../../../desktop-db");
62
+ const repo_lock_1 = require("../../../repo-lock");
63
+ const worktree_manager_1 = require("../../../worktree-manager");
64
+ const worktree_overlay_1 = require("../../../worktree-overlay");
65
+ const worktree_node_modules_1 = require("../../../worktree-node-modules");
66
+ const agent_store_1 = require("../../agents/runtime/agent-store");
67
+ const project_repositories_1 = require("../../../project-repositories");
68
+ const workspace_resolution_1 = require("../../../workspace-resolution");
69
+ const jira_db_1 = require("../../../jira/jira-db");
70
+ const providers_1 = require("../../../providers");
71
+ const provider_selection_1 = require("../../../provider-selection");
72
+ const runtime_1 = require("../../../providers/runtime");
73
+ const process_admission_1 = require("../../../process-admission");
74
+ const project_router_helpers_1 = require("../../../project-router-helpers");
75
+ const agent_runtime_controls_router_1 = require("../../agent-runtime/runtime/agent-runtime-controls-router");
76
+ const delivery_evidence_1 = require("../../delivery/runtime/delivery-evidence");
77
+ const flow_review_outcome_1 = require("../../delivery/runtime/flow-review-outcome");
78
+ const rail_pr_store_1 = require("../../delivery/runtime/rail-pr-store");
79
+ const flow_worktree_return_1 = require("../../delivery/runtime/flow-worktree-return");
80
+ const spec_generation_1 = require("../../specs/runtime/spec-generation");
81
+ const isolated_worktree_1 = require("../../delivery/runtime/isolated-worktree");
82
+ const flow_worktree_handoff_1 = require("../../delivery/runtime/flow-worktree-handoff");
83
+ const rails_store_1 = require("../../delivery/runtime/rails-store");
84
+ const agent_flow_prompt_1 = require("../../missions/runtime/agent-flow-prompt");
85
+ const agent_failure_briefing_1 = require("../../missions/runtime/agent-failure-briefing");
86
+ const flow_turn_context_1 = require("../../missions/runtime/flow-turn-context");
87
+ const ticket_store_1 = require("../../specs/runtime/ticket-store");
88
+ const spec_addenda_1 = require("../../specs/runtime/spec-addenda");
89
+ const spec_addenda_core_1 = require("../../specs/runtime/spec-addenda-core");
90
+ const rails_store_2 = require("../../delivery/runtime/rails-store");
91
+ const rail_pr_store_2 = require("../../delivery/runtime/rail-pr-store");
92
+ const domain_1 = require("../domain");
93
+ /** The automatic turn after Back to Flow (the briefing itself rides the Flow turn). */
94
+ exports.FLOW_RETURN_TURN_TEXT = 'Back to Flow: the Flow → Spec run came back with the findings above. In at most 2 short lines say what you will fix, then start fixing it in this worktree. If a finding leaves a genuine decision to me (for example removing behaviour nobody asked for versus recording it as a requirement), offer it as an `options` block before editing and wait for my answer.';
95
+ /** The automatic turn after a Flow → Spec run failed outright and came back on its own. */
96
+ exports.FLOW_FAILURE_RETURN_TURN_TEXT = 'Back to Flow: the Flow → Spec run failed with the error above and the worktree came back to this Flow intact. In at most 2 short lines tell me what failed in plain words and what you will do. If the cause is in this worktree, fix it here; if it is outside it (a tool version, the environment, credentials), tell me exactly what to change instead of working around it.';
97
+ /** Status codes of a Flow → Spec run that stopped for review reasons (never a crash). */
98
+ const FLOW_REVIEW_STATUS_CODES = new Set(['review_changes_requested', 'returned_to_flow']);
99
+ /** The delivery codes of a Flow → Spec run that failed outright (null for a review outcome). */
100
+ function deliveryFailureOf(snap) {
101
+ if (snap.flowReview)
102
+ return null;
103
+ // After the return, the delivery's own codes say `returned_to_flow`: the crash codes are gone.
104
+ const returned = snap.statusCode === 'returned_to_flow';
105
+ return {
106
+ stepId: null,
107
+ cause: null,
108
+ statusCode: returned ? null : snap.statusCode ?? null,
109
+ failureCode: snap.units.find((unit) => unit.failureCode)?.failureCode ?? null,
110
+ statusDetail: returned ? null : snap.statusDetail ?? null,
111
+ };
112
+ }
113
+ /** Whether a Flow → Spec delivery failed outright and is idle (the automatic return may take its worktree). */
114
+ function isCrashedFlowDelivery(snap) {
115
+ return snap.loopId === flow_review_outcome_1.FLOW_SPEC_DELIVERY_LOOP_ID
116
+ && snap.decision === 'implementation_failed'
117
+ && !snap.flowReview
118
+ && !FLOW_REVIEW_STATUS_CODES.has(snap.statusCode ?? '')
119
+ && !snap.operation;
120
+ }
121
+ exports.systemClock = { now: () => new Date().toISOString() };
122
+ function canonical(value) {
123
+ try {
124
+ return fs.realpathSync.native(value);
125
+ }
126
+ catch {
127
+ return path.resolve(value);
128
+ }
129
+ }
130
+ function isInside(child, parent) {
131
+ const relative = path.relative(canonical(parent), canonical(child));
132
+ return relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative);
133
+ }
134
+ /** The rail of a spec from the project's rails and their live deliveries. */
135
+ function railOfTicket(db) {
136
+ return (ticketId) => {
137
+ const rail = (0, rails_store_2.getRails)(db).find((candidate) => candidate.ticketIds.includes(ticketId));
138
+ if (!rail)
139
+ return null;
140
+ return { railIndex: rail.railIndex, running: Boolean((0, rail_pr_store_2.getActivePrDeliveryByRail)(db, rail.railIndex)) };
141
+ };
142
+ }
143
+ const CLOSED_SPEC_STATUSES = new Set(['done', 'cancelled']);
144
+ /** The open addenda of a spec, as the first Flow turn lists them. */
145
+ function renderOpenAddenda(ticket) {
146
+ const open = (0, spec_addenda_core_1.openAddenda)(ticket.addenda);
147
+ if (!open.length)
148
+ return '';
149
+ return ['## Open addenda (iterations requested on this spec)', '', ...open.slice(0, 20).map((addendum, index) => `${index + 1}. [${addendum.kind}] ${addendum.title}${addendum.body.trim() ? `\n ${addendum.body.trim().slice(0, 600).replace(/\n/g, '\n ')}` : ''}`)].join('\n');
150
+ }
151
+ function snapshotOf(ticket) {
152
+ return {
153
+ id: ticket.id,
154
+ title: ticket.title,
155
+ description: ticket.description ?? '',
156
+ status: ticket.status,
157
+ nonGoals: Array.isArray(ticket.nonGoals) ? ticket.nonGoals.filter((goal) => typeof goal === 'string') : [],
158
+ repositoryIds: Array.isArray(ticket.repositoryIds) ? ticket.repositoryIds.filter((id) => typeof id === 'string') : [],
159
+ addenda: renderOpenAddenda(ticket),
160
+ };
161
+ }
162
+ /** Why this spec cannot start a Flow now (null ⇒ it can). `flowId`: the Flow re-checking its own adoption. */
163
+ function existingSpecBlocker(ticket, railOf, flowId) {
164
+ if (!ticket)
165
+ return { code: 'spec_not_found', message: 'This spec no longer exists' };
166
+ if (CLOSED_SPEC_STATUSES.has(ticket.status))
167
+ return { code: 'spec_closed', message: `Spec #${ticket.id} is ${ticket.status === 'done' ? 'done' : 'cancelled'}; reopen it to work on it in Flow` };
168
+ if ((0, ticket_store_1.isFlowHeldTicket)(ticket) && ticket.metadata?.flow?.flowId !== flowId)
169
+ return { code: 'spec_in_flow', message: `Spec #${ticket.id} is already in Flow` };
170
+ const rail = railOf?.(ticket.id) ?? null;
171
+ if (rail?.running)
172
+ return { code: 'spec_running', message: `Spec #${ticket.id} is running on Rail ${rail.railIndex + 1}` };
173
+ if (rail)
174
+ return { code: 'spec_on_rail', message: `Spec #${ticket.id} is on Rail ${rail.railIndex + 1}; take it off the rail to start it in Flow` };
175
+ return null;
176
+ }
177
+ function createFlowTickets(ctx, clock = exports.systemClock, railOf) {
178
+ const file = () => (0, spec_addenda_1.ticketStorePathForProject)(ctx.project);
179
+ const announce = (revision, message) => {
180
+ try {
181
+ ctx.ticketWatcher.notifyDesktopWrite(revision);
182
+ }
183
+ catch { /* watcher is advisory */ }
184
+ try {
185
+ ctx.broadcast(message);
186
+ }
187
+ catch { /* clients rehydrate */ }
188
+ };
189
+ return {
190
+ createPlaceholder(input) {
191
+ let created;
192
+ // The non-promoting path: a plain local spec write. Jira sees nothing
193
+ // until the Flow -> Spec rail settles (isFlowHeldTicket guards promotion).
194
+ const store = (0, ticket_store_1.mutateStore)(file(), (s) => {
195
+ const id = s.next_id++;
196
+ created = {
197
+ id,
198
+ title: input.title,
199
+ description: input.description,
200
+ status: 'in_progress',
201
+ priority: 'medium',
202
+ labels: [],
203
+ assignee: null,
204
+ prerequisites: [],
205
+ metadata: {
206
+ flow: { conversationId: input.conversationId, flowId: input.flowId, worktreeId: input.flowId, startedAt: input.startedAt, state: 'active', chosenMode: 'flow' },
207
+ },
208
+ // A Flow in a non-primary repository: the spec targets exactly it, so
209
+ // the hand-off and every later launch run in that repository.
210
+ ...(input.repositoryIds?.length ? { repositoryIds: [...input.repositoryIds] } : {}),
211
+ comments: [],
212
+ origin_conversation_id: null,
213
+ is_epic: false,
214
+ parent_epic_id: null,
215
+ execution_order: null,
216
+ short_summary: null,
217
+ created_at: input.startedAt,
218
+ updated_at: input.startedAt,
219
+ created_by: 'flow',
220
+ source: 'flow',
221
+ };
222
+ s.tickets[String(id)] = created;
223
+ });
224
+ announce(store.revision, { type: 'ticket_created', ticket: created, projectId: ctx.project.id, timestamp: clock.now() });
225
+ return created.id;
226
+ },
227
+ setFlowState(ticketId, state) {
228
+ let updated;
229
+ const store = (0, ticket_store_1.mutateStore)(file(), (s) => {
230
+ const ticket = s.tickets[String(ticketId)];
231
+ if (!ticket?.metadata?.flow || ticket.metadata.flow.state === state)
232
+ return;
233
+ ticket.metadata.flow = { ...ticket.metadata.flow, state };
234
+ ticket.updated_at = clock.now();
235
+ updated = ticket;
236
+ });
237
+ if (updated)
238
+ announce(store.revision, { type: 'ticket_updated', ticket: updated, projectId: ctx.project.id, timestamp: clock.now() });
239
+ },
240
+ deletePlaceholder(ticketId) {
241
+ let deleted = false;
242
+ const store = (0, ticket_store_1.mutateStore)(file(), (s) => {
243
+ const ticket = s.tickets[String(ticketId)];
244
+ // Only a Flow placeholder is ever deleted by Flow: never the person's own spec.
245
+ if (!ticket?.metadata?.flow || ticket.metadata.flow.origin === 'existing')
246
+ return;
247
+ delete s.tickets[String(ticketId)];
248
+ deleted = true;
249
+ });
250
+ if (deleted)
251
+ announce(store.revision, { type: 'ticket_deleted', ticketId, projectId: ctx.project.id, timestamp: clock.now() });
252
+ },
253
+ markDelivered(ticketId, input) {
254
+ let updated;
255
+ const store = (0, ticket_store_1.mutateStore)(file(), (s) => {
256
+ const ticket = s.tickets[String(ticketId)];
257
+ if (!ticket?.metadata?.flow)
258
+ return;
259
+ const changeName = input.openspecChangeName ?? (typeof ticket.metadata.openspecChangeName === 'string' ? ticket.metadata.openspecChangeName : null);
260
+ const unchanged = ticket.metadata.flow.state === 'delivered' && ticket.metadata.openspecChangeName === (changeName ?? undefined)
261
+ && ticket.status !== 'in_progress' && ticket.status !== 'todo';
262
+ if (unchanged)
263
+ return;
264
+ ticket.metadata = { ...ticket.metadata, flow: { ...ticket.metadata.flow, state: 'delivered' }, ...(changeName ? { openspecChangeName: changeName } : {}) };
265
+ // The delivery is on review; never pull back a ticket that moved on (done, cancelled).
266
+ if (ticket.status === 'in_progress' || ticket.status === 'todo')
267
+ ticket.status = 'on_review';
268
+ ticket.updated_at = clock.now();
269
+ updated = ticket;
270
+ });
271
+ if (updated)
272
+ announce(store.revision, { type: 'ticket_updated', ticket: updated, projectId: ctx.project.id, timestamp: clock.now() });
273
+ },
274
+ read(ticketId) {
275
+ const ticket = (0, ticket_store_1.readStore)(file()).tickets[String(ticketId)];
276
+ if (!ticket)
277
+ return null;
278
+ const spec = snapshotOf(ticket);
279
+ return { title: spec.title, description: spec.description, status: spec.status, repositoryIds: [...spec.repositoryIds], nonGoals: [...spec.nonGoals] };
280
+ },
281
+ inspectExisting(ticketId) {
282
+ const ticket = (0, ticket_store_1.readStore)(file()).tickets[String(ticketId)];
283
+ return { spec: ticket ? snapshotOf(ticket) : null, blocker: existingSpecBlocker(ticket, railOf) };
284
+ },
285
+ adoptExisting(input) {
286
+ let adopted;
287
+ let blocker = null;
288
+ const store = (0, ticket_store_1.mutateStore)(file(), (s) => {
289
+ const ticket = s.tickets[String(input.ticketId)];
290
+ blocker = existingSpecBlocker(ticket, railOf, input.flowId);
291
+ if (blocker || !ticket)
292
+ return;
293
+ const current = ticket.metadata?.flow;
294
+ // Idempotent: this Flow already holds the spec.
295
+ if (current?.flowId === input.flowId && current.origin === 'existing') {
296
+ adopted = ticket;
297
+ return;
298
+ }
299
+ const previousStatus = ticket.status;
300
+ ticket.metadata = {
301
+ ...ticket.metadata,
302
+ flow: {
303
+ conversationId: input.conversationId, flowId: input.flowId, worktreeId: input.flowId, startedAt: input.startedAt,
304
+ state: 'active', chosenMode: 'flow', origin: 'existing', previousStatus,
305
+ },
306
+ };
307
+ // The same "in progress, In Flow" a placeholder spec shows.
308
+ ticket.status = 'in_progress';
309
+ ticket.updated_at = clock.now();
310
+ adopted = ticket;
311
+ });
312
+ if (blocker) {
313
+ const reason = blocker;
314
+ if (reason.code === 'spec_not_found')
315
+ throw new domain_1.FlowValidationError(reason.code, reason.message);
316
+ throw new domain_1.FlowConflictError(reason.code, reason.message);
317
+ }
318
+ announce(store.revision, { type: 'ticket_updated', ticket: adopted, projectId: ctx.project.id, timestamp: clock.now() });
319
+ return snapshotOf(adopted);
320
+ },
321
+ restoreExisting(ticketId, flowId) {
322
+ let updated;
323
+ const store = (0, ticket_store_1.mutateStore)(file(), (s) => {
324
+ const ticket = s.tickets[String(ticketId)];
325
+ const flow = ticket?.metadata?.flow;
326
+ // Only the spec THIS Flow holds; an existing spec is never deleted.
327
+ if (!ticket || !flow || flow.flowId !== flowId || flow.origin !== 'existing')
328
+ return;
329
+ const { flow: _held, ...metadata } = ticket.metadata ?? {};
330
+ ticket.metadata = metadata;
331
+ // Its own status comes back unless it moved on meanwhile (done, cancelled…).
332
+ if (ticket.status === 'in_progress' && flow.previousStatus)
333
+ ticket.status = flow.previousStatus;
334
+ ticket.updated_at = clock.now();
335
+ updated = ticket;
336
+ });
337
+ if (updated)
338
+ announce(store.revision, { type: 'ticket_updated', ticket: updated, projectId: ctx.project.id, timestamp: clock.now() });
339
+ },
340
+ preserveOriginal(ticketId, flowId) {
341
+ let updated;
342
+ const store = (0, ticket_store_1.mutateStore)(file(), (s) => {
343
+ const ticket = s.tickets[String(ticketId)];
344
+ const flow = ticket?.metadata?.flow;
345
+ if (!ticket || !flow || flow.flowId !== flowId)
346
+ return;
347
+ const comments = Array.isArray(ticket.comments) ? ticket.comments : [];
348
+ // Idempotent: the original was already kept for this Flow.
349
+ if (typeof flow.originalCommentId === 'number' && comments.some((comment) => comment.id === flow.originalCommentId))
350
+ return;
351
+ const id = comments.reduce((max, comment) => Math.max(max, typeof comment.id === 'number' ? comment.id : 0), 0) + 1;
352
+ const now = clock.now();
353
+ ticket.comments = [...comments, {
354
+ id,
355
+ body: (0, domain_1.buildOriginalSpecComment)({ title: ticket.title, description: ticket.description ?? '', nonGoals: Array.isArray(ticket.nonGoals) ? ticket.nonGoals : [], flowId }),
356
+ created_at: now,
357
+ created_by: 'flow',
358
+ }];
359
+ ticket.metadata = { ...ticket.metadata, flow: { ...flow, originalCommentId: id } };
360
+ ticket.updated_at = now;
361
+ updated = ticket;
362
+ });
363
+ if (updated)
364
+ announce(store.revision, { type: 'ticket_updated', ticket: updated, projectId: ctx.project.id, timestamp: clock.now() });
365
+ },
366
+ applyAddenda(ticketId, flowId, causalId) {
367
+ // Read-only probe first: a spec without live addenda (or a replay) never rewrites the store.
368
+ const probe = (0, ticket_store_1.readStore)(file()).tickets[String(ticketId)];
369
+ if (probe?.metadata?.flow?.flowId !== flowId || !(0, spec_addenda_core_1.readSpecAddenda)(probe.addenda).some((a) => a.status === 'open' || a.status === 'in_flight'))
370
+ return;
371
+ let updated;
372
+ const store = (0, ticket_store_1.mutateStore)(file(), (s) => {
373
+ const ticket = s.tickets[String(ticketId)];
374
+ // Only the spec this Flow holds (the label stays through settlement).
375
+ if (!ticket || ticket.metadata?.flow?.flowId !== flowId)
376
+ return;
377
+ if ((0, spec_addenda_1.applyFlowSpecAddenda)(s, ticketId, causalId, clock.now()))
378
+ updated = ticket;
379
+ });
380
+ if (updated)
381
+ announce(store.revision, { type: 'ticket_updated', ticket: updated, projectId: ctx.project.id, timestamp: clock.now() });
382
+ },
383
+ reopen(ticketId) {
384
+ let updated;
385
+ const store = (0, ticket_store_1.mutateStore)(file(), (s) => {
386
+ const ticket = s.tickets[String(ticketId)];
387
+ if (!ticket?.metadata?.flow)
388
+ return;
389
+ // A failed run moved the spec back to todo; Back to Flow works on it again.
390
+ // Never pull back a ticket that moved on (done, cancelled).
391
+ const status = ticket.status === 'todo' || ticket.status === 'on_review' ? 'in_progress' : ticket.status;
392
+ if (status === ticket.status && ticket.metadata.flow.state === 'paused')
393
+ return;
394
+ ticket.status = status;
395
+ ticket.metadata = { ...ticket.metadata, flow: { ...ticket.metadata.flow, state: 'paused' } };
396
+ ticket.updated_at = clock.now();
397
+ updated = ticket;
398
+ });
399
+ if (updated)
400
+ announce(store.revision, { type: 'ticket_updated', ticket: updated, projectId: ctx.project.id, timestamp: clock.now() });
401
+ },
402
+ };
403
+ }
404
+ /** The engine choices a stopped Flow → Spec launch used (Relaunch repeats them). */
405
+ function launchOptionsOf(raw) {
406
+ let config = {};
407
+ try {
408
+ const parsed = raw ? JSON.parse(raw) : null;
409
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
410
+ config = parsed;
411
+ }
412
+ catch { /* defaults */ }
413
+ const text = (value) => typeof value === 'string' && value.trim() && value.length <= 200 ? value.trim() : undefined;
414
+ const loopId = text(config.loopId), aiEngine = text(config.aiEngine), model = text(config.model), reasoningEffort = text(config.reasoning_effort ?? config.reasoningEffort);
415
+ return { ...(loopId ? { loopId } : {}), ...(aiEngine ? { aiEngine } : {}), ...(model ? { model } : {}), ...(reasoningEffort ? { reasoningEffort } : {}) };
416
+ }
417
+ // ─── Worktree reservation (delivery's single machinery) ───────────────────────
418
+ function readOverlayManifest(worktreePath) {
419
+ try {
420
+ const parsed = JSON.parse(fs.readFileSync(path.join(worktreePath, worktree_overlay_1.OVERLAY_MANIFEST), 'utf8'));
421
+ return Array.isArray(parsed.paths) ? parsed.paths.filter((entry) => typeof entry === 'string') : [];
422
+ }
423
+ catch {
424
+ return [];
425
+ }
426
+ }
427
+ async function forkPoint(git, worktreePath, repo) {
428
+ const branch = await git.run(['symbolic-ref', '--quiet', '--short', 'HEAD'], repo);
429
+ if (branch.code !== 0 || !branch.stdout.trim())
430
+ return null;
431
+ const base = await git.run(['merge-base', 'HEAD', branch.stdout.trim()], worktreePath);
432
+ const sha = base.code === 0 ? base.stdout.trim() : '';
433
+ return /^[0-9a-f]{40,64}$/i.test(sha) ? sha : null;
434
+ }
435
+ function excludedFromDiff(file, overlay) {
436
+ if (file === worktree_overlay_1.OVERLAY_MANIFEST)
437
+ return true;
438
+ if (file === 'node_modules' || file.startsWith('node_modules/') || file.includes('/node_modules/'))
439
+ return true;
440
+ const roots = [...worktree_manager_1.PR_NEVER_STAGE_PATHSPEC_ROOTS, ...overlay];
441
+ return roots.some((root) => file === root || file.startsWith(`${root.replace(/\/$/, '')}/`));
442
+ }
443
+ const STATUS = { A: 'added', M: 'modified', D: 'deleted', R: 'renamed', T: 'modified', C: 'added' };
444
+ function createFlowWorktrees(ctx, deps = { providerFor: () => 'claude' }) {
445
+ const git = deps.git ?? worktree_manager_1.defaultGitRunner;
446
+ // The Flow's repository: the project root for the primary (unchanged), or a
447
+ // non-primary Git member's own checkout and per-repository mount root.
448
+ const repositoryTarget = (repositoryId) => {
449
+ try {
450
+ return (0, isolated_worktree_1.isolatedRepositoryTarget)(ctx.project, repositoryId);
451
+ }
452
+ catch (error) {
453
+ throw new domain_1.FlowConflictError('flow_repository_missing', `The Flow's repository is no longer usable: ${error instanceof Error ? error.message : String(error)}`);
454
+ }
455
+ };
456
+ const flowRoot = (flowId, repositoryId) => path.join(repositoryTarget(repositoryId).worktreesRoot, flowId);
457
+ return {
458
+ async reserve(input) {
459
+ let prepared;
460
+ repositoryTarget(input.repositoryId);
461
+ try {
462
+ prepared = await (deps.prepare ?? isolated_worktree_1.prepareIsolatedWorktree)({
463
+ ctx: ctx,
464
+ ticketId: input.ticketId,
465
+ provider: deps.providerFor(input.conversationId),
466
+ // The Flow id is the mount id: the worktree path is provably Flow-owned.
467
+ runId: input.flowId,
468
+ ...(input.repositoryId ? { repositoryId: input.repositoryId } : {}),
469
+ }, { git });
470
+ }
471
+ catch (error) {
472
+ if (error instanceof isolated_worktree_1.RepositoryHasNoCommitsError)
473
+ throw new domain_1.FlowConflictError(error.code, error.message);
474
+ throw error;
475
+ }
476
+ // The Flow's base is the reservation SHA; never leave it unknown (a null
477
+ // base would measure the diff against HEAD and lose committed work).
478
+ return { branch: prepared.branch, worktreePath: prepared.worktreePath, baseSha: prepared.baseSha ?? prepared.initialSha, headSha: prepared.initialSha };
479
+ },
480
+ async release(input) {
481
+ const repo = repositoryTarget(input.repositoryId).path;
482
+ const root = flowRoot(input.flowId, input.repositoryId);
483
+ const target = input.worktreePath ?? (0, worktree_manager_1.worktreePath)(root, input.ticketId);
484
+ // Never remove anything outside the Flow's own mount root.
485
+ if (!isInside(target, root))
486
+ throw new Error(`Refusing to remove ${target}: it is not a Flow-owned worktree`);
487
+ await (0, repo_lock_1.withRepoLock)(repo, async () => {
488
+ const mounted = (await (0, worktree_manager_1.listWorktrees)(git, repo)).some((entry) => canonical(entry) === canonical(target));
489
+ let branch = input.branch;
490
+ if (mounted && !branch) {
491
+ const head = await git.run(['rev-parse', '--abbrev-ref', 'HEAD'], target);
492
+ branch = head.code === 0 && head.stdout.trim() !== 'HEAD' ? head.stdout.trim() : null;
493
+ }
494
+ if (mounted) {
495
+ await (0, worktree_manager_1.removeWorktree)(git, { repoDir: repo, worktreePath: target, branch: branch ?? '', deleteBranch: Boolean(branch), force: true });
496
+ }
497
+ else if (branch) {
498
+ // The mount is gone but the Flow-created branch may remain.
499
+ await git.run(['branch', '-D', branch], repo).catch(() => undefined);
500
+ }
501
+ try {
502
+ fs.rmSync(root, { recursive: true, force: true });
503
+ }
504
+ catch { /* best effort: empty mount root */ }
505
+ });
506
+ },
507
+ async freeze(input) {
508
+ const { path: repo, primary } = repositoryTarget(input.repositoryId);
509
+ return (0, repo_lock_1.withRepoLock)(repo, async () => {
510
+ // Same never-commit set the rail uses: overlay links and warm node_modules.
511
+ const sources = (0, isolated_worktree_1.resolveOverlaySources)({ slug: ctx.project.slug, baseRepo: repo, provider: deps.providerFor(input.conversationId) }, primary ? undefined : () => (0, workspace_resolution_1.resolveProjectExecution)(ctx.project));
512
+ const overlay = (0, worktree_overlay_1.applyWorktreeOverlay)({ worktreePath: input.worktreePath, ...sources });
513
+ const warm = (0, worktree_node_modules_1.linkNodeModulesIntoWorktree)(repo, input.worktreePath);
514
+ const excludes = [...new Set([...overlay.createdPaths, ...(warm.authenticated ?? warm.linked ?? [])])];
515
+ const title = ctx.getTicketSpec(input.ticketId)?.title ?? `Flow ${input.flowId}`;
516
+ // The Flow's own derived change (a returned Flow → Spec run left it
517
+ // active) is intended; any other new active change still blocks.
518
+ // Everything in a Flow worktree is the Flow's own work. A single active
519
+ // change the Flow does not know yet (an earlier Flow -> Spec run named
520
+ // it differently) is adopted as its derived change; several are
521
+ // ambiguous and still block, with a message the agent can act on.
522
+ const unknown = await unknownActiveChanges(git, input.worktreePath, input.baseSha, input.allowedChanges);
523
+ if (unknown.length > 1) {
524
+ throw new domain_1.FlowConflictError('flow_freeze_failed', `This Flow has ${unknown.length} open spec changes (${unknown.join(', ')}); keep one and archive or remove the others, then hand off again`, input.flowId);
525
+ }
526
+ const adoptedChange = unknown.length === 1 && !input.allowedChanges.some((name) => fs.existsSync(path.join(input.worktreePath, 'openspec', 'changes', name))) ? unknown[0] : undefined;
527
+ if (unknown.length === 1 && !adoptedChange) {
528
+ throw new domain_1.FlowConflictError('flow_freeze_failed', `This Flow has two open spec changes (${[...input.allowedChanges.filter((name) => fs.existsSync(path.join(input.worktreePath, 'openspec', 'changes', name))), unknown[0]].join(', ')}); keep one and archive or remove the other, then hand off again`, input.flowId);
529
+ }
530
+ const allowed = adoptedChange ? [...input.allowedChanges, adoptedChange] : input.allowedChanges;
531
+ const commit = await (0, worktree_manager_1.commitWorktreeAndVerify)(git, input.worktreePath, `Flow #${input.ticketId}: ${title}`, excludes, input.baseSha ?? undefined, { allowedActiveChanges: allowed });
532
+ if (!commit.clean) {
533
+ throw new domain_1.FlowConflictError('flow_freeze_failed', `The Flow worktree could not be committed: ${commit.error ?? commit.dirty.slice(0, 5).join(', ')}`, input.flowId);
534
+ }
535
+ const headSha = await (0, isolated_worktree_1.readHeadSha)(git, input.worktreePath);
536
+ if (!headSha)
537
+ throw new domain_1.FlowConflictError('flow_freeze_failed', 'The Flow worktree HEAD could not be verified', input.flowId);
538
+ return adoptedChange ? { headSha, adoptedChange } : { headSha };
539
+ });
540
+ },
541
+ exists(worktreePath) {
542
+ return fs.existsSync(path.join(worktreePath, '.git'));
543
+ },
544
+ async diff(input) {
545
+ const overlay = readOverlayManifest(input.worktreePath);
546
+ // Legacy sessions without a recorded base: the fork point from the
547
+ // project's checked-out branch, never HEAD (frozen commits would vanish).
548
+ const base = input.baseSha ?? await forkPoint(git, input.worktreePath, repositoryTarget(input.repositoryId).path) ?? 'HEAD';
549
+ const files = new Map();
550
+ const nameStatus = await git.run(['-c', 'core.quotepath=false', 'diff', '--no-renames', '--name-status', base, '--'], input.worktreePath);
551
+ if (nameStatus.code === 0) {
552
+ for (const line of nameStatus.stdout.split('\n')) {
553
+ const [code, file] = line.split('\t');
554
+ if (!file || excludedFromDiff(file, overlay))
555
+ continue;
556
+ files.set(file, { path: file, status: STATUS[code?.[0] ?? 'M'] ?? 'modified', additions: null, deletions: null });
557
+ }
558
+ }
559
+ const numstat = await git.run(['-c', 'core.quotepath=false', 'diff', '--no-renames', '--numstat', base, '--'], input.worktreePath);
560
+ if (numstat.code === 0) {
561
+ for (const line of numstat.stdout.split('\n')) {
562
+ const [added, removed, file] = line.split('\t');
563
+ const entry = file ? files.get(file) : undefined;
564
+ if (!entry)
565
+ continue;
566
+ entry.additions = added === '-' ? null : Number(added);
567
+ entry.deletions = removed === '-' ? null : Number(removed);
568
+ }
569
+ }
570
+ const untracked = await git.run(['-c', 'core.quotepath=false', 'ls-files', '--others', '--exclude-standard'], input.worktreePath);
571
+ if (untracked.code === 0) {
572
+ for (const file of untracked.stdout.split('\n').map((line) => line.trim()).filter(Boolean)) {
573
+ if (excludedFromDiff(file, overlay) || files.has(file))
574
+ continue;
575
+ files.set(file, { path: file, status: 'untracked', additions: null, deletions: null });
576
+ }
577
+ }
578
+ const list = [...files.values()].sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
579
+ return {
580
+ branch: input.branch,
581
+ baseSha: input.baseSha,
582
+ headSha: await (0, isolated_worktree_1.readHeadSha)(git, input.worktreePath),
583
+ files: list,
584
+ totals: {
585
+ files: list.length,
586
+ additions: list.reduce((sum, file) => sum + (file.additions ?? 0), 0),
587
+ deletions: list.reduce((sum, file) => sum + (file.deletions ?? 0), 0),
588
+ },
589
+ };
590
+ },
591
+ };
592
+ }
593
+ function createFlowPorts(deps) {
594
+ const { ctx, repository } = deps;
595
+ const clock = deps.clock ?? exports.systemClock;
596
+ const providerFor = (conversationId) => (0, agent_store_1.getAgentConversation)(ctx.desktopDb, conversationId)?.provider ?? ctx.project.provider ?? 'claude';
597
+ const host = () => {
598
+ const agentHost = deps.agentHost();
599
+ if (!agentHost)
600
+ throw new domain_1.FlowUnavailableError('Flow needs the mission agent chat, which is disabled');
601
+ return agentHost;
602
+ };
603
+ return {
604
+ repository,
605
+ // Target triage: a workspace or multi-repository project names the Git
606
+ // member a Flow runs in; a single repository is never triaged.
607
+ repositories: {
608
+ list: () => (0, project_repositories_1.getProjectRepositories)(ctx.project).map((member) => ({
609
+ id: member.id, name: member.name, isPrimary: member.isPrimary, kind: member.kind, ...(member.available === false ? { available: false } : {}),
610
+ })),
611
+ },
612
+ tickets: createFlowTickets(ctx, clock, railOfTicket(ctx.db)),
613
+ worktrees: createFlowWorktrees(ctx, { git: deps.git, providerFor }),
614
+ agent: {
615
+ async assertReady({ conversationId }) {
616
+ const conversation = (0, agent_store_1.getAgentConversation)(ctx.desktopDb, conversationId);
617
+ if (!conversation)
618
+ throw new domain_1.FlowValidationError('conversation_not_found', 'The mission conversation does not exist');
619
+ if (conversation.pinned_project_id !== ctx.project.id) {
620
+ throw new domain_1.FlowValidationError('conversation_not_pinned', 'Pin the mission to this project before starting a Flow');
621
+ }
622
+ try {
623
+ await host().assertFlowSupport(conversationId);
624
+ }
625
+ catch (error) {
626
+ if (error instanceof domain_1.FlowUnavailableError)
627
+ throw error;
628
+ throw new domain_1.FlowUnavailableError(error instanceof Error ? error.message : String(error));
629
+ }
630
+ },
631
+ async open({ flowId, renew }) {
632
+ // The Core session itself opens lazily on the first Flow turn (cwd = worktree).
633
+ // A resume never reuses a closed session: it gets a new generation.
634
+ return { coreSessionId: renew ? (0, domain_1.nextFlowCoreSessionId)(flowId, Date.now()) : (0, domain_1.flowCoreSessionId)(flowId) };
635
+ },
636
+ async close({ conversationId, coreSessionId }) {
637
+ const agentHost = deps.agentHost();
638
+ if (agentHost)
639
+ await agentHost.closeFlowSession(conversationId, coreSessionId, 'flow_closed');
640
+ },
641
+ launchEngine(conversationId) {
642
+ const conversation = (0, agent_store_1.getAgentConversation)(ctx.desktopDb, conversationId);
643
+ if (!conversation?.provider || !(0, provider_selection_1.isProviderEnabled)(ctx.project, conversation.provider))
644
+ return null;
645
+ return {
646
+ aiEngine: conversation.provider,
647
+ ...(conversation.model ? { model: conversation.model } : {}),
648
+ ...(conversation.reasoning_effort ? { reasoningEffort: conversation.reasoning_effort } : {}),
649
+ };
650
+ },
651
+ },
652
+ rails: {
653
+ async launch({ flowId, conversationId, ticketId, railIndex, options, repositoryId }) {
654
+ const rail = (0, rails_store_1.getRail)(ctx.db, railIndex);
655
+ if (rail.ticketIds.length > 0 && !(rail.ticketIds.length === 1 && rail.ticketIds[0] === ticketId)) {
656
+ throw new domain_1.FlowConflictError('rail_not_empty', `Rail ${railIndex} already carries other specs; pick a free rail`, flowId);
657
+ }
658
+ const base = `/projects/${encodeURIComponent(ctx.project.id)}/rails/${railIndex}`;
659
+ if (rail.ticketIds.length === 0) {
660
+ const assigned = await deps.internalApi.call('PUT', `${base}/tickets`, { ticketIds: [ticketId] });
661
+ if (!assigned.ok) {
662
+ const reason = (0, internal_api_1.internalApiError)(assigned);
663
+ throw new domain_1.FlowLaunchRejectedError(assigned.status, reason.error, reason.detail ?? reason.error);
664
+ }
665
+ }
666
+ const launched = await deps.internalApi.call('POST', `${base}/launch`, {
667
+ flowId,
668
+ originSurface: 'agent-chat',
669
+ originConversationId: conversationId,
670
+ // Never fall back to the rail's default loop: Flow hands off to Flow -> Spec unless told otherwise.
671
+ loopId: options.loopId ?? domain_1.FLOW_SPEC_LOOP_ID,
672
+ // A Flow in a non-primary repository launches exactly that repository.
673
+ ...(repositoryId ? { repositoryIds: [repositoryId] } : {}),
674
+ ...(options.aiEngine ? { aiEngine: options.aiEngine } : {}),
675
+ ...(options.model ? { model: options.model } : {}),
676
+ ...(options.reasoningEffort ? { reasoning_effort: options.reasoningEffort } : {}),
677
+ });
678
+ if (!launched.ok) {
679
+ const reason = (0, internal_api_1.internalApiError)(launched);
680
+ throw new domain_1.FlowLaunchRejectedError(launched.status, reason.error, reason.detail ?? reason.error);
681
+ }
682
+ const body = (launched.body ?? {});
683
+ return {
684
+ loopRunIds: Array.isArray(body.loopRunIds) ? body.loopRunIds.filter((id) => typeof id === 'string') : [],
685
+ deliveryId: typeof body.prDeliveryId === 'string' ? body.prDeliveryId : null,
686
+ };
687
+ },
688
+ stoppedDelivery(deliveryId) {
689
+ const row = (0, rail_pr_store_1.getPrDelivery)(ctx.db, deliveryId);
690
+ if (!row)
691
+ return null;
692
+ const derivation = (0, delivery_evidence_1.readSettleEvidence)(row.settle_evidence)?.units[0]?.runtime?.derivation ?? null;
693
+ const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
694
+ return {
695
+ railIndex: row.rail_index, options: launchOptionsOf(row.launch_config_json), findings: snap.flowReview ?? null,
696
+ derivation: derivation ? { change: derivation.change, files: derivation.files, explained: derivation.explained, unexplainedFiles: derivation.unexplainedFiles.slice(0, domain_1.FLOW_UNEXPLAINED_FILES_CAP), unexplainedOmitted: derivation.unexplainedOmitted + Math.max(0, derivation.unexplainedFiles.length - domain_1.FLOW_UNEXPLAINED_FILES_CAP) } : null,
697
+ failure: deliveryFailureOf(snap),
698
+ };
699
+ },
700
+ async runFailure(deliveryId) {
701
+ try {
702
+ const row = (0, rail_pr_store_1.getPrDelivery)(ctx.db, deliveryId);
703
+ const runId = row ? (0, rail_pr_store_1.toPrDeliverySnapshot)(row).runIds[0] : undefined;
704
+ if (!runId)
705
+ return null;
706
+ // The runtime's own record: the step it stopped at and its error
707
+ // (the same source the mission run card shows).
708
+ const summary = await (0, agent_runtime_controls_router_1.runtimeRunSummary)(ctx, runId);
709
+ if (!summary)
710
+ return null;
711
+ return {
712
+ stepId: summary.pendingApproval?.stepId ?? summary.nextStep ?? null,
713
+ cause: summary.status === 'failed' ? (0, domain_1.firstErrorLine)(summary.error) : null,
714
+ };
715
+ }
716
+ catch {
717
+ return null;
718
+ }
719
+ },
720
+ returnWorktree({ deliveryId, worktreePath, detail, commit }) {
721
+ try {
722
+ const closed = (0, flow_worktree_return_1.returnFlowWorktree)(ctx.db, { deliveryId, worktreePath, detail }, commit);
723
+ (0, flow_worktree_return_1.announceReturnedDelivery)(ctx.project.id, closed, (message) => ctx.broadcast(message));
724
+ }
725
+ catch (error) {
726
+ if (error instanceof flow_worktree_return_1.FlowReturnRejectedError)
727
+ throw new domain_1.FlowConflictError(error.code, error.message);
728
+ throw error;
729
+ }
730
+ },
731
+ },
732
+ conversation: {
733
+ postReturnCard({ conversationId, flowId, deliveryId, findings, derivation, failure }) {
734
+ deps.agentHost()?.postSystemRow?.(conversationId, {
735
+ kind: 'flow-return-briefing', flowId, deliveryId,
736
+ reason: findings?.reason ?? null, score: findings?.score ?? null, summary: findings?.summary ?? null,
737
+ issues: findings?.issues ?? [], issuesOmitted: findings?.issuesOmitted ?? 0, failingChecks: findings?.failingChecks ?? [],
738
+ derivation,
739
+ // A run that failed outright: the client localizes the step and keeps the codes as technical details.
740
+ ...(!findings && failure ? { failure } : {}),
741
+ at: clock.now(),
742
+ }, `flow-return-briefing:${deliveryId}`);
743
+ },
744
+ async startReturnTurn({ conversationId, deliveryId, failure }) {
745
+ await deps.agentHost()?.startAutomaticTurn?.(conversationId, failure ? exports.FLOW_FAILURE_RETURN_TURN_TEXT : exports.FLOW_RETURN_TURN_TEXT, { turnKey: `flow-return:${deliveryId}`, label: 'Back to Flow' });
746
+ },
747
+ postDeliveredSummary({ conversationId, flowId, deliveryId, ticketId, settlement }) {
748
+ const row = deliveryId ? (0, rail_pr_store_1.getPrDelivery)(ctx.db, deliveryId) : undefined;
749
+ const ticket = (0, ticket_store_1.readStore)((0, spec_addenda_1.ticketStorePathForProject)(ctx.project)).tickets[String(ticketId)];
750
+ const changeName = typeof ticket?.metadata?.openspecChangeName === 'string' ? ticket.metadata.openspecChangeName : null;
751
+ let jiraKey = null;
752
+ try {
753
+ const link = (0, jira_db_1.getLinkByLocalId)(ctx.db, ticketId);
754
+ jiraKey = link && !link.tombstoned ? link.jiraKey : null;
755
+ }
756
+ catch {
757
+ jiraKey = null;
758
+ }
759
+ deps.agentHost()?.postSystemRow?.(conversationId, {
760
+ kind: 'flow-delivered', flowId, deliveryId, ticketId,
761
+ prUrl: row?.pr_url ?? null, prNumber: row?.pr_number ?? null,
762
+ // Flow → Spec archives the change before it delivers (its `archive` step).
763
+ changeName, changeArchived: Boolean(changeName),
764
+ specRewrite: settlement.specRewrite, jiraCreate: settlement.jiraCreate, jiraKey,
765
+ at: clock.now(),
766
+ }, `flow-delivered:${flowId}`);
767
+ },
768
+ postBoundary({ conversationId, flowId, event, reason, branch }) {
769
+ const at = clock.now();
770
+ deps.agentHost()?.postSystemRow?.(conversationId, {
771
+ kind: 'flow-boundary', flowId, event, reason, branch, at,
772
+ }, `flow-boundary:${flowId}:${event}:${reason}:${at}`);
773
+ },
774
+ },
775
+ processes: deps.processes ?? { stop: async () => { } },
776
+ effects: deps.effects,
777
+ publication: createFlowPublication(ctx, { git: deps.git }),
778
+ usage: { costSoFar: (input) => (0, desktop_db_1.sumFlowInvocations)(ctx.desktopDb, input) },
779
+ notifier: {
780
+ changed(session) {
781
+ try {
782
+ ctx.broadcast({ type: 'flow.state', projectId: ctx.project.id, conversationId: session.conversationId, flowId: session.id, flow: session, timestamp: clock.now() });
783
+ }
784
+ catch { /* clients rehydrate through GET */ }
785
+ },
786
+ },
787
+ clock,
788
+ ids: ids_1.newId,
789
+ availability: deps.availability,
790
+ };
791
+ }
792
+ /**
793
+ * The rails launch route's view of Flow (delivery never imports this module).
794
+ * `adopt` and `release` run inside delivery's SQLite transaction on the same
795
+ * project connection, so the ownership transfer is atomic.
796
+ */
797
+ function createFlowHandOffAuthority(repository, clock = exports.systemClock, onChanged, summarize) {
798
+ return {
799
+ resolve(flowId) {
800
+ const session = repository.get(flowId);
801
+ if (!session || session.step !== 'handoff:launch' || !session.worktreePath || !session.branch || !session.headSha || session.ticketId === null) {
802
+ throw new flow_worktree_handoff_1.FlowHandOffNotReadyError('This Flow is not waiting for a rail launch; end it from the Flow bar');
803
+ }
804
+ return {
805
+ flowId,
806
+ ticketId: session.ticketId,
807
+ conversationId: session.conversationId,
808
+ ...(session.repositoryId ? { repositoryId: session.repositoryId } : {}),
809
+ branch: session.branch,
810
+ worktreePath: session.worktreePath,
811
+ headSha: session.headSha,
812
+ baseSha: session.baseSha,
813
+ // A re-derivation updates the Flow's own change in place (null ⇒ named after the spec).
814
+ changeId: (0, domain_1.currentDerivedChange)(session),
815
+ // A summary failure never blocks the hand-off: Core derives from the diff alone.
816
+ summary: (() => { try {
817
+ return summarize?.(session) ?? '';
818
+ }
819
+ catch {
820
+ return '';
821
+ } })(),
822
+ adopt(adoption) {
823
+ const current = repository.get(flowId);
824
+ if (!current)
825
+ throw new flow_worktree_handoff_1.FlowHandOffNotReadyError('The Flow disappeared during the hand-off');
826
+ repository.save((0, domain_1.transition)(current, { type: 'handed-off', railIndex: adoption.railIndex, deliveryId: adoption.deliveryId, headSha: adoption.headSha, now: clock.now() }).session);
827
+ // Announce the hand-off as soon as the delivery's transaction commits,
828
+ // so the hand-off card gives way to the run card that appears with it
829
+ // instead of waiting for the rest of the launch.
830
+ setImmediate(() => {
831
+ // Best effort: the connection may be gone (project closed) by then.
832
+ try {
833
+ const adopted = repository.get(flowId);
834
+ if (adopted?.state === 'handed_off' && adopted.deliveryId === adoption.deliveryId)
835
+ onChanged?.(adopted);
836
+ }
837
+ catch { /* clients rehydrate through GET */ }
838
+ });
839
+ },
840
+ release() {
841
+ const current = repository.get(flowId);
842
+ if (!current)
843
+ return;
844
+ const reverted = (0, domain_1.transition)(current, { type: 'adoption-reverted', now: clock.now() }).session;
845
+ repository.save(reverted);
846
+ onChanged?.(reverted);
847
+ },
848
+ };
849
+ },
850
+ };
851
+ }
852
+ /** The turn of an active Flow with a session (null otherwise). */
853
+ function toFlowTurn(session) {
854
+ if (!session || session.state !== 'active' || session.step !== null || !session.worktreePath || !session.coreSessionId)
855
+ return null;
856
+ return {
857
+ flowId: session.id,
858
+ cwd: session.worktreePath,
859
+ branch: session.branch,
860
+ coreSessionId: session.coreSessionId,
861
+ systemPrompt: (0, agent_flow_prompt_1.buildFlowSystemPrompt)(),
862
+ policy: flow_turn_context_1.FLOW_SESSION_BOUNDARY,
863
+ ...(session.returnBriefing ? { briefing: session.returnBriefing } : {}),
864
+ };
865
+ }
866
+ /**
867
+ * Missions' FlowTurnContext, bound app-wide: a conversation is in Flow while
868
+ * the Flow of its pinned project is `active` with an open session.
869
+ */
870
+ function createFlowTurnContext(deps) {
871
+ return {
872
+ async offerable(conversationId) {
873
+ const projectId = deps.conversationProject(conversationId);
874
+ if (!projectId || !deps.availability)
875
+ return false;
876
+ const service = deps.flowServiceFor(projectId);
877
+ if (!service)
878
+ return false;
879
+ const open = service.getByConversation(conversationId);
880
+ if (open && (open.state === 'active' || open.state === 'paused'))
881
+ return false;
882
+ return (await deps.availability()).available;
883
+ },
884
+ forConversation(conversationId) {
885
+ const projectId = deps.conversationProject(conversationId);
886
+ if (!projectId)
887
+ return null;
888
+ return toFlowTurn(deps.flowServiceFor(projectId)?.getByConversation(conversationId) ?? null);
889
+ },
890
+ async renewSession(conversationId, flowId) {
891
+ const projectId = deps.conversationProject(conversationId);
892
+ const service = projectId ? deps.flowServiceFor(projectId) : null;
893
+ if (!service?.renewSession)
894
+ return null;
895
+ return toFlowTurn(await service.renewSession(flowId));
896
+ },
897
+ async briefingDelivered(conversationId, flowId) {
898
+ const projectId = deps.conversationProject(conversationId);
899
+ if (!projectId)
900
+ return;
901
+ await deps.flowServiceFor(projectId)?.briefingDelivered?.(flowId);
902
+ },
903
+ };
904
+ }
905
+ // ─── Settlement publication (arch section 4.6) ───────────────────────────────
906
+ /** Decisions that mean the delivery reached review (or went beyond it). */
907
+ const DELIVERED_DECISIONS = new Set(['on_review', 'pr_draft', 'pr_ready', 'completed', 'merged']);
908
+ const ARCHIVED_CHANGE = /^openspec\/changes\/archive\/([^/]+)\/(proposal|design)\.md$/;
909
+ const ACTIVE_CHANGE = /^openspec\/changes\/(?!archive\/)([^/]+)\/(proposal|design)\.md$/;
910
+ const TEXT_CAP = 64 * 1024;
911
+ /**
912
+ * The bounded summary of a Flow conversation: the person's messages since the
913
+ * Flow started (automatic briefings excluded), the first line of each final
914
+ * agent reply and the recorded decisions. Message times (SQLite) and Flow times
915
+ * (ISO) are compared as instants, never as strings.
916
+ */
917
+ function flowConversationSummary(desktopDb, input) {
918
+ const messages = (0, agent_store_1.listAgentMessages)(desktopDb, input.conversationId)
919
+ .filter((message) => (0, domain_1.inFlowWindow)(message.created_at, input.from, input.to))
920
+ .map((message) => ({
921
+ role: message.role,
922
+ content: message.content,
923
+ ...(message.context_refs.some((ref) => ref.kind === agent_failure_briefing_1.FAILURE_BRIEFING_REF_KIND) ? { automated: true } : {}),
924
+ }));
925
+ return (0, domain_1.buildFlowSummary)({ idea: input.idea, messages });
926
+ }
927
+ /** Strip OpenSpec's `YYYY-MM-DD-` archive prefix. */
928
+ function changeNameFromArchive(directory) {
929
+ return directory.replace(/^\d{4}-\d{2}-\d{2}-/, '');
930
+ }
931
+ /**
932
+ * Read the derived OpenSpec change from the delivered commit: the archived
933
+ * (or still active) change directory the run added since the Flow base, its
934
+ * proposal and design, and a bounded diffstat. Pure Git reads; never mutates.
935
+ */
936
+ async function readDerivedChange(git, repo, input) {
937
+ const base = input.baseSha ?? `${input.ref}~1`;
938
+ const added = await git.run(['-c', 'core.quotepath=false', 'diff', '--name-only', '--diff-filter=A', base, input.ref, '--', 'openspec/changes'], repo);
939
+ if (added.code !== 0)
940
+ throw new Error(`git diff failed: ${added.stderr.trim() || added.code}`);
941
+ const candidates = added.stdout.split('\n').map((line) => line.trim()).filter(Boolean);
942
+ const directories = new Map();
943
+ for (const file of candidates) {
944
+ const archived = ARCHIVED_CHANGE.exec(file);
945
+ const active = archived ? null : ACTIVE_CHANGE.exec(file);
946
+ const match = archived ?? active;
947
+ if (!match)
948
+ continue;
949
+ const dir = file.slice(0, file.lastIndexOf('/'));
950
+ const entry = directories.get(dir) ?? { name: archived ? changeNameFromArchive(match[1]) : match[1], files: new Map() };
951
+ entry.files.set(match[2], file);
952
+ directories.set(dir, entry);
953
+ }
954
+ const ranked = [...directories.entries()].sort(([a], [b]) => Number(b.includes('/archive/')) - Number(a.includes('/archive/')));
955
+ const chosen = ranked.find(([, entry]) => input.changeName && entry.name === input.changeName) ?? ranked[0];
956
+ const show = async (file) => {
957
+ if (!file)
958
+ return null;
959
+ const result = await git.run(['show', `${input.ref}:${file}`], repo);
960
+ return result.code === 0 ? result.stdout.slice(0, TEXT_CAP) : null;
961
+ };
962
+ const stat = await git.run(['diff', '--stat=120', base, input.ref, '--'], repo);
963
+ return {
964
+ changeName: chosen?.[1].name ?? input.changeName,
965
+ proposal: await show(chosen?.[1].files.get('proposal')),
966
+ design: await show(chosen?.[1].files.get('design')),
967
+ diffstat: stat.code === 0 ? stat.stdout.slice(0, 8000) : null,
968
+ };
969
+ }
970
+ function createFlowPublication(ctx, deps = {}) {
971
+ const git = deps.git ?? worktree_manager_1.defaultGitRunner;
972
+ const ticketFile = () => (0, spec_addenda_1.ticketStorePathForProject)(ctx.project);
973
+ const readTicket = (ticketId) => (0, ticket_store_1.readStore)(ticketFile()).tickets[String(ticketId)];
974
+ return {
975
+ deliveryState(deliveryId) {
976
+ const row = (0, rail_pr_store_1.getPrDelivery)(ctx.db, deliveryId);
977
+ if (!row)
978
+ return null;
979
+ const delivered = DELIVERED_DECISIONS.has(row.decision) && row.implementation_outcome === 'succeeded';
980
+ return { delivered, crashed: !delivered && isCrashedFlowDelivery((0, rail_pr_store_1.toPrDeliverySnapshot)(row)) };
981
+ },
982
+ async derivedChange(input) {
983
+ const row = input.deliveryId ? (0, rail_pr_store_1.getPrDelivery)(ctx.db, input.deliveryId) : undefined;
984
+ let units = [];
985
+ try {
986
+ units = row ? JSON.parse(row.branches) : [];
987
+ }
988
+ catch {
989
+ units = [];
990
+ }
991
+ const unit = units.find((entry) => entry.ticketId === input.ticketId) ?? units[0];
992
+ const ref = unit?.finalSha ?? unit?.branch ?? row?.branch ?? input.branch;
993
+ if (!ref)
994
+ throw new Error('The delivered branch of this Flow is unknown');
995
+ const metadata = readTicket(input.ticketId)?.metadata;
996
+ const changeName = typeof metadata?.openspecChangeName === 'string' ? metadata.openspecChangeName : null;
997
+ // The delivered branch lives in the Flow's repository (the project root for the primary).
998
+ const repo = input.repositoryId ? (0, project_repositories_1.getProjectRepositories)(ctx.project).find((member) => member.id === input.repositoryId)?.path : ctx.project.path;
999
+ if (!repo)
1000
+ throw new Error(`The Flow's repository ${input.repositoryId} is no longer registered`);
1001
+ return readDerivedChange(git, repo, { ref, baseSha: input.baseSha, changeName });
1002
+ },
1003
+ conversationSummary(input) {
1004
+ return flowConversationSummary(ctx.desktopDb, { conversationId: input.conversationId, idea: readTicket(input.ticketId)?.description ?? null, from: input.from, to: input.to });
1005
+ },
1006
+ async rewriteSpec({ ticketId, text }) {
1007
+ const provider = (ctx.project.provider ?? 'claude');
1008
+ const scope = { specrails: false, openspec: false, full: false, mcp: false, contractRefine: true, userMcp: false };
1009
+ if (!(0, spec_generation_1.resolveSpecGenerationToolPolicy)(provider, scope))
1010
+ return { ok: false, error: `Provider ${provider} cannot run spec generation` };
1011
+ const model = (0, project_router_helpers_1.resolveDefaultSpecModel)({ projectPath: ctx.project.path, slug: ctx.project.slug, provider });
1012
+ const outcome = await (deps.generate ?? spec_generation_1.generateSpecFromText)({
1013
+ db: ctx.db,
1014
+ project: ctx.project,
1015
+ ticketStorePath: ticketFile(),
1016
+ ticketWatcher: ctx.ticketWatcher,
1017
+ broadcast: ctx.broadcast,
1018
+ admission: (0, process_admission_1.captureProcessAdmission)(ctx.project.id),
1019
+ }, {
1020
+ text, provider, model, scope, ticketId, surface: 'flow',
1021
+ // Contract Layer always (feedback-2026-10 decision 6.2), awaited so the
1022
+ // Jira issue that follows is born with the complete spec.
1023
+ contractRefine: (0, runtime_1.supportsContractRefine)((0, providers_1.getAdapter)(provider)) ? { model: null, await: true } : null,
1024
+ hooks: {
1025
+ onPersisted: (ticket) => {
1026
+ try {
1027
+ ctx.broadcast({ type: 'ticket_updated', ticket: ticket, projectId: ctx.project.id, timestamp: new Date().toISOString() });
1028
+ }
1029
+ catch { /* clients rehydrate */ }
1030
+ },
1031
+ },
1032
+ });
1033
+ return outcome.ok ? { ok: true } : { ok: false, error: outcome.error };
1034
+ },
1035
+ jira: {
1036
+ connected: () => { try {
1037
+ return ctx.jiraSyncManager.isActive();
1038
+ }
1039
+ catch {
1040
+ return false;
1041
+ } },
1042
+ enqueueCreate: (ticketId, key) => ctx.jiraSyncManager.enqueuePromote(ticketId, key),
1043
+ enqueueUpdate: (ticketId, key) => ctx.jiraSyncManager.enqueueSpecUpdate(ticketId, key),
1044
+ linked: (ticketId) => { try {
1045
+ const link = (0, jira_db_1.getLinkByLocalId)(ctx.db, ticketId);
1046
+ return Boolean(link && !link.tombstoned);
1047
+ }
1048
+ catch {
1049
+ return false;
1050
+ } },
1051
+ enqueueReview: (ticketId, refId) => ctx.jiraSyncManager.onRailReview([ticketId], refId),
1052
+ },
1053
+ };
1054
+ }
1055
+ /** Periodic retry of due settlement effects (backoff lives in the rows). */
1056
+ function startFlowSettlementScheduler(service, intervalMs = 30_000) {
1057
+ let running = false;
1058
+ const timer = setInterval(() => {
1059
+ if (running)
1060
+ return;
1061
+ running = true;
1062
+ void service.runDueSettlements().catch(() => undefined).finally(() => { running = false; });
1063
+ }, intervalMs);
1064
+ timer.unref?.();
1065
+ return { stop: () => clearInterval(timer) };
1066
+ }
1067
+ /** Active OpenSpec changes in the worktree that are neither in the base commit nor already the Flow's. */
1068
+ async function unknownActiveChanges(git, worktreePath, baseSha, known) {
1069
+ let names;
1070
+ try {
1071
+ names = fs.readdirSync(path.join(worktreePath, 'openspec', 'changes'), { withFileTypes: true })
1072
+ .filter((entry) => entry.isDirectory() && entry.name !== 'archive' && (0, domain_1.isOpenSpecChangeId)(entry.name))
1073
+ .map((entry) => entry.name);
1074
+ }
1075
+ catch {
1076
+ return [];
1077
+ }
1078
+ if (!names.length)
1079
+ return [];
1080
+ const baseline = new Set();
1081
+ if (baseSha) {
1082
+ const listed = await git.run(['ls-tree', '-d', '--name-only', `${baseSha}:openspec/changes`], worktreePath).catch(() => null);
1083
+ if (listed?.code === 0)
1084
+ for (const name of listed.stdout.split('\n'))
1085
+ if (name.trim())
1086
+ baseline.add(name.trim());
1087
+ }
1088
+ return names.filter((name) => !baseline.has(name) && !known.includes(name));
1089
+ }