specrails-desktop 2.64.1 → 2.65.0

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 (1117) 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/openspec-shim.js +1 -1
  813. package/server/dist/project-env.js +60 -0
  814. package/server/dist/project-git.js +65 -0
  815. package/server/dist/project-registry.js +264 -27
  816. package/server/dist/project-router-background-processes.js +27 -3
  817. package/server/dist/project-router-git.js +30 -0
  818. package/server/dist/project-router-helpers.js +5 -30
  819. package/server/dist/project-router-jobs.js +49 -1
  820. package/server/dist/project-router-loop-runs.js +72 -2
  821. package/server/dist/project-router-rules.js +54 -0
  822. package/server/dist/project-router-search.js +52 -0
  823. package/server/dist/project-router-settings.js +6 -0
  824. package/server/dist/project-router-setup.js +1 -1
  825. package/server/dist/project-router-spending.js +138 -0
  826. package/server/dist/project-router-tickets.js +246 -427
  827. package/server/dist/project-router.js +7 -0
  828. package/server/dist/providers/claude-adapter.js +25 -3
  829. package/server/dist/providers/codex-adapter.js +9 -1
  830. package/server/dist/providers/gemini-adapter.js +6 -1
  831. package/server/dist/providers/kimi-adapter.js +2 -0
  832. package/server/dist/providers/local-adapter.js +2 -0
  833. package/server/dist/providers/runtime.js +8 -0
  834. package/server/dist/schemas/agent-runtime.schema.json +3 -1
  835. package/server/dist/schemas/workflow-definition.schema.json +1 -0
  836. package/server/dist/setup-manager.js +19 -1
  837. package/server/dist/transient-children.js +25 -8
  838. package/server/dist/update-channel.js +21 -0
  839. package/server/dist/util/search-snippet.js +74 -0
  840. package/server/dist/worktree-manager.js +19 -8
  841. package/client/dist/assets/ActivityFeedPage-Dtp7EyHc.js +0 -1
  842. package/client/dist/assets/AgentBrowserCapture-CLqlEFw8.js +0 -1
  843. package/client/dist/assets/AgentModeAnalyticsPane-B8_hM3Tw.js +0 -2
  844. package/client/dist/assets/AgentModeCodePane-CNF8ZNjE.js +0 -2
  845. package/client/dist/assets/AgentModeJobsPane-CJpJbO9m.js +0 -1
  846. package/client/dist/assets/AgentsPage-BC8XSR79.js +0 -120
  847. package/client/dist/assets/AnalyticsPage-Cdv4jLtW.js +0 -1
  848. package/client/dist/assets/BarChart-BDMqVFJy.js +0 -55
  849. package/client/dist/assets/CodePage-DI1kegAr.js +0 -3
  850. package/client/dist/assets/DesktopAnalyticsPage-Bdp8E8U6.js +0 -1
  851. package/client/dist/assets/DocsDialog-Bm4RS7FX.js +0 -11
  852. package/client/dist/assets/DocsPage-DihYcU8r.js +0 -11
  853. package/client/dist/assets/ExportDropdown-Bb1lHx3r.js +0 -1
  854. package/client/dist/assets/IntegrationsPage-EAipiDWm.js +0 -1
  855. package/client/dist/assets/InteractiveJobComposer-BO6ASN-2.js +0 -19
  856. package/client/dist/assets/JobDetailModal-CuPYq7tP.js +0 -1
  857. package/client/dist/assets/JobDetailPage-BusMjJi9.js +0 -1
  858. package/client/dist/assets/JobsPage-C0QbsF2d.js +0 -1
  859. package/client/dist/assets/LoopBuilderPage-B7TlU4iS.js +0 -1
  860. package/client/dist/assets/LoopPreviewModal-BRWtXOD2.js +0 -1
  861. package/client/dist/assets/LoopsPage-C4q1DmCE.js +0 -2
  862. package/client/dist/assets/MinimizedChatsContext-DHfigjHS.js +0 -1
  863. package/client/dist/assets/PluginsPage-Z1JHSMdR.js +0 -2
  864. package/client/dist/assets/ProjectSettingsDialog-BUNj0tvN.js +0 -1
  865. package/client/dist/assets/RepositoryDeliveries-B4ybHOyB.js +0 -5
  866. package/client/dist/assets/ReviewPacketPage-hwfPNjyy.js +0 -4
  867. package/client/dist/assets/TemplatePreviewModal-V7FpMWuw.js +0 -1
  868. package/client/dist/assets/TicketDetailModalContext-Dkwo2cDs.js +0 -16
  869. package/client/dist/assets/Trans-BbFxRFtR.js +0 -1
  870. package/client/dist/assets/activity-B-rp4h_v.js +0 -1
  871. package/client/dist/assets/activity-C6kJpm9q.js +0 -1
  872. package/client/dist/assets/activity-CGx4kb_j.js +0 -1
  873. package/client/dist/assets/activity-CnoX2bH7.js +0 -1
  874. package/client/dist/assets/activity-DAyekdlt.js +0 -1
  875. package/client/dist/assets/activity-DCxtpT7j.js +0 -1
  876. package/client/dist/assets/activity-DiyjsgQV.js +0 -1
  877. package/client/dist/assets/activity-JzwRaWPD.js +0 -1
  878. package/client/dist/assets/addspec-BOvgmcgk.js +0 -1
  879. package/client/dist/assets/addspec-Clmyfn_R.js +0 -1
  880. package/client/dist/assets/addspec-CsNaBpHp.js +0 -1
  881. package/client/dist/assets/addspec-D2tvWmmV.js +0 -1
  882. package/client/dist/assets/addspec-D3nFwvD0.js +0 -1
  883. package/client/dist/assets/addspec-DVLEhK3w.js +0 -1
  884. package/client/dist/assets/addspec-DXbK-tb0.js +0 -1
  885. package/client/dist/assets/addspec-OHG8DFEn.js +0 -1
  886. package/client/dist/assets/agent-5bSixVzz.js +0 -1
  887. package/client/dist/assets/agent-BR4EHfhq.js +0 -1
  888. package/client/dist/assets/agent-C0IKkJP8.js +0 -1
  889. package/client/dist/assets/agent-C7li9ayC.js +0 -1
  890. package/client/dist/assets/agent-D0dRmEen.js +0 -1
  891. package/client/dist/assets/agent-DZVGHm7H.js +0 -1
  892. package/client/dist/assets/agent-Dip4h2YE.js +0 -1
  893. package/client/dist/assets/agent-Pp-P-n1p.js +0 -1
  894. package/client/dist/assets/agentRuntime-BxF81z52.js +0 -1
  895. package/client/dist/assets/agentRuntime-BxYS5V7u.js +0 -1
  896. package/client/dist/assets/agentRuntime-Dc9HG3BA.js +0 -1
  897. package/client/dist/assets/agents-B6ZsnARo.js +0 -1
  898. package/client/dist/assets/agents-BORdhe0K.js +0 -1
  899. package/client/dist/assets/agents-C6aq9Oqs.js +0 -1
  900. package/client/dist/assets/agents-Cbsc4bcX.js +0 -1
  901. package/client/dist/assets/agents-D0uYR6hq.js +0 -1
  902. package/client/dist/assets/agents-Doe1sHY5.js +0 -1
  903. package/client/dist/assets/agents-DyNi_I9m.js +0 -1
  904. package/client/dist/assets/agents-StKxiTg0.js +0 -1
  905. package/client/dist/assets/agentstudio-7cYCXn-L.js +0 -1
  906. package/client/dist/assets/agentstudio-BHWQh8G3.js +0 -1
  907. package/client/dist/assets/agentstudio-BjnWHyRs.js +0 -1
  908. package/client/dist/assets/agentstudio-BkV8vcK4.js +0 -1
  909. package/client/dist/assets/agentstudio-BzugqB_N.js +0 -1
  910. package/client/dist/assets/agentstudio-CWbp7KvH.js +0 -1
  911. package/client/dist/assets/agentstudio-DG6plf5o.js +0 -1
  912. package/client/dist/assets/agentstudio-DkZVF-Cc.js +0 -1
  913. package/client/dist/assets/analytics-B1DIQd4m.js +0 -1
  914. package/client/dist/assets/analytics-BAIZ9vE_.js +0 -1
  915. package/client/dist/assets/analytics-BTqgmgBd.js +0 -1
  916. package/client/dist/assets/analytics-BWynXPEm.js +0 -1
  917. package/client/dist/assets/analytics-DGcUsQ44.js +0 -1
  918. package/client/dist/assets/analytics-GnSnpJ4W.js +0 -1
  919. package/client/dist/assets/analytics-TWgYaoO0.js +0 -1
  920. package/client/dist/assets/analytics-kJy6Tuko.js +0 -1
  921. package/client/dist/assets/atom-one-dark-qiGhVQxg.js +0 -1
  922. package/client/dist/assets/builder-B9gorTnT.js +0 -1
  923. package/client/dist/assets/builder-Bvw5s3Mi.js +0 -1
  924. package/client/dist/assets/builder-CL5l4dU3.js +0 -1
  925. package/client/dist/assets/builder-CVDTVrQX.js +0 -1
  926. package/client/dist/assets/builder-CpS9liE9.js +0 -1
  927. package/client/dist/assets/builder-DNctIL9Q.js +0 -1
  928. package/client/dist/assets/builder-De2NxX6o.js +0 -1
  929. package/client/dist/assets/builder-DeYT7Y-m.js +0 -1
  930. package/client/dist/assets/button-4FS1ZDTp.js +0 -1
  931. package/client/dist/assets/chat-D_I7nU5K.js +0 -1
  932. package/client/dist/assets/chevron-up-6EFqEHBj.js +0 -1
  933. package/client/dist/assets/chunk-OB3PAWPO-B1EMk45A.js +0 -3
  934. package/client/dist/assets/clsx-CjueKrWZ.js +0 -1
  935. package/client/dist/assets/code-B37GRg9C.js +0 -1
  936. package/client/dist/assets/code-BBOEZbf9.js +0 -1
  937. package/client/dist/assets/code-BRm-jcyx.js +0 -1
  938. package/client/dist/assets/code-CF7w62CR.js +0 -1
  939. package/client/dist/assets/code-CLuvJt2r.js +0 -1
  940. package/client/dist/assets/code-D0RCm59f.js +0 -1
  941. package/client/dist/assets/code-DaZ-ZwCT.js +0 -1
  942. package/client/dist/assets/code-iIHkGaCL.js +0 -1
  943. package/client/dist/assets/commands-0XjAftla.js +0 -1
  944. package/client/dist/assets/commands-BAWSYHjQ.js +0 -1
  945. package/client/dist/assets/commands-BBwowgiE.js +0 -1
  946. package/client/dist/assets/commands-BacjIZLN.js +0 -1
  947. package/client/dist/assets/commands-Bs62IAZ3.js +0 -1
  948. package/client/dist/assets/commands-CLPdh-Hh.js +0 -1
  949. package/client/dist/assets/commands-DlbFzgrp.js +0 -1
  950. package/client/dist/assets/commands-LjPSsi5F.js +0 -1
  951. package/client/dist/assets/common-Bdi0qN4S.js +0 -1
  952. package/client/dist/assets/common-Bhb9zN1P.js +0 -1
  953. package/client/dist/assets/common-BykKlZg1.js +0 -1
  954. package/client/dist/assets/common-CvnNNSJA.js +0 -1
  955. package/client/dist/assets/common-D5zk_mqq.js +0 -1
  956. package/client/dist/assets/common-DQNO_al5.js +0 -1
  957. package/client/dist/assets/common-Dax30Vmp.js +0 -1
  958. package/client/dist/assets/common-DkllpVSb.js +0 -1
  959. package/client/dist/assets/core-B3mKBIh5.js +0 -1
  960. package/client/dist/assets/dashboard-B1ndRHuC.js +0 -1
  961. package/client/dist/assets/dashboard-BX7KXiqA.js +0 -1
  962. package/client/dist/assets/dashboard-B_BSNxcN.js +0 -1
  963. package/client/dist/assets/dashboard-CCeFN7-V.js +0 -1
  964. package/client/dist/assets/dashboard-CRl0WtFJ.js +0 -1
  965. package/client/dist/assets/dashboard-XGdQ5mjw.js +0 -1
  966. package/client/dist/assets/dashboard-_oltA6Jd.js +0 -1
  967. package/client/dist/assets/dashboard-bAuf5KVk.js +0 -1
  968. package/client/dist/assets/dialog-DtdR05v1.js +0 -45
  969. package/client/dist/assets/dist-js-CJ_2XX1Y.js +0 -1
  970. package/client/dist/assets/event-Bt7f3wXe.js +0 -1
  971. package/client/dist/assets/explore-BG99VGpL.js +0 -1
  972. package/client/dist/assets/explore-C0TjprJW.js +0 -1
  973. package/client/dist/assets/explore-C2dgEo7q.js +0 -1
  974. package/client/dist/assets/explore-C8NDHbob.js +0 -1
  975. package/client/dist/assets/explore-CWWgzQGR.js +0 -1
  976. package/client/dist/assets/explore-CcQXpdtS.js +0 -1
  977. package/client/dist/assets/explore-DgBACn39.js +0 -1
  978. package/client/dist/assets/explore-DsXAgnmJ.js +0 -1
  979. package/client/dist/assets/file-text-C0blZHLh.js +0 -1
  980. package/client/dist/assets/formatDistanceToNow-NjPHBLfB.js +0 -1
  981. package/client/dist/assets/getTimezoneOffsetInMilliseconds-vJ7qUoqN.js +0 -1
  982. package/client/dist/assets/git-branch-yf6LE1Bw.js +0 -1
  983. package/client/dist/assets/index-BgbCbIua.css +0 -2
  984. package/client/dist/assets/index-Ce4yZtKf.js +0 -83
  985. package/client/dist/assets/integrations-BkpRUbvp.js +0 -1
  986. package/client/dist/assets/integrations-Bo8qbJf4.js +0 -1
  987. package/client/dist/assets/integrations-CmSrKzZb.js +0 -1
  988. package/client/dist/assets/integrations-DGtq26Rr.js +0 -1
  989. package/client/dist/assets/integrations-De38GFnQ.js +0 -1
  990. package/client/dist/assets/integrations-Dw6zdtb-.js +0 -1
  991. package/client/dist/assets/integrations-Dwl9KQp0.js +0 -1
  992. package/client/dist/assets/integrations-Refg_d2I.js +0 -1
  993. package/client/dist/assets/jira-B6OYw4CJ.js +0 -1
  994. package/client/dist/assets/jira-BTF6RaOe.js +0 -1
  995. package/client/dist/assets/jira-CEetIB2q.js +0 -1
  996. package/client/dist/assets/jira-CIzsZLw5.js +0 -1
  997. package/client/dist/assets/jira-Daw9tmpI.js +0 -1
  998. package/client/dist/assets/jira-FXr7u2lh.js +0 -1
  999. package/client/dist/assets/jira-LaNQn7yl.js +0 -1
  1000. package/client/dist/assets/jira-api-Cabj-H0J.js +0 -1
  1001. package/client/dist/assets/job-time-BCL7wee9.js +0 -1
  1002. package/client/dist/assets/jobs-ARwD85B9.js +0 -1
  1003. package/client/dist/assets/jobs-BMF1w4WT.js +0 -1
  1004. package/client/dist/assets/jobs-CBfzGLwm.js +0 -1
  1005. package/client/dist/assets/jobs-CPjiluBY.js +0 -1
  1006. package/client/dist/assets/jobs-CQQd58pY.js +0 -1
  1007. package/client/dist/assets/jobs-De3EqaO0.js +0 -1
  1008. package/client/dist/assets/jobs-Du9-Ei9a.js +0 -1
  1009. package/client/dist/assets/jobs-qMHbnxwC.js +0 -1
  1010. package/client/dist/assets/layers-BCLTgHXO.js +0 -1
  1011. package/client/dist/assets/loader-circle-BqV9xYGf.js +0 -1
  1012. package/client/dist/assets/loop-layout-CyXj9223.js +0 -7
  1013. package/client/dist/assets/loops-B2PhQLKR.js +0 -1
  1014. package/client/dist/assets/loops-BqbF46st.js +0 -1
  1015. package/client/dist/assets/loops-CINnHbfI.js +0 -1
  1016. package/client/dist/assets/loops-D-3XhH04.js +0 -1
  1017. package/client/dist/assets/loops-DKkEEjZ_.js +0 -1
  1018. package/client/dist/assets/loops-DzWR5-v6.js +0 -1
  1019. package/client/dist/assets/loops-WyWDkhok.js +0 -1
  1020. package/client/dist/assets/loops-scD5fIBf.js +0 -1
  1021. package/client/dist/assets/mcp-6rMoZfEO.js +0 -1
  1022. package/client/dist/assets/mcp-BD8sL5mP.js +0 -1
  1023. package/client/dist/assets/mcp-BkcA3I5s.js +0 -1
  1024. package/client/dist/assets/mcp-CCpSelOh.js +0 -1
  1025. package/client/dist/assets/mcp-CUAN6ORK.js +0 -1
  1026. package/client/dist/assets/mcp-CqbRxRTE.js +0 -1
  1027. package/client/dist/assets/mcp-DP2YfVhO.js +0 -1
  1028. package/client/dist/assets/mcp-DUVQamDz.js +0 -1
  1029. package/client/dist/assets/narration-BEKMVxGm.js +0 -1
  1030. package/client/dist/assets/narration-CjLwGKap.js +0 -1
  1031. package/client/dist/assets/narration-DANWuGsW.js +0 -1
  1032. package/client/dist/assets/narration-DGeEDWiT.js +0 -1
  1033. package/client/dist/assets/narration-DJgpGwIP.js +0 -1
  1034. package/client/dist/assets/narration-DbHnz0qV.js +0 -1
  1035. package/client/dist/assets/narration-bZSsTZG8.js +0 -1
  1036. package/client/dist/assets/narration-i6aKJKEc.js +0 -1
  1037. package/client/dist/assets/nav--u7iPYlS.js +0 -1
  1038. package/client/dist/assets/nav-C5Jgfaby.js +0 -1
  1039. package/client/dist/assets/nav-CAna_Wpt.js +0 -1
  1040. package/client/dist/assets/nav-CCLqeyHo.js +0 -1
  1041. package/client/dist/assets/nav-Cf3c90Jk.js +0 -1
  1042. package/client/dist/assets/nav-DMYQaQjR.js +0 -1
  1043. package/client/dist/assets/nav-Df_PkZ9F.js +0 -1
  1044. package/client/dist/assets/nav-VyNGBJwj.js +0 -1
  1045. package/client/dist/assets/packet-8nn9RsU7.js +0 -1
  1046. package/client/dist/assets/packet-B0H15elv.js +0 -1
  1047. package/client/dist/assets/packet-BQvBgrwh.js +0 -1
  1048. package/client/dist/assets/packet-BR7mO0-a.js +0 -1
  1049. package/client/dist/assets/packet-BgcQ6q_K.js +0 -1
  1050. package/client/dist/assets/packet-D2s92Jnn.js +0 -1
  1051. package/client/dist/assets/packet-YbtcD1HS.js +0 -1
  1052. package/client/dist/assets/packet-c0Qj_9eX.js +0 -1
  1053. package/client/dist/assets/project-repositories-Cnnuj9Ia.js +0 -1
  1054. package/client/dist/assets/rotate-ccw-DalJAQQX.js +0 -1
  1055. package/client/dist/assets/settings-B1NV8Ow9.js +0 -1
  1056. package/client/dist/assets/settings-BQ8XFZeE.js +0 -1
  1057. package/client/dist/assets/settings-BRkxfBbO.js +0 -1
  1058. package/client/dist/assets/settings-C_CcU1dP.js +0 -1
  1059. package/client/dist/assets/settings-Cto9n0eL.js +0 -1
  1060. package/client/dist/assets/settings-Pyw8uYtL.js +0 -1
  1061. package/client/dist/assets/settings-b3HVCNNd.js +0 -1
  1062. package/client/dist/assets/settings-hdive4u6.js +0 -1
  1063. package/client/dist/assets/setup-Be485n2u.js +0 -1
  1064. package/client/dist/assets/setup-CKGUxKr-.js +0 -1
  1065. package/client/dist/assets/setup-Ck1Uwd7_.js +0 -1
  1066. package/client/dist/assets/setup-Cm774a6v.js +0 -1
  1067. package/client/dist/assets/setup-DIqMQpxt.js +0 -1
  1068. package/client/dist/assets/setup-DfCsoNFL.js +0 -1
  1069. package/client/dist/assets/setup-DkeE8mP0.js +0 -1
  1070. package/client/dist/assets/setup-xVntVaz1.js +0 -1
  1071. package/client/dist/assets/specs-Bqvtz2kz.js +0 -1
  1072. package/client/dist/assets/specs-CKes-kz6.js +0 -1
  1073. package/client/dist/assets/specs-CfXxPDNB.js +0 -1
  1074. package/client/dist/assets/specs-CyF9HuTI.js +0 -1
  1075. package/client/dist/assets/specs-DMj035Mt.js +0 -1
  1076. package/client/dist/assets/specs-DfIdoU5L.js +0 -1
  1077. package/client/dist/assets/specs-j5pGLQeU.js +0 -1
  1078. package/client/dist/assets/specs-xW5pkkB7.js +0 -1
  1079. package/client/dist/assets/spending-CQnrWiR3.js +0 -1
  1080. package/client/dist/assets/square-D0JTbRSR.js +0 -1
  1081. package/client/dist/assets/tauri-shell-DE6LfGPw.js +0 -2
  1082. package/client/dist/assets/terminal-BAzpHtpY.js +0 -1
  1083. package/client/dist/assets/terminal-C7dHeR3x.js +0 -1
  1084. package/client/dist/assets/terminal-CMla5Qsz.js +0 -1
  1085. package/client/dist/assets/terminal-CdNXH-n9.js +0 -1
  1086. package/client/dist/assets/terminal-Cw5bZsmV.js +0 -1
  1087. package/client/dist/assets/terminal-DFUP4eNv.js +0 -1
  1088. package/client/dist/assets/terminal-DGqljeK_.js +0 -1
  1089. package/client/dist/assets/terminal-cU70NodO.js +0 -1
  1090. package/client/dist/assets/tickets--tiSOCcn.js +0 -1
  1091. package/client/dist/assets/tickets-BUJ3DMWU.js +0 -1
  1092. package/client/dist/assets/tickets-C1WNPODq.js +0 -1
  1093. package/client/dist/assets/tickets-CDjhWmiE.js +0 -1
  1094. package/client/dist/assets/tickets-CLgPC3uO.js +0 -1
  1095. package/client/dist/assets/tickets-D41ZMQpf.js +0 -1
  1096. package/client/dist/assets/tickets-DEaQC06P.js +0 -1
  1097. package/client/dist/assets/tickets-kcMzbLCp.js +0 -1
  1098. package/client/dist/assets/trash-D8zYUmTg.js +0 -1
  1099. package/client/dist/assets/useDesktop-BjLT0_EE.js +0 -1
  1100. package/client/dist/assets/useRuntimeRuns-C97qEqMg.js +0 -1
  1101. package/client/dist/assets/useSharedWebSocket-Bj4LMp7b.js +0 -2
  1102. package/client/dist/assets/utils-BC4DHlz2.js +0 -1
  1103. package/docs/guide/en/getting-started/4-the-dashboard-tour.md +0 -48
  1104. package/docs/guide/es/getting-started/4-the-dashboard-tour.md +0 -48
  1105. package/server/dist/mobile/mobile-preview-channel.js +0 -179
  1106. package/server/dist/mobile/mobile-preview.js +0 -366
  1107. package/server/dist/modules/browser/domain/preview-origins.js +0 -117
  1108. package/server/dist/modules/browser/runtime/preview-targets.js +0 -80
  1109. /package/client/dist/assets/{atom-one-dark-B-oHczHB.css → DocView-B-oHczHB.css} +0 -0
  1110. /package/docs/guide/de/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1111. /package/docs/guide/en/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1112. /package/docs/guide/es/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1113. /package/docs/guide/fr/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1114. /package/docs/guide/it/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1115. /package/docs/guide/ja/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1116. /package/docs/guide/pt/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
  1117. /package/docs/guide/zh/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
@@ -25,6 +25,29 @@ The CLI and the desktop client read the token automatically. The browser client
25
25
 
26
26
  There is no UI to set or clear the token, and it is not an app setting.
27
27
 
28
+ ## Versioning and deprecation policy
29
+
30
+ Every response under `/api` — desktop routes, project-scoped routes, public routes, auth rejections and 404s — carries the header:
31
+
32
+ ```http
33
+ X-Specrails-Api-Version: 1
34
+ ```
35
+
36
+ The header is set by middleware mounted in `server/index.ts` before any `/api` router (and exposed to allowed CORS origins), so no route can bypass it. `GET /api/health` (public) also returns `apiVersion`, and `GET /api/meta` (authenticated) returns the full version set. The constant lives in `server/api-version.ts`.
37
+
38
+ Rules:
39
+
40
+ 1. **Additive changes keep the version.** New routes, new optional request fields and new response fields are not breaking. Clients must ignore response fields they do not know.
41
+ 2. **`apiVersion` is bumped only on a breaking change**: removing or renaming a route or field, changing a field's type or meaning, tightening validation of an existing request, or changing a WebSocket event contract. A bump is a `feat!`/`fix!` commit with a `BREAKING CHANGE:` footer.
42
+ 3. **Deprecate before removing.** A route or field to be removed is first marked deprecated: it keeps working, the deprecation is recorded in the ledger below and announced in `CHANGELOG.md` under a **Deprecations** heading for the release that ships it (see [CONTRIBUTING](../../CONTRIBUTING.md#api-changes-and-deprecations)).
43
+ 4. **Keep deprecated surface for at least two minor releases.** Something deprecated in `2.65.0` can be removed no earlier than `2.67.0`, and the removal itself is a breaking change under rule 2.
44
+
45
+ Deprecation ledger (newest first):
46
+
47
+ | Route or field | Deprecated in | Earliest removal | Replacement |
48
+ |---|---|---|---|
49
+ | — | — | — | No deprecations yet |
50
+
28
51
  This page is hand-maintained against the route declarations in `server/*-router.ts`, the per-domain `server/project-router-{jobs,spending,settings,terminals,tickets,chat,setup}.ts` family, `server/modules/code/runtime/code-explorer-router.ts`, and `server/jira-router.ts`. If you spot a discrepancy, please file an issue.
29
52
 
30
53
  ---
@@ -33,7 +56,7 @@ This page is hand-maintained against the route declarations in `server/*-router.
33
56
 
34
57
  | Prefix | Router | Auth | Notes |
35
58
  |--------|--------|------|-------|
36
- | `/api/health` | direct | none | Liveness probe (`{ status, version, uptime, projects, mode }`) |
59
+ | `/api/health` | direct | none | Liveness probe (`{ status, version, apiVersion, uptime, projects, mode }`) |
37
60
  | `/api/token` | direct | none | Returns the auth token for local bootstrapping (loopback-only) |
38
61
  | `/api/docs` | `docs-router` | loopback-only (mounted before token auth) | Bundled documentation portal |
39
62
  | `/api/mobile/*` | `mobile-admin-router` | Bearer / X-Desktop-Token + loopback | Mobile Gateway admin (enable/pair/devices) |
@@ -63,8 +86,9 @@ A non-localhost `Origin` header is rejected by the CORS middleware with `403 For
63
86
  | Method | Path | Notes |
64
87
  |--------|------|-------|
65
88
  | `GET` | `/projects` | List registered projects |
66
- | `POST` | `/projects` | Register a project. Body `{ path, name?, provider?, providers? }`. Each provider value is one of `claude`, `codex`, `gemini`, `kimi` (registry-validated). `providers: string[]` enables a multi-provider project (first entry = primary/default); legacy single `provider` still honoured; omit both to default to `["claude"]`. 409 if the path is already registered or Kimi fails its executable/version/Core-target checks. 400 if a provider is unknown, or if a disabled provider is selected: `codex` when `SPECRAILS_CODEX_BETA=0`, `gemini` when `SPECRAILS_GEMINI_BETA=0` (both default-enabled). Kimi has no beta flag: it requires a usable `kimi` CLI ≥ 0.27.0 and a Core build that advertises the Kimi target. Kimi 0.27 has no safe non-billing authentication probe, so login/model configuration is confirmed by the first real turn |
89
+ | `POST` | `/projects` | Register a project. Body `{ path, name?, provider?, providers? }`. Each provider value is one of `claude`, `codex`, `gemini`, `kimi` (registry-validated). `providers: string[]` enables a multi-provider project (first entry = primary/default); legacy single `provider` still honoured; omit both to register with the auto-detected provider set (`["claude"]` when nothing is detected yet). After `201` the workspace is assembled in the background for the detected providers; progress arrives as `project.assemble_progress` WS events. 409 if the path is already registered or Kimi fails its executable/version/Core-target checks. 400 if a provider is unknown, or if a disabled provider is selected: `codex` when `SPECRAILS_CODEX_BETA=0`, `gemini` when `SPECRAILS_GEMINI_BETA=0` (both default-enabled). Kimi has no beta flag: it requires a usable `kimi` CLI ≥ 0.27.0 and a Core build that advertises the Kimi target. Kimi 0.27 has no safe non-billing authentication probe, so login/model configuration is confirmed by the first real turn |
67
90
  | `DELETE` | `/projects/:id` | Unregister (does not delete the project directory) |
91
+ | `POST` | `/projects/:id/assemble-retry` | Re-run the background workspace assembly for the providers that failed (every detected provider when none is recorded as failed). `202 { retrying: [...] }`, or `202 { alreadyRunning: true }` while one is running; `409` when no provider is detected; progress via `project.assemble_progress` |
68
92
  | `GET` | `/resolve?path=…` | Find a project by **exact** canonical filesystem path. No parent-directory walking — a subdirectory returns 404 |
69
93
 
70
94
  Example — register a project that uses both Claude and Gemini:
@@ -85,18 +109,23 @@ Example — register a project that uses both Claude and Gemini:
85
109
  |--------|------|-------|
86
110
  | `GET` | `/state` | `{ projects, projectCount, …todayStats }` (today's cross-project cost/run aggregates spread into the response) |
87
111
  | `GET` | `/cli-status` | Detected AI CLI provider + version (`{ provider, version }`), e.g. `claude`, `codex`, `gemini`, or `kimi` — runs the registered adapter's version probe. Registry-driven |
88
- | `GET` | `/available-providers` | Provider catalogue used by the setup wizard. Registry-driven map (`{ claude, codex, gemini, kimi, tiers, providerIssues, launchDescriptors }`) reporting which CLIs are usable. Codex/Gemini are surfaced unless forced off by `SPECRAILS_CODEX_BETA=0` / `SPECRAILS_GEMINI_BETA=0` (both enabled by default). Kimi is reported unavailable, with a machine-readable `providerIssues.kimi`, when the CLI is missing/unusable, is older than 0.27.0, or the installed Core lacks the Kimi target. The bounded readiness probe is intentionally non-billing and cannot prove account authentication; a login/configuration problem is surfaced by the first model turn. `launchDescriptors` exposes each external CLI command; the app does not bundle a Kimi daemon/server |
112
+ | `GET` | `/available-providers` | Provider catalogue used by the Add Project dialog (no-provider warning), mission and provider pickers. Registry-driven map (`{ claude, codex, gemini, kimi, tiers, providerIssues, launchDescriptors }`) reporting which CLIs are usable. Codex/Gemini are surfaced unless forced off by `SPECRAILS_CODEX_BETA=0` / `SPECRAILS_GEMINI_BETA=0` (both enabled by default). Kimi is reported unavailable, with a machine-readable `providerIssues.kimi`, when the CLI is missing/unusable, is older than 0.27.0, or the installed Core lacks the Kimi target. The bounded readiness probe is intentionally non-billing and cannot prove account authentication; a login/configuration problem is surfaced by the first model turn. `launchDescriptors` exposes each external CLI command; the app does not bundle a Kimi daemon/server |
113
+ | `GET` | `/meta` | Versions a client negotiates with: `{ apiVersion, appVersion, coreVersion, contractSchemaVersion, channel, updateManifestUrl }`. `coreVersion` is the Core in use (active framework, else the located contract's Core, else the bundled one); `contractSchemaVersion` is the integration contract's `schemaVersion`; unknown values are `null`. `channel` is the update channel (`latest` or `stable`) and `updateManifestUrl` the Tauri updater manifest it reads |
89
114
  | `GET` | `/core-compat` | specrails-core version compatibility probe |
115
+ | `GET` | `/core-update/status` | Core update status without network access. Includes `channel`, `resolvedDistTag` (`latest`/`stable`/`null`) and `channelFallback` (`true` when `stable` was requested but Core has no `stable` dist-tag, so `latest` was used). A version cached for another channel is never offered |
116
+ | `POST` | `/core-update/check` | Resolve the channel's npm dist-tag (`stable` → `stable`, falling back to `latest` only on a 404 for the tag) and return the refreshed status |
117
+ | `POST` | `/core-update/update` | Install the checked version (or `{ version }`). `202`; progress over the `core_update.progress` WebSocket event |
90
118
  | `GET` | `/setup-prerequisites` | Tool checks (`node`/`npm`/`npx`/`git`, optionally `uv`). Add `?diagnostic=1` to nest a `diagnostic` object: `{ pathSegments, pathSources, loginShellStatus, whichResults, nodeEnv, platform }` |
91
119
 
92
120
  ### Settings, budget, theme
93
121
 
94
122
  | Method | Path | Notes |
95
123
  |--------|------|-------|
96
- | `GET` | `/settings` | App-wide settings, including `allowSubagents` (default `false`) and `subagentRuntime` (default `null`) |
97
- | `PUT` | `/settings` | Update any subset of `{ port?, specrailsTechUrl?, costAlertThresholdUsd?, allowSubagents?, subagentRuntime? }`. `subagentRuntime` is `null` (same as the mission agent) or `{ provider, model, effort: string \| null }` for missions without a project; an invalid value returns `400`. `allowSubagents` is the app-wide "Allow sub-agents" setting for missions without a project. It must be a boolean (otherwise `400` and nothing is written), and a change refreshes the policy of open sessions |
124
+ | `GET` | `/settings` | App-wide settings, including `allowSubagents` (default `true`), `subagentRuntime` (default `null`) and `updateChannel` (`latest` default, or `stable`) |
125
+ | `PUT` | `/settings` | Update any subset of `{ port?, specrailsTechUrl?, costAlertThresholdUsd?, allowSubagents?, subagentRuntime?, updateChannel? }`. `updateChannel` must be `latest` or `stable` (otherwise `400` and nothing is written); it selects the Desktop updater manifest and the Core npm dist-tag. `subagentRuntime` is `null` (same as the mission agent) or `{ provider, model, effort: string \| null }` for missions without a project; an invalid value returns `400`. `allowSubagents` is the app-wide "Allow sub-agents" setting for missions without a project. It must be a boolean (otherwise `400` and nothing is written), and a change refreshes the policy of open sessions |
98
126
  | `GET` | `/budget` | App-wide budget config |
99
- | `PATCH` | `/budget` | Update the app-wide daily budget |
127
+ | `PATCH` | `/budget` | Update the app-wide budgets: `{ desktopDailyBudgetUsd?, desktopWeeklyBudgetUsd?, desktopMonthlyBudgetUsd?, runCapUsd?, costAlertThresholdUsd? }` (`null` clears, a number > 0 sets; a bad weekly / monthly / run value is `400 { error: 'invalid_cap', field }`). `GET /budget` reports the same fields |
128
+ | `GET` | `/budget/caps` | Budget panel read model, app-wide: `{ generatedAt, spend: { day, week, month }, projection, config, caps }`. `spend.<period>` is `{ startsAt, resetsAt, usd, estimatedUsd, byProvider: [{ provider, usd, estimatedUsd, invocations, turns }] }` over the LOCAL period (week starts Monday); `projection` is `{ estimate: true, trailingDays, avgDailyUsd, monthToDateUsd, remainingDays, projectedUsd }` or `null` without a completed day of history; `config` is `{ day, week, month, run }`; `caps` lists the configured app-wide caps `{ scope, period, budgetUsd, spentUsd, exhausted, resetsAt }` |
100
129
  | `GET` | `/theme` | Current UI theme (defaults to `specrails`) |
101
130
  | `PATCH` | `/theme` | Set UI theme. Body `{ theme }`; one of `dracula`, `aurora-light`, `obsidian-dark`, `matrix`, `specrails`. 400 on an unknown value |
102
131
  | `GET` | `/language` | Current UI language; `{ language: null }` when the user never chose one (the client then follows the OS language) |
@@ -113,6 +142,33 @@ Example — register a project that uses both Claude and Gemini:
113
142
  | `GET` | `/analytics?period=&from=&to=` | Cross-project aggregated spending (the Desktop Analytics page; supports a custom `from`/`to` range) |
114
143
  | `GET` | `/recent-jobs?limit=` | Recent jobs across all projects (1–50) |
115
144
 
145
+ ### Failure diagnosis
146
+
147
+ A run that ended `failed`, `blocked` or `stalled` carries one typed record explaining why. It is persisted in `loop_runs.failure_diagnosis` when the run settles (migration 84) and served read-only by:
148
+
149
+ - `GET /api/projects/:projectId/jobs/:id` as `job.failureDiagnosis`;
150
+ - `GET /api/projects/:projectId/loop-runs/:id` as `loopRun.failureDiagnosis` (a delivery card reads its last run's);
151
+ - `GET /api/inbox` as `diagnosis` on failed / blocked items.
152
+
153
+ Shape: `{ kind, confidence, phase, rounds, resetAt, detail, resumablePhase, blocker, source, remedies }`.
154
+ `kind` is `tests_failed`, `provider_limit`, `environment`, `blocked`, `timeout`, `tool_inactivity`, `crash` or `unknown`; `confidence` is `high` or `low` (a low-confidence record is always `unknown`); `source` is `core` (the classification of Core contract 5.8) or `desktop` (derived from the loop's stall reason, the provider-limit signal, Core's fixed blocker sentences or `completion.blocker`); `remedies` are ranked ids from `resume`, `retry`, `edit-spec`, `fix-environment`, `open-logs`. A run finished before the column existed reads as `unknown`/low, and a successful run has none. Module: [`server/modules/recovery`](../../server/modules/recovery/README.md).
155
+
156
+ ### Needs-you inbox (app-wide)
157
+
158
+ | Method | Path | Notes |
159
+ |--------|------|-------|
160
+ | `GET` | `/inbox` | Read-only projection of what waits for the person, across every registered project: `{ items, projects, generatedAt }`. Each item: `id` (`<projectId>:<kind>:<sourceId>`), `projectId`, `projectName`, `kind` (`review` \| `question` \| `failed` \| `blocked` \| `budget` \| `jira`), `title`, `detail`, `at`, `version` (changes when the state changes), `action` (`open-review` \| `open-run` \| `resume-run` \| `retry-jira` \| `raise-cap`), `subjectId` (delivery id, loop-run id, Jira outbox id, or `<scope>:<period>` for a cap), `conversationId`, `diagnosis` (a failed / blocked run's [failure diagnosis](#failure-diagnosis), else `null`; a provider limit or environment problem is listed as `blocked`), and — only on a reached spend cap (`kind: 'budget'`, `action: 'raise-cap'`, id `<projectId>:budget:cap-<scope>-<period>`) — `cap: { scope, period, budgetUsd, spentUsd, resetsAt }`. A delivery or run item also carries `railIndex` (when known) and a delivery item its `decision` (the state a remote PR decision must echo back). An app-wide cap is listed once, under the first project. Newest first, at most 50 per project. Each project is read through its own database and a failing project is skipped; nothing is cached or stored. Snooze and Done are per viewer and never reach the server. Module: [`server/modules/inbox`](../../server/modules/inbox/README.md). |
161
+
162
+ ### Sample project (first run)
163
+
164
+ | Method | Path | Notes |
165
+ |--------|------|-------|
166
+ | `GET` | `/onboarding/sample` | `{ catalog: [{ id, name, specCount }], sample, defaultParentDir, launch }`. `sample` is the created sample (`{ sampleId, projectId, path, specIds }`) or `null`; a record whose project was removed by hand is dropped. `launch` is the pre-validated first-run configuration: `{ ready: true, preset, localPreset, estimate: { minutes: [3, 5], usd: [0.3, 1] }, runCapUsd }` or `{ ready: false, reason: 'no_provider' \| 'not_signed_in', estimate, runCapUsd }`. `preset` is `{ provider, model, local, loopId: 'factory:sdd-quick-openspec', runCapUsd }`: the cheapest priced model of the cheapest ready cloud provider with the per-run soft cap, or a configured local engine (no cap). `localPreset` is the local alternative when both exist. The estimate is a static, labelled envelope, never a quote. `?refresh=1` re-probes the providers first; a failing probe is "not ready", never an error. |
167
+ | `POST` | `/onboarding/sample` | Body `{ sampleId?, locale?, path?, parentDir? }`. Copies the bundled tic-tac-toe repository, runs `git init -b main` plus one commit, installs the three specs (title, summary and description in `locale`, English as fallback) and registers the project (broadcasting `desktop.project_added`, with the usual silent workspace assembly). `201 { reused: false, project, sample }`; a second call returns `200 { reused: true, ... }` and writes nothing. The folder must be strictly inside the home directory (`400 outside_home`); an explicit `path` must not exist (`409 path_exists`); without `path` the first free `<parentDir>/<name>[-N]` is used (default parent `~/Specrails Samples`). `404 unknown_sample`, `500 git_failed` / `write_failed` / `register_failed` (everything created is removed). |
168
+ | `DELETE` | `/onboarding/sample` | `?deleteFolder=1` (or body `{ deleteFolder: true }`) also deletes the folder, only when it is the recorded path, strictly inside home and still a git repository (`409 unsafe_delete` otherwise; the project is not unregistered then). Returns `{ ok, removedProject, deletedFolder }`; `404 not_found` when there is no sample. Module: [`server/modules/onboarding`](../../server/modules/onboarding/README.md). |
169
+
170
+ The first run itself is the ordinary rail launch: the client assigns the first sample spec to a free rail (`PUT /rails/:n/tickets`) and calls `POST /rails/:n/launch` with `{ loopId, aiEngine, model, runCapUsd }` from the preset.
171
+
116
172
  ### Mobile Gateway admin (`/api/mobile/*`)
117
173
 
118
174
  Loopback-only admin surface for the Mobile Gateway (the gateway itself is a separate HTTPS listener that tunnels the web companion's RPC over WebRTC). The wire contract the phone consumes intentionally keeps the legacy `hub.*` names — see the frozen mobile wire-compat note in `CLAUDE.md`.
@@ -127,32 +183,35 @@ Loopback-only admin surface for the Mobile Gateway (the gateway itself is a sepa
127
183
  | `GET` | `/devices` | List paired devices |
128
184
  | `DELETE` | `/devices/:id` | Revoke a paired device |
129
185
  | `POST` | `/cert/rotate` | Rotate the gateway TLS identity (unpairs every device) |
130
- | `GET` | `/previews` | Live Companion app previews (`{ previews: [{ projectId, projectName, sessionId, deviceId, deviceName, url, title, createdAt }] }`) |
131
- | `DELETE` | `/previews/:projectId/:sessionId` | End a device-owned preview from Desktop (`{ ok }`; Desktop sessions are never affected) |
132
-
133
- Revoking a device also ends its previews. The app-level WS event `mobile.previews_changed` (no `projectId`) tells Settings ▸ Mobile to refetch the list.
134
-
135
- #### Companion app preview (gateway `/v1`)
136
186
 
137
- A paired Companion views a project's locally served web app through a device-owned server-side browser session. The routes require the mission grant (all-projects device) and the `appPreview` capability (`GET /v1/capabilities` → `features.appPreview`, true when browser capture is enabled).
187
+ ### Companion inbox decisions (`/v1/inbox*`, paired devices only)
138
188
 
139
- | Method | Path | Notes |
140
- |--------|------|-------|
141
- | `GET` | `/v1/projects/:pid/missions/:cid/preview-targets` | `{ targets: [{ processId, urls }] }`: local URLs announced in the logs of the mission's running background processes |
142
- | `POST` | `/v1/projects/:pid/preview-sessions` | Body `{ missionId, processId, url, viewport? }`; `url` must be announced by that process. `201 { sessionId, channel, url }` |
143
- | `POST` | `/v1/projects/:pid/preview-sessions/:sid/attach` | Re-attach after a reconnect: `{ sessionId, channel }` (a new DataChannel replaces the old one) |
144
- | `POST` | `/v1/projects/:pid/preview-sessions/:sid/navigate` | Body `{ action: goto\|back\|forward\|reload, url? }`; `goto` accepts only paths on announced origins |
145
- | `DELETE` | `/v1/projects/:pid/preview-sessions/:sid` | End the device's own preview |
189
+ The paired companion reads the [Needs-you inbox](#needs-you-inbox-app-wide) and runs a closed set of safe decisions through the Mobile Gateway (`/v1`, device bearer token, same project grant as every other `/v1` route). Each action is forwarded to the route the desktop UI itself uses, addressed to one project, and tier-checked with the MCP permission tiers (Settings ▸ MCP): a tier that is off answers `403 { error: "tier_disabled", tier, action }` and nothing is forwarded. See [companion inbox decisions](companion-inbox-decisions.md).
146
190
 
147
- Errors carry `{ error, code }`. Codes: `preview_unavailable` (404), `preview_target_gone` (404), `preview_session_closed` (404), `preview_url_not_announced` (400), `preview_limit` (429), `preview_requires_webrtc` (409), `preview_failed` (502). Sessions owned by Desktop or by another device are reported as `preview_session_closed`.
191
+ | Method | Path | Tier | Forwards to |
192
+ |--------|------|------|-------------|
193
+ | `GET` | `/v1/inbox` | none (read) | `GET /api/inbox`, narrowed to the device's granted projects; each item gains `companion: { actions: [{ id, tier, enabled }], runId?, sourceId?, railIndex?, expectedDecision? }` |
194
+ | `GET` | `/v1/projects/:pid/inbox/runs/:runId/question` | none (read) | `GET /agent-runtime/runs/:runId`; answers `{ pending, question?, requestedAt? }` |
195
+ | `POST` | `/v1/projects/:pid/inbox/answer` | `write` | body `{ runId, answer }` (1-20000 chars) -> `POST /loop-runs/:runId/resume { answer, interruptId }` (workflow runs) or `POST /agent-runtime/runs/:runId/resume { answer }`; `409 no_pending_question` when nothing waits |
196
+ | `POST` | `/v1/projects/:pid/inbox/resume` | `ai-spawn` | body `{ runId, runCap?: "ignore" \| runCapUsd?: number }` -> `POST /loop-runs/:runId/resume`; the budget `409` body is passed through so the phone can offer Continue / Raise |
197
+ | `POST` | `/v1/projects/:pid/inbox/retry` | `ai-spawn` | body `{ sourceId, railIndex }` (`sourceId` is a delivery id or `run:<id>`) -> `POST /rails/:railIndex/relaunch { sourceId }` |
198
+ | `POST` | `/v1/projects/:pid/inbox/create-pr` | `destructive` (pushes a branch) | body `{ prDeliveryId, expectedDecision: "on_review" }` -> `POST /rails/pr-decision { action: "create-pr" }`; the answer is narrowed to `{ ok, decision, prUrl, prState, detail }` |
199
+ | any | `/v1/projects/:pid/inbox/<anything else>` | n/a | `403 action_not_allowed_for_companion` (merge, discard, publish, force-push, settings, delete stay on Desktop) |
148
200
 
149
- **Channel.** `channel` is the label of an ordered, reliable DataChannel (`preview:<sessionId>`) that Desktop opens on the device's existing WebRTC peer without renegotiation:
201
+ WebSocket: a device subscribed to the `inbox` topic receives a bare `{ type: "inbox.changed", projectId, reason }` when `rail.pr_state`, `rail.job_completed`, `rail.job_stopped`, `job.stuck`, `jira.outbox_changed` or `loop.run_paused|resumed|stopped|completed` fires for a project it may see; the phone re-reads `GET /v1/inbox`.
150
202
 
151
- - **Desktop → Companion, text:** JSON control: `ready` (`{ id, url, title, viewport }`), `nav`, `popup`, `closed` (`{ reason }`) and `nav_rejected`.
152
- - **Desktop → Companion, binary:** JPEG screencast frames in fragments of at most 16 000 bytes. Each fragment starts with an 8-byte big-endian header `u32 frameSeq | u16 index | u16 count`. Render a frame only when all of its fragments have arrived. A newer `frameSeq` discards an incomplete older frame.
153
- - **Companion → Desktop:** JSON `{ type: 'input', event }` (mouse / wheel / key / resize, validated) and `{ type: 'navigate', action, url? }`, rate-limited to 6 000 messages per minute.
203
+ ### Mission app addresses
154
204
 
155
- **Origin policy.** A device session may load a loopback origin only while a running background process of the project announces it. Every other request passes the regular server-side SSRF guard. Device sessions have their own budget: one per device (opening a new one replaces it) and two per project. They never count against Desktop's four sessions.
205
+ A running mission background process (`GET /api/projects/:id/background-processes`,
206
+ its `/:pid/logs` snapshot, the Companion's `/v1/projects/:pid/missions/:cid/processes`
207
+ proxy and every `background_process.*` WS event) carries
208
+ `appUrls: { local: string[], network: string[] }` once its output announces an
209
+ address. `local` opens on the Desktop computer; `network` holds private LAN/VPN
210
+ addresses (RFC 1918, `100.64/10`, `*.local`, or this machine's addresses for a
211
+ `0.0.0.0` bind) that a phone on the same Wi-Fi opens in its own browser. The
212
+ field is derived from the retained logs on read, never persisted, and absent
213
+ once the process stops. A new or changed address is announced as a
214
+ `background_process.updated` event; log lines themselves are not broadcast.
156
215
 
157
216
  ### specrails-tech proxy
158
217
 
@@ -182,6 +241,9 @@ These routes are available when a mission ran in a Core agent session (`SPECRAIL
182
241
  | Method | Path | Notes |
183
242
  |--------|------|-------|
184
243
  | `GET` | `/agent/active-turns` | Reconnect snapshot. Besides `turns`, the response includes `sessions[]`: `{ conversationId, residentPhase, processAlive, liveSubagents, subagents }` for missions with background work. |
244
+ | `DELETE` | `/agent/conversations/:id` | Soft delete: stops the live turn, closes the Core session and hides the mission (`deleted_at`); `{ ok, restorable: true }`. `?permanent=1` removes the row, history and attachments for good (`404` unknown id). Deleted missions are `404` on `GET /agent/conversations/:id` and `/send`, and absent from the list, search and mobile listings |
245
+ | `GET` | `/agent/conversations/trash?projectId=` | Deleted missions pinned to the project (all when omitted), newest deletion first: `{ items: [{ conversation, deletedAt, purgeAt }], retentionDays: 30 }`. Purges missions deleted more than 30 days ago first |
246
+ | `POST` | `/agent/conversations/:id/restore` | Undo a delete; idempotent. `{ ok, conversation }`, `404` when the mission no longer exists |
185
247
  | `GET` | `/agent/conversations/:id` | Includes `session`: `{ residentPhase, processAlive, liveSubagents, subagents }`, or `null` when the mission never ran in Core. |
186
248
  | `GET` | `/agent/conversations/:id/subagents` | `{ subagents, session }`. Each sub-agent has id, parent, kind, agent type, description, phase (`running`/`idle`/`failed`/`stopped`/`killed`/`interrupted`), reason, restarts, launching Core turn, timestamps, usage, tool uses, duration and result summary. Sub-agents Specrails launched on another provider carry `delegated: { driver, model }`; their usage is recorded as separate `subagent` invocations. |
187
249
  | `GET` | `/agent/conversations/:id/subagents/:subagentId/events?after=&limit=` | Paged sub-agent transcript `{ events: [{ seq, channel, delta?, tool?, createdAt }], hasMore }`. `limit` is 1–1000. |
@@ -204,6 +266,8 @@ Background turns also stream `agent_stream`, `agent_tool` and `agent_tool_result
204
266
 
205
267
  `agent_error` may carry `code` and `provider` for failures the client explains in the user's language. One example is `policy_unenforceable`, sent when a provider cannot honour "Allow sub-agents: off".
206
268
 
269
+ Flow mode: `POST /agent/conversations/:id/send` also accepts `deliveryMode: 'interrupt'`, only while the conversation's Flow is active (`409 interrupt_requires_flow` otherwise). In a Flow every mid-turn input reaches Core as `session.send { delivery: 'interrupt' }`, which cuts the running turn and runs the input next; the reply continues the same user turn. A Flow turn on a host without `flowSessions` fails with `agent_error` code `flow_sessions_unavailable` (there is no legacy Flow transport). Flow turns are recorded in `agent_invocations` with `surface: 'flow'`.
270
+
207
271
  ### Webhooks
208
272
 
209
273
  | Method | Path | Notes |
@@ -249,8 +313,10 @@ Example — queue a command on a specific provider:
249
313
  | `GET` | `/issues` | GitHub issues linked to the project |
250
314
  | `GET` | `/jobs` | Job list (`?limit=&offset=&status=`) |
251
315
  | `GET` | `/jobs/export` | CSV/JSON export |
316
+ | `GET` | `/jobs/:runId/audit` | Agent actions of one run (job id or loop run id) as an attachment. `?format=jsonl` (default) or `csv`. Pending batched rows are flushed first; at most 100 000 rows, oldest first; `X-Agent-Actions-Rows` carries the count. `400` invalid format. See [agent actions audit](agent-actions-audit.md) |
317
+ | `GET` | `/agent-actions` | Project-wide agent actions export. `?format=jsonl\|csv&from=&to=` (ISO timestamps, inclusive). `400` for an invalid format, an unparsable timestamp or `from` after `to` |
252
318
  | `GET` | `/jobs/compare` | Compare metrics between two jobs |
253
- | `GET` | `/jobs/:id` | One job. Returns `{ job, events, phaseDefinitions }`; `job` is annotated with `hasTelemetry`, `tickets[]` (resolved from the command, powers the ticket header), `interactiveSettleMode` (`'finalize'` \| `'auto'` \| `null`) and `interactiveAcceptingTurns` (whether a resident session accepts turns right now — a between-steps loop run reports `'auto'`/`false` so the composer can phrase the waiting state) |
319
+ | `GET` | `/jobs/:id` | One job. Returns `{ job, events, phaseDefinitions }`; `job` is annotated with `hasTelemetry`, `tickets[]` (resolved from the command, powers the ticket header), `interactiveSettleMode` (`'finalize'` \| `'auto'` \| `null`) and `interactiveAcceptingTurns` (whether a resident session accepts turns right now — a between-steps loop run reports `'auto'`/`false` so the composer can phrase the waiting state) and `failureDiagnosis` (`null`, or why a failed / stalled / blocked job stopped: see [failure diagnosis](#failure-diagnosis)) |
254
320
  | `DELETE` | `/jobs/:id` | Cancel a running or queued job |
255
321
  | `DELETE` | `/jobs` | Purge completed jobs (optional `{ from, to }` window) |
256
322
  | `PATCH` | `/jobs/:id/priority` | Re-rank a queued job |
@@ -307,6 +373,9 @@ Spending is tracked across six surfaces: `job`, `quick-spec`, `explore-spec`, `a
307
373
  | `GET` | `/invocations` | Paginated raw `ai_invocations` rows |
308
374
  | `GET` | `/tickets/:id/spending-summary` | Per-ticket cross-surface aggregate (powers `TicketSpendingLine`) |
309
375
  | `GET` | `/analytics/export?format=csv\|json&mode=summary\|raw&…` | Multi-section summary CSV/JSON, or raw rows (10 000 cap) |
376
+ | `GET` | `/analytics/decision-times?period=7d\|30d\|90d\|all\|custom&from&to` | Time to decision / merge per delivery: `{ period, from, to, project, byLoop[] }`, each group `{ deliveries, toDecision, toMerge }` with `{ measured, pending, unknown, medianMs, p90Ms }`. Window = `on_review_at` (or `created_at` for legacy rows). `medianMs`/`p90Ms` are `null` when nothing is measurable; unknown is never zero. Repository children are excluded (counted via the group parent). 400 on an invalid period or a custom period without `from`/`to` |
377
+ | `GET` | `/analytics/loop-economics?period=7d\|30d\|90d\|all\|custom&from&to` | Loop economics: `{ period, from, to, sources: { escapedDefects: tracked\|untracked, requirementsDemonstrated: measured\|unavailable, triageAccuracy: unavailable }, project, byLoop[] }`. Each group: `{ hasData, delivered, merged, discarded, superseded, onReview, discardRate, cost: { pricedDeliveries, unpricedDeliveries, incompleteDeliveries, totalUsd, authoritativeUsd, estimatedUsd, avgCostUsd, estimatedShare }, decisionTimes, rounds: { measuredDeliveries, reviewRounds, fixerRounds, reviewPerDelivery, fixerPerDelivery }, escapedDefects, requirementsDemonstrated, triageAccuracy }`; loops add `loopId`, `loopName`. Delivered = parent delivery that reached `on_review` or beyond. Unknown values are `null`, never 0; published saved loops without deliveries appear with `hasData: false`. `escapedDefects` counts tickets whose `metadata.regressionOf` names a delivery in the window (null while no ticket carries a link). `requirementsDemonstrated` is `{ demonstrated, total, deliveries }` summed over the spec traces (Core `specTrace`) in the settle evidence of delivered deliveries, `null` when none carries one. Same period validation as decision-times |
378
+ | `GET` | `/analytics/loop-economics/deliveries?limit=50` | Recent delivered parent deliveries `{ deliveries: [{ id, loopId, loopName, decision, ticketIds, createdAt }] }` (max 200) — source of the ticket "Regression of" picker |
310
379
 
311
380
  Example — the Analytics dashboard payload (abridged):
312
381
 
@@ -328,8 +397,28 @@ provides no authoritative token/USD envelope, so those values remain null.
328
397
 
329
398
  | Method | Path | Notes |
330
399
  |--------|------|-------|
331
- | `GET` | `/budget` | Daily cap + per-job alert |
332
- | `PATCH` | `/budget` | Update |
400
+ | `GET` | `/budget` | Daily / weekly / monthly caps, per-run soft cap and per-job alert: `{ dailyBudgetUsd, weeklyBudgetUsd, monthlyBudgetUsd, runCapUsd, jobCostThresholdUsd, costToday, … }` |
401
+ | `PATCH` | `/budget` | Update `{ dailyBudgetUsd?, weeklyBudgetUsd?, monthlyBudgetUsd?, runCapUsd?, jobCostThresholdUsd? }`. `null` clears; a number > 0 sets; a bad weekly / monthly / run value is `400 { error: 'invalid_cap', field }`. All caps are enforced by the same gate (below) |
402
+ | `GET` | `/budget/caps` | Budget panel read model: `{ generatedAt, spend, projection, config, appConfig, caps }` — see the app-wide `GET /api/budget/caps` for the shapes. `caps` holds every configured cap of this project AND the app-wide ones with the spend the gate counts; `spend.<period>.byProvider` carries `turns` so a subscription provider can show turns instead of dollars. The projection is an estimate (average of the last 14 completed local days × days left in the month + month to date, integer cents), never a billed figure |
403
+ | `GET` | `/budget/what-if?from=<provider:model>&to=<provider:model>&days=30` | What-if pricing over recorded usage. Without `from`/`to`: `{ days, sources, targets, result: null }` (`sources` = models seen in the window with `{ invocations, recordedUsd, priced }`, `targets` = every model the local rate card prices). With both: `result` re-prices each invocation's recorded tokens on both models (`estimateCurrentUsd`, `estimateWhatIfUsd`, `deltaUsd = whatIf − current`, all estimates) and reports `repriced` / `skipped` invocations and `recordedUsd` apart. A model without a rate card yields `noPricing: { side, provider, model }` and null estimates, never a guess. `400 invalid_model_ref` on a malformed ref. Usage is recorded per model, not per profile role |
404
+ | `GET` | `/run-duration-range?loopId=\|command=` | Measured p25/median/p75 of this project's settled runs of a loop or job-command shape (`{ range, minSamples }`); `range` is `null` below 5 samples. Feeds the job story's "Runs like this have taken…" |
405
+ | `GET` | `/launch-forecast?loopId=\|command=&provider=` | Read-only launch forecast: `{ time, cost, minSamples, budget }`. Same samples as `run-duration-range`, narrowed to `provider`. `time` is `{ p25Ms, medianMs, p75Ms, sampleCount }`. `cost` is `{ lowUsd, highUsd, sampleCount }` (cents), built **only** from provider-reported costs (estimated costs and runs without a cost are excluded) and is an estimate, never a billed figure. Each is `null` below the 5-sample floor (render "Not enough history yet"). `factory:implement`/`factory:batch`/`factory:freestyle` read the `/specrails:implement`/`/specrails:freestyle` jobs; any other loop id reads `loop_runs`. `budget` is the tightest configured cap (daily, weekly or monthly; project or app-wide) `{ scope, period?, budgetUsd, spentUsd, exhausted, resetsAt }` (the same figures the launch gate enforces; `period` is absent for the daily budget) or `null`. `400` without `loopId`/`command` or on a malformed `provider` |
406
+
407
+ ### Scoped search (⌘K)
408
+
409
+ The command palette's scopes. Missions (`@`) stay on `GET /api/agents/search`, files (`f:`) on `GET /code/find`
410
+ and docs (`?`) on `GET /api/docs/search`; these two are project-scoped and read only that project's data.
411
+
412
+ | Method | Path | Notes |
413
+ |--------|------|-------|
414
+ | `GET` | `/search/specs` | `?q=` (required, single line, at most 200 characters, `400` otherwise), `?limit=` (default 8, max 30). Folded (case- and diacritics-insensitive) substring scan of the ticket store: title, short summary, description, labels, non-goals, addenda and comments, so it is never behind the file Core also writes. `#12`/`12` also matches by id. Live Flow placeholders are skipped. Returns `{ results: [{ id, title, status, priority, field, snippet }] }`, best field first (`field`: `id` \| `title` \| `summary` \| `label` \| `description` \| `nonGoal` \| `addendum` \| `comment`), then newest. `snippet` is `{ text, ranges: [[start, end], ...] }` (plain text plus character ranges to mark; never HTML) or `null` |
415
+ | `GET` | `/search/jobs` | Same `q`/`limit` rules. FTS5 trigram search (`bm25`, one row per job; queries under 3 characters use a bounded `LIKE` scan) over the job-log index of this project's database (migration 86, `server/db/job-search.ts`): job command, loop name, phase titles and the failure diagnosis kind/detail/host-blocker text. It never indexes events or token streams. Returns `{ results: [{ jobId, command, status, startedAt, field, snippet }] }` (`field`: `command` \| `loop` \| `phase` \| `failure` \| `detail`). `jobId` is also the loop-run id, so the client opens `/jobs/:jobId` |
416
+
417
+ The job-log index (`job_search_docs` + external-content `job_search_fts`) is derived data kept current at job create,
418
+ phase events and settle (`finishJob`, loop-run settle), cleaned on delete/purge, and bounded: 300 characters per
419
+ document, 30 phase documents per job, 30,000 documents per project (the oldest tenth is dropped when over). Migration 86
420
+ creates it and runs the same idempotent backfill (`rebuildJobSearchIndex`, newest 5,000 jobs). An indexing failure never
421
+ fails the write that triggered it.
333
422
 
334
423
  ### Tickets
335
424
 
@@ -337,14 +426,18 @@ provides no authoritative token/USD envelope, so those values remain null.
337
426
  |--------|------|-------|
338
427
  | `GET` | `/tickets` | Filters: `?status=`, `?label=`, `?q=` |
339
428
  | `GET` | `/tickets/:id` | One ticket |
340
- | `POST` | `/tickets` | Create |
341
- | `PATCH` | `/tickets/:id` | Update any subset of fields |
342
- | `DELETE` | `/tickets/:id` | Delete (cascades the draft conversation if it is the last reference) |
429
+ | `POST` | `/tickets` | Create. Optional `nonGoals: string[]` ("Out of scope"; `400 nonGoals must be an array of strings` otherwise) |
430
+ | `PATCH` | `/tickets/:id` | Update any subset of fields. `metadata` merges keys; `metadata.regressionOf` (delivery id string ≤ 200 chars, escaped-defect link) is validated on create/update/commit-draft (400 otherwise) and `null` removes it. `nonGoals` (string array; `[]` or `null` removes the field) is cleaned (list markers, blanks, duplicates; at most 20 items of 300 characters) and never written back to Jira |
431
+ | `DELETE` | `/tickets/:id` | Soft delete: the spec moves to the trash sidecar `<store>.trash.json` (hidden from every list, search and Core read; `{ ok, revision, restorable: true }`, `404` unknown id, repeat deletes are idempotent). A deleted epic orphans its children. Attachments, the Explore draft conversation and the Jira link are kept until the entry is purged or deleted permanently. Broadcasts `ticket_deleted` |
432
+ | `GET` | `/tickets/trash` | Recently deleted specs, newest deletion first: `{ items: [{ ticket, deletedAt, purgeAt }], retentionDays: 30 }`. Purges entries older than 30 days first |
433
+ | `POST` | `/tickets/:id/restore` | Undo a delete: the spec returns under the same id (and re-adopts the children it orphaned). Idempotent (`alreadyLive: true`), `404` when it is in neither the board nor the trash. Broadcasts `ticket_created` |
434
+ | `DELETE` | `/tickets/trash/:id` | Delete permanently: removes the entry plus the cascade a hard delete used to run (attachments, the draft's orphan Explore conversation). `404` when not in the trash |
343
435
  | `POST` | `/tickets/generate-spec` | Quick-mode generation. Body `{ idea, model?, contractRefine?, aiEngine?, attachmentIds?, pendingSpecId?, contextScope? }` (the spec text is `idea`, not `title`). Streams progress over WS |
344
436
  | `POST` | `/tickets/save-as-draft` | Persist an Explore conversation as a draft (idempotent on `conversationId`) |
345
- | `POST` | `/tickets/from-draft` | Commit a draft (flip-in-place) or insert a new ticket |
437
+ | `POST` | `/tickets/from-draft` | Commit a draft (flip-in-place) or insert a new ticket. An explicit `nonGoals` list wins; otherwise a `## Out of Scope` section of the description moves into `nonGoals` |
346
438
  | `POST` | `/tickets/from-prompt` | Create a ticket directly from a prompt |
347
439
  | `POST` | `/tickets/:id/contract-refine` | Retry Contract Refine for an existing ticket. `202` scheduled, `404` unknown ticket, `409` when the effective provider cannot enforce the required tool policy (`contract_refine_unsupported_for_<provider>`; this includes Kimi), the kill switch is active (`feature_disabled_by_env`), or the ticket has no origin conversation. Kimi is rejected before spawn or mutation |
440
+ | `POST` | `/tickets/:id/triage` | Recalculate the [spec triage](spec-triage.md) (forced, even when the inputs hash is unchanged). `200 { triage }` with the stored `metadata.triage` record (`ready`, `unavailable` or `failed`), `400` invalid id, `404` unknown ticket, `409 { error: 'triage_not_applicable', reason }` for a cancelled spec, an epic or a Flow-held spec, `503 triage_unavailable` when the project has no triage service. The record is also broadcast as `ticket_updated` |
348
441
  | `POST` | `/tickets/:id/smash` | SMASH an epic into sub-specs |
349
442
  | `POST` | `/tickets/:id/smash/undo` | Undo a SMASH operation |
350
443
  | `DELETE` | `/tickets/:id/children` | Delete all children of an epic |
@@ -355,6 +448,8 @@ provides no authoritative token/USD envelope, so those values remain null.
355
448
  | `GET` | `/tickets/:ticketId/attachments/:attachmentId` | Download one |
356
449
  | `DELETE` | `/tickets/:ticketId/attachments/:attachmentId` | Delete one |
357
450
  | `DELETE` | `/tickets/:ticketId/attachments` | Delete all |
451
+ | `GET` | `/tickets/:ticketId/timeline` | The spec's lifecycle, a read-model over existing stores (no store of its own). Query: `?kinds=spec_edit,addendum,mission_turn,job,phase,audit,pr_event,review` (comma list, `400` for an unknown kind), `?limit=` (1-200, default 50), `?cursor=` (opaque, from `nextCursor`; `400` when malformed). Returns `{ ticketId, entries, nextCursor, counts, total }`, newest first; `counts` are per kind over the whole timeline so filter chips keep counting. An entry is `{ id, at, kind, event, params, title, summary, actor, tone: neutral\|ok\|failure\|review, provider, costUsd?, costKind?: billed\|estimated, costEstimatedUsd?, turns?, link, url?, count?, items? }`: `event`/`params` are a stable code the client localizes, `title` is the source text (or an English fallback), `link` is `{ place: spec\|mission\|job\|review, id }` for the client to turn into a place URL, `count`/`items` describe a collapsed group (phases per job, agent actions per job, mission turns per conversation). `costKind: estimated` means part of `costUsd` came from the pricing table; a run the provider reported no cost for carries no `costUsd`. Free text is passed through `redactProse`. `400` invalid id, `404` unknown ticket |
452
+ | `GET` | `/tickets/:ticketId/handoff` | The hand-off export: `?format=md\|html\|pr` (default `md`; `pr` is the concise Markdown PR description), `?locale=` (UI language, any of the 8; headings follow it, unknown falls back to `en`), `?planProviders=claude,codex` (providers billed through a plan: shown as turns, never dollars). Returns `{ format, filename, contentType, body, redactions, locale }`. Sections: summary, request, decisions (addenda, clarifications, reviewer verdicts), changes (delivery diff stats from the review packet's Changes read model), verification, cost (billed and estimated apart), open follow-ups (open addenda, unresolved findings). Every string and the finished document go through `redactProse`; `redactions` counts the changed strings. `400` invalid format or id, `404` unknown ticket |
358
453
 
359
454
  ### Chat / Explore
360
455
 
@@ -364,7 +459,7 @@ provides no authoritative token/USD envelope, so those values remain null.
364
459
  | `POST` | `/chat/conversations` | Create. Body `{ kind?, model?, aiEngine? (alias provider), contextScope? }`. `contextScope` is only allowed for `kind=explore` |
365
460
  | `GET` | `/chat/conversations/:id` | One conversation (with messages) |
366
461
  | `PATCH` | `/chat/conversations/:id` | Update metadata (title, contextScope, etc.) |
367
- | `DELETE` | `/chat/conversations/:id` | Delete (clears `origin_conversation_id` on linked draft tickets) |
462
+ | `DELETE` | `/chat/conversations/:id` | Delete (clears `origin_conversation_id` on linked draft tickets). Sidebar/Explore chats keep their hard delete; the soft delete applies to specs and agent missions |
368
463
  | `GET` | `/chat/conversations/:id/messages` | List messages |
369
464
  | `POST` | `/chat/conversations/:id/messages` | Send a turn; streams over WS |
370
465
  | `DELETE` | `/chat/conversations/:id/messages/stream` | Cancel an in-progress turn |
@@ -372,20 +467,20 @@ provides no authoritative token/USD envelope, so those values remain null.
372
467
  | `POST` | `/chat/conversations/:id/minimize` | Park the session (arms the idle-kill timer) |
373
468
  | `POST` | `/chat/conversations/:id/restore` | Cancel the idle-kill timer |
374
469
 
375
- ### Setup wizard
470
+ ### Setup (API / MCP only)
376
471
 
377
- The setup wizard is a three-step flow (Configure / Install / Done). The `enrich/*` and `setup/start`+`setup/message` endpoints back the legacy AI-enriched flow that the app UI does not expose; they remain mounted for forward compatibility.
472
+ The app UI has no setup wizard: adding a project assembles its workspace in the background (see `POST /api/projects` and `POST /api/projects/:id/assemble-retry`). These per-project routes remain mounted for the MCP `specrails_setup` tool and other API callers. The `enrich/*` and `setup/start`+`setup/message` endpoints back the legacy AI-enriched flow.
378
473
 
379
474
  | Method | Path | Notes |
380
475
  |--------|------|-------|
381
476
  | `POST` | `/setup/install-config` | Write `.specrails/install-config.yaml` to the project |
382
- | `POST` | `/setup/install` | Run `npx specrails-core init --from-config <file>` (the pinned core release — currently `specrails-core@^4.12.0` — is resolved by SetupManager, overridable via `SPECRAILS_CORE_BIN`) |
477
+ | `POST` | `/setup/install` | Run `npx specrails-core init --from-config <file>` (the pinned Core range `CORE_PACKAGE_SPEC` from `server/core-package.ts` — currently `specrails-core@^6.0.0` — is resolved by SetupManager, overridable via `SPECRAILS_CORE_BIN`) |
383
478
  | `POST` | `/setup/start` | Legacy setup-chat session start |
384
479
  | `POST` | `/setup/message` | Legacy setup-chat turn |
385
480
  | `POST` | `/enrich/start` | Legacy AI-enrich session start |
386
481
  | `POST` | `/enrich/message` | Legacy AI-enrich turn |
387
482
  | `GET` | `/setup/checkpoints` | Checkpoint state + last log lines |
388
- | `POST` | `/setup/abort` | Abort the wizard |
483
+ | `POST` | `/setup/abort` | Abort the in-progress install |
389
484
 
390
485
  ### Proposals
391
486
 
@@ -460,8 +555,12 @@ Gated by `requireBrowserCaptureEnabled` — returns 404 when the feature is disa
460
555
 
461
556
  | Method | Path | Notes |
462
557
  |--------|------|-------|
463
- | `GET` | `/settings` | Project settings, including `allowSubagents` (default `false`) and `subagentRuntime` (default `null`) |
464
- | `PATCH` | `/settings` | Update. `allowSubagents` must be a boolean; `subagentRuntime` is `null` or `{ provider, model, effort: string \| null }` (strictly validated). A change to either refreshes the sub-agent policy of the project's open agent sessions. A change to `worktreeEnvPassthrough` (names only) re-warms the project's login-shell recovery |
558
+ | `GET` | `/settings` | Project settings, including `allowSubagents` (default `true`), `subagentRuntime` (default `null`), `reviewerFamilySuggestionDismissed` (default `false`), `reviewWipLimit` (default `null` = no limit), `agentAuditRetentionDays` (default `30`), `jiraPostClarifications` (default `false`) and `baselineOnTouch` (default `false`) |
559
+ | `PATCH` | `/settings` | Update. `reviewWipLimit` is an integer from 1 to 100 or `null` (otherwise `400` and nothing is written). `allowSubagents` must be a boolean; `subagentRuntime` is `null` or `{ provider, model, effort: string \| null }` (strictly validated); `reviewerFamilySuggestionDismissed` must be a boolean. A change to either refreshes the sub-agent policy of the project's open agent sessions. A change to `worktreeEnvPassthrough` (names only) re-warms the project's login-shell recovery. `agentAuditRetentionDays` must be an integer between 1 and 3650. `jiraPostClarifications` and `baselineOnTouch` must be booleans (see [existing-project anchoring](existing-project-anchoring.md)) |
560
+ | `GET` | `/core/phase3-capabilities` | `{ architectClarifications, specTrace, baselineOnTouch, rulesInventory }` booleans from the active Core's `runtime api` (all `false` when Core is unavailable). The settings UI gates each switch on its flag |
561
+ | `GET` | `/rules` | Project rules inventory (`.specrails/rules.json`, workspace first, then the repository): `{ supported, running, state: 'missing' }`, `{ ..., state: 'invalid', file, message }` or `{ ..., state: 'ok', file, modifiedAt, inventory: { generatedAt, gates, rules[{ id, index, text, source, status: enforcedBy\|automatable\|humanOnly\|unclassified, enforcedBy, proposedCheck }], counts, classification, dropped } }`. `supported` is Core `rulesInventory: 1`; `running` covers the automatic run after setup too; `lastRun: { trigger: setup\|manual, ok, exitCode, output, at }` (absent until a run in this app session) |
562
+ | `POST` | `/rules/inventory` | Re-run Core's inventory (`specrails-core rules inventory --root <repo> [--artifact-root <dir>]`). `200 { ok: true, exitCode, output, ...read }`, `502` when the command failed (same body with `ok: false`), `409 rules_inventory_unsupported` without the capability, `409 rules_inventory_running` while one runs for the project |
563
+ | `POST` | `/rules/specs` | Body `{ id }` (Core rule id) or `{ index }`: turn an `automatable` rule into a spec (source `rules`, labels `rules`, `automation`, with non-goals). `201 { ticket }`, `400` invalid index or `rule_not_automatable`, `404 rules_missing` / `rule_not_found`, `409 rules_inventory_unsupported` |
465
564
  | `GET` | `/env-passthrough/status` | Value-free resolution status of every configured `worktreeEnvPassthrough` name: `{ loginShellRecovery, timeoutMs, checking, names: [{ name, status, shell, checkedAt, exitCode }] }`. `status` is `inherited`, `recovered`, `not-defined`, `probe-timeout`, `probe-failed`, or `pending` for a name never checked. Probes first only when a missing name has no valid cached result. Never returns values |
466
565
  | `POST` | `/env-passthrough/recheck` | Probe the login shell now (asynchronously, `SPECRAILS_LOGIN_SHELL_TIMEOUT_MS`, default 10 s), then return the same payload as the status route |
467
566
  | `GET` | `/terminal-settings` | Per-project terminal overrides |
@@ -492,18 +591,59 @@ A non-developer-friendly file tree + Monaco viewer with plain-language AI summar
492
591
 
493
592
  ---
494
593
 
594
+ ## `/api/projects/:projectId/flow/*`
595
+
596
+ Flow mode ([guide](flow-mode.md)): build with an agent in an isolated worktree,
597
+ then hand the worktree to a rail. Thin routes over the
598
+ [Flow module](../../server/modules/flow/README.md). Every response carries the
599
+ Flow as `{ id, conversationId, ticketId, state, branch, worktreePath, baseSha,
600
+ headSha, coreSessionId, railIndex, deliveryId, step, createdAt, updatedAt }`;
601
+ `state` is `active` / `paused` / `handed_off` / `delivered` / `discarded` /
602
+ `needs-review` and `step` names an unfinished saga step (`start:*`, `handoff:*`).
603
+
604
+ | Method | Path | Notes |
605
+ |--------|------|-------|
606
+ | `GET` | `/flow/availability` | `{ available, reason, missing[] }`. Available only when Core sessions are usable and Core advertises `flowSessions` and `deriveChange`. |
607
+ | `POST` | `/flow` | Start. Body `{ conversationId, idea, title?, flowId?, repositoryId?, ticketId? }`. With `ticketId` the Flow starts from that EXISTING spec (idea optional): no placeholder; the spec is labelled In Flow and seeds the first turn; `400 invalid_ticket_id` / `spec_not_found`, `409 spec_closed` / `spec_in_flow` / `spec_on_rail` / `spec_running` before anything is written. The mission must be pinned to this project and its provider must have a Core session driver on a host with `flowSessions`. Creates the placeholder spec, reserves the worktree and returns `201 { flow }`. Idempotent by `flowId`. `409 flow_already_open` (with `flowId`) when the conversation has an open Flow; `409 feature_unavailable` (with `missing`) without the capabilities; `409 repository_has_no_commits` when the repository has an unborn HEAD (nothing is created; the placeholder spec is removed; the client offers `POST /api/projects/:projectId/git/initial-commit`, which runs only `git commit --allow-empty -m "Initial commit"` in the primary repository against an empty scratch index (zero files, nothing staged) and answers `201 { sha, repositoryId }`, `409 repository_has_commits`, `409 git_identity_missing` or `409 repository_is_not_git`); `400 conversation_not_pinned` / `idea_required` (without `ticketId`). |
608
+ | `GET` | `/flow/by-conversation/:conversationId` | `{ flow }`: the open Flow, else the latest one, else `null`. |
609
+ | `GET` | `/flow/open` | `{ flows: [{ id, conversationId, state, branch }] }`: the project's conversations in Flow mode (active, paused, needing review) — the mission list's "In Flow" mark. No worktree paths. |
610
+ | `GET` | `/flow/:flowId` | `{ flow }`; `404 flow_not_found`. |
611
+ | `POST` | `/flow/:flowId/pause` | Closes the Flow's Core session (a running Flow turn is stopped); worktree and spec stay. Idempotent. |
612
+ | `POST` | `/flow/:flowId/resume` | Reopens the session lazily on the next turn. `409 flow_worktree_missing` when the worktree disappeared. Idempotent. |
613
+ | `POST` | `/flow/:flowId/discard` | Closes the session, removes the Flow worktree and branch and deletes the placeholder spec. `409 illegal_transition` after a hand-off and for a `needs-review` Flow. Idempotent. |
614
+ | `POST` | `/flow/:flowId/close` | Ends a `needs-review` Flow WITHOUT deleting anything: branch, any surviving worktree and the spec stay; the Flow becomes `closed` (terminal; `discarded` means the worktree and branch were removed), the spec's `metadata.flow.state` becomes `closed` (no "In Flow" label) and the history gets a `left/closed` boundary. `409 illegal_transition` from any other open state. Idempotent. |
615
+ | `POST` | `/flow/:flowId/hand-off` | Body `{ railIndex, loopId?, aiEngine?, model?, reasoning_effort? }`; `loopId` defaults to `factory:flow-spec` (never the rail's default loop). Commits the worktree (HEAD frozen), closes the session, assigns the Flow spec to a free rail and launches it with `flowId`. Returns `202 { flow, loopRunIds, deliveryId }`. A refused launch keeps its status and code (`409 rail_not_empty`, `409 flow_worktree_mismatch`, `409 pr_decision_pending`…) and the Flow returns to `paused`. |
616
+ | `POST` | `/flow/by-delivery/:deliveryId/return` | Back to Flow: the Flow → Spec delivery stopped with requested changes (`implementation_failed` / `review_changes_requested`) gives its adopted worktree back. One delivery-owned transaction removes the `rail_worktrees` row, closes the delivery as `discarded` / `returned_to_flow` and sets the Flow `paused` with the review as its next-turn briefing; then the session reopens (`active`, or `paused` when it cannot open). Returns `{ flow }`. Idempotent by delivery. `404 flow_not_found`; `409 flow_return_not_allowed`, `flow_return_busy`, `flow_return_worktree_mismatch`, `flow_worktree_missing`. |
617
+ | `POST` | `/flow/by-delivery/:deliveryId/relaunch` | The same return, then the ordinary hand-off on the stopped delivery's rail and engine choices: Flow → Spec runs again on the same worktree and re-derives the existing change. Returns `202 { flow, loopRunIds, deliveryId }`; refusals as for `return` and `hand-off`. |
618
+ | `GET` | `/flow/:flowId/diff` | `{ branch, baseSha, headSha, files: [{ path, status, additions, deletions }], totals: { files, additions, deletions } }` — working tree against the Flow base, overlay and `node_modules` excluded. Empty once the Flow is no longer open. |
619
+ | `GET` | `/flow/:flowId/cost` | `{ flowId, costUsd, turns, unpricedTurns, tokensIn, tokensOut }` — provider-billed cost of the Flow's turns only; turns without billed cost are counted in `unpricedTurns`, never estimated. |
620
+
621
+ WebSocket: `flow.state` `{ projectId, conversationId, flowId, flow, timestamp }`
622
+ on every committed state change (project-scoped).
623
+
624
+ The launched `factory:flow-spec` loop exists only on a Core with `deriveChange: 1`
625
+ (`409 engine_unsupported` otherwise; `400 flow_id_required` without `flowId`).
626
+ When its delivery reaches review the Flow settles: spec rewrite, Jira create and
627
+ review transition as durable effects ([settlement](flow-mode.md#settlement)). The
628
+ delivery's review packet carries `derivation` and `flowSettlement`.
629
+
630
+ ---
631
+
495
632
  ## `/api/projects/:projectId/rails/*`
496
633
 
497
634
  | Method | Path | Notes |
498
635
  |--------|------|-------|
499
- | `GET` | `/` | List rails |
636
+ | `GET` | `/` | List rails. Also returns `reviewWip { limit, pending: [{ deliveryId, railIndex, ticketIds, decision, since }], reached }` (the review WIP limit and the deliveries that count against it) |
500
637
  | `PUT` | `/:railIndex/tickets` | Assign tickets to a rail. Body `{ ticketIds: number[], mode?, profileName?, aiEngine? }`. An omitted `mode` keeps the rail's stored mode; `mode` must be `implement` / `freestyle` / `loop` (400 otherwise), with `batch-implement` / `batch` normalized to `implement`. |
501
638
  | `PUT` | `/:railIndex/profile` | Set the rail's default profile |
502
639
  | `PUT` | `/:railIndex/engine` | Set the rail's AI engine override. Body `{ aiEngine }` (string — one of the project's providers — or `null` to clear) |
503
640
  | `PUT` | `/:railIndex/name` | Set the rail's display name. Body `{ name }` (string or `null` to clear back to the default label); 400 if longer than 60 characters |
504
- | `POST` | `/:railIndex/launch` | Launch the rail. Body `{ mode?, loopId?, profileName?, aiEngine?, model?, reasoning_effort?, originConversationId?, originSurface?, interactive? }`. `mode` is `implement` / `freestyle` / `loop` (the removed Batch mode's `batch-implement` / `batch` are accepted as input aliases and normalized to `implement`); a factory `loopId` maps to its canonical rail mode (`factory:batch` resolves to `factory:implement`). `model` and `reasoning_effort` are validated against the effective adapter/model (Kimi effort is K3-only). Kimi + a loop containing a Decider returns a capability error before the first step. Claude alone advertises persistent in-job stdin; `interactive` remains wire-compatible. Returns `202 { jobId, railIndex, mode }`; a missing provider CLI fails before a job starts. |
641
+ | `POST` | `/:railIndex/launch` | Launch the rail. Body `{ mode?, loopId?, profileName?, aiEngine?, model?, reasoning_effort?, originConversationId?, originSurface?, interactive?, flowId? }`. `flowId` (sent by the Flow hand-off, never by the dashboard) adopts that Flow's frozen worktree: the rail must carry exactly the Flow spec (`409 flow_rail_mismatch`), the Flow must be waiting for the launch (`409 flow_handoff_not_ready`), the launch must be isolated (`409 flow_requires_isolation`), relaunch/revision/target PR/follow-up/base options are refused (`400 flow_handoff_incompatible`) and a mount/branch/HEAD discrepancy returns `409 flow_worktree_mismatch`. `loopId: 'factory:flow-spec'` without `flowId` returns `400 flow_id_required`. `runCapUsd` (a number > 0 caps this run's provider-reported cost: it pauses and asks through the budget gate; `0` waives the default; absent keeps the project/app default) is accepted on a fresh launch and stored with the run. `mode` is `implement` / `freestyle` / `loop` (the removed Batch mode's `batch-implement` / `batch` are accepted as input aliases and normalized to `implement`); a factory `loopId` maps to its canonical rail mode (`factory:batch` resolves to `factory:implement`). `model` and `reasoning_effort` are validated against the effective adapter/model (Kimi effort is K3-only). Kimi + a loop containing a Decider returns a capability error before the first step. Claude alone advertises persistent in-job stdin; `interactive` remains wire-compatible. Returns `202 { jobId, railIndex, mode }`; a missing provider CLI fails before a job starts. While the project or app-wide daily budget is exhausted, this route and `/relaunch` return `409 { error: 'daily_budget_exceeded', scope, period?, budgetUsd, spentUsd, resetsAt, detail, action }` and spawn nothing (`period` is `week` / `month` for the longer caps and absent for the daily budget, so the body predating caps is unchanged). `POST /loop-runs` and `POST /loop-runs/:id/resume` return the same body. Resume also continues a `budget_paused` run in place; a run paused at its per-run soft cap answers `409` with `period: 'run'` (`resetsAt: null`) until the resume body carries the person's choice: `{ runCap: 'ignore' }` (continue without the cap) or `{ runCapUsd: n }` (raise it; it must end above what the run spent). `POST /loop-runs` also accepts `runCapUsd` (a number > 0 caps that run, `0` waives the default). When the project's `reviewWipLimit` is reached and the launch would open a new delivery, this route and `/relaunch` return `409 { error: 'review_wip_limit_reached', limit, pending: [{ deliveryId, railIndex, ticketIds, since }], detail, action }` and spawn nothing. Continuations of an existing delivery (`revisionOfDeliveryId`, Relaunch of a recorded delivery, `targetPrNumber`, `followUp`, or a rail that still owns an active delivery) are exempt.A repository that must be worktree-isolated (e.g. a multi-repository launch) but has no commits yet returns `409 { error: 'repository_has_no_commits', detail }` before any delivery row, branch or worktree exists; a single-repository launch without commits keeps the shared-checkout fallback (`isolationUnavailable: 'no-commits'`). |
505
642
  | `POST` | `/:railIndex/stop` | Stop the rail's running job (cancels every job the rail registered) |
506
643
  | `POST` | `/:railIndex/relaunch` | Relaunch a settled source. Body `{ sourceId: deliveryId or 'run:<runId>', originConversationId?, originSurface? }`. Uses its recorded specs and admitted options, restores empty assignments after preflight and atomically replaces an undelivered failed generation. Returns the same `202` launch response. Reused/removed rails, active/stale sources, missing specs/workflow and delivered work needing recovery return actionable errors. Request-side workflow overrides are ignored. |
644
+ | `GET` | `/pr-deliveries/:id/packet[?repositoryId=]` | The plain-language [review packet](review-packet.md) with the pre-resolved Accept ladder. 404 when `SPECRAILS_REVIEW_PACKET=false`. |
645
+ | `GET` | `/pr-deliveries/:id/changes[?repositoryId=&source=]` | Changes tab list (read-only). `{ prDeliveryId, repositoryId, changes }`; `changes` is `{ available: true, source, sources: [{ id: 'delivery' \| 'ticket:<id>', ticketId, branch }], base, head, baseSha, headSha, root, rootKind: 'worktree' \| 'repository', files: [{ path, oldPath, status: added\|modified\|deleted\|renamed\|copied\|typechange, additions, deletions, binary, hash }], truncated, totals, annotations }` or `{ available: false, reason: not_a_repository\|no_branch\|head_missing\|base_missing\|git_failed, sources, annotations }`. The comparison is the delivery head (settled sha, else the branch) against its merge-base with the base branch. `source` picks one unit's branch when there is no assembled branch (`400` on a malformed value). At most 2000 files (`truncated`). `hash` changes whenever the file's diff does (viewed-mark invalidation). `annotations` are reviewer findings (anchored when Core contract 5.9 named a location), review-brief risks and untested files, and follow-up comments; `location` is `null` when the source named no place. |
646
+ | `GET` | `/pr-deliveries/:id/changes/file?path=&full=1[&repositoryId=&source=]` | One file's parsed diff: `{ prDeliveryId, diff: { path, oldPath, status, binary, hunks: [{ header, oldStart, oldLines, newStart, newLines, lines: [{ type: context\|add\|delete, oldNo, newNo, text, noNewline? }] }], truncated, totalLines } }`. Capped at 4000 lines unless `full=1` (60,000). `path` must be a path of the listing (`404 file_not_in_changes`, `400` without it); it is never passed to git as a free pathspec. `409` with the unavailable `reason` when the comparison cannot be made. |
507
647
 
508
648
  ---
509
649
 
@@ -624,8 +764,11 @@ The bundled documentation portal (served by `docs-router`, loopback-only — mou
624
764
  | Method | Path | Notes |
625
765
  |--------|------|-------|
626
766
  | `GET` | `/` | List categories. Top-level `.md` files → a synthetic `guides` category; each subdirectory becomes its own category |
767
+ | `GET` | `/search?q=&lang=` | Search page titles and headings (levels 2–4) in one language, English fallback per page. `{ results: [{ category, categoryName, slug, title, heading, anchor }] }`, titles first, at most 8; `heading`/`anchor` are null on a title match, `anchor` is null for a heading without an explicit anchor. Empty `[]` for a query that is blank or longer than 80 chars |
627
768
  | `GET` | `/:category/:slug` | Fetch one document (`{ title, content, category, slug }`) |
628
769
 
770
+ Headings may carry an explicit, locale-independent anchor, `## Title {#anchor}`. The server removes it from page titles; the client renders it as the heading id (`doc-<anchor>`) and never shows it. In-app "Learn more" hints address a section by `category/slug#anchor` (see [`client/src/features/README.md`](../../client/src/features/README.md#contextual-help-learn-more)).
771
+
629
772
  Source resolution: `~/.specrails/docs/` (user-editable) wins if present; otherwise the bundled `docs/` from the install.
630
773
 
631
774
  ---
@@ -670,8 +813,8 @@ Every project-scoped message includes a `projectId` field. App-level messages ha
670
813
  | Type | Scope | Notes |
671
814
  |------|-------|-------|
672
815
  | `cost_alert` | project | Job exceeded the per-job alert threshold |
673
- | `daily_budget_exceeded` | project | Project daily budget hit; queue paused |
674
- | `desktop_daily_budget_exceeded` | app | App-wide daily budget hit |
816
+ | `daily_budget_exceeded` | project | Project budget hit; queue paused. Carries `period: 'week' \| 'month'` for the weekly / monthly cap (absent = daily) |
817
+ | `desktop_daily_budget_exceeded` | app | App-wide budget hit (same optional `period`) |
675
818
  | `spending.invalidated` | project | Analytics cache should refetch (no payload) |
676
819
 
677
820
  ### Tickets, specs & drafts
@@ -745,7 +888,9 @@ Every project-scoped message includes a `projectId` field. App-level messages ha
745
888
  | `jira.outbox_changed` | project | The durable write-back outbox changed (op enqueued/drained/dead-lettered) |
746
889
  | `jira.degraded` | project | A write-back op was dead-lettered or a path is blocked; sync continues |
747
890
 
748
- ### Setup wizard
891
+ ### Setup (API / MCP install flow)
892
+
893
+ Emitted by the legacy per-project `/setup/*` install flow (MCP `specrails_setup`). Background workspace assembly after `POST /api/projects` reports through the app-level `project.assemble_progress` event instead.
749
894
 
750
895
  | Type | Scope | Notes |
751
896
  |------|-------|-------|