specrails-desktop 2.30.2 → 2.31.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 (462) hide show
  1. package/README.md +28 -24
  2. package/client/dist/assets/{ActivityFeedPage-9DZOvIcY.js → ActivityFeedPage-CAhFRUO4.js} +1 -1
  3. package/client/dist/assets/{AgentBrowserCapture-DqyHbzk7.js → AgentBrowserCapture-Ct4G5lsE.js} +1 -1
  4. package/client/dist/assets/AgentModeCodePane-DQt9WIvu.js +2 -0
  5. package/client/dist/assets/{AgentModeJobsPane-CTIHMUKN.js → AgentModeJobsPane-podaJVl9.js} +1 -1
  6. package/client/dist/assets/AgentsPage-DTZdbW80.js +87 -0
  7. package/client/dist/assets/AnalyticsPage-BskgGPm0.js +1 -0
  8. package/client/dist/assets/CodePage-CvtYo1DU.js +2 -0
  9. package/client/dist/assets/{DesktopAnalyticsPage-CkXUFj3F.js → DesktopAnalyticsPage-Dnf99E8e.js} +1 -1
  10. package/client/dist/assets/{DocsDialog-PhdCJNVj.js → DocsDialog-DHi36rZ4.js} +1 -1
  11. package/client/dist/assets/{DocsPage-BY-wDthx.js → DocsPage-DIdVrQz1.js} +1 -1
  12. package/client/dist/assets/{InteractiveJobComposer-C9I0A4KR.js → InteractiveJobComposer-BHeB2inv.js} +1 -1
  13. package/client/dist/assets/{JobDetailModal-I_RoQJV4.js → JobDetailModal-CF1SKUHH.js} +1 -1
  14. package/client/dist/assets/JobDetailPage-De3rY18h.js +1 -0
  15. package/client/dist/assets/{JobsPage-DcllM4Ip.js → JobsPage-CfAqqJTx.js} +1 -1
  16. package/client/dist/assets/{LoopBuilderPage-DGm_iuff.js → LoopBuilderPage-DSBMuTb3.js} +2 -2
  17. package/client/dist/assets/{LoopPreviewModal-BC-TeFdD.js → LoopPreviewModal-B-c37kA0.js} +1 -1
  18. package/client/dist/assets/LoopsPage-DjnNXdmm.js +1 -0
  19. package/client/dist/assets/{MinimizedChatsContext-Cs34FPTz.js → MinimizedChatsContext-DIsnQMVz.js} +1 -1
  20. package/client/dist/assets/PluginsPage-DA5pQ_6u.js +2 -0
  21. package/client/dist/assets/{ProjectSettingsDialog-nEs-ENrE.js → ProjectSettingsDialog-DA23PSi6.js} +1 -1
  22. package/client/dist/assets/{TemplatePreviewModal-D4qW-J9B.js → TemplatePreviewModal-Cp7IQ-g2.js} +1 -1
  23. package/client/dist/assets/TicketDetailModal-BPD2i_0R.js +14 -0
  24. package/client/dist/assets/{Trans-CPISVji8.js → Trans-cWtExGkC.js} +1 -1
  25. package/client/dist/assets/addspec-4WmLJmBG.js +1 -0
  26. package/client/dist/assets/addspec-BRlk8jON.js +1 -0
  27. package/client/dist/assets/addspec-C7XRejU4.js +1 -0
  28. package/client/dist/assets/addspec-CHW9xf_X.js +1 -0
  29. package/client/dist/assets/addspec-DTmRrWrF.js +1 -0
  30. package/client/dist/assets/addspec-DhmnXER8.js +1 -0
  31. package/client/dist/assets/addspec-Di41DpYV.js +1 -0
  32. package/client/dist/assets/addspec-x3mizDxc.js +1 -0
  33. package/client/dist/assets/agent-BKsuIgIT.js +1 -0
  34. package/client/dist/assets/agent-Bs9NilfI.js +1 -0
  35. package/client/dist/assets/agent-C23h684q.js +1 -0
  36. package/client/dist/assets/agent-CqEjy3Z2.js +1 -0
  37. package/client/dist/assets/agent-D5DZTks1.js +1 -0
  38. package/client/dist/assets/agent-DE8hUYPl.js +1 -0
  39. package/client/dist/assets/agent-DsTuJGSc.js +1 -0
  40. package/client/dist/assets/agent-DwZM05-x.js +1 -0
  41. package/client/dist/assets/agents-45GbINfh.js +1 -0
  42. package/client/dist/assets/agents-BHp0_FQt.js +1 -0
  43. package/client/dist/assets/agents-Bvyi3y6R.js +1 -0
  44. package/client/dist/assets/agents-DMKFStHL.js +1 -0
  45. package/client/dist/assets/agents-DaYcxAr1.js +1 -0
  46. package/client/dist/assets/agents-IUOgqT5t.js +1 -0
  47. package/client/dist/assets/agents-ms7TwG16.js +1 -0
  48. package/client/dist/assets/agents-rzPnqoBR.js +1 -0
  49. package/client/dist/assets/agentstudio-8TQqBenW.js +1 -0
  50. package/client/dist/assets/agentstudio-B8Z_mmEX.js +1 -0
  51. package/client/dist/assets/agentstudio-BZR9YmLs.js +1 -0
  52. package/client/dist/assets/agentstudio-Bge9pAWb.js +1 -0
  53. package/client/dist/assets/agentstudio-Bz169Vzt.js +1 -0
  54. package/client/dist/assets/agentstudio-D6L2jpNi.js +1 -0
  55. package/client/dist/assets/agentstudio-K2-Z7CL0.js +1 -0
  56. package/client/dist/assets/agentstudio-Zmgzthv8.js +1 -0
  57. package/client/dist/assets/analytics-B8Qtptbl.js +1 -0
  58. package/client/dist/assets/analytics-BHqUazhP.js +1 -0
  59. package/client/dist/assets/analytics-BPptRY4f.js +1 -0
  60. package/client/dist/assets/analytics-BxDGOIwf.js +1 -0
  61. package/client/dist/assets/analytics-C9RaQcE3.js +1 -0
  62. package/client/dist/assets/analytics-CJIwqrEl.js +1 -0
  63. package/client/dist/assets/analytics-D_OZdQ9O.js +1 -0
  64. package/client/dist/assets/analytics-We6lUMI8.js +1 -0
  65. package/client/dist/assets/builder-3bygQtZi.js +1 -0
  66. package/client/dist/assets/builder-BiUG9Z5K.js +1 -0
  67. package/client/dist/assets/builder-CGRz_-zP.js +1 -0
  68. package/client/dist/assets/builder-CWYPw7Cw.js +1 -0
  69. package/client/dist/assets/builder-CX1437hF.js +1 -0
  70. package/client/dist/assets/{builder-CwA4T7gP.js → builder-Cowk9jtL.js} +1 -1
  71. package/client/dist/assets/builder-DwDexYRE.js +1 -0
  72. package/client/dist/assets/builder-skfnZ1uC.js +1 -0
  73. package/client/dist/assets/code-B0O8-p8k.js +1 -0
  74. package/client/dist/assets/code-B1VLZDhS.js +1 -0
  75. package/client/dist/assets/code-B86IMAfz.js +1 -0
  76. package/client/dist/assets/code-Bpj4Ddml.js +1 -0
  77. package/client/dist/assets/code-BykBZ5-e.js +1 -0
  78. package/client/dist/assets/code-CHPkOkDS.js +1 -0
  79. package/client/dist/assets/code-CkUuW4m9.js +1 -0
  80. package/client/dist/assets/code-cAqaqMTx.js +1 -0
  81. package/client/dist/assets/{dashboard-Dy2Um-US.js → dashboard-BVq6kRJe.js} +1 -1
  82. package/client/dist/assets/{dashboard-CHCEkds4.js → dashboard-BaKPPmLH.js} +1 -1
  83. package/client/dist/assets/{dashboard-CrlTV1ms.js → dashboard-Bm8e4zYG.js} +1 -1
  84. package/client/dist/assets/{dashboard-WhzOQw1S.js → dashboard-Bt6IesnM.js} +1 -1
  85. package/client/dist/assets/{dashboard-Cslu_GCH.js → dashboard-C_NQZle_.js} +1 -1
  86. package/client/dist/assets/{dashboard-DweT3Y4R.js → dashboard-CyZKoGoI.js} +1 -1
  87. package/client/dist/assets/{dashboard-DUU8-_Rg.js → dashboard-HIUdUBQ0.js} +1 -1
  88. package/client/dist/assets/{dashboard-Cqmmbh3l.js → dashboard-pm4Mr229.js} +1 -1
  89. package/client/dist/assets/{dist-js-jwoXo0YD.js → dist-js-BaP-xLOy.js} +1 -1
  90. package/client/dist/assets/{dist-js-Dj72W6qo.js → dist-js-CLlgOa5a.js} +1 -1
  91. package/client/dist/assets/format-command-C0D9IPmV.js +1 -0
  92. package/client/dist/assets/{formatDistanceToNow-ByKli7Q_.js → formatDistanceToNow-DUyzS4rr.js} +1 -1
  93. package/client/dist/assets/{getTimezoneOffsetInMilliseconds-qrcBaLW1.js → getTimezoneOffsetInMilliseconds-BCIwmmTj.js} +1 -1
  94. package/client/dist/assets/{i18n-Bf9Ckd10.js → i18n-D21Pr8Sj.js} +2 -2
  95. package/client/dist/assets/index-BdSDUFnA.css +2 -0
  96. package/client/dist/assets/index-Ci4-JKDr.js +77 -0
  97. package/client/dist/assets/{jobs-CVFD8rar.js → jobs-BAls3bWq.js} +1 -1
  98. package/client/dist/assets/{jobs-DoSaFzAa.js → jobs-B_TeSQxb.js} +1 -1
  99. package/client/dist/assets/jobs-Bgq-PZkC.js +1 -0
  100. package/client/dist/assets/jobs-Bpks6doU.js +1 -0
  101. package/client/dist/assets/jobs-CN_zv4Gr.js +1 -0
  102. package/client/dist/assets/jobs-DUlWSYq2.js +1 -0
  103. package/client/dist/assets/{jobs-B-sDHEay.js → jobs-DhxKgWFq.js} +1 -1
  104. package/client/dist/assets/{jobs-lk1_Dq1U.js → jobs-SwYS2M-B.js} +1 -1
  105. package/client/dist/assets/nav-BHDiSIVu.js +1 -0
  106. package/client/dist/assets/nav-CMiYAq4i.js +1 -0
  107. package/client/dist/assets/nav-CqS7NrDW.js +1 -0
  108. package/client/dist/assets/nav-D-0M7xfv.js +1 -0
  109. package/client/dist/assets/nav-D65O6u9I.js +1 -0
  110. package/client/dist/assets/nav-D_LKYvBr.js +1 -0
  111. package/client/dist/assets/nav-FDTJmU79.js +1 -0
  112. package/client/dist/assets/nav-VaB-C4k5.js +1 -0
  113. package/client/dist/assets/provider-capabilities-BvoExILy.js +1 -0
  114. package/client/dist/assets/settings-BveOJoaI.js +1 -0
  115. package/client/dist/assets/settings-Cj1C6F5k.js +1 -0
  116. package/client/dist/assets/settings-CuVwOpe0.js +1 -0
  117. package/client/dist/assets/settings-D5X4DfRc.js +1 -0
  118. package/client/dist/assets/settings-DXwxe-BW.js +1 -0
  119. package/client/dist/assets/settings-Di81Ba_V.js +1 -0
  120. package/client/dist/assets/settings-jbLjCYC_.js +1 -0
  121. package/client/dist/assets/settings-wIZNPFnn.js +1 -0
  122. package/client/dist/assets/setup-BBiHEO7h.js +1 -0
  123. package/client/dist/assets/setup-BlTWhNIQ.js +1 -0
  124. package/client/dist/assets/setup-Bp2L_oiP.js +1 -0
  125. package/client/dist/assets/setup-CInYXp1-.js +1 -0
  126. package/client/dist/assets/{setup-CITtPjed.js → setup-CYH3bP6K.js} +1 -1
  127. package/client/dist/assets/setup-DwcQ921P.js +1 -0
  128. package/client/dist/assets/setup-PBLjuDSs.js +1 -0
  129. package/client/dist/assets/setup-bx6FtoBp.js +1 -0
  130. package/client/dist/assets/{spending-DMnCXy84.js → spending-BCyUxoOI.js} +1 -1
  131. package/client/dist/assets/{tickets-B8BuAaj5.js → tickets-BL9r1G0e.js} +1 -1
  132. package/client/dist/assets/{tickets-DpmdE8tv.js → tickets-B_NyHJ8f.js} +1 -1
  133. package/client/dist/assets/{tickets-B_yh4qQk.js → tickets-BarF1wuG.js} +1 -1
  134. package/client/dist/assets/{tickets-pAUJkDTu.js → tickets-CclVhpQA.js} +1 -1
  135. package/client/dist/assets/{tickets-D_yDquEw.js → tickets-CqqOHbli.js} +1 -1
  136. package/client/dist/assets/{tickets-CFk2n2Or.js → tickets-DCkFSiqt.js} +1 -1
  137. package/client/dist/assets/{tickets-DQp7JS2R.js → tickets-Djn3ccfT.js} +1 -1
  138. package/client/dist/assets/{tickets-Bs37scwY.js → tickets-MiHBPsy_.js} +1 -1
  139. package/client/dist/assets/{useBrowserCaptureSession-CkBJShUw.js → useBrowserCaptureSession-CkVCDzer.js} +1 -1
  140. package/client/dist/assets/{useDesktop-B4pSBIDd.js → useDesktop-DCP_MHp9.js} +1 -1
  141. package/client/dist/index.html +25 -24
  142. package/docs/README.md +7 -3
  143. package/docs/cli.md +3 -3
  144. package/docs/codex.md +51 -64
  145. package/docs/creating-specs.md +36 -4
  146. package/docs/customizing.md +5 -5
  147. package/docs/gemini.md +35 -47
  148. package/docs/getting-started.md +15 -9
  149. package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +5 -1
  150. package/docs/guide/de/agents/4-custom-agents-catalog.md +7 -4
  151. package/docs/guide/de/getting-started/1-what-is-specrails.md +1 -0
  152. package/docs/guide/de/getting-started/2-installing-and-first-run.md +1 -0
  153. package/docs/guide/de/getting-started/4-the-dashboard-tour.md +4 -4
  154. package/docs/guide/de/integrations/1-ai-providers.md +29 -18
  155. package/docs/guide/de/integrations/2-plugins.md +3 -3
  156. package/docs/guide/de/integrations/6-agent-chat.md +8 -1
  157. package/docs/guide/de/pipeline/1-rails-and-jobs.md +9 -6
  158. package/docs/guide/de/pipeline/2-the-job-detail-view.md +3 -1
  159. package/docs/guide/de/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  160. package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +13 -13
  161. package/docs/guide/de/pipeline/5-the-loop-builder.md +6 -2
  162. package/docs/guide/de/specs/2-add-spec-quick-mode.md +6 -1
  163. package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +7 -1
  164. package/docs/guide/en/agents/4-custom-agents-catalog.md +17 -4
  165. package/docs/guide/en/getting-started/1-what-is-specrails.md +2 -1
  166. package/docs/guide/en/getting-started/2-installing-and-first-run.md +2 -1
  167. package/docs/guide/en/getting-started/4-the-dashboard-tour.md +5 -5
  168. package/docs/guide/en/insights/3-code-explorer.md +5 -0
  169. package/docs/guide/en/integrations/1-ai-providers.md +63 -22
  170. package/docs/guide/en/integrations/2-plugins.md +3 -3
  171. package/docs/guide/en/integrations/6-agent-chat.md +14 -2
  172. package/docs/guide/en/pipeline/1-rails-and-jobs.md +19 -7
  173. package/docs/guide/en/pipeline/2-the-job-detail-view.md +3 -1
  174. package/docs/guide/en/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  175. package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +25 -11
  176. package/docs/guide/en/pipeline/5-the-loop-builder.md +7 -2
  177. package/docs/guide/en/specs/2-add-spec-quick-mode.md +10 -1
  178. package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +5 -1
  179. package/docs/guide/es/agents/4-custom-agents-catalog.md +7 -4
  180. package/docs/guide/es/getting-started/1-what-is-specrails.md +1 -0
  181. package/docs/guide/es/getting-started/2-installing-and-first-run.md +1 -0
  182. package/docs/guide/es/getting-started/4-the-dashboard-tour.md +4 -4
  183. package/docs/guide/es/integrations/1-ai-providers.md +30 -18
  184. package/docs/guide/es/integrations/2-plugins.md +3 -3
  185. package/docs/guide/es/integrations/6-agent-chat.md +8 -1
  186. package/docs/guide/es/pipeline/1-rails-and-jobs.md +9 -6
  187. package/docs/guide/es/pipeline/2-the-job-detail-view.md +3 -1
  188. package/docs/guide/es/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  189. package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +15 -13
  190. package/docs/guide/es/pipeline/5-the-loop-builder.md +6 -2
  191. package/docs/guide/es/specs/2-add-spec-quick-mode.md +6 -1
  192. package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +5 -1
  193. package/docs/guide/fr/agents/4-custom-agents-catalog.md +7 -4
  194. package/docs/guide/fr/getting-started/1-what-is-specrails.md +1 -0
  195. package/docs/guide/fr/getting-started/2-installing-and-first-run.md +1 -0
  196. package/docs/guide/fr/getting-started/4-the-dashboard-tour.md +4 -4
  197. package/docs/guide/fr/integrations/1-ai-providers.md +29 -18
  198. package/docs/guide/fr/integrations/2-plugins.md +3 -3
  199. package/docs/guide/fr/integrations/6-agent-chat.md +8 -1
  200. package/docs/guide/fr/pipeline/1-rails-and-jobs.md +9 -6
  201. package/docs/guide/fr/pipeline/2-the-job-detail-view.md +3 -1
  202. package/docs/guide/fr/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  203. package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +15 -13
  204. package/docs/guide/fr/pipeline/5-the-loop-builder.md +6 -2
  205. package/docs/guide/fr/specs/2-add-spec-quick-mode.md +6 -1
  206. package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +5 -1
  207. package/docs/guide/it/agents/4-custom-agents-catalog.md +7 -4
  208. package/docs/guide/it/getting-started/1-what-is-specrails.md +1 -0
  209. package/docs/guide/it/getting-started/2-installing-and-first-run.md +1 -0
  210. package/docs/guide/it/getting-started/4-the-dashboard-tour.md +4 -4
  211. package/docs/guide/it/integrations/1-ai-providers.md +28 -18
  212. package/docs/guide/it/integrations/2-plugins.md +3 -3
  213. package/docs/guide/it/integrations/6-agent-chat.md +8 -1
  214. package/docs/guide/it/pipeline/1-rails-and-jobs.md +9 -6
  215. package/docs/guide/it/pipeline/2-the-job-detail-view.md +3 -1
  216. package/docs/guide/it/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  217. package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +13 -13
  218. package/docs/guide/it/pipeline/5-the-loop-builder.md +6 -2
  219. package/docs/guide/it/specs/2-add-spec-quick-mode.md +6 -1
  220. package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +6 -1
  221. package/docs/guide/ja/agents/4-custom-agents-catalog.md +7 -4
  222. package/docs/guide/ja/getting-started/1-what-is-specrails.md +1 -0
  223. package/docs/guide/ja/getting-started/2-installing-and-first-run.md +1 -0
  224. package/docs/guide/ja/getting-started/4-the-dashboard-tour.md +4 -4
  225. package/docs/guide/ja/integrations/1-ai-providers.md +28 -18
  226. package/docs/guide/ja/integrations/2-plugins.md +3 -3
  227. package/docs/guide/ja/integrations/6-agent-chat.md +7 -1
  228. package/docs/guide/ja/pipeline/1-rails-and-jobs.md +9 -6
  229. package/docs/guide/ja/pipeline/2-the-job-detail-view.md +3 -1
  230. package/docs/guide/ja/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  231. package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +14 -13
  232. package/docs/guide/ja/pipeline/5-the-loop-builder.md +6 -2
  233. package/docs/guide/ja/specs/2-add-spec-quick-mode.md +6 -1
  234. package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +5 -1
  235. package/docs/guide/pt/agents/4-custom-agents-catalog.md +7 -4
  236. package/docs/guide/pt/getting-started/1-what-is-specrails.md +1 -0
  237. package/docs/guide/pt/getting-started/2-installing-and-first-run.md +1 -0
  238. package/docs/guide/pt/getting-started/4-the-dashboard-tour.md +4 -4
  239. package/docs/guide/pt/integrations/1-ai-providers.md +28 -18
  240. package/docs/guide/pt/integrations/2-plugins.md +3 -3
  241. package/docs/guide/pt/integrations/6-agent-chat.md +7 -1
  242. package/docs/guide/pt/pipeline/1-rails-and-jobs.md +9 -6
  243. package/docs/guide/pt/pipeline/2-the-job-detail-view.md +2 -1
  244. package/docs/guide/pt/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  245. package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +14 -13
  246. package/docs/guide/pt/pipeline/5-the-loop-builder.md +6 -2
  247. package/docs/guide/pt/specs/2-add-spec-quick-mode.md +6 -1
  248. package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +4 -1
  249. package/docs/guide/zh/agents/4-custom-agents-catalog.md +7 -4
  250. package/docs/guide/zh/getting-started/1-what-is-specrails.md +1 -0
  251. package/docs/guide/zh/getting-started/2-installing-and-first-run.md +1 -0
  252. package/docs/guide/zh/getting-started/4-the-dashboard-tour.md +4 -4
  253. package/docs/guide/zh/integrations/1-ai-providers.md +26 -18
  254. package/docs/guide/zh/integrations/2-plugins.md +3 -3
  255. package/docs/guide/zh/integrations/6-agent-chat.md +6 -1
  256. package/docs/guide/zh/pipeline/1-rails-and-jobs.md +9 -6
  257. package/docs/guide/zh/pipeline/2-the-job-detail-view.md +2 -1
  258. package/docs/guide/zh/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  259. package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +12 -12
  260. package/docs/guide/zh/pipeline/5-the-loop-builder.md +6 -2
  261. package/docs/guide/zh/specs/2-add-spec-quick-mode.md +6 -1
  262. package/docs/internals/README.md +4 -1
  263. package/docs/internals/adding-a-provider.md +32 -28
  264. package/docs/internals/api-reference.md +37 -13
  265. package/docs/internals/architecture.md +5 -5
  266. package/docs/internals/bundled-framework-build-plan.md +3 -3
  267. package/docs/internals/code-explorer-story.md +4 -0
  268. package/docs/internals/configuration.md +17 -5
  269. package/docs/internals/global-artifacts-alignment-contract.md +1 -1
  270. package/docs/internals/operations-runbook.md +1 -1
  271. package/docs/internals/profiles.md +37 -45
  272. package/docs/internals/project-builder.md +16 -0
  273. package/docs/kimi.md +291 -0
  274. package/docs/mcp.md +9 -2
  275. package/docs/platforms/macos.md +17 -7
  276. package/docs/platforms/windows.md +9 -4
  277. package/docs/running-pipelines.md +46 -12
  278. package/docs/terminal.md +1 -1
  279. package/docs/tracking-cost.md +25 -6
  280. package/package.json +4 -2
  281. package/server/dist/agent-chat-manager.js +74 -32
  282. package/server/dist/agent-chat-router.js +40 -17
  283. package/server/dist/agent-cwd-manager.js +14 -7
  284. package/server/dist/agent-generator.js +69 -85
  285. package/server/dist/agent-mcp-config.js +17 -11
  286. package/server/dist/agent-operator-prompt.js +29 -20
  287. package/server/dist/agent-refine-manager.js +58 -38
  288. package/server/dist/ai-invocations.js +65 -20
  289. package/server/dist/attachment-manager.js +49 -15
  290. package/server/dist/blueprint-chat-manager.js +41 -16
  291. package/server/dist/blueprint-router.js +40 -6
  292. package/server/dist/chat-manager.js +165 -89
  293. package/server/dist/code-explorer-router.js +26 -7
  294. package/server/dist/contract-refine-runner.js +146 -113
  295. package/server/dist/core-compat.js +57 -2
  296. package/server/dist/core-package.js +3 -3
  297. package/server/dist/core-update-manager.js +17 -1
  298. package/server/dist/db.js +60 -5
  299. package/server/dist/desktop-analytics.js +44 -6
  300. package/server/dist/desktop-router.js +127 -11
  301. package/server/dist/explore-cwd-manager.js +19 -3
  302. package/server/dist/feature-flags.js +1 -1
  303. package/server/dist/file-story-manager.js +3 -3
  304. package/server/dist/file-summary-generator.js +21 -15
  305. package/server/dist/file-summary-manager.js +6 -6
  306. package/server/dist/framework-manager.js +19 -2
  307. package/server/dist/framework-migration.js +27 -12
  308. package/server/dist/install-config-path.js +1 -1
  309. package/server/dist/interactive-job-session.js +8 -6
  310. package/server/dist/loop-command-catalog.js +27 -10
  311. package/server/dist/loop-executors.js +59 -27
  312. package/server/dist/loop-factory.js +2 -2
  313. package/server/dist/loop-run-manager.js +100 -39
  314. package/server/dist/loops-router.js +1 -1
  315. package/server/dist/mcp/guide.js +23 -16
  316. package/server/dist/mcp/tools/agents.js +47 -41
  317. package/server/dist/mcp/tools/analytics.js +2 -2
  318. package/server/dist/mcp/tools/loops.js +2 -2
  319. package/server/dist/mcp/tools/plugins.js +14 -9
  320. package/server/dist/mcp/tools/rails.js +12 -13
  321. package/server/dist/mcp/tools/support.js +1 -1
  322. package/server/dist/mobile/mobile-router.js +5 -1
  323. package/server/dist/offline-assemble.js +13 -1
  324. package/server/dist/path-resolver.js +2 -2
  325. package/server/dist/plugin-manager.js +391 -106
  326. package/server/dist/plugins/claude-md-mutation.js +5 -4
  327. package/server/dist/plugins/drift.js +32 -29
  328. package/server/dist/plugins/rail-integration.js +13 -2
  329. package/server/dist/plugins/serena/install.js +25 -17
  330. package/server/dist/plugins/serena/manifest.js +22 -5
  331. package/server/dist/plugins/serena/verify.js +46 -16
  332. package/server/dist/plugins-router.js +59 -8
  333. package/server/dist/profile-manager.js +148 -36
  334. package/server/dist/profiles-router.js +311 -82
  335. package/server/dist/project-registry.js +2 -2
  336. package/server/dist/project-router-chat.js +17 -8
  337. package/server/dist/project-router-helpers.js +93 -5
  338. package/server/dist/project-router-jobs.js +76 -12
  339. package/server/dist/project-router-loop-runs.js +42 -14
  340. package/server/dist/project-router-settings.js +31 -10
  341. package/server/dist/project-router-setup.js +4 -5
  342. package/server/dist/project-router-spending.js +15 -3
  343. package/server/dist/project-router-tickets.js +187 -181
  344. package/server/dist/project-router.js +1 -0
  345. package/server/dist/proposal-manager.js +125 -85
  346. package/server/dist/providers/claude-adapter.js +14 -0
  347. package/server/dist/providers/codex-adapter.js +20 -0
  348. package/server/dist/providers/gemini-adapter.js +14 -0
  349. package/server/dist/providers/index.js +18 -1
  350. package/server/dist/providers/kimi-adapter.js +361 -0
  351. package/server/dist/providers/kimi-skill-prompt.js +332 -0
  352. package/server/dist/providers/runtime.js +137 -0
  353. package/server/dist/queue-manager.js +103 -78
  354. package/server/dist/rail-isolated-launch.js +1 -1
  355. package/server/dist/rails-router.js +51 -38
  356. package/server/dist/result-event.js +5 -0
  357. package/server/dist/schemas/profile.v1.json +3 -4
  358. package/server/dist/setup-manager.js +222 -101
  359. package/server/dist/setup-prerequisites.js +7 -1
  360. package/server/dist/smash-runner.js +104 -57
  361. package/server/dist/spawn-lifecycle.js +18 -14
  362. package/server/dist/spec-launcher-manager.js +66 -54
  363. package/server/dist/spec-models.js +15 -6
  364. package/server/dist/spending.js +110 -17
  365. package/server/dist/util/cli-prompt.js +142 -5
  366. package/server/dist/util/stream-display.js +46 -0
  367. package/server/dist/workspace-manager.js +100 -37
  368. package/server/dist/worktree-manager.js +4 -0
  369. package/server/dist/worktree-overlay.js +12 -3
  370. package/client/dist/assets/AgentModeCodePane-BAYyFRmY.js +0 -2
  371. package/client/dist/assets/AgentsPage-DuyJuaFs.js +0 -86
  372. package/client/dist/assets/AnalyticsPage-BY7gtCx6.js +0 -1
  373. package/client/dist/assets/CodePage-vyQr40Vl.js +0 -2
  374. package/client/dist/assets/JobDetailPage-CU4FEnUC.js +0 -1
  375. package/client/dist/assets/LoopsPage-SqglnXlp.js +0 -1
  376. package/client/dist/assets/PluginsPage-B89S8o1a.js +0 -2
  377. package/client/dist/assets/TicketDetailModal-CI47Dq9E.js +0 -14
  378. package/client/dist/assets/addspec-BXjvkh5q.js +0 -1
  379. package/client/dist/assets/addspec-C4bwrmpi.js +0 -1
  380. package/client/dist/assets/addspec-CArHXUDM.js +0 -1
  381. package/client/dist/assets/addspec-DTKJcXiR.js +0 -1
  382. package/client/dist/assets/addspec-DbNBbrha.js +0 -1
  383. package/client/dist/assets/addspec-Rw8uVBC1.js +0 -1
  384. package/client/dist/assets/addspec-htHGZHOe.js +0 -1
  385. package/client/dist/assets/addspec-lr_LP6jk.js +0 -1
  386. package/client/dist/assets/agent-BABjRt0P.js +0 -1
  387. package/client/dist/assets/agent-BuUpgqVx.js +0 -1
  388. package/client/dist/assets/agent-CCDZesgU.js +0 -1
  389. package/client/dist/assets/agent-CVn64zWH.js +0 -1
  390. package/client/dist/assets/agent-CWeOny0E.js +0 -1
  391. package/client/dist/assets/agent-DOysmad_.js +0 -1
  392. package/client/dist/assets/agent-DSsjTBhn.js +0 -1
  393. package/client/dist/assets/agent-DlZMxfM9.js +0 -1
  394. package/client/dist/assets/agents-6ZOJXWVk.js +0 -1
  395. package/client/dist/assets/agents-BZ0XQKjg.js +0 -1
  396. package/client/dist/assets/agents-BqWklnHR.js +0 -1
  397. package/client/dist/assets/agents-Bz-thHkB.js +0 -1
  398. package/client/dist/assets/agents-CJclElx6.js +0 -1
  399. package/client/dist/assets/agents-D_l9L0VA.js +0 -1
  400. package/client/dist/assets/agents-DhG7mg6-.js +0 -1
  401. package/client/dist/assets/agents-u_C0jPB5.js +0 -1
  402. package/client/dist/assets/agentstudio-BF19hbXj.js +0 -1
  403. package/client/dist/assets/agentstudio-BIUe1Im2.js +0 -1
  404. package/client/dist/assets/agentstudio-BLGvxWBx.js +0 -1
  405. package/client/dist/assets/agentstudio-D9UKiWTj.js +0 -1
  406. package/client/dist/assets/agentstudio-Drs37nIM.js +0 -1
  407. package/client/dist/assets/agentstudio-nEnKkcXM.js +0 -1
  408. package/client/dist/assets/agentstudio-pyFcSBKy.js +0 -1
  409. package/client/dist/assets/agentstudio-zfTzQh3U.js +0 -1
  410. package/client/dist/assets/analytics-BC7mwR4s.js +0 -1
  411. package/client/dist/assets/analytics-BiNg8edP.js +0 -1
  412. package/client/dist/assets/analytics-C0s_T2GN.js +0 -1
  413. package/client/dist/assets/analytics-CdsAPAwZ.js +0 -1
  414. package/client/dist/assets/analytics-Cr1_q-lC.js +0 -1
  415. package/client/dist/assets/analytics-DZ8Aoq3I.js +0 -1
  416. package/client/dist/assets/analytics-IEsKZvpW.js +0 -1
  417. package/client/dist/assets/analytics-SRPf84OT.js +0 -1
  418. package/client/dist/assets/builder-BH8Fua-g.js +0 -1
  419. package/client/dist/assets/builder-BoV7DgKd.js +0 -1
  420. package/client/dist/assets/builder-Cc_Lf79C.js +0 -1
  421. package/client/dist/assets/builder-CwZ7Bme2.js +0 -1
  422. package/client/dist/assets/builder-CxW-JFsR.js +0 -1
  423. package/client/dist/assets/builder-D94lrV7x.js +0 -1
  424. package/client/dist/assets/builder-cqHpCyGa.js +0 -1
  425. package/client/dist/assets/code-76gS0IdL.js +0 -1
  426. package/client/dist/assets/code-BDXEM4ml.js +0 -1
  427. package/client/dist/assets/code-C1VwxlML.js +0 -1
  428. package/client/dist/assets/code-CnMZyJpr.js +0 -1
  429. package/client/dist/assets/code-D20ef9Cf.js +0 -1
  430. package/client/dist/assets/code-DdOXaWRY.js +0 -1
  431. package/client/dist/assets/code-Duohuf9l.js +0 -1
  432. package/client/dist/assets/code-geHmknB9.js +0 -1
  433. package/client/dist/assets/format-command-Dfa1o2d-.js +0 -1
  434. package/client/dist/assets/index-Dh9i4CnN.css +0 -2
  435. package/client/dist/assets/index-F9r8mWP_.js +0 -76
  436. package/client/dist/assets/jobs-BCtGfgUA.js +0 -1
  437. package/client/dist/assets/jobs-BHR_EnDI.js +0 -1
  438. package/client/dist/assets/jobs-BMbZJjJJ.js +0 -1
  439. package/client/dist/assets/jobs-DzSIR8V6.js +0 -1
  440. package/client/dist/assets/nav-BRJBxaGt.js +0 -1
  441. package/client/dist/assets/nav-CAGKv3_F.js +0 -1
  442. package/client/dist/assets/nav-CNskRJKQ.js +0 -1
  443. package/client/dist/assets/nav-DY93irBL.js +0 -1
  444. package/client/dist/assets/nav-DhjvYgqt.js +0 -1
  445. package/client/dist/assets/nav-Gb-r4wop.js +0 -1
  446. package/client/dist/assets/nav-TvumAFD2.js +0 -1
  447. package/client/dist/assets/nav-myFaXRHD.js +0 -1
  448. package/client/dist/assets/settings-B0ypw9uw.js +0 -1
  449. package/client/dist/assets/settings-B9ilOSYO.js +0 -1
  450. package/client/dist/assets/settings-BqlWHRHA.js +0 -1
  451. package/client/dist/assets/settings-D8dlqt4d.js +0 -1
  452. package/client/dist/assets/settings-DAZqjX2a.js +0 -1
  453. package/client/dist/assets/settings-DRh39v1S.js +0 -1
  454. package/client/dist/assets/settings-Mj1OJbfd.js +0 -1
  455. package/client/dist/assets/settings-lRReaSYm.js +0 -1
  456. package/client/dist/assets/setup-3832BJCo.js +0 -1
  457. package/client/dist/assets/setup-B8J-gECe.js +0 -1
  458. package/client/dist/assets/setup-BCIOxVsc.js +0 -1
  459. package/client/dist/assets/setup-BciLj_tU.js +0 -1
  460. package/client/dist/assets/setup-CTkE3cfh.js +0 -1
  461. package/client/dist/assets/setup-ajB4rYm-.js +0 -1
  462. package/client/dist/assets/setup-xFO1wNl0.js +0 -1
@@ -26,6 +26,22 @@ const path_resolver_1 = require("./path-resolver");
26
26
  function nodeInterpreter() {
27
27
  return (0, path_resolver_1.resolveBundledNodeExe)() ?? process.execPath;
28
28
  }
29
+ /**
30
+ * Resolve symlinks in the CLI path we pass as the child's argv[1]. Core's
31
+ * cli.js auto-run guard compares import.meta.url (realpathed by Node's ESM
32
+ * loader) against pathToFileURL(process.argv[1]) — a symlinked argv[1] (e.g.
33
+ * a staging dir under macOS /var/folders) makes them differ, so main() never
34
+ * runs and the child exits 0 as a silent no-op. Realpathing here keeps the
35
+ * guard true regardless of where the core package lives.
36
+ */
37
+ function realpathOrSelf(p) {
38
+ try {
39
+ return fs_1.default.realpathSync(p);
40
+ }
41
+ catch {
42
+ return p;
43
+ }
44
+ }
29
45
  /** `~/.specrails/framework` — same home as the registry. */
30
46
  function frameworkRoot(home) {
31
47
  return path_1.default.join((0, artifact_registry_1.resolveHome)(home), '.specrails', 'framework');
@@ -121,9 +137,10 @@ class FrameworkManager {
121
137
  resolveCli() {
122
138
  if (this.coreRoot) {
123
139
  const cli = path_1.default.join(this.coreRoot, 'dist', 'installer', 'cli.js');
124
- return fs_1.default.existsSync(cli) ? cli : null;
140
+ return fs_1.default.existsSync(cli) ? realpathOrSelf(cli) : null;
125
141
  }
126
- return (0, bundled_core_1.getBundledCoreCli)();
142
+ const bundled = (0, bundled_core_1.getBundledCoreCli)();
143
+ return bundled ? realpathOrSelf(bundled) : null;
127
144
  }
128
145
  /** True when a usable core (override or bundled) is present (else methods no-op). */
129
146
  isAvailable() {
@@ -11,16 +11,30 @@ const path_1 = __importDefault(require("path"));
11
11
  const framework_manager_1 = require("./framework-manager");
12
12
  const workspace_manager_1 = require("./workspace-manager");
13
13
  const artifact_registry_1 = require("./artifact-registry");
14
- /** The shared, statically-linked subtrees of a providerDir. `agent-memory` is
15
- * intentionally absent — it is real per-workspace state, never compared/linked. */
14
+ const providers_1 = require("./providers");
15
+ /** Whole-directory shared subtrees for the legacy providers. `agent-memory` is
16
+ * intentionally absent — it is real per-workspace state, never compared/linked. */
16
17
  const SHARED_SUBTREES = ['commands', 'agents', 'skills', 'rules'];
18
+ /**
19
+ * Roots that core assembles as whole-directory framework links.
20
+ *
21
+ * Kimi is intentionally special: `.kimi-code/skills` remains a REAL directory
22
+ * and core links only the framework-owned children within it. That merged layout
23
+ * is what lets Kimi keep OpenSpec skills and desktop-authored `custom-*` roles
24
+ * as direct children. Treating the root as a copied shared subtree would back it up,
25
+ * expect a root symlink that core will never create, then revert every launch.
26
+ */
27
+ function sharedSubtreesFor(provider) {
28
+ return provider === 'kimi' ? ['rules'] : SHARED_SUBTREES;
29
+ }
17
30
  /** Map a provider id to its providerDir name (mirrors core). */
18
31
  function providerDirFor(provider) {
19
- if (provider === 'codex')
20
- return '.codex';
21
- if (provider === 'gemini')
22
- return '.gemini';
23
- return '.claude';
32
+ try {
33
+ return (0, providers_1.getAdapter)(provider).projectDirName;
34
+ }
35
+ catch {
36
+ return '.claude';
37
+ }
24
38
  }
25
39
  /** sha256 of a file's bytes, or null when unreadable. */
26
40
  function hashFile(p) {
@@ -83,9 +97,9 @@ function isCustomAgent(rel) {
83
97
  * from (or is missing in) `current` — excluding `custom-*` agents — counts as
84
98
  * local divergence.
85
99
  */
86
- function compareSharedSubtrees(workspaceProviderDir, fwProviderDir) {
100
+ function compareSharedSubtrees(workspaceProviderDir, fwProviderDir, subtrees) {
87
101
  let hadSharedSubtree = false;
88
- for (const sub of SHARED_SUBTREES) {
102
+ for (const sub of subtrees) {
89
103
  const copyDir = path_1.default.join(workspaceProviderDir, sub);
90
104
  if (!isRealDir(copyDir))
91
105
  continue;
@@ -154,15 +168,16 @@ function runMigration(slug, projectPath, provider, fwCurrent, fm, opts) {
154
168
  const ws = (0, workspace_manager_1.workspacePathFor)(slug, opts.home);
155
169
  const wsProviderDir = path_1.default.join(ws, providerDir);
156
170
  const fwProviderDir = path_1.default.join(fwCurrent, providerDir);
171
+ const sharedSubtrees = sharedSubtreesFor(provider);
157
172
  // Idempotent: if any shared subtree is already a symlink into `current`, the
158
173
  // workspace is migrated — no-op.
159
- for (const sub of SHARED_SUBTREES) {
174
+ for (const sub of sharedSubtrees) {
160
175
  if (linkResolvesIntoFramework(path_1.default.join(wsProviderDir, sub), fwCurrent)) {
161
176
  return { outcome: 'already-symlinked' };
162
177
  }
163
178
  }
164
179
  // Detect the migratable real-copy layout + the local-divergence guard.
165
- const cmp = compareSharedSubtrees(wsProviderDir, fwProviderDir);
180
+ const cmp = compareSharedSubtrees(wsProviderDir, fwProviderDir, sharedSubtrees);
166
181
  if (!cmp.hadSharedSubtree) {
167
182
  return { outcome: 'not-a-copy' };
168
183
  }
@@ -172,7 +187,7 @@ function runMigration(slug, projectPath, provider, fwCurrent, fm, opts) {
172
187
  }
173
188
  // ── Backup the copied shared subtrees (never delete). ──────────────────────
174
189
  const backedUp = [];
175
- for (const sub of SHARED_SUBTREES) {
190
+ for (const sub of sharedSubtrees) {
176
191
  const live = path_1.default.join(wsProviderDir, sub);
177
192
  if (!isRealDir(live))
178
193
  continue;
@@ -48,7 +48,7 @@ function isSafeSlug(slug) {
48
48
  !slug.includes('..'));
49
49
  }
50
50
  /** True when a provider id is a safe filename segment (registry ids are
51
- * lowercase-kebab — `claude` / `codex` / `gemini`). */
51
+ * lowercase-kebab — `claude` / `codex` / `gemini` / `kimi`). */
52
52
  function isSafeProvider(provider) {
53
53
  return typeof provider === 'string' && /^[a-z0-9][a-z0-9-]*$/.test(provider);
54
54
  }
@@ -39,6 +39,7 @@ const explore_stdin_session_1 = require("./explore-stdin-session");
39
39
  const result_event_1 = require("./result-event");
40
40
  const db_1 = require("./db");
41
41
  const stream_display_1 = require("./util/stream-display");
42
+ const runtime_1 = require("./providers/runtime");
42
43
  /** Claude's stream-json result frames do not carry a turn id. Hash a canonical
43
44
  * representation of the real frame instead: an exact/semantic retransmission
44
45
  * remains identifiable even after the next stdin turn has been armed, while a
@@ -443,10 +444,10 @@ class InteractiveJobSession {
443
444
  if (this._acceptedResultSignatures.has(signature))
444
445
  return;
445
446
  }
446
- const adapterEv = this._adapter.parseStreamLine(line);
447
- if (adapterEv) {
448
- this._turnEvents.push(adapterEv);
449
- if (!this._sawModelWork && isModelWorkEvent(adapterEv))
447
+ const adapterEvents = (0, runtime_1.parseStreamEvents)(this._adapter, line);
448
+ for (const adapterEvent of adapterEvents) {
449
+ this._turnEvents.push(adapterEvent);
450
+ if (!this._sawModelWork && isModelWorkEvent(adapterEvent))
450
451
  this._sawModelWork = true;
451
452
  }
452
453
  if (parsed) {
@@ -476,8 +477,9 @@ class InteractiveJobSession {
476
477
  }
477
478
  else {
478
479
  this._persistLog('stdout', line);
479
- if (adapterEv?.kind === 'text-delta') {
480
- this._emitLog('stdout', adapterEv.text);
480
+ const textEvent = adapterEvents.find((event) => event.kind === 'text-delta');
481
+ if (textEvent?.kind === 'text-delta') {
482
+ this._emitLog('stdout', textEvent.text);
481
483
  }
482
484
  else {
483
485
  this._emitLog('stdout', line);
@@ -8,8 +8,9 @@
8
8
  * claude `/specrails:<name>`, codex `$<name>` (skill), gemini `/specrails:<name>`.
9
9
  * Mirrors QueueManager's rail invocation (`/specrails:implement #1 #2 --yes`).
10
10
  * - `template`: a provider-invariant curated prompt (no core coupling).
11
- * - `native`: a raw autonomous Freestyle command — claude-only, NOT a slash
12
- * command; it expands to a self-contained autonomous prompt.
11
+ * - `native`: a raw autonomous Freestyle command — gated by the provider's
12
+ * Freestyle capability, NOT a slash command; it expands to a self-contained
13
+ * autonomous prompt.
13
14
  *
14
15
  * Each command declares its TICKET SCOPE:
15
16
  * - `all` → one run over ALL the rail's tickets (`#1 #2 #3`). implement, batch.
@@ -24,6 +25,8 @@ exports.getLoopCommand = getLoopCommand;
24
25
  exports.expandCommands = expandCommands;
25
26
  exports.dominantTicketScope = dominantTicketScope;
26
27
  exports.referencesClaudeOnlyCommand = referencesClaudeOnlyCommand;
28
+ exports.referencesUnsupportedProviderCommand = referencesUnsupportedProviderCommand;
29
+ const registry_1 = require("./providers/registry");
27
30
  /** The autonomous prompt a `native` command (Freestyle) expands to for the
28
31
  * LoopRunManager path. Factory Freestyle loops route to QueueManager's real
29
32
  * `_buildFreestylePrompt` instead (phase A); this is the custom-loop fallback. */
@@ -70,9 +73,9 @@ exports.LOOP_COMMANDS = [
70
73
  {
71
74
  name: 'freestyle',
72
75
  label: 'Freestyle',
73
- description: 'Free-form autonomous per-ticket implementation — Claude receives the spec as a prompt and works it end-to-end with no pipeline. Claude only. Internal token: {{cmd:freestyle}}.',
76
+ description: 'Free-form autonomous per-ticket implementation — the selected capable provider receives the spec as a prompt and works it end-to-end with no pipeline. Internal token: {{cmd:freestyle}}.',
74
77
  native: true,
75
- claudeOnly: true,
78
+ requiredCapability: 'freestyle',
76
79
  ticketScope: 'per-ticket',
77
80
  },
78
81
  {
@@ -134,19 +137,19 @@ exports.LOOP_COMMANDS = [
134
137
  {
135
138
  name: 'opsx:ff', label: 'opsx:ff', ticketScope: 'per-ticket',
136
139
  description: 'OpenSpec fast-forward: create (or continue) a change and generate all its artifacts (proposal, specs, design, tasks). Native /opsx:ff (claude/gemini) or $opsx:ff (codex).',
137
- providerNative: { claude: '/opsx:ff', gemini: '/opsx:ff', codex: '$opsx:ff' },
140
+ providerNative: { claude: '/opsx:ff', gemini: '/opsx:ff', codex: '$opsx:ff', kimi: '/skill:openspec-ff-change' },
138
141
  template: 'Create or continue an OpenSpec change for the work described next and generate all of its artifacts (proposal, specs, design, and tasks) so it is ready to implement.',
139
142
  },
140
143
  {
141
144
  name: 'opsx:apply', label: 'opsx:apply', ticketScope: 'per-ticket',
142
145
  description: 'OpenSpec apply: implement all pending tasks of the active change. Native /opsx:apply (claude/gemini) or $opsx:apply (codex).',
143
- providerNative: { claude: '/opsx:apply', gemini: '/opsx:apply', codex: '$opsx:apply' },
146
+ providerNative: { claude: '/opsx:apply', gemini: '/opsx:apply', codex: '$opsx:apply', kimi: '/skill:openspec-apply-change' },
144
147
  template: 'Implement every pending task of the active OpenSpec change, editing the code as needed and marking each task complete as you finish it.',
145
148
  },
146
149
  {
147
150
  name: 'opsx:verify', label: 'opsx:verify', ticketScope: 'per-ticket',
148
151
  description: "OpenSpec verify: check the active change's implementation against its specs/tasks; ends with VERIFICATION: PASS|FAIL. Native /opsx:verify (claude/gemini) or $opsx:verify (codex).",
149
- providerNative: { claude: '/opsx:verify', gemini: '/opsx:verify', codex: '$opsx:verify' },
152
+ providerNative: { claude: '/opsx:verify', gemini: '/opsx:verify', codex: '$opsx:verify', kimi: '/skill:openspec-verify-change' },
150
153
  template: 'Verify the active OpenSpec change: inspect the REAL implementation against its specs, design, and tasks. Finish with exactly `VERIFICATION: PASS` when nothing required is missing, or `VERIFICATION: FAIL — <what is still missing>` otherwise.',
151
154
  },
152
155
  // ── Merge-resolver (parallel rails: integrate worktree branches back) ───────
@@ -225,7 +228,11 @@ const CMD_TOKEN_RE = /\{\{\s*cmd:([\w:-]+)\s*\}\}/g;
225
228
  * identical in shape to the rail's `/specrails:implement #1 #2 --yes`. Codex has
226
229
  * no `/namespace:cmd` parser, so it invokes the equivalent `$<name>` skill. */
227
230
  function nativeInvocation(coreCommand, provider, ids) {
228
- const head = provider === 'codex' ? `$${coreCommand}` : `/specrails:${coreCommand}`;
231
+ const head = provider === 'codex'
232
+ ? `$${coreCommand}`
233
+ : provider === 'kimi'
234
+ ? `/skill:specrails-${coreCommand}`
235
+ : `/specrails:${coreCommand}`;
229
236
  const tickets = ids.length ? ' ' + ids.map((id) => `#${id}`).join(' ') : '';
230
237
  return `${head}${tickets} --yes`;
231
238
  }
@@ -267,10 +274,20 @@ function dominantTicketScope(text) {
267
274
  }
268
275
  return sawPerTicket ? 'per-ticket' : 'per-ticket';
269
276
  }
270
- /** True if a prompt references any claude-only command (e.g. Freestyle's canonical token). */
277
+ /** Legacy helper retained for API compatibility. */
271
278
  function referencesClaudeOnlyCommand(text) {
272
279
  for (const m of text.matchAll(CMD_TOKEN_RE)) {
273
- if (COMMANDS_BY_NAME.get(m[1])?.claudeOnly)
280
+ if (COMMANDS_BY_NAME.get(m[1])?.requiredCapability === 'freestyle')
281
+ return true;
282
+ }
283
+ return false;
284
+ }
285
+ /** True when a prompt uses a command the selected provider cannot execute. */
286
+ function referencesUnsupportedProviderCommand(text, provider) {
287
+ const capabilities = (0, registry_1.getAdapter)(provider).capabilities;
288
+ for (const m of text.matchAll(CMD_TOKEN_RE)) {
289
+ const required = COMMANDS_BY_NAME.get(m[1])?.requiredCapability;
290
+ if (required && capabilities[required] !== true)
274
291
  return true;
275
292
  }
276
293
  return false;
@@ -23,6 +23,7 @@ const result_event_1 = require("./result-event");
23
23
  const loop_decider_1 = require("./loop-decider");
24
24
  const rail_isolation_1 = require("./rail-isolation");
25
25
  const feature_flags_1 = require("./feature-flags");
26
+ const runtime_1 = require("./providers/runtime");
26
27
  // Per-step wall-clock caps so a single hung step can't block the engine's
27
28
  // overall deadline check (which only runs between nodes).
28
29
  const AI_STEP_TIMEOUT_MS = 15 * 60_000;
@@ -109,13 +110,10 @@ function aiStepEnv(env, repoDir) {
109
110
  * no-op under danger-full-access on iteration 1.
110
111
  */
111
112
  function aiStepExtraArgs(adapter, cwd, repoDir) {
112
- return !repoDir
113
- ? undefined
114
- : adapter.id === 'claude'
115
- ? ['--add-dir', repoDir]
116
- : adapter.id === 'codex'
117
- ? ['-c', `sandbox_workspace_write.writable_roots=[${JSON.stringify(repoDir)}, ${JSON.stringify(cwd)}]`]
118
- : undefined;
113
+ if (!repoDir)
114
+ return undefined;
115
+ const args = (0, runtime_1.buildProviderRepoAccessArgs)(adapter, [repoDir, ...(adapter.id === 'codex' ? [cwd] : [])]);
116
+ return args.length > 0 ? args : undefined;
119
117
  }
120
118
  function createLoopExecutors(opts = {}) {
121
119
  const resolveEnv = () => typeof opts.env === 'function' ? opts.env() : opts.env ?? process.env;
@@ -150,6 +148,14 @@ function createLoopExecutors(opts = {}) {
150
148
  // agent self-heal on Windows.
151
149
  const stepEnv = aiStepEnv(resolveEnv(), repoDir);
152
150
  const extraArgs = aiStepExtraArgs(adapter, cwd, repoDir);
151
+ const effectivePrompt = (0, runtime_1.formatProviderCommand)(adapter, prompt, cwd, sessionId ?? undefined);
152
+ const buildOpts = {
153
+ prompt: effectivePrompt,
154
+ model,
155
+ sessionId: sessionId ?? undefined,
156
+ reasoning_effort: effort,
157
+ extraArgs,
158
+ };
153
159
  if (repoDir) {
154
160
  try {
155
161
  (0, workspace_manager_1.ensureFrameworkAgents)(cwd, adapter.projectDirName);
@@ -169,12 +175,13 @@ function createLoopExecutors(opts = {}) {
169
175
  // surface the REAL reason (e.g. "You've hit your usage limit") instead of
170
176
  // the `stderrTail`, which often holds only an informational line.
171
177
  let errorText;
178
+ const wallStartedAt = Date.now();
172
179
  const res = await (0, spawn_lifecycle_1.runAiCliInvocation)({
173
180
  adapter,
174
181
  action,
175
- buildOpts: { prompt, model, sessionId: sessionId ?? undefined, reasoning_effort: effort, extraArgs },
182
+ buildOpts,
176
183
  cwd,
177
- env: stepEnv,
184
+ env: (0, runtime_1.buildProviderEnv)(adapter, buildOpts, stepEnv),
178
185
  timeoutMs: aiStepTimeoutMs ?? AI_STEP_TIMEOUT_MS,
179
186
  onSpawn,
180
187
  // Two complementary streams, mirroring QueueManager's contract:
@@ -194,7 +201,10 @@ function createLoopExecutors(opts = {}) {
194
201
  errorText = ev.message;
195
202
  },
196
203
  });
197
- const failed = res.spawnFailed || res.timedOut || (res.code != null && res.code !== 0);
204
+ const failed = res.spawnFailed ||
205
+ res.timedOut ||
206
+ (res.code != null && res.code !== 0) ||
207
+ errorText !== undefined;
198
208
  if (res.spawnFailed) {
199
209
  errorText = errorText ?? `failed to spawn "${adapter.binary}" (on PATH?)`;
200
210
  const msg = `AI step: ${errorText}`;
@@ -219,11 +229,24 @@ function createLoopExecutors(opts = {}) {
219
229
  console.error(`[loop] ${msg}`);
220
230
  onLine?.(msg, 'stderr');
221
231
  }
222
- const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, res.events, { fallbackModel: model });
223
- const tokensIn = result.tokens_in ?? 0;
224
- const tokensOut = result.tokens_out ?? 0;
225
- const tokensCacheRead = result.tokens_cache_read ?? 0;
226
- const tokensCacheCreate = result.tokens_cache_create ?? 0;
232
+ else if (errorText) {
233
+ // A normalized provider error is terminal even if an upstream CLI
234
+ // anomalously reports a clean process exit.
235
+ const msg = `AI step: ${adapter.binary} reported an error — ${errorText}`;
236
+ console.error(`[loop] ${msg}`);
237
+ onLine?.(msg, 'stderr');
238
+ }
239
+ const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, res.events, {
240
+ fallbackModel: model,
241
+ durationMs: Math.max(0, Date.now() - wallStartedAt),
242
+ });
243
+ const tokensIn = result.tokens_in;
244
+ const tokensOut = result.tokens_out;
245
+ const tokensCacheRead = result.tokens_cache_read;
246
+ const tokensCacheCreate = result.tokens_cache_create;
247
+ const tokens = tokensIn === undefined && tokensOut === undefined
248
+ ? undefined
249
+ : (tokensIn ?? 0) + (tokensOut ?? 0);
227
250
  return {
228
251
  text,
229
252
  sessionId: res.sessionId ?? undefined,
@@ -234,7 +257,7 @@ function createLoopExecutors(opts = {}) {
234
257
  // cache tokens or the claude loop-job token display would inflate. The
235
258
  // full cache breakdown is persisted to the ai_invocations row via the
236
259
  // structured tokensCacheRead/tokensCacheCreate fields below.
237
- tokens: tokensIn + tokensOut,
260
+ tokens,
238
261
  tokensIn,
239
262
  tokensOut,
240
263
  tokensCacheRead,
@@ -280,7 +303,7 @@ function createLoopExecutors(opts = {}) {
280
303
  (0, claude_trust_1.ensureClaudeTrusted)(adapter.id, [cwd, repoDir]);
281
304
  }
282
305
  catch { /* best-effort */ }
283
- const args = adapter.buildArgs('chat-stream', {
306
+ const buildOpts = {
284
307
  // chat-stream feeds the prompt over stdin per-turn, so the argv `prompt`
285
308
  // is unused — pass empty to satisfy the shared SpawnOptions shape.
286
309
  prompt: '',
@@ -291,10 +314,11 @@ function createLoopExecutors(opts = {}) {
291
314
  sessionId: sessionId ?? undefined,
292
315
  reasoning_effort: effort,
293
316
  extraArgs,
294
- });
317
+ };
318
+ const args = adapter.buildArgs('chat-stream', buildOpts);
295
319
  return {
296
320
  adapter,
297
- spec: { binary: adapter.binary, args, cwd, env: stepEnv },
321
+ spec: { binary: adapter.binary, args, cwd, env: (0, runtime_1.buildProviderEnv)(adapter, buildOpts, stepEnv) },
298
322
  // The loop's ai-step timeout bounds the WHOLE step, interactive included.
299
323
  stepTimeoutMs: aiStepTimeoutMs ?? AI_STEP_TIMEOUT_MS,
300
324
  };
@@ -309,12 +333,14 @@ function createLoopExecutors(opts = {}) {
309
333
  const decEnv = repoDir ? { ...baseEnv, SPECRAILS_REPO_DIR: repoDir } : baseEnv;
310
334
  // spec-gen is a one-shot, system-prompted invocation (workspace-write on
311
335
  // codex, not full-access) — appropriate for a read-only judgment.
336
+ const buildOpts = { prompt: userPrompt, systemPrompt, model, maxTurns: 1, reasoning_effort: effort, toolPolicy: 'read-only' };
337
+ const wallStartedAt = Date.now();
312
338
  const res = await (0, spawn_lifecycle_1.runAiCliInvocation)({
313
339
  adapter,
314
340
  action: 'spec-gen',
315
- buildOpts: { prompt: userPrompt, systemPrompt, model, maxTurns: 1, reasoning_effort: effort },
341
+ buildOpts,
316
342
  cwd,
317
- env: decEnv,
343
+ env: (0, runtime_1.buildProviderEnv)(adapter, buildOpts, decEnv),
318
344
  timeoutMs: DECIDER_TIMEOUT_MS,
319
345
  onSpawn,
320
346
  onStdoutLine: onRawLine,
@@ -322,11 +348,17 @@ function createLoopExecutors(opts = {}) {
322
348
  text += ev.text; },
323
349
  });
324
350
  const decision = (0, loop_decider_1.parseDeciderDecision)(text);
325
- const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, res.events, { fallbackModel: model });
326
- const tokensIn = result.tokens_in ?? 0;
327
- const tokensOut = result.tokens_out ?? 0;
328
- const tokensCacheRead = result.tokens_cache_read ?? 0;
329
- const tokensCacheCreate = result.tokens_cache_create ?? 0;
351
+ const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, res.events, {
352
+ fallbackModel: model,
353
+ durationMs: Math.max(0, Date.now() - wallStartedAt),
354
+ });
355
+ const tokensIn = result.tokens_in;
356
+ const tokensOut = result.tokens_out;
357
+ const tokensCacheRead = result.tokens_cache_read;
358
+ const tokensCacheCreate = result.tokens_cache_create;
359
+ const tokens = tokensIn === undefined && tokensOut === undefined
360
+ ? undefined
361
+ : (tokensIn ?? 0) + (tokensOut ?? 0);
330
362
  return {
331
363
  ...decision,
332
364
  cost: result.total_cost_usd,
@@ -336,7 +368,7 @@ function createLoopExecutors(opts = {}) {
336
368
  // cache tokens or the claude loop-job token display would inflate. The
337
369
  // full cache breakdown is persisted to the ai_invocations row via the
338
370
  // structured tokensCacheRead/tokensCacheCreate fields below.
339
- tokens: tokensIn + tokensOut,
371
+ tokens,
340
372
  tokensIn,
341
373
  tokensOut,
342
374
  tokensCacheRead,
@@ -42,9 +42,9 @@ exports.FACTORY_LOOPS = [
42
42
  // with full freedom — no pipeline, it works like a regular coding agent.
43
43
  // The id/mode strings are the canonical rail contract.
44
44
  name: 'Freestyle',
45
- description: 'Hands the spec straight to the model with full freedom — no pipeline, it works like a regular coding agent, then verify + refine until green. Claude only.',
45
+ description: 'Hands the spec straight to the model with full freedom — no pipeline, it works like a regular coding agent, then verify + refine until green.',
46
46
  mode: 'freestyle',
47
- claudeOnly: true,
47
+ requiredCapability: 'freestyle',
48
48
  graph: (0, loop_templates_1.fixLoopGraph)(['{{cmd:freestyle}}'], GREEN_GOAL, FACTORY_MAX_ITERATIONS, FACTORY_LOOP_TIMEOUT_MIN, FACTORY_AI_STEP_TIMEOUT_MIN),
49
49
  },
50
50
  SDD_QUICK_OPENSPEC_FACTORY,