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
@@ -19,6 +19,7 @@ const loop_runs_store_1 = require("./loop-runs-store");
19
19
  const ai_invocations_1 = require("./ai-invocations");
20
20
  const ids_1 = require("./ids");
21
21
  const providers_1 = require("./providers");
22
+ const runtime_1 = require("./providers/runtime");
22
23
  const result_event_1 = require("./result-event");
23
24
  const rails_store_1 = require("./rails-store");
24
25
  const IMPLEMENT_CMD_TOKEN_RE = /\{\{\s*cmd:(?:implement|batch)\s*\}\}/;
@@ -153,13 +154,14 @@ function insertLoopInvocation(db, payload, result, finishedAt) {
153
154
  FROM ai_invocations
154
155
  WHERE surface = 'loop' AND loop_run_id = ?
155
156
  `).get(payload.runId);
157
+ const usageTelemetryAvailable = (0, providers_1.getAdapter)(payload.provider).capabilities.reportsUsage !== false;
156
158
  db.prepare(`
157
159
  UPDATE jobs
158
160
  SET total_cost_usd = ?, tokens_in = ?, tokens_out = ?,
159
161
  tokens_cache_read = ?, tokens_cache_create = ?,
160
162
  duration_ms = ?, num_turns = ?
161
163
  WHERE id = ? AND owner = 'loop'
162
- `).run(aggregate.cost, aggregate.tokens_in, aggregate.tokens_out, aggregate.cache_read, aggregate.cache_create, aggregate.duration, aggregate.turns, payload.runId);
164
+ `).run(usageTelemetryAvailable ? aggregate.cost : null, usageTelemetryAvailable ? aggregate.tokens_in : null, usageTelemetryAvailable ? aggregate.tokens_out : null, usageTelemetryAvailable ? aggregate.cache_read : null, usageTelemetryAvailable ? aggregate.cache_create : null, aggregate.duration, usageTelemetryAvailable ? aggregate.turns : null, payload.runId);
163
165
  }
164
166
  /** Recover every AI/decider step that was staged before provider spawn but did
165
167
  * not atomically land its invocation. Completed interactive turns are the jobs
@@ -226,9 +228,9 @@ function recoverOrphanLoopStepAccounting(db, finishedAt = new Date().toISOString
226
228
  ORDER BY seq
227
229
  `).all(payload.runId, payload.completedEventSeq ?? -1);
228
230
  const adapter = (0, providers_1.getAdapter)(payload.provider);
231
+ const usageTelemetryAvailable = adapter.capabilities.reportsUsage !== false;
229
232
  const events = rawRows
230
- .map((raw) => adapter.parseStreamLine(raw.payload))
231
- .filter((event) => event != null);
233
+ .flatMap((raw) => [...(0, runtime_1.parseStreamEvents)(adapter, raw.payload)]);
232
234
  const { result: partial, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, events, {
233
235
  fallbackModel: payload.model ?? undefined,
234
236
  });
@@ -260,19 +262,34 @@ function recoverOrphanLoopStepAccounting(db, finishedAt = new Date().toISOString
260
262
  // never both.
261
263
  const recoveredDurationMs = (payload.completedDurationMs ?? 0) + partialDurationMs;
262
264
  const didRecover = (0, loop_runs_store_1.completeLoopStepRecovery)(db, payload.runId, payload.stepKey, (stable) => {
263
- if (partialUsage.tokens_in || partialUsage.tokens_out ||
264
- partialUsage.tokens_cache_read || partialUsage.tokens_cache_create ||
265
- partialUsage.total_cost_usd || partialUsage.num_turns) {
265
+ if (usageTelemetryAvailable &&
266
+ (partialUsage.tokens_in || partialUsage.tokens_out ||
267
+ partialUsage.tokens_cache_read || partialUsage.tokens_cache_create ||
268
+ partialUsage.total_cost_usd || partialUsage.num_turns)) {
266
269
  (0, db_1.accumulateInteractiveTurn)(db, payload.runId, partialUsage);
267
270
  }
268
271
  insertLoopInvocation(db, stable, {
269
- cost: completed.totalCostUsd + partialUsage.total_cost_usd,
270
- tokens: completed.tokensIn + completed.tokensOut + partialUsage.tokens_in + partialUsage.tokens_out,
271
- tokensIn: completed.tokensIn + partialUsage.tokens_in,
272
- tokensOut: completed.tokensOut + partialUsage.tokens_out,
273
- tokensCacheRead: completed.tokensCacheRead + partialUsage.tokens_cache_read,
274
- tokensCacheCreate: completed.tokensCacheCreate + partialUsage.tokens_cache_create,
275
- numTurns: completed.numTurns + partialUsage.num_turns,
272
+ cost: usageTelemetryAvailable
273
+ ? completed.totalCostUsd + partialUsage.total_cost_usd
274
+ : undefined,
275
+ tokens: usageTelemetryAvailable
276
+ ? completed.tokensIn + completed.tokensOut + partialUsage.tokens_in + partialUsage.tokens_out
277
+ : undefined,
278
+ tokensIn: usageTelemetryAvailable
279
+ ? completed.tokensIn + partialUsage.tokens_in
280
+ : undefined,
281
+ tokensOut: usageTelemetryAvailable
282
+ ? completed.tokensOut + partialUsage.tokens_out
283
+ : undefined,
284
+ tokensCacheRead: usageTelemetryAvailable
285
+ ? completed.tokensCacheRead + partialUsage.tokens_cache_read
286
+ : undefined,
287
+ tokensCacheCreate: usageTelemetryAvailable
288
+ ? completed.tokensCacheCreate + partialUsage.tokens_cache_create
289
+ : undefined,
290
+ numTurns: usageTelemetryAvailable
291
+ ? completed.numTurns + partialUsage.num_turns
292
+ : undefined,
276
293
  durationMs: recoveredDurationMs,
277
294
  model: partial.model ?? payload.model ?? undefined,
278
295
  sessionId: partial.session_id,
@@ -474,6 +491,14 @@ class LoopRunManager {
474
491
  async run(req) {
475
492
  if (this._disposed)
476
493
  throw new Error('LoopRunManager is shut down');
494
+ const adapter = (0, providers_1.getAdapter)(req.provider);
495
+ // A Decider is a structured, read-only judgment over repository state.
496
+ // Prompt wording is not a permission boundary: reject before allocating or
497
+ // persisting the run when the CLI cannot enforce read-only natively.
498
+ if (req.graph.nodes.some((node) => node.type === 'decider')) {
499
+ (0, providers_1.requireToolPolicy)(adapter, 'read-only');
500
+ }
501
+ const usageTelemetryAvailable = adapter.capabilities.reportsUsage !== false;
477
502
  const neverAfterDispose = () => new Promise(() => { });
478
503
  const runId = req.runId ?? (0, ids_1.newId)();
479
504
  const maxIterations = req.graph.config.maxIterations;
@@ -489,9 +514,13 @@ class LoopRunManager {
489
514
  // cap (may overshoot by at most one step). Honest accuracy caveat: for
490
515
  // non-Claude providers the per-step cost is ESTIMATED (rate card) — see the
491
516
  // fail-open warning below when a step yields no priced cost.
492
- const maxCostUsd = typeof req.graph.config.maxCostUsd === 'number' && req.graph.config.maxCostUsd > 0
517
+ const configuredMaxCostUsd = typeof req.graph.config.maxCostUsd === 'number' && req.graph.config.maxCostUsd > 0
493
518
  ? req.graph.config.maxCostUsd
494
519
  : undefined;
520
+ // A cap with no observable usage is not a guard at all. Disable it rather
521
+ // than pretending an unknown bill is $0 and surface the limitation in the
522
+ // run log below.
523
+ const maxCostUsd = usageTelemetryAvailable ? configuredMaxCostUsd : undefined;
495
524
  const launchStartedAt = new Date(this.now()).toISOString();
496
525
  const jobCommand = `loop: ${req.loopName ?? req.loopId}${req.ticketId != null ? ` #${req.ticketId}` : ''}`;
497
526
  const exactTicketIds = req.spec?.ticketIds ?? (req.ticketId == null ? [] : [req.ticketId]);
@@ -610,6 +639,8 @@ class LoopRunManager {
610
639
  const parsed = JSON.parse(line);
611
640
  if (typeof parsed.type === 'string')
612
641
  eventType = parsed.type;
642
+ else if (typeof parsed.role === 'string')
643
+ eventType = parsed.role;
613
644
  }
614
645
  catch { /* not JSON */ }
615
646
  if (!eventType) {
@@ -635,6 +666,12 @@ class LoopRunManager {
635
666
  logLine(`▶ Loop "${req.loopName ?? req.loopId}" started${req.spec?.title ? ` — spec: ${req.spec.title}` : ''}`);
636
667
  if (req.isolation)
637
668
  logLine(`⎇ Isolated worktree: ${req.isolation.worktreePath} (branch ${req.isolation.branch})`);
669
+ if (!usageTelemetryAvailable) {
670
+ logLine(`⚠️ ${adapter.displayName} does not report token/cost usage in headless mode; usage totals will remain unavailable.` +
671
+ (configuredMaxCostUsd !== undefined
672
+ ? ' The configured maxCostUsd guard is disabled because it cannot be verified.'
673
+ : ''), 'stderr');
674
+ }
638
675
  // Per-run graph SNAPSHOT — once, before the first loop_step — so a later
639
676
  // edit/delete of the loop never breaks the historical replay of this run.
640
677
  const graphPayload = {
@@ -655,11 +692,11 @@ class LoopRunManager {
655
692
  let totalTokens = 0;
656
693
  let totalDuration = 0;
657
694
  let finalJobUsage = {
658
- tokensIn: 0,
659
- tokensOut: 0,
660
- tokensCacheRead: 0,
661
- tokensCacheCreate: 0,
662
- numTurns: 0,
695
+ tokensIn: usageTelemetryAvailable ? 0 : null,
696
+ tokensOut: usageTelemetryAvailable ? 0 : null,
697
+ tokensCacheRead: usageTelemetryAvailable ? 0 : null,
698
+ tokensCacheCreate: usageTelemetryAvailable ? 0 : null,
699
+ numTurns: usageTelemetryAvailable ? 0 : null,
663
700
  };
664
701
  let aiSessionId;
665
702
  // Consecutive AI steps that hard-failed with no output (provider down /
@@ -706,13 +743,16 @@ class LoopRunManager {
706
743
  // The REAL turn-start instant, captured before the step/decider await. The
707
744
  // row is bucketed/ordered by started_at, so it must be the start, not finish.
708
745
  startedAt, stepKey) => {
709
- totalCost += r.cost ?? 0;
746
+ if (usageTelemetryAvailable)
747
+ totalCost += r.cost ?? 0;
710
748
  // A cost-bearing step that produced work (tokens) or hard-failed but reports
711
749
  // no priced cost → its real spend is missing from the total. The common case
712
750
  // is a claude step killed by timeout before its terminal `result` event:
713
751
  // tokens streamed, but cost (and tokens) are dropped, so the step bills $0.
714
752
  // Flag the run total as a lower bound and say so, per occurrence.
715
- const costBearingButUnpriced = r.cost == null && (r.failed === true || (r.tokens ?? 0) > 0);
753
+ const costBearingButUnpriced = usageTelemetryAvailable
754
+ && r.cost == null
755
+ && (r.failed === true || (r.tokens ?? 0) > 0);
716
756
  if (costBearingButUnpriced) {
717
757
  costUncertain = true;
718
758
  costUnknownWarned = true; // this line already carries the cap caveat below
@@ -720,11 +760,16 @@ class LoopRunManager {
720
760
  }
721
761
  // Honest cost-cap caveat: a cost-bearing step that reports no figure means
722
762
  // the cap can't be enforced precisely from here on. Warn once (live).
723
- if (maxCostUsd !== undefined && r.cost == null && !costUnknownWarned) {
763
+ if (usageTelemetryAvailable
764
+ && maxCostUsd !== undefined
765
+ && r.cost == null
766
+ && !costUnknownWarned) {
724
767
  costUnknownWarned = true;
725
768
  logLine('⚠️ A step reported no priced cost (non-Claude estimate / unknown model / failed step) — the cost cap may under-count.', 'stderr');
726
769
  }
727
- totalTokens += r.tokens ?? ((r.tokensIn ?? 0) + (r.tokensOut ?? 0));
770
+ if (usageTelemetryAvailable) {
771
+ totalTokens += r.tokens ?? ((r.tokensIn ?? 0) + (r.tokensOut ?? 0));
772
+ }
728
773
  totalDuration += r.durationMs ?? 0;
729
774
  const finishedAt = new Date(this.now()).toISOString();
730
775
  if (stepKey) {
@@ -1237,7 +1282,7 @@ class LoopRunManager {
1237
1282
  // session so the next pass starts fresh (re-reads the code on disk).
1238
1283
  // Provider-agnostic: clearing aiSessionId makes runAiStep use the
1239
1284
  // 'rail-job' (fresh) action, which every adapter maps to its own
1240
- // native spawn — no claude/codex/gemini branching here.
1285
+ // native spawn — no claude/codex/gemini/kimi branching here.
1241
1286
  if (target === firstStepId)
1242
1287
  aiSessionId = undefined;
1243
1288
  }
@@ -1303,8 +1348,10 @@ class LoopRunManager {
1303
1348
  FROM ai_invocations
1304
1349
  WHERE surface = 'loop' AND loop_run_id = ?
1305
1350
  `).get(runId);
1306
- totalCost = aggregate.cost;
1307
- totalTokens = aggregate.tokens_in + aggregate.tokens_out;
1351
+ if (usageTelemetryAvailable) {
1352
+ totalCost = aggregate.cost;
1353
+ totalTokens = aggregate.tokens_in + aggregate.tokens_out;
1354
+ }
1308
1355
  if (recoveredSteps > 0) {
1309
1356
  // Recovery already committed the authoritative D+X totals. Refresh the
1310
1357
  // traversal locals before finishLoopRunAndJob; otherwise a catch path
@@ -1319,18 +1366,21 @@ class LoopRunManager {
1319
1366
  iteration = Math.max(iteration, durable.iteration_count);
1320
1367
  }
1321
1368
  }
1322
- finalJobUsage = {
1323
- tokensIn: aggregate.tokens_in,
1324
- tokensOut: aggregate.tokens_out,
1325
- tokensCacheRead: aggregate.cache_read,
1326
- tokensCacheCreate: aggregate.cache_create,
1327
- numTurns: aggregate.turns,
1328
- };
1369
+ if (usageTelemetryAvailable) {
1370
+ finalJobUsage = {
1371
+ tokensIn: aggregate.tokens_in,
1372
+ tokensOut: aggregate.tokens_out,
1373
+ tokensCacheRead: aggregate.cache_read,
1374
+ tokensCacheCreate: aggregate.cache_create,
1375
+ numTurns: aggregate.turns,
1376
+ };
1377
+ }
1329
1378
  }
1330
1379
  catch (err) {
1331
1380
  console.error(`[loop] staged accounting reconciliation failed for ${runId}:`, err);
1332
1381
  }
1333
- console.log(`[loop] settle run=${runId} outcome=${outcome} iterations=${iteration} cost=$${totalCost.toFixed(4)}`);
1382
+ console.log(`[loop] settle run=${runId} outcome=${outcome} iterations=${iteration} ` +
1383
+ (usageTelemetryAvailable ? `cost=$${totalCost.toFixed(4)}` : 'usage=unavailable'));
1334
1384
  // Settle the backing job so the Jobs list + JobDetail reflect the final
1335
1385
  // status, and emit job.finalized so an open JobDetail re-fetches + stops the
1336
1386
  // live stream (mirrors QueueManager).
@@ -1341,14 +1391,20 @@ class LoopRunManager {
1341
1391
  : outcome === 'stopped' || outcome === 'stalled' ? 'canceled'
1342
1392
  : 'failed';
1343
1393
  // `≥` when any cost-bearing step ended unpriced (timeout/crash) — the figure
1344
- // is a lower bound, not exact.
1345
- logLine(`\n■ Loop finished: ${outcome} — ${iteration} iteration${iteration === 1 ? '' : 's'}, ${costUncertain ? '≥ ' : ''}$${totalCost.toFixed(4)}`);
1394
+ // is a lower bound, not exact. Providers without usage telemetry get an
1395
+ // explicit unavailable marker, never a fabricated "$0.0000".
1396
+ logLine(`\n■ Loop finished: ${outcome} — ${iteration} iteration${iteration === 1 ? '' : 's'}, ` +
1397
+ (usageTelemetryAvailable
1398
+ ? `${costUncertain ? '≥ ' : ''}$${totalCost.toFixed(4)}`
1399
+ : 'usage/cost unavailable'));
1346
1400
  const finishedAt = new Date(this.now()).toISOString();
1347
1401
  (0, loop_runs_store_1.finishLoopRunAndJob)(this.db, runId, {
1348
1402
  outcome,
1349
1403
  finishedAt,
1350
1404
  counters: {
1351
1405
  iterationCount: iteration,
1406
+ // loop_runs retains its legacy non-null internal counters; public/job
1407
+ // telemetry below carries the honest nullable availability contract.
1352
1408
  totalCostUsd: totalCost,
1353
1409
  totalTokens,
1354
1410
  totalDurationMs: totalDuration,
@@ -1356,7 +1412,7 @@ class LoopRunManager {
1356
1412
  job: {
1357
1413
  exitCode: outcome === 'success' ? 0 : 1,
1358
1414
  status: jobStatus,
1359
- totalCostUsd: totalCost,
1415
+ totalCostUsd: usageTelemetryAvailable ? totalCost : null,
1360
1416
  tokensIn: finalJobUsage.tokensIn,
1361
1417
  tokensOut: finalJobUsage.tokensOut,
1362
1418
  tokensCacheRead: finalJobUsage.tokensCacheRead,
@@ -1377,7 +1433,7 @@ class LoopRunManager {
1377
1433
  tokens_out: finalJobUsage.tokensOut,
1378
1434
  tokens_cache_read: finalJobUsage.tokensCacheRead,
1379
1435
  tokens_cache_create: finalJobUsage.tokensCacheCreate,
1380
- total_cost_usd: totalCost,
1436
+ total_cost_usd: usageTelemetryAvailable ? totalCost : null,
1381
1437
  num_turns: finalJobUsage.numTurns,
1382
1438
  },
1383
1439
  timestamp: new Date(this.now()).toISOString(),
@@ -1390,7 +1446,12 @@ class LoopRunManager {
1390
1446
  status: outcome,
1391
1447
  ticketIds: exactTicketIds,
1392
1448
  });
1393
- return { runId, outcome, iterations: iteration, totalCostUsd: totalCost };
1449
+ return {
1450
+ runId,
1451
+ outcome,
1452
+ iterations: iteration,
1453
+ totalCostUsd: usageTelemetryAvailable ? totalCost : null,
1454
+ };
1394
1455
  }
1395
1456
  /**
1396
1457
  * Run ONE ai-step as a resident interactive session (settleMode 'auto'):
@@ -64,7 +64,7 @@ function registerLoopsRoutes(router, deps) {
64
64
  name: f.name,
65
65
  description: f.description,
66
66
  mode: f.mode,
67
- claudeOnly: f.claudeOnly ?? false,
67
+ requiredCapability: f.requiredCapability ?? null,
68
68
  graph: f.graph,
69
69
  })),
70
70
  });
@@ -17,7 +17,7 @@ differs by client kind (see below).
17
17
 
18
18
  Specrails is a local dashboard + pipeline runner that manages multiple software
19
19
  projects (registered repositories) and drives AI coding agents (Claude Code,
20
- Codex, Gemini) to implement specs.
20
+ Codex, Gemini, Kimi Code) to implement specs.
21
21
 
22
22
  ## The object model
23
23
 
@@ -46,8 +46,8 @@ Codex, Gemini) to implement specs.
46
46
  - **Loop**: an APP-LEVEL saved workflow graph (not project-scoped). Author with
47
47
  \`specrails_loops\`; RUN it with \`specrails_rails(launch, mode:'loop', loopId)\`.
48
48
  - **Profile**: per-project agent configuration (which agents, which models,
49
- routing). CLAUDE-ONLY; forced to null for codex/gemini rails.
50
- - **Provider / engine**: claude, codex or gemini. A project installs one or
49
+ routing). Supported by Claude and Kimi; forced to null for Codex/Gemini rails.
50
+ - **Provider / engine**: claude, codex, gemini or kimi. A project installs one or
51
51
  more; a requested engine must be one of the installed set.
52
52
  - **Plugin**: an MCP-based integration installed per project (e.g. serena).
53
53
 
@@ -135,15 +135,15 @@ heading inside the description); \`labels\`; \`priority\`. Spec content is Engli
135
135
  - \`implement\`: one pipeline job (Architect → Developer → Reviewer → Ship)
136
136
  over the rail's tickets.
137
137
  - \`batch-implement\`: dependency-aware waves across many tickets.
138
- - Freestyle: sends a free-form autonomous prompt straight to Claude — one job
139
- per ticket; Claude-only; \`model\` picker; optional \`interactive\` in-job
140
- chat (settle with \`specrails_jobs(finalize)\`). To launch it through the API,
141
- pass the canonical mode value \`freestyle\`. In user-facing language, call
138
+ - Freestyle: sends a free-form autonomous prompt to a capable provider — one
139
+ job per ticket; Claude and Kimi; \`model\` picker. Claude additionally
140
+ supports optional \`interactive\` in-job chat (settle with
141
+ \`specrails_jobs(finalize)\`). To launch it through the API, pass the canonical mode value \`freestyle\`. In user-facing language, call
142
142
  the feature "Freestyle".
143
143
  - \`loop\`: runs a published loop graph per ticket (\`loopId\`,
144
144
  \`reasoning_effort\`).
145
- - Profiles are Claude-only: a profile set on a rail that is then pointed at
146
- codex/gemini is force-nulled.
145
+ - Profiles are supported by Claude and Kimi: a profile set on a rail that is
146
+ then pointed at Codex/Gemini is force-nulled.
147
147
  - \`stop\` kills the rail's process tree AND cancels its queued jobs
148
148
  (destructive).
149
149
  - \`specrails_jobs(spawn, command)\` bypasses rails and enqueues an arbitrary
@@ -196,20 +196,27 @@ global update work. Note the
196
196
  embedded spec-refinement happy path (investigate + commit_draft) needs only
197
197
  read + write — ai-spawn is required only to launch work or spawn a nested AI.
198
198
 
199
- ## Providers & Claude-only surface
199
+ ## Providers & capability-gated surfaces
200
200
 
201
201
  - Installed providers are per-project; AI-spawning calls may pick any installed
202
202
  one (\`aiEngine\`); rails carry a per-rail engine.
203
- - CLAUDE-ONLY: agent profiles, Contract Refine, SMASH, Freestyle mode (API mode
204
- \`freestyle\`; say "Freestyle" to users), interactive jobs. They are
205
- rejected or inert when the effective engine is codex or gemini.
206
- - Cost figures are authoritative for claude and estimated for codex/gemini
207
- (flagged as estimated in analytics).
203
+ - Claude and Kimi support agent profiles and Freestyle mode (pass the canonical
204
+ API value \`freestyle\`; call the feature "Freestyle" to users). Persistent
205
+ interactive jobs remain Claude-only.
206
+ - Kimi prompt mode cannot enforce a no-tools or read-only boundary. Consequently
207
+ pure-output and safety-bounded surfaces fail closed before spawn: Quick Spec,
208
+ AI Edit, Contract Refine, SMASH, Builder chat/commit, milestone generation,
209
+ Loop Decider, Code Explorer AI summaries, and Agent Studio automation. Use
210
+ Explore/direct authoring or another installed provider for those surfaces.
211
+ - Cost figures are authoritative for Claude and estimated for Codex/Gemini
212
+ (flagged as estimated in analytics). Kimi cost is unavailable when its stream
213
+ omits usage and billing data.
208
214
 
209
215
  ## Domain cheat-sheet
210
216
 
211
217
  - **Epics / SMASH** (\`specrails_specs\`): \`smash\` splits a large spec into child
212
- specs (Claude-only); \`smash_undo\` restores (needs the \`smashedAt\` stamp);
218
+ specs with a structured-action provider (currently Claude); \`smash_undo\`
219
+ restores (needs the \`smashedAt\` stamp);
213
220
  \`delete_epic_children\` removes a whole family.
214
221
  - **Attachments**: \`list_attachments\` / \`get_attachment\` read files the user
215
222
  attached in the app UI; \`generate\` / \`ai_edit\` accept \`attachmentIds\`.