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
@@ -44,14 +44,18 @@ const project_repositories_1 = require("./project-repositories");
44
44
  const ids_1 = require("./ids");
45
45
  const db_1 = require("./db");
46
46
  const providers_1 = require("./providers");
47
+ const non_goals_1 = require("./modules/specs/domain/non-goals");
47
48
  const contract_refine_runner_1 = require("./modules/specs/runtime/contract-refine-runner");
48
49
  const explore_contract_refine_1 = require("./modules/conversations/runtime/explore-contract-refine");
50
+ const ticket_trash_1 = require("./modules/specs/runtime/ticket-trash");
51
+ const ticket_trash_service_1 = require("./modules/specs/runtime/ticket-trash-service");
49
52
  const smash_runner_1 = require("./modules/specs/runtime/smash-runner");
50
53
  const explore_smash_1 = require("./modules/conversations/runtime/explore-smash");
51
54
  const ai_invocations_1 = require("./modules/accounting/runtime/ai-invocations");
52
- const context_scope_1 = require("./modules/conversations/runtime/context-scope");
55
+ const spec_generation_1 = require("./modules/specs/runtime/spec-generation");
53
56
  const result_event_1 = require("./modules/accounting/runtime/result-event");
54
57
  const runtime_1 = require("./providers/runtime");
58
+ const project_env_1 = require("./project-env");
55
59
  const crypto_1 = require("crypto");
56
60
  const spec_models_1 = require("./modules/specs/runtime/spec-models");
57
61
  const provider_selection_1 = require("./provider-selection");
@@ -63,10 +67,12 @@ const transient_children_1 = require("./transient-children");
63
67
  const process_admission_1 = require("./process-admission");
64
68
  const readline_1 = require("readline");
65
69
  const tree_kill_1 = __importDefault(require("tree-kill"));
66
- const workspace_resolution_1 = require("./workspace-resolution");
67
70
  const multer_1 = __importDefault(require("multer"));
71
+ const timeline_http_1 = require("./modules/specs/adapters/timeline-http");
68
72
  const attachment_manager_1 = require("./attachment-manager");
69
73
  const project_router_helpers_1 = require("./project-router-helpers");
74
+ /** The client's Undo window (8 s) plus margin: outbound Jira writes of undoable edits wait this long. */
75
+ const UNDO_WINDOW_HOLD_MS = 10_000;
70
76
  /**
71
77
  * A NULL conversation provider is the intentional single-provider encoding:
72
78
  * it means "use this project's primary provider", never "use Claude".
@@ -174,6 +180,86 @@ function registerTicketsRoutes(deps) {
174
180
  res.status(500).json({ error: 'Failed to read tickets' });
175
181
  }
176
182
  });
183
+ // ─── Recently deleted (soft-deleted specs) ───────────────────────────────────
184
+ // Registered before GET /tickets/:id so `trash` is not read as a ticket id.
185
+ const trashDeps = (req) => {
186
+ const c = ctx(req);
187
+ return {
188
+ ticketStorePath: () => ticketPath(req),
189
+ db: c.db,
190
+ deleteAttachments: (key) => attachment_manager_1.attachmentManager.deleteAll(c.project.slug, key),
191
+ forgetExploreConversation: (conversationId) => {
192
+ c.chatManager?.forgetSpecDraft(conversationId);
193
+ c.chatManager?.forgetExploreLifecycle(conversationId);
194
+ },
195
+ };
196
+ };
197
+ // GET /:projectId/tickets/trash — "Recently deleted" specs (newest first).
198
+ router.get('/:projectId/tickets/trash', async (req, res) => {
199
+ try {
200
+ await (0, ticket_trash_service_1.purgeProjectTrash)(trashDeps(req));
201
+ const items = (0, ticket_trash_1.listTrashedTickets)(ticketPath(req)).map((e) => ({
202
+ ticket: e.ticket,
203
+ deletedAt: e.deleted_at,
204
+ purgeAt: new Date(Date.parse(e.deleted_at) + ticket_trash_1.TRASH_RETENTION_MS).toISOString(),
205
+ }));
206
+ res.json({ items, retentionDays: ticket_trash_1.TRASH_RETENTION_DAYS });
207
+ }
208
+ catch (err) {
209
+ console.error('[project-router] ticket trash list error:', err);
210
+ res.status(500).json({ error: 'Failed to read recently deleted specs' });
211
+ }
212
+ });
213
+ // POST /:projectId/tickets/:id/restore — Undo a delete. Idempotent.
214
+ router.post('/:projectId/tickets/:id/restore', (req, res) => {
215
+ const ticketId = req.params.id;
216
+ if (!/^\d+$/.test(ticketId)) {
217
+ res.status(400).json({ error: 'Invalid ticket ID' });
218
+ return;
219
+ }
220
+ try {
221
+ const result = (0, ticket_trash_1.restoreTicket)(ticketPath(req), Number(ticketId));
222
+ if (!result) {
223
+ res.status(404).json({ error: 'Ticket not found in recently deleted' });
224
+ return;
225
+ }
226
+ const { broadcast, ticketWatcher, project } = ctx(req);
227
+ if (!result.alreadyLive) {
228
+ ticketWatcher.notifyDesktopWrite(result.revision);
229
+ const now = new Date().toISOString();
230
+ broadcast({ type: 'ticket_created', ticket: result.ticket, projectId: project.id, timestamp: now });
231
+ for (const child of result.readoptedChildren) {
232
+ broadcast({ type: 'ticket_updated', ticket: child, projectId: project.id, timestamp: now });
233
+ }
234
+ }
235
+ res.json({ ok: true, ticket: result.ticket, revision: result.revision, alreadyLive: result.alreadyLive });
236
+ }
237
+ catch (err) {
238
+ console.error('[project-router] ticket restore error:', err);
239
+ res.status(500).json({ error: 'Failed to restore ticket' });
240
+ }
241
+ });
242
+ // DELETE /:projectId/tickets/trash/:id — "Delete permanently" (the one confirmed step).
243
+ router.delete('/:projectId/tickets/trash/:id', async (req, res) => {
244
+ const ticketId = req.params.id;
245
+ if (!/^\d+$/.test(ticketId)) {
246
+ res.status(400).json({ error: 'Invalid ticket ID' });
247
+ return;
248
+ }
249
+ try {
250
+ const entry = (0, ticket_trash_1.purgeTrashedTicket)(ticketPath(req), Number(ticketId));
251
+ if (!entry) {
252
+ res.status(404).json({ error: 'Ticket not found in recently deleted' });
253
+ return;
254
+ }
255
+ await (0, ticket_trash_service_1.finalizeTrashedTicket)(trashDeps(req), entry);
256
+ res.json({ ok: true });
257
+ }
258
+ catch (err) {
259
+ console.error('[project-router] ticket permanent delete error:', err);
260
+ res.status(500).json({ error: 'Failed to delete ticket permanently' });
261
+ }
262
+ });
177
263
  // GET /:projectId/tickets/:id — Get single ticket
178
264
  router.get('/:projectId/tickets/:id', (req, res) => {
179
265
  const ticketId = req.params.id;
@@ -244,19 +330,11 @@ function registerTicketsRoutes(deps) {
244
330
  const projectId = project.id;
245
331
  const admission = (0, process_admission_1.captureProcessAdmission)(projectId);
246
332
  const filePath = ticketPath(req);
247
- let hasAttachments = false;
248
- let baseUserPrompt = `Generate a spec for the following idea:\n\n${idea.trim()}`;
249
- let imageFlags = [];
250
- let imagePaths = [];
333
+ let attachments;
251
334
  if (attachmentIds.length > 0 && pendingSpecId) {
252
335
  try {
253
336
  const extracted = await attachment_manager_1.attachmentManager.getClaudeArgs(project.slug, pendingSpecId, attachmentIds);
254
- imageFlags = extracted.imageFlags;
255
- imagePaths = extracted.imagePaths;
256
- if (extracted.textBlocks.length > 0) {
257
- hasAttachments = true;
258
- baseUserPrompt = `${baseUserPrompt}\n\n## Attached Resources\n\n${extracted.textBlocks.join('\n\n')}`;
259
- }
337
+ attachments = { textBlocks: extracted.textBlocks, imageFlags: extracted.imageFlags, imagePaths: extracted.imagePaths };
260
338
  }
261
339
  catch (err) {
262
340
  console.error('[project-router] generate-spec attachment extraction error:', err);
@@ -286,16 +364,12 @@ function registerTicketsRoutes(deps) {
286
364
  // Quick spawns from project.path, so project `.mcp.json` (the `mcp`
287
365
  // toggle) is discovered natively. `userMcp` additionally loads the
288
366
  // developer's user-scope/plugin/connector MCP servers via the claude
289
- // adapter's `loadUserEnv` (see below).
367
+ // adapter's `loadUserEnv`.
290
368
  mcp: typeof rawScope?.mcp === 'boolean' ? rawScope.mcp : false,
291
369
  contractRefine: quickContractRefine,
292
370
  userMcp: typeof rawScope?.userMcp === 'boolean' ? rawScope.userMcp : false,
293
371
  };
294
- const adapter = (0, providers_1.getAdapter)(provider);
295
- const quickToolPolicy = quickScope.full
296
- ? ((0, runtime_1.supportsToolPolicy)(adapter, 'read-only') ? 'read-only' : null)
297
- : (0, runtime_1.pureOutputToolPolicy)(adapter);
298
- if (!quickToolPolicy) {
372
+ if (!(0, spec_generation_1.resolveSpecGenerationToolPolicy)(provider, quickScope)) {
299
373
  res.status(409).json({
300
374
  error: 'provider_tool_policy_unsupported',
301
375
  provider,
@@ -305,269 +379,45 @@ function registerTicketsRoutes(deps) {
305
379
  }
306
380
  // Persist Quick mode Contract Refine choice (per-project last value).
307
381
  (0, db_1.setQuickContractRefineLast)(ctx(req).db, quickContractRefine);
308
- // Relocate-artifacts: tickets read from the workspace when relocated.
309
- const quickSpecRoot = (() => {
310
- const e = (0, workspace_resolution_1.resolveProjectExecution)({ slug: project.slug, path: project.path });
311
- return e.relocated && e.workspaceDir ? e.workspaceDir : project.path;
312
- })();
313
- const specsPrefix = (0, context_scope_1.buildScopedSystemPromptPrefix)(quickScope, project.path, quickSpecRoot);
314
- const codebaseRule = quickScope.full
315
- ? `- You MAY use Read, Grep, and Glob to inspect the project codebase. Bash is not available.`
316
- : hasAttachments
317
- ? `- Do NOT explore the project codebase. The resources inside <user-attachment> blocks below are pre-loaded context the user intentionally provided — read and use them freely.`
318
- : `- Do NOT read any files or explore the codebase. Work purely from the user's description.`;
319
- // The specrails-tickets prefix (when scope.specrails is toggled on)
320
- // dumps every ticket into the prompt as informational context. Without
321
- // an explicit dedup instruction the model treats it as background and
322
- // still proposes a near-duplicate of something already in the backlog.
323
- // Adding the rule here, gated on `quickScope.specrails`, keeps the
324
- // "toggle is the only gate" contract the user asked for.
325
- const dedupRule = quickScope.specrails
326
- ? `- The "Specrails Tickets" section above lists every ticket already in the backlog. Do NOT propose a duplicate or a near-duplicate of any of them. If the user's idea is already covered by an existing ticket, say so in "Problem Statement" and pick a *different* angle / sub-feature / next step that builds on the existing one — do not repeat it.\n`
327
- : '';
328
- const backlogRecommendationRule = quickScope.specrails
329
- ? `- If the user's idea asks for the "next best spec" or a backlog recommendation, use the existing tickets and OpenSpec context to choose one concrete next spec. Do not respond with generic product directions.\n`
330
- : '';
331
- let baseSystemPrompt = `You are a senior product engineer generating a structured spec proposal.\n\n` +
332
- (specsPrefix ? `${specsPrefix}\n\n` : '') +
333
- `RULES:\n` +
334
- `${codebaseRule}\n` +
335
- dedupRule +
336
- backlogRecommendationRule +
337
- `- Do NOT create files, tickets, or issues.\n` +
338
- `- Output ONLY the structured markdown below. No preamble, no explanation.\n\n` +
339
- `REQUIRED FORMAT:\n` +
340
- `## Spec Title\n[Concise, action-oriented title]\n\n` +
341
- `## Labels\n[2-4 short kebab-case tags categorising the spec — comma-separated on one line, e.g. "ui, settings, dark-mode". Lowercase, no spaces inside a tag.]\n\n` +
342
- `## Problem Statement\n[2-3 sentences]\n\n` +
343
- `## Proposed Solution\n[3-5 sentences]\n\n` +
344
- `## Out of Scope\n[Bullet list]\n\n` +
345
- `## Acceptance Criteria\n[Numbered list of testable outcomes]\n\n` +
346
- `## Technical Considerations\n[Bullet list]\n\n` +
347
- `## Estimated Complexity\n[Low/Medium/High/Very High + one sentence justification]\n\n` +
348
- `## Short Summary\n[One or two plain-language sentences, max 120 characters total, that capture the essence of this spec for a dashboard postit. No markdown, no bullets, no headings.]`;
349
- if (hasAttachments)
350
- baseSystemPrompt = `${baseSystemPrompt}\n\n${attachment_manager_1.USER_ATTACHMENT_SYSTEM_NOTE}`;
351
- const selectedIds = res.locals.repositoryIds;
352
- if ((0, project_repositories_1.getProjectRepositories)(project).length > 1) {
353
- baseSystemPrompt += `\n\nThis logical project has one shared backlog across these repositories: ${JSON.stringify((0, project_repositories_1.getProjectRepositories)(project).map(({ id, name, path, isPrimary, kind }) => ({ id, name, path, isPrimary, kind })))}.\nThis spec targets repository IDs: ${JSON.stringify(selectedIds ?? [(0, project_repositories_1.getProjectRepositories)(project).find((repo) => repo.isPrimary).id])}. Describe cross-repository contracts when selected; do not create separate tickets per repository.`;
354
- }
355
- const systemPrompt = baseSystemPrompt;
356
- const userPrompt = baseUserPrompt;
357
- // Generate-spec spawn args are adapter-driven. For Claude the `--tools`
358
- // flag set comes from `toolFlagsForScope(quickScope)` which the adapter
359
- // doesn't model — pass them through `extraArgs` so they slot in after
360
- // the standard COMMON_FLAGS. `imageFlags` (also Claude-only) goes the
361
- // same way. For codex the system prompt folds into the user prompt
362
- // (no --system-prompt flag) and the extra Claude-only flags are ignored
363
- // by the codex adapter (it doesn't read extraArgs that don't apply).
364
- const toolFlags = provider === 'claude' ? (0, context_scope_1.toolFlagsForScope)(quickScope) : { args: [] };
365
- // Full scope grants Read/Grep/Glob. The model spends turns exploring the
366
- // repo before it writes the spec; 6 was too tight (a few tool calls on a
367
- // sparse/empty repo hit error_max_turns → exit 1 → opaque failure). 15
368
- // leaves comfortable headroom while --max-turns still bounds runaway loops.
369
- const claudeMaxTurns = quickScope.full ? 15 : (hasAttachments ? 3 : 1);
370
- const specGenOptions = {
371
- prompt: userPrompt,
372
- systemPrompt,
382
+ // The spec-generation use case owns the provider spawn, parsing, ticket
383
+ // persistence, Contract Layer scheduling and accounting; this route maps
384
+ // its lifecycle onto the spec_gen_* / ticket_created WebSocket contract.
385
+ (0, spec_generation_1.startSpecGeneration)({
386
+ db: ctx(req).db,
387
+ project,
388
+ ticketStorePath: filePath,
389
+ ticketWatcher,
390
+ broadcast: broadcast,
391
+ admission,
392
+ }, {
393
+ text: idea,
394
+ provider,
373
395
  model: resolvedModel,
374
- toolPolicy: quickToolPolicy,
375
- maxTurns: provider === 'claude' ? claudeMaxTurns : undefined,
376
- extraArgs: provider === 'claude' ? [...toolFlags.args, ...imageFlags] : undefined,
377
- // "My approved MCPs" (scope.userMcp) loads the developer's user-scope,
378
- // plugin, and connector MCP servers (claude-only). Quick already spawns
379
- // from project.path so project `.mcp.json` is discovered without a flag.
380
- loadUserEnv: adapter.capabilities.userMcp === true && quickScope.userMcp,
381
- imagePaths: adapter.capabilities.supportsImageInput ? imagePaths : undefined,
382
- };
383
- const args = adapter.buildArgs('spec-gen', specGenOptions);
384
- const binary = adapter.binary;
385
- // Relocate-artifacts gate: spawn from the workspace + SPECRAILS_REPO_DIR when
386
- // relocated, else cwd = project.path + process.env (byte-identical legacy).
387
- const specGenExec = (0, workspace_resolution_1.resolveProjectExecution)({ slug: project.slug, path: project.path });
388
- let specGenEnv = process.env;
389
- if (specGenExec.relocated) {
390
- specGenEnv = { ...process.env, ...specGenExec.env };
391
- if (adapter.id === 'gemini')
392
- specGenEnv = { ...specGenEnv, GEMINI_CLI_TRUST_WORKSPACE: 'true' };
393
- }
394
- // spawnAiCli reroutes multi-line argv values through stdin on Windows;
395
- // POSIX argv path unchanged.
396
- console.log(`[project-router] spec-gen spawn: ${binary} (cwd=${specGenExec.cwd}, requestId=${requestId})`);
397
- const child = (0, cli_prompt_1.spawnAiCli)(binary, args, {
398
- env: (0, runtime_1.buildProviderEnv)(adapter, specGenOptions, specGenEnv),
399
- stdio: ['ignore', 'pipe', 'pipe'],
400
- cwd: specGenExec.cwd,
401
- });
402
- // Register so removeProject()/shutdown() can tree-kill this otherwise-untracked
403
- // fire-and-forget child (auto-unregisters on close/error).
404
- (0, transient_children_1.trackTransientChild)(projectId, child);
405
- // Watchdog: unlike ai-edit, generate-spec keeps no cancellable handle, so a
406
- // hung CLI (network stall, model never emitting a terminating event) would
407
- // otherwise leak this child + its readline for the app's lifetime. Cap is
408
- // generous — the 'full' scope can legitimately run minutes and --max-turns
409
- // bounds turns, not wall-clock. Cleared on close/error.
410
- const GENERATE_SPEC_TIMEOUT_MS = 8 * 60 * 1000;
411
- let specGenWatchdog = setTimeout(() => {
412
- specGenWatchdog = null;
413
- if (child.pid) {
414
- try {
415
- (0, tree_kill_1.default)(child.pid, 'SIGTERM');
416
- }
417
- catch { /* best-effort */ }
418
- }
419
- if (!admission.isCurrent())
420
- return;
421
- broadcast({
422
- type: 'spec_gen_error', projectId, requestId,
423
- error: `Spec generation timed out after ${Math.round(GENERATE_SPEC_TIMEOUT_MS / 1000)}s`,
424
- timestamp: new Date().toISOString(),
425
- });
426
- }, GENERATE_SPEC_TIMEOUT_MS);
427
- if (typeof specGenWatchdog.unref === 'function')
428
- specGenWatchdog.unref();
429
- const clearSpecGenWatchdog = () => {
430
- if (specGenWatchdog) {
431
- clearTimeout(specGenWatchdog);
432
- specGenWatchdog = null;
433
- }
434
- };
435
- // Capture stderr so failures (auth missing, model errors, etc.) surface
436
- // in the server log instead of being swallowed.
437
- let stderrBuf = '';
438
- /* c8 ignore start -- diagnostic-only; fires only when claude writes stderr */
439
- child.stderr?.on('data', (chunk) => {
440
- const s = chunk.toString();
441
- stderrBuf += s;
442
- console.error(`[project-router] spec-gen stderr (${requestId}): ${s.trimEnd()}`);
443
- });
444
- /* c8 ignore stop */
445
- // Without this listener, ENOENT (binary missing on PATH) propagates as
446
- // an unhandled 'error' event and crashes the entire app process.
447
- /* c8 ignore start -- spawn-failure path; exercised manually, not in CI */
448
- child.on('error', (err) => {
449
- clearSpecGenWatchdog();
450
- console.error(`[project-router] spec-gen spawn failed (${binary}): ${err.message}`);
451
- if (!admission.isCurrent())
452
- return;
453
- const errMsg = {
454
- type: 'spec_gen_error', projectId, requestId,
455
- error: `Failed to launch ${binary}: ${err.message}`,
456
- timestamp: new Date().toISOString(),
457
- };
458
- broadcast(errMsg);
459
- });
460
- /* c8 ignore stop */
461
- res.status(202).json({ requestId });
462
- let buffer = '';
463
- let lastResultEvent = null;
464
- // Canonical adapter events feed finaliseInvocationResult on close, giving
465
- // codex a real pricing-table cost estimate (+ estimated flag) and tokens,
466
- // instead of the legacy hardcoded $0. Accumulated ALONGSIDE the existing
467
- // buffer/delta plumbing below — never in place of it.
468
- const adapterEvents = [];
469
- const turnStartedAt = new Date().toISOString();
470
- const stdoutReader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
471
- stdoutReader.on('line', (line) => {
472
- if (!admission.isCurrent())
473
- return;
474
- const eventsForLine = (0, runtime_1.parseStreamEvents)(adapter, line);
475
- adapterEvents.push(...eventsForLine);
476
- let parsed = null;
477
- try {
478
- parsed = JSON.parse(line);
479
- }
480
- catch { /* skip */ }
481
- if (parsed && eventsForLine.some((event) => event.kind === 'result')) {
482
- lastResultEvent = parsed;
483
- }
484
- for (const event of eventsForLine) {
485
- if (event.kind !== 'text-delta' || !event.text)
486
- continue;
487
- buffer += event.text;
488
- const wsMsg = {
489
- type: 'spec_gen_stream', projectId, requestId,
490
- delta: event.text, timestamp: new Date().toISOString(),
491
- };
492
- broadcast(wsMsg);
493
- }
494
- });
495
- child.on('close', async (code) => {
496
- clearSpecGenWatchdog();
497
- if (!admission.isCurrent())
498
- return;
499
- let createdTicketId = null;
500
- // When claude burns its whole --max-turns budget it exits non-zero with
501
- // a result event of subtype:error_max_turns — but it may already have
502
- // emitted a complete spec. Salvage that usable output instead of failing
503
- // the whole request on an exit code.
504
- const resultSubtype = lastResultEvent?.subtype ?? null;
505
- const hasUsableSpec = buffer.trim().length > 0 && /##\s*Spec Title/i.test(buffer);
506
- const salvageMaxTurns = code !== 0 && resultSubtype === 'error_max_turns' && hasUsableSpec;
507
- if ((code === 0 && buffer.trim()) || salvageMaxTurns) {
508
- if (salvageMaxTurns) {
509
- console.warn(`[project-router] spec-gen salvaged partial output after error_max_turns (${requestId}); ` +
510
- `consider raising --max-turns if this recurs`);
511
- }
512
- // Extract title from generated spec
513
- const titleMatch = buffer.match(/##\s*Spec Title\s*\n+(.+)/);
514
- const specTitle = titleMatch ? titleMatch[1].trim() : idea.trim().slice(0, 80);
515
- // Extract complexity for priority mapping
516
- const complexityMatch = buffer.match(/##\s*Estimated Complexity\s*\n+(\w+)/);
517
- const complexity = complexityMatch ? complexityMatch[1].toLowerCase() : 'medium';
518
- const priority = complexity === 'low' ? 'low' : complexity === 'high' || complexity === 'very' ? 'high' : 'medium';
519
- // Extract labels from the `## Labels` section. Comma- or
520
- // newline-separated tags, normalised to lowercase kebab-case.
521
- // `spec-proposal` is always retained as the marker label.
522
- const labelsMatch = buffer.match(/##\s*Labels\s*\n+([^\n]+(?:\n(?!##)[^\n]+)*)/);
523
- const claudeLabels = labelsMatch
524
- ? labelsMatch[1]
525
- .replace(/[\[\]]/g, '')
526
- .split(/[,\n]/)
527
- .map((s) => s.trim().toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''))
528
- .filter((s) => s.length > 0 && s.length <= 32)
529
- .slice(0, 6)
530
- : [];
531
- const finalLabels = Array.from(new Set(['spec-proposal', ...claudeLabels]));
532
- const shortSummary = (0, ticket_store_1.clampShortSummary)((0, project_router_helpers_1.extractShortSummary)(buffer));
533
- const description = (0, project_router_helpers_1.stripSpecMetadataSections)(buffer);
534
- // Create ticket directly
535
- try {
536
- const now = new Date().toISOString();
537
- let created;
538
- const store = (0, ticket_store_1.mutateStore)(filePath, (s) => {
539
- const id = s.next_id++;
540
- const ticket = {
541
- ...repositoryScope(req, res),
542
- id,
543
- title: specTitle,
544
- description,
545
- status: 'todo',
546
- priority: priority,
547
- labels: finalLabels,
548
- assignee: null,
549
- prerequisites: [],
550
- metadata: {},
551
- comments: [],
552
- origin_conversation_id: null,
553
- is_epic: false,
554
- parent_epic_id: null,
555
- execution_order: null,
556
- short_summary: shortSummary,
557
- created_at: now,
558
- updated_at: now,
559
- created_by: 'sr-product-engineer',
560
- source: 'propose-spec',
561
- };
562
- s.tickets[String(id)] = ticket;
563
- created = ticket;
564
- });
565
- ticketWatcher.notifyDesktopWrite(store.revision);
566
- if (created)
567
- createdTicketId = created.id;
396
+ scope: quickScope,
397
+ repositoryIds: res.locals.repositoryIds,
398
+ resolveRepositoryScope: () => repositoryScope(req, res),
399
+ attachments,
400
+ contractRefine: quickContractRefine ? { model: req.body?.model ?? null } : null,
401
+ requestId,
402
+ hooks: {
403
+ onDelta: (delta) => {
404
+ const wsMsg = {
405
+ type: 'spec_gen_stream', projectId, requestId,
406
+ delta, timestamp: new Date().toISOString(),
407
+ };
408
+ broadcast(wsMsg);
409
+ },
410
+ onError: (error) => {
411
+ const msg = {
412
+ type: 'spec_gen_error', projectId, requestId,
413
+ error, timestamp: new Date().toISOString(),
414
+ };
415
+ broadcast(msg);
416
+ },
417
+ onPersisted: async (created) => {
568
418
  // Migrate attachments from pendingSpecId → real ticket id (if any were uploaded).
569
419
  // Must complete BEFORE broadcasting ticket_created so WS listeners see the populated attachments[].
570
- if (pendingSpecId && created) {
420
+ if (pendingSpecId) {
571
421
  try {
572
422
  const migrated = await attachment_manager_1.attachmentManager.renameTicketDir({
573
423
  slug: project.slug,
@@ -583,7 +433,7 @@ function registerTicketsRoutes(deps) {
583
433
  console.error('[project-router] generate-spec attachment migration error:', err);
584
434
  }
585
435
  if (!admission.isCurrent())
586
- return;
436
+ return 'abort';
587
437
  }
588
438
  const ticketMsg = {
589
439
  type: 'ticket_created', ticket: created,
@@ -598,91 +448,10 @@ function registerTicketsRoutes(deps) {
598
448
  // Add Spec → Jira: promote the new ticket to a Jira issue when the
599
449
  // project is Jira-backed (unless the user opted to keep it local).
600
450
  void maybePromoteSpecToJira(ctx(req), created.id, req.body?.createLocal === true, broadcast);
601
- // Quick mode Contract Refine runs on the same selected provider.
602
- if (quickContractRefine && created) {
603
- const refineTicketId = created.id;
604
- const refineTitle = created.title;
605
- const refineDescription = created.description;
606
- const refineModel = req.body?.model ?? null;
607
- process.nextTick(() => {
608
- if (!admission.isCurrent())
609
- return;
610
- void (0, contract_refine_runner_1.runContractRefineForQuick)({
611
- db: ctx(req).db,
612
- projectId: project.id,
613
- projectSlug: project.slug,
614
- projectPath: project.path,
615
- projectName: project.name,
616
- providerId: provider,
617
- broadcast: broadcast,
618
- }, refineTicketId, refineTitle, refineDescription, refineModel).catch((err) => {
619
- console.error('[project-router] runContractRefineForQuick error:', err);
620
- });
621
- });
622
- }
623
- }
624
- catch (err) {
625
- console.error('[project-router] generate-spec ticket creation error:', err);
626
- const errMsg = {
627
- type: 'spec_gen_error', projectId, requestId,
628
- error: 'Failed to create ticket', timestamp: new Date().toISOString(),
629
- };
630
- broadcast(errMsg);
631
- }
632
- }
633
- else {
634
- const reason = code === 0
635
- ? 'Empty response from AI'
636
- : resultSubtype === 'error_max_turns'
637
- ? 'AI hit its turn limit before finishing the spec. Try again, or narrow the idea / turn off full-codebase context.'
638
- : `Process exited with code ${code}`;
639
- console.error(`[project-router] spec-gen failed (${requestId}): ${reason}` +
640
- (stderrBuf.trim() ? `\n stderr: ${stderrBuf.trim()}` : '') +
641
- (buffer.trim() ? `\n stdout-buffer: ${buffer.trim().slice(0, 500)}` : ''));
642
- const msg = {
643
- type: 'spec_gen_error', projectId, requestId,
644
- error: reason,
645
- timestamp: new Date().toISOString(),
646
- };
647
- broadcast(msg);
648
- }
649
- // ai_invocations capture (surface='quick-spec'). Always emit a row, success or fail.
650
- try {
651
- // Adapter-driven finalisation: claude passes its native total_cost_usd
652
- // through untouched; codex (nativeCostUsd:false) gets a pricing-table
653
- // estimate from its captured token usage + estimated=true. This
654
- // replaces the legacy normaliseResultEvent path that hardcoded codex
655
- // cost to $0 and never set the estimated flag.
656
- const { result: normalised, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, adapterEvents, { fallbackModel: resolvedModel });
657
- // extractCodexResult does not surface duration (codex stream carries
658
- // none); stamp wall-clock so the row's duration isn't lost. Claude's
659
- // result event already provides duration_ms, so prefer it.
660
- const wallMs = Date.now() - new Date(turnStartedAt).getTime();
661
- (0, ai_invocations_1.recordInvocation)(ctx(req).db, {
662
- id: (0, crypto_1.randomUUID)(),
663
- project_id: projectId,
664
- provider: adapter.id,
665
- surface: 'quick-spec',
666
- surface_ref_id: requestId,
667
- ticket_id: createdTicketId,
668
- // A ticket was delivered — whether via the clean code===0 path OR the
669
- // error_max_turns salvage path — iff createdTicketId is set. Record
670
- // 'success' for any delivered ticket so success-scoped averages and
671
- // failureRate are not skewed by salvaged runs (LOW-13). Genuine
672
- // failures (no ticket) stay 'failed'.
673
- status: createdTicketId !== null ? 'success' : 'failed',
674
- started_at: turnStartedAt,
675
- finished_at: new Date().toISOString(),
676
- total_cost_usd_estimated: estimated,
677
- ...normalised,
678
- duration_ms: normalised.duration_ms ?? wallMs,
679
- });
680
- broadcast({ type: 'spending.invalidated', projectId });
681
- }
682
- catch (err) {
683
- console.error('[project-router] generate-spec recordInvocation failed:', err);
684
- }
451
+ },
452
+ },
685
453
  });
454
+ res.status(202).json({ requestId });
686
455
  });
687
456
  // POST /:projectId/tickets/save-as-draft — Persist an in-progress Explore session as a draft ticket
688
457
  router.post('/:projectId/tickets/save-as-draft', (req, res) => {
@@ -848,6 +617,11 @@ function registerTicketsRoutes(deps) {
848
617
  .filter((c) => c.length > 0)
849
618
  : [];
850
619
  const priority = (0, ticket_store_1.isValidPriority)(body.priority) ? body.priority : 'medium';
620
+ const draftNonGoals = body.nonGoals === undefined ? null : (0, non_goals_1.validateNonGoals)(body.nonGoals);
621
+ if (draftNonGoals && !draftNonGoals.ok) {
622
+ res.status(400).json({ error: draftNonGoals.error });
623
+ return;
624
+ }
851
625
  // Optional assignee/prerequisites/metadata (same normalization as the
852
626
  // PATCH /tickets/:id route) so an MCP commit_draft is a true one-shot
853
627
  // insert — no follow-up update call needed for these fields.
@@ -858,7 +632,12 @@ function registerTicketsRoutes(deps) {
858
632
  ? body.prerequisites.filter((p) => typeof p === 'number')
859
633
  : [];
860
634
  const hasMetadata = typeof body.metadata === 'object' && body.metadata !== null;
861
- const metadata = hasMetadata ? body.metadata : {};
635
+ const regressionCheck = (0, ticket_store_1.normalizeRegressionOfMetadata)(hasMetadata ? body.metadata : {});
636
+ if (!regressionCheck.ok) {
637
+ res.status(400).json({ error: regressionCheck.error });
638
+ return;
639
+ }
640
+ const metadata = hasMetadata ? regressionCheck.metadata : {};
862
641
  // A supplied conversationId must reference a REAL chat conversation in this
863
642
  // project (an Explore row in chat_conversations). Agent/desktop conversation
864
643
  // ids are NOT valid origins — stamping one would corrupt the ticket's origin
@@ -895,6 +674,13 @@ function registerTicketsRoutes(deps) {
895
674
  if (bodyShortSummary === null) {
896
675
  bodyShortSummary = (0, project_router_helpers_1.deriveFallbackShortSummary)(rawTitle, descriptionForStore);
897
676
  }
677
+ // Non-goals (3.2): an explicit `nonGoals` list wins; otherwise a draft's
678
+ // `## Out of Scope` section moves into the field. Either way the section
679
+ // leaves the description so the ticket shows it once, under it.
680
+ const outOfScope = (0, non_goals_1.extractOutOfScopeSection)(descriptionForStore);
681
+ const nonGoalsForStore = draftNonGoals?.ok ? draftNonGoals.nonGoals : outOfScope.nonGoals;
682
+ if (draftNonGoals?.ok || outOfScope.nonGoals.length > 0)
683
+ descriptionForStore = outOfScope.description;
898
684
  try {
899
685
  const filePath = ticketPath(req);
900
686
  const now = new Date().toISOString();
@@ -930,6 +716,8 @@ function registerTicketsRoutes(deps) {
930
716
  flipTarget.priority = priority;
931
717
  flipTarget.title = rawTitle;
932
718
  flipTarget.description = descriptionForStore;
719
+ if (nonGoalsForStore.length > 0 || draftNonGoals?.ok)
720
+ flipTarget.nonGoals = nonGoalsForStore;
933
721
  if (labels.length > 0)
934
722
  flipTarget.labels = labels;
935
723
  // PATCH-route semantics: apply only when the field was supplied;
@@ -939,8 +727,11 @@ function registerTicketsRoutes(deps) {
939
727
  flipTarget.assignee = assignee;
940
728
  if (hasPrerequisites)
941
729
  flipTarget.prerequisites = prerequisites;
942
- if (hasMetadata)
730
+ if (hasMetadata) {
943
731
  flipTarget.metadata = { ...flipTarget.metadata, ...metadata };
732
+ if (regressionCheck.clear)
733
+ delete flipTarget.metadata.regressionOf;
734
+ }
944
735
  flipTarget.updated_at = now;
945
736
  // Preserve prior short_summary on flip when the model/body omits one;
946
737
  // overwrite only when a non-null value is provided.
@@ -984,6 +775,7 @@ function registerTicketsRoutes(deps) {
984
775
  parent_epic_id: null,
985
776
  execution_order: null,
986
777
  short_summary: bodyShortSummary,
778
+ ...(nonGoalsForStore.length ? { nonGoals: nonGoalsForStore } : {}),
987
779
  created_at: now,
988
780
  updated_at: now,
989
781
  created_by: 'sr-explore-spec',
@@ -1236,6 +1028,41 @@ function registerTicketsRoutes(deps) {
1236
1028
  res.status(500).json({ error: 'Failed to create ticket' });
1237
1029
  }
1238
1030
  });
1031
+ // POST /:projectId/tickets/:id/triage — Recalculate the spec triage
1032
+ // (launch-triage). Forced: runs even when the inputs hash is unchanged. The
1033
+ // record is stored in metadata.triage and announced as ticket_updated.
1034
+ router.post('/:projectId/tickets/:id/triage', async (req, res) => {
1035
+ const ticketId = String(req.params.id ?? '');
1036
+ if (!/^\d+$/.test(ticketId)) {
1037
+ res.status(400).json({ error: 'Invalid ticket ID' });
1038
+ return;
1039
+ }
1040
+ const service = ctx(req).specTriage;
1041
+ if (!service) {
1042
+ res.status(503).json({ error: 'triage_unavailable' });
1043
+ return;
1044
+ }
1045
+ try {
1046
+ const outcome = await service.triageNow(Number(ticketId), { force: true });
1047
+ if (outcome.kind === 'not_found') {
1048
+ res.status(404).json({ error: 'Ticket not found' });
1049
+ return;
1050
+ }
1051
+ if (outcome.kind === 'not_applicable') {
1052
+ res.status(409).json({ error: 'triage_not_applicable', reason: outcome.reason });
1053
+ return;
1054
+ }
1055
+ if (outcome.kind === 'stored' || outcome.kind === 'unchanged') {
1056
+ res.json({ triage: outcome.triage });
1057
+ return;
1058
+ }
1059
+ res.status(503).json({ error: 'triage_unavailable' });
1060
+ }
1061
+ catch (err) {
1062
+ console.error('[project-router] ticket triage error:', err);
1063
+ res.status(500).json({ error: 'Failed to triage ticket' });
1064
+ }
1065
+ });
1239
1066
  // POST /:projectId/tickets/:id/contract-refine — Manually re-fire refine
1240
1067
  router.post('/:projectId/tickets/:id/contract-refine', async (req, res) => {
1241
1068
  const ticketId = Number.parseInt(String(req.params.id ?? ''), 10);
@@ -1478,11 +1305,22 @@ function registerTicketsRoutes(deps) {
1478
1305
  });
1479
1306
  // POST /:projectId/tickets — Create new ticket
1480
1307
  router.post('/:projectId/tickets', (req, res) => {
1481
- const { title, description, status, priority, labels, assignee, prerequisites, metadata, source } = req.body ?? {};
1308
+ const { title, description, status, priority, labels, assignee, prerequisites, metadata: rawMetadata, source, nonGoals: rawNonGoals } = req.body ?? {};
1482
1309
  if (!title || typeof title !== 'string' || !title.trim()) {
1483
1310
  res.status(400).json({ error: 'title is required' });
1484
1311
  return;
1485
1312
  }
1313
+ const createNonGoals = rawNonGoals === undefined ? null : (0, non_goals_1.validateNonGoals)(rawNonGoals);
1314
+ if (createNonGoals && !createNonGoals.ok) {
1315
+ res.status(400).json({ error: createNonGoals.error });
1316
+ return;
1317
+ }
1318
+ const createRegression = (0, ticket_store_1.normalizeRegressionOfMetadata)(typeof rawMetadata === 'object' && rawMetadata !== null ? rawMetadata : {});
1319
+ if (!createRegression.ok) {
1320
+ res.status(400).json({ error: createRegression.error });
1321
+ return;
1322
+ }
1323
+ const metadata = typeof rawMetadata === 'object' && rawMetadata !== null ? createRegression.metadata : undefined;
1486
1324
  if (status !== undefined && !(0, ticket_store_1.isValidStatus)(status)) {
1487
1325
  res.status(400).json({ error: 'status must be one of: draft, todo, in_progress, on_review, done, cancelled' });
1488
1326
  return;
@@ -1517,6 +1355,7 @@ function registerTicketsRoutes(deps) {
1517
1355
  parent_epic_id: null,
1518
1356
  execution_order: null,
1519
1357
  short_summary: null,
1358
+ ...(createNonGoals?.ok && createNonGoals.nonGoals.length ? { nonGoals: createNonGoals.nonGoals } : {}),
1520
1359
  created_at: now,
1521
1360
  updated_at: now,
1522
1361
  created_by: source === 'mcp' ? 'mcp' : 'hub', // 'hub' = legacy on-disk wire value (tickets.json, shared with specrails-core) — do not rename
@@ -1575,6 +1414,8 @@ function registerTicketsRoutes(deps) {
1575
1414
  }
1576
1415
  res.status(409).json({ error: 'addendum_applied', detail: 'an applied addendum is history; reopen it or add a new one' });
1577
1416
  };
1417
+ // GET /:projectId/tickets/:ticketId/timeline and /handoff — the spec lifecycle projection and its export.
1418
+ (0, timeline_http_1.registerSpecTimelineRoutes)(router, { ctx, ticketPath });
1578
1419
  // GET /:projectId/tickets/:id/addenda — list a spec's addenda
1579
1420
  router.get('/:projectId/tickets/:id/addenda', (req, res) => {
1580
1421
  const ticketId = addendaTicketId(req, res);
@@ -1765,11 +1606,22 @@ function registerTicketsRoutes(deps) {
1765
1606
  res.status(400).json({ error: 'Invalid ticket ID' });
1766
1607
  return;
1767
1608
  }
1768
- const { title, description, status, priority, labels, assignee, prerequisites, metadata, acceptanceCriteria, short_summary } = req.body ?? {};
1609
+ const { title, description, status, priority, labels, assignee, prerequisites, metadata: rawMetadata, acceptanceCriteria, short_summary, nonGoals: rawNonGoals } = req.body ?? {};
1610
+ const patchNonGoals = rawNonGoals === undefined ? null : (0, non_goals_1.validateNonGoals)(rawNonGoals);
1611
+ if (patchNonGoals && !patchNonGoals.ok) {
1612
+ res.status(400).json({ error: patchNonGoals.error });
1613
+ return;
1614
+ }
1769
1615
  if (status !== undefined && !(0, ticket_store_1.isValidStatus)(status)) {
1770
1616
  res.status(400).json({ error: 'status must be one of: draft, todo, in_progress, on_review, done, cancelled' });
1771
1617
  return;
1772
1618
  }
1619
+ const patchRegression = (0, ticket_store_1.normalizeRegressionOfMetadata)(typeof rawMetadata === 'object' && rawMetadata !== null ? rawMetadata : {});
1620
+ if (!patchRegression.ok) {
1621
+ res.status(400).json({ error: patchRegression.error });
1622
+ return;
1623
+ }
1624
+ const metadata = typeof rawMetadata === 'object' && rawMetadata !== null ? patchRegression.metadata : rawMetadata;
1773
1625
  if (priority !== undefined && priority !== null && !(0, ticket_store_1.isValidPriority)(priority)) {
1774
1626
  res.status(400).json({ error: 'priority must be one of: critical, high, medium, low' });
1775
1627
  return;
@@ -1812,6 +1664,13 @@ function registerTicketsRoutes(deps) {
1812
1664
  }
1813
1665
  if (status !== undefined)
1814
1666
  ticket.status = status;
1667
+ // Non-goals (3.2): local-only (never a Jira write-back); [] / null clear.
1668
+ if (patchNonGoals?.ok) {
1669
+ if (patchNonGoals.nonGoals.length)
1670
+ ticket.nonGoals = patchNonGoals.nonGoals;
1671
+ else
1672
+ delete ticket.nonGoals;
1673
+ }
1815
1674
  if (priority !== undefined)
1816
1675
  ticket.priority = nextPriority;
1817
1676
  if (labels !== undefined && Array.isArray(labels))
@@ -1822,6 +1681,8 @@ function registerTicketsRoutes(deps) {
1822
1681
  ticket.prerequisites = prerequisites.filter((p) => typeof p === 'number');
1823
1682
  if (metadata !== undefined && typeof metadata === 'object' && metadata !== null) {
1824
1683
  ticket.metadata = { ...ticket.metadata, ...metadata };
1684
+ if (patchRegression.clear)
1685
+ delete ticket.metadata.regressionOf;
1825
1686
  }
1826
1687
  // Short summary: explicit non-empty overwrites; explicit null clears;
1827
1688
  // omitted leaves the existing value untouched (preserves prior summary
@@ -1862,8 +1723,11 @@ function registerTicketsRoutes(deps) {
1862
1723
  changes.priority = u.priority ?? null;
1863
1724
  if (labels !== undefined)
1864
1725
  changes.labels = u.labels;
1726
+ // A label-only edit is undoable for a few seconds in the UI: hold its Jira
1727
+ // write past that window so an undone change never reaches Jira.
1728
+ const labelsOnly = Object.keys(changes).length === 1 && changes.labels !== undefined;
1865
1729
  if (Object.keys(changes).length > 0)
1866
- jiraSyncManager?.onSpecEdited(Number(ticketId), changes);
1730
+ jiraSyncManager?.onSpecEdited(Number(ticketId), changes, labelsOnly ? { holdMs: UNDO_WINDOW_HOLD_MS } : {});
1867
1731
  }
1868
1732
  catch (e) {
1869
1733
  console.error('[project-router] jira write-back enqueue failed:', e);
@@ -2000,7 +1864,7 @@ function registerTicketsRoutes(deps) {
2000
1864
  // spawnAiCli reroutes multi-line argv values through stdin on Windows.
2001
1865
  console.log(`[project-router] ai-edit spawn: ${binary} (cwd=${project.path}, requestId=${requestId})`);
2002
1866
  const child = (0, cli_prompt_1.spawnAiCli)(binary, args, {
2003
- env: (0, runtime_1.buildProviderEnv)(adapter, aiEditOptions),
1867
+ env: (0, runtime_1.buildProviderEnv)(adapter, aiEditOptions, (0, project_env_1.projectAgentSourceEnv)(ctx(req).db, (0, runtime_1.providerEnvAllowlist)(adapter))),
2004
1868
  stdio: ['ignore', 'pipe', 'pipe'],
2005
1869
  cwd: project.path,
2006
1870
  });
@@ -2123,6 +1987,11 @@ function registerTicketsRoutes(deps) {
2123
1987
  res.json({ ok: true });
2124
1988
  });
2125
1989
  // DELETE /:projectId/tickets/:id — Delete ticket
1990
+ // DELETE /:projectId/tickets/:id — soft delete: the spec moves to "Recently
1991
+ // deleted" (restorable for 30 days). Attachments, its Explore draft
1992
+ // conversation and the Jira link stay untouched until the entry is purged or
1993
+ // deleted permanently, so Undo is lossless and Jira never sees a transient
1994
+ // delete (a spec delete has never written to Jira).
2126
1995
  router.delete('/:projectId/tickets/:id', (req, res) => {
2127
1996
  const ticketId = req.params.id;
2128
1997
  if (!/^\d+$/.test(ticketId)) {
@@ -2130,76 +1999,26 @@ function registerTicketsRoutes(deps) {
2130
1999
  return;
2131
2000
  }
2132
2001
  try {
2133
- const filePath = ticketPath(req);
2134
- let found = false;
2135
- let orphanedConversationId = null;
2136
- const orphanedChildren = [];
2137
- const numericId = Number(ticketId);
2138
- const store = (0, ticket_store_1.mutateStore)(filePath, (s) => {
2139
- const t = s.tickets[ticketId];
2140
- if (!t)
2141
- return;
2142
- // If this is a draft and no other ticket references the same
2143
- // origin_conversation_id, mark it for cascade delete.
2144
- if (t.status === 'draft' && t.origin_conversation_id) {
2145
- const otherRefs = Object.values(s.tickets).some((other) => other.id !== t.id && other.origin_conversation_id === t.origin_conversation_id);
2146
- if (!otherRefs)
2147
- orphanedConversationId = t.origin_conversation_id;
2148
- }
2149
- // SMASH: when deleting an épica, orphan its children (set
2150
- // parent_epic_id/execution_order to null) rather than cascade-delete.
2151
- if (t.is_epic) {
2152
- const now = new Date().toISOString();
2153
- for (const childId of Object.keys(s.tickets)) {
2154
- const child = s.tickets[childId];
2155
- if (child.parent_epic_id === numericId) {
2156
- child.parent_epic_id = null;
2157
- child.execution_order = null;
2158
- child.updated_at = now;
2159
- orphanedChildren.push(child);
2160
- }
2161
- }
2162
- }
2163
- delete s.tickets[ticketId];
2164
- found = true;
2165
- });
2166
- if (!found) {
2002
+ const result = (0, ticket_trash_1.softDeleteTicket)(ticketPath(req), Number(ticketId));
2003
+ if (!result) {
2167
2004
  res.status(404).json({ error: 'Ticket not found' });
2168
2005
  return;
2169
2006
  }
2170
- const { broadcast, ticketWatcher, db, chatManager } = ctx(req);
2171
- ticketWatcher.notifyDesktopWrite(store.revision);
2172
- // Cascade-delete attachments for this ticket
2173
- attachment_manager_1.attachmentManager.deleteAll(ctx(req).project.slug, ticketId).catch((e) => {
2174
- console.error('[project-router] attachment cascade delete failed:', e);
2175
- });
2176
- // Cascade-delete the orphaned Explore conversation, if any.
2177
- if (orphanedConversationId) {
2178
- try {
2179
- const conv = (0, db_1.getConversation)(db, orphanedConversationId);
2180
- if (conv && conv.kind === 'explore') {
2181
- (0, db_1.deleteConversation)(db, orphanedConversationId);
2182
- chatManager?.forgetSpecDraft(orphanedConversationId);
2183
- chatManager?.forgetExploreLifecycle(orphanedConversationId);
2184
- }
2185
- }
2186
- catch (err) {
2187
- console.error('[project-router] orphan conversation cleanup failed:', err);
2188
- }
2189
- }
2007
+ const { broadcast, ticketWatcher, project } = ctx(req);
2008
+ ticketWatcher.notifyDesktopWrite(result.revision);
2190
2009
  // Broadcast ticket_updated for each orphaned child so observers see them
2191
2010
  // as regular tickets (no longer attached to the deleted épica).
2192
- for (const child of orphanedChildren) {
2011
+ for (const child of result.orphanedChildren) {
2193
2012
  broadcast({
2194
2013
  type: 'ticket_updated',
2195
2014
  ticket: child,
2196
- projectId: ctx(req).project.id,
2015
+ projectId: project.id,
2197
2016
  timestamp: new Date().toISOString(),
2198
2017
  });
2199
2018
  }
2200
- const msg = { type: 'ticket_deleted', ticketId: Number(ticketId), projectId: ctx(req).project.id, timestamp: new Date().toISOString() };
2019
+ const msg = { type: 'ticket_deleted', ticketId: Number(ticketId), projectId: project.id, timestamp: new Date().toISOString() };
2201
2020
  broadcast(msg);
2202
- res.json({ ok: true, revision: store.revision });
2021
+ res.json({ ok: true, revision: result.revision, restorable: true });
2203
2022
  }
2204
2023
  catch (err) {
2205
2024
  console.error('[project-router] ticket delete error:', err);