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,527 @@
1
+ ---
2
+ name: "Health Check Dashboard"
3
+ description: "Run a comprehensive codebase health check — tests, linting, coverage, complexity, and dependency audit. Compare with previous runs to detect regressions."
4
+ category: Workflow
5
+ tags: [workflow, health, quality, dashboard]
6
+ ---
7
+
8
+ Run a full health check for **specrails-desktop**: detect available tools, execute each quality check, compare results against the previous run, detect regressions, compute a health grade, and store a snapshot for future comparison.
9
+
10
+ **Input:** $ARGUMENTS — optional flags:
11
+ - `--since <date>` — use the report from this date (ISO format: YYYY-MM-DD) as the comparison baseline instead of the most recent
12
+ - `--only <checks>` — comma-separated subset to run. Valid values: `tests`, `coverage`, `lint`, `complexity`, `deps`, `perf`, `static`
13
+ - `--save` — always save the snapshot even when `--only` is used (default: skip save for partial runs)
14
+
15
+ ---
16
+
17
+ ## Phase 0: Argument Parsing
18
+
19
+ Parse `$ARGUMENTS` to set runtime variables.
20
+
21
+ **Variables to set:**
22
+
23
+ - `COMPARE_DATE` — string (ISO date) or empty string. Default: `""` (use most recent report).
24
+ - `CHECKS_FILTER` — array of check names or the string `"all"`. Default: `"all"`.
25
+ - `SAVE_SNAPSHOT` — boolean. Default: `true` when `CHECKS_FILTER="all"`, `false` for partial runs unless `--save` is present.
26
+
27
+ **Parsing rules:**
28
+
29
+ 1. Scan `$ARGUMENTS` for `--since <date>`. If found, set `COMPARE_DATE=<date>`. Strip from arguments.
30
+ 2. Scan for `--only <checks>`. If found:
31
+ - Split `<checks>` on commas to produce an array.
32
+ - Validate each entry against the allowed set: `tests`, `coverage`, `lint`, `complexity`, `deps`, `perf`, `static`.
33
+ - If any unknown value is found: print `Error: unknown check "<value>". Valid checks: tests, coverage, lint, complexity, deps, perf, static` and stop.
34
+ - Set `CHECKS_FILTER=<validated-array>`.
35
+ - Set `SAVE_SNAPSHOT=false` (partial run — snapshot may be incomplete).
36
+ 3. Scan for `--save`. If found, set `SAVE_SNAPSHOT=true` regardless of `CHECKS_FILTER`.
37
+
38
+ **Print active configuration:**
39
+
40
+ ```
41
+ Running checks: <all | comma-separated list> | Static analysis: <enabled|disabled> | Comparing to: <COMPARE_DATE or "latest">
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Phase 1: Toolchain Detection
47
+
48
+ Detect available tools for each check category. Run all detections simultaneously (in parallel). For each category, try tools in the order listed — use the first one found.
49
+
50
+ If `CHECKS_FILTER` is not `"all"`, skip detection for categories not in the filter.
51
+
52
+ For each category, set two variables:
53
+ - `TOOL_<CHECK>` — the tool name or command string (e.g., `"jest"`, `"eslint"`)
54
+ - `TOOL_<CHECK>_AVAILABLE` — boolean (`true` / `false`)
55
+
56
+ **Detection sequences:**
57
+
58
+ - **tests:** Try in order: `jest`, `vitest`, `mocha`, `pytest`, `go test`, `cargo test`, `rspec`, `dotnet test`. If none found, check whether `` provides a test command — use it as fallback and set `TOOL_TESTS="ci-commands"`.
59
+ - **coverage:** Try in order: `nyc`, `c8`, `pytest-cov`, `coverage` (Python), `go test -cover`, `cargo tarpaulin`, `lcov`.
60
+ - **lint:** Try in order: `eslint`, `pylint`, `flake8`, `ruff`, `golangci-lint`, `rubocop`, `cargo clippy`.
61
+ - **complexity:** Try in order: `lizard`, `radon`, `gocyclo`, `plato`. If none found, set `TOOL_COMPLEXITY_AVAILABLE=false` — complexity will be estimated from linter output if lint ran.
62
+ - **deps:** Try in order: `npm audit`, `pip-audit`, `govulncheck`, `cargo audit`, `bundle audit`.
63
+ - **perf:** Look for a performance entry point at these paths in order:
64
+ 1. `scripts/perf.sh`
65
+ 2. `scripts/benchmark.sh`
66
+ 3. A `"perf"` or `"benchmark"` script key in `package.json`
67
+ 4. A `perf` or `benchmark` target in `Makefile`
68
+
69
+ If found, set `TOOL_PERF=<path-or-command>` and `TOOL_PERF_AVAILABLE=true`. Otherwise set `TOOL_PERF_AVAILABLE=false`.
70
+
71
+ **Detection summary table** (print after all probes complete):
72
+
73
+ ```
74
+ | Category | Available | Tool |
75
+ |------------|-----------|-------------------|
76
+ | tests | yes/no | <tool or N/A> |
77
+ | coverage | yes/no | <tool or N/A> |
78
+ | lint | yes/no | <tool or N/A> |
79
+ | complexity | yes/no | <tool or N/A> |
80
+ | deps | yes/no | <tool or N/A> |
81
+ | perf | yes/no | <tool or N/A> |
82
+ | static | yes | ai-analysis |
83
+ ```
84
+
85
+ The `static` check is always available (AI-assisted analysis requires no external tools).
86
+
87
+ ---
88
+
89
+ ## Phase 2: Load Previous Report
90
+
91
+ Read `.claude/health-history/` to find the comparison baseline.
92
+
93
+ **Variables to set:**
94
+ - `PREV_REPORT_PATH` — absolute file path or `null`
95
+ - `IS_FIRST_RUN` — boolean
96
+ - `PREV_REPORT` — parsed JSON object or `null`
97
+
98
+ **Logic:**
99
+
100
+ 1. Check whether `.claude/health-history/` exists and contains `.json` files.
101
+ - If directory is absent or empty: set `IS_FIRST_RUN=true`, `PREV_REPORT_PATH=null`, `PREV_REPORT=null`. Print: `First run — no previous report found. Regression comparison is not available.` Proceed.
102
+
103
+ 2. If reports exist and `COMPARE_DATE` is empty: select the most recently modified `.json` file.
104
+
105
+ 3. If `COMPARE_DATE` is set: find the report whose filename date component is closest to `COMPARE_DATE` (without exceeding it). If no report matches within 7 days, print: `Warning: no report found near <COMPARE_DATE>. Falling back to most recent.` Then use the most recent.
106
+
107
+ 4. Set `IS_FIRST_RUN=false`, `PREV_REPORT_PATH=<path>`, load file content into `PREV_REPORT`.
108
+
109
+ 5. Print one line:
110
+
111
+ - First run: `Baseline: first run (no comparison)`
112
+ - Report found: `Comparing to: <YYYY-MM-DD> (<short-sha from filename>)`
113
+
114
+ ---
115
+
116
+ ## Phase 3: Run Checks
117
+
118
+ Run checks **sequentially** in this order: `tests`, `coverage`, `lint`, `complexity`, `deps`, `perf`. Sequential execution avoids resource contention that would skew timing and coverage metrics.
119
+
120
+ For each check, follow this pattern:
121
+
122
+ **Skip condition:** If `TOOL_<CHECK>_AVAILABLE=false` OR check is excluded by `CHECKS_FILTER`:
123
+ - Set `RESULT_<CHECK> = { status: "skipped", tool: null, metrics: null }`
124
+ - Print `<check>: SKIPPED`
125
+ - Continue to next check.
126
+
127
+ **Run:** Execute the tool with the command shown below. If the tool exits non-zero: set `status: "fail"`, capture the error message, record whatever partial metrics are available, and continue — do NOT abort the command.
128
+
129
+ **Store:** Set `RESULT_<CHECK>` to a structured object with `status`, `tool`, and `metrics` fields.
130
+
131
+ ---
132
+
133
+ ### Check: tests
134
+
135
+ Run command (first tool that matches):
136
+
137
+ - `jest`: `jest --json 2>/dev/null` — parse JSON stdout for `numPassedTests`, `numFailedTests`, `numPendingTests`, `testResults[].duration`
138
+ - `vitest`: `vitest run --reporter=json 2>/dev/null` — parse JSON for equivalent fields
139
+ - `mocha`: `mocha --reporter json 2>/dev/null` — parse `stats` object
140
+ - `pytest`: `pytest --tb=no -q 2>&1` — extract pass/fail/skip counts from summary line
141
+ - `go test`: `go test ./... -v 2>&1` — count `--- PASS`, `--- FAIL`, `--- SKIP` lines
142
+ - `cargo test`: `cargo test 2>&1` — parse `test result:` summary line
143
+ - `rspec`: `rspec --format json 2>/dev/null` — parse JSON
144
+ - `dotnet test`: `dotnet test --logger "console;verbosity=normal" 2>&1` — extract summary
145
+ - `ci-commands` fallback: run `` and extract pass/fail counts from output using best-effort parsing
146
+
147
+ **Metrics to extract:** `tests_total`, `tests_passed`, `tests_failed`, `tests_skipped`, `pass_rate` (0.0–100.0), `duration_seconds`.
148
+
149
+ Set `RESULT_TESTS`.
150
+
151
+ ---
152
+
153
+ ### Check: coverage
154
+
155
+ Run command:
156
+
157
+ - `nyc` / `c8`: `nyc report --reporter=text-summary 2>/dev/null` or `c8 report --reporter=text-summary 2>/dev/null` — parse "Statements" or "Lines" coverage percentage
158
+ - `pytest-cov`: re-run as `pytest --cov --cov-report=term-missing -q 2>&1` or read `.coverage` via `coverage report 2>/dev/null`
159
+ - `coverage` (Python): `coverage report 2>/dev/null` — extract `TOTAL` line percentage
160
+ - `go test -cover`: `go test -cover ./... 2>&1` — extract `coverage: N.N%` from each package, compute mean
161
+ - `cargo tarpaulin`: `cargo tarpaulin --out Stdout 2>/dev/null` — extract coverage percentage
162
+ - `lcov`: `lcov --summary coverage.info 2>/dev/null` — extract lines-found/lines-hit
163
+
164
+ **Metrics to extract:** `coverage_pct` (float), `coverage_type` (`"line"` / `"branch"` / `"statement"`).
165
+
166
+ Set `RESULT_COVERAGE`.
167
+
168
+ ---
169
+
170
+ ### Check: lint
171
+
172
+ Run command:
173
+
174
+ - `eslint`: `eslint . --format json 2>/dev/null` — count `severity: 2` (errors) and `severity: 1` (warnings) across all results; count files analyzed
175
+ - `pylint`: `pylint --output-format json <src-dir-or-.> 2>/dev/null` — count messages by type (`error`, `warning`)
176
+ - `flake8`: `flake8 --format default . 2>&1` — count lines with `E` prefix (errors) vs `W` prefix (warnings)
177
+ - `ruff`: `ruff check --output-format json . 2>/dev/null` — parse JSON array, count by severity
178
+ - `golangci-lint`: `golangci-lint run --out-format json 2>/dev/null` — count issues by severity
179
+ - `rubocop`: `rubocop --format json 2>/dev/null` — parse offenses by severity
180
+ - `cargo clippy`: `cargo clippy --message-format json 2>/dev/null` — count `"level":"error"` and `"level":"warning"` messages
181
+
182
+ **Metrics to extract:** `lint_errors`, `lint_warnings`, `lint_files_checked`. Compute `lint_score = max(0, 100 - lint_errors * 5 - lint_warnings * 1)`.
183
+
184
+ Set `RESULT_LINT`.
185
+
186
+ ---
187
+
188
+ ### Check: complexity
189
+
190
+ If `TOOL_COMPLEXITY_AVAILABLE=false`:
191
+ - If `RESULT_LINT` is available (lint ran and has output): set `complexity_source: "estimated"` — use Claude's reasoning to estimate complexity signals from lint output (e.g., complexity-related lint rules fired). Set numeric metrics to `null`.
192
+ - Otherwise: set `complexity_source: "unavailable"`, all metrics `null`, `status: "skipped"`.
193
+
194
+ Run command (if tool available):
195
+
196
+ - `lizard`: `lizard . --csv 2>/dev/null` — parse CSV, compute average CCN, max CCN, count functions with CCN > 10
197
+ - `radon`: `radon cc . -a -j 2>/dev/null` — parse JSON, use `average_complexity` field; count items with complexity > 10
198
+ - `gocyclo`: `gocyclo -over 10 . 2>/dev/null` and `gocyclo -avg . 2>/dev/null` — extract average and functions exceeding threshold
199
+ - `plato`: `plato -r -d /tmp/plato-report . 2>/dev/null && cat /tmp/plato-report/report.json` — extract `summary.average.maintainability`
200
+
201
+ **Metrics to extract:** `avg_cyclomatic_complexity` (float), `max_cyclomatic_complexity` (int), `high_complexity_functions` (int, count with CCN > 10), `complexity_source` (`"measured"` / `"estimated"` / `"unavailable"`).
202
+
203
+ Set `RESULT_COMPLEXITY`. Status is `"measured"` when a tool ran, `"estimated"` when inferred, `"skipped"` when neither is possible.
204
+
205
+ ---
206
+
207
+ ### Check: deps
208
+
209
+ Run command:
210
+
211
+ - `npm audit`: `npm audit --json 2>/dev/null` — parse `vulnerabilities` object; count by `severity` field
212
+ - `pip-audit`: `pip-audit --format json 2>/dev/null` — parse JSON array; count by `fix_versions` presence and severity
213
+ - `govulncheck`: `govulncheck ./... 2>&1` — extract vulnerability counts from summary; if no JSON flag, use Claude's reasoning on text output
214
+ - `cargo audit`: `cargo audit --json 2>/dev/null` — parse `vulnerabilities.list`, count by `advisory.severity`
215
+ - `bundle audit`: `bundle audit check 2>&1` — parse output for `Insecure Source` and `Unpatched versions`; classify by severity from advisory text
216
+
217
+ **Metrics to extract:** `vuln_critical`, `vuln_high`, `vuln_moderate`, `vuln_low`, `vuln_total`.
218
+
219
+ Set `RESULT_DEPS`.
220
+
221
+ ---
222
+
223
+ ### Check: perf
224
+
225
+ If `TOOL_PERF_AVAILABLE=false`: set `RESULT_PERF = { status: "skipped", tool: null, metrics: null }`, print `perf: SKIPPED`, continue.
226
+
227
+ Run the detected entry point. After it completes, attempt to parse its stdout for these standard keys:
228
+ - `p50`, `p50_ms`, `median_ms` → `perf_p50_ms`
229
+ - `p95`, `p95_ms` → `perf_p95_ms`
230
+ - `p99`, `p99_ms` → `perf_p99_ms`
231
+ - Any remaining numeric key-value pairs → `perf_custom`
232
+
233
+ If the script output does not contain recognizable keys, set all latency fields to `null` and store the raw output in `perf_custom.raw`.
234
+
235
+ **Metrics to extract:** `perf_p50_ms`, `perf_p95_ms`, `perf_p99_ms`, `perf_custom`.
236
+
237
+ Set `RESULT_PERF`.
238
+
239
+ ---
240
+
241
+ **Phase 3 summary** (print after all checks):
242
+
243
+ ```
244
+ tests: <PASS|FAIL|SKIPPED> (<tool>)
245
+ coverage: <PASS|FAIL|SKIPPED> (<tool>)
246
+ lint: <PASS|FAIL|SKIPPED> (<tool>)
247
+ complexity: <MEASURED|ESTIMATED|SKIPPED> (<tool>)
248
+ deps: <PASS|FAIL|SKIPPED> (<tool>)
249
+ perf: <PASS|FAIL|SKIPPED> (<tool>)
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Phase 3.5: Static Code Analysis
255
+
256
+ Perform static code inspection to detect issues that tools cannot surface: missing documentation, broken imports, and unused exports. These checks are language-aware and use AI-assisted code reading rather than external tooling.
257
+
258
+ Always exclude the following directories from analysis:
259
+ - `node_modules/`, `.git/`, `dist/`, `build/`, `vendor/`, `.claude/`, `coverage/`
260
+
261
+ For each finding, record a structured object:
262
+ ```
263
+ { severity: "critical"|"warning"|"info", check: string, file: string, line: number, description: string, action: string }
264
+ ```
265
+
266
+ Set `STATIC_FINDINGS = []` before starting. Append each finding to this list.
267
+
268
+ ---
269
+
270
+ ### Check: documentation
271
+
272
+ Scan public-facing code units (exported functions, classes, interfaces, modules) for missing documentation comments.
273
+
274
+ **Language-specific rules:**
275
+
276
+ - **TypeScript/JavaScript**: Identify functions/classes with `export` keyword. Check whether a JSDoc block (`/** ... */`) appears immediately above the declaration. Missing JSDoc on exported symbols = finding.
277
+ - **Python**: Identify top-level functions, classes, and methods. Check for a docstring (a string literal as the first statement in the body). Missing docstring on public (non-underscore-prefixed) symbols = finding.
278
+ - **Ruby**: Identify public methods and classes. Check for a YARD/RDoc comment (`# @param`, `##`, or any comment block) immediately above the definition. Missing comment on public methods in lib/ = finding.
279
+ - **Go**: Identify exported types and functions (capitalized names). Check for a doc comment (line starting with `// <ExportedName>`) immediately above. Missing comment on exported symbols = finding.
280
+
281
+ **Severity assignment:**
282
+ - `critical`: Main entry points (e.g., `index.ts`, `main.go`, `app.rb`) with no module-level documentation
283
+ - `warning`: Exported/public function or class with no documentation
284
+ - `info`: Non-exported function over 20 lines with no documentation
285
+
286
+ Scan all source files matching the detected language(s). Skip test files (`*.test.*`, `*.spec.*`, `_test.go`, `spec/**`).
287
+
288
+ Append each finding to `STATIC_FINDINGS`.
289
+
290
+ ---
291
+
292
+ ### Check: broken_imports
293
+
294
+ Detect import/require statements that reference non-existent paths. Focus on local relative imports (skip `node_modules`, stdlib, installed packages — these are validated by the runtime).
295
+
296
+ **Language-specific rules:**
297
+
298
+ - **TypeScript/JavaScript**: Scan all `import ... from '...'` and `require('...')` statements. For each import path starting with `.` or `/`:
299
+ 1. Resolve the path relative to the source file.
300
+ 2. Check whether the resolved file exists (try: exact path, `.ts`, `.tsx`, `.js`, `.jsx`, `/index.ts`, `/index.js`).
301
+ 3. If no match found: add a `critical` finding.
302
+ - **Python**: Scan all `from . import`, `from .. import`, and `import X` with relative markers. Resolve relative paths from the package root. If the resolved module file does not exist: add a `critical` finding.
303
+ - **Ruby**: Scan `require_relative '...'` statements. Resolve paths from the source file's directory (try `.rb` extension if missing). If the resolved path does not exist: add a `critical` finding.
304
+ - **Go**: Skip — Go's compiler validates imports; broken imports would fail the build.
305
+
306
+ **Severity:** Always `critical` — a broken import is a runtime error.
307
+
308
+ Append each finding to `STATIC_FINDINGS`.
309
+
310
+ ---
311
+
312
+ ### Check: unused_exports
313
+
314
+ Detect exported symbols that are never imported anywhere else in the codebase. Limit to the project source — do not flag exports intended as a library's public API (i.e., symbols re-exported from a barrel file like `index.ts`).
315
+
316
+ **Language-specific rules:**
317
+
318
+ - **TypeScript/JavaScript**:
319
+ 1. Build a list of all exported symbols: scan `export const`, `export function`, `export class`, `export type`, `export interface`, `export default` across all non-test `.ts`/`.tsx`/`.js` files.
320
+ 2. For each exported symbol, search the rest of the codebase for imports of that symbol by name. Exclude the barrel/index file itself.
321
+ 3. If no import found anywhere: add a finding with severity `warning` (may be an intentional API export) unless the file is not `index.ts` and not under `src/` root — in that case severity is `info`.
322
+ - **Python**:
323
+ 1. Scan for symbols listed in `__all__` or public top-level definitions (non-underscore).
324
+ 2. Search for usages across the codebase. If the symbol appears only in its definition file: add a `info` finding.
325
+ - **Ruby**:
326
+ 1. Scan for public constants, classes, and modules defined in `lib/`. Search for `require` or direct references elsewhere. If a class/module in `lib/` is never referenced outside its own file: add a `warning` finding.
327
+
328
+ **Severity:** `warning` for clearly unexported contexts; `info` when the symbol could be part of a public API.
329
+
330
+ Append each finding to `STATIC_FINDINGS`.
331
+
332
+ ---
333
+
334
+ ### Phase 3.5 summary
335
+
336
+ After all three static checks complete, print:
337
+
338
+ ```
339
+ documentation: <N findings> (<N critical, N warning, N info>)
340
+ broken_imports: <N findings> (<N critical>)
341
+ unused_exports: <N findings> (<N warning, N info>)
342
+ Static findings total: <N>
343
+ ```
344
+
345
+ ---
346
+
347
+ ## Phase 4: Build Health Report
348
+
349
+ Using all `RESULT_<CHECK>` values and `PREV_REPORT` (if `IS_FIRST_RUN=false`), compute the final health report object.
350
+
351
+ ### Step 1: Compute per-metric deltas
352
+
353
+ For each numeric metric, compute `delta = current_value - prev_value`. If `IS_FIRST_RUN=true`, set all deltas to `"N/A (first run)"`.
354
+
355
+ Delta notation convention:
356
+ - For metrics where higher is better (pass_rate, coverage_pct, lint_score): positive delta = improvement, negative delta = regression.
357
+ - For metrics where lower is better (lint_errors, vuln_*, high_complexity_functions): positive delta = regression, negative delta = improvement.
358
+
359
+ ### Step 2: Detect regressions
360
+
361
+ A regression is triggered when any of the following thresholds is crossed vs. the previous report:
362
+
363
+ | Check | Threshold |
364
+ |-------|-----------|
365
+ | tests | `pass_rate` drops by more than 1% |
366
+ | coverage | `coverage_pct` drops by more than 2 percentage points |
367
+ | lint | `lint_errors` increases vs. previous |
368
+ | lint | `lint_score` drops by more than 5 points |
369
+ | complexity | `high_complexity_functions` increases vs. previous |
370
+ | deps | `vuln_critical` increases vs. previous |
371
+ | deps | `vuln_high` increases vs. previous |
372
+ | perf | `perf_p50_ms` increases by more than 10% vs. previous |
373
+
374
+ If `IS_FIRST_RUN=true`: set `REGRESSIONS=[]` (no regression detection possible on first run).
375
+
376
+ Build `REGRESSIONS` as a list of objects: `{ check, metric, previous, current, delta }`.
377
+
378
+ ### Step 3: Assign health grade
379
+
380
+ Evaluate criteria in order from F to A; assign the first grade whose criteria are met:
381
+
382
+ | Grade | Criteria |
383
+ |-------|----------|
384
+ | F | Test suite fails to run (RESULT_TESTS.status = "fail") OR pass_rate < 50% |
385
+ | D | Multiple regressions detected (len(REGRESSIONS) >= 2) OR pass_rate < 80% OR vuln_critical > 2 |
386
+ | C | One regression detected OR pass_rate 80–89% OR vuln_critical > 0 |
387
+ | B | No critical regressions. Any one of: pass_rate 90–94%, OR coverage_pct 70–79%, OR lint_errors 1–5, OR vuln_high <= 2 |
388
+ | A | No regressions. pass_rate >= 95%. coverage_pct >= 80% (if measured). lint_errors == 0 (if measured). vuln_critical == 0 AND vuln_high == 0 (if measured). |
389
+
390
+ When `IS_FIRST_RUN=true`, regressions cannot be detected — base the grade on absolute metric thresholds only (no regression criteria apply).
391
+
392
+ When a check is SKIPPED, omit its metric from grade criteria (do not penalize for unavailable tools).
393
+
394
+ ### Step 4: Assemble HEALTH_REPORT
395
+
396
+ Build `HEALTH_REPORT` as a structured object matching the JSON storage schema exactly:
397
+
398
+ ```
399
+ HEALTH_REPORT = {
400
+ schema_version: "1",
401
+ project: "specrails-desktop",
402
+ timestamp: <ISO 8601 current datetime>,
403
+ git_sha: <full SHA from `git rev-parse HEAD` or "unknown">,
404
+ git_short_sha: <7-char SHA from `git rev-parse --short HEAD` or "unknown">,
405
+ git_branch: <branch from `git rev-parse --abbrev-ref HEAD` or "unknown">,
406
+ checks: {
407
+ tests: { status, tool, metrics: { tests_total, tests_passed, tests_failed, tests_skipped, pass_rate, duration_seconds } },
408
+ coverage: { status, tool, metrics: { coverage_pct, coverage_type } },
409
+ lint: { status, tool, metrics: { lint_errors, lint_warnings, lint_score, lint_files_checked } },
410
+ complexity: { status, tool, metrics: { avg_cyclomatic_complexity, max_cyclomatic_complexity, high_complexity_functions, complexity_source } },
411
+ deps: { status, tool, metrics: { vuln_critical, vuln_high, vuln_moderate, vuln_low, vuln_total } },
412
+ perf: { status, tool, metrics: { perf_p50_ms, perf_p95_ms, perf_p99_ms, perf_custom } }
413
+ },
414
+ static_findings: <STATIC_FINDINGS array — each: { severity, check, file, line, description, action }>,
415
+ grade: <"A"|"B"|"C"|"D"|"F">,
416
+ regressions: <REGRESSIONS array>,
417
+ comparison_report: <PREV_REPORT_PATH basename or null>
418
+ }
419
+ ```
420
+
421
+ ---
422
+
423
+ ## Phase 5: Display Report and Store Snapshot
424
+
425
+ ### Action 1: Display
426
+
427
+ Render the health report to the terminal using Markdown formatting:
428
+
429
+ ```
430
+ ## Codebase Health Report — specrails-desktop
431
+ Date: <ISO date> | Commit: <git_short_sha> | Compared to: <previous report date or "first run">
432
+
433
+ Overall Grade: <A/B/C/D/F> (<one-line summary>)
434
+
435
+ ### Test Suite [<PASS/FAIL/SKIPPED>]
436
+ Tests: N passed, N failed, N skipped (N total)
437
+ Pass rate: N% <delta: (+N%) or (-N%) or N/A (first run)>
438
+ Duration: Xs
439
+
440
+ ### Code Coverage [<PASS/FAIL/SKIPPED/ESTIMATED>]
441
+ Coverage: N% <delta vs previous>
442
+ Type: line/branch/statement
443
+
444
+ ### Linting [<PASS/FAIL/SKIPPED>]
445
+ Score: N/100 <delta vs previous>
446
+ Errors: N Warnings: N
447
+
448
+ ### Complexity [<MEASURED/ESTIMATED/SKIPPED>]
449
+ Avg CCN: N Max CCN: N
450
+ High-complexity functions: N (>10 CCN) <delta vs previous>
451
+
452
+ ### Dependencies [<PASS/FAIL/SKIPPED>]
453
+ Vulnerabilities: N critical, N high, N moderate, N low
454
+
455
+ ### Performance [<PASS/FAIL/SKIPPED>]
456
+ p50: Nms p95: Nms p99: Nms <delta vs previous>
457
+
458
+ ---
459
+ Regressions detected: N
460
+ <if N > 0, list each:>
461
+ - <check>: <metric> changed from X to Y (<delta>)
462
+ <if N == 0:>
463
+ No regressions detected.
464
+
465
+ ---
466
+
467
+ ### Static Analysis Findings [<N total: N critical, N warning, N info>]
468
+
469
+ <if STATIC_FINDINGS is empty:>
470
+ No static findings detected.
471
+
472
+ <if STATIC_FINDINGS is non-empty:>
473
+
474
+ | Severity | Check | File | Line | Finding | Action |
475
+ |----------|-------|------|------|---------|--------|
476
+ <for each finding in STATIC_FINDINGS, sorted by severity (critical first, then warning, then info):>
477
+ | <CRITICAL|WARNING|INFO> | <check> | <file> | <line> | <description> | <action> |
478
+
479
+ <if any critical findings:>
480
+ #### Critical Findings (require immediate attention)
481
+ <for each critical finding:>
482
+ **[CRITICAL] <check>** — `<file>:<line>`
483
+ > <description>
484
+ > **Action:** <action>
485
+
486
+ <if any warning findings (limit to top 5 by file breadth — prefer findings spread across more files):>
487
+ #### Warnings (recommended fixes)
488
+ <for each warning finding, up to 5:>
489
+ **[WARNING] <check>** — `<file>:<line>`
490
+ > <description>
491
+ > **Action:** <action>
492
+ <if more than 5 warning findings:>
493
+ > ... and N more warnings. Run with `--only static` to see all.
494
+
495
+ <if any info findings:>
496
+ #### Info (low-priority improvements)
497
+ Summary: N info-level findings across N files. Run with `--only static` to see full list.
498
+ ```
499
+
500
+ For delta display: wrap positive deltas on error/failure metrics in `(+N)` to indicate regression; wrap negative deltas on pass-rate/coverage in `(-N%)` styled as improvement. For terminal rendering, use plain notation — the sign alone conveys direction.
501
+
502
+ ### Action 2: Store snapshot
503
+
504
+ Only store if `SAVE_SNAPSHOT=true`.
505
+
506
+ 1. Determine filename: `<YYYY-MM-DD>-<git_short_sha>.json` where the date is today's ISO date. If git is unavailable, use `<YYYY-MM-DD>-unknown.json`.
507
+ 2. Create `.claude/health-history/` if it does not exist (idempotent — no error if already present).
508
+ 3. Write `HEALTH_REPORT` serialized as JSON to `.claude/health-history/<filename>`.
509
+ 4. Print: `Stored: .claude/health-history/<filename>`
510
+
511
+ ### Housekeeping notice
512
+
513
+ After writing (or after checking the directory if `SAVE_SNAPSHOT=false`), count `.json` files in `.claude/health-history/`. If count > 30, print:
514
+
515
+ ```
516
+ Note: .claude/health-history/ has N reports. Consider pruning old ones with:
517
+ ls -t .claude/health-history/ | tail -n +31 | xargs -I{} rm .claude/health-history/{}
518
+ ```
519
+
520
+ ### .gitignore suggestion
521
+
522
+ Check whether `.claude/health-history` appears in `.gitignore` (if `.gitignore` exists). If it does not appear, print:
523
+
524
+ ```
525
+ Tip: health history reports are local artifacts. Add to .gitignore:
526
+ echo '.claude/health-history/' >> .gitignore
527
+ ```