specrails-desktop 2.20.1 → 2.22.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 (540) hide show
  1. package/README.md +3 -2
  2. package/client/dist/assets/{ActivityFeedPage-3WSqRYVx.js → ActivityFeedPage-roDyKGuv.js} +1 -1
  3. package/client/dist/assets/AgentBrowserCapture-BsXnWa4j.js +1 -0
  4. package/client/dist/assets/{AgentModeCodePane-Cnsea6eZ.js → AgentModeCodePane-o97EJvbJ.js} +2 -2
  5. package/client/dist/assets/AgentModeJobsPane-CLtpPxPM.js +1 -0
  6. package/client/dist/assets/AgentsPage-eNSo_ZcC.js +86 -0
  7. package/client/dist/assets/AnalyticsPage-cAJ60_Ex.js +1 -0
  8. package/client/dist/assets/{BarChart-C6If656N.js → BarChart-NLtK7xAY.js} +1 -1
  9. package/client/dist/assets/CodePage-B5rum8ZB.js +2 -0
  10. package/client/dist/assets/DesktopAnalyticsPage-DSuvG6Tq.js +1 -0
  11. package/client/dist/assets/DocsDialog-Bo38G3Yc.js +11 -0
  12. package/client/dist/assets/DocsPage-BNkiBBrC.js +11 -0
  13. package/client/dist/assets/{ExportDropdown-CezTK0EX.js → ExportDropdown-DCV8PN4-.js} +1 -1
  14. package/client/dist/assets/IntegrationsPage-BMJOzpPz.js +3 -0
  15. package/client/dist/assets/InteractiveJobComposer-aLduNs5R.js +19 -0
  16. package/client/dist/assets/JobDetailModal-kpkUWJIS.js +1 -0
  17. package/client/dist/assets/JobDetailPage-CFeqlrPU.js +1 -0
  18. package/client/dist/assets/JobsPage-fuwhXy2I.js +1 -0
  19. package/client/dist/assets/LoopBuilderPage-DP66322C.js +7 -0
  20. package/client/dist/assets/LoopPreviewModal-CpmBhE31.js +1 -0
  21. package/client/dist/assets/LoopsPage-CvQ18VUx.js +1 -0
  22. package/client/dist/assets/ProjectSettingsDialog-Deq4pwvq.js +1 -0
  23. package/client/dist/assets/TemplatePreviewModal-DziOj2Ct.js +1 -0
  24. package/client/dist/assets/agent-Csh4kP2S.js +1 -0
  25. package/client/dist/assets/agent-Cz_jgQX32.js +1 -0
  26. package/client/dist/assets/agent-D3vcIvaz2.js +1 -0
  27. package/client/dist/assets/agent-Dnbt0V4e.js +1 -0
  28. package/client/dist/assets/agent-HolR7QrZ.js +1 -0
  29. package/client/dist/assets/agent-Ka0rRWJy.js +1 -0
  30. package/client/dist/assets/agent-Te3yysMd.js +1 -0
  31. package/client/dist/assets/agent-vM4_iLDk2.js +1 -0
  32. package/client/dist/assets/{upload-CRtTj4Co.js → brain-kFJuEDNH.js} +1 -1
  33. package/client/dist/assets/{browser-DEEO-OSi.js → browser-BPkhILSJ.js} +1 -1
  34. package/client/dist/assets/{browser-BTivfZKE2.js → browser-BijVYG0Y2.js} +1 -1
  35. package/client/dist/assets/{browser-bpO3onlS.js → browser-BqLqJVVT.js} +1 -1
  36. package/client/dist/assets/{browser-DlSXtfu5.js → browser-Cc0iDqUi.js} +1 -1
  37. package/client/dist/assets/browser-CdS6O1Qb.js +1 -0
  38. package/client/dist/assets/{browser-BKP6hqQC2.js → browser-Cvg-QHvd2.js} +1 -1
  39. package/client/dist/assets/{browser-INCUyduh.js → browser-FRv8P02E.js} +1 -1
  40. package/client/dist/assets/{browser-DlKLfT612.js → browser-rWKj-RR_2.js} +1 -1
  41. package/client/dist/assets/code-BRcDlze52.js +1 -0
  42. package/client/dist/assets/code-BdMy3Ffq.js +1 -0
  43. package/client/dist/assets/code-CeQ0FZpC.js +1 -0
  44. package/client/dist/assets/code-CqCcRThR.js +1 -0
  45. package/client/dist/assets/code-DgeHz9CB.js +1 -0
  46. package/client/dist/assets/code-DzC1rMk12.js +1 -0
  47. package/client/dist/assets/code-UPVvmAKM2.js +1 -0
  48. package/client/dist/assets/code-thSEptMx.js +1 -0
  49. package/client/dist/assets/{common-QjVnq9XP2.js → common-BM3LFLCE2.js} +1 -1
  50. package/client/dist/assets/{common-CeQUwuHt2.js → common-Bwafujnc2.js} +1 -1
  51. package/client/dist/assets/{common-Bb64s3Bm.js → common-C-vU-j-I.js} +1 -1
  52. package/client/dist/assets/{common-KbQuTSGg.js → common-C5HKSbbz.js} +1 -1
  53. package/client/dist/assets/{common-BPQQkgJZ.js → common-CYaT2yHp.js} +1 -1
  54. package/client/dist/assets/{common-DPxotRK9.js → common-DhWTkocg.js} +1 -1
  55. package/client/dist/assets/{common-k5MTOHpn.js → common-DiPTT7V_2.js} +1 -1
  56. package/client/dist/assets/{common-C8ZD5upH2.js → common-DmqBPwZG.js} +1 -1
  57. package/client/dist/assets/{cssMode-DsArsSCT.js → cssMode-DBHbkBvI.js} +1 -1
  58. package/client/dist/assets/dashboard-BaStj_a_.js +1 -0
  59. package/client/dist/assets/dashboard-Bi6ugu5Q.js +1 -0
  60. package/client/dist/assets/dashboard-BmqTn3L02.js +1 -0
  61. package/client/dist/assets/dashboard-CvT8lOCT.js +1 -0
  62. package/client/dist/assets/dashboard-D7Pmeavq2.js +1 -0
  63. package/client/dist/assets/dashboard-DAnWdAac2.js +1 -0
  64. package/client/dist/assets/dashboard-JnYy2WLg.js +1 -0
  65. package/client/dist/assets/dashboard-L47YsFS_.js +1 -0
  66. package/client/dist/assets/{dist-js-BQn4yxaw.js → dist-js-BZSiJDbG.js} +1 -1
  67. package/client/dist/assets/{dist-js-BAWSqVtr.js → dist-js-DKpmIJlQ.js} +1 -1
  68. package/client/dist/assets/{editor.main-G3Sl9C67.js → editor.main-C9J2ikJK.js} +2 -2
  69. package/client/dist/assets/{freemarker2-pBzQNgFi.js → freemarker2-J5iIIIK-.js} +1 -1
  70. package/client/dist/assets/{handlebars-CtBTCnBI.js → handlebars-DSw1l_tw.js} +1 -1
  71. package/client/dist/assets/{html-Dx3DYBzY.js → html-h2-wE1Lj.js} +1 -1
  72. package/client/dist/assets/{htmlMode-In7frFOo.js → htmlMode-Cc_ij7lW.js} +1 -1
  73. package/client/dist/assets/index-DM6heiGa.js +155 -0
  74. package/client/dist/assets/index-DPX6_xIC.css +2 -0
  75. package/client/dist/assets/{javascript-BKcn-YkN.js → javascript-C1q3xv6N.js} +1 -1
  76. package/client/dist/assets/jira-B3613-gj.js +1 -0
  77. package/client/dist/assets/jira-BHAKtc4B.js +1 -0
  78. package/client/dist/assets/jira-Be369RIR2.js +1 -0
  79. package/client/dist/assets/jira-CPpgA-5z2.js +1 -0
  80. package/client/dist/assets/jira-D5efgwp_.js +1 -0
  81. package/client/dist/assets/jira-DS7ownDy.js +1 -0
  82. package/client/dist/assets/jira-bDs7Im2C.js +1 -0
  83. package/client/dist/assets/jira-uNH1gETL2.js +1 -0
  84. package/client/dist/assets/jobs-1GV2-4zd2.js +1 -0
  85. package/client/dist/assets/jobs-26F9gGcE.js +1 -0
  86. package/client/dist/assets/jobs-BgQzB0Sx2.js +1 -0
  87. package/client/dist/assets/jobs-BqWui9_f.js +1 -0
  88. package/client/dist/assets/jobs-CE8qeIYj.js +1 -0
  89. package/client/dist/assets/jobs-D5sZzgLs.js +1 -0
  90. package/client/dist/assets/jobs-DzeuASRf.js +1 -0
  91. package/client/dist/assets/jobs-Wh7dn28q2.js +1 -0
  92. package/client/dist/assets/{jsonMode-jNREoQ3C.js → jsonMode-CeaCdEhr.js} +1 -1
  93. package/client/dist/assets/{lib-C-g8QbZl.js → lib-B2nCKzmA.js} +1 -1
  94. package/client/dist/assets/{liquid-CtRkGqBu.js → liquid-eFsVK0V-.js} +1 -1
  95. package/client/dist/assets/loops-BvEenWBy.js +1 -0
  96. package/client/dist/assets/loops-CBiWd9Hf.js +1 -0
  97. package/client/dist/assets/loops-DNGiYKll2.js +1 -0
  98. package/client/dist/assets/{loops-Y3FQsUCh.js → loops-DjOtVXRo.js} +1 -1
  99. package/client/dist/assets/loops-HTHf-xu32.js +1 -0
  100. package/client/dist/assets/loops-YYV2bwjd.js +1 -0
  101. package/client/dist/assets/loops-hXgncEpF2.js +1 -0
  102. package/client/dist/assets/loops-kYbydDyN.js +1 -0
  103. package/client/dist/assets/{lspLanguageFeatures-Cl3gvD_W.js → lspLanguageFeatures-DT3-bbhn.js} +1 -1
  104. package/client/dist/assets/{mdx-B_nJldHz.js → mdx-Fuwnh1cX.js} +1 -1
  105. package/client/dist/assets/{monaco.contribution-PUeaZk8T.js → monaco.contribution-Desq7oq4.js} +2 -2
  106. package/client/dist/assets/{python-DS1Ce-A6.js → python-BgoEs6Cj.js} +1 -1
  107. package/client/dist/assets/{razor-L41Qg9OK.js → razor-CM1sPMMq.js} +1 -1
  108. package/client/dist/assets/{settings-BPq9nCJm.js → settings-BOHOmHkb.js} +1 -1
  109. package/client/dist/assets/{settings-r8Qq2Gzp2.js → settings-BlEA_7h02.js} +1 -1
  110. package/client/dist/assets/{settings-C-m3yEZ2.js → settings-BsJMsWGc.js} +1 -1
  111. package/client/dist/assets/{settings-zZr7NzuB.js → settings-D6qY9_UI.js} +1 -1
  112. package/client/dist/assets/{settings-VgCsjaYf.js → settings-DZJeXoRV.js} +1 -1
  113. package/client/dist/assets/settings-Mr7MnJbf.js +1 -0
  114. package/client/dist/assets/{settings-BWHGtmU12.js → settings-TNga5gIF2.js} +1 -1
  115. package/client/dist/assets/{settings-DZj7Uqy32.js → settings-lFoaYT-s2.js} +1 -1
  116. package/client/dist/assets/setup-B590KsTX.js +1 -0
  117. package/client/dist/assets/setup-BkyGoby6.js +1 -0
  118. package/client/dist/assets/setup-CEj6uY3-2.js +1 -0
  119. package/client/dist/assets/setup-CbIerFGf2.js +1 -0
  120. package/client/dist/assets/setup-CmU6bTCV2.js +1 -0
  121. package/client/dist/assets/setup-D674kWQH.js +1 -0
  122. package/client/dist/assets/setup-VNqXyB6Y.js +1 -0
  123. package/client/dist/assets/setup-iY8vH8pB.js +1 -0
  124. package/client/dist/assets/specs-C9Sd7BhH2.js +1 -0
  125. package/client/dist/assets/specs-CBDvEYKv.js +1 -0
  126. package/client/dist/assets/specs-CIPr9reA2.js +1 -0
  127. package/client/dist/assets/specs-CWtKcVDC.js +1 -0
  128. package/client/dist/assets/specs-CmEZY57v.js +1 -0
  129. package/client/dist/assets/specs-D2clrt2c2.js +1 -0
  130. package/client/dist/assets/specs-DTplt2XM.js +1 -0
  131. package/client/dist/assets/specs-PozUNhqb.js +1 -0
  132. package/client/dist/assets/{tsMode-BC1g186U.js → tsMode-BmT8WogI.js} +1 -1
  133. package/client/dist/assets/{typescript-BGlRGvJW.js → typescript-CQrQPsoW.js} +1 -1
  134. package/client/dist/assets/upload-CLAzW1mS.js +1 -0
  135. package/client/dist/assets/{value-D9aLbxw-.js → value-DSwzyyWR.js} +1 -1
  136. package/client/dist/assets/{workers-CXcXtO3b.js → workers-U0UXyLUf.js} +1 -1
  137. package/client/dist/assets/{xml-JdZZaIhJ.js → xml-WRxJs8_I.js} +1 -1
  138. package/client/dist/assets/{yaml-Cm82BVBt.js → yaml-CjpSTjJU.js} +1 -1
  139. package/client/dist/index.html +14 -14
  140. package/docs/customizing.md +2 -2
  141. package/docs/gemini.md +15 -4
  142. package/docs/guide/de/insights/3-code-explorer.md +6 -0
  143. package/docs/guide/de/integrations/3-jira-integration.md +1 -1
  144. package/docs/guide/de/integrations/6-agent-chat.md +5 -0
  145. package/docs/guide/de/pipeline/1-rails-and-jobs.md +6 -6
  146. package/docs/guide/de/pipeline/2-the-job-detail-view.md +27 -2
  147. package/docs/guide/de/pipeline/3-batch-implement-and-multi-feature.md +9 -5
  148. package/docs/guide/de/pipeline/5-the-loop-builder.md +1 -1
  149. package/docs/guide/de/specs/1-specs-and-the-backlog.md +3 -2
  150. package/docs/guide/en/insights/3-code-explorer.md +6 -0
  151. package/docs/guide/en/integrations/3-jira-integration.md +1 -1
  152. package/docs/guide/en/integrations/6-agent-chat.md +5 -0
  153. package/docs/guide/en/pipeline/1-rails-and-jobs.md +6 -6
  154. package/docs/guide/en/pipeline/2-the-job-detail-view.md +27 -2
  155. package/docs/guide/en/pipeline/3-batch-implement-and-multi-feature.md +10 -4
  156. package/docs/guide/en/pipeline/5-the-loop-builder.md +1 -1
  157. package/docs/guide/en/specs/1-specs-and-the-backlog.md +3 -2
  158. package/docs/guide/es/insights/3-code-explorer.md +6 -0
  159. package/docs/guide/es/integrations/3-jira-integration.md +1 -1
  160. package/docs/guide/es/integrations/6-agent-chat.md +5 -0
  161. package/docs/guide/es/pipeline/1-rails-and-jobs.md +6 -6
  162. package/docs/guide/es/pipeline/2-the-job-detail-view.md +27 -2
  163. package/docs/guide/es/pipeline/3-batch-implement-and-multi-feature.md +9 -5
  164. package/docs/guide/es/pipeline/5-the-loop-builder.md +1 -1
  165. package/docs/guide/es/specs/1-specs-and-the-backlog.md +3 -2
  166. package/docs/guide/fr/insights/3-code-explorer.md +6 -0
  167. package/docs/guide/fr/integrations/3-jira-integration.md +1 -1
  168. package/docs/guide/fr/integrations/6-agent-chat.md +5 -0
  169. package/docs/guide/fr/pipeline/1-rails-and-jobs.md +6 -6
  170. package/docs/guide/fr/pipeline/2-the-job-detail-view.md +27 -2
  171. package/docs/guide/fr/pipeline/3-batch-implement-and-multi-feature.md +9 -5
  172. package/docs/guide/fr/pipeline/5-the-loop-builder.md +1 -1
  173. package/docs/guide/fr/specs/1-specs-and-the-backlog.md +3 -2
  174. package/docs/guide/it/insights/3-code-explorer.md +6 -0
  175. package/docs/guide/it/integrations/3-jira-integration.md +1 -1
  176. package/docs/guide/it/integrations/6-agent-chat.md +5 -0
  177. package/docs/guide/it/pipeline/1-rails-and-jobs.md +6 -6
  178. package/docs/guide/it/pipeline/2-the-job-detail-view.md +27 -2
  179. package/docs/guide/it/pipeline/3-batch-implement-and-multi-feature.md +10 -6
  180. package/docs/guide/it/pipeline/5-the-loop-builder.md +1 -1
  181. package/docs/guide/it/specs/1-specs-and-the-backlog.md +3 -2
  182. package/docs/guide/ja/insights/3-code-explorer.md +6 -0
  183. package/docs/guide/ja/integrations/3-jira-integration.md +1 -1
  184. package/docs/guide/ja/integrations/6-agent-chat.md +5 -0
  185. package/docs/guide/ja/pipeline/1-rails-and-jobs.md +6 -6
  186. package/docs/guide/ja/pipeline/2-the-job-detail-view.md +27 -2
  187. package/docs/guide/ja/pipeline/3-batch-implement-and-multi-feature.md +9 -5
  188. package/docs/guide/ja/pipeline/5-the-loop-builder.md +1 -1
  189. package/docs/guide/ja/specs/1-specs-and-the-backlog.md +3 -2
  190. package/docs/guide/pt/insights/3-code-explorer.md +6 -0
  191. package/docs/guide/pt/integrations/3-jira-integration.md +1 -1
  192. package/docs/guide/pt/integrations/6-agent-chat.md +5 -0
  193. package/docs/guide/pt/pipeline/1-rails-and-jobs.md +6 -6
  194. package/docs/guide/pt/pipeline/2-the-job-detail-view.md +27 -2
  195. package/docs/guide/pt/pipeline/3-batch-implement-and-multi-feature.md +9 -5
  196. package/docs/guide/pt/pipeline/5-the-loop-builder.md +1 -1
  197. package/docs/guide/pt/specs/1-specs-and-the-backlog.md +3 -2
  198. package/docs/guide/zh/insights/3-code-explorer.md +6 -0
  199. package/docs/guide/zh/integrations/3-jira-integration.md +1 -1
  200. package/docs/guide/zh/integrations/6-agent-chat.md +5 -0
  201. package/docs/guide/zh/pipeline/1-rails-and-jobs.md +6 -6
  202. package/docs/guide/zh/pipeline/2-the-job-detail-view.md +27 -2
  203. package/docs/guide/zh/pipeline/3-batch-implement-and-multi-feature.md +10 -6
  204. package/docs/guide/zh/pipeline/5-the-loop-builder.md +1 -1
  205. package/docs/guide/zh/specs/1-specs-and-the-backlog.md +3 -2
  206. package/docs/internals/README.md +5 -0
  207. package/docs/internals/adding-a-provider.md +15 -3
  208. package/docs/internals/api-reference.md +6 -5
  209. package/docs/internals/browser-capture-performance.md +93 -0
  210. package/docs/internals/code-explorer-story.md +135 -0
  211. package/docs/internals/gemini-mcp-registration.md +53 -0
  212. package/docs/internals/interactive-jobs.md +212 -0
  213. package/docs/internals/loop-step-log-explorer.md +146 -0
  214. package/docs/internals/safe-pr-review-flow.md +367 -0
  215. package/docs/mcp.md +1 -1
  216. package/docs/running-pipelines.md +6 -2
  217. package/package.json +1 -1
  218. package/server/dist/agent-chat-manager.js +211 -0
  219. package/server/dist/agent-chat-registry.js +20 -0
  220. package/server/dist/agent-chat-router.js +22 -0
  221. package/server/dist/agent-mcp-config.js +45 -4
  222. package/server/dist/agent-operator-prompt.js +149 -56
  223. package/server/dist/agent-store.js +25 -0
  224. package/server/dist/agent-tier.js +6 -1
  225. package/server/dist/browser-capture-manager.js +184 -34
  226. package/server/dist/browser-playwright.js +98 -13
  227. package/server/dist/code-explorer-router.js +92 -0
  228. package/server/dist/db.js +102 -0
  229. package/server/dist/file-provenance.js +54 -1
  230. package/server/dist/file-story-manager.js +170 -0
  231. package/server/dist/file-story.js +148 -0
  232. package/server/dist/file-summary-generator.js +5 -4
  233. package/server/dist/git-guardrails.js +62 -0
  234. package/server/dist/index.js +5 -0
  235. package/server/dist/integration-branch.js +63 -0
  236. package/server/dist/interactive-job-session.js +226 -18
  237. package/server/dist/jira/jira-adf.js +9 -0
  238. package/server/dist/jira/jira-materializer.js +27 -4
  239. package/server/dist/jira/jira-status-resolver.js +12 -4
  240. package/server/dist/jira/jira-sync-manager.js +130 -2
  241. package/server/dist/jira-router.js +1 -1
  242. package/server/dist/loop-effect.js +12 -0
  243. package/server/dist/loop-executors.js +92 -22
  244. package/server/dist/loop-run-manager.js +354 -28
  245. package/server/dist/mcp/guide.js +18 -7
  246. package/server/dist/mcp/tools/jira.js +1 -1
  247. package/server/dist/mcp/tools/jobs.js +14 -5
  248. package/server/dist/mcp/tools/rails.js +137 -12
  249. package/server/dist/mcp/tools/specs.js +35 -9
  250. package/server/dist/mcp/tools/types.js +49 -0
  251. package/server/dist/mobile/mobile-ws.js +4 -0
  252. package/server/dist/path-resolver.js +46 -0
  253. package/server/dist/pr-body.js +240 -0
  254. package/server/dist/pr-naming.js +210 -0
  255. package/server/dist/pr-publisher.js +68 -0
  256. package/server/dist/project-registry.js +77 -17
  257. package/server/dist/project-router-jobs.js +53 -13
  258. package/server/dist/project-router-settings.js +33 -0
  259. package/server/dist/project-router-terminals.js +16 -0
  260. package/server/dist/project-router-tickets.js +57 -3
  261. package/server/dist/project-router.js +52 -13
  262. package/server/dist/queue-manager.js +268 -83
  263. package/server/dist/rail-isolated-launch.js +324 -34
  264. package/server/dist/rail-isolation.js +32 -5
  265. package/server/dist/rail-pr-decision.js +519 -0
  266. package/server/dist/rail-pr-delivery.js +75 -0
  267. package/server/dist/rail-pr-store.js +175 -0
  268. package/server/dist/rail-worktrees-store.js +18 -0
  269. package/server/dist/rails-router.js +241 -17
  270. package/server/dist/rails-store.js +78 -1
  271. package/server/dist/setup-prerequisites.js +105 -0
  272. package/server/dist/smash-runner.js +3 -1
  273. package/server/dist/ticket-store.js +7 -3
  274. package/server/dist/workspace-resolution.js +27 -0
  275. package/server/dist/worktree-manager.js +42 -7
  276. package/server/dist/worktree-overlay.js +261 -0
  277. package/client/dist/assets/AgentBrowserCapture-BlGDZahz.js +0 -1
  278. package/client/dist/assets/AgentModeJobsPane-CyNR-9BO.js +0 -1
  279. package/client/dist/assets/AgentsPage-dNsEsY_x.js +0 -86
  280. package/client/dist/assets/AnalyticsPage-BAxmR0HQ.js +0 -1
  281. package/client/dist/assets/CodePage-Crc4BBQN.js +0 -2
  282. package/client/dist/assets/DesktopAnalyticsPage-IXSnbCce.js +0 -1
  283. package/client/dist/assets/DocsDialog-Bc4hx7oW.js +0 -11
  284. package/client/dist/assets/DocsPage-bEU4t9c6.js +0 -11
  285. package/client/dist/assets/IntegrationsPage-wq2CezEL.js +0 -3
  286. package/client/dist/assets/JobDetailPage-BBcPk3j8.js +0 -1
  287. package/client/dist/assets/JobsPage-DXrSPlwa.js +0 -1
  288. package/client/dist/assets/LogViewer-BoYbwvbU.js +0 -16
  289. package/client/dist/assets/LoopBuilderPage-CiUMAuWz.js +0 -7
  290. package/client/dist/assets/LoopsPage-Xrp6W5XW.js +0 -1
  291. package/client/dist/assets/ProjectSettingsDialog-BU98L5JD.js +0 -1
  292. package/client/dist/assets/agent-B7GdHP3Z.js +0 -1
  293. package/client/dist/assets/agent-BHmcgoJf.js +0 -1
  294. package/client/dist/assets/agent-BdY_fii4.js +0 -1
  295. package/client/dist/assets/agent-C32FOi9v.js +0 -1
  296. package/client/dist/assets/agent-CiFQxoaZ2.js +0 -1
  297. package/client/dist/assets/agent-CtAag7V6.js +0 -1
  298. package/client/dist/assets/agent-DE4Mp1fY2.js +0 -1
  299. package/client/dist/assets/agent-DK8qovyG2.js +0 -1
  300. package/client/dist/assets/browser-ZB1afzjZ.js +0 -1
  301. package/client/dist/assets/code-BFxE1Yt62.js +0 -1
  302. package/client/dist/assets/code-BefYOm5Q.js +0 -1
  303. package/client/dist/assets/code-BkXpJt99.js +0 -1
  304. package/client/dist/assets/code-C6Sq7_t8.js +0 -1
  305. package/client/dist/assets/code-CGj3w-2N.js +0 -1
  306. package/client/dist/assets/code-Dfsxc9o82.js +0 -1
  307. package/client/dist/assets/code-Y5urks5s2.js +0 -1
  308. package/client/dist/assets/code-wtcs0ivb.js +0 -1
  309. package/client/dist/assets/dashboard-B8032psZ.js +0 -1
  310. package/client/dist/assets/dashboard-BHGKtxty2.js +0 -1
  311. package/client/dist/assets/dashboard-CXnoUgN22.js +0 -1
  312. package/client/dist/assets/dashboard-Ccyxqy7d.js +0 -1
  313. package/client/dist/assets/dashboard-CoED_41r.js +0 -1
  314. package/client/dist/assets/dashboard-Dc5ZAgMN.js +0 -1
  315. package/client/dist/assets/dashboard-JMY8ueD3.js +0 -1
  316. package/client/dist/assets/dashboard-tkWr1aHD2.js +0 -1
  317. package/client/dist/assets/index-BHPbzyg6.css +0 -2
  318. package/client/dist/assets/index-n2PmJGF6.js +0 -152
  319. package/client/dist/assets/jira-BcZzX9122.js +0 -1
  320. package/client/dist/assets/jira-CTYs7LA12.js +0 -1
  321. package/client/dist/assets/jira-D2nN39e92.js +0 -1
  322. package/client/dist/assets/jira-DJxmIkyr.js +0 -1
  323. package/client/dist/assets/jira-DXMoAKWD.js +0 -1
  324. package/client/dist/assets/jira-IhC1ROIc.js +0 -1
  325. package/client/dist/assets/jira-Iw575fN8.js +0 -1
  326. package/client/dist/assets/jira-kbWZY7jH.js +0 -1
  327. package/client/dist/assets/jobs-BqF79kHz2.js +0 -1
  328. package/client/dist/assets/jobs-C1XM5urS.js +0 -1
  329. package/client/dist/assets/jobs-C5UjG0262.js +0 -1
  330. package/client/dist/assets/jobs-DBfaHTxC.js +0 -1
  331. package/client/dist/assets/jobs-DM4BDPdg.js +0 -1
  332. package/client/dist/assets/jobs-Da5OkZmf2.js +0 -1
  333. package/client/dist/assets/jobs-JJdnuQ03.js +0 -1
  334. package/client/dist/assets/jobs-SI34ML8I.js +0 -1
  335. package/client/dist/assets/loops-BR4FmOv12.js +0 -1
  336. package/client/dist/assets/loops-BgX_uudn.js +0 -1
  337. package/client/dist/assets/loops-Bpl2j2LP.js +0 -1
  338. package/client/dist/assets/loops-CQuuMlyZ.js +0 -1
  339. package/client/dist/assets/loops-DW8hSMdS2.js +0 -1
  340. package/client/dist/assets/loops-Q2muu8hW2.js +0 -1
  341. package/client/dist/assets/loops-q7CNDvfK.js +0 -1
  342. package/client/dist/assets/settings-CY8udi0e.js +0 -1
  343. package/client/dist/assets/setup-CNMdCHHt2.js +0 -1
  344. package/client/dist/assets/setup-Cag4XrbL2.js +0 -1
  345. package/client/dist/assets/setup-D9IHGoWU.js +0 -1
  346. package/client/dist/assets/setup-Dg6Ba3JT.js +0 -1
  347. package/client/dist/assets/setup-DyK36RIW.js +0 -1
  348. package/client/dist/assets/setup-G4ZvDKxX.js +0 -1
  349. package/client/dist/assets/setup-aTlGxuwi2.js +0 -1
  350. package/client/dist/assets/setup-kWsoAeHQ.js +0 -1
  351. package/client/dist/assets/specs-BFSUPa122.js +0 -1
  352. package/client/dist/assets/specs-BMzip1WY2.js +0 -1
  353. package/client/dist/assets/specs-BYeAbIEy.js +0 -1
  354. package/client/dist/assets/specs-C-mtLcXw.js +0 -1
  355. package/client/dist/assets/specs-CAzpvADd2.js +0 -1
  356. package/client/dist/assets/specs-CyRIw_IR.js +0 -1
  357. package/client/dist/assets/specs-DMm7gB_l.js +0 -1
  358. package/client/dist/assets/specs-DuottM0Z.js +0 -1
  359. /package/client/dist/assets/{abap-CpHUwCVK.js → abap-D0E4FfVW.js} +0 -0
  360. /package/client/dist/assets/{activity-DemHQS7l.js → activity--iN4Ad2R2.js} +0 -0
  361. /package/client/dist/assets/{activity-B_71BWg3.js → activity-6hM_ZSg9.js} +0 -0
  362. /package/client/dist/assets/{activity-DHv2V5Oi.js → activity-BZNfOdiS.js} +0 -0
  363. /package/client/dist/assets/{activity-D0rfjQzT2.js → activity-BuVo5sPB.js} +0 -0
  364. /package/client/dist/assets/{activity-BpTTj_PH.js → activity-CIOLxGvh.js} +0 -0
  365. /package/client/dist/assets/{activity-D2e62vbV2.js → activity-D2r2h3SE2.js} +0 -0
  366. /package/client/dist/assets/{activity-Ch-wbr0C2.js → activity-DtxrAUMo2.js} +0 -0
  367. /package/client/dist/assets/{addon-image-Ba-TY3wr.js → addon-image-CwoZj17F.js} +0 -0
  368. /package/client/dist/assets/{addon-ligatures-T4ARLiuu.js → addon-ligatures-CWDrED80.js} +0 -0
  369. /package/client/dist/assets/{addon-webgl-Cd73n8eh.js → addon-webgl-DMbGeI_u.js} +0 -0
  370. /package/client/dist/assets/{addspec-xwRX_Pnf.js → addspec-BMtLZLW62.js} +0 -0
  371. /package/client/dist/assets/{addspec-l_zU5gla.js → addspec-CP0HRuxY.js} +0 -0
  372. /package/client/dist/assets/{addspec-Dio-H5z0.js → addspec-CRuvWn8d.js} +0 -0
  373. /package/client/dist/assets/{addspec-D6L4ZteP.js → addspec-D-JLDsUV.js} +0 -0
  374. /package/client/dist/assets/{addspec-CrEm6Fzr2.js → addspec-DfhDbg5c.js} +0 -0
  375. /package/client/dist/assets/{addspec-B6Ns8KU02.js → addspec-bsNDdqRm2.js} +0 -0
  376. /package/client/dist/assets/{addspec-qGyH7MHy2.js → addspec-mgPOt5q02.js} +0 -0
  377. /package/client/dist/assets/{agents-OzxCLVW1.js → agents-78bTZGZh.js} +0 -0
  378. /package/client/dist/assets/{agents-hv3sqmPm2.js → agents-BLhWCmDS2.js} +0 -0
  379. /package/client/dist/assets/{agents-CHgCudUV.js → agents-BUdEi3-N.js} +0 -0
  380. /package/client/dist/assets/{agents-Dumx4JiM2.js → agents-BpoUaoW92.js} +0 -0
  381. /package/client/dist/assets/{agents-CnaPeSyw.js → agents-CWo-KyAB.js} +0 -0
  382. /package/client/dist/assets/{agents-Xh-zYHUx2.js → agents-DDtCJ5M02.js} +0 -0
  383. /package/client/dist/assets/{agents-DuhLEaQ_.js → agents-bvyRLczL.js} +0 -0
  384. /package/client/dist/assets/{agentstudio-CCthUdzR.js → agentstudio-BMQxc_bz.js} +0 -0
  385. /package/client/dist/assets/{agentstudio-CcH8Ckql2.js → agentstudio-COZriimI2.js} +0 -0
  386. /package/client/dist/assets/{agentstudio-Bo91kfUd2.js → agentstudio-CWgXG5W52.js} +0 -0
  387. /package/client/dist/assets/{agentstudio-VJOa_NVO.js → agentstudio-C_Jq8Tl4.js} +0 -0
  388. /package/client/dist/assets/{agentstudio-BIxikDf_.js → agentstudio-Dtq3dGYk.js} +0 -0
  389. /package/client/dist/assets/{agentstudio-Bz8cP8_c.js → agentstudio-jKMTdT70.js} +0 -0
  390. /package/client/dist/assets/{agentstudio-DARgYg5Z2.js → agentstudio-sI27TpBu2.js} +0 -0
  391. /package/client/dist/assets/{aiedit-5ZXN4cep2.js → aiedit-6CHdb_iv2.js} +0 -0
  392. /package/client/dist/assets/{aiedit-B7gAJZVC.js → aiedit-B03pD_Na.js} +0 -0
  393. /package/client/dist/assets/{aiedit-D92V-kUW.js → aiedit-BtRqRxML.js} +0 -0
  394. /package/client/dist/assets/{aiedit-D9ualLVJ.js → aiedit-eMN4eQPF.js} +0 -0
  395. /package/client/dist/assets/{aiedit-h48tJU0V2.js → aiedit-hknZlly82.js} +0 -0
  396. /package/client/dist/assets/{aiedit-xkA_mR2a2.js → aiedit-igmw-ZoZ2.js} +0 -0
  397. /package/client/dist/assets/{aiedit-7B2dvCv-.js → aiedit-pc5JDUq1.js} +0 -0
  398. /package/client/dist/assets/{analytics-slx4X1mu2.js → analytics-BWMUZ2Pq2.js} +0 -0
  399. /package/client/dist/assets/{analytics-uRNP6yAJ.js → analytics-Bj-SmKHa.js} +0 -0
  400. /package/client/dist/assets/{analytics-WF1I49ln.js → analytics-C5dpiS0o.js} +0 -0
  401. /package/client/dist/assets/{analytics-CBvaxOId.js → analytics-CCprAqk3.js} +0 -0
  402. /package/client/dist/assets/{analytics-BakymH7Z2.js → analytics-CR1TJqUi2.js} +0 -0
  403. /package/client/dist/assets/{analytics-B7bPj6u_2.js → analytics-DfNdXR0y2.js} +0 -0
  404. /package/client/dist/assets/{analytics-DZ74aQ54.js → analytics-rmHuJv0V.js} +0 -0
  405. /package/client/dist/assets/{apex-DlD7oJX6.js → apex-D_X_8J4d.js} +0 -0
  406. /package/client/dist/assets/{atom-one-dark-BrRN8wBy.js → atom-one-dark-BMDPFwRZ.js} +0 -0
  407. /package/client/dist/assets/{attachments-C11tOKZ_.js → attachments-BgBNSqQd.js} +0 -0
  408. /package/client/dist/assets/{attachments-Bnbyj2PN.js → attachments-BjyMmrwE.js} +0 -0
  409. /package/client/dist/assets/{attachments-CIeLa8l12.js → attachments-C9GTTJsx2.js} +0 -0
  410. /package/client/dist/assets/{attachments-DslHfa-L.js → attachments-DCZOL1RU.js} +0 -0
  411. /package/client/dist/assets/{attachments-C-gyrCOb.js → attachments-DL-bPy9E.js} +0 -0
  412. /package/client/dist/assets/{attachments-Cxrs0pyL2.js → attachments-DPCmkFZu2.js} +0 -0
  413. /package/client/dist/assets/{attachments-TTPsc0a52.js → attachments-rNn1ekRy2.js} +0 -0
  414. /package/client/dist/assets/{azcli-CmXFAbc-.js → azcli-PZLnZ3jH.js} +0 -0
  415. /package/client/dist/assets/{bat-DdNJq4hH.js → bat-KlBOxpO4.js} +0 -0
  416. /package/client/dist/assets/{bicep-Bppz7WOA.js → bicep-CgG9oF3V.js} +0 -0
  417. /package/client/dist/assets/{cameligo-0MRMdSmg.js → cameligo-6R45j6Ph.js} +0 -0
  418. /package/client/dist/assets/{chat-BvHrebKC2.js → chat-BgL3zv6x2.js} +0 -0
  419. /package/client/dist/assets/{chat-CZyiLJvQ.js → chat-Bh3NdgJs.js} +0 -0
  420. /package/client/dist/assets/{chat-DKYP7NnC.js → chat-Bom6bqK3.js} +0 -0
  421. /package/client/dist/assets/{chat-5mdg_YIc2.js → chat-DdwZjT8K2.js} +0 -0
  422. /package/client/dist/assets/{chat-wkTIy9rX.js → chat-Dnwg-NpQ.js} +0 -0
  423. /package/client/dist/assets/{chat-BpYxnkr4.js → chat-DsbwJhus.js} +0 -0
  424. /package/client/dist/assets/{chat-BGax2nV62.js → chat-vylxqR0P2.js} +0 -0
  425. /package/client/dist/assets/{clojure-B5dKj863.js → clojure-CLAAMO7J.js} +0 -0
  426. /package/client/dist/assets/{clsx-1dnHRn8W.js → clsx-CNmW0Nip.js} +0 -0
  427. /package/client/dist/assets/{coffee-DSbWjzk7.js → coffee-AruSygo-.js} +0 -0
  428. /package/client/dist/assets/{commands-uz_uKT242.js → commands-C4Y3C-PF2.js} +0 -0
  429. /package/client/dist/assets/{commands-Bb7MnPqn2.js → commands-CSDs9q_2.js} +0 -0
  430. /package/client/dist/assets/{commands-C_7zZwJf.js → commands-DkU0qliq.js} +0 -0
  431. /package/client/dist/assets/{commands-D_6B8lfU.js → commands-JWMfGDmr.js} +0 -0
  432. /package/client/dist/assets/{commands-DBc5llLi2.js → commands-RHOchN4n2.js} +0 -0
  433. /package/client/dist/assets/{commands-CQkdthjF.js → commands-u-4eEHCN.js} +0 -0
  434. /package/client/dist/assets/{commands-DhZNhSbl.js → commands-xHDDGfcP2.js} +0 -0
  435. /package/client/dist/assets/{cpp-SBF8SAh9.js → cpp-DEE5r4Pw.js} +0 -0
  436. /package/client/dist/assets/{csharp-Lzuq_1t-.js → csharp-BVXJUvbK.js} +0 -0
  437. /package/client/dist/assets/{csp-BEzxZqi1.js → csp-cXOF0JoV.js} +0 -0
  438. /package/client/dist/assets/{css-C3D3PKln.js → css-C_zQuAoy.js} +0 -0
  439. /package/client/dist/assets/{cypher-CQ3dEPmv.js → cypher-t95m_Q-O.js} +0 -0
  440. /package/client/dist/assets/{dart-DCPmxolI.js → dart-B4r1Tg-e.js} +0 -0
  441. /package/client/dist/assets/{dockerfile-B_2_aaTO.js → dockerfile-6mt7zHQw.js} +0 -0
  442. /package/client/dist/assets/{ecl-rADUeXsV.js → ecl-DEY_Fz_Q.js} +0 -0
  443. /package/client/dist/assets/{editor.api2-T7u8kQWG.js → editor.api2-C3B0tp2x.js} +0 -0
  444. /package/client/dist/assets/{elixir-DOd-TuJO.js → elixir-R6-q1c5t.js} +0 -0
  445. /package/client/dist/assets/{explore-BHEhNekP2.js → explore-B7fblXBb2.js} +0 -0
  446. /package/client/dist/assets/{explore-DAsroA482.js → explore-BHtEpoNN2.js} +0 -0
  447. /package/client/dist/assets/{explore-UwHHj2ux.js → explore-C0k8HrkN.js} +0 -0
  448. /package/client/dist/assets/{explore-DaXiW9-6.js → explore-CNBzrEPS.js} +0 -0
  449. /package/client/dist/assets/{explore-CWlAXx0f2.js → explore-D_mWBYCS2.js} +0 -0
  450. /package/client/dist/assets/{explore-DG1CtYqT.js → explore-Dahc1lOx.js} +0 -0
  451. /package/client/dist/assets/{explore-DMSGAnhK.js → explore-UvW1jEMa.js} +0 -0
  452. /package/client/dist/assets/{flow9-Bf7zg_j0.js → flow9-CNQvHBOt.js} +0 -0
  453. /package/client/dist/assets/{format-command-BHymDa4r.js → format-command-CuWuRvka.js} +0 -0
  454. /package/client/dist/assets/{fsharp-BqROZjbA.js → fsharp-vPZkFXwv.js} +0 -0
  455. /package/client/dist/assets/{go-oQTP5uLe.js → go-KUzBMYJ_.js} +0 -0
  456. /package/client/dist/assets/{graphql-CSHfTU3q.js → graphql-C3W0rCsD.js} +0 -0
  457. /package/client/dist/assets/{hcl-CeG-RoFJ.js → hcl-BOOMFSNX.js} +0 -0
  458. /package/client/dist/assets/{ini-B2Dv4ohc.js → ini-CFat1WJr.js} +0 -0
  459. /package/client/dist/assets/{integrations-CAF21FbQ.js → integrations-4KZnYECp.js} +0 -0
  460. /package/client/dist/assets/{integrations-CHCgning2.js → integrations-7W266oqF2.js} +0 -0
  461. /package/client/dist/assets/{integrations-B-JVE1_D.js → integrations-BNuauK3o.js} +0 -0
  462. /package/client/dist/assets/{integrations-BAujIDoE.js → integrations-CHy8tnpV.js} +0 -0
  463. /package/client/dist/assets/{integrations-DS5FFMes.js → integrations-Cl_wD5AI.js} +0 -0
  464. /package/client/dist/assets/{integrations-axZN4--n2.js → integrations-Cy8nZ_dv2.js} +0 -0
  465. /package/client/dist/assets/{integrations-CtsOpq2D2.js → integrations-zMqY4VU12.js} +0 -0
  466. /package/client/dist/assets/{java-aUDDeufb.js → java-Dee-CNAM.js} +0 -0
  467. /package/client/dist/assets/{julia-C5LbruO5.js → julia-CGNlLYuU.js} +0 -0
  468. /package/client/dist/assets/{kotlin-C6mOuSKk.js → kotlin-CY7lhknJ.js} +0 -0
  469. /package/client/dist/assets/{less-D5qC3caW.js → less-D0KN7hfJ.js} +0 -0
  470. /package/client/dist/assets/{lexon-Dr2La-fj.js → lexon-CuRJufPs.js} +0 -0
  471. /package/client/dist/assets/{lua-Zy6u5z6Z.js → lua-DHvH62Zf.js} +0 -0
  472. /package/client/dist/assets/{m3-C7XHeDz_.js → m3-tlthQ8Fo.js} +0 -0
  473. /package/client/dist/assets/{markdown-PiF7r-2h.js → markdown-Dbx1LgUZ.js} +0 -0
  474. /package/client/dist/assets/{mcp-B_nWlxZa2.js → mcp-CjVKXAhD2.js} +0 -0
  475. /package/client/dist/assets/{mcp-B8omp_Cd.js → mcp-Dcl-XxkR.js} +0 -0
  476. /package/client/dist/assets/{mcp-DTCCrYHz2.js → mcp-DtbxuH3V2.js} +0 -0
  477. /package/client/dist/assets/{mcp-DytBbASZ.js → mcp-H-gnQUdN.js} +0 -0
  478. /package/client/dist/assets/{mcp-D_oPS6Zc.js → mcp-N1nzp8oL.js} +0 -0
  479. /package/client/dist/assets/{mcp-Cb2jtHP72.js → mcp-XJNRfxVp2.js} +0 -0
  480. /package/client/dist/assets/{mcp-DPqm2C8-.js → mcp-sRmWE8WJ.js} +0 -0
  481. /package/client/dist/assets/{mips-nn07GiyE.js → mips-D_O3IUz_.js} +0 -0
  482. /package/client/dist/assets/{msdax-DaKFVMST.js → msdax-C_ZmCnRt.js} +0 -0
  483. /package/client/dist/assets/{mysql-C6d6xrbU.js → mysql-C-dCEYSX.js} +0 -0
  484. /package/client/dist/assets/{nav-Cibp2KWF.js → nav-40HzpIFb.js} +0 -0
  485. /package/client/dist/assets/{nav-DtTnF9xd.js → nav-8yPhBn00.js} +0 -0
  486. /package/client/dist/assets/{nav-Danf5sRf2.js → nav-B6PkGfTk2.js} +0 -0
  487. /package/client/dist/assets/{nav-Bqhyfbcj2.js → nav-BHqMLrS72.js} +0 -0
  488. /package/client/dist/assets/{nav-CQb9y1km.js → nav-CGy4yx3C.js} +0 -0
  489. /package/client/dist/assets/{nav-BAsYcqdw2.js → nav-CXEDcRdv2.js} +0 -0
  490. /package/client/dist/assets/{nav-BRrNlZkr.js → nav-EI_OhEAo.js} +0 -0
  491. /package/client/dist/assets/{objective-c-B6KMtI-k.js → objective-c-DZY9Aqxd.js} +0 -0
  492. /package/client/dist/assets/{pascal-DYr8MPE7.js → pascal-BVHLXoor.js} +0 -0
  493. /package/client/dist/assets/{pascaligo-B3pd-jJ_.js → pascaligo-XdG_6u3k.js} +0 -0
  494. /package/client/dist/assets/{perl-z2xUzoaL.js → perl-b9QV0BcD.js} +0 -0
  495. /package/client/dist/assets/{pgsql-DUvT-09-.js → pgsql-Du5FDOgT.js} +0 -0
  496. /package/client/dist/assets/{php-CGyOmJfy.js → php-WJD0z2Z_.js} +0 -0
  497. /package/client/dist/assets/{pla-CMqgvyD0.js → pla-CbciTf2w.js} +0 -0
  498. /package/client/dist/assets/{postiats-Dx5LUn4Z.js → postiats-C1QxmvVq.js} +0 -0
  499. /package/client/dist/assets/{powerquery-DazYxvJ6.js → powerquery-BEYDhPLZ.js} +0 -0
  500. /package/client/dist/assets/{powershell-B3nwlDka.js → powershell-CfaYw4XL.js} +0 -0
  501. /package/client/dist/assets/{protobuf-BGuu2u2s.js → protobuf-pwZEDOYa.js} +0 -0
  502. /package/client/dist/assets/{pug-Dbte1MXA.js → pug-5ftqSPVe.js} +0 -0
  503. /package/client/dist/assets/{qsharp-DJLwBOvG.js → qsharp-uI6qZMq4.js} +0 -0
  504. /package/client/dist/assets/{r-DmGBRSHj.js → r-BK54P1EG.js} +0 -0
  505. /package/client/dist/assets/{redis-VvUYn0a4.js → redis-DI0yd7kN.js} +0 -0
  506. /package/client/dist/assets/{redshift-6GdDrxg3.js → redshift-Dov26eyI.js} +0 -0
  507. /package/client/dist/assets/{restructuredtext-CfAB8aRU.js → restructuredtext-QqJ_1dC-.js} +0 -0
  508. /package/client/dist/assets/{ruby-CIYK6MXY.js → ruby-5WjveeVb.js} +0 -0
  509. /package/client/dist/assets/{rust-CTHZfjj9.js → rust-BzVSfqFH.js} +0 -0
  510. /package/client/dist/assets/{sb-CkKTdkz_.js → sb-DMIUfT-3.js} +0 -0
  511. /package/client/dist/assets/{scala-Bx-Wr9TM.js → scala-CSKA7lqt.js} +0 -0
  512. /package/client/dist/assets/{scheme-Dcfi6f83.js → scheme-CojOP2Qc.js} +0 -0
  513. /package/client/dist/assets/{scss-ByL-7PFQ.js → scss-DoBZGJG6.js} +0 -0
  514. /package/client/dist/assets/{shell-Csnb9Yqd.js → shell-YOaE4udl.js} +0 -0
  515. /package/client/dist/assets/{solidity-Dbw5-0QP.js → solidity-l3jSyVLu.js} +0 -0
  516. /package/client/dist/assets/{sophia-ZQ3saZQx.js → sophia-BhSGTaQJ.js} +0 -0
  517. /package/client/dist/assets/{sparql-BEtOel8u.js → sparql-qhk6QD9w.js} +0 -0
  518. /package/client/dist/assets/{sql-DGPDbzB7.js → sql-DoO3y21-.js} +0 -0
  519. /package/client/dist/assets/{st-GeW2MOgh.js → st-ChZAY8oG.js} +0 -0
  520. /package/client/dist/assets/{swift-BVYTN8jq.js → swift-D290Tr7_.js} +0 -0
  521. /package/client/dist/assets/{systemverilog-Deg2a8Lr.js → systemverilog-DsxzgJ-o.js} +0 -0
  522. /package/client/dist/assets/{tcl-6DnLmROF.js → tcl-BKDUHAAR.js} +0 -0
  523. /package/client/dist/assets/{terminal-CDiOAmBd2.js → terminal-BRm03iFA2.js} +0 -0
  524. /package/client/dist/assets/{terminal-CJN-mQMc.js → terminal-De2Brd23.js} +0 -0
  525. /package/client/dist/assets/{terminal-CYB4TiAd.js → terminal-DxQWCqSD2.js} +0 -0
  526. /package/client/dist/assets/{terminal-DsaDTq5N2.js → terminal-WSAvHXoU.js} +0 -0
  527. /package/client/dist/assets/{terminal-DTQ_dPqi2.js → terminal-Z7KsDM_n.js} +0 -0
  528. /package/client/dist/assets/{terminal-58ReNaya.js → terminal-cqfd3EDV.js} +0 -0
  529. /package/client/dist/assets/{terminal-DawP8xNL.js → terminal-xGbCZJHg.js} +0 -0
  530. /package/client/dist/assets/{tickets-DoRTUYRT.js → tickets-B7zT4IRf.js} +0 -0
  531. /package/client/dist/assets/{tickets-DBfFePwk2.js → tickets-BoXom7l8.js} +0 -0
  532. /package/client/dist/assets/{tickets-DvohTziT2.js → tickets-C3b8cHhd2.js} +0 -0
  533. /package/client/dist/assets/{tickets-Da15iaRw.js → tickets-CFXnJsYF.js} +0 -0
  534. /package/client/dist/assets/{tickets-CujsZvkf.js → tickets-CWYFvx1W2.js} +0 -0
  535. /package/client/dist/assets/{tickets-Df6pee-O2.js → tickets-DTHo9c3C.js} +0 -0
  536. /package/client/dist/assets/{tickets-CNvIilmP.js → tickets-SuX_HkK4.js} +0 -0
  537. /package/client/dist/assets/{twig-XbbXW9Yz.js → twig-UpZQaM8G.js} +0 -0
  538. /package/client/dist/assets/{typespec-CRlV8GhI.js → typespec-DzaKvN8i.js} +0 -0
  539. /package/client/dist/assets/{vb-BHE2izPH.js → vb-CZpbb7tk.js} +0 -0
  540. /package/client/dist/assets/{wgsl-Bf5vkfmY.js → wgsl-CNt3OIvl.js} +0 -0
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ACTIVE_PR_DECISIONS = exports.TERMINAL_PR_DECISIONS = void 0;
4
+ exports.isTerminalPrDecision = isTerminalPrDecision;
5
+ exports.createPrDelivery = createPrDelivery;
6
+ exports.getPrDelivery = getPrDelivery;
7
+ exports.getActivePrDeliveryByRail = getActivePrDeliveryByRail;
8
+ exports.listActivePrDeliveries = listActivePrDeliveries;
9
+ exports.transitionDecision = transitionDecision;
10
+ exports.toPrDeliverySnapshot = toPrDeliverySnapshot;
11
+ exports.toRailPrStateMessage = toRailPrStateMessage;
12
+ exports.toPrDecisionCardEnvelope = toPrDecisionCardEnvelope;
13
+ const ids_1 = require("./ids");
14
+ /** States after which the delivery is closed (no further decision possible). */
15
+ exports.TERMINAL_PR_DECISIONS = new Set(['merged', 'discarded']);
16
+ /** States in which the delivery still awaits (or is executing) a user decision. */
17
+ exports.ACTIVE_PR_DECISIONS = new Set([
18
+ 'building',
19
+ 'on_review',
20
+ 'pr_draft',
21
+ 'pr_ready',
22
+ 'pr_failed',
23
+ ]);
24
+ function isTerminalPrDecision(s) {
25
+ return exports.TERMINAL_PR_DECISIONS.has(s);
26
+ }
27
+ /**
28
+ * Insert a new delivery row for a rail launch. The row starts at
29
+ * decision='building', pr_state='none' with empty branches/worktree_ids —
30
+ * settle patches those via transitionDecision.
31
+ */
32
+ function createPrDelivery(db, input) {
33
+ const id = input.id ?? (0, ids_1.newId)();
34
+ db.prepare(`INSERT INTO rail_pr_deliveries (
35
+ id, rail_index, loop_id, rail_key, ticket_ids, base_branch,
36
+ loop_name, origin_surface, origin_conversation_id
37
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.railIndex, input.loopId ?? null, input.railKey, JSON.stringify(input.ticketIds), input.baseBranch, input.loopName, input.originSurface, input.originConversationId ?? null);
38
+ return getPrDelivery(db, id);
39
+ }
40
+ function getPrDelivery(db, id) {
41
+ return db.prepare('SELECT * FROM rail_pr_deliveries WHERE id = ?').get(id);
42
+ }
43
+ /**
44
+ * The newest non-terminal delivery for a rail slot (a slot can be relaunched;
45
+ * older terminal rows are history). Used by the relaunch-collision guard and
46
+ * the GET /rails snapshot.
47
+ */
48
+ function getActivePrDeliveryByRail(db, railIndex) {
49
+ return db
50
+ .prepare(`SELECT * FROM rail_pr_deliveries
51
+ WHERE rail_index = ? AND decision NOT IN ('merged','discarded')
52
+ ORDER BY created_at DESC, rowid DESC LIMIT 1`)
53
+ .get(railIndex);
54
+ }
55
+ /** Every non-terminal delivery — hydrates the GET /rails prDeliveries snapshot. */
56
+ function listActivePrDeliveries(db) {
57
+ return db
58
+ .prepare(`SELECT * FROM rail_pr_deliveries
59
+ WHERE decision NOT IN ('merged','discarded')
60
+ ORDER BY rail_index, created_at DESC, rowid DESC`)
61
+ .all();
62
+ }
63
+ // Column allow-list — patch keys are interpolated into the SET clause, so gate
64
+ // them to prevent any future caller injecting SQL via an object key (values
65
+ // are always parameterized). Mirrors loop-runs-store's COUNTER_COLUMNS.
66
+ const PATCH_COLUMNS = {
67
+ branch: 'branch',
68
+ prUrl: 'pr_url',
69
+ prNumber: 'pr_number',
70
+ prState: 'pr_state',
71
+ branches: 'branches',
72
+ worktreeIds: 'worktree_ids',
73
+ runIds: 'run_ids',
74
+ };
75
+ function patchValue(key, patch) {
76
+ const raw = patch[key];
77
+ if (key === 'branches' || key === 'worktreeIds' || key === 'runIds')
78
+ return JSON.stringify(raw);
79
+ return raw;
80
+ }
81
+ /**
82
+ * COMPARE-AND-SET decision transition: one atomic
83
+ * `UPDATE … WHERE id = ? AND decision = ?` (no read-modify-write), so two
84
+ * surfaces racing on the same delivery cannot both win. Returns `false` (row
85
+ * untouched) when `expected` is stale — the caller maps that to a 409.
86
+ * `patch` may set delivery columns alongside the transition; `updated_at` is
87
+ * always bumped.
88
+ */
89
+ function transitionDecision(db, id, expected, next, patch = {}) {
90
+ const keys = Object.keys(patch).filter((k) => patch[k] !== undefined);
91
+ const patchClause = keys.map((k) => `, ${PATCH_COLUMNS[k]} = ?`).join('');
92
+ const values = keys.map((k) => patchValue(k, patch));
93
+ return (db
94
+ .prepare(`UPDATE rail_pr_deliveries
95
+ SET decision = ?, updated_at = datetime('now')${patchClause}
96
+ WHERE id = ? AND decision = ?`)
97
+ .run(next, ...values, id, expected).changes > 0);
98
+ }
99
+ function parseJsonArray(raw) {
100
+ try {
101
+ const parsed = JSON.parse(raw);
102
+ return Array.isArray(parsed) ? parsed : [];
103
+ }
104
+ catch {
105
+ return [];
106
+ }
107
+ }
108
+ function toPrDeliverySnapshot(row) {
109
+ return {
110
+ id: row.id,
111
+ railIndex: row.rail_index,
112
+ loopId: row.loop_id,
113
+ railKey: row.rail_key,
114
+ ticketIds: parseJsonArray(row.ticket_ids),
115
+ baseBranch: row.base_branch,
116
+ branch: row.branch,
117
+ prUrl: row.pr_url,
118
+ prNumber: row.pr_number,
119
+ prState: row.pr_state,
120
+ decision: row.decision,
121
+ branches: parseJsonArray(row.branches),
122
+ loopName: row.loop_name,
123
+ worktreeIds: parseJsonArray(row.worktree_ids),
124
+ runIds: parseJsonArray(row.run_ids ?? '[]'),
125
+ originSurface: row.origin_surface,
126
+ originConversationId: row.origin_conversation_id,
127
+ createdAt: row.created_at,
128
+ updatedAt: row.updated_at,
129
+ };
130
+ }
131
+ /**
132
+ * Build the durable `rail.pr_state` broadcast payload from a delivery snapshot
133
+ * — the ONE message shape every mutation of the row re-broadcasts (launch
134
+ * insert, build-settle, decision-endpoint transitions), so both decision
135
+ * surfaces converge on the same state.
136
+ */
137
+ function toRailPrStateMessage(projectId, snap) {
138
+ return {
139
+ type: 'rail.pr_state',
140
+ projectId,
141
+ railIndex: snap.railIndex,
142
+ prDeliveryId: snap.id,
143
+ railKey: snap.railKey,
144
+ ticketIds: snap.ticketIds,
145
+ baseBranch: snap.baseBranch,
146
+ branch: snap.branch,
147
+ prUrl: snap.prUrl,
148
+ prNumber: snap.prNumber,
149
+ prState: snap.prState,
150
+ decision: snap.decision,
151
+ runIds: snap.runIds,
152
+ originConversationId: snap.originConversationId,
153
+ };
154
+ }
155
+ /**
156
+ * Build the agent-chat PR-decision card envelope from a delivery snapshot —
157
+ * the ONE mapper both card writers (rail-isolated-launch's origin-card sync
158
+ * and rail-pr-decision's finalizeTransition) share, so the persisted card and
159
+ * the `agent_pr_decision` broadcast can never drift between the two sites.
160
+ */
161
+ function toPrDecisionCardEnvelope(projectId, snap) {
162
+ return {
163
+ kind: 'pr_decision',
164
+ prDeliveryId: snap.id,
165
+ railIndex: snap.railIndex,
166
+ projectId,
167
+ baseBranch: snap.baseBranch,
168
+ ticketIds: snap.ticketIds,
169
+ decision: snap.decision,
170
+ prUrl: snap.prUrl,
171
+ prState: snap.prState,
172
+ branch: snap.branch,
173
+ runIds: snap.runIds,
174
+ };
175
+ }
@@ -9,6 +9,8 @@ exports.setRailWorktreeRunId = setRailWorktreeRunId;
9
9
  exports.listRailWorktrees = listRailWorktrees;
10
10
  exports.listNonTerminalRailWorktrees = listNonTerminalRailWorktrees;
11
11
  exports.deleteRailWorktree = deleteRailWorktree;
12
+ exports.listRailWorktreesForTicket = listRailWorktreesForTicket;
13
+ exports.railWorktreeBranchExistsForTicket = railWorktreeBranchExistsForTicket;
12
14
  /** States after which the worktree is done (eligible for cleanup/reconciliation). */
13
15
  exports.TERMINAL_MERGE_STATES = new Set(['merged', 'needs-review', 'failed']);
14
16
  function isTerminalMergeState(s) {
@@ -50,3 +52,19 @@ function listNonTerminalRailWorktrees(db) {
50
52
  function deleteRailWorktree(db, id) {
51
53
  return db.prepare('DELETE FROM rail_worktrees WHERE id = ?').run(id).changes > 0;
52
54
  }
55
+ /** Every rail allocation ever made for a ticket, newest first — the recovery
56
+ * input for create-pr's pre-flight: when a delivery row records a branch that
57
+ * no longer exists, any OTHER branch a rail allocated for the same ticket that
58
+ * still exists with commits ahead of base is the real carrier of the work. */
59
+ function listRailWorktreesForTicket(db, ticketId) {
60
+ return db
61
+ .prepare('SELECT * FROM rail_worktrees WHERE ticket_id = ? ORDER BY created_at DESC, rowid DESC')
62
+ .all(ticketId);
63
+ }
64
+ /** True when a prior rail allocation for this ticket used exactly this branch —
65
+ * i.e. an existing branch of that name is OURS to resume (partial work from a
66
+ * stopped run), not a foreign collision to suffix away from. */
67
+ function railWorktreeBranchExistsForTicket(db, ticketId, branch) {
68
+ return (db.prepare('SELECT 1 FROM rail_worktrees WHERE ticket_id = ? AND branch = ? LIMIT 1').get(ticketId, branch) !==
69
+ undefined);
70
+ }
@@ -6,6 +6,8 @@ const rails_store_1 = require("./rails-store");
6
6
  const queue_manager_1 = require("./queue-manager");
7
7
  const provider_selection_1 = require("./provider-selection");
8
8
  const feature_flags_1 = require("./feature-flags");
9
+ const file_provenance_1 = require("./file-provenance");
10
+ const file_story_1 = require("./file-story");
9
11
  const loops_store_1 = require("./loops-store");
10
12
  const loop_runs_store_1 = require("./loop-runs-store");
11
13
  const providers_1 = require("./providers");
@@ -16,8 +18,12 @@ const loop_constants_1 = require("./loop-constants");
16
18
  const loop_command_catalog_1 = require("./loop-command-catalog");
17
19
  const loop_graph_1 = require("./loop-graph");
18
20
  const rail_isolation_1 = require("./rail-isolation");
21
+ const rail_pr_store_1 = require("./rail-pr-store");
22
+ const loop_effect_1 = require("./loop-effect");
23
+ const rail_pr_decision_1 = require("./rail-pr-decision");
19
24
  const rail_isolated_launch_1 = require("./rail-isolated-launch");
20
25
  const worktree_manager_1 = require("./worktree-manager");
26
+ const pr_publisher_1 = require("./pr-publisher");
21
27
  const ids_1 = require("./ids");
22
28
  const VALID_MODES = new Set(['implement', 'batch-implement', 'ultracode', 'loop']);
23
29
  // Models the ultracode picker exposes (Claude aliases). Mirrors the client
@@ -85,17 +91,103 @@ function createRailsRouter() {
85
91
  const counts = (0, loop_runs_store_1.getRunEventCounts)(c.db, run.id);
86
92
  activeLoopRuns[run.rail_index] = { loopRunId: run.id, loopId: run.loop_id, loopName: run.loop_name, provider: run.provider, model: run.model, iteration: run.iteration_count, startedAt: run.started_at, steps: counts.steps, lines: counts.lines };
87
93
  }
88
- res.json({ rails, activeJobs, activeLoopRuns });
94
+ // Pending ask-first PR decisions (safe-pr-review-flow): the newest ACTIVE
95
+ // (non-terminal) delivery per rail slot, so a refreshed client re-renders
96
+ // the decision surface without waiting for a broadcast. The store lists
97
+ // newest-first within each rail — keep the first per index.
98
+ const prDeliveries = {};
99
+ for (const row of (0, rail_pr_store_1.listActivePrDeliveries)(c.db)) {
100
+ if (!(row.rail_index in prDeliveries))
101
+ prDeliveries[row.rail_index] = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
102
+ }
103
+ res.json({ rails, activeJobs, activeLoopRuns, prDeliveries });
89
104
  }
90
105
  catch (err) {
91
106
  console.error('[rails-router] get rails error:', err);
92
107
  res.status(500).json({ error: 'Failed to fetch rails' });
93
108
  }
94
109
  });
110
+ // POST /rails — create a new rail slot (dynamic rails). Body: { name? }.
111
+ // Allocates the lowest free index; capped at MAX_RAILS per project so the
112
+ // railIndex-keyed maps (metrics, PR deliveries, worktree progress) stay
113
+ // bounded. Broadcast rides the existing rail.updated shape (changed:'name')
114
+ // so every client — including the mobile companion — adopts the new slot
115
+ // without a new wire message.
116
+ router.post('/', (req, res) => {
117
+ const c = ctx(req);
118
+ const body = req.body ?? {};
119
+ const name = body.name;
120
+ if (name !== undefined && name !== null && typeof name !== 'string') {
121
+ res.status(400).json({ error: 'name must be a string or null' });
122
+ return;
123
+ }
124
+ if (typeof name === 'string' && name.length > 60) {
125
+ res.status(400).json({ error: 'name must be 60 characters or fewer' });
126
+ return;
127
+ }
128
+ try {
129
+ if ((0, rails_store_1.railCount)(c.db) >= rails_store_1.MAX_RAILS) {
130
+ res.status(400).json({ error: 'rail_limit_reached', maxRails: rails_store_1.MAX_RAILS });
131
+ return;
132
+ }
133
+ const rail = (0, rails_store_1.createRail)(c.db, typeof name === 'string' ? name : null);
134
+ broadcastRailUpdated(c, rail.railIndex, 'name');
135
+ res.status(201).json({ rail });
136
+ }
137
+ catch (err) {
138
+ console.error('[rails-router] create rail error:', err);
139
+ res.status(500).json({ error: 'Failed to create rail' });
140
+ }
141
+ });
142
+ // DELETE /rails/:railIndex — remove a rail slot. Guarded: the rail must
143
+ // exist, hold no tickets, have no active job/loop run, no undecided PR
144
+ // delivery, and must not be the last remaining rail. Indices are identity —
145
+ // deleting a middle rail leaves a gap (never re-numbered).
146
+ router.delete('/:railIndex', (req, res) => {
147
+ const railIndex = parseInt(req.params.railIndex, 10);
148
+ if (isNaN(railIndex) || railIndex < 0 || railIndex >= rails_store_1.MAX_RAILS) {
149
+ res.status(400).json({ error: 'Invalid rail index' });
150
+ return;
151
+ }
152
+ const c = ctx(req);
153
+ try {
154
+ if (!(0, rails_store_1.railExists)(c.db, railIndex)) {
155
+ res.status(404).json({ error: 'Rail not found' });
156
+ return;
157
+ }
158
+ if ((0, rails_store_1.railCount)(c.db) <= 1) {
159
+ res.status(400).json({ error: 'cannot_delete_last_rail' });
160
+ return;
161
+ }
162
+ const hasActiveJob = Array.from(c.railJobs.values()).some((m) => m.railIndex === railIndex);
163
+ const hasActiveRun = Array.from(c.railLoopRuns.values()).some((m) => m.railIndex === railIndex);
164
+ if (hasActiveJob || hasActiveRun) {
165
+ res.status(409).json({ error: 'rail_active' });
166
+ return;
167
+ }
168
+ if ((0, rails_store_1.getRail)(c.db, railIndex).ticketIds.length > 0) {
169
+ res.status(409).json({ error: 'rail_not_empty' });
170
+ return;
171
+ }
172
+ const pending = (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex);
173
+ if (pending) {
174
+ res.status(409).json({ error: 'pr_decision_pending', prDeliveryId: pending.id });
175
+ return;
176
+ }
177
+ (0, rails_store_1.deleteRail)(c.db, railIndex);
178
+ const msg = { type: 'rail.removed', projectId: c.project.id, railIndex };
179
+ c.broadcast(msg);
180
+ res.json({ ok: true, railIndex });
181
+ }
182
+ catch (err) {
183
+ console.error('[rails-router] delete rail error:', err);
184
+ res.status(500).json({ error: 'Failed to delete rail' });
185
+ }
186
+ });
95
187
  // PUT /rails/:railIndex/tickets — set ticket assignments for a rail
96
188
  router.put('/:railIndex/tickets', (req, res) => {
97
189
  const railIndex = parseInt(req.params.railIndex, 10);
98
- if (isNaN(railIndex) || railIndex < 0) {
190
+ if (isNaN(railIndex) || railIndex < 0 || railIndex >= rails_store_1.MAX_RAILS) {
99
191
  res.status(400).json({ error: 'Invalid rail index' });
100
192
  return;
101
193
  }
@@ -130,7 +222,7 @@ function createRailsRouter() {
130
222
  // Body: { profileName: string | null } (null = force legacy mode for this rail)
131
223
  router.put('/:railIndex/profile', (req, res) => {
132
224
  const railIndex = parseInt(req.params.railIndex, 10);
133
- if (isNaN(railIndex) || railIndex < 0) {
225
+ if (isNaN(railIndex) || railIndex < 0 || railIndex >= rails_store_1.MAX_RAILS) {
134
226
  res.status(400).json({ error: 'Invalid rail index' });
135
227
  return;
136
228
  }
@@ -159,7 +251,7 @@ function createRailsRouter() {
159
251
  // Body: { aiEngine: string | null } (null = use the project's primary provider)
160
252
  router.put('/:railIndex/engine', (req, res) => {
161
253
  const railIndex = parseInt(req.params.railIndex, 10);
162
- if (isNaN(railIndex) || railIndex < 0) {
254
+ if (isNaN(railIndex) || railIndex < 0 || railIndex >= rails_store_1.MAX_RAILS) {
163
255
  res.status(400).json({ error: 'Invalid rail index' });
164
256
  return;
165
257
  }
@@ -192,7 +284,7 @@ function createRailsRouter() {
192
284
  // Body: { name: string | null } (empty/null clears it back to the default label)
193
285
  router.put('/:railIndex/name', (req, res) => {
194
286
  const railIndex = parseInt(req.params.railIndex, 10);
195
- if (isNaN(railIndex) || railIndex < 0) {
287
+ if (isNaN(railIndex) || railIndex < 0 || railIndex >= rails_store_1.MAX_RAILS) {
196
288
  res.status(400).json({ error: 'Invalid rail index' });
197
289
  return;
198
290
  }
@@ -225,16 +317,29 @@ function createRailsRouter() {
225
317
  // POST /rails/:railIndex/launch — launch job(s) for a rail
226
318
  router.post('/:railIndex/launch', async (req, res) => {
227
319
  const railIndex = parseInt(req.params.railIndex, 10);
228
- if (isNaN(railIndex) || railIndex < 0) {
320
+ if (isNaN(railIndex) || railIndex < 0 || railIndex >= rails_store_1.MAX_RAILS) {
229
321
  res.status(400).json({ error: 'Invalid rail index' });
230
322
  return;
231
323
  }
232
324
  let { mode = 'implement' } = req.body ?? {};
233
- const { profileName, aiEngine, model, loopId, reasoning_effort } = req.body ?? {};
325
+ const { profileName, aiEngine, model, loopId: rawLoopId, reasoning_effort, originConversationId, originSurface } = req.body ?? {};
326
+ let loopId = rawLoopId;
327
+ // Origin link (safe-pr-review-flow): an agent-chat/MCP launch tags itself so
328
+ // the PR decision can later be posted back into the launching conversation.
329
+ // Both fields are optional; malformed values are rejected outright.
330
+ if (originConversationId !== undefined && originConversationId !== null) {
331
+ if (typeof originConversationId !== 'string' || !/^[A-Za-z0-9-]{1,64}$/.test(originConversationId)) {
332
+ res.status(400).json({ error: 'originConversationId must be 1-64 chars of [A-Za-z0-9-]' });
333
+ return;
334
+ }
335
+ }
336
+ if (originSurface !== undefined && originSurface !== 'dashboard' && originSurface !== 'agent-chat') {
337
+ res.status(400).json({ error: "originSurface must be 'dashboard' or 'agent-chat'" });
338
+ return;
339
+ }
234
340
  // rails-as-loops: a FACTORY loop id (`factory:implement` etc.) maps to its
235
- // legacy mode and runs through the EXISTING engine (QueueManager) — the rail
236
- // "picks a Loop", the plumbing is unchanged. A CUSTOM loop id keeps mode='loop'
237
- // (LoopRunManager). Legacy callers that still send a bare `mode` are unchanged.
341
+ // legacy mode for validation/back-compat; the loop branch below still runs
342
+ // it through the LoopRunManager. A CUSTOM loop id keeps mode='loop'.
238
343
  if (typeof loopId === 'string' && (0, loop_factory_1.isFactoryLoopId)(loopId)) {
239
344
  const fmode = (0, loop_factory_1.factoryLoopMode)(loopId);
240
345
  if (!fmode) {
@@ -247,6 +352,15 @@ function createRailsRouter() {
247
352
  res.status(400).json({ error: 'mode must be "implement", "batch-implement", "ultracode" or "loop"' });
248
353
  return;
249
354
  }
355
+ // A bare legacy mode (MCP tools, mobile, direct REST — no loopId) must run
356
+ // through the SAME factory loop the dashboard sends, so worktree isolation
357
+ // and the ask-first PR flow apply identically regardless of the launch door.
358
+ // Without this, an agent-launched implement lands in the bare QueueManager
359
+ // branch: shared cwd, SPECRAILS_GIT_AUTO=false, no delivery row — stranded
360
+ // uncommitted work. Loops off ⇒ legacy QueueManager path, unchanged.
361
+ if ((0, feature_flags_1.isLoopsEnabled)() && (typeof loopId !== 'string' || !loopId) && mode !== 'loop') {
362
+ loopId = (0, loop_factory_1.factoryLoopForMode)(mode)?.id;
363
+ }
250
364
  if (mode === 'loop' && !(0, feature_flags_1.isLoopsEnabled)()) {
251
365
  res.status(403).json({ error: 'Loops are disabled on this server' });
252
366
  return;
@@ -259,8 +373,9 @@ function createRailsRouter() {
259
373
  return;
260
374
  }
261
375
  }
262
- // Interactive in-job chat is ON by default for every Freestyle (ultracode)
263
- // job whenever the feature is enabled — the per-rail toggle is gone. A
376
+ // Interactive in-job chat is ON by default for EVERY claude job — the
377
+ // spawn-time gate in QueueManager (kill-switch + persistent-stdin
378
+ // capability) decides, so the launch no longer passes an explicit flag. A
264
379
  // legacy `interactive` body param is accepted and ignored (wire compat).
265
380
  const c = ctx(req);
266
381
  const rail = (0, rails_store_1.getRail)(c.db, railIndex);
@@ -268,6 +383,24 @@ function createRailsRouter() {
268
383
  res.status(400).json({ error: 'Rail has no tickets assigned' });
269
384
  return;
270
385
  }
386
+ // Concurrent-launch safety (parallel rails): a ticket already worked by an
387
+ // ACTIVE run — this rail relaunched mid-run, or the same ticket sitting on
388
+ // two rails — must not spawn a second concurrent writer. The per-ticket
389
+ // worktree path is keyed by ticketId, so a duplicate launch would silently
390
+ // reuse (and corrupt) the in-flight run's checkout. 409 so Launch-all and
391
+ // agent-driven fan-outs surface a clean per-rail skip instead of a clash.
392
+ const inFlightTickets = new Set();
393
+ for (const meta of c.railJobs.values())
394
+ for (const id of meta.ticketIds)
395
+ inFlightTickets.add(id);
396
+ for (const meta of c.railLoopRuns.values())
397
+ for (const id of meta.ticketIds)
398
+ inFlightTickets.add(id);
399
+ const inFlightOverlap = rail.ticketIds.filter((id) => inFlightTickets.has(id));
400
+ if (inFlightOverlap.length > 0) {
401
+ res.status(409).json({ error: 'tickets_in_flight', ticketIds: inFlightOverlap });
402
+ return;
403
+ }
271
404
  // AI engine precedence: explicit body param > stored rail engine > primary.
272
405
  // `undefined`/empty in both means "run on the project's primary provider".
273
406
  const requestedEngine = aiEngine === undefined ? (rail.aiEngine ?? undefined) : aiEngine;
@@ -379,7 +512,22 @@ function createRailsRouter() {
379
512
  // repo, an unborn HEAD, or a worktree-allocation failure all fall through to
380
513
  // the shared-cwd path below. See rail-isolation.ts.
381
514
  let isolationUnavailable;
382
- if ((0, rail_isolation_1.isolationApplies)({ loopsEnabled: (0, feature_flags_1.isLoopsEnabled)(), scope, ticketCount: rail.ticketIds.length, readOnly: false })) {
515
+ // Read-only vs mutating is DERIVED from the loop's nodes (see loop-effect),
516
+ // not a user flag — a content-read-only loop (no ai-step/shell) never writes,
517
+ // so it is not isolated; anything that can write is.
518
+ const loopReadOnly = (0, loop_effect_1.classifyLoopEffect)(loopGraph) === 'read-only';
519
+ if ((0, rail_isolation_1.isolationApplies)({ loopsEnabled: (0, feature_flags_1.isLoopsEnabled)(), scope, ticketCount: rail.ticketIds.length, readOnly: loopReadOnly })) {
520
+ // Relaunch collision (ask-first PR delivery): a still-undecided
521
+ // delivery on this slot references the slot's ticket branches, and a
522
+ // relaunch would append new commits to them (createWorktree resumes
523
+ // existing branches). Block until the user resolves or discards it.
524
+ if ((0, rail_isolation_1.isRailPrDeliveryEnabled)()) {
525
+ const pending = (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex);
526
+ if (pending) {
527
+ res.status(409).json({ error: 'pr_decision_pending', prDeliveryId: pending.id });
528
+ return;
529
+ }
530
+ }
383
531
  // Worktree isolation needs a git repo WITH at least one commit (an
384
532
  // unborn HEAD can't be branched). Fall back (with a message) otherwise.
385
533
  const status = await (0, worktree_manager_1.repoIsolationStatus)(worktree_manager_1.defaultGitRunner, c.project.path);
@@ -391,7 +539,9 @@ function createRailsRouter() {
391
539
  try {
392
540
  const ids = await (0, rail_isolated_launch_1.launchIsolatedRail)({
393
541
  ctx: c, railIndex, ticketIds: [...rail.ticketIds], loopId, loopName, loopGraph,
394
- provider: loopProvider, model: loopModel, effort,
542
+ provider: loopProvider, model: loopModel, effort, scope,
543
+ originSurface: originSurface ?? 'dashboard',
544
+ originConversationId: originConversationId ?? null,
395
545
  });
396
546
  res.status(202).json({ loopRunIds: ids, railIndex, mode, isolated: true });
397
547
  return;
@@ -409,6 +559,36 @@ function createRailsRouter() {
409
559
  const loopRunIds = [];
410
560
  const launchLoopRun = (runId, ticketIds, spec) => {
411
561
  c.railLoopRuns.set(runId, { railIndex, ticketIds });
562
+ // Code-Explorer provenance for shared-cwd loop runs (isolated runs
563
+ // record inside rail-isolated-launch): snapshot the REPO before the
564
+ // run, diff + record at settle. Loop runs settle outside QueueManager,
565
+ // so without this they leave no file_provenance at all. Best-effort;
566
+ // diffs the repo (never the workspace) exactly like QueueManager.
567
+ const provenanceRepoDir = loopExec.relocated && loopExec.repoDir ? loopExec.repoDir : loopExec.cwd;
568
+ let provenanceSnapshot = null;
569
+ if ((0, feature_flags_1.isCodeExplorerEnabled)()) {
570
+ try {
571
+ provenanceSnapshot = (0, file_provenance_1.snapshotWorkingTree)(provenanceRepoDir);
572
+ }
573
+ catch (err) {
574
+ console.warn(`[rails-router] provenance snapshot failed: ${err.message}`);
575
+ }
576
+ }
577
+ let provenanceRecorded = false;
578
+ const recordRunProvenance = () => {
579
+ if (provenanceRecorded)
580
+ return;
581
+ provenanceRecorded = true;
582
+ (0, file_story_1.recordLoopRunProvenance)({
583
+ db: c.db,
584
+ projectId: c.project.id,
585
+ runId,
586
+ ticketId: ticketIds[0] ?? null,
587
+ repoDir: provenanceRepoDir,
588
+ snapshot: provenanceSnapshot,
589
+ broadcast: (msg) => c.broadcast(msg),
590
+ });
591
+ };
412
592
  c.loopRunManager
413
593
  .run({
414
594
  runId,
@@ -426,9 +606,13 @@ function createRailsRouter() {
426
606
  model: loopModel,
427
607
  effort,
428
608
  })
429
- .then((r) => c.onLoopRunFinished(r.runId, r.outcome))
609
+ .then((r) => {
610
+ recordRunProvenance();
611
+ c.onLoopRunFinished(r.runId, r.outcome);
612
+ })
430
613
  .catch((err) => {
431
614
  console.error('[rails-router] loop run failed:', err);
615
+ recordRunProvenance();
432
616
  c.onLoopRunFinished(runId, 'failed');
433
617
  });
434
618
  loopRunIds.push(runId);
@@ -475,7 +659,9 @@ function createRailsRouter() {
475
659
  profileName: null,
476
660
  provider: 'claude',
477
661
  ...(ultracodeModel ? { model: ultracodeModel } : {}),
478
- ...((0, feature_flags_1.isInteractiveJobsEnabled)() ? { interactive: true } : {}),
662
+ // No explicit `interactive` — QueueManager's spawn-time default
663
+ // (kill-switch + persistent-stdin capability) covers it, and the
664
+ // decision survives a restart that way.
479
665
  });
480
666
  jobIds.push(job.id);
481
667
  c.railJobs.set(job.id, { railIndex, mode, ticketIds: [ticketId] });
@@ -538,7 +724,7 @@ function createRailsRouter() {
538
724
  // POST /rails/:railIndex/stop — kill the running job for a rail
539
725
  router.post('/:railIndex/stop', (req, res) => {
540
726
  const railIndex = parseInt(req.params.railIndex, 10);
541
- if (isNaN(railIndex) || railIndex < 0) {
727
+ if (isNaN(railIndex) || railIndex < 0 || railIndex >= rails_store_1.MAX_RAILS) {
542
728
  res.status(400).json({ error: 'Invalid rail index' });
543
729
  return;
544
730
  }
@@ -601,5 +787,43 @@ function createRailsRouter() {
601
787
  }
602
788
  res.json({ ok: true, jobIds: targetJobIds, loopRunIds: targetLoopRunIds, canceled: canceledCount });
603
789
  });
790
+ // POST /rails/pr-decision — the ONE decision action (safe-pr-review-flow) both
791
+ // surfaces (dashboard rail row + agent-chat card) call on a rail_pr_deliveries
792
+ // row: create-pr | publish | discard | poll-merge, compare-and-set-guarded by
793
+ // expectedDecision (a raced concurrent answer loses with 409 stale_decision).
794
+ // Replaces the stateless v1 POST /rails/pr-review passthrough. The route only
795
+ // validates and delegates — the action logic lives in rail-pr-decision.ts.
796
+ // specrails never merges — the engineer owns the merge.
797
+ router.post('/pr-decision', async (req, res) => {
798
+ const c = ctx(req);
799
+ const { prDeliveryId, action, expectedDecision } = req.body ?? {};
800
+ if (typeof prDeliveryId !== 'string' || !prDeliveryId) {
801
+ res.status(400).json({ error: 'prDeliveryId is required' });
802
+ return;
803
+ }
804
+ if (!(0, rail_pr_decision_1.isPrDecisionAction)(action)) {
805
+ res.status(400).json({ error: "action must be 'create-pr', 'publish', 'discard' or 'poll-merge'" });
806
+ return;
807
+ }
808
+ if (typeof expectedDecision !== 'string' || !expectedDecision) {
809
+ res.status(400).json({ error: 'expectedDecision is required' });
810
+ return;
811
+ }
812
+ try {
813
+ const result = await (0, rail_pr_decision_1.executePrDecision)({
814
+ db: c.db,
815
+ project: { id: c.project.id, slug: c.project.slug, path: c.project.path },
816
+ git: worktree_manager_1.defaultGitRunner,
817
+ exec: pr_publisher_1.defaultExec,
818
+ broadcast: c.broadcast,
819
+ jiraSyncManager: c.jiraSyncManager,
820
+ }, { prDeliveryId, action, expectedDecision });
821
+ res.status(result.status).json(result.body);
822
+ }
823
+ catch (err) {
824
+ console.error('[rails-router] pr-decision error:', err);
825
+ res.status(500).json({ error: 'pr-decision failed', detail: err.message });
826
+ }
827
+ });
604
828
  return router;
605
829
  }