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
@@ -2,6 +2,10 @@
2
2
 
3
3
  REST and WebSocket endpoints exposed by the app server. The server binds to `127.0.0.1` only (loopback); the default port is `4200` but it can be overridden with `--port <n>` on the server command line.
4
4
 
5
+ > **New here?** This page is the contract the desktop UI, the CLI, and the mobile gateway all speak to the local server. **You normally never call these endpoints directly — the app does it for you.** Read on only if you are scripting against the server, writing an integration, or debugging. Everything is local-only: there is no cloud API.
6
+
7
+ The app speaks to three interchangeable AI provider CLIs — **Claude, Codex, and Gemini** — all enabled by default. Endpoints that accept a provider value (`provider` / `aiEngine`) take any of `claude`, `codex`, or `gemini`, validated against the providers the project actually installed. See the [Codex guide](../codex.md) and the [Gemini guide](../gemini.md) for provider specifics.
8
+
5
9
  ## Authentication
6
10
 
7
11
  An app token is **auto-generated on first run** (two concatenated UUIDs) and persisted to `~/.specrails/desktop.token` with mode `0600`. It is **mandatory**, not optional. Every `/api/*` route is protected by it, with two exceptions that are mounted before the auth middleware: `/api/health` and `/api/token`.
@@ -17,7 +21,7 @@ The CLI and the desktop client read the token automatically. The browser client
17
21
 
18
22
  There is no UI to set or clear the token, and it is not an app setting.
19
23
 
20
- This page is hand-maintained against the route declarations in `server/*-router.ts`. If you spot a discrepancy, please file an issue.
24
+ This page is hand-maintained against the route declarations in `server/*-router.ts`, the per-domain `server/project-router-{jobs,spending,settings,terminals,tickets,chat,setup}.ts` family, `server/code-explorer-router.ts`, and `server/jira-router.ts`. If you spot a discrepancy, please file an issue.
21
25
 
22
26
  ---
23
27
 
@@ -27,14 +31,15 @@ This page is hand-maintained against the route declarations in `server/*-router.
27
31
  |--------|--------|------|-------|
28
32
  | `/api/health` | direct | none | Liveness probe (`{ status, version, uptime, projects, mode }`) |
29
33
  | `/api/token` | direct | none | Returns the auth token for local bootstrapping (loopback-only) |
30
- | `/api/docs` | `docs-router` | none (mounted before auth) | Bundled documentation portal |
34
+ | `/api/docs` | `docs-router` | loopback-only (mounted before token auth) | Bundled documentation portal |
31
35
  | `/api/mobile/*` | `mobile-admin-router` | Bearer / X-Desktop-Token + loopback | Mobile Gateway admin (enable/pair/devices) |
32
36
  | `/api/*` | `desktop-router` | Bearer / X-Desktop-Token | Cross-project operations |
33
37
  | `/api/projects/:projectId/*` | `project-router` | Bearer / X-Desktop-Token | Project-scoped operations |
34
- | `/api/projects/:projectId/code/*` | `code-explorer-router` | Bearer / X-Desktop-Token | Read-only Code explorer |
38
+ | `/api/projects/:projectId/code/*` | `code-explorer-router` | Bearer / X-Desktop-Token | Code explorer (read + in-app file editing; 404 when the gate is off) |
35
39
  | `/api/projects/:projectId/rails/*` | `rails-router` | Bearer / X-Desktop-Token | Rails (execution lanes) |
36
40
  | `/api/projects/:projectId/profiles/*` | `profiles-router` | Bearer / X-Desktop-Token | Agent profiles + catalog studio |
37
41
  | `/api/projects/:projectId/plugins/*` | `plugins-router` | Bearer / X-Desktop-Token | Plugin marketplace |
42
+ | `/api/projects/:projectId/jira/*` | `jira-router` | Bearer / X-Desktop-Token | Jira integration (404 when `SPECRAILS_JIRA_SECTION=false`) |
38
43
  | `/otlp/v1/{traces,metrics,logs}` | `telemetry-receiver` | none (gated by job id) | OTLP/JSON receiver |
39
44
  | `/ws` | WebSocket | token in query | Project + app event stream |
40
45
  | `/ws/terminal/:id` | WebSocket | token in query | PTY traffic for the terminal panel |
@@ -54,17 +59,29 @@ A non-localhost `Origin` header is rejected by the CORS middleware with `403 For
54
59
  | Method | Path | Notes |
55
60
  |--------|------|-------|
56
61
  | `GET` | `/projects` | List registered projects |
57
- | `POST` | `/projects` | Register a project. Body `{ path, name?, provider?, providers? }`. `providers: string[]` enables a multi-provider project (first entry = primary/default); legacy single `provider` still honoured; omit both to default to `["claude"]`. 409 if the path is already registered |
62
+ | `POST` | `/projects` | Register a project. Body `{ path, name?, provider?, providers? }`. Each provider value is one of `claude`, `codex`, `gemini` (registry-validated). `providers: string[]` enables a multi-provider project (first entry = primary/default); legacy single `provider` still honoured; omit both to default to `["claude"]`. 409 if the path is already registered. 400 if a provider is unknown, or if a disabled provider is selected: `codex` when `SPECRAILS_CODEX_BETA=0`, `gemini` when `SPECRAILS_GEMINI_BETA=0` (both default-enabled) |
58
63
  | `DELETE` | `/projects/:id` | Unregister (does not delete the project directory) |
59
64
  | `GET` | `/resolve?path=…` | Find a project by **exact** canonical filesystem path. No parent-directory walking — a subdirectory returns 404 |
60
65
 
66
+ Example — register a project that uses both Claude and Gemini:
67
+
68
+ ```json
69
+ // POST /api/projects
70
+ {
71
+ "path": "/Users/me/code/my-app",
72
+ "name": "My App",
73
+ "providers": ["claude", "gemini"]
74
+ }
75
+ // → 201 { "project": { "id": "my-app", "name": "My App", "provider": "claude", "providers": ["claude", "gemini"], ... } }
76
+ ```
77
+
61
78
  ### App state
62
79
 
63
80
  | Method | Path | Notes |
64
81
  |--------|------|-------|
65
82
  | `GET` | `/state` | `{ projects, projectCount, …todayStats }` (today's cross-project cost/run aggregates spread into the response) |
66
- | `GET` | `/cli-status` | Detected AI CLI provider + version (`{ provider, version }`), e.g. claude or codex — runs `<binary> --version` |
67
- | `GET` | `/available-providers` | Provider catalogue (Claude, Codex) used by the setup wizard |
83
+ | `GET` | `/cli-status` | Detected AI CLI provider + version (`{ provider, version }`), e.g. `claude`, `codex`, or `gemini` — runs `<binary> --version`. Registry-driven |
84
+ | `GET` | `/available-providers` | Provider catalogue used by the setup wizard. Registry-driven map (`{ claude, codex, gemini, tiers }`) reporting which CLIs are installed. Codex/Gemini are surfaced unless forced off by `SPECRAILS_CODEX_BETA=0` / `SPECRAILS_GEMINI_BETA=0` (both enabled by default) |
68
85
  | `GET` | `/core-compat` | specrails-core version compatibility probe |
69
86
  | `GET` | `/setup-prerequisites` | Tool checks (`node`/`npm`/`npx`/`git`, optionally `uv`). Add `?diagnostic=1` to nest a `diagnostic` object: `{ pathSegments, pathSources, loginShellStatus, whichResults, nodeEnv, platform }` |
70
87
 
@@ -155,6 +172,14 @@ All routes below are prefixed with `/api/projects/:projectId/`. In the client, u
155
172
  | `POST` | `/config` | Force re-discovery |
156
173
  | `GET` | `/default-spec-model?provider=` | Resolve the Quick-spec model for an engine. Returns `{ model, provider, allowed, providers }`; `provider` falls back to the primary if omitted/invalid |
157
174
 
175
+ Example — queue a command on a specific provider:
176
+
177
+ ```json
178
+ // POST /api/projects/my-app/spawn
179
+ { "command": "/specrails:implement #42 --yes", "aiEngine": "gemini" }
180
+ // → 202 { "jobId": "j_01H...", "position": 0 }
181
+ ```
182
+
158
183
  ### Pipelines and jobs
159
184
 
160
185
  | Method | Path | Notes |
@@ -170,8 +195,32 @@ All routes below are prefixed with `/api/projects/:projectId/`. In the client, u
170
195
  | `DELETE` | `/jobs/:id` | Cancel a running or queued job |
171
196
  | `DELETE` | `/jobs` | Purge completed jobs (optional `{ from, to }` window) |
172
197
  | `PATCH` | `/jobs/:id/priority` | Re-rank a queued job |
198
+ | `POST` | `/jobs/:id/messages` | Send one more user turn to a running **interactive** ultracode job. Body `{ text }`. `202` accepted, `400` missing text, `403` interactive jobs disabled, `409` the job is not an active interactive session |
199
+ | `POST` | `/jobs/:id/finalize` | Finalize a running interactive job (SIGTERM the resident child; final totals + `completed` status are stamped when it closes). `202` scheduled, `403` interactive jobs disabled, `409` not an active interactive session |
173
200
  | `GET` | `/jobs/:jobId/diagnostic` | Stream a diagnostic ZIP (telemetry + profile + plugins snapshots) |
174
201
 
202
+ The two interactive endpoints back the in-job chat for **Interactive Ultracode** rails (Claude-only). They both 403 when the server has `SPECRAILS_INTERACTIVE_JOBS=false`.
203
+
204
+ Example — fetch one job:
205
+
206
+ ```json
207
+ // GET /api/projects/my-app/jobs/j_01H...
208
+ {
209
+ "job": {
210
+ "id": "j_01H...",
211
+ "command": "/specrails:implement #42 --yes",
212
+ "status": "completed",
213
+ "total_cost_usd": 0.83,
214
+ "num_turns": 14,
215
+ "model": "sonnet",
216
+ "hasTelemetry": true,
217
+ "tickets": [{ "id": 42, "title": "Add CSV export" }]
218
+ },
219
+ "events": [ /* streamed job events */ ],
220
+ "phaseDefinitions": [ /* architect → developer → reviewer → ship */ ]
221
+ }
222
+ ```
223
+
175
224
  ### Queue
176
225
 
177
226
  Jobs within a project run **strictly one at a time** (serialized) — a single queue per project. Parallelism is across projects only.
@@ -196,6 +245,21 @@ Spending is tracked across six surfaces: `job`, `quick-spec`, `explore-spec`, `a
196
245
  | `GET` | `/tickets/:id/spending-summary` | Per-ticket cross-surface aggregate (powers `TicketSpendingLine`) |
197
246
  | `GET` | `/analytics/export?format=csv\|json&mode=summary\|raw&…` | Multi-section summary CSV/JSON, or raw rows (10 000 cap) |
198
247
 
248
+ Example — the Analytics dashboard payload (abridged):
249
+
250
+ ```json
251
+ // GET /api/projects/my-app/spending?period=30d
252
+ {
253
+ "summary": { "totalCostUsd": 12.40, "totalRuns": 58, "prevPeriodDeltaPct": -8.2, "trackingStartedAt": "2026-05-01" },
254
+ "bySurface": [{ "surface": "job", "costUsd": 9.10 }, { "surface": "explore-spec", "costUsd": 2.30 }],
255
+ "byModel": [{ "model": "sonnet", "costUsd": 8.00 }, { "model": "gemini-3.5-flash", "costUsd": 1.20 }],
256
+ "dailyTimeline": [ /* zero-filled, stacked by surface */ ],
257
+ "topTickets": [ /* top 10 cross-surface */ ]
258
+ }
259
+ ```
260
+
261
+ Cost is **provider-billed and exact for Claude**; for Codex and Gemini it is **estimated from a rate card** (those CLIs do not report a native cost).
262
+
199
263
  ### Budget
200
264
 
201
265
  | Method | Path | Notes |
@@ -216,7 +280,7 @@ Spending is tracked across six surfaces: `job`, `quick-spec`, `explore-spec`, `a
216
280
  | `POST` | `/tickets/save-as-draft` | Persist an Explore conversation as a draft (idempotent on `conversationId`) |
217
281
  | `POST` | `/tickets/from-draft` | Commit a draft (flip-in-place) or insert a new ticket |
218
282
  | `POST` | `/tickets/from-prompt` | Create a ticket directly from a prompt |
219
- | `POST` | `/tickets/:id/contract-refine` | Retry Contract Refine for an existing ticket (202 / 404 / 409) |
283
+ | `POST` | `/tickets/:id/contract-refine` | Retry Contract Refine for an existing ticket. `202` scheduled, `404` unknown ticket, `409` when: the project is Codex (`contract_refine_unsupported_for_codex` — Contract Refine is Claude-only), the kill switch is active (`feature_disabled_by_env`), or the ticket has no origin conversation |
220
284
  | `POST` | `/tickets/:id/smash` | SMASH an epic into sub-specs |
221
285
  | `POST` | `/tickets/:id/smash/undo` | Undo a SMASH operation |
222
286
  | `DELETE` | `/tickets/:id/children` | Delete all children of an epic |
@@ -251,7 +315,7 @@ The setup wizard is a three-step flow (Configure / Install / Done). The `enrich/
251
315
  | Method | Path | Notes |
252
316
  |--------|------|-------|
253
317
  | `POST` | `/setup/install-config` | Write `.specrails/install-config.yaml` to the project |
254
- | `POST` | `/setup/install` | Run `npx specrails-core@^4.6.0 init --from-config <file>` |
318
+ | `POST` | `/setup/install` | Run `npx specrails-core init --from-config <file>` (the pinned core release — currently `specrails-core@^4.8.0` — is resolved by SetupManager, overridable via `SPECRAILS_CORE_BIN`) |
255
319
  | `POST` | `/setup/start` | Legacy setup-chat session start |
256
320
  | `POST` | `/setup/message` | Legacy setup-chat turn |
257
321
  | `POST` | `/enrich/start` | Legacy AI-enrich session start |
@@ -348,12 +412,13 @@ Gated by `requireBrowserCaptureEnabled` — returns 404 when the feature is disa
348
412
 
349
413
  ## `/api/projects/:projectId/code/*`
350
414
 
351
- Read-only Code explorer (mounted via `code-explorer-router`; 404 when the server gate is off).
415
+ A non-developer-friendly file tree + Monaco viewer with plain-language AI summaries and *touched-by-AI* provenance chips, plus opt-in in-app editing of existing files (overwrite-only). Mounted via `code-explorer-router`; 404 when the server gate is off.
352
416
 
353
417
  | Method | Path | Notes |
354
418
  |--------|------|-------|
355
419
  | `GET` | `/tree?withProvenance=1&filter=touched-by-ai\|all&cursor=…` | Virtualised file tree (pagination cap 2000, `.gitignore`-aware) |
356
420
  | `GET` | `/file?path=…` | File contents (binary refusal, 2 MB cap, path-traversal guard) |
421
+ | `PUT` | `/file` | In-app edit: overwrite an **existing** text file. Body `{ path, content }`. Overwrite-only (no create, no rename); same traversal / deny-list / `.gitignore` guards as the read path. `404` if the path does not exist, `413` over the 2 MB cap, `415` for binary content/files |
357
422
  | `GET` | `/summary?path=…` | Plain-language AI summary for a file |
358
423
  | `POST` | `/file/regenerate-summary?path=…` | Enqueue a summary regeneration. Body `{ overrideBudget? }` → `202 { enqueued: true }` |
359
424
  | `GET` | `/provenance?ticketId=…` | Files touched by a ticket |
@@ -368,15 +433,18 @@ Read-only Code explorer (mounted via `code-explorer-router`; 404 when the server
368
433
  | `GET` | `/` | List rails |
369
434
  | `PUT` | `/:railIndex/tickets` | Assign tickets to a rail. Body `{ ticketIds: number[] }` |
370
435
  | `PUT` | `/:railIndex/profile` | Set the rail's default profile |
371
- | `PUT` | `/:railIndex/engine` | Set the rail's AI engine override. Body `{ aiEngine }` (string or `null` to clear) |
372
- | `POST` | `/:railIndex/launch` | Launch the rail. Body `{ mode?, profileName?, aiEngine?, model? }`; `mode` is `implement` / `batch-implement` / `ultracode`; `model` (haiku/sonnet/opus) applies to ultracode only |
373
- | `POST` | `/:railIndex/stop` | Stop the rail's running job |
436
+ | `PUT` | `/:railIndex/engine` | Set the rail's AI engine override. Body `{ aiEngine }` (string — one of the project's providers — or `null` to clear) |
437
+ | `PUT` | `/:railIndex/name` | Set the rail's display name. Body `{ name }` (string or `null` to clear back to the default label); 400 if longer than 60 characters |
438
+ | `POST` | `/:railIndex/launch` | Launch the rail. Body `{ mode?, profileName?, aiEngine?, model?, interactive? }`. `mode` is `implement` / `batch-implement` / `ultracode`; `model` (haiku/sonnet/opus) applies to ultracode only; `interactive: true` opens an in-job chat and is **ultracode-only** (400 for any other mode, 403 when interactive jobs are disabled). Returns `202 { jobId, railIndex, mode }`; **`503`** when the Claude or Codex CLI binary is not found (a missing Gemini/other binary surfaces as `500`) |
439
+ | `POST` | `/:railIndex/stop` | Stop the rail's running job (cancels every job the rail registered) |
374
440
 
375
441
  ---
376
442
 
377
443
  ## `/api/projects/:projectId/profiles/*`
378
444
 
379
- Gated by `SPECRAILS_AGENTS_SECTION !== 'false'`. Profiles are effectively Claude-only a non-Claude rail engine runs in legacy mode.
445
+ Gated by `SPECRAILS_AGENTS_SECTION !== 'false'`. Rails force legacy (no-profile) mode whenever the chosen engine is not Claude, and the Agents section is hidden in multi-provider projects; profile env-injection itself works for any provider whose adapter advertises `profileEnvSupport`.
446
+
447
+ > **Provider capability notes.** A few behaviours are not the same across all three providers: **Contract Refine** is Claude-only; **rails force legacy (no-profile) mode** for any non-Claude engine; **Ultracode rails** are Claude-only; the **Serena plugin** (and other `project-json` plugins) work for Claude and Gemini but are filtered out for Codex; and **cost is exact only for Claude** (estimated from a rate card for Codex and Gemini). See the [Codex guide](../codex.md) and [Gemini guide](../gemini.md).
380
448
 
381
449
  ### Profile CRUD
382
450
 
@@ -387,8 +455,8 @@ Gated by `SPECRAILS_AGENTS_SECTION !== 'false'`. Profiles are effectively Claude
387
455
  | `GET` | `/:name` | One profile |
388
456
  | `PATCH` | `/:name` | Update |
389
457
  | `DELETE` | `/:name` | Delete |
390
- | `POST` | `/:name/duplicate` | Duplicate. Body `{ newName }` |
391
- | `POST` | `/:name/rename` | Rename. Body `{ newName }` |
458
+ | `POST` | `/:name/duplicate` | Duplicate. Body `{ name }` (the new profile name) |
459
+ | `POST` | `/:name/rename` | Rename. Body `{ name }` (the new profile name) |
392
460
  | `GET` | `/resolve?profile=…` | Preview which profile would run given a selection |
393
461
 
394
462
  ### Bootstrap and analytics
@@ -445,9 +513,32 @@ Gated by `SPECRAILS_PLUGINS_SECTION !== 'false'`.
445
513
 
446
514
  ---
447
515
 
516
+ ## `/api/projects/:projectId/jira/*`
517
+
518
+ Optional per-project Jira integration: a project's specs can be backed by a Jira board instead of the local store. Mounted via `jira-router` and gated by `SPECRAILS_JIRA_SECTION` — **every route 404s when the flag is `false`**. Inert until a connection is configured. The Jira token is never returned to the client (connection responses carry `hasToken` only). The first six endpoints back the step-by-step connect wizard (test → pick project → optional status map → connect).
519
+
520
+ | Method | Path | Notes |
521
+ |--------|------|-------|
522
+ | `GET` | `/connection` | Current connection (token redacted) or `{ connected: false }` |
523
+ | `PATCH` | `/connection` | Toggle `enabled` (hot-swap local ↔ Jira) and/or update the discard status / status map. `404` if no connection |
524
+ | `DELETE` | `/connection` | Disconnect and restore the local backlog config |
525
+ | `POST` | `/test` | Wizard step 1: validate credentials without saving. Body `{ baseUrl, accountEmail?, token }`. `401` on bad credentials |
526
+ | `POST` | `/discover-projects` | Wizard step 2: list visible Jira projects. Body `{ baseUrl, accountEmail?, token, query? }` |
527
+ | `POST` | `/discover-statuses` | Wizard step 3 (optional): list a project's statuses. Body `{ baseUrl, accountEmail?, token, projectKey }` |
528
+ | `POST` | `/connect` | Wizard final step: validate + persist + start sync. Body `{ baseUrl, accountEmail?, token, jiraProjectKey, statusMap?, discardStatus? }`. `201` on success |
529
+ | `GET` | `/statuses` | The connected project's real statuses (post-connect picker), using stored credentials |
530
+ | `POST` | `/resume` | Re-paste a fresh token after a `401` and drain the parked outbox |
531
+ | `POST` | `/sync` | Manual "Sync now" — a full re-fetch ignoring the high-water mark |
532
+ | `GET` | `/outbox?state=` | List durable write-back ops (optional `state=pending\|inflight\|done\|dead`) + counts |
533
+ | `POST` | `/outbox/:id/retry` | Re-queue a dead-lettered op. `404` if the op is missing or not dead |
534
+ | `POST` | `/specs` | Add Spec when the project source is Jira: create the issue in Jira and materialize it locally. Body `{ title, description?, labels?, priority?, issueType? }` → `201 { localId, jiraKey }` |
535
+ | `POST` | `/specs/:localId/discard` | Move the linked issue to the configured discard status (instead of deleting). Body `{ comment? }`. `404` if unlinked, `409` otherwise |
536
+ | `GET` | `/specs/:localId/details` | Read-only Jira details + development payload for the spec detail modal |
537
+ | `GET` | `/links` | The spec ↔ Jira issue map (drives the badge and diagnostics) |
538
+
448
539
  ## `/api/docs/*`
449
540
 
450
- The bundled documentation portal (served by `docs-router`, public — mounted before auth).
541
+ The bundled documentation portal (served by `docs-router`, loopback-only — mounted before token auth).
451
542
 
452
543
  | Method | Path | Notes |
453
544
  |--------|------|-------|
@@ -476,17 +567,21 @@ A single connection at `ws://127.0.0.1:4200/ws?token=<authToken>` multiplexes ev
476
567
 
477
568
  Every project-scoped message includes a `projectId` field. App-level messages have no `projectId` and reach every handler.
478
569
 
570
+ **On connect**, the current Super-mode server sends exactly **one** frame: `desktop.projects` (the project list). There is **no live `init` frame** — the `init` type still exists in `server/types.ts` and is consumed by `usePipeline`, but only demo-mode emits it; per-project initial state is fetched via REST (e.g. `GET /jobs`, `GET /queue`).
571
+
479
572
  ### Job, queue & pipeline
480
573
 
481
574
  | Type | Scope | Notes |
482
575
  |------|-------|-------|
483
- | `init` | project | Per-connection dashboard snapshot sent on (re)connect: `{ projectName, phases, phaseDefinitions, logBuffer, recentJobs, queue }` |
484
576
  | `log` | project | Streaming log line |
485
577
  | `event` | project | Structured job event |
486
578
  | `phase` | project | Pipeline phase transition |
487
579
  | `queue` | project | Queue snapshot (`{ jobs, activeJobId, paused, timestamp }`) — job-exit state changes reach the client here |
488
580
  | `pipeline_status` | project | Pipeline finished (`completed` / `failed`) |
489
581
  | `exit` | both | Replay of a process exit (`{ code, signal, early }`); also emitted on the terminal stream |
582
+ | `job.turn_user` | project | Interactive job: a user prompt was accepted (echoed so the in-job chat can render the bubble immediately; `queued` is true when a turn is already streaming) |
583
+ | `job.turn_done` | project | Interactive job: a turn finished streaming, carrying the running sum of real token/cost totals |
584
+ | `job.finalized` | project | Interactive job finalized (or crashed): final authoritative totals + terminal status |
490
585
 
491
586
  ### Budget & cost
492
587
 
@@ -540,6 +635,7 @@ Every project-scoped message includes a `projectId` field. App-level messages ha
540
635
  | Type | Scope | Notes |
541
636
  |------|-------|-------|
542
637
  | `rail.job_started` / `rail.job_completed` / `rail.job_stopped` | project | Rail job lifecycle |
638
+ | `rail.updated` | project | A non-launch rail change (tickets reassigned, renamed, mode/profile/engine edited) — carries the full post-mutation rail snapshot |
543
639
 
544
640
  ### Plugins
545
641
 
@@ -557,6 +653,16 @@ Every project-scoped message includes a `projectId` field. App-level messages ha
557
653
  | `file.provenance_updated` | project | A job touched files |
558
654
  | `file.summary_updated` / `file.summary_failed` / `file.summary_skipped` | project | Summary lifecycle |
559
655
 
656
+ ### Jira
657
+
658
+ | Type | Scope | Notes |
659
+ |------|-------|-------|
660
+ | `jira.synced` | project | Inbound poll materialized issues into the local cache |
661
+ | `jira.sync_error` | project | A sync attempt failed |
662
+ | `jira.auth_expired` | project | A `401` paused the project; the user must re-paste a token (then `POST /jira/resume`) |
663
+ | `jira.outbox_changed` | project | The durable write-back outbox changed (op enqueued/drained/dead-lettered) |
664
+ | `jira.degraded` | project | A write-back op was dead-lettered or a path is blocked; sync continues |
665
+
560
666
  ### Setup wizard
561
667
 
562
668
  | Type | Scope | Notes |
@@ -616,10 +722,13 @@ The app uses standard HTTP status codes. Notable conventions:
616
722
 
617
723
  - `400` — malformed body / invalid params
618
724
  - `401` — missing or invalid token (Bearer or `X-Desktop-Token`)
619
- - `403` — cross-origin request (a non-localhost `Origin` header)
620
- - `404` — resource not found (including a project resolved from an unregistered path)
621
- - `409` — write conflict (file-lock contention on tickets, plugin name collision, project path already registered)
725
+ - `403` — cross-origin request (a non-localhost `Origin` header), or a feature gated off (interactive jobs disabled, code-explorer deny-list/gitignore)
726
+ - `404` — resource not found (including a project resolved from an unregistered path, or any route under a disabled section gate such as Jira / Code explorer)
727
+ - `409` — write conflict (file-lock contention on tickets, plugin/profile name collision, project path already registered) or a state conflict (e.g. not an active interactive job, Contract Refine unsupported)
728
+ - `413` — payload too large (code-explorer edit over the 2 MB cap)
729
+ - `415` — unsupported media type (code-explorer edit of binary content)
622
730
  - `500` — unhandled exception (logged to stdout)
731
+ - `503` — the Claude or Codex CLI binary was not found when launching a rail job (a missing Gemini/other-provider binary falls through to `500`)
623
732
 
624
733
  Error responses are `{ "error": "<message>" }`.
625
734
 
@@ -627,5 +736,5 @@ Error responses are `{ "error": "<message>" }`.
627
736
 
628
737
  ## Caveats
629
738
 
630
- - **Surface drift**: this file is hand-maintained against the route declarations in `server/*-router.ts` and `server/code-explorer-router.ts`. The app adds endpoints regularly; if a route exists in code but not here, please open an issue.
739
+ - **Surface drift**: this file is hand-maintained against the route declarations in `server/*-router.ts`, the per-domain `server/project-router-{jobs,spending,settings,terminals,tickets,chat,setup}.ts` family, `server/code-explorer-router.ts`, and `server/jira-router.ts`. The app adds endpoints regularly; if a route exists in code but not here, please open an issue.
631
740
  - **Stability**: routes under `/api/*` and `/api/projects/:projectId/*` are considered stable. A few legacy setup endpoints (`setup/start`, `setup/message`, `enrich/*`) back a flow the UI does not expose and remain only for forward compatibility.
@@ -1,6 +1,6 @@
1
1
  # Architecture
2
2
 
3
- This document describes the technical architecture of specrails-desktop (v1.63.1): its layers, data layout, request flow, authentication, and the subsystems that make up the app. It is the entry point to the other internals docs — see the [See also](#see-also) block at the bottom.
3
+ This document describes the technical architecture of specrails-desktop: its layers, data layout, request flow, authentication, and the subsystems that make up the app. It is the entry point to the other internals docs — see the [See also](#see-also) block at the bottom. (The authoritative version lives in `package.json`; this doc is verified against `main`.)
4
4
 
5
5
  ---
6
6
 
@@ -39,16 +39,22 @@ Tests use vitest with `:memory:` SQLite databases.
39
39
  ~/.specrails/
40
40
  desktop.sqlite # project registry (id, name, path, slug, provider…)
41
41
  desktop.token # auth token, mode 0600 (auto-generated on first run)
42
+ registry.json # repo-realpath → workspace map shared with specrails-core (artifact relocation)
42
43
  manager.pid # server PID for clean shutdown
44
+ framework/<version>/<provider>/ # bundled specrails-core framework, materialized once
45
+ framework/current # symlink → active framework version (atomic swap on app update)
43
46
  projects/
44
47
  <slug>/
45
48
  jobs.sqlite # per-project: jobs, rails, tickets, invocations, …
46
49
  jobs/<jobId>/ # per-job snapshots (profile.json, plugins.json, …)
50
+ workspace/ # relocated spawn cwd (artifactRoot); ./project link → repo
47
51
  telemetry/ # OTEL blobs (compacted after 7 days)
48
52
  explore-cwd/ # app-managed Explore spawn cwd (CLAUDE.md + ./project link)
49
53
  terminals/ # per-session shell-integration shims
50
54
  ```
51
55
 
56
+ > **Artifact relocation + bundled framework (pre-release, branch `feat/relocate-artifacts-to-home`).** Relocated projects spawn AI-CLIs from `projects/<slug>/workspace` (with `SPECRAILS_REPO_DIR` pointing at the repo) instead of the repo, so imported repos stay pristine; the framework is bundled and symlinked instead of installed per-project via `npx`. See the **Artifact relocation + bundled framework** section in `CLAUDE.md` and the three internal docs: `global-artifacts-relocation-evaluation.md`, `global-artifacts-alignment-contract.md`, `bundled-framework-build-plan.md`.
57
+
52
58
  The app SQLite (`desktop.sqlite`) stores only project metadata. All per-project data lives in an isolated `jobs.sqlite` under the project's slug directory — not just jobs and chat, but rails, tickets, agent profiles/versions, AI invocations (cost analytics), telemetry pointers, file provenance, terminal settings/marks, and more (see the `MIGRATIONS` array in `server/db.ts`). Projects can be removed and re-added without losing history, and the registry can be wiped without touching project data.
53
59
 
54
60
  > The data root is hardcoded to `os.homedir()/.specrails`. There is no environment override for the data directory.
@@ -153,7 +159,7 @@ client/src/
153
159
  │ ├── AnalyticsPage.tsx # Per-project cost analytics
154
160
  │ ├── DesktopAnalyticsPage.tsx # Cross-project spending roll-up
155
161
  │ ├── AgentsPage.tsx # Agent profiles + catalog
156
- │ ├── CodePage.tsx # Read-only code explorer (flag-gated)
162
+ │ ├── CodePage.tsx # Code explorer: file tree + Monaco viewer + edit (flag-gated)
157
163
  │ ├── SettingsPage.tsx # Per-project settings
158
164
  │ ├── GlobalSettingsPage.tsx # App settings
159
165
  │ └── JobDetailPage.tsx # Full log viewer for a single job
@@ -202,20 +208,25 @@ A single WebSocket connection at `ws://127.0.0.1:4200/ws` multiplexes all applic
202
208
 
203
209
  Every project-scoped message includes a `projectId` field; app-level messages (`desktop.project_added`, `desktop.project_removed`, `desktop.projects`) have none.
204
210
 
211
+ ### Connect handshake
212
+
213
+ The **only** frame the server sends on connect is `desktop.projects` (the full project registry) — `server/index.ts` pushes it inside `wss.on('connection', …)`. There is no rich per-connection dashboard snapshot pushed automatically. After connecting, a client subscribes to a project (sends a subscribe frame with `projectId`); per-project state then arrives as the project broadcasts it — notably the `queue` snapshot and per-job `exit` replay. A new client should code against `desktop.projects`, not against an `init` frame.
214
+
215
+ > **`init` is defined-but-unused.** A `type:'init'` shape exists as a TypeScript interface in `server/types.ts`, but no code path emits it in Super mode — it is a legacy shape, not a live frame. Do not wire a client to receive it.
216
+
205
217
  ### Representative message types
206
218
 
207
219
  Canonical shapes live in `server/types.ts`. The core dashboard messages:
208
220
 
209
221
  | Type | Scope | Payload (key fields) |
210
222
  |------|-------|----------------------|
211
- | `init` | project | `{ projectName, phases, phaseDefinitions, logBuffer, recentJobs, queue, projectId }` — per-connection dashboard snapshot sent on (re)connect |
223
+ | `desktop.projects` | app | `{ projects }` — full registry, the **on-connect** frame |
212
224
  | `queue` | project | `{ jobs, activeJobId, paused, timestamp, projectId }` — full queue snapshot |
213
225
  | `log` | project | `{ source: 'stdout'\|'stderr', line, timestamp, processId, projectId }` |
214
226
  | `phase` | project | `{ phase, state, timestamp, projectId }` |
215
227
  | `exit` | project | `{ code, signal, early }` — process exit replay on the WS upgrade |
216
228
  | `desktop.project_added` | app | `{ project }` |
217
229
  | `desktop.project_removed` | app | `{ projectId }` |
218
- | `desktop.projects` | app | `{ projects }` |
219
230
 
220
231
  Job lifecycle is reported by the message types `job_started`, `job_completed`, `job_failed`, and `job_canceled`. Feature subsystems add many more (`spending.invalidated`, `plugin.*`, `file.*`, `rail.job_started/completed/stopped`, `explore.contract_refine_failed`, chat/refine/SMASH/proposal streams). See [`api-reference.md`](api-reference.md) for the full outbound-event catalogue.
221
232
 
@@ -237,7 +248,7 @@ App-level messages (no `projectId`) are processed by all handlers.
237
248
 
238
249
  ## Process spawning and concurrency
239
250
 
240
- `QueueManager` and `ChatManager` spawn the provider CLI (`claude` or `codex`) as subprocesses, always with `cwd` set so the process runs in the correct directory.
251
+ `QueueManager` and `ChatManager` spawn the project's provider CLI (`claude`, `codex`, or `gemini`) as subprocesses, always with `cwd` set so the process runs in the correct directory. The exact binary and argv are chosen by the resolved `ProviderAdapter` — managers never branch on the provider id (see [Multi-provider adapters](#feature-subsystems)).
241
252
 
242
253
  - **Within a project, jobs run strictly one at a time.** Each `ProjectContext` has exactly one `QueueManager` with a single `_activeJobId`; `_drainQueue()` early-returns while a job is active, so the next rail job queues behind the current one.
243
254
  - **Parallelism is across projects only** — each project has its own `QueueManager`, so jobs in different projects run simultaneously. There is no "max concurrent jobs" setting; the only automatic queue-pause is budget-based (daily budget / per-job cost alert).
@@ -253,15 +264,16 @@ The app is more than the job pipeline. Each subsystem owns its modules; this is
253
264
 
254
265
  | Subsystem | Server modules | Notes |
255
266
  |-----------|---------------|-------|
256
- | **Multi-provider adapters** | `server/providers/{types,claude-adapter,codex-adapter,registry,index}.ts`, `server/provider-selection.ts` | Claude (full native support) and Codex ( 0.128.0, estimated cost, synthesized OTEL) behind a `ProviderAdapter` contract. A project can install both; `providers[]` is a JSON column, the first entry is primary. Per-invocation provider is late-bound. See [`adding-a-provider.md`](adding-a-provider.md). |
267
+ | **Multi-provider adapters** | `server/providers/{types,claude-adapter,codex-adapter,gemini-adapter,registry,index}.ts`, `server/provider-selection.ts` | **Three first-class providers — Claude, Codex, and Gemini — all enabled by default** behind a `ProviderAdapter` contract. Claude has full native support (native cost + native OTEL + `--system-prompt`); Codex (`≥ 0.128.0`) has estimated cost and OTEL synthesized by the app; Gemini (`≥ 0.11.0`) has estimated cost but **native OTEL** (it honours the standard `OTEL_*` env vars QueueManager injects — no synthetic bridge), folds its system prompt into `GEMINI.md`, uses `project-json` MCP registration, defaults to `gemini-3.5-flash`, and uniquely implements the optional `prepareHeadlessSpawn()` hook to pre-acknowledge subagents for headless rail spawns. A project can install any subset; `providers[]` is a JSON column, the first entry is primary. Per-invocation provider is late-bound. Provider availability is gated by `SPECRAILS_CODEX_BETA` / `SPECRAILS_GEMINI_BETA` (set either to `0` to disable; both default-enabled, see [`configuration.md`](configuration.md)). See [`adding-a-provider.md`](adding-a-provider.md), [`../codex.md`](../codex.md), and [`../gemini.md`](../gemini.md). |
257
268
  | **Spending analytics** | `server/spending.ts`, `server/ai-invocations.ts`, `server/pricing.ts` | `recordInvocation` writes an `ai_invocations` row per AI CLI call across six surfaces (`job`, `quick-spec`, `explore-spec`, `ai-edit`, `smash`, `file-summary`); powers the Analytics page and `spending.invalidated`. |
258
- | **Agent profiles** | `server/profile-manager.ts`, `server/profiles-router.ts` | Declarative JSON in `.specrails/profiles/*.json`, snapshot-per-job, `SPECRAILS_PROFILE_PATH` env injection. Requires `specrails-core ≥ 4.1.0`. |
269
+ | **Agent profiles** | `server/profile-manager.ts`, `server/profiles-router.ts` | Declarative JSON in `.specrails/profiles/*.json`, snapshot-per-job, `SPECRAILS_PROFILE_PATH` env injection. Requires `specrails-core ≥ 4.1.0` **in the project** (distinct from the app-wide install floor of `^4.8.0` — see [Setup wizard flow](#setup-wizard-flow)). Claude-only: the rails router force-nulls the profile for any non-Claude engine. |
259
270
  | **Plugins (Integrations)** | `server/plugin-manager.ts`, `server/plugins/` | Bundled-only, MCP-based, additivity invariant, surgical `.mcp.json` merge, `plugin.*` WS events. Serena ships today. |
260
271
  | **Terminal panel** | `server/terminal-manager.ts` | `node-pty` sessions over the dedicated `/ws/terminal/:id` socket, OSC shell-integration marks. See [`../terminal.md`](../terminal.md). |
261
- | **Code explorer** | `server/code-explorer-router.ts`, `server/file-provenance.ts`, `server/file-summary-manager.ts` | Read-only file tree + Monaco viewer + AI summaries; provenance per ticket/job. |
272
+ | **Code explorer** | `server/code-explorer-router.ts`, `server/file-provenance.ts`, `server/file-summary-manager.ts` | A non-developer-friendly file tree + Monaco viewer with plain-language AI summaries and *touched-by-AI* provenance chips per ticket/job, plus opt-in in-app editing of existing files (overwrite-only via `PUT /file` — no create/rename; refuses binaries `415`, enforces a 2 MB cap `413`, `404` on a missing path, respects deny-list/`.gitignore`). |
262
273
  | **Pipeline telemetry** | `server/telemetry-receiver.ts` + QueueManager OTEL injection | Opt-in OTLP/JSON signals to `POST /otlp/v1/{traces,metrics,logs}`; blobs compacted after 7 days; diagnostic ZIP export. |
263
274
  | **Explore acceleration + Contract Refine** | `server/explore-cwd-manager.ts`, `server/contract-refine-runner.ts` | App-managed Explore spawn cwd for fast first-token; optional post-commit Contract Layer enrichment. Kill switches: `SPECRAILS_EXPLORE_CONTRACT_REFINE`, `SPECRAILS_EXPLORE_LEGACY_CWD`. |
264
275
  | **Tickets / drafts** | `server/ticket-store.ts` | Spec tickets (incl. `draft` status) backing the Specs board and Save-as-Draft flow. |
276
+ | **Jira integration** | `server/jira/*` (`jira-sync-manager`, `jira-client`, `jira-materializer`, `jira-status-resolver`, `jira-db`, `jira-credential-store`), `server/jira-router.ts` | Optional per-project sync that backs a project's specs with a Jira board (Cloud or Data Center). Desktop is the sync layer — specrails-core reads the materialized cache unchanged and stays read-only. Inbound polling + a durable outbox handle write-back; the encrypted token lives on-device. Routes under `/api/projects/:id/jira/*` (gated by `SPECRAILS_JIRA_SECTION`, 404 when off); project-scoped WS events `jira.synced`, `jira.sync_error`, `jira.auth_expired`, `jira.outbox_changed`, `jira.degraded`. See [`../jira-integration-plan.md`](../jira-integration-plan.md). |
265
277
  | **Theme system** | `server/desktop-router.ts` (`GET/PATCH /api/theme`) | Five built-in themes (`dracula`, `aurora-light`, `obsidian-dark`, `matrix`, `specrails`), default `specrails`, persisted app-wide with an anti-FOUC inline script. |
266
278
 
267
279
  Most client feature sections are gated by VITE flags, and they share one polarity: `VITE_FEATURE_TERMINAL_PANEL`, `VITE_FEATURE_AGENTS_SECTION`, `VITE_FEATURE_EXPLORE_PREMIUM_UX`, and `VITE_FEATURE_CODE_EXPLORER` are all **opt-out** — default ON, set the flag to `false` to hide that section. See [`configuration.md`](configuration.md) for the full flag and settings reference.
@@ -273,7 +285,7 @@ Most client feature sections are gated by VITE flags, and they share one polarit
273
285
  When a project is added without specrails-core, the setup wizard runs. The client renders a **3-step** indicator: **Configure → Install → Done**.
274
286
 
275
287
  1. **Configure** — confirm path and pick provider(s) and model presets. (Multi-provider projects get one Configure step per provider.)
276
- 2. **Install** — the app writes `.specrails/install-config.yaml` and runs `npx --yes --prefer-online specrails-core@latest init --yes --from-config <tempPath>`, streaming the log. For multi-provider projects each provider's install runs sequentially.
288
+ 2. **Install** — the app writes `.specrails/install-config.yaml` and runs `npx --yes --prefer-online specrails-core@^4.8.0 init --yes --from-config <tempPath>`, streaming the log. The package spec is the constant `CORE_PACKAGE_SPEC` — a deliberately pinned major range (the floor is `4.8.0`, the release that ships the Gemini provider target), so a future core `5.x` doesn't auto-land. Override the binary locally with `SPECRAILS_CORE_BIN`. For multi-provider projects each provider's install runs sequentially.
277
289
  3. **Done** — per-provider completion summary.
278
290
 
279
291
  `SetupManager` (server) owns wizard state; `DesktopProvider` (client) tracks which projects are in setup via `setupProjectIds`. The wizard does spawn a real AI CLI for the `/setup` chat, but that spawn is deliberately left uninstrumented (it writes no `ai_invocations` row).
@@ -328,5 +340,6 @@ macOS desktop builds are signed + notarized. Windows builds (x64 and arm64) ship
328
340
  - [Configuration](configuration.md) — env vars, feature flags, app/project settings
329
341
  - [Agent profiles](profiles.md) — profile schema, resolution order, snapshot-per-job
330
342
  - [Adding a provider](adding-a-provider.md) — the `ProviderAdapter` contract
343
+ - [Codex](../codex.md) / [Gemini](../gemini.md) — per-provider user guides
331
344
  - [OpenSpec workflow](openspec-workflow.md) — the spec-driven change lifecycle
332
345
  - [Operations runbook](operations-runbook.md) — running, upgrading, and recovering the app