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
@@ -37,6 +37,11 @@ function finaliseInvocationResult(adapter, events, opts = {}) {
37
37
  if (!cloned.model && opts.fallbackModel) {
38
38
  cloned.model = opts.fallbackModel;
39
39
  }
40
+ if (cloned.duration_ms == null &&
41
+ typeof opts.durationMs === 'number' &&
42
+ Number.isFinite(opts.durationMs)) {
43
+ cloned.duration_ms = Math.max(0, opts.durationMs);
44
+ }
40
45
  let estimated = false;
41
46
  // Guard: when the breakdown carries NO billable usage (every token field
42
47
  // undefined/0 — e.g. a codex/gemini turn aborted/crashed before its
@@ -26,7 +26,7 @@
26
26
  "provider": {
27
27
  "type": "string",
28
28
  "pattern": "^[a-z0-9][a-z0-9-]*$",
29
- "description": "Optional provider id (e.g. `claude`, `codex`). When set, the profile's model values are validated against that provider's adapter catalog. When omitted, validation falls back to the project's resolved provider."
29
+ "description": "Optional registered provider id (for example `claude`, `codex`, `gemini`, or `kimi`). When set, the profile's model values are validated according to that provider adapter: normally against its catalog, while adapters that support configured aliases (such as Kimi) accept any schema-valid non-empty alias. When omitted, validation falls back to the project's resolved provider."
30
30
  },
31
31
  "orchestrator": {
32
32
  "type": "object",
@@ -82,8 +82,7 @@
82
82
  "modelAlias": {
83
83
  "type": "string",
84
84
  "minLength": 1,
85
- "maxLength": 64,
86
- "description": "Accepted model alias. JSON schema accepts any non-empty string; provider-specific catalog enforcement runs at runtime (see profile-manager.validateStructural)."
85
+ "description": "Accepted model alias. JSON schema accepts any non-empty string without truncating provider-configured aliases; provider-specific catalog enforcement runs at runtime (see profile-manager.validateStructural)."
87
86
  },
88
87
  "agentEntry": {
89
88
  "type": "object",
@@ -93,7 +92,7 @@
93
92
  "id": {
94
93
  "type": "string",
95
94
  "pattern": "^(sr|custom)-[a-z0-9][a-z0-9-]*$",
96
- "description": "Agent identifier. MUST correspond to a file at `.claude/agents/<id>.md`."
95
+ "description": "Agent identifier. MUST correspond to the selected provider's provider-native role artifact. File-based providers use their own agents catalog (for example `.claude/agents/<id>.md`); Kimi uses the directly discoverable `.kimi-code/skills/<id>/SKILL.md` layout."
97
96
  },
98
97
  "model": {
99
98
  "$ref": "#/$defs/modelAlias",
@@ -20,6 +20,7 @@ const win_spawn_1 = require("./util/win-spawn");
20
20
  const setup_prerequisites_1 = require("./setup-prerequisites");
21
21
  const core_package_1 = require("./core-package");
22
22
  const providers_1 = require("./providers");
23
+ const runtime_1 = require("./providers/runtime");
23
24
  const result_event_1 = require("./result-event");
24
25
  const ai_invocations_1 = require("./ai-invocations");
25
26
  const crypto_1 = require("crypto");
@@ -240,21 +241,29 @@ exports.QUICK_CHECKPOINTS = [
240
241
  { key: 'base_install', name: 'Base installation' },
241
242
  { key: 'quick_complete', name: 'Quick install complete' },
242
243
  ];
243
- function checkFilesystem(projectPath) {
244
- const dir = SPECRAILS_DIR;
244
+ function checkFilesystem(projectPath, provider = 'claude') {
245
+ const adapter = (0, providers_1.hasAdapter)(provider) ? (0, providers_1.getAdapter)(provider) : (0, providers_1.getAdapter)('claude');
246
+ const dir = adapter.projectDirName;
247
+ const artifactState = setupArtifactState(projectPath, 'full', provider);
245
248
  const hasBaseInstall = (0, fs_1.existsSync)((0, path_1.join)(projectPath, '.specrails', 'specrails-version')) ||
246
249
  (0, fs_1.existsSync)((0, path_1.join)(projectPath, '.specrails-version'));
247
250
  const hasSetupTemplates = (0, fs_1.existsSync)((0, path_1.join)(projectPath, '.specrails', 'setup-templates')) ||
248
251
  (0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'setup-templates'));
249
252
  const hasRules = (0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'rules')) &&
250
253
  hasFiles((0, path_1.join)(projectPath, dir, 'rules'), /\.md$/);
251
- const hasPersonas = (0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'agents', 'personas')) &&
252
- hasFiles((0, path_1.join)(projectPath, dir, 'agents', 'personas'), /\.md$/);
253
- const hasAgents = (0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'agents')) &&
254
- hasFiles((0, path_1.join)(projectPath, dir, 'agents'), /^sr-.*\.md$/);
255
- const hasCommands = (((0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'commands', 'sr')) && hasFiles((0, path_1.join)(projectPath, dir, 'commands', 'sr'), /\.md$/)) ||
256
- ((0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'commands', 'specrails')) && hasFiles((0, path_1.join)(projectPath, dir, 'commands', 'specrails'), /\.md$/)));
257
- const hasCLAUDE = (0, fs_1.existsSync)((0, path_1.join)(projectPath, 'CLAUDE.md'));
254
+ const hasPersonas = artifactState.hasPersonas;
255
+ const hasAgents = artifactState.hasAgents;
256
+ const hasCommands = artifactState.hasCommands;
257
+ const instructionCandidates = [(0, path_1.join)(projectPath, adapter.instructionsFilename)];
258
+ // Older Core releases sometimes placed a top-level instructions filename
259
+ // inside the provider directory. Preserve that compatibility only for
260
+ // actual filenames: Kimi's adapter already declares the provider-relative
261
+ // `.kimi-code/AGENTS.md` path, so prefixing projectDirName again would probe
262
+ // the nonsensical `.kimi-code/.kimi-code/AGENTS.md`.
263
+ if (adapter.instructionsFilename === (0, path_1.basename)(adapter.instructionsFilename)) {
264
+ instructionCandidates.push((0, path_1.join)(projectPath, dir, adapter.instructionsFilename));
265
+ }
266
+ const hasInstructions = instructionCandidates.some((candidate) => (0, fs_1.existsSync)(candidate));
258
267
  const hasInstallConfig = (0, fs_1.existsSync)((0, path_1.join)(projectPath, '.specrails', 'install-config.yaml')) ||
259
268
  (0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'install-config.yaml'));
260
269
  const hasAgentConfig = (0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'agents.yaml'));
@@ -264,7 +273,7 @@ function checkFilesystem(projectPath) {
264
273
  // Back-compat filesystem signals from older cores are translated to the
265
274
  // current integration-contract checkpoint keys.
266
275
  agent_selection: hasInstallConfig || hasAgentConfig || hasBacklogConfig || hasAgents || hasCommands,
267
- codebase_analysis: hasBaseInstall && (hasCLAUDE || hasSetupTemplates),
276
+ codebase_analysis: hasBaseInstall && (hasInstructions || hasSetupTemplates),
268
277
  vpc_discovery: hasPersonas,
269
278
  persona_synthesis: hasPersonas,
270
279
  agent_generation: hasAgents,
@@ -355,19 +364,19 @@ function detectCheckpointFromText(text) {
355
364
  if (/\/agents\/sr-[^/]+\.md/.test(text)) {
356
365
  hits.push({ key: 'agent_generation', detail: 'Writing agents...' });
357
366
  }
358
- // Codex path: .codex/skills/sr-<name>/SKILL.md (rail skills ship in
359
- // specrails-core 4.6.0+ — see openspec/.../specs/setup-wizard… for the
360
- // checkpoint protocol shared across providers).
361
- if (/\.codex\/skills\/sr-[^/]+\/SKILL\.md/.test(text)) {
367
+ // Provider-native rail skills. Kimi's upstream discovery contract scans only
368
+ // direct children of `.kimi-code/skills`, so its roles are top-level
369
+ // `.kimi-code/skills/sr-*/SKILL.md` entries. Codex may also use `rails/`.
370
+ if (/\.(?:codex|kimi-code)\/skills\/(?:rails\/)?sr-[^/]+\/SKILL\.md/.test(text)) {
362
371
  hits.push({ key: 'agent_generation', detail: 'Writing agent skills...' });
363
372
  }
364
373
  if ((text.includes('/commands/sr/') || text.includes('/commands/specrails/')) && text.includes('.md')) {
365
374
  hits.push({ key: 'command_generation', detail: 'Writing commands...' });
366
375
  }
367
- // Codex enrich/doctor skills (the non-rail commands) also indicate
376
+ // Provider-native enrich/doctor skills (the non-rail commands) also indicate
368
377
  // command_generation progress.
369
- if (/\.codex\/skills\/(enrich|doctor)\/SKILL\.md/.test(text)) {
370
- hits.push({ key: 'command_generation', detail: 'Writing codex command skills...' });
378
+ if (/\.(?:codex|kimi-code)\/skills\/(?:specrails-)?(?:enrich|doctor)\/SKILL\.md/.test(text)) {
379
+ hits.push({ key: 'command_generation', detail: 'Writing provider command skills...' });
371
380
  }
372
381
  if (text.includes('/rules/') && text.includes('.md')) {
373
382
  hits.push({ key: 'command_generation', detail: 'Writing conventions...' });
@@ -456,24 +465,33 @@ function computeSummary(projectPath, tier, provider = 'claude') {
456
465
  let specrailsCommands = 0;
457
466
  let opsxCommands = 0;
458
467
  try {
459
- if (provider === 'codex') {
460
- // Codex layout: every artefact ships as a SKILL under `.codex/skills/`.
468
+ if (provider === 'codex' || provider === 'kimi') {
469
+ // Codex/Kimi layout: every artefact ships as a SKILL under the provider's
470
+ // `skills/` root.
461
471
  // - agents = rail personas (`skills/rails/sr-*/SKILL.md`) + orchestrator
462
- // skills at the root with an `sr-` prefix (sr-implement,
463
- // sr-batch-implement, …)
472
+ // skills at the root with an `sr-` prefix. Kimi roles MUST be
473
+ // direct children (`skills/sr-*/SKILL.md`) because upstream
474
+ // Kimi discovery is intentionally one level deep.
464
475
  // - opsxCommands = `skills/openspec-*/SKILL.md`
465
476
  // - specrailsCommands = everything else under `skills/` (ported claude
466
477
  // slash commands like propose-spec, explore-spec, retry, doctor,
467
478
  // enrich, vpc-drift, …)
468
- // - personas = 0 today; codex VPC pass not implemented yet.
469
- const skillsDir = (0, path_1.join)(projectPath, '.codex', 'skills');
479
+ // - personas = Kimi's provider-local `.kimi-code/personas/*.md`; Codex
480
+ // keeps its legacy nested skill representation.
481
+ const skillsDir = (0, path_1.join)(projectPath, provider === 'kimi' ? '.kimi-code' : '.codex', 'skills');
470
482
  if ((0, fs_1.existsSync)(skillsDir)) {
471
- // Rails (always counted as agents).
483
+ // Codex retains its nested Rails catalog. Kimi cannot: nested skills
484
+ // are not discoverable by the Kimi CLI.
472
485
  const railsDir = (0, path_1.join)(skillsDir, 'rails');
473
- if ((0, fs_1.existsSync)(railsDir)) {
486
+ if (provider === 'codex' && (0, fs_1.existsSync)(railsDir)) {
474
487
  for (const entry of (0, fs_1.readdirSync)(railsDir)) {
475
- if ((0, fs_1.existsSync)((0, path_1.join)(railsDir, entry, 'SKILL.md')))
488
+ if (entry === 'personas') {
489
+ const personasDir = (0, path_1.join)(railsDir, entry);
490
+ personas = (0, fs_1.readdirSync)(personasDir).filter((persona) => (0, fs_1.existsSync)((0, path_1.join)(personasDir, persona, 'SKILL.md'))).length;
491
+ }
492
+ else if ((0, fs_1.existsSync)((0, path_1.join)(railsDir, entry, 'SKILL.md'))) {
476
493
  agents++;
494
+ }
477
495
  }
478
496
  }
479
497
  // Top-level skill dirs.
@@ -490,6 +508,14 @@ function computeSummary(projectPath, tier, provider = 'claude') {
490
508
  specrailsCommands++;
491
509
  }
492
510
  }
511
+ if (provider === 'kimi') {
512
+ const personasDir = (0, path_1.join)(projectPath, '.kimi-code', 'personas');
513
+ if ((0, fs_1.existsSync)(personasDir)) {
514
+ personas = (0, fs_1.readdirSync)(personasDir)
515
+ .filter((entry) => entry.endsWith('.md'))
516
+ .length;
517
+ }
518
+ }
493
519
  }
494
520
  else {
495
521
  // Claude / Gemini layout: agents at `<dir>/agents/sr-*.md`, slash commands
@@ -510,10 +536,18 @@ function computeSummary(projectPath, tier, provider = 'claude') {
510
536
  }
511
537
  }
512
538
  const commandsDirSpecrails = (0, path_1.join)(projectPath, dir, 'commands', 'specrails');
539
+ const commandsDirLegacySr = (0, path_1.join)(projectPath, dir, 'commands', 'sr');
513
540
  const commandsDirOpsx = (0, path_1.join)(projectPath, dir, 'commands', 'opsx');
514
541
  if ((0, fs_1.existsSync)(commandsDirSpecrails)) {
515
542
  specrailsCommands = (0, fs_1.readdirSync)(commandsDirSpecrails).filter((f) => f.endsWith(commandExt)).length;
516
543
  }
544
+ if (specrailsCommands === 0 && (0, fs_1.existsSync)(commandsDirLegacySr)) {
545
+ // Core <=4.1 used commands/sr. Count it only when the canonical
546
+ // specrails tree has no commands so a transition install is never
547
+ // doubled but an empty pre-created directory cannot hide real legacy
548
+ // artefacts.
549
+ specrailsCommands = (0, fs_1.readdirSync)(commandsDirLegacySr).filter((f) => f.endsWith(commandExt)).length;
550
+ }
517
551
  if ((0, fs_1.existsSync)(commandsDirOpsx)) {
518
552
  opsxCommands = (0, fs_1.readdirSync)(commandsDirOpsx).filter((f) => f.endsWith(commandExt)).length;
519
553
  }
@@ -524,6 +558,35 @@ function computeSummary(projectPath, tier, provider = 'claude') {
524
558
  }
525
559
  return { agents, specrailsCommands, opsxCommands, personas, legacySrRemoved: 0, tier, provider };
526
560
  }
561
+ /**
562
+ * Resolve completion against the selected provider's real filesystem layout.
563
+ * A legacy `.claude` fallback remains intentional only for Codex/Gemini:
564
+ * older Core releases scaffolded Claude artefacts for those selections.
565
+ * Kimi never had such a released legacy Core target; accepting a mixed
566
+ * project's `.claude` tree would falsely report a missing `.kimi-code` setup
567
+ * as complete.
568
+ */
569
+ function setupArtifactState(projectPath, tier, provider) {
570
+ const nativeSummary = computeSummary(projectPath, tier, provider);
571
+ const supportsLegacyClaudeFallback = provider === 'codex' || provider === 'gemini';
572
+ const legacySummary = supportsLegacyClaudeFallback
573
+ ? computeSummary(projectPath, tier, 'claude')
574
+ : nativeSummary;
575
+ const nativeHasCommands = nativeSummary.specrailsCommands + nativeSummary.opsxCommands > 0;
576
+ const legacyHasCommands = legacySummary.specrailsCommands + legacySummary.opsxCommands > 0;
577
+ const nativeComplete = nativeSummary.agents > 0 && nativeHasCommands;
578
+ const legacyComplete = legacySummary.agents > 0 && legacyHasCommands;
579
+ const selected = nativeComplete || !legacyComplete ? nativeSummary : legacySummary;
580
+ return {
581
+ // Preserve the actual selected provider for UI labels even when the
582
+ // artefacts came from the legacy Claude compatibility tree.
583
+ summary: { ...selected, provider },
584
+ hasAgents: nativeSummary.agents > 0 || legacySummary.agents > 0,
585
+ hasCommands: nativeHasCommands || legacyHasCommands,
586
+ hasPersonas: nativeSummary.personas > 0 || legacySummary.personas > 0,
587
+ complete: nativeComplete || legacyComplete,
588
+ };
589
+ }
527
590
  /**
528
591
  * Deletes the deprecated `.claude/commands/sr/` directory (if present) and returns
529
592
  * the number of `.md` files that were removed. Safe to call even if the directory
@@ -934,16 +997,22 @@ class SetupManager {
934
997
  this._projectNames.set(projectId, projectName);
935
998
  this._projectTiers.set(projectId, 'full');
936
999
  this._initCheckpoints(projectId);
1000
+ // Resolve the relocated artifact workspace before touching any provider
1001
+ // directories. The imported source repo must remain pristine.
1002
+ const enrichSlug = (0, artifact_registry_1.resolveArtifacts)(projectPath).entry?.slug;
1003
+ if (enrichSlug)
1004
+ this._projectSlugs.set(projectId, enrichSlug);
1005
+ const enrichRoot = this._artifactRoot(projectId, projectPath);
937
1006
  // Pre-create the directory structure that /specrails:enrich will write to.
938
1007
  // Claude Code's Write tool does not create parent directories automatically —
939
1008
  // if a target directory doesn't exist the write fails and Claude reports a
940
1009
  // misleading "write permissions aren't enabled" error. Creating the dirs
941
1010
  // here ensures enrich runs transparently without any user intervention.
942
1011
  try {
943
- (0, fs_1.mkdirSync)((0, path_1.join)(projectPath, SPECRAILS_DIR, 'agents', 'personas'), { recursive: true });
944
- (0, fs_1.mkdirSync)((0, path_1.join)(projectPath, SPECRAILS_DIR, 'commands', 'sr'), { recursive: true });
945
- (0, fs_1.mkdirSync)((0, path_1.join)(projectPath, SPECRAILS_DIR, 'commands', 'specrails'), { recursive: true });
946
- (0, fs_1.mkdirSync)((0, path_1.join)(projectPath, SPECRAILS_DIR, 'rules'), { recursive: true });
1012
+ (0, fs_1.mkdirSync)((0, path_1.join)(enrichRoot, SPECRAILS_DIR, 'agents', 'personas'), { recursive: true });
1013
+ (0, fs_1.mkdirSync)((0, path_1.join)(enrichRoot, SPECRAILS_DIR, 'commands', 'sr'), { recursive: true });
1014
+ (0, fs_1.mkdirSync)((0, path_1.join)(enrichRoot, SPECRAILS_DIR, 'commands', 'specrails'), { recursive: true });
1015
+ (0, fs_1.mkdirSync)((0, path_1.join)(enrichRoot, SPECRAILS_DIR, 'rules'), { recursive: true });
947
1016
  }
948
1017
  catch (err) {
949
1018
  console.warn(`[SetupManager] Failed to pre-create enrich directories: ${err}`);
@@ -952,7 +1021,6 @@ class SetupManager {
952
1021
  // The slug was allocated at addProject and mirrored into the shared registry
953
1022
  // before/at install time, so resolve it from there (legacy full-flow path —
954
1023
  // not exercised by the app's quick flow).
955
- const enrichSlug = (0, artifact_registry_1.resolveArtifacts)(projectPath).entry?.slug;
956
1024
  const configPath = (0, install_config_path_1.installConfigPath)({ slug: enrichSlug, path: projectPath });
957
1025
  const hasConfig = (0, fs_1.existsSync)(configPath);
958
1026
  const enrichCmd = hasConfig ? '/specrails:enrich --from-config' : '/specrails:enrich';
@@ -1034,8 +1102,10 @@ class SetupManager {
1034
1102
  if (!db)
1035
1103
  return;
1036
1104
  try {
1105
+ const finishedAt = new Date().toISOString();
1037
1106
  const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, events, {
1038
1107
  fallbackModel: adapter.defaultModel(),
1108
+ durationMs: Math.max(0, Date.parse(finishedAt) - Date.parse(startedAtIso)),
1039
1109
  });
1040
1110
  (0, ai_invocations_1.recordInvocation)(db, {
1041
1111
  id: (0, crypto_1.randomUUID)(),
@@ -1045,7 +1115,7 @@ class SetupManager {
1045
1115
  surface_ref_id: projectId,
1046
1116
  status,
1047
1117
  started_at: startedAtIso,
1048
- finished_at: new Date().toISOString(),
1118
+ finished_at: finishedAt,
1049
1119
  total_cost_usd_estimated: estimated,
1050
1120
  ...result,
1051
1121
  });
@@ -1068,37 +1138,64 @@ class SetupManager {
1068
1138
  console.warn('[SetupManager] No AI CLI detected. Falling back to claude.');
1069
1139
  }
1070
1140
  const adapter = (0, providers_1.getAdapter)(resolvedProvider ?? 'claude');
1141
+ const execution = (0, workspace_resolution_1.resolveProjectExecution)({
1142
+ slug: this._projectSlugs.get(projectId),
1143
+ path: projectPath,
1144
+ });
1071
1145
  // Provider-aware prompt resolution:
1072
1146
  // - claude: pass the slash command unresolved so the CLI looks up
1073
1147
  // `.claude/commands/specrails/enrich.md` natively. Honours the
1074
1148
  // skills-resolution priority over CLAUDE.md.
1075
1149
  // - codex: no slash-command support; fold the enrich.md content into
1076
1150
  // the prompt with the PROJECT context header so codex knows the cwd.
1077
- let effectivePrompt = opts.prompt;
1078
- if (!adapter.capabilities.systemPromptArg &&
1151
+ let effectivePrompt;
1152
+ try {
1153
+ effectivePrompt = adapter.formatCoreCommand?.(opts.prompt, execution.cwd) ?? opts.prompt;
1154
+ }
1155
+ catch (error) {
1156
+ const message = error instanceof Error ? error.message : String(error);
1157
+ console.error(`[SetupManager] provider command resolution failed for ${projectId}: ${message}`);
1158
+ this._stopFilesystemPoll(projectId);
1159
+ this._broadcast({
1160
+ type: 'setup_error',
1161
+ projectId,
1162
+ error: message,
1163
+ });
1164
+ return;
1165
+ }
1166
+ if (adapter.id === 'codex' &&
1167
+ !adapter.capabilities.systemPromptArg &&
1079
1168
  (opts.prompt === '/specrails:enrich' || opts.prompt === '/specrails:enrich --from-config')) {
1080
- const enrichContent = readEnrichMdContent(projectPath);
1169
+ const enrichContent = readEnrichMdContent(execution.cwd);
1081
1170
  if (enrichContent) {
1082
1171
  const projectName = this._projectNames.get(projectId);
1172
+ const cwdContext = execution.relocated
1173
+ ? `CWD: ${execution.cwd}\nREPOSITORY: ${execution.repoDir}`
1174
+ : `CWD: ${projectPath}`;
1083
1175
  effectivePrompt = projectName
1084
- ? `PROJECT: ${projectName}\nCWD: ${projectPath}\n\n---\n\n${enrichContent}`
1176
+ ? `PROJECT: ${projectName}\n${cwdContext}\n\n---\n\n${enrichContent}`
1085
1177
  : enrichContent;
1086
1178
  }
1087
1179
  else {
1088
1180
  console.warn(`[SetupManager] Could not read enrich.md or setup.md — falling back to literal prompt`);
1089
1181
  }
1090
1182
  }
1091
- const args = adapter.buildArgs(opts.action, {
1183
+ const repoAccessArgs = execution.relocated
1184
+ ? (0, runtime_1.buildProviderRepoAccessArgs)(adapter, [execution.repoDir])
1185
+ : [];
1186
+ const spawnOpts = {
1092
1187
  prompt: effectivePrompt,
1093
1188
  model: adapter.defaultModel(),
1094
1189
  sessionId: opts.sessionId,
1095
- });
1190
+ extraArgs: repoAccessArgs,
1191
+ };
1192
+ const args = adapter.buildArgs(opts.action, spawnOpts);
1096
1193
  // No OTEL env injection here — SetupManager spawns drive the initial project
1097
1194
  // setup wizard, not repeatable pipeline jobs. Telemetry is scoped to
1098
1195
  // QueueManager pipeline runs only.
1099
1196
  const child = (0, cli_prompt_1.spawnAiCli)(adapter.binary, args, {
1100
- cwd: projectPath,
1101
- env: process.env,
1197
+ cwd: execution.cwd,
1198
+ env: (0, runtime_1.buildProviderEnv)(adapter, spawnOpts, { ...process.env, ...execution.env }),
1102
1199
  stdio: ['ignore', 'pipe', 'pipe'],
1103
1200
  });
1104
1201
  this._setupProcesses.set(projectId, child);
@@ -1122,65 +1219,71 @@ class SetupManager {
1122
1219
  // Start periodic filesystem polling for checkpoint detection
1123
1220
  this._startFilesystemPoll(projectId, projectPath);
1124
1221
  let capturedSessionId = null;
1222
+ let providerError = null;
1125
1223
  const stdoutReader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
1126
1224
  const stderrReader = (0, readline_1.createInterface)({ input: child.stderr, crlfDelay: Infinity });
1127
1225
  stdoutReader.on('line', (line) => {
1128
- const ev = adapter.parseStreamLine(line);
1129
- if (ev)
1130
- adapterEvents.push(ev);
1131
- if (!ev) {
1226
+ const parsedEvents = (0, runtime_1.parseStreamEvents)(adapter, line);
1227
+ if (parsedEvents.length === 0) {
1132
1228
  // Non-parseable line — emit as raw log.
1133
1229
  if (line)
1134
1230
  this._broadcast({ type: 'setup_log', projectId, line, stream: 'stdout' });
1135
1231
  return;
1136
1232
  }
1137
- switch (ev.kind) {
1138
- case 'session-started': {
1139
- if (!capturedSessionId) {
1140
- capturedSessionId = ev.sessionId;
1141
- this._onSessionCaptured?.(projectId, ev.sessionId);
1233
+ for (const ev of parsedEvents) {
1234
+ adapterEvents.push(ev);
1235
+ switch (ev.kind) {
1236
+ case 'session-started': {
1237
+ if (!capturedSessionId) {
1238
+ capturedSessionId = ev.sessionId;
1239
+ this._onSessionCaptured?.(projectId, ev.sessionId);
1240
+ }
1241
+ break;
1142
1242
  }
1143
- break;
1144
- }
1145
- case 'text-delta': {
1146
- // Run checkpoint detection over the assistant text and surface it
1147
- // both to the collapsible log viewer and the wizard chat panel.
1148
- this._broadcast({ type: 'setup_log', projectId, line: ev.text, stream: 'stdout' });
1149
- this._broadcast({ type: 'setup_chat', projectId, text: ev.text, role: 'assistant' });
1150
- const hits = detectCheckpointFromText(ev.text);
1151
- for (const hit of hits) {
1152
- this._advanceCheckpoint(projectId, hit.key, hit.detail);
1243
+ case 'text-delta': {
1244
+ // Run checkpoint detection over the assistant text and surface it
1245
+ // both to the collapsible log viewer and the wizard chat panel.
1246
+ this._broadcast({ type: 'setup_log', projectId, line: ev.text, stream: 'stdout' });
1247
+ this._broadcast({ type: 'setup_chat', projectId, text: ev.text, role: 'assistant' });
1248
+ const hits = detectCheckpointFromText(ev.text);
1249
+ for (const hit of hits) {
1250
+ this._advanceCheckpoint(projectId, hit.key, hit.detail);
1251
+ }
1252
+ // Also sync filesystem (cheap mtime/exists checks, see helper).
1253
+ this._syncFilesystemCheckpoints(projectId, projectPath);
1254
+ break;
1153
1255
  }
1154
- // Also sync filesystem (cheap mtime/exists checks, see helper).
1155
- this._syncFilesystemCheckpoints(projectId, projectPath);
1156
- break;
1157
- }
1158
- case 'tool-use': {
1159
- this._broadcast({ type: 'setup_log', projectId, line: `[tool] ${ev.name}`, stream: 'stdout' });
1160
- // Tool inputs commonly mention the paths being written — feed the
1161
- // input preview into the checkpoint detector so writes to
1162
- // .claude/agents/sr-*.md or .codex/skills/sr-*/SKILL.md advance
1163
- // the checkpoint state immediately.
1164
- const hits = detectCheckpointFromText(ev.inputPreview);
1165
- for (const hit of hits) {
1166
- this._advanceCheckpoint(projectId, hit.key, hit.detail);
1256
+ case 'tool-use': {
1257
+ this._broadcast({ type: 'setup_log', projectId, line: `[tool] ${ev.name}`, stream: 'stdout' });
1258
+ // Tool inputs commonly mention the paths being written — feed the
1259
+ // input preview into the checkpoint detector so writes to
1260
+ // .claude/agents/sr-*.md or .codex/skills/sr-*/SKILL.md advance
1261
+ // the checkpoint state immediately.
1262
+ const hits = detectCheckpointFromText(ev.inputPreview);
1263
+ for (const hit of hits) {
1264
+ this._advanceCheckpoint(projectId, hit.key, hit.detail);
1265
+ }
1266
+ break;
1167
1267
  }
1168
- break;
1169
- }
1170
- case 'result': {
1171
- // Claude's `result` event also carries session_id; use it as a
1172
- // backstop if `session-started` wasn't observed earlier.
1173
- const sid = ev.payload.session_id;
1174
- if (sid && !capturedSessionId) {
1175
- capturedSessionId = sid;
1176
- this._onSessionCaptured?.(projectId, sid);
1268
+ case 'result': {
1269
+ // Claude's `result` event also carries session_id; use it as a
1270
+ // backstop if `session-started` wasn't observed earlier.
1271
+ const sid = ev.payload.session_id;
1272
+ if (sid && !capturedSessionId) {
1273
+ capturedSessionId = sid;
1274
+ this._onSessionCaptured?.(projectId, sid);
1275
+ }
1276
+ break;
1177
1277
  }
1178
- break;
1278
+ case 'error':
1279
+ providerError = ev.message;
1280
+ this._broadcast({ type: 'setup_log', projectId, line: ev.message, stream: 'stderr' });
1281
+ break;
1282
+ case 'other':
1283
+ // Other event types (system progress markers) — already broadcast
1284
+ // implicitly through the line itself if useful. Skip.
1285
+ break;
1179
1286
  }
1180
- case 'other':
1181
- // Other event types (system progress markers) — already broadcast
1182
- // implicitly through the line itself if useful. Skip.
1183
- break;
1184
1287
  }
1185
1288
  });
1186
1289
  stderrReader.on('line', (line) => {
@@ -1198,25 +1301,29 @@ class SetupManager {
1198
1301
  }
1199
1302
  // Record the completed setup turn's spend (success on clean exit, failed
1200
1303
  // otherwise). LOW-2.
1201
- this._recordSetupInvocation(projectId, adapter, adapterEvents, code === 0 ? 'success' : 'failed', turnStartedAt);
1304
+ const providerReportedFailure = providerError !== null;
1305
+ this._recordSetupInvocation(projectId, adapter, adapterEvents, code === 0 && !providerReportedFailure ? 'success' : 'failed', turnStartedAt);
1202
1306
  // Final filesystem sync
1203
1307
  this._syncFilesystemCheckpoints(projectId, projectPath);
1204
- if (code === 0) {
1308
+ if (code === 0 && !providerReportedFailure) {
1205
1309
  // Sync filesystem checkpoints
1206
1310
  this._syncFilesystemCheckpoints(projectId, projectPath);
1207
1311
  // Relocated installs write artifacts to the workspace, not the repo —
1208
1312
  // resolve the has-agents/has-commands gate + summary against it.
1209
1313
  const artifactRoot = this._artifactRoot(projectId, projectPath);
1210
- // Check if setup is truly complete — real artifacts must exist
1211
- const hasAgents = (0, fs_1.existsSync)((0, path_1.join)(artifactRoot, SPECRAILS_DIR, 'agents')) &&
1212
- hasFiles((0, path_1.join)(artifactRoot, SPECRAILS_DIR, 'agents'), /^sr-.*\.md$/);
1213
- const hasCommands = (((0, fs_1.existsSync)((0, path_1.join)(artifactRoot, SPECRAILS_DIR, 'commands', 'sr')) && hasFiles((0, path_1.join)(artifactRoot, SPECRAILS_DIR, 'commands', 'sr'), /\.md$/)) ||
1214
- ((0, fs_1.existsSync)((0, path_1.join)(artifactRoot, SPECRAILS_DIR, 'commands', 'specrails')) && hasFiles((0, path_1.join)(artifactRoot, SPECRAILS_DIR, 'commands', 'specrails'), /\.md$/)));
1215
- const isComplete = hasAgents && hasCommands;
1314
+ // Check completion against the selected provider's native artefacts.
1315
+ // In particular, Kimi rail roles are direct-child SKILL.md files under
1316
+ // `.kimi-code/skills/`, not Markdown agents/commands in `.claude`.
1317
+ const tier = this._projectTiers.get(projectId) ?? 'full';
1318
+ const provider = this._projectProviders.get(projectId) ?? 'claude';
1319
+ const artifactState = setupArtifactState(artifactRoot, tier, provider);
1320
+ const isComplete = artifactState.complete;
1216
1321
  if (isComplete) {
1217
1322
  const legacySrRemoved = sweepLegacySrCommands(artifactRoot);
1218
- const tier = this._projectTiers.get(projectId) ?? 'full';
1219
- const summary = { ...computeSummary(artifactRoot, tier, this._projectProviders.get(projectId) ?? 'claude'), legacySrRemoved };
1323
+ const summary = {
1324
+ ...artifactState.summary,
1325
+ legacySrRemoved,
1326
+ };
1220
1327
  this._onSetupDone?.(projectId);
1221
1328
  this._broadcast({
1222
1329
  type: 'setup_complete',
@@ -1240,7 +1347,7 @@ class SetupManager {
1240
1347
  this._broadcast({
1241
1348
  type: 'setup_error',
1242
1349
  projectId,
1243
- error: `${adapter.binary} enrich exited with code ${code ?? 'unknown'}`,
1350
+ error: providerError ?? `${adapter.binary} enrich exited with code ${code ?? 'unknown'}`,
1244
1351
  });
1245
1352
  }
1246
1353
  });
@@ -1306,8 +1413,6 @@ class SetupManager {
1306
1413
  * known or the project isn't relocated. */
1307
1414
  _artifactRoot(projectId, projectPath) {
1308
1415
  const slug = this._projectSlugs.get(projectId);
1309
- if (!slug)
1310
- return projectPath;
1311
1416
  try {
1312
1417
  return (0, workspace_resolution_1.resolveProjectExecution)({ slug, path: projectPath }).cwd;
1313
1418
  }
@@ -1319,7 +1424,7 @@ class SetupManager {
1319
1424
  const statuses = this._checkpoints.get(projectId);
1320
1425
  if (!statuses)
1321
1426
  return;
1322
- const fsChecks = checkFilesystem(this._artifactRoot(projectId, projectPath));
1427
+ const fsChecks = checkFilesystem(this._artifactRoot(projectId, projectPath), this._projectProviders.get(projectId) ?? 'claude');
1323
1428
  for (const [key, exists] of Object.entries(fsChecks)) {
1324
1429
  if (!exists)
1325
1430
  continue;
@@ -1426,7 +1531,23 @@ class SetupManager {
1426
1531
  catch {
1427
1532
  // Missing install-config — stay on claude default.
1428
1533
  }
1429
- return computeSummary(project.path, tier, provider);
1534
+ // Relocated installs intentionally keep the imported repository pristine:
1535
+ // provider artefacts live in the populated workspace. The immediate install
1536
+ // completion path already uses `_artifactRoot`; a later GET after reopening
1537
+ // must resolve the same root or Kimi (and every relocated provider) is
1538
+ // incorrectly summarised as 0 agents / 0 commands.
1539
+ let artifactRoot = project.path;
1540
+ try {
1541
+ artifactRoot = (0, workspace_resolution_1.resolveProjectExecution)({
1542
+ slug: project.slug,
1543
+ path: project.path,
1544
+ }).cwd;
1545
+ }
1546
+ catch {
1547
+ // Registry/workspace resolution is fail-open by contract. Legacy projects
1548
+ // continue to read their in-repo artefacts.
1549
+ }
1550
+ return computeSummary(artifactRoot, tier, provider);
1430
1551
  }
1431
1552
  }
1432
1553
  exports.SetupManager = SetupManager;
@@ -42,7 +42,7 @@ function runVersionSpawn(cmd, args, timeoutMs = 5_000) {
42
42
  // budget; the `where`/`which` LOCATE probe stays fast (5s) since it's a builtin.
43
43
  const VERSION_PROBE_TIMEOUT_MS = process.platform === 'win32' ? 20_000 : 8_000;
44
44
  exports.MIN_VERSIONS = {
45
- node: '18.0.0',
45
+ node: '20.19.0',
46
46
  npm: '9.0.0',
47
47
  git: '2.20.0',
48
48
  uv: '0.1.0',
@@ -518,6 +518,8 @@ function providerInstallUrl(id) {
518
518
  return 'https://developers.openai.com/codex';
519
519
  case 'gemini':
520
520
  return 'https://github.com/google-gemini/gemini-cli';
521
+ case 'kimi':
522
+ return 'https://www.kimi.com/code/docs/en/';
521
523
  default:
522
524
  return 'https://github.com';
523
525
  }
@@ -534,6 +536,10 @@ function providerInstallHint(id, platform) {
534
536
  : 'Install Codex CLI from https://developers.openai.com/codex (or `pipx install codex-cli`), authenticate with `codex login`, then restart Specrails.';
535
537
  case 'gemini':
536
538
  return 'Install Gemini CLI via `npm i -g @google/gemini-cli` (or see https://github.com/google-gemini/gemini-cli), set GEMINI_API_KEY, then restart Specrails.';
539
+ case 'kimi':
540
+ return platform === 'win32'
541
+ ? 'Install Kimi Code from https://www.kimi.com/code/docs/en/, run `kimi login`, then restart Specrails so Windows refreshes PATH.'
542
+ : 'Install Kimi Code from https://www.kimi.com/code/docs/en/, run `kimi login`, then restart Specrails.';
537
543
  default:
538
544
  return `Install the ${id} CLI and restart Specrails.`;
539
545
  }