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,450 @@
1
+ "use strict";
2
+ /**
3
+ * SPECs SMASH — pure agent contract module.
4
+ *
5
+ * Decomposes a committed ticket (with Contract Layer) into 3–8 ordered
6
+ * child tickets. This module contains only the byte-stable system prompt,
7
+ * the output schema, and the parser/validator. The spawn lifecycle and
8
+ * store mutation live in `server/smash-runner.ts`.
9
+ *
10
+ * See openspec/changes/add-specs-smash.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SMASH_MAX_CHILDREN = exports.SMASH_MIN_CHILDREN = exports.SMASH_PROMPT_VERSION = void 0;
14
+ exports.isSpecsSmashKillSwitchActive = isSpecsSmashKillSwitchActive;
15
+ exports.buildSmashSystemPrompt = buildSmashSystemPrompt;
16
+ exports.validateSmashOutput = validateSmashOutput;
17
+ exports.parseSmashOutput = parseSmashOutput;
18
+ exports.SMASH_PROMPT_VERSION = 1;
19
+ exports.SMASH_MIN_CHILDREN = 3;
20
+ exports.SMASH_MAX_CHILDREN = 8;
21
+ // ─── Kill switch ─────────────────────────────────────────────────────────────
22
+ /**
23
+ * Returns `true` when the app-wide kill switch is active and SMASH spawns
24
+ * MUST be skipped regardless of per-project state.
25
+ *
26
+ * The env var `SPECRAILS_SMASH` controls the feature:
27
+ * - unset / any other value → feature ENABLED (kill switch inactive)
28
+ * - `0` / `false` / `off` (CI) → feature DISABLED (kill switch active)
29
+ */
30
+ function isSpecsSmashKillSwitchActive(envValue = process.env.SPECRAILS_SMASH) {
31
+ if (envValue == null)
32
+ return false;
33
+ const v = envValue.trim().toLowerCase();
34
+ return v === '0' || v === 'false' || v === 'off';
35
+ }
36
+ const VALID_PRIORITIES = new Set(['critical', 'high', 'medium', 'low']);
37
+ const TITLE_MAX_LEN = 80;
38
+ const RATIONALE_MAX_LEN = 200;
39
+ // ─── System prompt ───────────────────────────────────────────────────────────
40
+ const EXAMPLE_BLOCK = `\`\`\`smash
41
+ {
42
+ "smashVersion": 1,
43
+ "children": [
44
+ {
45
+ "title": "WS infra + presence channel",
46
+ "description": "Set up the websocket transport and a presence channel that tracks connected users per document. Includes server-side connection lifecycle and client-side reconnect handling.",
47
+ "priority": "high",
48
+ "executionOrder": 1,
49
+ "rationale": "Other children depend on a working transport"
50
+ },
51
+ {
52
+ "title": "CRDT document model",
53
+ "description": "Define the CRDT operations and the in-memory document shape. No UI work yet.",
54
+ "priority": "high",
55
+ "executionOrder": 2,
56
+ "rationale": "Required before any broadcast or merge work"
57
+ },
58
+ {
59
+ "title": "Cursor broadcast UI",
60
+ "description": "Render other users' cursors in the editor. Throttle position updates to 30Hz.",
61
+ "priority": "medium",
62
+ "executionOrder": 3,
63
+ "rationale": "Visible win once transport + model exist"
64
+ },
65
+ {
66
+ "title": "Conflict resolution UX",
67
+ "description": "Show a non-blocking banner when concurrent edits diverge and allow accept/reject.",
68
+ "priority": "medium",
69
+ "executionOrder": 4,
70
+ "rationale": "Closes the loop on multi-user editing"
71
+ }
72
+ ]
73
+ }
74
+ \`\`\``;
75
+ /**
76
+ * Build the byte-stable system prompt for a SMASH turn.
77
+ *
78
+ * MUST be byte-stable for a given mode across two consecutive calls — the
79
+ * only inputs that vary the output are intentional version bumps
80
+ * (SMASH_PROMPT_VERSION) and the `mode` argument.
81
+ */
82
+ function buildSmashSystemPrompt(mode = 'simple') {
83
+ if (mode === 'full')
84
+ return buildSmashFullSystemPrompt();
85
+ return buildSmashSimpleSystemPrompt();
86
+ }
87
+ function buildSmashSimpleSystemPrompt() {
88
+ return [
89
+ '# SPECs SMASH — decomposition pass',
90
+ '',
91
+ 'You are SPECs SMASH. The user has a committed ticket that is too big to',
92
+ 'execute as a single unit. Your sole job is to split it into between',
93
+ `${exports.SMASH_MIN_CHILDREN} and ${exports.SMASH_MAX_CHILDREN} ordered child tickets, each independently`,
94
+ 'executable. Emit EXACTLY ONE fenced code block tagged `smash` containing a',
95
+ 'JSON object matching the schema below. No prose before or after the block.',
96
+ '',
97
+ '## Hard rules',
98
+ '',
99
+ '- DO NOT call any tool. Work only from the title and description provided.',
100
+ '- DO NOT ask clarifying questions.',
101
+ '- Each child MUST be independently executable. If the user already has',
102
+ ' enough context to start that child on its own, you have done it right.',
103
+ `- Produce between ${exports.SMASH_MIN_CHILDREN} and ${exports.SMASH_MAX_CHILDREN} children inclusive. Below ${exports.SMASH_MIN_CHILDREN} means the spec`,
104
+ ` did not need to be split; above ${exports.SMASH_MAX_CHILDREN} means each child is too small.`,
105
+ '- `executionOrder` MUST start at 1 and be contiguous (1, 2, 3, …). Lower',
106
+ ' numbers run first; ties imply you should pick one. Encode technical',
107
+ ' dependency: a child cannot rely on another with a higher number.',
108
+ '- `title` MUST be ≤ 80 chars, non-empty, imperative form ("Add X", "Refactor Y").',
109
+ '- `description` MUST be non-empty markdown. Include WHAT to build, not why.',
110
+ '- `priority` MUST be one of: "critical", "high", "medium", "low". Inherit',
111
+ ' conservatively from the parent ticket if unsure.',
112
+ '- `rationale` MUST be ≤ 200 chars and explain why this child exists as a',
113
+ ' separate ticket (e.g. dependency anchor, scope isolation, parallelisable).',
114
+ '- DO NOT include a Contract Layer in any child description. The app will run',
115
+ ' Contract Refine per child separately if the user requests it.',
116
+ '- `shortSummary` is OPTIONAL: when included, a single plain-text sentence',
117
+ ' ≤ 120 chars summarising the child for a dashboard postit. No markdown,',
118
+ ' no bullets, no headings. Omit the field if you cannot say anything new.',
119
+ '',
120
+ '## Required JSON shape',
121
+ '',
122
+ '```',
123
+ '{',
124
+ ' "smashVersion": 1,',
125
+ ' "children": [',
126
+ ' {',
127
+ ' "title": string (≤ 80 chars, non-empty),',
128
+ ' "description": string (non-empty markdown),',
129
+ ' "priority": "critical" | "high" | "medium" | "low",',
130
+ ' "executionOrder": integer (1-based, contiguous, unique),',
131
+ ' "rationale": string (≤ 200 chars),',
132
+ ' "shortSummary": string (≤ 120 chars, optional, plain text)',
133
+ ' }',
134
+ ' ]',
135
+ '}',
136
+ '```',
137
+ '',
138
+ '## Example output',
139
+ '',
140
+ EXAMPLE_BLOCK,
141
+ '',
142
+ `## Prompt version: ${exports.SMASH_PROMPT_VERSION}`,
143
+ '',
144
+ ].join('\n');
145
+ }
146
+ /**
147
+ * FULL mode: deep decomposition with codebase access. The agent uses
148
+ * read-only tools (Read, Grep, Glob) extensively to ground the partition in
149
+ * the real project. Each Sub-Spec is a stand-alone "super-spec" with rich
150
+ * description sections, exhaustive acceptance criteria, and concrete file
151
+ * paths. Tokens are spent freely — quality over speed.
152
+ */
153
+ function buildSmashFullSystemPrompt() {
154
+ return [
155
+ '# SPECs SMASH — Super-Spec decomposition (Full mode)',
156
+ '',
157
+ 'You are SPECs SMASH in Full mode. The user has committed a spec that is',
158
+ 'too big to execute as a single unit. Your job is to partition it into',
159
+ `${exports.SMASH_MIN_CHILDREN}-${exports.SMASH_MAX_CHILDREN} ordered Sub-Specs that are themselves super-specs:`,
160
+ 'each as detailed and prescriptive as the parent — sometimes more so.',
161
+ '',
162
+ '**Do not economise on tokens.** Read aggressively, write thoroughly.',
163
+ 'Sub-Specs that ship to engineers should leave zero room for guessing.',
164
+ '',
165
+ '## Process — follow it in order',
166
+ '',
167
+ '1. **Read the parent spec end-to-end.** Internalise the title, the body,',
168
+ ' and (critically) the Contract Layer. Note every identifier, file path,',
169
+ ' data shape, invariant, and state machine step.',
170
+ '',
171
+ '2. **Survey the codebase.** USE Read, Grep, and Glob freely. Open every',
172
+ ' file the Contract Layer mentions. Trace each named function /',
173
+ ' identifier to its definition. Read sibling files in the same dir to',
174
+ ' learn existing patterns, error-handling conventions, test style,',
175
+ ' imports, and naming. Read the project root README / CLAUDE.md if',
176
+ ' present. Read package.json for dependency versions. The more you',
177
+ ' read, the better — there is no quota.',
178
+ '',
179
+ `3. **Decide the partition.** Carve ${exports.SMASH_MIN_CHILDREN}-${exports.SMASH_MAX_CHILDREN} Sub-Specs whose union covers`,
180
+ ' the parent scope completely with zero overlap. Each Sub-Spec must be:',
181
+ ' - **End-to-end executable on its own**: every dependency it relies on',
182
+ ' exists today OR comes from a lower-numbered sibling.',
183
+ ' - **Anchored to real artefacts**: cite concrete file paths and',
184
+ ' identifiers from your reads, not invented names.',
185
+ ' - **Faithful to the parent Contract Layer**: same names, same types,',
186
+ ' same file touch list. Do not rename, do not "improve".',
187
+ '',
188
+ '4. **Draft each Sub-Spec as a super-spec.** Each description MUST contain',
189
+ ' the following markdown sections in this order:',
190
+ '',
191
+ ' ```markdown',
192
+ ' ## Background',
193
+ ' <2-5 sentences: why this Sub-Spec exists in the broader spec, what it',
194
+ ' unblocks, why it stands alone.>',
195
+ '',
196
+ ' ## Implementation Plan',
197
+ ' <Numbered, step-by-step plan. Every step cites the file path it',
198
+ ' touches (and roughly the function/area). Include type signatures,',
199
+ ' data shapes, schema migrations, env vars. Mention `import` paths',
200
+ ' when relevant.>',
201
+ '',
202
+ ' ## Affected Files',
203
+ ' <Bullet list of every file you expect to be created / extended /',
204
+ ' deleted. Use `create` / `extend` / `delete` next to each path, plus',
205
+ ' a one-line "why".>',
206
+ '',
207
+ ' ## Edge Cases & Risks',
208
+ ' <Bullets: things that could go wrong, race conditions, backwards',
209
+ ' compatibility, perf, security, error paths the engineer must handle.>',
210
+ '',
211
+ ' ## Out of Scope',
212
+ ' <Bullets: explicit "not this Sub-Spec" items, especially when a',
213
+ ' reader might assume they belong here.>',
214
+ '',
215
+ ' ## Testing Strategy',
216
+ ' <How to test this Sub-Spec end-to-end: unit, integration, manual',
217
+ ' smoke. Mention specific existing test files when relevant.>',
218
+ ' ```',
219
+ '',
220
+ '5. **Write exhaustive acceptance criteria.** 4-10 entries per Sub-Spec.',
221
+ ' Each MUST be:',
222
+ ' - A complete sentence starting with a capital letter.',
223
+ ' - A *verifiable* outcome (a tester could mark it pass/fail).',
224
+ ' - Phrased in the *result* tense ("X happens when Y"), not the',
225
+ ' *implementation* tense ("we add a function").',
226
+ ' - Cover happy path AND at least one error / edge case.',
227
+ '',
228
+ '6. **Final output.** Emit EXACTLY ONE fenced code block tagged `smash`',
229
+ ' with the JSON shape below. No prose before or after the block. No',
230
+ ' second block.',
231
+ '',
232
+ '## Hard rules',
233
+ '',
234
+ '- You MAY call Read, Grep, Glob freely. DO NOT call Bash, Edit, Write.',
235
+ '- DO NOT ask clarifying questions — work from the codebase you can read.',
236
+ `- Produce ${exports.SMASH_MIN_CHILDREN}-${exports.SMASH_MAX_CHILDREN} children inclusive.`,
237
+ '- `executionOrder` starts at 1 and is contiguous; lower numbers run',
238
+ ' first; higher-numbered Sub-Specs MAY depend on lower-numbered ones.',
239
+ '- `title` ≤ 80 chars, imperative ("Add WS infra", "Refactor X").',
240
+ '- `description` is markdown using the six section template above. Spend',
241
+ ' the tokens — a thin description is a failed Sub-Spec.',
242
+ '- `priority` ∈ {"critical","high","medium","low"}.',
243
+ '- `rationale` ≤ 200 chars: WHY this Sub-Spec exists separately (dependency',
244
+ ' anchor, isolation, parallelisability, Contract Layer constraint).',
245
+ '- `acceptanceCriteria` is 4-10 strings, capitalised, testable outcomes.',
246
+ '- `shortSummary` is OPTIONAL: when included, a single plain-text sentence',
247
+ ' ≤ 120 chars summarising this Sub-Spec for a dashboard postit. No markdown.',
248
+ '- DO NOT include a Contract Layer in any child description.',
249
+ '- Use the parent Contract Layer as the immutable source of truth for',
250
+ ' names, types, and file paths.',
251
+ '',
252
+ '## Required JSON shape',
253
+ '',
254
+ '```',
255
+ '{',
256
+ ' "smashVersion": 1,',
257
+ ' "children": [',
258
+ ' {',
259
+ ' "title": string (≤ 80 chars, non-empty, imperative),',
260
+ ' "description": string (markdown — 6-section super-spec body),',
261
+ ' "priority": "critical" | "high" | "medium" | "low",',
262
+ ' "executionOrder": integer (1-based, contiguous, unique),',
263
+ ' "rationale": string (≤ 200 chars — WHY this Sub-Spec),',
264
+ ' "acceptanceCriteria": string[] (4-10 items, capitalised, testable),',
265
+ ' "shortSummary": string (≤ 120 chars, optional, plain text)',
266
+ ' }',
267
+ ' ]',
268
+ '}',
269
+ '```',
270
+ '',
271
+ '## Example output (illustrative shape — not example content)',
272
+ '',
273
+ EXAMPLE_BLOCK,
274
+ '',
275
+ `## Prompt version: ${exports.SMASH_PROMPT_VERSION}`,
276
+ '',
277
+ ].join('\n');
278
+ }
279
+ // ─── Parser ──────────────────────────────────────────────────────────────────
280
+ const SMASH_FENCE_RE = /```smash\s*\n([\s\S]*?)\n```/;
281
+ function fail(reason, detail) {
282
+ return detail ? { ok: false, reason, detail } : { ok: false, reason };
283
+ }
284
+ function asString(v) {
285
+ return typeof v === 'string' ? v : null;
286
+ }
287
+ function validateChild(raw, index) {
288
+ if (typeof raw !== 'object' || raw === null) {
289
+ return { ok: false, reason: 'child-shape', detail: `child[${index}] is not an object` };
290
+ }
291
+ const o = raw;
292
+ const title = asString(o.title);
293
+ if (title === null) {
294
+ return { ok: false, reason: 'child-shape', detail: `child[${index}].title is not a string` };
295
+ }
296
+ if (title.trim().length === 0) {
297
+ return { ok: false, reason: 'title-empty', detail: `child[${index}].title is empty` };
298
+ }
299
+ if (title.length > TITLE_MAX_LEN) {
300
+ return {
301
+ ok: false,
302
+ reason: 'title-too-long',
303
+ detail: `child[${index}].title length ${title.length} > ${TITLE_MAX_LEN}`,
304
+ };
305
+ }
306
+ const description = asString(o.description);
307
+ if (description === null) {
308
+ return { ok: false, reason: 'child-shape', detail: `child[${index}].description is not a string` };
309
+ }
310
+ if (description.trim().length === 0) {
311
+ return { ok: false, reason: 'description-empty', detail: `child[${index}].description is empty` };
312
+ }
313
+ const priority = asString(o.priority);
314
+ if (priority === null || !VALID_PRIORITIES.has(priority)) {
315
+ return { ok: false, reason: 'invalid-priority', detail: `child[${index}].priority=${String(o.priority)}` };
316
+ }
317
+ const eo = o.executionOrder;
318
+ if (typeof eo !== 'number' || !Number.isInteger(eo) || eo < 1) {
319
+ return {
320
+ ok: false,
321
+ reason: 'invalid-execution-order',
322
+ detail: `child[${index}].executionOrder=${String(eo)}`,
323
+ };
324
+ }
325
+ const rationale = asString(o.rationale);
326
+ if (rationale === null) {
327
+ return { ok: false, reason: 'child-shape', detail: `child[${index}].rationale is not a string` };
328
+ }
329
+ if (rationale.length > RATIONALE_MAX_LEN) {
330
+ return {
331
+ ok: false,
332
+ reason: 'rationale-too-long',
333
+ detail: `child[${index}].rationale length ${rationale.length} > ${RATIONALE_MAX_LEN}`,
334
+ };
335
+ }
336
+ // Optional acceptanceCriteria: string[] of non-empty strings (full mode).
337
+ let acceptanceCriteria;
338
+ if (o.acceptanceCriteria !== undefined) {
339
+ if (!Array.isArray(o.acceptanceCriteria)) {
340
+ return { ok: false, reason: 'child-shape', detail: `child[${index}].acceptanceCriteria is not an array` };
341
+ }
342
+ const valid = [];
343
+ for (const ac of o.acceptanceCriteria) {
344
+ if (typeof ac !== 'string' || ac.trim().length === 0)
345
+ continue;
346
+ valid.push(ac.trim());
347
+ }
348
+ if (valid.length > 0)
349
+ acceptanceCriteria = valid;
350
+ }
351
+ // Optional shortSummary: tolerated when missing. Sanitized (trim, control-strip,
352
+ // 240-char hard cap) by the ticket-store helper at persistence time; here we
353
+ // only accept strings and pass them through.
354
+ let shortSummary;
355
+ if (o.shortSummary !== undefined && o.shortSummary !== null) {
356
+ if (typeof o.shortSummary !== 'string') {
357
+ // Reject only when present-but-wrong-type, to surface model bugs early.
358
+ return { ok: false, reason: 'child-shape', detail: `child[${index}].shortSummary is not a string` };
359
+ }
360
+ shortSummary = o.shortSummary;
361
+ }
362
+ return {
363
+ ok: true,
364
+ value: {
365
+ title,
366
+ description,
367
+ priority: priority,
368
+ executionOrder: eo,
369
+ rationale,
370
+ ...(acceptanceCriteria ? { acceptanceCriteria } : {}),
371
+ ...(shortSummary !== undefined ? { shortSummary } : {}),
372
+ },
373
+ };
374
+ }
375
+ /**
376
+ * Validate a parsed payload as a SmashOutput. Used by parseSmashOutput, and
377
+ * directly testable.
378
+ */
379
+ function validateSmashOutput(payload) {
380
+ if (typeof payload !== 'object' || payload === null) {
381
+ return fail('malformed', 'payload is not an object');
382
+ }
383
+ const obj = payload;
384
+ if (!('smashVersion' in obj))
385
+ return fail('missing-version');
386
+ if (obj.smashVersion !== 1)
387
+ return fail('wrong-version', `smashVersion=${String(obj.smashVersion)}`);
388
+ if (!('children' in obj))
389
+ return fail('children-missing');
390
+ const rawChildren = obj.children;
391
+ if (!Array.isArray(rawChildren))
392
+ return fail('children-missing', 'children is not an array');
393
+ if (rawChildren.length === 0)
394
+ return fail('children-empty');
395
+ if (rawChildren.length < exports.SMASH_MIN_CHILDREN) {
396
+ return fail('count-below-min', `${rawChildren.length} < ${exports.SMASH_MIN_CHILDREN}`);
397
+ }
398
+ if (rawChildren.length > exports.SMASH_MAX_CHILDREN) {
399
+ return fail('count-above-max', `${rawChildren.length} > ${exports.SMASH_MAX_CHILDREN}`);
400
+ }
401
+ const validated = [];
402
+ for (let i = 0; i < rawChildren.length; i++) {
403
+ const r = validateChild(rawChildren[i], i);
404
+ if (!r.ok)
405
+ return r;
406
+ validated.push(r.value);
407
+ }
408
+ // Sort by the agent-provided executionOrder (stable: preserves original
409
+ // child index on ties), then re-number 1..N. This tolerates agents that
410
+ // emit duplicates or non-contiguous numbers while still preserving the
411
+ // ordering intent the agent signalled. We only reject malformed numbers
412
+ // (non-int / < 1) at the per-child validation step above.
413
+ const withIndex = validated.map((c, i) => ({ c, i }));
414
+ withIndex.sort((a, b) => {
415
+ if (a.c.executionOrder !== b.c.executionOrder)
416
+ return a.c.executionOrder - b.c.executionOrder;
417
+ return a.i - b.i;
418
+ });
419
+ const renumbered = withIndex.map(({ c }, idx) => ({ ...c, executionOrder: idx + 1 }));
420
+ return { ok: true, value: { smashVersion: 1, children: renumbered } };
421
+ }
422
+ /**
423
+ * Parse a SMASH-fenced block from raw assistant text, then validate it.
424
+ *
425
+ * - `{ ok: false, reason: 'not-found' }` when no fenced block is present.
426
+ * - `{ ok: false, reason: 'malformed' }` when JSON parse fails.
427
+ * - Other validation reasons from `validateSmashOutput`.
428
+ */
429
+ function parseSmashOutput(raw) {
430
+ const match = raw.match(SMASH_FENCE_RE);
431
+ if (!match) {
432
+ // Also try parsing the whole input as raw JSON in case the model omitted
433
+ // fences (defensive — strict prompt asks for fences but agents drift).
434
+ try {
435
+ const payload = JSON.parse(raw);
436
+ return validateSmashOutput(payload);
437
+ }
438
+ catch {
439
+ return fail('not-found');
440
+ }
441
+ }
442
+ let payload;
443
+ try {
444
+ payload = JSON.parse(match[1]);
445
+ }
446
+ catch {
447
+ return fail('malformed', 'JSON.parse failed');
448
+ }
449
+ return validateSmashOutput(payload);
450
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isCodeExplorerEnabled = isCodeExplorerEnabled;
4
+ exports.isBrowserCaptureEnabled = isBrowserCaptureEnabled;
5
+ function isCodeExplorerEnabled() {
6
+ return process.env.SPECRAILS_CODE_EXPLORER !== 'false';
7
+ }
8
+ /**
9
+ * Browser-capture feature ("Add Spec from browser"): an embedded CDP/Chromium
10
+ * browser whose screencast is streamed in-app, plus region-select → screenshot +
11
+ * DOM capture that feeds Add Spec (Quick/Explore). Server-side default ON; set
12
+ * SPECRAILS_BROWSER_CAPTURE="false" to disable the routes + WS endpoint entirely
13
+ * (emergency rollback). The client gates separately on VITE_FEATURE_BROWSER_CAPTURE.
14
+ */
15
+ function isBrowserCaptureEnabled() {
16
+ return process.env.SPECRAILS_BROWSER_CAPTURE !== 'false';
17
+ }