specrails-desktop 2.0.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 (455) hide show
  1. package/.claude/commands/specrails/batch-implement.md +287 -0
  2. package/.claude/commands/specrails/compat-check.md +271 -0
  3. package/.claude/commands/specrails/doctor.md +62 -0
  4. package/.claude/commands/specrails/enrich.md +1635 -0
  5. package/.claude/commands/specrails/explore-spec.md +173 -0
  6. package/.claude/commands/specrails/health-check.md +527 -0
  7. package/.claude/commands/specrails/implement.md +1457 -0
  8. package/.claude/commands/specrails/memory-inspect.md +259 -0
  9. package/.claude/commands/specrails/opsx-diff.md +419 -0
  10. package/.claude/commands/specrails/propose-spec.md +102 -0
  11. package/.claude/commands/specrails/reconfig.md +89 -0
  12. package/.claude/commands/specrails/refactor-recommender.md +212 -0
  13. package/.claude/commands/specrails/retry.md +363 -0
  14. package/.claude/commands/specrails/telemetry.md +552 -0
  15. package/.claude/commands/specrails/why.md +96 -0
  16. package/LICENSE +21 -0
  17. package/README.md +290 -0
  18. package/cli/dist/specrails-desktop.js +1098 -0
  19. package/client/dist/assets/ActivityFeedPage-Gy4x8dBt.js +1 -0
  20. package/client/dist/assets/AgentsPage-CPgu--Fb.js +86 -0
  21. package/client/dist/assets/AnalyticsPage-B5sJEee2.js +1 -0
  22. package/client/dist/assets/BarChart-7IMQ8HY1.js +33 -0
  23. package/client/dist/assets/CodePage-CBdFvbwe.js +2 -0
  24. package/client/dist/assets/DesktopAnalyticsPage-w0rdTq4w.js +1 -0
  25. package/client/dist/assets/DocsDialog-BZUYM7wm.js +11 -0
  26. package/client/dist/assets/DocsPage-9QglWl46.js +11 -0
  27. package/client/dist/assets/ExportDropdown-BLZFXtNi.js +1 -0
  28. package/client/dist/assets/IntegrationsPage-BxBE4y99.js +3 -0
  29. package/client/dist/assets/JobDetailPage-DydWx_5S.js +16 -0
  30. package/client/dist/assets/JobsPage-20ibw0IO.js +1 -0
  31. package/client/dist/assets/abap-Bw6f2wDG.js +1 -0
  32. package/client/dist/assets/activity-BEIp_Y1A.js +1 -0
  33. package/client/dist/assets/activity-BdrPln96.js +1 -0
  34. package/client/dist/assets/activity-CpkRS8Sx.js +1 -0
  35. package/client/dist/assets/activity-DKCpESPt.js +1 -0
  36. package/client/dist/assets/activity-DOUVEjJi.js +1 -0
  37. package/client/dist/assets/activity-DRwkql_y.js +1 -0
  38. package/client/dist/assets/activity-DcDQ7tjw.js +1 -0
  39. package/client/dist/assets/activity-Dv6H7wEr.js +1 -0
  40. package/client/dist/assets/addon-image-3WCl5Vhd.js +1 -0
  41. package/client/dist/assets/addon-ligatures-C5OdliKs.js +2 -0
  42. package/client/dist/assets/addon-webgl-BbX6pSjl.js +44 -0
  43. package/client/dist/assets/addspec-B5yl4Loj.js +1 -0
  44. package/client/dist/assets/addspec-BEeF5-zc.js +1 -0
  45. package/client/dist/assets/addspec-D33ocMxf.js +1 -0
  46. package/client/dist/assets/addspec-DFswZ0jK.js +1 -0
  47. package/client/dist/assets/addspec-DRE-jZv7.js +1 -0
  48. package/client/dist/assets/addspec-DVZ15Jp8.js +1 -0
  49. package/client/dist/assets/addspec-Fkv91Opc.js +1 -0
  50. package/client/dist/assets/addspec-GWm4ffKl.js +1 -0
  51. package/client/dist/assets/agents-1nCDWRmP.js +1 -0
  52. package/client/dist/assets/agents-Bm9rPqnt.js +1 -0
  53. package/client/dist/assets/agents-CMxtJMLD.js +1 -0
  54. package/client/dist/assets/agents-DK-Dlc0i.js +1 -0
  55. package/client/dist/assets/agents-Q6Ldfpxx.js +1 -0
  56. package/client/dist/assets/agents-TeOSy-ax.js +1 -0
  57. package/client/dist/assets/agents-iTqjRajS.js +1 -0
  58. package/client/dist/assets/agents-s87sMGzL.js +1 -0
  59. package/client/dist/assets/agentstudio-B6Wb59E7.js +1 -0
  60. package/client/dist/assets/agentstudio-BADhZ41e.js +1 -0
  61. package/client/dist/assets/agentstudio-BSnWLR63.js +1 -0
  62. package/client/dist/assets/agentstudio-BdidyBzZ.js +1 -0
  63. package/client/dist/assets/agentstudio-CxlUllqI.js +1 -0
  64. package/client/dist/assets/agentstudio-D3I62TLJ.js +1 -0
  65. package/client/dist/assets/agentstudio-DuH9TogZ.js +1 -0
  66. package/client/dist/assets/agentstudio-Kw88_dUF.js +1 -0
  67. package/client/dist/assets/aiedit-BWxHGsYA.js +1 -0
  68. package/client/dist/assets/aiedit-D2ji6Qy0.js +1 -0
  69. package/client/dist/assets/aiedit-DAhZTvtk.js +1 -0
  70. package/client/dist/assets/aiedit-DJMny-D5.js +1 -0
  71. package/client/dist/assets/aiedit-DOcxERkU.js +1 -0
  72. package/client/dist/assets/aiedit-DvrcbwGv.js +1 -0
  73. package/client/dist/assets/aiedit-TTwzL1TS.js +1 -0
  74. package/client/dist/assets/aiedit-WBSjT_C1.js +1 -0
  75. package/client/dist/assets/analytics-BIdr0YfL.js +1 -0
  76. package/client/dist/assets/analytics-C6EzgtdE.js +1 -0
  77. package/client/dist/assets/analytics-C9Zc-rkM.js +1 -0
  78. package/client/dist/assets/analytics-CVx3YOc0.js +1 -0
  79. package/client/dist/assets/analytics-CYj0tfj7.js +1 -0
  80. package/client/dist/assets/analytics-CnY4kNG3.js +1 -0
  81. package/client/dist/assets/analytics-CrPCZRJ-.js +1 -0
  82. package/client/dist/assets/analytics-DMCto-TF.js +1 -0
  83. package/client/dist/assets/apex-Cw8_REBo.js +1 -0
  84. package/client/dist/assets/atom-one-dark-B-oHczHB.css +1 -0
  85. package/client/dist/assets/attachments-BIsSSnHJ.js +1 -0
  86. package/client/dist/assets/attachments-BW4L3l2L.js +1 -0
  87. package/client/dist/assets/attachments-Bcf6BG6V.js +1 -0
  88. package/client/dist/assets/attachments-Bke8sCU4.js +1 -0
  89. package/client/dist/assets/attachments-COcrGRFz.js +1 -0
  90. package/client/dist/assets/attachments-DYHGA2Dj.js +1 -0
  91. package/client/dist/assets/attachments-Dd92KpUH.js +1 -0
  92. package/client/dist/assets/attachments-DzdU6DV6.js +1 -0
  93. package/client/dist/assets/azcli-Cz6HAoOw.js +1 -0
  94. package/client/dist/assets/bat-CcJ-xyqL.js +1 -0
  95. package/client/dist/assets/bicep-z1WDCKYz.js +2 -0
  96. package/client/dist/assets/browser-5ErDlJoR.js +1 -0
  97. package/client/dist/assets/browser-Bc-YdlVg.js +1 -0
  98. package/client/dist/assets/browser-BlYF4OOq.js +1 -0
  99. package/client/dist/assets/browser-CT-ReZGt.js +1 -0
  100. package/client/dist/assets/browser-DGITz3fC.js +1 -0
  101. package/client/dist/assets/browser-JsAIGCEW.js +1 -0
  102. package/client/dist/assets/browser-M5-rbPlw.js +1 -0
  103. package/client/dist/assets/browser-Qya9cARy.js +1 -0
  104. package/client/dist/assets/cameligo-BRewOpfa.js +1 -0
  105. package/client/dist/assets/chat-BEGuC03z.js +1 -0
  106. package/client/dist/assets/chat-BEW60P_u.js +1 -0
  107. package/client/dist/assets/chat-BQNMD0PL.js +1 -0
  108. package/client/dist/assets/chat-BsbNGPW9.js +1 -0
  109. package/client/dist/assets/chat-CboQguCi.js +1 -0
  110. package/client/dist/assets/chat-DRCa9pOt.js +1 -0
  111. package/client/dist/assets/chat-DwUm6W9z.js +1 -0
  112. package/client/dist/assets/chat-yoXwguQu.js +1 -0
  113. package/client/dist/assets/chunk-CilyBKbf.js +1 -0
  114. package/client/dist/assets/clojure-DBjRWN6g.js +1 -0
  115. package/client/dist/assets/clsx-DnqN-uhr.js +1 -0
  116. package/client/dist/assets/code-AL1rVIMb.js +1 -0
  117. package/client/dist/assets/code-C0BKpkht.js +1 -0
  118. package/client/dist/assets/code-C0FTS3ew.js +1 -0
  119. package/client/dist/assets/code-CPcHxzxw.js +1 -0
  120. package/client/dist/assets/code-D3ryDniw.js +1 -0
  121. package/client/dist/assets/code-D3zVVQTj.js +1 -0
  122. package/client/dist/assets/code-PCmfS3dn.js +1 -0
  123. package/client/dist/assets/code-exI0G5Wd.js +1 -0
  124. package/client/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  125. package/client/dist/assets/coffee-Cfk_XHGR.js +1 -0
  126. package/client/dist/assets/commands-B772IyDa.js +1 -0
  127. package/client/dist/assets/commands-BDDp6xFG.js +1 -0
  128. package/client/dist/assets/commands-CJxCry-o.js +1 -0
  129. package/client/dist/assets/commands-CfgY-_of.js +1 -0
  130. package/client/dist/assets/commands-DLrvnPNg.js +1 -0
  131. package/client/dist/assets/commands-IXMOKBYt.js +1 -0
  132. package/client/dist/assets/commands-UD1NzmwX.js +1 -0
  133. package/client/dist/assets/commands-sqrqsxyE.js +1 -0
  134. package/client/dist/assets/common-DCr6VzJ7.js +1 -0
  135. package/client/dist/assets/common-Dard9UNH.js +1 -0
  136. package/client/dist/assets/common-DeDELLZJ.js +1 -0
  137. package/client/dist/assets/common-DltqHaAe.js +1 -0
  138. package/client/dist/assets/common-Dmm1GhdD.js +1 -0
  139. package/client/dist/assets/common-DnjcgkPH.js +1 -0
  140. package/client/dist/assets/common-GbpxfPG8.js +1 -0
  141. package/client/dist/assets/common-wA36jmj1.js +1 -0
  142. package/client/dist/assets/cpp-BVob6BaP.js +1 -0
  143. package/client/dist/assets/csharp-C4fbRuOu.js +1 -0
  144. package/client/dist/assets/csp-DthFP_vT.js +1 -0
  145. package/client/dist/assets/css-CGMH0hcW.js +3 -0
  146. package/client/dist/assets/css.worker-Wv5dxAWO.js +89 -0
  147. package/client/dist/assets/cssMode-Cc6ozl-J.js +1 -0
  148. package/client/dist/assets/cypher-Pnf68BRV.js +1 -0
  149. package/client/dist/assets/dart-PMMOtxZX.js +1 -0
  150. package/client/dist/assets/dashboard-B4ixDVk8.js +1 -0
  151. package/client/dist/assets/dashboard-BZBADHSj.js +1 -0
  152. package/client/dist/assets/dashboard-C1MfeUHs.js +1 -0
  153. package/client/dist/assets/dashboard-C7SK6xu5.js +1 -0
  154. package/client/dist/assets/dashboard-CB6Le1yN.js +1 -0
  155. package/client/dist/assets/dashboard-CoTpMOBM.js +1 -0
  156. package/client/dist/assets/dashboard-Duo4DDCW.js +1 -0
  157. package/client/dist/assets/dashboard-I19DXBxw.js +1 -0
  158. package/client/dist/assets/dist-js-BY-Fv_fg.js +1 -0
  159. package/client/dist/assets/dist-js-Bakc4uxT.js +1 -0
  160. package/client/dist/assets/dockerfile-di1nsJCc.js +1 -0
  161. package/client/dist/assets/ecl-D_WVcB5M.js +1 -0
  162. package/client/dist/assets/editor-Br_kD0ds.css +1 -0
  163. package/client/dist/assets/editor.api2-XLGzZfbc.js +872 -0
  164. package/client/dist/assets/editor.main-CfXxHimg.js +6 -0
  165. package/client/dist/assets/editor.worker-Bd9IXS8d.js +26 -0
  166. package/client/dist/assets/elixir-OAdJEMOn.js +1 -0
  167. package/client/dist/assets/explore-4mFpnrKU.js +1 -0
  168. package/client/dist/assets/explore-A8Ltoblq.js +1 -0
  169. package/client/dist/assets/explore-B9A3iN2W.js +1 -0
  170. package/client/dist/assets/explore-BV5Xxlsn.js +1 -0
  171. package/client/dist/assets/explore-BrBJvfjP.js +1 -0
  172. package/client/dist/assets/explore-C3FSE42C.js +1 -0
  173. package/client/dist/assets/explore-D2EFgt8J.js +1 -0
  174. package/client/dist/assets/explore-hFc3HFcp.js +1 -0
  175. package/client/dist/assets/flow9-D3QEZjgn.js +1 -0
  176. package/client/dist/assets/format-command-CwGuwzGA.js +1 -0
  177. package/client/dist/assets/freemarker2-DP7J1gG3.js +3 -0
  178. package/client/dist/assets/fsharp-BF0k_8N8.js +1 -0
  179. package/client/dist/assets/go-BAQO5Jsz.js +1 -0
  180. package/client/dist/assets/graphql-hdFVFkiV.js +1 -0
  181. package/client/dist/assets/handlebars-BjRlucw6.js +1 -0
  182. package/client/dist/assets/hcl-DWnl1o-X.js +1 -0
  183. package/client/dist/assets/html-OumBQJ-U.js +1 -0
  184. package/client/dist/assets/html.worker-CQP8QQsS.js +502 -0
  185. package/client/dist/assets/htmlMode-CStc3zXM.js +1 -0
  186. package/client/dist/assets/index-CimDRRi7.css +2 -0
  187. package/client/dist/assets/index-XGZaKl_u.js +142 -0
  188. package/client/dist/assets/ini-CB-6OVu3.js +1 -0
  189. package/client/dist/assets/integrations-C3p12Ms6.js +1 -0
  190. package/client/dist/assets/integrations-Cr6hH7XR.js +1 -0
  191. package/client/dist/assets/integrations-Cublz3m6.js +1 -0
  192. package/client/dist/assets/integrations-D28q1kF6.js +1 -0
  193. package/client/dist/assets/integrations-DRdbki5W.js +1 -0
  194. package/client/dist/assets/integrations-DaC4SzzL.js +1 -0
  195. package/client/dist/assets/integrations-DmQYCUvN.js +1 -0
  196. package/client/dist/assets/integrations-HIlUxXVs.js +1 -0
  197. package/client/dist/assets/java-d1CmfiHX.js +1 -0
  198. package/client/dist/assets/javascript-CMk--e7g.js +1 -0
  199. package/client/dist/assets/jobs-BE1siB0M.js +1 -0
  200. package/client/dist/assets/jobs-BHcQ_Faf.js +1 -0
  201. package/client/dist/assets/jobs-CFfc2dNX.js +1 -0
  202. package/client/dist/assets/jobs-CSi5n8X_.js +1 -0
  203. package/client/dist/assets/jobs-Dc3X86PY.js +1 -0
  204. package/client/dist/assets/jobs-De5tASex.js +1 -0
  205. package/client/dist/assets/jobs-DsoXEdo7.js +1 -0
  206. package/client/dist/assets/jobs-Wl-ApPMb.js +1 -0
  207. package/client/dist/assets/json.worker-DzV-CpCQ.js +58 -0
  208. package/client/dist/assets/jsonMode-C2h3ZcjZ.js +7 -0
  209. package/client/dist/assets/julia-Bgv08lKa.js +1 -0
  210. package/client/dist/assets/kotlin-u98kaVTf.js +1 -0
  211. package/client/dist/assets/less-CjYwpgg5.js +2 -0
  212. package/client/dist/assets/lexon-YTjaAFBB.js +1 -0
  213. package/client/dist/assets/lib-CPxTMOAq.js +7 -0
  214. package/client/dist/assets/liquid-mI3KJrBE.js +1 -0
  215. package/client/dist/assets/lspLanguageFeatures-DU09ggWi.js +4 -0
  216. package/client/dist/assets/lua-BzmkWv27.js +1 -0
  217. package/client/dist/assets/m3-CFwk9fw0.js +1 -0
  218. package/client/dist/assets/markdown-CR5iMpSZ.js +1 -0
  219. package/client/dist/assets/mdx-C41VDTR_.js +1 -0
  220. package/client/dist/assets/mips-CcEalc17.js +1 -0
  221. package/client/dist/assets/monaco.contribution-CPObAXMC.js +2 -0
  222. package/client/dist/assets/msdax-BQbkawnr.js +1 -0
  223. package/client/dist/assets/mysql-GTlaaW_P.js +1 -0
  224. package/client/dist/assets/nav-0fwkrgHt.js +1 -0
  225. package/client/dist/assets/nav-BEL3MTwK.js +1 -0
  226. package/client/dist/assets/nav-B_G-TJDW.js +1 -0
  227. package/client/dist/assets/nav-C2YXcbZS.js +1 -0
  228. package/client/dist/assets/nav-ClzOE4mA.js +1 -0
  229. package/client/dist/assets/nav-CtYwmMgu.js +1 -0
  230. package/client/dist/assets/nav-D2bOGSEg.js +1 -0
  231. package/client/dist/assets/nav-iH1V5j6o.js +1 -0
  232. package/client/dist/assets/objective-c-Byu1T5if.js +1 -0
  233. package/client/dist/assets/pascal-BrfzBfRm.js +1 -0
  234. package/client/dist/assets/pascaligo-BXXKFUeo.js +1 -0
  235. package/client/dist/assets/perl-B3OikKq-.js +1 -0
  236. package/client/dist/assets/pgsql-CTsa0Acc.js +1 -0
  237. package/client/dist/assets/php-DiQh3FUW.js +1 -0
  238. package/client/dist/assets/pla-92uH8Fzm.js +1 -0
  239. package/client/dist/assets/postiats-BbeWkKUr.js +1 -0
  240. package/client/dist/assets/powerquery-DgDMzpsm.js +1 -0
  241. package/client/dist/assets/powershell-BfdUUzaG.js +1 -0
  242. package/client/dist/assets/preload-helper-DSXbuxSR.js +1 -0
  243. package/client/dist/assets/protobuf-BojW2ftW.js +2 -0
  244. package/client/dist/assets/pug-BxqTg3IU.js +1 -0
  245. package/client/dist/assets/python-Y27rKQtk.js +1 -0
  246. package/client/dist/assets/qsharp-BX_A-MW9.js +1 -0
  247. package/client/dist/assets/r-D9BMnxvJ.js +1 -0
  248. package/client/dist/assets/razor-Cd5-q9Bp.js +1 -0
  249. package/client/dist/assets/redis-5cJqEQJJ.js +1 -0
  250. package/client/dist/assets/redshift-d8BBqiwb.js +1 -0
  251. package/client/dist/assets/restructuredtext-C8a6yIcZ.js +1 -0
  252. package/client/dist/assets/ruby-egeh-6KX.js +1 -0
  253. package/client/dist/assets/rust-a3r9IInB.js +1 -0
  254. package/client/dist/assets/sb-y8iRIDei.js +1 -0
  255. package/client/dist/assets/scala-BPDK2AmK.js +1 -0
  256. package/client/dist/assets/scheme-BIWUEoOs.js +1 -0
  257. package/client/dist/assets/scss-CA-PSzwg.js +3 -0
  258. package/client/dist/assets/settings-55oDcbSh.js +1 -0
  259. package/client/dist/assets/settings-Bd4Tq1RB.js +1 -0
  260. package/client/dist/assets/settings-CCSM-Fhn.js +1 -0
  261. package/client/dist/assets/settings-D3e_bDoW.js +1 -0
  262. package/client/dist/assets/settings-DKbTkbn7.js +1 -0
  263. package/client/dist/assets/settings-Dxpo6_w7.js +1 -0
  264. package/client/dist/assets/settings-bt84e3Aa.js +1 -0
  265. package/client/dist/assets/settings-nu68QukM.js +1 -0
  266. package/client/dist/assets/setup-BMqwfbW9.js +1 -0
  267. package/client/dist/assets/setup-Bb5LcG28.js +1 -0
  268. package/client/dist/assets/setup-BeEx2_da.js +1 -0
  269. package/client/dist/assets/setup-CCCrB53Q.js +1 -0
  270. package/client/dist/assets/setup-CJA0ATmd.js +1 -0
  271. package/client/dist/assets/setup-CeiDbZcb.js +1 -0
  272. package/client/dist/assets/setup-Cus7TApA.js +1 -0
  273. package/client/dist/assets/setup-D9qOs2Xo.js +1 -0
  274. package/client/dist/assets/shell--LiT1Bja.js +1 -0
  275. package/client/dist/assets/solidity-DdqZccZg.js +1 -0
  276. package/client/dist/assets/sophia-S6-YxNG_.js +1 -0
  277. package/client/dist/assets/sparql-BSf5kMp2.js +1 -0
  278. package/client/dist/assets/specs-BFfu3u-a.js +1 -0
  279. package/client/dist/assets/specs-B__C8-8a.js +1 -0
  280. package/client/dist/assets/specs-CZ1PsXsC.js +1 -0
  281. package/client/dist/assets/specs-D2FzlLn9.js +1 -0
  282. package/client/dist/assets/specs-DaUTrNF9.js +1 -0
  283. package/client/dist/assets/specs-Dyc5hYeE.js +1 -0
  284. package/client/dist/assets/specs-cKEh2LXt.js +1 -0
  285. package/client/dist/assets/specs-k0PyLDVt.js +1 -0
  286. package/client/dist/assets/sql-D7KgjR8G.js +1 -0
  287. package/client/dist/assets/st-BnoDa-Ml.js +1 -0
  288. package/client/dist/assets/swift-DEUHTkUX.js +1 -0
  289. package/client/dist/assets/systemverilog-Tqb_KPnW.js +1 -0
  290. package/client/dist/assets/tcl-BmBFS2qq.js +1 -0
  291. package/client/dist/assets/terminal-80yDMgMF.js +1 -0
  292. package/client/dist/assets/terminal-Bje4ziIa.js +1 -0
  293. package/client/dist/assets/terminal-C2WYcFHF.js +1 -0
  294. package/client/dist/assets/terminal-CSONJOex.js +1 -0
  295. package/client/dist/assets/terminal-DEqzGtcr.js +1 -0
  296. package/client/dist/assets/terminal-DeWzh6ys.js +1 -0
  297. package/client/dist/assets/terminal-YOlsJCQj.js +1 -0
  298. package/client/dist/assets/terminal-lkZYR4wJ.js +1 -0
  299. package/client/dist/assets/tickets-CB7N30gm.js +1 -0
  300. package/client/dist/assets/tickets-CF2PYelu.js +1 -0
  301. package/client/dist/assets/tickets-DNOANUXr.js +1 -0
  302. package/client/dist/assets/tickets-DU1aqsbr.js +1 -0
  303. package/client/dist/assets/tickets-DYvafSaY.js +1 -0
  304. package/client/dist/assets/tickets-DlpC_iTg.js +1 -0
  305. package/client/dist/assets/tickets-DucYgtdl.js +1 -0
  306. package/client/dist/assets/tickets-clefmXLv.js +1 -0
  307. package/client/dist/assets/ts.worker-METxwbDZ.js +67719 -0
  308. package/client/dist/assets/tsMode-B0y_xEci.js +11 -0
  309. package/client/dist/assets/twig-BQV8igWC.js +1 -0
  310. package/client/dist/assets/typescript-BzK0OgwW.js +1 -0
  311. package/client/dist/assets/typespec-DlFroUGY.js +1 -0
  312. package/client/dist/assets/useProjectCache-DSaiGFjV.js +1 -0
  313. package/client/dist/assets/vb-BlrJpIMX.js +1 -0
  314. package/client/dist/assets/wgsl-BWgIc6FZ.js +298 -0
  315. package/client/dist/assets/workers-rt--R2Qy.js +1 -0
  316. package/client/dist/assets/xml-eX9QXAmI.js +1 -0
  317. package/client/dist/assets/yaml-fcsNkpOt.js +1 -0
  318. package/client/dist/index.html +246 -0
  319. package/docs/README.md +54 -0
  320. package/docs/cli.md +198 -0
  321. package/docs/codex.md +210 -0
  322. package/docs/creating-specs.md +197 -0
  323. package/docs/customizing.md +197 -0
  324. package/docs/getting-started.md +140 -0
  325. package/docs/internals/README.md +25 -0
  326. package/docs/internals/adding-a-provider.md +238 -0
  327. package/docs/internals/api-reference.md +634 -0
  328. package/docs/internals/architecture.md +332 -0
  329. package/docs/internals/configuration.md +172 -0
  330. package/docs/internals/openspec-workflow.md +282 -0
  331. package/docs/internals/operations-runbook.md +198 -0
  332. package/docs/internals/profiles.md +152 -0
  333. package/docs/platforms/macos.md +130 -0
  334. package/docs/platforms/windows.md +81 -0
  335. package/docs/running-pipelines.md +240 -0
  336. package/docs/terminal.md +138 -0
  337. package/docs/tracking-cost.md +155 -0
  338. package/package.json +82 -0
  339. package/server/dist/agent-generator.js +232 -0
  340. package/server/dist/agent-refine-db.js +124 -0
  341. package/server/dist/agent-refine-manager.js +526 -0
  342. package/server/dist/ai-invocations.js +111 -0
  343. package/server/dist/attachment-manager.js +299 -0
  344. package/server/dist/auth.js +207 -0
  345. package/server/dist/binary-probe.js +35 -0
  346. package/server/dist/browser-capture-manager.js +576 -0
  347. package/server/dist/browser-capture-types.js +28 -0
  348. package/server/dist/browser-network.js +149 -0
  349. package/server/dist/browser-playwright.js +888 -0
  350. package/server/dist/build-dirs.js +44 -0
  351. package/server/dist/changes-reader.js +120 -0
  352. package/server/dist/chat-manager.js +1060 -0
  353. package/server/dist/chromium-resolver.js +311 -0
  354. package/server/dist/code-explorer-router.js +788 -0
  355. package/server/dist/codex-otel-bridge.js +235 -0
  356. package/server/dist/command-resolver.js +102 -0
  357. package/server/dist/config.js +306 -0
  358. package/server/dist/context-budget.js +113 -0
  359. package/server/dist/context-scope.js +279 -0
  360. package/server/dist/contract-refine-runner.js +521 -0
  361. package/server/dist/core-compat.js +207 -0
  362. package/server/dist/core-package.js +14 -0
  363. package/server/dist/db.js +1034 -0
  364. package/server/dist/desktop-analytics.js +156 -0
  365. package/server/dist/desktop-db.js +456 -0
  366. package/server/dist/desktop-router.js +735 -0
  367. package/server/dist/docs-router.js +207 -0
  368. package/server/dist/explore-contract-refine.js +421 -0
  369. package/server/dist/explore-cwd-manager.js +242 -0
  370. package/server/dist/explore-draft-title.js +47 -0
  371. package/server/dist/explore-smash.js +450 -0
  372. package/server/dist/feature-flags.js +17 -0
  373. package/server/dist/file-provenance.js +382 -0
  374. package/server/dist/file-summary-generator.js +221 -0
  375. package/server/dist/file-summary-manager.js +689 -0
  376. package/server/dist/hooks.js +102 -0
  377. package/server/dist/ids.js +7 -0
  378. package/server/dist/index.js +586 -0
  379. package/server/dist/metrics.js +136 -0
  380. package/server/dist/mobile/index.js +16 -0
  381. package/server/dist/mobile/mobile-admin-router.js +84 -0
  382. package/server/dist/mobile/mobile-auth.js +67 -0
  383. package/server/dist/mobile/mobile-devices.js +80 -0
  384. package/server/dist/mobile/mobile-event-bus.js +39 -0
  385. package/server/dist/mobile/mobile-gateway.js +285 -0
  386. package/server/dist/mobile/mobile-mdns.js +81 -0
  387. package/server/dist/mobile/mobile-pairing.js +179 -0
  388. package/server/dist/mobile/mobile-redact.js +53 -0
  389. package/server/dist/mobile/mobile-router.js +411 -0
  390. package/server/dist/mobile/mobile-tls.js +86 -0
  391. package/server/dist/mobile/mobile-types.js +9 -0
  392. package/server/dist/mobile/mobile-ws.js +275 -0
  393. package/server/dist/path-resolver.js +298 -0
  394. package/server/dist/plugin-manager.js +617 -0
  395. package/server/dist/plugins/claude-approval.js +179 -0
  396. package/server/dist/plugins/claude-md-mutation.js +146 -0
  397. package/server/dist/plugins/codex-mcp.js +108 -0
  398. package/server/dist/plugins/contributors.js +72 -0
  399. package/server/dist/plugins/drift.js +58 -0
  400. package/server/dist/plugins/index.js +14 -0
  401. package/server/dist/plugins/json-mutation.js +120 -0
  402. package/server/dist/plugins/manager.js +32 -0
  403. package/server/dist/plugins/ownership.js +86 -0
  404. package/server/dist/plugins/paths.js +37 -0
  405. package/server/dist/plugins/prereq-installer.js +104 -0
  406. package/server/dist/plugins/rail-integration.js +79 -0
  407. package/server/dist/plugins/serena/index.js +13 -0
  408. package/server/dist/plugins/serena/install.js +91 -0
  409. package/server/dist/plugins/serena/instructions-content.js +21 -0
  410. package/server/dist/plugins/serena/manifest.js +111 -0
  411. package/server/dist/plugins/serena/verify.js +78 -0
  412. package/server/dist/plugins-router.js +215 -0
  413. package/server/dist/pricing.js +89 -0
  414. package/server/dist/profile-manager.js +310 -0
  415. package/server/dist/profiles-router.js +759 -0
  416. package/server/dist/project-registry.js +443 -0
  417. package/server/dist/project-router.js +4016 -0
  418. package/server/dist/proposal-manager.js +291 -0
  419. package/server/dist/provider-selection.js +69 -0
  420. package/server/dist/providers/claude-adapter.js +281 -0
  421. package/server/dist/providers/codex-adapter.js +264 -0
  422. package/server/dist/providers/index.js +23 -0
  423. package/server/dist/providers/registry.js +37 -0
  424. package/server/dist/providers/types.js +22 -0
  425. package/server/dist/queue-manager.js +1511 -0
  426. package/server/dist/rails-router.js +362 -0
  427. package/server/dist/rails-store.js +116 -0
  428. package/server/dist/result-event.js +106 -0
  429. package/server/dist/schemas/profile.v1.json +151 -0
  430. package/server/dist/setup-manager.js +1165 -0
  431. package/server/dist/setup-prerequisites.js +372 -0
  432. package/server/dist/smash-runner.js +663 -0
  433. package/server/dist/spec-draft-parser.js +133 -0
  434. package/server/dist/spec-launcher-manager.js +174 -0
  435. package/server/dist/spec-models.js +32 -0
  436. package/server/dist/specrails-tech-client.js +82 -0
  437. package/server/dist/spending.js +448 -0
  438. package/server/dist/telemetry-compactor.js +180 -0
  439. package/server/dist/telemetry-export.js +317 -0
  440. package/server/dist/telemetry-receiver.js +224 -0
  441. package/server/dist/terminal-manager.js +633 -0
  442. package/server/dist/terminal-marks-store.js +117 -0
  443. package/server/dist/terminal-osc-parser.js +159 -0
  444. package/server/dist/terminal-settings.js +282 -0
  445. package/server/dist/terminal-shell-integration.js +196 -0
  446. package/server/dist/ticket-broadcast.js +47 -0
  447. package/server/dist/ticket-store.js +397 -0
  448. package/server/dist/ticket-watcher.js +117 -0
  449. package/server/dist/types.js +10 -0
  450. package/server/dist/user-mcp-config.js +117 -0
  451. package/server/dist/util/cli-prompt.js +181 -0
  452. package/server/dist/util/secure-fs.js +50 -0
  453. package/server/dist/util/win-spawn.js +43 -0
  454. package/server/dist/webhook-manager.js +89 -0
  455. package/server/dist/ws-routing.js +47 -0
@@ -0,0 +1,443 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ProjectRegistry = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const os_1 = __importDefault(require("os"));
10
+ const db_1 = require("./db");
11
+ const queue_manager_1 = require("./queue-manager");
12
+ const chat_manager_1 = require("./chat-manager");
13
+ const setup_manager_1 = require("./setup-manager");
14
+ const proposal_manager_1 = require("./proposal-manager");
15
+ const agent_refine_manager_1 = require("./agent-refine-manager");
16
+ const file_summary_manager_1 = require("./file-summary-manager");
17
+ const file_summary_generator_1 = require("./file-summary-generator");
18
+ const providers_1 = require("./providers");
19
+ const agent_refine_db_1 = require("./agent-refine-db");
20
+ const spec_launcher_manager_1 = require("./spec-launcher-manager");
21
+ const webhook_manager_1 = require("./webhook-manager");
22
+ const ticket_watcher_1 = require("./ticket-watcher");
23
+ const terminal_manager_1 = require("./terminal-manager");
24
+ const browser_capture_manager_1 = require("./browser-capture-manager");
25
+ const explore_cwd_manager_1 = require("./explore-cwd-manager");
26
+ const ticket_store_1 = require("./ticket-store");
27
+ const rails_store_1 = require("./rails-store");
28
+ const desktop_db_1 = require("./desktop-db");
29
+ const config_1 = require("./config");
30
+ // ─── ProjectRegistry ──────────────────────────────────────────────────────────
31
+ class ProjectRegistry {
32
+ _desktopDb;
33
+ _contexts;
34
+ _broadcast;
35
+ _webhookManager;
36
+ _desktopPort;
37
+ // M9: projects whose per-project DB failed to load at startup (corrupt, locked,
38
+ // or migration-stuck). They stay registered but have no live context.
39
+ _failedProjects;
40
+ constructor(broadcast, desktopDbPath, desktopPort) {
41
+ this._broadcast = broadcast;
42
+ this._desktopDb = (0, desktop_db_1.initDesktopDb)(desktopDbPath ?? (0, desktop_db_1.getDesktopDbPath)());
43
+ this._contexts = new Map();
44
+ this._webhookManager = new webhook_manager_1.WebhookManager(this._desktopDb);
45
+ this._desktopPort = desktopPort ?? 4200;
46
+ this._failedProjects = new Map();
47
+ }
48
+ get desktopDb() {
49
+ return this._desktopDb;
50
+ }
51
+ loadAll() {
52
+ const projects = (0, desktop_db_1.listProjects)(this._desktopDb);
53
+ for (const project of projects) {
54
+ try {
55
+ this._loadProjectContext(project);
56
+ this._failedProjects.delete(project.id);
57
+ }
58
+ catch (err) {
59
+ // M9: a single corrupt / locked / migration-stuck per-project jobs.sqlite
60
+ // must NOT crash the whole app at startup (previously it did, killing
61
+ // every other project + the UI in a restart loop). Log it, record it as
62
+ // failed-to-load, and keep loading the rest.
63
+ const msg = err instanceof Error ? err.message : String(err);
64
+ console.error(`[project-registry] failed to load project ${project.id} (${project.slug}): ${msg}`);
65
+ this._failedProjects.set(project.id, { project, error: msg });
66
+ }
67
+ }
68
+ }
69
+ /** Projects whose per-project DB failed to load at startup (M9). */
70
+ listFailedProjects() {
71
+ return Array.from(this._failedProjects.values());
72
+ }
73
+ addProject(opts) {
74
+ const row = (0, desktop_db_1.addProject)(this._desktopDb, opts);
75
+ return this._loadProjectContext(row);
76
+ }
77
+ removeProject(id) {
78
+ const ctx = this._contexts.get(id);
79
+ if (ctx) {
80
+ // Tear down spawners BEFORE closing the DB. QueueManager.shutdown() drops
81
+ // its DB handle so a late child 'close' can't run prepared statements on
82
+ // the closed connection (which would crash the app) and terminates any
83
+ // orphaned rail child + dangling zombie timer. ChatManager.shutdown()
84
+ // kills in-flight chat/Explore children and clears their idle timers.
85
+ // SetupManager.abort() stops the 3s install poll and kills install/enrich
86
+ // children. All are idempotent no-ops when nothing is running.
87
+ try {
88
+ ctx.queueManager.shutdown();
89
+ }
90
+ catch { /* ignore */ }
91
+ try {
92
+ ctx.chatManager.shutdown();
93
+ }
94
+ catch { /* ignore */ }
95
+ try {
96
+ ctx.setupManager.abort(id);
97
+ }
98
+ catch { /* ignore */ }
99
+ // M12: these three also spawn children that outlive removeProject. Proposal
100
+ // and AgentRefine write to the per-project DB in their close handlers — if
101
+ // not disposed before db.close() they throw on the closed connection and
102
+ // (no uncaughtException handler) crash the entire app. SpecLauncher has no
103
+ // DB but its --dangerously-skip-permissions child keeps burning spend.
104
+ try {
105
+ ctx.proposalManager.shutdown();
106
+ }
107
+ catch { /* ignore */ }
108
+ try {
109
+ ctx.agentRefineManager.shutdown();
110
+ }
111
+ catch { /* ignore */ }
112
+ try {
113
+ ctx.specLauncherManager.shutdown();
114
+ }
115
+ catch { /* ignore */ }
116
+ // Tear down the embedded browser (closes pages + persistent context).
117
+ void ctx.browserCaptureManager.shutdown().catch(() => { });
118
+ // Kill any terminal sessions belonging to this project
119
+ try {
120
+ (0, terminal_manager_1.getTerminalManager)().killAllForProject(id);
121
+ }
122
+ catch { /* ignore */ }
123
+ // Close the ticket file watcher
124
+ ctx.ticketWatcher.close().catch(() => { });
125
+ // Tear down the code-explorer summary manager: aborts any in-flight
126
+ // provider child, rejects queued work, and detaches the watcher — BEFORE
127
+ // db.close() so a completing generation can't write to the closed handle.
128
+ try {
129
+ ctx.fileSummaryManager.dispose();
130
+ }
131
+ catch { /* ignore */ }
132
+ // Drop the app-managed Explore Spec cwd (CLAUDE.md + symlink to project)
133
+ try {
134
+ (0, explore_cwd_manager_1.removeExploreCwd)(ctx.project.slug);
135
+ }
136
+ catch { /* ignore — non-fatal */ }
137
+ // Close the DB connection BEFORE removing the project's data dir below.
138
+ try {
139
+ ctx.db.close();
140
+ }
141
+ catch { /* ignore */ }
142
+ // B54: remove the ENTIRE app-managed data dir for this project, not just
143
+ // the telemetry subdir. It also holds user-mcp.json (a copy of the user's
144
+ // MCP config that can contain API keys), profile snapshots, codex-home, and
145
+ // terminal shim dirs — all secret-bearing residue that previously survived
146
+ // project removal. Guard on a non-empty slug so we never rm the projects/
147
+ // root itself.
148
+ try {
149
+ const slug = ctx.project.slug;
150
+ if (slug && slug.trim() && !slug.includes('/') && !slug.includes('..')) {
151
+ const projectDir = path_1.default.join(os_1.default.homedir(), '.specrails', 'projects', slug);
152
+ if (fs_1.default.existsSync(projectDir)) {
153
+ fs_1.default.rmSync(projectDir, { recursive: true, force: true });
154
+ }
155
+ }
156
+ }
157
+ catch { /* ignore — non-fatal */ }
158
+ this._contexts.delete(id);
159
+ }
160
+ (0, desktop_db_1.removeProject)(this._desktopDb, id);
161
+ }
162
+ getContext(id) {
163
+ return this._contexts.get(id);
164
+ }
165
+ getContextByPath(projectPath) {
166
+ const row = (0, desktop_db_1.getProjectByPath)(this._desktopDb, projectPath);
167
+ if (!row)
168
+ return undefined;
169
+ return this._contexts.get(row.id);
170
+ }
171
+ listContexts() {
172
+ return Array.from(this._contexts.values());
173
+ }
174
+ /**
175
+ * Graceful process-level teardown: terminate every project's active rail and
176
+ * chat children so SIGTERM/SIGINT (or desktop parent-death) does not leave
177
+ * orphaned claude/codex processes reparented to init. Best-effort per project
178
+ * — one failure never blocks the rest. Does NOT close DBs (the process is
179
+ * exiting anyway).
180
+ */
181
+ shutdown() {
182
+ for (const ctx of this._contexts.values()) {
183
+ try {
184
+ ctx.queueManager.shutdown();
185
+ }
186
+ catch { /* ignore */ }
187
+ try {
188
+ ctx.chatManager.shutdown();
189
+ }
190
+ catch { /* ignore */ }
191
+ try {
192
+ ctx.proposalManager.shutdown();
193
+ }
194
+ catch { /* ignore */ }
195
+ try {
196
+ ctx.agentRefineManager.shutdown();
197
+ }
198
+ catch { /* ignore */ }
199
+ try {
200
+ ctx.specLauncherManager.shutdown();
201
+ }
202
+ catch { /* ignore */ }
203
+ void ctx.browserCaptureManager.shutdown().catch(() => { });
204
+ // Release chokidar watchers + abort in-flight generations so a restart
205
+ // does not leak handles/children — mirror removeProject()'s per-project teardown.
206
+ try {
207
+ ctx.fileSummaryManager.dispose();
208
+ }
209
+ catch { /* ignore */ }
210
+ ctx.ticketWatcher.close().catch(() => { });
211
+ }
212
+ }
213
+ touchProject(id) {
214
+ (0, desktop_db_1.touchProject)(this._desktopDb, id);
215
+ }
216
+ getProjectRow(id) {
217
+ return (0, desktop_db_1.getProject)(this._desktopDb, id);
218
+ }
219
+ _loadProjectContext(project) {
220
+ // Avoid double-loading
221
+ const existing = this._contexts.get(project.id);
222
+ if (existing)
223
+ return existing;
224
+ const db = (0, db_1.initDb)(project.db_path);
225
+ // Bind broadcast with projectId so all WS messages carry context.
226
+ // Also wire agent status: when a queued job reaches a terminal state,
227
+ // clear current_job_id on any agent that was assigned to it.
228
+ const TERMINAL_JOB_STATUSES = new Set(['completed', 'failed', 'canceled']);
229
+ const boundBroadcast = (msg) => {
230
+ const enriched = { ...msg, projectId: project.id };
231
+ this._broadcast(enriched);
232
+ if (msg.type === 'queue') {
233
+ for (const job of msg.jobs) {
234
+ if (TERMINAL_JOB_STATUSES.has(job.status)) {
235
+ (0, desktop_db_1.clearAgentJob)(this._desktopDb, job.id);
236
+ }
237
+ }
238
+ }
239
+ };
240
+ // Per-project zombie timeout (stored in queue_state)
241
+ let projectZombieTimeout;
242
+ try {
243
+ const row = db.prepare(`SELECT value FROM queue_state WHERE key = 'config.zombie_timeout_ms'`).get();
244
+ if (row) {
245
+ const parsed = parseInt(row.value, 10);
246
+ if (!isNaN(parsed) && parsed > 0)
247
+ projectZombieTimeout = parsed;
248
+ }
249
+ }
250
+ catch { /* queue_state table may not exist yet */ }
251
+ const webhookManager = this._webhookManager;
252
+ const railJobs = new Map();
253
+ const queueManager = new queue_manager_1.QueueManager(boundBroadcast, db, undefined, project.path, {
254
+ zombieTimeoutMs: projectZombieTimeout,
255
+ provider: project.provider ?? 'claude',
256
+ projectId: project.id,
257
+ projectSlug: project.slug,
258
+ desktopPort: this._desktopPort,
259
+ getCostAlertThreshold: () => {
260
+ const val = (0, desktop_db_1.getDesktopSetting)(this._desktopDb, 'cost_alert_threshold_usd');
261
+ return val != null ? parseFloat(val) : null;
262
+ },
263
+ getDesktopDailyBudget: () => {
264
+ const val = (0, desktop_db_1.getDesktopSetting)(this._desktopDb, 'desktop_daily_budget_usd');
265
+ const budget = val != null ? parseFloat(val) : null;
266
+ let totalSpend = 0;
267
+ for (const c of this.listContexts()) {
268
+ const row = c.db.prepare(`SELECT COALESCE(SUM(total_cost_usd), 0) as total FROM jobs WHERE status = 'completed' AND total_cost_usd IS NOT NULL AND started_at >= date('now')`).get();
269
+ totalSpend += row.total;
270
+ }
271
+ return { budget, totalSpend };
272
+ },
273
+ onJobFinished: (jobId, status, costUsd) => {
274
+ const jobRow = db.prepare('SELECT command, duration_ms FROM jobs WHERE id = ?').get(jobId);
275
+ const event = status === 'completed' ? 'job.completed' : status === 'canceled' ? 'job.canceled' : 'job.failed';
276
+ webhookManager.deliver(project.id, event, {
277
+ jobId,
278
+ command: jobRow?.command ?? '',
279
+ status,
280
+ costUsd: costUsd ?? null,
281
+ durationMs: jobRow?.duration_ms ?? null,
282
+ });
283
+ // Broadcast rail.job_completed if this job was launched by a rail
284
+ const railMeta = railJobs.get(jobId);
285
+ if (railMeta) {
286
+ railJobs.delete(jobId);
287
+ }
288
+ // Determine ticket IDs: from rail metadata, or parse from command as fallback
289
+ // (railJobs Map is in-memory and lost on server restart)
290
+ let completedTicketIds = railMeta?.ticketIds ?? [];
291
+ if (completedTicketIds.length === 0 && jobRow?.command) {
292
+ const matches = jobRow.command.match(/#(\d+)/g);
293
+ if (matches)
294
+ completedTicketIds = matches.map((m) => parseInt(m.slice(1), 10));
295
+ }
296
+ // Apply the job outcome to its tickets. Success promotes todo/in_progress
297
+ // → done (→ Specs Done); failure/cancel/zombie reverts in_progress → todo
298
+ // (→ Specs) or flags an already-done spec for review. zombie_terminated is
299
+ // treated as a failure here (and is included in the _onJobExit callback
300
+ // guard) so a timed-out rail releases its specs instead of stranding them.
301
+ if (completedTicketIds.length > 0 &&
302
+ (status === 'completed' || status === 'failed' || status === 'canceled' || status === 'zombie_terminated')) {
303
+ try {
304
+ const ticketFile = (0, ticket_store_1.resolveTicketStoragePath)(project.path);
305
+ const now = new Date().toISOString();
306
+ let changedIds = [];
307
+ const store = (0, ticket_store_1.mutateStore)(ticketFile, (s) => {
308
+ changedIds = (0, ticket_store_1.applyJobOutcomeToTickets)(s, completedTicketIds, status, now);
309
+ });
310
+ for (const tid of changedIds) {
311
+ const ticket = store.tickets[String(tid)];
312
+ if (!ticket)
313
+ continue;
314
+ boundBroadcast({
315
+ type: 'ticket_updated',
316
+ ticket: ticket,
317
+ projectId: project.id,
318
+ timestamp: ticket.updated_at,
319
+ });
320
+ }
321
+ }
322
+ catch (err) {
323
+ console.error('[project-registry] failed to apply job outcome to tickets:', err);
324
+ }
325
+ }
326
+ // Release the job's tickets from any rail that still holds them. The
327
+ // server `rails` table is the source of truth for mobile clients (the
328
+ // desktop strips its localStorage copy on rail.job_completed) — without
329
+ // this, a finished spec stays stranded on the rail forever. Runs on
330
+ // every terminal outcome, mirroring the desktop: success → spec is
331
+ // done; failure/cancel/zombie → spec returns to the board. Scans ALL
332
+ // rails (not just railMeta.railIndex) so it also heals after a server
333
+ // restart, when the in-memory railJobs map is lost.
334
+ if (completedTicketIds.length > 0 &&
335
+ (status === 'completed' || status === 'failed' || status === 'canceled' || status === 'zombie_terminated')) {
336
+ try {
337
+ for (const rail of (0, rails_store_1.getRails)(db)) {
338
+ const remaining = rail.ticketIds.filter((id) => !completedTicketIds.includes(id));
339
+ if (remaining.length === rail.ticketIds.length)
340
+ continue;
341
+ (0, rails_store_1.setRailTickets)(db, rail.railIndex, remaining, rail.mode, rail.profileName, rail.aiEngine);
342
+ boundBroadcast({
343
+ type: 'rail.updated',
344
+ projectId: project.id,
345
+ railIndex: rail.railIndex,
346
+ changed: 'tickets',
347
+ ticketIds: remaining,
348
+ name: rail.name ?? null,
349
+ mode: rail.mode,
350
+ profileName: rail.profileName ?? null,
351
+ aiEngine: rail.aiEngine ?? null,
352
+ });
353
+ }
354
+ }
355
+ catch (err) {
356
+ console.error('[project-registry] failed to release rail tickets after job exit:', err);
357
+ }
358
+ }
359
+ // Broadcast rail.job_completed if we know the rail index
360
+ if (railMeta) {
361
+ boundBroadcast({
362
+ type: 'rail.job_completed',
363
+ projectId: project.id,
364
+ railIndex: railMeta.railIndex,
365
+ jobId,
366
+ status,
367
+ ticketIds: completedTicketIds,
368
+ });
369
+ }
370
+ },
371
+ });
372
+ const chatManager = new chat_manager_1.ChatManager(boundBroadcast, db, project.path, project.name, project.provider ?? 'claude', project.id, project.slug);
373
+ const setupManager = new setup_manager_1.SetupManager(boundBroadcast, (pid, sid) => (0, desktop_db_1.setProjectSetupSession)(this._desktopDb, pid, sid), (pid) => (0, desktop_db_1.clearProjectSetupSession)(this._desktopDb, pid));
374
+ const proposalManager = new proposal_manager_1.ProposalManager(boundBroadcast, db, project.path);
375
+ const agentRefineManager = new agent_refine_manager_1.AgentRefineManager(boundBroadcast, db, project.path, project.id, project.provider ?? 'claude');
376
+ // Retention prune: drop stale/abandoned refine sessions on project load.
377
+ try {
378
+ (0, agent_refine_db_1.pruneStaleRefineSessions)(db);
379
+ }
380
+ catch (err) {
381
+ console.error('[project-registry] prune refine sessions failed:', err);
382
+ }
383
+ const specLauncherManager = new spec_launcher_manager_1.SpecLauncherManager(boundBroadcast, project.path);
384
+ // FileSummaryManager — code-explorer. The class is constructed for every
385
+ // project regardless of the feature flag; the router 404s when the flag
386
+ // is off, so no spawn can occur. Budget reader queries `ai_invocations`
387
+ // for the current calendar month.
388
+ const fileSummaryAdapter = (0, providers_1.getAdapter)(project.provider ?? 'claude');
389
+ const fileSummaryGenerate = (0, file_summary_generator_1.createFileSummaryGenerator)({ adapter: fileSummaryAdapter, cwd: project.path });
390
+ const fileSummaryManager = new file_summary_manager_1.FileSummaryManager({
391
+ db,
392
+ broadcast: boundBroadcast,
393
+ generate: fileSummaryGenerate,
394
+ monthToDateSpend: (projectId) => {
395
+ const row = db.prepare(`SELECT COALESCE(SUM(total_cost_usd), 0) AS total FROM ai_invocations
396
+ WHERE project_id = ? AND surface = 'file-summary'
397
+ AND started_at >= strftime('%Y-%m-01', 'now')`).get(projectId);
398
+ return row?.total ?? 0;
399
+ },
400
+ monthlyBudgetUsd: () => {
401
+ const raw = (0, desktop_db_1.getDesktopSetting)(this._desktopDb, 'summary_monthly_budget_usd');
402
+ const n = parseFloat(raw ?? '5.00');
403
+ return isNaN(n) ? 5.0 : n;
404
+ },
405
+ language: () => {
406
+ const raw = (0, desktop_db_1.getDesktopSetting)(this._desktopDb, 'summary_language');
407
+ return raw === 'es' ? 'es' : 'en';
408
+ },
409
+ providerId: () => fileSummaryAdapter.id,
410
+ });
411
+ // NOTE: the chokidar watcher is NOT attached here. It is only needed to mark
412
+ // already-generated summaries stale, which is irrelevant until the user opens
413
+ // the Code section. Attaching at startup for every project — even ones that
414
+ // never use Code Explorer (the client flag is OFF by default) — added a
415
+ // persistent recursive watcher per project, the source of the fd leak that
416
+ // broke terminals. The watcher is now attached lazily on the first
417
+ // code-explorer request (see code-explorer-router.ts).
418
+ // Load commands for this project
419
+ try {
420
+ const config = (0, config_1.getConfig)(project.path, db, project.name);
421
+ queueManager.setCommands(config.commands);
422
+ }
423
+ catch {
424
+ // Non-fatal: project may not have commands yet
425
+ }
426
+ const ticketWatcher = new ticket_watcher_1.TicketWatcher(project.path, project.id, boundBroadcast);
427
+ ticketWatcher.start();
428
+ // BrowserCaptureManager — "Add Spec from browser". Constructed for every
429
+ // project regardless of the feature flag; the routes + WS endpoint 404 when
430
+ // the flag is off, and the persistent Chromium context is launched lazily on
431
+ // first session create, so a project that never uses it pays nothing.
432
+ const browserCaptureManager = new browser_capture_manager_1.BrowserCaptureManager({
433
+ projectId: project.id,
434
+ projectSlug: project.slug,
435
+ db,
436
+ broadcast: boundBroadcast,
437
+ });
438
+ const ctx = { project, db, queueManager, chatManager, setupManager, proposalManager, agentRefineManager, fileSummaryManager, specLauncherManager, ticketWatcher, browserCaptureManager, broadcast: boundBroadcast, railJobs };
439
+ this._contexts.set(project.id, ctx);
440
+ return ctx;
441
+ }
442
+ }
443
+ exports.ProjectRegistry = ProjectRegistry;