specrails-desktop 2.7.0 → 2.9.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 (329) hide show
  1. package/README.md +23 -19
  2. package/client/dist/assets/{ActivityFeedPage-LKqd18-G.js → ActivityFeedPage-DNqnf1fZ.js} +1 -1
  3. package/client/dist/assets/{AgentsPage-Cb-b-6Ot.js → AgentsPage-vmNIEbGM.js} +1 -1
  4. package/client/dist/assets/{AnalyticsPage-HVxQQ1wy.js → AnalyticsPage-CdfN0ofZ.js} +1 -1
  5. package/client/dist/assets/{BarChart-BOyHB0dw.js → BarChart-CIkopHjl.js} +1 -1
  6. package/client/dist/assets/{CodePage-DnOnwKGB.js → CodePage-DDRNU5FN.js} +1 -1
  7. package/client/dist/assets/{DesktopAnalyticsPage-D2auU39x.js → DesktopAnalyticsPage-Cl3sKKSG.js} +1 -1
  8. package/client/dist/assets/{DocsDialog-CTuDX3GK.js → DocsDialog-BGrBOfUr.js} +2 -2
  9. package/client/dist/assets/{DocsPage-DRyMmu0Z.js → DocsPage-CY-2SSzw.js} +2 -2
  10. package/client/dist/assets/{ExportDropdown-DO-GGiMh.js → ExportDropdown-BRHcvP0r.js} +1 -1
  11. package/client/dist/assets/{IntegrationsPage-BhbO4jFT.js → IntegrationsPage-nKdLB4Ub.js} +1 -1
  12. package/client/dist/assets/{JobDetailPage-DJooEg1s.js → JobDetailPage-Bf0A6WWQ.js} +1 -1
  13. package/client/dist/assets/{JobsPage-BbaC-YOg.js → JobsPage-Vg4nXPdL.js} +1 -1
  14. package/client/dist/assets/{dist-js-CiIVMsx3.js → dist-js-0i_klubI.js} +1 -1
  15. package/client/dist/assets/{dist-js-Xc2lRKp2.js → dist-js-CUs5GjwA.js} +1 -1
  16. package/client/dist/assets/{index-DK214dak.js → index-BXoHFtfG.js} +8 -8
  17. package/client/dist/assets/index-D6BaYRRU.css +2 -0
  18. package/client/dist/assets/{integrations-2C7MkGT0.js → integrations-7YyTBuU9.js} +1 -1
  19. package/client/dist/assets/{integrations-CX4p_bij.js → integrations-B9CEpNF0.js} +1 -1
  20. package/client/dist/assets/{integrations-C2jQtv-s.js → integrations-BlvAdewo.js} +1 -1
  21. package/client/dist/assets/{integrations-eQPHAYsE.js → integrations-Bw8UM9Xd.js} +1 -1
  22. package/client/dist/assets/{integrations-BDC670cg.js → integrations-C5SxNKnG.js} +1 -1
  23. package/client/dist/assets/{integrations-BqUmRUef.js → integrations-CJQKMmdW.js} +1 -1
  24. package/client/dist/assets/{integrations-CB98NeH5.js → integrations-DWz1eU_K.js} +1 -1
  25. package/client/dist/assets/{integrations-_SuVeQIG.js → integrations-DiPR8Fzp.js} +1 -1
  26. package/client/dist/assets/{lib-Bo5s6xpe.js → lib-D6M_MvoC.js} +1 -1
  27. package/client/dist/assets/setup-B6egeeTM.js +1 -0
  28. package/client/dist/assets/setup-BHroXlke.js +1 -0
  29. package/client/dist/assets/setup-BIXsWUp1.js +1 -0
  30. package/client/dist/assets/setup-BJRdg1iE.js +1 -0
  31. package/client/dist/assets/setup-C0rVGnCy.js +1 -0
  32. package/client/dist/assets/setup-Cpu17hJv.js +1 -0
  33. package/client/dist/assets/setup-D-1r0uSx.js +1 -0
  34. package/client/dist/assets/setup-Dn2-veYO.js +1 -0
  35. package/client/dist/assets/{useProjectCache-DVNypkmR.js → useProjectCache-BeyBSNpD.js} +1 -1
  36. package/client/dist/index.html +4 -4
  37. package/docs/README.md +5 -2
  38. package/docs/agy-cli-provider-study.md +78 -0
  39. package/docs/cli.md +23 -4
  40. package/docs/codex.md +116 -58
  41. package/docs/creating-specs.md +19 -5
  42. package/docs/customizing.md +27 -6
  43. package/docs/gemini.md +225 -73
  44. package/docs/getting-started.md +18 -9
  45. package/docs/guide/de/agents/1-meet-the-agents.md +38 -0
  46. package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +45 -0
  47. package/docs/guide/de/agents/3-customizing-models-per-agent.md +60 -0
  48. package/docs/guide/de/agents/4-custom-agents-catalog.md +43 -0
  49. package/docs/guide/de/getting-started/1-what-is-specrails.md +49 -0
  50. package/docs/guide/de/getting-started/2-installing-and-first-run.md +42 -0
  51. package/docs/guide/de/getting-started/3-adding-your-first-project.md +58 -0
  52. package/docs/guide/de/getting-started/4-the-dashboard-tour.md +53 -0
  53. package/docs/guide/de/insights/1-analytics-and-cost-tracking.md +78 -0
  54. package/docs/guide/de/insights/2-the-integrated-terminal.md +46 -0
  55. package/docs/guide/de/insights/3-code-explorer.md +50 -0
  56. package/docs/guide/de/integrations/1-ai-providers.md +64 -0
  57. package/docs/guide/de/integrations/2-plugins.md +44 -0
  58. package/docs/guide/de/integrations/3-jira-integration.md +71 -0
  59. package/docs/guide/de/integrations/4-mobile-companion.md +38 -0
  60. package/docs/guide/de/pipeline/1-rails-and-jobs.md +94 -0
  61. package/docs/guide/de/pipeline/2-the-job-detail-view.md +90 -0
  62. package/docs/guide/de/pipeline/3-batch-implement-and-multi-feature.md +78 -0
  63. package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +60 -0
  64. package/docs/guide/de/settings/1-themes.md +37 -0
  65. package/docs/guide/de/settings/2-language.md +39 -0
  66. package/docs/guide/de/settings/3-pipeline-telemetry-and-diagnostics.md +46 -0
  67. package/docs/guide/de/settings/4-where-your-data-lives.md +48 -0
  68. package/docs/guide/de/specs/1-specs-and-the-backlog.md +52 -0
  69. package/docs/guide/de/specs/2-add-spec-quick-mode.md +45 -0
  70. package/docs/guide/de/specs/3-add-spec-explore-mode.md +68 -0
  71. package/docs/guide/de/specs/4-drafts-and-contract-layer.md +81 -0
  72. package/docs/guide/en/agents/1-meet-the-agents.md +38 -0
  73. package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +45 -0
  74. package/docs/guide/en/agents/3-customizing-models-per-agent.md +60 -0
  75. package/docs/guide/en/agents/4-custom-agents-catalog.md +43 -0
  76. package/docs/guide/en/getting-started/1-what-is-specrails.md +49 -0
  77. package/docs/guide/en/getting-started/2-installing-and-first-run.md +42 -0
  78. package/docs/guide/en/getting-started/3-adding-your-first-project.md +58 -0
  79. package/docs/guide/en/getting-started/4-the-dashboard-tour.md +53 -0
  80. package/docs/guide/en/insights/1-analytics-and-cost-tracking.md +78 -0
  81. package/docs/guide/en/insights/2-the-integrated-terminal.md +46 -0
  82. package/docs/guide/en/insights/3-code-explorer.md +50 -0
  83. package/docs/guide/en/integrations/1-ai-providers.md +64 -0
  84. package/docs/guide/en/integrations/2-plugins.md +44 -0
  85. package/docs/guide/en/integrations/3-jira-integration.md +71 -0
  86. package/docs/guide/en/integrations/4-mobile-companion.md +38 -0
  87. package/docs/guide/en/pipeline/1-rails-and-jobs.md +94 -0
  88. package/docs/guide/en/pipeline/2-the-job-detail-view.md +90 -0
  89. package/docs/guide/en/pipeline/3-batch-implement-and-multi-feature.md +78 -0
  90. package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +60 -0
  91. package/docs/guide/en/settings/1-themes.md +37 -0
  92. package/docs/guide/en/settings/2-language.md +39 -0
  93. package/docs/guide/en/settings/3-pipeline-telemetry-and-diagnostics.md +46 -0
  94. package/docs/guide/en/settings/4-where-your-data-lives.md +48 -0
  95. package/docs/guide/en/specs/1-specs-and-the-backlog.md +52 -0
  96. package/docs/guide/en/specs/2-add-spec-quick-mode.md +45 -0
  97. package/docs/guide/en/specs/3-add-spec-explore-mode.md +68 -0
  98. package/docs/guide/en/specs/4-drafts-and-contract-layer.md +81 -0
  99. package/docs/guide/es/agents/1-meet-the-agents.md +38 -0
  100. package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +45 -0
  101. package/docs/guide/es/agents/3-customizing-models-per-agent.md +60 -0
  102. package/docs/guide/es/agents/4-custom-agents-catalog.md +43 -0
  103. package/docs/guide/es/getting-started/1-what-is-specrails.md +49 -0
  104. package/docs/guide/es/getting-started/2-installing-and-first-run.md +42 -0
  105. package/docs/guide/es/getting-started/3-adding-your-first-project.md +58 -0
  106. package/docs/guide/es/getting-started/4-the-dashboard-tour.md +53 -0
  107. package/docs/guide/es/insights/1-analytics-and-cost-tracking.md +78 -0
  108. package/docs/guide/es/insights/2-the-integrated-terminal.md +46 -0
  109. package/docs/guide/es/insights/3-code-explorer.md +50 -0
  110. package/docs/guide/es/integrations/1-ai-providers.md +64 -0
  111. package/docs/guide/es/integrations/2-plugins.md +44 -0
  112. package/docs/guide/es/integrations/3-jira-integration.md +71 -0
  113. package/docs/guide/es/integrations/4-mobile-companion.md +38 -0
  114. package/docs/guide/es/pipeline/1-rails-and-jobs.md +94 -0
  115. package/docs/guide/es/pipeline/2-the-job-detail-view.md +90 -0
  116. package/docs/guide/es/pipeline/3-batch-implement-and-multi-feature.md +78 -0
  117. package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +60 -0
  118. package/docs/guide/es/settings/1-themes.md +37 -0
  119. package/docs/guide/es/settings/2-language.md +39 -0
  120. package/docs/guide/es/settings/3-pipeline-telemetry-and-diagnostics.md +46 -0
  121. package/docs/guide/es/settings/4-where-your-data-lives.md +48 -0
  122. package/docs/guide/es/specs/1-specs-and-the-backlog.md +52 -0
  123. package/docs/guide/es/specs/2-add-spec-quick-mode.md +45 -0
  124. package/docs/guide/es/specs/3-add-spec-explore-mode.md +68 -0
  125. package/docs/guide/es/specs/4-drafts-and-contract-layer.md +81 -0
  126. package/docs/guide/fr/agents/1-meet-the-agents.md +38 -0
  127. package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +45 -0
  128. package/docs/guide/fr/agents/3-customizing-models-per-agent.md +60 -0
  129. package/docs/guide/fr/agents/4-custom-agents-catalog.md +43 -0
  130. package/docs/guide/fr/getting-started/1-what-is-specrails.md +49 -0
  131. package/docs/guide/fr/getting-started/2-installing-and-first-run.md +42 -0
  132. package/docs/guide/fr/getting-started/3-adding-your-first-project.md +58 -0
  133. package/docs/guide/fr/getting-started/4-the-dashboard-tour.md +53 -0
  134. package/docs/guide/fr/insights/1-analytics-and-cost-tracking.md +78 -0
  135. package/docs/guide/fr/insights/2-the-integrated-terminal.md +46 -0
  136. package/docs/guide/fr/insights/3-code-explorer.md +50 -0
  137. package/docs/guide/fr/integrations/1-ai-providers.md +64 -0
  138. package/docs/guide/fr/integrations/2-plugins.md +44 -0
  139. package/docs/guide/fr/integrations/3-jira-integration.md +71 -0
  140. package/docs/guide/fr/integrations/4-mobile-companion.md +38 -0
  141. package/docs/guide/fr/pipeline/1-rails-and-jobs.md +94 -0
  142. package/docs/guide/fr/pipeline/2-the-job-detail-view.md +90 -0
  143. package/docs/guide/fr/pipeline/3-batch-implement-and-multi-feature.md +78 -0
  144. package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +60 -0
  145. package/docs/guide/fr/settings/1-themes.md +37 -0
  146. package/docs/guide/fr/settings/2-language.md +39 -0
  147. package/docs/guide/fr/settings/3-pipeline-telemetry-and-diagnostics.md +46 -0
  148. package/docs/guide/fr/settings/4-where-your-data-lives.md +48 -0
  149. package/docs/guide/fr/specs/1-specs-and-the-backlog.md +52 -0
  150. package/docs/guide/fr/specs/2-add-spec-quick-mode.md +45 -0
  151. package/docs/guide/fr/specs/3-add-spec-explore-mode.md +68 -0
  152. package/docs/guide/fr/specs/4-drafts-and-contract-layer.md +81 -0
  153. package/docs/guide/it/agents/1-meet-the-agents.md +38 -0
  154. package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +45 -0
  155. package/docs/guide/it/agents/3-customizing-models-per-agent.md +60 -0
  156. package/docs/guide/it/agents/4-custom-agents-catalog.md +43 -0
  157. package/docs/guide/it/getting-started/1-what-is-specrails.md +49 -0
  158. package/docs/guide/it/getting-started/2-installing-and-first-run.md +42 -0
  159. package/docs/guide/it/getting-started/3-adding-your-first-project.md +58 -0
  160. package/docs/guide/it/getting-started/4-the-dashboard-tour.md +53 -0
  161. package/docs/guide/it/insights/1-analytics-and-cost-tracking.md +78 -0
  162. package/docs/guide/it/insights/2-the-integrated-terminal.md +46 -0
  163. package/docs/guide/it/insights/3-code-explorer.md +50 -0
  164. package/docs/guide/it/integrations/1-ai-providers.md +64 -0
  165. package/docs/guide/it/integrations/2-plugins.md +44 -0
  166. package/docs/guide/it/integrations/3-jira-integration.md +71 -0
  167. package/docs/guide/it/integrations/4-mobile-companion.md +38 -0
  168. package/docs/guide/it/pipeline/1-rails-and-jobs.md +94 -0
  169. package/docs/guide/it/pipeline/2-the-job-detail-view.md +90 -0
  170. package/docs/guide/it/pipeline/3-batch-implement-and-multi-feature.md +78 -0
  171. package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +60 -0
  172. package/docs/guide/it/settings/1-themes.md +37 -0
  173. package/docs/guide/it/settings/2-language.md +39 -0
  174. package/docs/guide/it/settings/3-pipeline-telemetry-and-diagnostics.md +46 -0
  175. package/docs/guide/it/settings/4-where-your-data-lives.md +48 -0
  176. package/docs/guide/it/specs/1-specs-and-the-backlog.md +52 -0
  177. package/docs/guide/it/specs/2-add-spec-quick-mode.md +45 -0
  178. package/docs/guide/it/specs/3-add-spec-explore-mode.md +68 -0
  179. package/docs/guide/it/specs/4-drafts-and-contract-layer.md +81 -0
  180. package/docs/guide/ja/agents/1-meet-the-agents.md +38 -0
  181. package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +45 -0
  182. package/docs/guide/ja/agents/3-customizing-models-per-agent.md +60 -0
  183. package/docs/guide/ja/agents/4-custom-agents-catalog.md +43 -0
  184. package/docs/guide/ja/getting-started/1-what-is-specrails.md +49 -0
  185. package/docs/guide/ja/getting-started/2-installing-and-first-run.md +42 -0
  186. package/docs/guide/ja/getting-started/3-adding-your-first-project.md +58 -0
  187. package/docs/guide/ja/getting-started/4-the-dashboard-tour.md +53 -0
  188. package/docs/guide/ja/insights/1-analytics-and-cost-tracking.md +78 -0
  189. package/docs/guide/ja/insights/2-the-integrated-terminal.md +46 -0
  190. package/docs/guide/ja/insights/3-code-explorer.md +50 -0
  191. package/docs/guide/ja/integrations/1-ai-providers.md +64 -0
  192. package/docs/guide/ja/integrations/2-plugins.md +44 -0
  193. package/docs/guide/ja/integrations/3-jira-integration.md +71 -0
  194. package/docs/guide/ja/integrations/4-mobile-companion.md +38 -0
  195. package/docs/guide/ja/pipeline/1-rails-and-jobs.md +94 -0
  196. package/docs/guide/ja/pipeline/2-the-job-detail-view.md +90 -0
  197. package/docs/guide/ja/pipeline/3-batch-implement-and-multi-feature.md +78 -0
  198. package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +60 -0
  199. package/docs/guide/ja/settings/1-themes.md +37 -0
  200. package/docs/guide/ja/settings/2-language.md +39 -0
  201. package/docs/guide/ja/settings/3-pipeline-telemetry-and-diagnostics.md +46 -0
  202. package/docs/guide/ja/settings/4-where-your-data-lives.md +48 -0
  203. package/docs/guide/ja/specs/1-specs-and-the-backlog.md +52 -0
  204. package/docs/guide/ja/specs/2-add-spec-quick-mode.md +45 -0
  205. package/docs/guide/ja/specs/3-add-spec-explore-mode.md +68 -0
  206. package/docs/guide/ja/specs/4-drafts-and-contract-layer.md +81 -0
  207. package/docs/guide/pt/agents/1-meet-the-agents.md +38 -0
  208. package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +45 -0
  209. package/docs/guide/pt/agents/3-customizing-models-per-agent.md +60 -0
  210. package/docs/guide/pt/agents/4-custom-agents-catalog.md +43 -0
  211. package/docs/guide/pt/getting-started/1-what-is-specrails.md +49 -0
  212. package/docs/guide/pt/getting-started/2-installing-and-first-run.md +42 -0
  213. package/docs/guide/pt/getting-started/3-adding-your-first-project.md +58 -0
  214. package/docs/guide/pt/getting-started/4-the-dashboard-tour.md +53 -0
  215. package/docs/guide/pt/insights/1-analytics-and-cost-tracking.md +78 -0
  216. package/docs/guide/pt/insights/2-the-integrated-terminal.md +46 -0
  217. package/docs/guide/pt/insights/3-code-explorer.md +50 -0
  218. package/docs/guide/pt/integrations/1-ai-providers.md +64 -0
  219. package/docs/guide/pt/integrations/2-plugins.md +44 -0
  220. package/docs/guide/pt/integrations/3-jira-integration.md +71 -0
  221. package/docs/guide/pt/integrations/4-mobile-companion.md +38 -0
  222. package/docs/guide/pt/pipeline/1-rails-and-jobs.md +94 -0
  223. package/docs/guide/pt/pipeline/2-the-job-detail-view.md +90 -0
  224. package/docs/guide/pt/pipeline/3-batch-implement-and-multi-feature.md +78 -0
  225. package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +60 -0
  226. package/docs/guide/pt/settings/1-themes.md +37 -0
  227. package/docs/guide/pt/settings/2-language.md +39 -0
  228. package/docs/guide/pt/settings/3-pipeline-telemetry-and-diagnostics.md +46 -0
  229. package/docs/guide/pt/settings/4-where-your-data-lives.md +48 -0
  230. package/docs/guide/pt/specs/1-specs-and-the-backlog.md +52 -0
  231. package/docs/guide/pt/specs/2-add-spec-quick-mode.md +45 -0
  232. package/docs/guide/pt/specs/3-add-spec-explore-mode.md +68 -0
  233. package/docs/guide/pt/specs/4-drafts-and-contract-layer.md +81 -0
  234. package/docs/guide/zh/agents/1-meet-the-agents.md +38 -0
  235. package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +45 -0
  236. package/docs/guide/zh/agents/3-customizing-models-per-agent.md +60 -0
  237. package/docs/guide/zh/agents/4-custom-agents-catalog.md +43 -0
  238. package/docs/guide/zh/getting-started/1-what-is-specrails.md +49 -0
  239. package/docs/guide/zh/getting-started/2-installing-and-first-run.md +42 -0
  240. package/docs/guide/zh/getting-started/3-adding-your-first-project.md +58 -0
  241. package/docs/guide/zh/getting-started/4-the-dashboard-tour.md +53 -0
  242. package/docs/guide/zh/insights/1-analytics-and-cost-tracking.md +78 -0
  243. package/docs/guide/zh/insights/2-the-integrated-terminal.md +46 -0
  244. package/docs/guide/zh/insights/3-code-explorer.md +50 -0
  245. package/docs/guide/zh/integrations/1-ai-providers.md +64 -0
  246. package/docs/guide/zh/integrations/2-plugins.md +44 -0
  247. package/docs/guide/zh/integrations/3-jira-integration.md +71 -0
  248. package/docs/guide/zh/integrations/4-mobile-companion.md +38 -0
  249. package/docs/guide/zh/pipeline/1-rails-and-jobs.md +94 -0
  250. package/docs/guide/zh/pipeline/2-the-job-detail-view.md +90 -0
  251. package/docs/guide/zh/pipeline/3-batch-implement-and-multi-feature.md +78 -0
  252. package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +60 -0
  253. package/docs/guide/zh/settings/1-themes.md +37 -0
  254. package/docs/guide/zh/settings/2-language.md +39 -0
  255. package/docs/guide/zh/settings/3-pipeline-telemetry-and-diagnostics.md +46 -0
  256. package/docs/guide/zh/settings/4-where-your-data-lives.md +48 -0
  257. package/docs/guide/zh/specs/1-specs-and-the-backlog.md +52 -0
  258. package/docs/guide/zh/specs/2-add-spec-quick-mode.md +45 -0
  259. package/docs/guide/zh/specs/3-add-spec-explore-mode.md +68 -0
  260. package/docs/guide/zh/specs/4-drafts-and-contract-layer.md +81 -0
  261. package/docs/internals/README.md +1 -1
  262. package/docs/internals/adding-a-provider.md +192 -59
  263. package/docs/internals/api-reference.md +130 -21
  264. package/docs/internals/architecture.md +22 -9
  265. package/docs/internals/bundled-framework-build-plan.md +264 -0
  266. package/docs/internals/configuration.md +33 -8
  267. package/docs/internals/global-artifacts-alignment-contract.md +486 -0
  268. package/docs/internals/global-artifacts-relocation-evaluation.md +294 -0
  269. package/docs/internals/operations-runbook.md +16 -5
  270. package/docs/internals/profiles.md +42 -14
  271. package/docs/platforms/macos.md +27 -8
  272. package/docs/platforms/windows.md +20 -6
  273. package/docs/running-pipelines.md +17 -9
  274. package/docs/terminal.md +9 -3
  275. package/docs/tracking-cost.md +17 -11
  276. package/package.json +1 -1
  277. package/server/dist/agent-refine-manager.js +20 -5
  278. package/server/dist/artifact-registry.js +468 -0
  279. package/server/dist/attachment-manager.js +5 -8
  280. package/server/dist/browser-capture-manager.js +4 -4
  281. package/server/dist/bundled-core.js +72 -0
  282. package/server/dist/bundled-openspec.js +58 -0
  283. package/server/dist/chat-manager.js +42 -5
  284. package/server/dist/code-explorer-router.js +10 -7
  285. package/server/dist/config.js +7 -2
  286. package/server/dist/context-budget.js +17 -6
  287. package/server/dist/context-scope.js +6 -2
  288. package/server/dist/contract-refine-runner.js +31 -9
  289. package/server/dist/desktop-router.js +39 -14
  290. package/server/dist/docs-router.js +210 -132
  291. package/server/dist/file-summary-manager.js +41 -16
  292. package/server/dist/framework-manager.js +248 -0
  293. package/server/dist/framework-migration.js +308 -0
  294. package/server/dist/index.js +30 -0
  295. package/server/dist/install-config-path.js +73 -0
  296. package/server/dist/jira/jira-sync-manager.js +23 -11
  297. package/server/dist/openspec-shim.js +153 -0
  298. package/server/dist/plugins-router.js +19 -8
  299. package/server/dist/profiles-router.js +38 -16
  300. package/server/dist/project-registry.js +101 -3
  301. package/server/dist/project-router-chat.js +1 -1
  302. package/server/dist/project-router-helpers.js +25 -12
  303. package/server/dist/project-router-jobs.js +3 -3
  304. package/server/dist/project-router-settings.js +8 -6
  305. package/server/dist/project-router-setup.js +27 -10
  306. package/server/dist/project-router-spending.js +6 -1
  307. package/server/dist/project-router-tickets.js +30 -10
  308. package/server/dist/project-router.js +16 -1
  309. package/server/dist/providers/gemini-adapter.js +4 -0
  310. package/server/dist/providers/gemini-agent-ack.js +65 -0
  311. package/server/dist/queue-manager.js +156 -12
  312. package/server/dist/setup-manager.js +131 -29
  313. package/server/dist/smash-runner.js +21 -6
  314. package/server/dist/ticket-store.js +6 -2
  315. package/server/dist/ticket-watcher.js +5 -1
  316. package/server/dist/util/stream-display.js +18 -3
  317. package/server/dist/vitest-setup.js +25 -0
  318. package/server/dist/workspace-manager.js +199 -0
  319. package/server/dist/workspace-resolution.js +147 -0
  320. package/client/dist/assets/index-DgKfQFcf.css +0 -2
  321. package/client/dist/assets/setup-BIIkb-_K.js +0 -1
  322. package/client/dist/assets/setup-BeQxu9kD.js +0 -1
  323. package/client/dist/assets/setup-CPa6GnlI.js +0 -1
  324. package/client/dist/assets/setup-CZl4OEJx.js +0 -1
  325. package/client/dist/assets/setup-ChpodNfn.js +0 -1
  326. package/client/dist/assets/setup-D_fjJH6u.js +0 -1
  327. package/client/dist/assets/setup-YzD8DX4O.js +0 -1
  328. package/client/dist/assets/setup-fRpDozmq.js +0 -1
  329. package/docs/adding-a-provider.md +0 -107
@@ -1,19 +1,30 @@
1
1
  # Adding a new AI provider to Specrails
2
2
 
3
+ > Last verified against `main` (app 2.8.0), which ships **three** registered
4
+ > providers: **Claude, Codex, and Gemini**. Gemini is the freshest worked
5
+ > example — `server/providers/gemini-adapter.ts` is the cleanest single-file
6
+ > template to copy.
7
+
3
8
  The app is provider-agnostic by design. Every manager that spawns an AI
4
9
  CLI consumes a `ProviderAdapter` rather than branching on a hardcoded
5
- `if (provider === 'claude')`. Adding a new provider is mostly one adapter
6
- file plus one entry in the registry but the codebase still carries a
7
- handful of `'claude' | 'codex'` type unions and two hardcoded provider
8
- lists that you must widen by hand today. Those are tracked in the
9
- **Type-union widening** and **Manual wiring still required** sections
10
- below.
10
+ `if (provider === 'claude')`. Adding a provider is, in the ideal case,
11
+ **one adapter file plus one registry line**and that ideal is now real:
12
+ `ProviderId` is just `string` (no `'claude' | 'codex'` union to widen),
13
+ and the provider-discovery routes are registry-driven, so a newly-registered
14
+ adapter surfaces in the API and the Add Project UI with **zero** further edits.
15
+ You only fill a few non-adapter seams that are inherently provider-specific
16
+ (pricing rows, a spawn-env quirk, install hints, a branded UI chip) — tracked
17
+ in **Optional polish** and the conditional steps 3–6 below.
11
18
 
12
19
  If you find yourself wanting to write `if (this._provider === 'X')` in
13
20
  a manager, **the design has drifted** — find the capability you're
14
21
  gating on, add a flag to `ProviderCapabilities`, and branch on the
15
22
  flag instead.
16
23
 
24
+ The remaining genuine id-keyed sites (the legacy `normaliseResultEvent`
25
+ branch and the Codex rail slash-command rewrite) are inventoried in
26
+ **Don't break the principle** at the end.
27
+
17
28
  ## The recipe
18
29
 
19
30
  ### 1. Implement the adapter
@@ -52,24 +63,79 @@ export const exampleAdapter: ProviderAdapter = {
52
63
  extractResult: (events): NormalisedResult => { /* events → tokens/cost/session */ },
53
64
  baselineAgents: () => ['sr-architect', 'sr-developer', 'sr-reviewer'],
54
65
  detectInstalled: async (): Promise<DetectionResult> => { /* `which` + `--version` */ },
66
+ // Optional — see "(Optional) prepareHeadlessSpawn" below. Gemini uses it to
67
+ // pre-acknowledge project subagents so they load in headless `gemini -p` rails.
68
+ // prepareHeadlessSpawn: (projectPath: string): void => { /* best-effort prep */ },
55
69
  }
56
70
  ```
57
71
 
58
72
  The `ProviderAdapter` interface is documented in
59
73
  `server/providers/types.ts`. Read the existing
60
- `server/providers/{claude,codex}-adapter.ts` for the patterns —
74
+ `server/providers/{claude,codex,gemini}-adapter.ts` for the patterns —
61
75
  `SpawnAction` shapes per provider, `text-delta` event normalisation
62
- across native JSONL formats, etc. Note the shipped baseline is the
76
+ across native JSONL formats, etc. **`gemini-adapter.ts` is the newest and
77
+ most representative end-to-end exemplar** to copy: it shows the optional
78
+ `prepareHeadlessSpawn` hook, `systemPromptArg: false` system-prompt folding
79
+ (via the `GEMINI_SYSTEM_MD` env), native OTEL with `nativeCostUsd: false`,
80
+ and a per-action `buildArgs` switch that throws defensively on the
81
+ `chat-stream` action it doesn't support. Note the shipped baseline is the
63
82
  three-agent trio `['sr-architect', 'sr-developer', 'sr-reviewer']`;
64
83
  `ProfileManager` validation requires exactly your `baselineAgents()` to
65
84
  be present in every profile chain, so don't add agents your scaffold
66
85
  won't actually create.
67
86
 
87
+ The `SpawnAction` union also includes **`chat-stream`** — used by the
88
+ Explore persistent-stdin fast-path and interactive jobs. Only providers
89
+ that advertise `capabilities.persistentStdin` (claude today) ever receive
90
+ it; if your CLI has no persistent-stdin transport, `throw` in that `case`
91
+ (as Gemini does) so a misrouted spawn fails loudly instead of emitting a
92
+ broken argv.
93
+
94
+ #### (Optional) prepareHeadlessSpawn
95
+
96
+ `prepareHeadlessSpawn?(projectPath)` is an optional, best-effort filesystem
97
+ prep run **right before a headless rail spawn** (cwd = the project path).
98
+ Gemini implements it to pre-acknowledge the project's custom subagents
99
+ (writing `~/.gemini/acknowledgments/agents.json`) so they load in
100
+ `gemini -p` mode instead of falling back to a generic agent. Claude and
101
+ Codex omit it. Managers wrap the call so a thrown error never blocks the
102
+ spawn — adding it is allowed and does **not** violate the no-id-branching
103
+ principle (it's an adapter member, not a `provider === 'X'` check in a
104
+ manager). See `server/providers/gemini-agent-ack.ts` for the worked use.
105
+
68
106
  `parseStreamLine` returns `null` for empty input lines **and** for lines
69
107
  that fail `JSON.parse` (see `server/providers/codex-adapter.ts`); unknown
70
108
  JSON event types resolve to `{ kind: 'other' }`. Write your tests
71
109
  accordingly — don't assume null-only-on-empty.
72
110
 
111
+ #### Two capability flags that bite
112
+
113
+ - **`systemPromptArg: false`** ⇒ the CLI has no `--system-prompt` flag, so the
114
+ adapter must fold the system prompt into the user prompt before spawning —
115
+ **except** Explore (`chat-turn`) turns, which must stay user-text-only (a
116
+ long system prompt drowns a short Explore message); those trust the
117
+ app-managed instructions file (`<instructionsFilename>`) in the explore cwd
118
+ instead. Folding isn't the only mechanism: Gemini *also* exports its system
119
+ prompt via the `GEMINI_SYSTEM_MD` env, so an implementer should pick whatever
120
+ the CLI actually honours rather than assuming string concatenation.
121
+ - **`nativeCostUsd: false`** ⇒ `extractResult` leaves `total_cost_usd`
122
+ undefined and the framework estimates it from a rate card (step 3). If your
123
+ token usage reports `cached` as a **subset** of input (it usually does — see
124
+ Gemini's `stats.cached`), map it to `tokens_cache_read`; `pricing.ts` already
125
+ bills `tokens_in - tokens_cache_read` at the input rate and the cached portion
126
+ at the cache rate, so don't double-count.
127
+
128
+ #### Mirror the model catalog into spec-models.ts
129
+
130
+ The model catalog is **duplicated** by design: the adapter's `modelCatalog()`
131
+ drives the spawn-time UI, but spec-model validation reads a *second* copy in
132
+ `server/spec-models.ts` (`PROVIDER_MODELS` + `PROVIDER_DEFAULT_MODEL`, both
133
+ `Record<string, …>` keyed by provider id). The file even comments that
134
+ `GEMINI_MODELS` "Mirrors GEMINI_MODELS in server/providers/gemini-adapter.ts".
135
+ If you add the catalog only to the adapter, your models won't validate in the
136
+ Add Spec flow. **Add your provider to both.** (Unmatched providers fall back to
137
+ the Claude catalog, so the failure is silent — easy to miss.)
138
+
73
139
  ### 2. Register it
74
140
 
75
141
  Append the import to `server/providers/index.ts`:
@@ -90,43 +156,55 @@ provider with zero edits):
90
156
 
91
157
  - `getAdapter` / `listAdapters` / `hasAdapter` (`server/providers/registry.ts`).
92
158
  - `detectAvailableCLIs` (`server/core-compat.ts`).
159
+ - `GET /api/available-providers` (`server/desktop-router.ts`) — returns the
160
+ **full detected map** built by iterating the registry, not a hardcoded
161
+ `{ claude, codex }` literal. A new provider shows up here with no edit
162
+ (the only per-id touch on this route is an optional beta gate, below).
93
163
  - `POST /api/projects` provider validation (`server/desktop-router.ts`,
94
164
  via `hasAdapter` / `listAdapters`).
165
+ - `AddProjectDialog` (`client/src/components/AddProjectDialog.tsx`) — it
166
+ fetches `/available-providers` generically (`Object.entries(data)`) and a
167
+ `providerRenderOrder()` helper appends **any** detected-but-unlisted
168
+ provider after the canonical-ordered known ones, with a neutral chip
169
+ fallback. A new provider appears in the Add Project UI automatically.
95
170
  - `setup-prerequisites` provider rows (`server/setup-prerequisites.ts`,
96
171
  iterates `listAdapters()`).
97
172
  - Analytics `byProvider` (`server/spending.ts`) and the
98
173
  `ProviderBreakdownCard` (`client/src/components/analytics/ProviderBreakdownCard.tsx`).
99
174
 
100
- **Manual wiring still required** (these hardcode `claude` / `codex`
101
- today and will NOT surface a 4th provider until edited):
175
+ ### `ProviderId` is `string` no compile-time blocker
102
176
 
103
- - `GET /api/available-providers` (`server/desktop-router.ts`) returns a
104
- literal `{ claude, codex }` shape add your key.
105
- - `AddProjectDialog` (`client/src/components/AddProjectDialog.tsx`)
106
- hardcodes `PROVIDER_ORDER = ['claude', 'codex']` and reads
107
- `data.claude` / `data.codex` explicitly. Without editing it the
108
- provider won't appear in the Add Project UI.
109
- - `providerInstallUrl` / `providerInstallHint`
110
- (`server/setup-prerequisites.ts`) have generic `default:` fallbacks so
111
- nothing crashes, but a good install hint needs a `case` for your id.
112
-
113
- ### Type-union widening
177
+ There is **no type-union to widen**. `ProviderId` is `export type ProviderId = string`
178
+ (`server/providers/types.ts`), and every provider-typed seam already aliases it:
179
+ `CliProvider` (`server/desktop-db.ts`), `SpecProvider` (`server/spec-models.ts`),
180
+ `EnqueueOptions.provider` and `_jobProviderSelection` (`server/queue-manager.ts`),
181
+ `ChatManager`, `AgentRefineManager`, and `ProjectRegistry`. Adding a provider is
182
+ **not** a compile-time blocker the old "widen ~8 unions" step is paid off (Gemini
183
+ is the proof it works). Any remaining `'claude' | 'codex'` literals live in test
184
+ fixtures and code comments, not the production type system.
114
185
 
115
- A 4th provider is a **compile-time blocker** until you widen the
116
- `'claude' | 'codex'` unions still scattered across the server. The build
117
- fails until they're widened (or migrated to a shared `ProviderId`):
186
+ ### Optional polish (auto-works, but nicer with an edit)
118
187
 
119
- - `CliProvider` (`server/desktop-db.ts`)the canonical project-row provider type.
120
- - `SpecProvider` (`server/spec-models.ts`).
121
- - The inline `'claude' | 'codex'` unions in `server/queue-manager.ts`
122
- (`EnqueueOptions.provider`, `_jobProviderSelection`),
123
- `server/chat-manager.ts`, `server/agent-refine-manager.ts`, and
124
- `server/project-registry.ts`.
188
+ None of these block a new provider it works without them — but each one
189
+ makes it look first-class instead of falling back to a raw id:
125
190
 
126
- Expect to widen roughly eight unions. The long-term goal is to delete
127
- them in favour of a single `ProviderId` derived from the registry — if
128
- you add a new hardcoded site instead of widening the existing ones, file
129
- an OpenSpec change first (see the closing section).
191
+ - **Canonical position + branded chip.** `PROVIDER_ORDER` / `PROVIDER_META`
192
+ in `AddProjectDialog` give the provider a fixed position in the picker and
193
+ a custom icon + label (otherwise it's appended last with a `•` neutral chip).
194
+ - **Install hint.** `providerInstallUrl` / `providerInstallHint`
195
+ (`server/setup-prerequisites.ts`) have generic `default:` fallbacks so
196
+ nothing crashes, but a good install hint needs a `case` for your id.
197
+ - **Beta gate (only if you ship behind a kill switch).** If your CLI's stream
198
+ schema isn't yet validated against a live binary, gate selection behind a
199
+ `SPECRAILS_<ID>_BETA` env var. Mirror Codex/Gemini: add an
200
+ `isXBetaDisabled()` helper in `server/desktop-router.ts` (return `true`
201
+ only when the env value is the **exact string `'0'`** — both providers are
202
+ default-**enabled**), force the provider `false` in the `/available-providers`
203
+ response when disabled, and reject it in `POST /projects` with the same 400
204
+ the others use. There is no `isGeminiBetaEnabled` — the helper is
205
+ `isGeminiBetaDisabled` (returns `true` to DISABLE). Codex additionally honours
206
+ the legacy `SPECRAILS_HUB_CODEX_BETA` name as a fallback; a brand-new provider
207
+ has no such legacy alias.
130
208
 
131
209
  ### 3. (If `nativeCostUsd === false`) add pricing entries
132
210
 
@@ -144,16 +222,22 @@ back to this table automatically and returns an `estimated` flag that
144
222
  `total_cost_usd_estimated = 1` on the `ai_invocations` row, which in
145
223
  turn lights up the `~` tilde + Hero footnote on the AnalyticsPage.
146
224
 
147
- ### 4. (If `nativeOtelEnv === false`) confirm the OTEL bridge works
225
+ ### 4. OTEL telemetry
148
226
 
149
- The synthetic OTEL bridge at `server/codex-otel-bridge.ts` is
150
- provider-neutral despite its name — it consumes the canonical
151
- `AdapterEvent` stream. As long as your adapter's `parseStreamLine`
152
- emits `text-delta`, `tool-use`, `session-started`, and `result` events,
153
- the bridge will synthesise traces / metrics / logs for free. The
154
- exported factory is still named `createCodexOtelBridge`; if that bugs
155
- you, renaming it to `createSyntheticOtelBridge` (and updating callers)
156
- is safe same logic.
227
+ Two paths, picked by your `nativeOtelEnv` capability flag:
228
+
229
+ - **`nativeOtelEnv: true`** (Claude, Gemini) nothing to do. `QueueManager`
230
+ injects the **standard `OTEL_*` env vars** (`buildTelemetryEnv`) into every
231
+ rail spawn and the CLI exports OTLP/JSON to the app's receiver natively. There
232
+ is no `GEMINI_TELEMETRY_*` env var — Gemini honours the same `OTEL_*` vars as
233
+ Claude.
234
+ - **`nativeOtelEnv: false`** (Codex) ⇒ the synthetic OTEL bridge at
235
+ `server/codex-otel-bridge.ts` fills the gap. It's provider-neutral despite its
236
+ name — it consumes the canonical `AdapterEvent` stream. As long as your
237
+ adapter's `parseStreamLine` emits `text-delta`, `tool-use`, `session-started`,
238
+ and `result` events, the bridge synthesises traces / metrics / logs for free.
239
+ The exported factory is still named `createCodexOtelBridge`; renaming it to
240
+ `createSyntheticOtelBridge` (and updating callers) is safe — same logic.
157
241
 
158
242
  ### 5. (If `mcpRegistration === 'cli-add'`) wire the plugin install path
159
243
 
@@ -166,7 +250,33 @@ app-level `PluginManager` already threads `providerId` through every
166
250
  relevant method.
167
251
 
168
252
  For `mcpRegistration === 'project-json'` providers, the existing
169
- `.mcp.json` surgical-merge path applies — nothing to add.
253
+ `.mcp.json` surgical-merge path applies — nothing to add. (This is why
254
+ Serena-style plugins resolve for Claude and Gemini rails but are skipped
255
+ for Codex-only projects, which use `cli-add`.)
256
+
257
+ ### 6. (If the binary needs a spawn-env quirk) add it to cli-prompt.ts
258
+
259
+ Per-binary spawn quirks live in `server/util/cli-prompt.ts` — the spawn layer
260
+ already special-cases `spawnClaude` / `spawnCodex` / `spawnGemini`, dispatched
261
+ by binary name. Gemini needed `GEMINI_CLI_TRUST_WORKSPACE=true` injected into
262
+ every spawn (its "trusted folders" gate otherwise silently disables `--yolo`
263
+ and blocks headless tool calls). If your CLI has an equivalent env that
264
+ non-interactive spawns require, add a `spawn<Provider>` helper there. Most
265
+ providers need nothing here.
266
+
267
+ ### CLI version floor vs. specrails-core package floor
268
+
269
+ Two distinct version concepts — don't conflate them:
270
+
271
+ - **`minCliVersion`** is the **binary** floor surfaced by `detectInstalled`
272
+ (Claude = `null` / none pinned, Codex = `0.128.0`, Gemini = `0.11.0`). It
273
+ guards stream-format / flag availability for that one CLI.
274
+ - **`specrails-core@^4.8.0`** (`CORE_PACKAGE_SPEC`, `server/core-package.ts`) is
275
+ the single shared package floor the app installs/probes for **all** providers.
276
+ It matters when your provider's **rails** rely on core-side scaffolding: core
277
+ must emit the provider's command/agent/skill tree (e.g. Gemini needed core
278
+ `4.8.0` to ship the `.gemini/` commands + `sr-*` agents). The desktop adapter
279
+ alone covers spec / explore / quick; rails need the matching core target.
170
280
 
171
281
  ## Known gotchas
172
282
 
@@ -174,7 +284,7 @@ For `mcpRegistration === 'project-json'` providers, the existing
174
284
  (`server/result-event.ts`) is still live for any callsite not yet
175
285
  migrated to `finaliseInvocationResult`. It only special-cases
176
286
  `provider === 'claude'`; everything else falls into the non-claude
177
- (codex-shaped) branch. A 4th provider hitting that path would be
287
+ (codex-shaped) branch. A new provider hitting that path would be
178
288
  silently parsed as codex — migrate the callsite or extend the branch.
179
289
  - **Rail slash-command translation is provider-specific.** In
180
290
  `server/queue-manager.ts` the rail prompt builder rewrites
@@ -199,9 +309,12 @@ Required coverage:
199
309
 
200
310
  - Identity: id / binary / projectDirName / instructionsFilename /
201
311
  mcpRegistration / capability flags / model catalog.
202
- - `buildArgs` for every `SpawnAction` the manager flow uses (today:
312
+ - `buildArgs` for every `SpawnAction` the manager flow uses:
203
313
  `chat-turn`, `chat-resume`, `rail-job`, `spec-gen`, `agent-refine`,
204
- `setup-enrich`, `setup-enrich-resume`, `auto-title`).
314
+ `setup-enrich`, `setup-enrich-resume`, `auto-title`, and `chat-stream`
315
+ (the persistent-stdin / interactive-job action — test either the argv
316
+ you emit or the defensive `throw`, like Gemini does, if your CLI has no
317
+ persistent-stdin transport).
205
318
  - `parseStreamLine` per event type, including an "unknown type maps
206
319
  to kind: 'other'" defensive test and a "returns null on empty input
207
320
  and on unparseable JSON" test.
@@ -216,9 +329,9 @@ npx vitest run server/providers server/pricing server/result-event server/plugin
216
329
  ```
217
330
 
218
331
  `npm run typecheck` runs `tsc --noEmit` for both the server and the
219
- client — important here, because the type-union widening above touches
220
- types both halves import, and a missed union surfaces only on the side
221
- you didn't check.
332
+ client — run both halves, because a provider touches types each side
333
+ imports (`ProviderId`, the model catalog) and a mistake can surface only
334
+ on the side you didn't check.
222
335
 
223
336
  Then a manual smoke test: register a project via the UI with the new
224
337
  provider, run a chat turn, run a rail, confirm tokens + cost land on
@@ -226,13 +339,33 @@ the AnalyticsPage.
226
339
 
227
340
  ## Don't break the principle
228
341
 
229
- The drift inventory abovethe two hardcoded provider lists, the ~8
230
- `'claude' | 'codex'` unions, the legacy `normaliseResultEvent` branch,
231
- and the provider-specific rail rewrite is the current debt. The
232
- long-term goal is to delete every one of those sites in favour of a
233
- registry-derived `ProviderId` so that adding a fifth provider really is
234
- just the adapter file plus the registry entry. If you find a NEW
235
- hardcoded `if (provider === 'X')` site that this guide doesn't list,
236
- **the architecture has drifted further** — file an OpenSpec change at
237
- `openspec/changes/<your-change-name>/` and capture the drift before
342
+ Most of the old debt is **paid off** and Gemini's addition is what paid it:
343
+
344
+ - The `'claude' | 'codex'` type unions are gone (`ProviderId = string`).
345
+ - The two hardcoded provider lists are gone (`/available-providers` and
346
+ `AddProjectDialog` are registry-driven with fallbacks).
347
+
348
+ The genuine id-keyed sites that **remain** are:
349
+
350
+ - **`normaliseResultEvent` legacy branch** (`server/result-event.ts`) the
351
+ pre-`finaliseInvocationResult` path that special-cases `provider === 'claude'`.
352
+ - **Codex rail slash-command rewrite** (`server/queue-manager.ts`) —
353
+ `adapter.id === 'codex'`.
354
+
355
+ Plus a few cosmetic per-id sites that are *expected* edits, not drift: the
356
+ provider beta-gate env checks (`server/desktop-router.ts`), the install-hint
357
+ `switch` (`server/setup-prerequisites.ts`), the `PROVIDER_ORDER` / `PROVIDER_META`
358
+ chip, and the duplicated model catalog (`server/spec-models.ts`).
359
+
360
+ The long-term goal is to delete the two remaining branches so adding a fourth
361
+ provider really is just the adapter file plus the registry entry. If you find a
362
+ **new** hardcoded `if (provider === 'X')` site in a manager that this guide
363
+ doesn't list, **the architecture has drifted further** — file an OpenSpec
364
+ change at `openspec/changes/<your-change-name>/` and capture the drift before
238
365
  papering over it with another manager-level branch.
366
+
367
+ ## See also
368
+
369
+ - [`docs/codex.md`](../codex.md) and [`docs/gemini.md`](../gemini.md) — the
370
+ user-facing guides for the two non-Claude providers; `gemini.md` is the most
371
+ recent worked example end-to-end.