@rulemetric/cli 0.2.1 → 0.2.3

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 (780) hide show
  1. package/dist/base-command.js +13 -52
  2. package/dist/base-command.js.map +7 -1
  3. package/dist/chunk-2AM54TUK.js +59 -0
  4. package/dist/chunk-2AM54TUK.js.map +7 -0
  5. package/dist/chunk-3TIMQ3O6.js +96 -0
  6. package/dist/chunk-3TIMQ3O6.js.map +7 -0
  7. package/dist/chunk-4BHDHHKL.js +48 -0
  8. package/dist/chunk-4BHDHHKL.js.map +7 -0
  9. package/dist/chunk-4D537GXE.js +99 -0
  10. package/dist/chunk-4D537GXE.js.map +7 -0
  11. package/dist/chunk-4SCZK7AL.js +129 -0
  12. package/dist/chunk-4SCZK7AL.js.map +7 -0
  13. package/dist/chunk-4WFE4PFP.js +61 -0
  14. package/dist/chunk-4WFE4PFP.js.map +7 -0
  15. package/dist/chunk-52WIYRZH.js +73 -0
  16. package/dist/chunk-52WIYRZH.js.map +7 -0
  17. package/dist/chunk-7FAA3YNB.js +1549 -0
  18. package/dist/chunk-7FAA3YNB.js.map +7 -0
  19. package/dist/chunk-7NYKWN7U.js +12 -0
  20. package/dist/chunk-7NYKWN7U.js.map +7 -0
  21. package/dist/chunk-AULP2OWH.js +99 -0
  22. package/dist/chunk-AULP2OWH.js.map +7 -0
  23. package/dist/chunk-B5KNTGMJ.js +1788 -0
  24. package/dist/chunk-B5KNTGMJ.js.map +7 -0
  25. package/dist/chunk-BD7CY42U.js +23 -0
  26. package/dist/chunk-BD7CY42U.js.map +7 -0
  27. package/dist/chunk-BO76WKJR.js +42 -0
  28. package/dist/chunk-BO76WKJR.js.map +7 -0
  29. package/dist/chunk-BRD5RUGM.js +53 -0
  30. package/dist/chunk-BRD5RUGM.js.map +7 -0
  31. package/dist/chunk-BT6Z6545.js +43 -0
  32. package/dist/chunk-BT6Z6545.js.map +7 -0
  33. package/dist/chunk-BZDKEQKU.js +39 -0
  34. package/dist/chunk-BZDKEQKU.js.map +7 -0
  35. package/dist/chunk-CROYS75W.js +161 -0
  36. package/dist/chunk-CROYS75W.js.map +7 -0
  37. package/dist/chunk-DGHWRQXL.js +17 -0
  38. package/dist/chunk-DGHWRQXL.js.map +7 -0
  39. package/dist/chunk-DQ3KELXD.js +74 -0
  40. package/dist/chunk-DQ3KELXD.js.map +7 -0
  41. package/dist/chunk-DTFXCHHI.js +108 -0
  42. package/dist/chunk-DTFXCHHI.js.map +7 -0
  43. package/dist/chunk-DU73QUS3.js +75 -0
  44. package/dist/chunk-DU73QUS3.js.map +7 -0
  45. package/dist/chunk-EHZJ6OXD.js +307 -0
  46. package/dist/chunk-EHZJ6OXD.js.map +7 -0
  47. package/dist/chunk-EJOI2ZGU.js +109 -0
  48. package/dist/chunk-EJOI2ZGU.js.map +7 -0
  49. package/dist/chunk-EKJ2CABV.js +76 -0
  50. package/dist/chunk-EKJ2CABV.js.map +7 -0
  51. package/dist/chunk-EKP32DLN.js +16 -0
  52. package/dist/chunk-EKP32DLN.js.map +7 -0
  53. package/dist/chunk-EOOP6WTC.js +148 -0
  54. package/dist/chunk-EOOP6WTC.js.map +7 -0
  55. package/dist/chunk-ERPMDAO3.js +20 -0
  56. package/dist/chunk-ERPMDAO3.js.map +7 -0
  57. package/dist/chunk-FTJRMUID.js +96 -0
  58. package/dist/chunk-FTJRMUID.js.map +7 -0
  59. package/dist/chunk-FZKLLNDS.js +228 -0
  60. package/dist/chunk-FZKLLNDS.js.map +7 -0
  61. package/dist/chunk-GQCISMAH.js +157 -0
  62. package/dist/chunk-GQCISMAH.js.map +7 -0
  63. package/dist/chunk-IGXX624H.js +55 -0
  64. package/dist/chunk-IGXX624H.js.map +7 -0
  65. package/dist/chunk-IJGF2ETG.js +68 -0
  66. package/dist/chunk-IJGF2ETG.js.map +7 -0
  67. package/dist/chunk-IWYCRLEK.js +220 -0
  68. package/dist/chunk-IWYCRLEK.js.map +7 -0
  69. package/dist/chunk-J7N3DLH6.js +117 -0
  70. package/dist/chunk-J7N3DLH6.js.map +7 -0
  71. package/dist/chunk-JX5UI6RW.js +99 -0
  72. package/dist/chunk-JX5UI6RW.js.map +7 -0
  73. package/dist/chunk-K3BFZ7KG.js +154 -0
  74. package/dist/chunk-K3BFZ7KG.js.map +7 -0
  75. package/dist/chunk-KHJUQFIK.js +51 -0
  76. package/dist/chunk-KHJUQFIK.js.map +7 -0
  77. package/dist/chunk-KRBQLMOP.js +41 -0
  78. package/dist/chunk-KRBQLMOP.js.map +7 -0
  79. package/dist/chunk-KZRFUXGF.js +145 -0
  80. package/dist/chunk-KZRFUXGF.js.map +7 -0
  81. package/dist/chunk-L674RNKQ.js +492 -0
  82. package/dist/chunk-L674RNKQ.js.map +7 -0
  83. package/dist/chunk-N52AHNBH.js +47 -0
  84. package/dist/chunk-N52AHNBH.js.map +7 -0
  85. package/dist/chunk-NIDLJO6F.js +228 -0
  86. package/dist/chunk-NIDLJO6F.js.map +7 -0
  87. package/dist/chunk-NSBPE2FW.js +17 -0
  88. package/dist/chunk-NSBPE2FW.js.map +7 -0
  89. package/dist/chunk-OGVORIFM.js +70 -0
  90. package/dist/chunk-OGVORIFM.js.map +7 -0
  91. package/dist/chunk-OQSQC7VB.js +77 -0
  92. package/dist/chunk-OQSQC7VB.js.map +7 -0
  93. package/dist/chunk-PHLMIZKM.js +153 -0
  94. package/dist/chunk-PHLMIZKM.js.map +7 -0
  95. package/dist/chunk-PQU7GZ7A.js +92 -0
  96. package/dist/chunk-PQU7GZ7A.js.map +7 -0
  97. package/dist/chunk-PXVQLD7S.js +196 -0
  98. package/dist/chunk-PXVQLD7S.js.map +7 -0
  99. package/dist/chunk-QD6X4L4L.js +79 -0
  100. package/dist/chunk-QD6X4L4L.js.map +7 -0
  101. package/dist/chunk-QJQS6TUN.js +44 -0
  102. package/dist/chunk-QJQS6TUN.js.map +7 -0
  103. package/dist/chunk-QJXAULRC.js +191 -0
  104. package/dist/chunk-QJXAULRC.js.map +7 -0
  105. package/dist/chunk-QN34TGD3.js +83 -0
  106. package/dist/chunk-QN34TGD3.js.map +7 -0
  107. package/dist/chunk-R5MFHGHR.js +122 -0
  108. package/dist/chunk-R5MFHGHR.js.map +7 -0
  109. package/dist/chunk-RH7NHVSK.js +16 -0
  110. package/dist/chunk-RH7NHVSK.js.map +7 -0
  111. package/dist/chunk-RJ7BHDLM.js +121 -0
  112. package/dist/chunk-RJ7BHDLM.js.map +7 -0
  113. package/dist/chunk-RQ2TMLKG.js +142 -0
  114. package/dist/chunk-RQ2TMLKG.js.map +7 -0
  115. package/dist/chunk-S56LOTGQ.js +63 -0
  116. package/dist/chunk-S56LOTGQ.js.map +7 -0
  117. package/dist/chunk-UF73WX2J.js +49 -0
  118. package/dist/chunk-UF73WX2J.js.map +7 -0
  119. package/dist/chunk-W53GKIZQ.js +50 -0
  120. package/dist/chunk-W53GKIZQ.js.map +7 -0
  121. package/dist/chunk-WA4MWYRW.js +254 -0
  122. package/dist/chunk-WA4MWYRW.js.map +7 -0
  123. package/dist/chunk-WFULKPEQ.js +269 -0
  124. package/dist/chunk-WFULKPEQ.js.map +7 -0
  125. package/dist/chunk-XC6M4CSW.js +44 -0
  126. package/dist/chunk-XC6M4CSW.js.map +7 -0
  127. package/dist/chunk-XPUEGHXN.js +243 -0
  128. package/dist/chunk-XPUEGHXN.js.map +7 -0
  129. package/dist/chunk-XZXS2W24.js +148 -0
  130. package/dist/chunk-XZXS2W24.js.map +7 -0
  131. package/dist/chunk-YBNW7ARH.js +167 -0
  132. package/dist/chunk-YBNW7ARH.js.map +7 -0
  133. package/dist/chunk-YNIH3KMU.js +121 -0
  134. package/dist/chunk-YNIH3KMU.js.map +7 -0
  135. package/dist/commands/antigravity/backfill.js +135 -0
  136. package/dist/commands/antigravity/backfill.js.map +7 -0
  137. package/dist/commands/auth/create-key.js +48 -33
  138. package/dist/commands/auth/create-key.js.map +7 -1
  139. package/dist/commands/auth/login.js +58 -46
  140. package/dist/commands/auth/login.js.map +7 -1
  141. package/dist/commands/auth/logout.js +28 -13
  142. package/dist/commands/auth/logout.js.map +7 -1
  143. package/dist/commands/auth/revoke-key.js +32 -18
  144. package/dist/commands/auth/revoke-key.js.map +7 -1
  145. package/dist/commands/auth/status.js +40 -22
  146. package/dist/commands/auth/status.js.map +7 -1
  147. package/dist/commands/catalog/index.js +50 -34
  148. package/dist/commands/catalog/index.js.map +7 -1
  149. package/dist/commands/catalog/recommend.js +41 -26
  150. package/dist/commands/catalog/recommend.js.map +7 -1
  151. package/dist/commands/convert.js +72 -54
  152. package/dist/commands/convert.js.map +7 -1
  153. package/dist/commands/converters.js +52 -38
  154. package/dist/commands/converters.js.map +7 -1
  155. package/dist/commands/crons/list.js +50 -24
  156. package/dist/commands/crons/list.js.map +7 -1
  157. package/dist/commands/crons/run.js +72 -47
  158. package/dist/commands/crons/run.js.map +7 -1
  159. package/dist/commands/dashboard.js +45 -24
  160. package/dist/commands/dashboard.js.map +7 -1
  161. package/dist/commands/eval-targets/create.js +51 -39
  162. package/dist/commands/eval-targets/create.js.map +7 -1
  163. package/dist/commands/eval-targets/list.js +52 -35
  164. package/dist/commands/eval-targets/list.js.map +7 -1
  165. package/dist/commands/evals/agent.js +292 -0
  166. package/dist/commands/evals/agent.js.map +7 -0
  167. package/dist/commands/evals/benchmark.js +70 -51
  168. package/dist/commands/evals/benchmark.js.map +7 -1
  169. package/dist/commands/evals/compare.js +90 -78
  170. package/dist/commands/evals/compare.js.map +7 -1
  171. package/dist/commands/evals/create.js +64 -50
  172. package/dist/commands/evals/create.js.map +7 -1
  173. package/dist/commands/evals/optimize-description.js +225 -222
  174. package/dist/commands/evals/optimize-description.js.map +7 -1
  175. package/dist/commands/evals/optimize.js +206 -196
  176. package/dist/commands/evals/optimize.js.map +7 -1
  177. package/dist/commands/evals/run.js +178 -164
  178. package/dist/commands/evals/run.js.map +7 -1
  179. package/dist/commands/gateway/ensure.js +33 -19
  180. package/dist/commands/gateway/ensure.js.map +7 -1
  181. package/dist/commands/hooks/install.js +335 -275
  182. package/dist/commands/hooks/install.js.map +7 -1
  183. package/dist/commands/hooks/run.js +72 -53
  184. package/dist/commands/hooks/run.js.map +7 -1
  185. package/dist/commands/hooks/uninstall.js +117 -94
  186. package/dist/commands/hooks/uninstall.js.map +7 -1
  187. package/dist/commands/import.js +63 -53
  188. package/dist/commands/import.js.map +7 -1
  189. package/dist/commands/instructions/create.js +71 -58
  190. package/dist/commands/instructions/create.js.map +7 -1
  191. package/dist/commands/instructions/delete.js +53 -36
  192. package/dist/commands/instructions/delete.js.map +7 -1
  193. package/dist/commands/instructions/fork.js +33 -19
  194. package/dist/commands/instructions/fork.js.map +7 -1
  195. package/dist/commands/instructions/get.js +66 -49
  196. package/dist/commands/instructions/get.js.map +7 -1
  197. package/dist/commands/instructions/list.js +63 -46
  198. package/dist/commands/instructions/list.js.map +7 -1
  199. package/dist/commands/instructions/promote.js +41 -27
  200. package/dist/commands/instructions/promote.js.map +7 -1
  201. package/dist/commands/instructions/pull.js +37 -21
  202. package/dist/commands/instructions/pull.js.map +7 -1
  203. package/dist/commands/instructions/upstream.js +36 -21
  204. package/dist/commands/instructions/upstream.js.map +7 -1
  205. package/dist/commands/instructions/versions.js +51 -33
  206. package/dist/commands/instructions/versions.js.map +7 -1
  207. package/dist/commands/launcher.js +39 -0
  208. package/dist/commands/launcher.js.map +7 -0
  209. package/dist/commands/org/current.js +74 -68
  210. package/dist/commands/org/current.js.map +7 -1
  211. package/dist/commands/org/list.js +50 -36
  212. package/dist/commands/org/list.js.map +7 -1
  213. package/dist/commands/org/switch.js +69 -51
  214. package/dist/commands/org/switch.js.map +7 -1
  215. package/dist/commands/packs/add-instruction.js +36 -22
  216. package/dist/commands/packs/add-instruction.js.map +7 -1
  217. package/dist/commands/packs/apply.js +38 -24
  218. package/dist/commands/packs/apply.js.map +7 -1
  219. package/dist/commands/packs/create.js +47 -33
  220. package/dist/commands/packs/create.js.map +7 -1
  221. package/dist/commands/packs/fork.js +33 -19
  222. package/dist/commands/packs/fork.js.map +7 -1
  223. package/dist/commands/packs/get.js +54 -35
  224. package/dist/commands/packs/get.js.map +7 -1
  225. package/dist/commands/packs/list.js +64 -47
  226. package/dist/commands/packs/list.js.map +7 -1
  227. package/dist/commands/packs/remove-instruction.js +34 -20
  228. package/dist/commands/packs/remove-instruction.js.map +7 -1
  229. package/dist/commands/proxy/env.js +126 -116
  230. package/dist/commands/proxy/env.js.map +7 -1
  231. package/dist/commands/proxy/logs.js +83 -74
  232. package/dist/commands/proxy/logs.js.map +7 -1
  233. package/dist/commands/proxy/restart.js +34 -36
  234. package/dist/commands/proxy/restart.js.map +7 -1
  235. package/dist/commands/proxy/setup.js +432 -375
  236. package/dist/commands/proxy/setup.js.map +7 -1
  237. package/dist/commands/proxy/start.js +289 -289
  238. package/dist/commands/proxy/start.js.map +7 -1
  239. package/dist/commands/proxy/status.js +74 -64
  240. package/dist/commands/proxy/status.js.map +7 -1
  241. package/dist/commands/proxy/stop.js +81 -75
  242. package/dist/commands/proxy/stop.js.map +7 -1
  243. package/dist/commands/research/backfill.js +58 -0
  244. package/dist/commands/research/backfill.js.map +7 -0
  245. package/dist/commands/research/tail-transcript.js +69 -0
  246. package/dist/commands/research/tail-transcript.js.map +7 -0
  247. package/dist/commands/service/install.js +639 -405
  248. package/dist/commands/service/install.js.map +7 -1
  249. package/dist/commands/service/status.js +178 -111
  250. package/dist/commands/service/status.js.map +7 -1
  251. package/dist/commands/service/uninstall.js +85 -110
  252. package/dist/commands/service/uninstall.js.map +7 -1
  253. package/dist/commands/sessions/analyze.js +46 -25
  254. package/dist/commands/sessions/analyze.js.map +7 -1
  255. package/dist/commands/sessions/end.js +81 -79
  256. package/dist/commands/sessions/end.js.map +7 -1
  257. package/dist/commands/sessions/import.js +44 -27
  258. package/dist/commands/sessions/import.js.map +7 -1
  259. package/dist/commands/sessions/list.js +46 -33
  260. package/dist/commands/sessions/list.js.map +7 -1
  261. package/dist/commands/sessions/start.js +88 -87
  262. package/dist/commands/sessions/start.js.map +7 -1
  263. package/dist/commands/signals/report.js +42 -34
  264. package/dist/commands/signals/report.js.map +7 -1
  265. package/dist/commands/skills/export-approved.js +44 -30
  266. package/dist/commands/skills/export-approved.js.map +7 -1
  267. package/dist/commands/skills/install.js +99 -84
  268. package/dist/commands/skills/install.js.map +7 -1
  269. package/dist/commands/skills/list.js +59 -42
  270. package/dist/commands/skills/list.js.map +7 -1
  271. package/dist/commands/skills/publish.js +95 -78
  272. package/dist/commands/skills/publish.js.map +7 -1
  273. package/dist/commands/skills/search.js +68 -53
  274. package/dist/commands/skills/search.js.map +7 -1
  275. package/dist/commands/skills/update.js +52 -39
  276. package/dist/commands/skills/update.js.map +7 -1
  277. package/dist/commands/suggestions/accept.js +82 -59
  278. package/dist/commands/suggestions/accept.js.map +7 -1
  279. package/dist/commands/suggestions/dismiss.js +44 -26
  280. package/dist/commands/suggestions/dismiss.js.map +7 -1
  281. package/dist/commands/suggestions/list.js +59 -39
  282. package/dist/commands/suggestions/list.js.map +7 -1
  283. package/dist/commands/suggestions/refresh.js +26 -11
  284. package/dist/commands/suggestions/refresh.js.map +7 -1
  285. package/dist/cursor-BGQJ4CWI.js +134 -0
  286. package/dist/cursor-BGQJ4CWI.js.map +7 -0
  287. package/dist/dashboard/Dashboard.js +229 -126
  288. package/dist/dashboard/Dashboard.js.map +7 -1
  289. package/dist/dashboard/data.js +13 -137
  290. package/dist/dashboard/data.js.map +7 -1
  291. package/dist/dashboard/launcher/ActiveJobsList.js +10 -0
  292. package/dist/dashboard/launcher/ActiveJobsList.js.map +7 -0
  293. package/dist/dashboard/launcher/LauncherOverlay.js +14 -0
  294. package/dist/dashboard/launcher/LauncherOverlay.js.map +7 -0
  295. package/dist/dashboard/launcher/NewLaunchForm.js +10 -0
  296. package/dist/dashboard/launcher/NewLaunchForm.js.map +7 -0
  297. package/dist/dashboard/launcher/api.js +14 -0
  298. package/dist/dashboard/launcher/api.js.map +7 -0
  299. package/dist/dashboard/launcher/tool-labels.js +10 -0
  300. package/dist/dashboard/launcher/tool-labels.js.map +7 -0
  301. package/dist/dashboard/launcher/types.js +1 -0
  302. package/dist/dashboard/launcher/types.js.map +7 -0
  303. package/dist/dashboard/launcher/useLaunchJobs.js +9 -0
  304. package/dist/dashboard/launcher/useLaunchJobs.js.map +7 -0
  305. package/dist/dashboard/panels/friction.js +10 -22
  306. package/dist/dashboard/panels/friction.js.map +7 -1
  307. package/dist/dashboard/panels/insights.js +10 -109
  308. package/dist/dashboard/panels/insights.js.map +7 -1
  309. package/dist/dashboard/panels/instructions.js +10 -17
  310. package/dist/dashboard/panels/instructions.js.map +7 -1
  311. package/dist/dashboard/panels/outcomes.js +9 -28
  312. package/dist/dashboard/panels/outcomes.js.map +7 -1
  313. package/dist/dashboard/panels/overview.js +10 -20
  314. package/dist/dashboard/panels/overview.js.map +7 -1
  315. package/dist/dashboard/panels/shared.js +18 -61
  316. package/dist/dashboard/panels/shared.js.map +7 -1
  317. package/dist/dashboard/types.js +23 -26
  318. package/dist/dashboard/types.js.map +7 -1
  319. package/dist/dist-CSUYFYKI.js +52 -0
  320. package/dist/dist-CSUYFYKI.js.map +7 -0
  321. package/dist/index.js +8 -2
  322. package/dist/index.js.map +7 -1
  323. package/dist/lib/active-org-refresh.js +15 -108
  324. package/dist/lib/active-org-refresh.js.map +7 -1
  325. package/dist/lib/active-org.js +15 -95
  326. package/dist/lib/active-org.js.map +7 -1
  327. package/dist/lib/agent-loop.js +44 -0
  328. package/dist/lib/agent-loop.js.map +7 -0
  329. package/dist/lib/antigravity-transcript.js +22 -0
  330. package/dist/lib/antigravity-transcript.js.map +7 -0
  331. package/dist/lib/api-client.js +21 -92
  332. package/dist/lib/api-client.js.map +7 -1
  333. package/dist/lib/auth.js +26 -137
  334. package/dist/lib/auth.js.map +7 -1
  335. package/dist/lib/detect-languages.js +8 -113
  336. package/dist/lib/detect-languages.js.map +7 -1
  337. package/dist/lib/detect-tmux.js +9 -0
  338. package/dist/lib/detect-tmux.js.map +7 -0
  339. package/dist/lib/eval-analyzer.js +9 -89
  340. package/dist/lib/eval-analyzer.js.map +7 -1
  341. package/dist/lib/eval-benchmark.js +12 -92
  342. package/dist/lib/eval-benchmark.js.map +7 -1
  343. package/dist/lib/eval-conversation-handler.js +13 -200
  344. package/dist/lib/eval-conversation-handler.js.map +7 -1
  345. package/dist/lib/eval-executor.js +8 -83
  346. package/dist/lib/eval-executor.js.map +7 -1
  347. package/dist/lib/eval-grader.js +9 -123
  348. package/dist/lib/eval-grader.js.map +7 -1
  349. package/dist/lib/eval-meta-judge.js +9 -116
  350. package/dist/lib/eval-meta-judge.js.map +7 -1
  351. package/dist/lib/eval-trigger-tester.js +11 -96
  352. package/dist/lib/eval-trigger-tester.js.map +7 -1
  353. package/dist/lib/eval-worktree.js +8 -87
  354. package/dist/lib/eval-worktree.js.map +7 -1
  355. package/dist/lib/gateway-entry.js +20 -18
  356. package/dist/lib/gateway-entry.js.map +7 -1
  357. package/dist/lib/gateway-lifecycle.js +22 -97
  358. package/dist/lib/gateway-lifecycle.js.map +7 -1
  359. package/dist/lib/gateway.js +12 -216
  360. package/dist/lib/gateway.js.map +7 -1
  361. package/dist/lib/handlers/cron-close-stale-sessions.js +18 -7
  362. package/dist/lib/handlers/cron-close-stale-sessions.js.map +7 -1
  363. package/dist/lib/handlers/cron-data-integrity-audit.js +21 -15
  364. package/dist/lib/handlers/cron-data-integrity-audit.js.map +7 -1
  365. package/dist/lib/handlers/cron-refresh-skills.js +7 -90
  366. package/dist/lib/handlers/cron-refresh-skills.js.map +7 -1
  367. package/dist/lib/handlers/cron-suggest-instructions.js +14 -158
  368. package/dist/lib/handlers/cron-suggest-instructions.js.map +7 -1
  369. package/dist/lib/handlers/process-announcement.js +11 -0
  370. package/dist/lib/handlers/process-announcement.js.map +7 -0
  371. package/dist/lib/handlers/process-changelog.js +11 -0
  372. package/dist/lib/handlers/process-changelog.js.map +7 -0
  373. package/dist/lib/handlers/process-conversation.js +14 -35
  374. package/dist/lib/handlers/process-conversation.js.map +7 -1
  375. package/dist/lib/handlers/process-eval.js +15 -207
  376. package/dist/lib/handlers/process-eval.js.map +7 -1
  377. package/dist/lib/handlers/process-insights.js +14 -300
  378. package/dist/lib/handlers/process-insights.js.map +7 -1
  379. package/dist/lib/handlers/process-launch.js +16 -41
  380. package/dist/lib/handlers/process-launch.js.map +7 -1
  381. package/dist/lib/handlers/process-run-cleanup.js +13 -0
  382. package/dist/lib/handlers/process-run-cleanup.js.map +7 -0
  383. package/dist/lib/handlers/process-send-message.js +10 -0
  384. package/dist/lib/handlers/process-send-message.js.map +7 -0
  385. package/dist/lib/handlers/process-session-goal.js +11 -74
  386. package/dist/lib/handlers/process-session-goal.js.map +7 -1
  387. package/dist/lib/hooks-config.js +52 -544
  388. package/dist/lib/hooks-config.js.map +7 -1
  389. package/dist/lib/insights-prompts.js +12 -145
  390. package/dist/lib/insights-prompts.js.map +7 -1
  391. package/dist/lib/job-helpers.js +1 -0
  392. package/dist/lib/job-helpers.js.map +7 -0
  393. package/dist/lib/llm-client.js +16 -274
  394. package/dist/lib/llm-client.js.map +7 -1
  395. package/dist/lib/manual-tasks.js +22 -0
  396. package/dist/lib/manual-tasks.js.map +7 -0
  397. package/dist/lib/output.js +12 -36
  398. package/dist/lib/output.js.map +7 -1
  399. package/dist/lib/permanent-job-error.js +10 -23
  400. package/dist/lib/permanent-job-error.js.map +7 -1
  401. package/dist/lib/provider-aggregator.js +57 -55
  402. package/dist/lib/provider-aggregator.js.map +7 -1
  403. package/dist/lib/research-client.js +12 -0
  404. package/dist/lib/research-client.js.map +7 -0
  405. package/dist/lib/skills-loader.js +8 -51
  406. package/dist/lib/skills-loader.js.map +7 -1
  407. package/dist/lib/statusline-shim.js +16 -0
  408. package/dist/lib/statusline-shim.js.map +7 -0
  409. package/dist/lib/terminal-target-heartbeat.js +15 -0
  410. package/dist/lib/terminal-target-heartbeat.js.map +7 -0
  411. package/dist/lib/tmux.js +16 -0
  412. package/dist/lib/tmux.js.map +7 -0
  413. package/dist/lib/transcript-rate-limit-watcher.js +22 -0
  414. package/dist/lib/transcript-rate-limit-watcher.js.map +7 -0
  415. package/dist/lib/types.js +8 -7
  416. package/dist/lib/types.js.map +7 -1
  417. package/dist/lib/version-check.js +10 -106
  418. package/dist/lib/version-check.js.map +7 -1
  419. package/dist/lib/which.js +8 -0
  420. package/dist/lib/which.js.map +7 -0
  421. package/dist/lib/worktree.js +17 -0
  422. package/dist/lib/worktree.js.map +7 -0
  423. package/dist/opencode-IQ7X5YMJ.js +190 -0
  424. package/dist/opencode-IQ7X5YMJ.js.map +7 -0
  425. package/oclif.manifest.json +299 -66
  426. package/package.json +26 -10
  427. package/dist/base-command.d.ts +0 -12
  428. package/dist/base-command.d.ts.map +0 -1
  429. package/dist/commands/auth/create-key.d.ts +0 -11
  430. package/dist/commands/auth/create-key.d.ts.map +0 -1
  431. package/dist/commands/auth/login.d.ts +0 -11
  432. package/dist/commands/auth/login.d.ts.map +0 -1
  433. package/dist/commands/auth/logout.d.ts +0 -7
  434. package/dist/commands/auth/logout.d.ts.map +0 -1
  435. package/dist/commands/auth/revoke-key.d.ts +0 -10
  436. package/dist/commands/auth/revoke-key.d.ts.map +0 -1
  437. package/dist/commands/auth/status.d.ts +0 -7
  438. package/dist/commands/auth/status.d.ts.map +0 -1
  439. package/dist/commands/catalog/index.d.ts +0 -11
  440. package/dist/commands/catalog/index.d.ts.map +0 -1
  441. package/dist/commands/catalog/recommend.d.ts +0 -9
  442. package/dist/commands/catalog/recommend.d.ts.map +0 -1
  443. package/dist/commands/convert.d.ts +0 -15
  444. package/dist/commands/convert.d.ts.map +0 -1
  445. package/dist/commands/converters.d.ts +0 -12
  446. package/dist/commands/converters.d.ts.map +0 -1
  447. package/dist/commands/crons/list.d.ts +0 -7
  448. package/dist/commands/crons/list.d.ts.map +0 -1
  449. package/dist/commands/crons/run.d.ts +0 -13
  450. package/dist/commands/crons/run.d.ts.map +0 -1
  451. package/dist/commands/dashboard.d.ts +0 -10
  452. package/dist/commands/dashboard.d.ts.map +0 -1
  453. package/dist/commands/eval-targets/create.d.ts +0 -14
  454. package/dist/commands/eval-targets/create.d.ts.map +0 -1
  455. package/dist/commands/eval-targets/list.d.ts +0 -10
  456. package/dist/commands/eval-targets/list.d.ts.map +0 -1
  457. package/dist/commands/evals/benchmark.d.ts +0 -13
  458. package/dist/commands/evals/benchmark.d.ts.map +0 -1
  459. package/dist/commands/evals/compare.d.ts +0 -15
  460. package/dist/commands/evals/compare.d.ts.map +0 -1
  461. package/dist/commands/evals/create.d.ts +0 -17
  462. package/dist/commands/evals/create.d.ts.map +0 -1
  463. package/dist/commands/evals/listen.d.ts +0 -37
  464. package/dist/commands/evals/listen.d.ts.map +0 -1
  465. package/dist/commands/evals/listen.js +0 -188
  466. package/dist/commands/evals/listen.js.map +0 -1
  467. package/dist/commands/evals/listen.test.d.ts +0 -2
  468. package/dist/commands/evals/listen.test.d.ts.map +0 -1
  469. package/dist/commands/evals/listen.test.js +0 -48
  470. package/dist/commands/evals/listen.test.js.map +0 -1
  471. package/dist/commands/evals/optimize-description.d.ts +0 -22
  472. package/dist/commands/evals/optimize-description.d.ts.map +0 -1
  473. package/dist/commands/evals/optimize.d.ts +0 -22
  474. package/dist/commands/evals/optimize.d.ts.map +0 -1
  475. package/dist/commands/evals/run.d.ts +0 -21
  476. package/dist/commands/evals/run.d.ts.map +0 -1
  477. package/dist/commands/gateway/ensure.d.ts +0 -7
  478. package/dist/commands/gateway/ensure.d.ts.map +0 -1
  479. package/dist/commands/hooks/install.d.ts +0 -16
  480. package/dist/commands/hooks/install.d.ts.map +0 -1
  481. package/dist/commands/hooks/run.d.ts +0 -11
  482. package/dist/commands/hooks/run.d.ts.map +0 -1
  483. package/dist/commands/hooks/uninstall.d.ts +0 -7
  484. package/dist/commands/hooks/uninstall.d.ts.map +0 -1
  485. package/dist/commands/import.d.ts +0 -17
  486. package/dist/commands/import.d.ts.map +0 -1
  487. package/dist/commands/instructions/create.d.ts +0 -17
  488. package/dist/commands/instructions/create.d.ts.map +0 -1
  489. package/dist/commands/instructions/delete.d.ts +0 -13
  490. package/dist/commands/instructions/delete.d.ts.map +0 -1
  491. package/dist/commands/instructions/fork.d.ts +0 -10
  492. package/dist/commands/instructions/fork.d.ts.map +0 -1
  493. package/dist/commands/instructions/get.d.ts +0 -15
  494. package/dist/commands/instructions/get.d.ts.map +0 -1
  495. package/dist/commands/instructions/list.d.ts +0 -12
  496. package/dist/commands/instructions/list.d.ts.map +0 -1
  497. package/dist/commands/instructions/promote.d.ts +0 -14
  498. package/dist/commands/instructions/promote.d.ts.map +0 -1
  499. package/dist/commands/instructions/pull.d.ts +0 -9
  500. package/dist/commands/instructions/pull.d.ts.map +0 -1
  501. package/dist/commands/instructions/upstream.d.ts +0 -9
  502. package/dist/commands/instructions/upstream.d.ts.map +0 -1
  503. package/dist/commands/instructions/versions.d.ts +0 -12
  504. package/dist/commands/instructions/versions.d.ts.map +0 -1
  505. package/dist/commands/org/current.d.ts +0 -7
  506. package/dist/commands/org/current.d.ts.map +0 -1
  507. package/dist/commands/org/list.d.ts +0 -7
  508. package/dist/commands/org/list.d.ts.map +0 -1
  509. package/dist/commands/org/switch.d.ts +0 -13
  510. package/dist/commands/org/switch.d.ts.map +0 -1
  511. package/dist/commands/packs/add-instruction.d.ts +0 -11
  512. package/dist/commands/packs/add-instruction.d.ts.map +0 -1
  513. package/dist/commands/packs/apply.d.ts +0 -13
  514. package/dist/commands/packs/apply.d.ts.map +0 -1
  515. package/dist/commands/packs/create.d.ts +0 -13
  516. package/dist/commands/packs/create.d.ts.map +0 -1
  517. package/dist/commands/packs/fork.d.ts +0 -10
  518. package/dist/commands/packs/fork.d.ts.map +0 -1
  519. package/dist/commands/packs/get.d.ts +0 -10
  520. package/dist/commands/packs/get.d.ts.map +0 -1
  521. package/dist/commands/packs/list.d.ts +0 -22
  522. package/dist/commands/packs/list.d.ts.map +0 -1
  523. package/dist/commands/packs/remove-instruction.d.ts +0 -11
  524. package/dist/commands/packs/remove-instruction.d.ts.map +0 -1
  525. package/dist/commands/proxy/env.d.ts +0 -14
  526. package/dist/commands/proxy/env.d.ts.map +0 -1
  527. package/dist/commands/proxy/logs.d.ts +0 -11
  528. package/dist/commands/proxy/logs.d.ts.map +0 -1
  529. package/dist/commands/proxy/restart.d.ts +0 -11
  530. package/dist/commands/proxy/restart.d.ts.map +0 -1
  531. package/dist/commands/proxy/setup.d.ts +0 -23
  532. package/dist/commands/proxy/setup.d.ts.map +0 -1
  533. package/dist/commands/proxy/start.d.ts +0 -17
  534. package/dist/commands/proxy/start.d.ts.map +0 -1
  535. package/dist/commands/proxy/status.d.ts +0 -7
  536. package/dist/commands/proxy/status.d.ts.map +0 -1
  537. package/dist/commands/proxy/stop.d.ts +0 -8
  538. package/dist/commands/proxy/stop.d.ts.map +0 -1
  539. package/dist/commands/service/install.d.ts +0 -33
  540. package/dist/commands/service/install.d.ts.map +0 -1
  541. package/dist/commands/service/install.test.d.ts +0 -2
  542. package/dist/commands/service/install.test.d.ts.map +0 -1
  543. package/dist/commands/service/install.test.js +0 -345
  544. package/dist/commands/service/install.test.js.map +0 -1
  545. package/dist/commands/service/status.d.ts +0 -6
  546. package/dist/commands/service/status.d.ts.map +0 -1
  547. package/dist/commands/service/uninstall.d.ts +0 -6
  548. package/dist/commands/service/uninstall.d.ts.map +0 -1
  549. package/dist/commands/sessions/analyze.d.ts +0 -10
  550. package/dist/commands/sessions/analyze.d.ts.map +0 -1
  551. package/dist/commands/sessions/end.d.ts +0 -9
  552. package/dist/commands/sessions/end.d.ts.map +0 -1
  553. package/dist/commands/sessions/import.d.ts +0 -13
  554. package/dist/commands/sessions/import.d.ts.map +0 -1
  555. package/dist/commands/sessions/list.d.ts +0 -11
  556. package/dist/commands/sessions/list.d.ts.map +0 -1
  557. package/dist/commands/sessions/start.d.ts +0 -11
  558. package/dist/commands/sessions/start.d.ts.map +0 -1
  559. package/dist/commands/signals/report.d.ts +0 -10
  560. package/dist/commands/signals/report.d.ts.map +0 -1
  561. package/dist/commands/signals/report.test.d.ts +0 -2
  562. package/dist/commands/signals/report.test.d.ts.map +0 -1
  563. package/dist/commands/signals/report.test.js +0 -65
  564. package/dist/commands/signals/report.test.js.map +0 -1
  565. package/dist/commands/skills/export-approved.d.ts +0 -10
  566. package/dist/commands/skills/export-approved.d.ts.map +0 -1
  567. package/dist/commands/skills/install.d.ts +0 -15
  568. package/dist/commands/skills/install.d.ts.map +0 -1
  569. package/dist/commands/skills/list.d.ts +0 -11
  570. package/dist/commands/skills/list.d.ts.map +0 -1
  571. package/dist/commands/skills/publish.d.ts +0 -17
  572. package/dist/commands/skills/publish.d.ts.map +0 -1
  573. package/dist/commands/skills/search.d.ts +0 -17
  574. package/dist/commands/skills/search.d.ts.map +0 -1
  575. package/dist/commands/skills/update.d.ts +0 -10
  576. package/dist/commands/skills/update.d.ts.map +0 -1
  577. package/dist/commands/suggestions/accept.d.ts +0 -16
  578. package/dist/commands/suggestions/accept.d.ts.map +0 -1
  579. package/dist/commands/suggestions/accept.test.d.ts +0 -2
  580. package/dist/commands/suggestions/accept.test.d.ts.map +0 -1
  581. package/dist/commands/suggestions/accept.test.js +0 -52
  582. package/dist/commands/suggestions/accept.test.js.map +0 -1
  583. package/dist/commands/suggestions/dismiss.d.ts +0 -10
  584. package/dist/commands/suggestions/dismiss.d.ts.map +0 -1
  585. package/dist/commands/suggestions/list.d.ts +0 -10
  586. package/dist/commands/suggestions/list.d.ts.map +0 -1
  587. package/dist/commands/suggestions/refresh.d.ts +0 -7
  588. package/dist/commands/suggestions/refresh.d.ts.map +0 -1
  589. package/dist/dashboard/Dashboard.d.ts +0 -3
  590. package/dist/dashboard/Dashboard.d.ts.map +0 -1
  591. package/dist/dashboard/data.d.ts +0 -11
  592. package/dist/dashboard/data.d.ts.map +0 -1
  593. package/dist/dashboard/panels/friction.d.ts +0 -7
  594. package/dist/dashboard/panels/friction.d.ts.map +0 -1
  595. package/dist/dashboard/panels/insights.d.ts +0 -8
  596. package/dist/dashboard/panels/insights.d.ts.map +0 -1
  597. package/dist/dashboard/panels/instructions.d.ts +0 -9
  598. package/dist/dashboard/panels/instructions.d.ts.map +0 -1
  599. package/dist/dashboard/panels/outcomes.d.ts +0 -7
  600. package/dist/dashboard/panels/outcomes.d.ts.map +0 -1
  601. package/dist/dashboard/panels/overview.d.ts +0 -8
  602. package/dist/dashboard/panels/overview.d.ts.map +0 -1
  603. package/dist/dashboard/panels/shared.d.ts +0 -17
  604. package/dist/dashboard/panels/shared.d.ts.map +0 -1
  605. package/dist/dashboard/types.d.ts +0 -80
  606. package/dist/dashboard/types.d.ts.map +0 -1
  607. package/dist/index.d.ts +0 -2
  608. package/dist/index.d.ts.map +0 -1
  609. package/dist/lib/active-org-refresh.d.ts +0 -22
  610. package/dist/lib/active-org-refresh.d.ts.map +0 -1
  611. package/dist/lib/active-org-refresh.test.d.ts +0 -2
  612. package/dist/lib/active-org-refresh.test.d.ts.map +0 -1
  613. package/dist/lib/active-org-refresh.test.js +0 -190
  614. package/dist/lib/active-org-refresh.test.js.map +0 -1
  615. package/dist/lib/active-org.d.ts +0 -43
  616. package/dist/lib/active-org.d.ts.map +0 -1
  617. package/dist/lib/active-org.test.d.ts +0 -2
  618. package/dist/lib/active-org.test.d.ts.map +0 -1
  619. package/dist/lib/active-org.test.js +0 -147
  620. package/dist/lib/active-org.test.js.map +0 -1
  621. package/dist/lib/api-client.d.ts +0 -17
  622. package/dist/lib/api-client.d.ts.map +0 -1
  623. package/dist/lib/api-client.test.d.ts +0 -2
  624. package/dist/lib/api-client.test.d.ts.map +0 -1
  625. package/dist/lib/api-client.test.js +0 -161
  626. package/dist/lib/api-client.test.js.map +0 -1
  627. package/dist/lib/auth.d.ts +0 -27
  628. package/dist/lib/auth.d.ts.map +0 -1
  629. package/dist/lib/auth.test.d.ts +0 -2
  630. package/dist/lib/auth.test.d.ts.map +0 -1
  631. package/dist/lib/auth.test.js +0 -110
  632. package/dist/lib/auth.test.js.map +0 -1
  633. package/dist/lib/cron-registry.d.ts +0 -47
  634. package/dist/lib/cron-registry.d.ts.map +0 -1
  635. package/dist/lib/cron-registry.js +0 -102
  636. package/dist/lib/cron-registry.js.map +0 -1
  637. package/dist/lib/cron-registry.test.d.ts +0 -2
  638. package/dist/lib/cron-registry.test.d.ts.map +0 -1
  639. package/dist/lib/cron-registry.test.js +0 -136
  640. package/dist/lib/cron-registry.test.js.map +0 -1
  641. package/dist/lib/cron-runner.d.ts +0 -16
  642. package/dist/lib/cron-runner.d.ts.map +0 -1
  643. package/dist/lib/cron-runner.js +0 -68
  644. package/dist/lib/cron-runner.js.map +0 -1
  645. package/dist/lib/detect-languages.d.ts +0 -7
  646. package/dist/lib/detect-languages.d.ts.map +0 -1
  647. package/dist/lib/detect-languages.test.d.ts +0 -2
  648. package/dist/lib/detect-languages.test.d.ts.map +0 -1
  649. package/dist/lib/detect-languages.test.js +0 -29
  650. package/dist/lib/detect-languages.test.js.map +0 -1
  651. package/dist/lib/eval-analyzer.d.ts +0 -23
  652. package/dist/lib/eval-analyzer.d.ts.map +0 -1
  653. package/dist/lib/eval-benchmark.d.ts +0 -17
  654. package/dist/lib/eval-benchmark.d.ts.map +0 -1
  655. package/dist/lib/eval-conversation-handler.d.ts +0 -9
  656. package/dist/lib/eval-conversation-handler.d.ts.map +0 -1
  657. package/dist/lib/eval-executor.d.ts +0 -21
  658. package/dist/lib/eval-executor.d.ts.map +0 -1
  659. package/dist/lib/eval-executor.test.d.ts +0 -2
  660. package/dist/lib/eval-executor.test.d.ts.map +0 -1
  661. package/dist/lib/eval-executor.test.js +0 -8
  662. package/dist/lib/eval-executor.test.js.map +0 -1
  663. package/dist/lib/eval-grader.d.ts +0 -38
  664. package/dist/lib/eval-grader.d.ts.map +0 -1
  665. package/dist/lib/eval-grader.test.d.ts +0 -2
  666. package/dist/lib/eval-grader.test.d.ts.map +0 -1
  667. package/dist/lib/eval-grader.test.js +0 -8
  668. package/dist/lib/eval-grader.test.js.map +0 -1
  669. package/dist/lib/eval-meta-judge.d.ts +0 -28
  670. package/dist/lib/eval-meta-judge.d.ts.map +0 -1
  671. package/dist/lib/eval-trigger-tester.d.ts +0 -19
  672. package/dist/lib/eval-trigger-tester.d.ts.map +0 -1
  673. package/dist/lib/eval-worktree.d.ts +0 -11
  674. package/dist/lib/eval-worktree.d.ts.map +0 -1
  675. package/dist/lib/eval-worktree.test.d.ts +0 -2
  676. package/dist/lib/eval-worktree.test.d.ts.map +0 -1
  677. package/dist/lib/eval-worktree.test.js +0 -68
  678. package/dist/lib/eval-worktree.test.js.map +0 -1
  679. package/dist/lib/gateway-entry.d.ts +0 -3
  680. package/dist/lib/gateway-entry.d.ts.map +0 -1
  681. package/dist/lib/gateway-lifecycle.d.ts +0 -9
  682. package/dist/lib/gateway-lifecycle.d.ts.map +0 -1
  683. package/dist/lib/gateway.d.ts +0 -11
  684. package/dist/lib/gateway.d.ts.map +0 -1
  685. package/dist/lib/graphile-worker-runner.d.ts +0 -124
  686. package/dist/lib/graphile-worker-runner.d.ts.map +0 -1
  687. package/dist/lib/graphile-worker-runner.js +0 -530
  688. package/dist/lib/graphile-worker-runner.js.map +0 -1
  689. package/dist/lib/graphile-worker-runner.test.d.ts +0 -2
  690. package/dist/lib/graphile-worker-runner.test.d.ts.map +0 -1
  691. package/dist/lib/graphile-worker-runner.test.js +0 -153
  692. package/dist/lib/graphile-worker-runner.test.js.map +0 -1
  693. package/dist/lib/handlers/cron-close-stale-sessions.d.ts +0 -3
  694. package/dist/lib/handlers/cron-close-stale-sessions.d.ts.map +0 -1
  695. package/dist/lib/handlers/cron-data-integrity-audit.d.ts +0 -3
  696. package/dist/lib/handlers/cron-data-integrity-audit.d.ts.map +0 -1
  697. package/dist/lib/handlers/cron-refresh-skills.d.ts +0 -3
  698. package/dist/lib/handlers/cron-refresh-skills.d.ts.map +0 -1
  699. package/dist/lib/handlers/cron-refresh-skills.test.d.ts +0 -2
  700. package/dist/lib/handlers/cron-refresh-skills.test.d.ts.map +0 -1
  701. package/dist/lib/handlers/cron-refresh-skills.test.js +0 -114
  702. package/dist/lib/handlers/cron-refresh-skills.test.js.map +0 -1
  703. package/dist/lib/handlers/cron-regenerate-insights.d.ts +0 -3
  704. package/dist/lib/handlers/cron-regenerate-insights.d.ts.map +0 -1
  705. package/dist/lib/handlers/cron-regenerate-insights.js +0 -6
  706. package/dist/lib/handlers/cron-regenerate-insights.js.map +0 -1
  707. package/dist/lib/handlers/cron-suggest-instructions.d.ts +0 -3
  708. package/dist/lib/handlers/cron-suggest-instructions.d.ts.map +0 -1
  709. package/dist/lib/handlers/cron-suggest-instructions.test.d.ts +0 -2
  710. package/dist/lib/handlers/cron-suggest-instructions.test.d.ts.map +0 -1
  711. package/dist/lib/handlers/cron-suggest-instructions.test.js +0 -80
  712. package/dist/lib/handlers/cron-suggest-instructions.test.js.map +0 -1
  713. package/dist/lib/handlers/process-conversation.d.ts +0 -35
  714. package/dist/lib/handlers/process-conversation.d.ts.map +0 -1
  715. package/dist/lib/handlers/process-eval.d.ts +0 -32
  716. package/dist/lib/handlers/process-eval.d.ts.map +0 -1
  717. package/dist/lib/handlers/process-insights.d.ts +0 -39
  718. package/dist/lib/handlers/process-insights.d.ts.map +0 -1
  719. package/dist/lib/handlers/process-launch.d.ts +0 -29
  720. package/dist/lib/handlers/process-launch.d.ts.map +0 -1
  721. package/dist/lib/handlers/process-session-goal.d.ts +0 -29
  722. package/dist/lib/handlers/process-session-goal.d.ts.map +0 -1
  723. package/dist/lib/handlers/process-session-goal.test.d.ts +0 -2
  724. package/dist/lib/handlers/process-session-goal.test.d.ts.map +0 -1
  725. package/dist/lib/handlers/process-session-goal.test.js +0 -134
  726. package/dist/lib/handlers/process-session-goal.test.js.map +0 -1
  727. package/dist/lib/hooks-config.d.ts +0 -119
  728. package/dist/lib/hooks-config.d.ts.map +0 -1
  729. package/dist/lib/hooks-config.test.d.ts +0 -2
  730. package/dist/lib/hooks-config.test.d.ts.map +0 -1
  731. package/dist/lib/hooks-config.test.js +0 -231
  732. package/dist/lib/hooks-config.test.js.map +0 -1
  733. package/dist/lib/insights-prompts.d.ts +0 -13
  734. package/dist/lib/insights-prompts.d.ts.map +0 -1
  735. package/dist/lib/llm-client.d.ts +0 -26
  736. package/dist/lib/llm-client.d.ts.map +0 -1
  737. package/dist/lib/llm-client.test.d.ts +0 -2
  738. package/dist/lib/llm-client.test.d.ts.map +0 -1
  739. package/dist/lib/llm-client.test.js +0 -62
  740. package/dist/lib/llm-client.test.js.map +0 -1
  741. package/dist/lib/mirror-writer-db.d.ts +0 -12
  742. package/dist/lib/mirror-writer-db.d.ts.map +0 -1
  743. package/dist/lib/mirror-writer-db.js +0 -51
  744. package/dist/lib/mirror-writer-db.js.map +0 -1
  745. package/dist/lib/mirror-writer.d.ts +0 -35
  746. package/dist/lib/mirror-writer.d.ts.map +0 -1
  747. package/dist/lib/mirror-writer.js +0 -27
  748. package/dist/lib/mirror-writer.js.map +0 -1
  749. package/dist/lib/mirror-writer.test.d.ts +0 -2
  750. package/dist/lib/mirror-writer.test.d.ts.map +0 -1
  751. package/dist/lib/mirror-writer.test.js +0 -47
  752. package/dist/lib/mirror-writer.test.js.map +0 -1
  753. package/dist/lib/output.d.ts +0 -4
  754. package/dist/lib/output.d.ts.map +0 -1
  755. package/dist/lib/output.test.d.ts +0 -2
  756. package/dist/lib/output.test.d.ts.map +0 -1
  757. package/dist/lib/output.test.js +0 -71
  758. package/dist/lib/output.test.js.map +0 -1
  759. package/dist/lib/permanent-job-error.d.ts +0 -17
  760. package/dist/lib/permanent-job-error.d.ts.map +0 -1
  761. package/dist/lib/permanent-job-error.test.d.ts +0 -2
  762. package/dist/lib/permanent-job-error.test.d.ts.map +0 -1
  763. package/dist/lib/permanent-job-error.test.js +0 -29
  764. package/dist/lib/permanent-job-error.test.js.map +0 -1
  765. package/dist/lib/provider-aggregator.d.ts +0 -24
  766. package/dist/lib/provider-aggregator.d.ts.map +0 -1
  767. package/dist/lib/provider-aggregator.test.d.ts +0 -2
  768. package/dist/lib/provider-aggregator.test.d.ts.map +0 -1
  769. package/dist/lib/provider-aggregator.test.js +0 -103
  770. package/dist/lib/provider-aggregator.test.js.map +0 -1
  771. package/dist/lib/skills-loader.d.ts +0 -6
  772. package/dist/lib/skills-loader.d.ts.map +0 -1
  773. package/dist/lib/types.d.ts +0 -48
  774. package/dist/lib/types.d.ts.map +0 -1
  775. package/dist/lib/version-check.d.ts +0 -11
  776. package/dist/lib/version-check.d.ts.map +0 -1
  777. package/dist/test-helpers.d.ts +0 -58
  778. package/dist/test-helpers.d.ts.map +0 -1
  779. package/dist/test-helpers.js +0 -58
  780. package/dist/test-helpers.js.map +0 -1
@@ -1,305 +1,485 @@
1
- import { Flags } from '@oclif/core';
2
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
- import { execSync, execFileSync } from 'node:child_process';
4
- import { homedir } from 'node:os';
5
- import { dirname, join } from 'node:path';
6
- import { BaseCommand } from '../../base-command.js';
7
- import { bootstrapActiveOrg } from '../../lib/active-org-refresh.js';
8
- // Only these env vars are written to the plist — never leak unrelated secrets
9
- const ALLOWED_ENV_VARS = new Set([
10
- 'SUPABASE_URL',
11
- 'SUPABASE_ANON_KEY',
12
- 'SUPABASE_SERVICE_ROLE_KEY',
13
- 'DATABASE_URL',
14
- 'RULEMETRIC_API_URL',
15
- 'RULEMETRIC_API_KEY',
16
- 'RULEMETRIC_ACCESS_TOKEN',
17
- // Recipient for the weekly cron_data_integrity_audit notification.
18
- // Without one of these, the audit cron runs but nobody is notified —
19
- // see cron-data-integrity-audit.ts (defaults: NOTIFY_USER_ID then USER_ID).
20
- 'RULEMETRIC_AUDIT_NOTIFY_USER_ID',
21
- 'RULEMETRIC_USER_ID',
1
+ import {
2
+ detectTmux
3
+ } from "../../chunk-BO76WKJR.js";
4
+ import "../../chunk-KRBQLMOP.js";
5
+ import {
6
+ BaseCommand
7
+ } from "../../chunk-S56LOTGQ.js";
8
+ import "../../chunk-OGVORIFM.js";
9
+ import {
10
+ bootstrapActiveOrg
11
+ } from "../../chunk-2AM54TUK.js";
12
+ import "../../chunk-EJOI2ZGU.js";
13
+ import "../../chunk-KZRFUXGF.js";
14
+ import "../../chunk-EKJ2CABV.js";
15
+ import "../../chunk-NSBPE2FW.js";
16
+
17
+ // src/commands/service/install.ts
18
+ import { Flags } from "@oclif/core";
19
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
20
+ import { execSync, execFileSync, spawnSync } from "node:child_process";
21
+ import { homedir } from "node:os";
22
+ import { dirname, join } from "node:path";
23
+ var ALLOWED_ENV_VARS = /* @__PURE__ */ new Set([
24
+ "SUPABASE_URL",
25
+ "SUPABASE_ANON_KEY",
26
+ "SUPABASE_SERVICE_ROLE_KEY",
27
+ // Enables local HS256 JWT verification in the API's authMiddleware —
28
+ // without it every authed request pays a /auth/v1/user network round-trip
29
+ // (measured p50 ~244ms) to Supabase.
30
+ "SUPABASE_JWT_SECRET",
31
+ "DATABASE_URL",
32
+ "RULEMETRIC_API_URL",
33
+ "RULEMETRIC_API_KEY",
34
+ "RULEMETRIC_ACCESS_TOKEN",
35
+ // Recipient for the weekly cron_data_integrity_audit notification.
36
+ // Without one of these, the audit cron runs but nobody is notified —
37
+ // see cron-data-integrity-audit.ts (defaults: NOTIFY_USER_ID then USER_ID).
38
+ "RULEMETRIC_AUDIT_NOTIFY_USER_ID",
39
+ "RULEMETRIC_USER_ID",
40
+ // cron_refresh_skills needs an authenticated GitHub API budget (5000
41
+ // req/hr) — without it the handler skips and the skills registry goes
42
+ // stale, which makes cron_suggest_instructions mark every suggestion
43
+ // stale on each nightly run.
44
+ "GITHUB_TOKEN",
45
+ // Pool-tuning overrides so the plist generators (buildPlist / buildWorkerPlist)
46
+ // actually honor a user-set value instead of always falling back to the pinned
47
+ // default — without these in the allow-list the `envVars.PG_* ?? '<default>'`
48
+ // escape hatch was silently dead. Pool-exhaustion RCA 2026-06-21.
49
+ "PG_POOL_MAX",
50
+ "PG_IDLE_TIMEOUT",
51
+ "PG_STATEMENT_TIMEOUT_MS"
22
52
  ]);
23
- const PLIST_LABEL = 'com.rulemetric.api';
24
- const PLIST_PATH = join(homedir(), 'Library', 'LaunchAgents', `${PLIST_LABEL}.plist`);
25
- const WORKER_PLIST_LABEL = 'com.rulemetric.worker';
26
- const WORKER_PLIST_PATH = join(homedir(), 'Library', 'LaunchAgents', `${WORKER_PLIST_LABEL}.plist`);
27
- // Daily kickstart agent — closes the graphile-LISTEN-wedge class observed
28
- // at ~25h uptime by ensuring the worker is restarted clean every day at
29
- // 04:00 local time. Sibling agent, separate launchd job, depends on
30
- // WORKER_PLIST_LABEL existing. Without this, end users would hit the
31
- // same wedge every ~day and have to debug it manually.
32
- const WORKER_RESTART_PLIST_LABEL = 'com.rulemetric.worker.restart';
33
- const WORKER_RESTART_PLIST_PATH = join(homedir(), 'Library', 'LaunchAgents', `${WORKER_RESTART_PLIST_LABEL}.plist`);
34
- const CONFIG_DIR = join(homedir(), '.config', 'rulemetric');
35
- const LOG_DIR = join(CONFIG_DIR, 'logs');
36
- export default class ServiceInstall extends BaseCommand {
37
- static description = 'Install RuleMetric API as a persistent macOS service (launchd)';
38
- static examples = [
39
- '<%= config.bin %> service install',
40
- '<%= config.bin %> service install --port 3000',
41
- ];
42
- static flags = {
43
- port: Flags.integer({
44
- char: 'p',
45
- default: 3000,
46
- description: 'API server port',
47
- }),
48
- force: Flags.boolean({
49
- char: 'f',
50
- default: false,
51
- description: 'Overwrite existing service configuration',
52
- }),
53
- };
54
- async run() {
55
- const { flags } = await this.parse(ServiceInstall);
56
- const port = flags.port;
57
- // macOS only
58
- if (process.platform !== 'darwin') {
59
- this.error('Service install is currently macOS-only (launchd). For Linux, use systemd manually.');
60
- }
61
- // Check for existing service
62
- if (existsSync(PLIST_PATH) && !flags.force) {
63
- this.log(`Service already installed at ${PLIST_PATH}`);
64
- this.log('Use --force to overwrite, or run: rulemetric service status');
65
- return;
66
- }
67
- // Check for port conflict
68
- try {
69
- const res = await fetch(`http://localhost:${port}/health`);
70
- if (res.ok && !flags.force) {
71
- this.warn(`Port ${port} is already in use (API may be running via start.sh).`);
72
- this.warn('Stop it first with scripts/stop.sh, or use --force to overwrite.');
73
- return;
74
- }
75
- }
76
- catch {
77
- // Port free — good
78
- }
79
- // Find project root (where the API package lives)
80
- const projectRoot = this.findProjectRoot();
81
- if (!projectRoot) {
82
- this.error('Could not find RuleMetric project root. Run this command from within the momento-mori repo, or set RULEMETRIC_PROJECT_ROOT.');
83
- }
84
- // Verify .env.local exists (needed for Supabase credentials)
85
- const envLocal = join(projectRoot, '.env.local');
86
- if (!existsSync(envLocal)) {
87
- this.error(`.env.local not found at ${envLocal}. The API needs Supabase credentials to start.`);
88
- }
89
- // Load env vars from .env.local and ~/.config/rulemetric/env
90
- const envVars = this.loadEnvVars(projectRoot);
91
- // Find node and pnpm paths
92
- const nodePath = this.findBinary('node');
93
- const pnpmPath = this.findBinary('pnpm');
94
- if (!nodePath || !pnpmPath) {
95
- this.error('Could not find node or pnpm. Ensure they are in your PATH.');
96
- }
97
- // Build the plist
98
- const plist = this.buildPlist({
99
- port,
100
- projectRoot,
101
- nodePath,
102
- pnpmPath,
103
- envVars,
104
- });
105
- // Create directories
106
- mkdirSync(join(homedir(), 'Library', 'LaunchAgents'), { recursive: true });
107
- mkdirSync(LOG_DIR, { recursive: true });
108
- // Unload existing service if running
109
- const uid = execSync('id -u', { encoding: 'utf-8' }).trim();
110
- try {
111
- execFileSync('launchctl', ['bootout', `gui/${uid}`, PLIST_PATH], { encoding: 'utf-8' });
112
- this.log('[OK] Unloaded existing service');
113
- }
114
- catch (err) {
115
- const msg = err.message || '';
116
- // Expected errors when service isn't loaded
117
- if (!msg.includes('Could not find specified service') && !msg.includes('No such process') && !msg.includes('3: No such process')) {
118
- this.warn(`Could not unload existing service: ${msg.trim()}`);
119
- }
120
- }
121
- // Write plist with restrictive permissions (contains credentials)
122
- writeFileSync(PLIST_PATH, plist, { mode: 0o600 });
123
- this.log(`[OK] Service plist written to ${PLIST_PATH}`);
124
- // Load the service
125
- try {
126
- execFileSync('launchctl', ['bootstrap', `gui/${uid}`, PLIST_PATH]);
127
- this.log('[OK] Service loaded into launchd');
128
- }
129
- catch (bootstrapErr) {
130
- this.warn(`bootstrap failed (${bootstrapErr.message.trim()}), trying legacy load...`);
131
- try {
132
- execFileSync('launchctl', ['load', PLIST_PATH]);
133
- this.log('[OK] Service loaded into launchd (legacy)');
134
- }
135
- catch (loadErr) {
136
- this.error(`Could not load service.\n` +
137
- ` bootstrap: ${bootstrapErr.message.trim()}\n` +
138
- ` load: ${loadErr.message.trim()}\n` +
139
- `Try manually: launchctl bootstrap gui/${uid} "${PLIST_PATH}"`);
140
- }
141
- }
142
- // Wait for API to come up
143
- this.log(`[..] Waiting for API on :${port}...`);
144
- const started = await this.waitForApi(port, 15);
145
- if (started) {
146
- this.log(`[OK] RuleMetric API running on :${port}`);
147
- }
148
- else {
149
- this.warn('API did not respond within 15s. Check logs:');
150
- this.log(` tail -f ${LOG_DIR}/api-stdout.log`);
151
- this.log(` tail -f ${LOG_DIR}/api-stderr.log`);
152
- }
153
- // --- Worker service (eval/insights job processor) ---
154
- this.log('');
155
- this.log('Installing worker service...');
156
- const workerPlist = this.buildWorkerPlist({
157
- projectRoot,
158
- nodePath,
159
- pnpmPath,
160
- envVars,
161
- });
162
- // Unload existing worker service if running
163
- try {
164
- execFileSync('launchctl', ['bootout', `gui/${uid}`, WORKER_PLIST_PATH], { encoding: 'utf-8' });
165
- }
166
- catch {
167
- // Expected if not loaded
168
- }
169
- writeFileSync(WORKER_PLIST_PATH, workerPlist, { mode: 0o600 });
170
- this.log(`[OK] Worker plist written to ${WORKER_PLIST_PATH}`);
171
- try {
172
- execFileSync('launchctl', ['bootstrap', `gui/${uid}`, WORKER_PLIST_PATH]);
173
- this.log('[OK] Worker service loaded into launchd');
174
- }
175
- catch (bootstrapErr) {
176
- try {
177
- execFileSync('launchctl', ['load', WORKER_PLIST_PATH]);
178
- this.log('[OK] Worker service loaded into launchd (legacy)');
179
- }
180
- catch (loadErr) {
181
- this.warn(`Could not load worker service: ${loadErr.message.trim()}`);
182
- }
183
- }
184
- // --- Worker daily auto-restart agent ---
185
- // Closes the graphile-LISTEN-wedge class (observed at ~25h worker uptime).
186
- // Without this, end users would hit a silent wedge every ~day where the
187
- // worker stays "alive" but stops claiming jobs. With this, launchd
188
- // kickstarts the worker every day at 04:00 local time; KeepAlive on the
189
- // worker plist then respawns it clean, and the reclaimStaleLocks() boot
190
- // step in graphile-worker-runner.ts releases any in-flight locks the
191
- // old process was holding. See worker:restart helper for the manual path.
192
- this.log('');
193
- this.log('Installing worker auto-restart agent (daily 04:00)...');
194
- const restartPlist = this.buildWorkerRestartPlist({ uid });
195
- try {
196
- execFileSync('launchctl', ['bootout', `gui/${uid}`, WORKER_RESTART_PLIST_PATH], { encoding: 'utf-8' });
197
- }
198
- catch {
199
- // Expected if not loaded
200
- }
201
- writeFileSync(WORKER_RESTART_PLIST_PATH, restartPlist, { mode: 0o600 });
202
- this.log(`[OK] Restart agent plist written to ${WORKER_RESTART_PLIST_PATH}`);
203
- try {
204
- execFileSync('launchctl', ['bootstrap', `gui/${uid}`, WORKER_RESTART_PLIST_PATH]);
205
- this.log('[OK] Restart agent loaded into launchd (daily kickstart at 04:00)');
206
- }
207
- catch (bootstrapErr) {
208
- try {
209
- execFileSync('launchctl', ['load', WORKER_RESTART_PLIST_PATH]);
210
- this.log('[OK] Restart agent loaded into launchd (legacy)');
211
- }
212
- catch (loadErr) {
213
- this.warn(`Could not load restart agent: ${loadErr.message.trim()}`);
214
- }
215
- }
216
- this.log('');
217
- this.log('All three services installed: API + worker + daily worker restart.');
218
- this.log('Both API and worker will start automatically on login and restart on crash.');
219
- this.log('The worker processes eval jobs, insights jobs, and session analysis.');
220
- this.log('');
221
- this.log('NOTE: Env vars are baked in at install time. If you change');
222
- this.log('.env.local or credentials, re-run: rulemetric service install --force');
223
- this.log('');
224
- this.log('Manage with:');
225
- this.log(' rulemetric service status — check if running');
226
- this.log(' rulemetric service uninstall — remove the service');
227
- // Ensure the active-org cache reflects the user's current active_org_id
228
- // before the worker spawns its first capture. Belt-and-suspenders with
229
- // BaseCommand's guarded refresh.
230
- await bootstrapActiveOrg();
231
- }
232
- findProjectRoot() {
233
- // Check env var override
234
- if (process.env.RULEMETRIC_PROJECT_ROOT) {
235
- return process.env.RULEMETRIC_PROJECT_ROOT;
53
+ var PLIST_LABEL = "com.rulemetric.api";
54
+ var PLIST_PATH = join(homedir(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
55
+ var WORKER_PLIST_LABEL = "com.rulemetric.worker";
56
+ var WORKER_PLIST_PATH = join(homedir(), "Library", "LaunchAgents", `${WORKER_PLIST_LABEL}.plist`);
57
+ var GATEWAY_PLIST_LABEL = "com.rulemetric.gateway";
58
+ var GATEWAY_PLIST_PATH = join(homedir(), "Library", "LaunchAgents", `${GATEWAY_PLIST_LABEL}.plist`);
59
+ var PROXY_PLIST_LABEL = "com.rulemetric.proxy";
60
+ var PROXY_PLIST_PATH = join(homedir(), "Library", "LaunchAgents", `${PROXY_PLIST_LABEL}.plist`);
61
+ var WORKER_RESTART_PLIST_LABEL = "com.rulemetric.worker.restart";
62
+ var WORKER_RESTART_PLIST_PATH = join(homedir(), "Library", "LaunchAgents", `${WORKER_RESTART_PLIST_LABEL}.plist`);
63
+ var CONFIG_DIR = join(homedir(), ".config", "rulemetric");
64
+ var LOG_DIR = join(CONFIG_DIR, "logs");
65
+ var GATEWAY_PORT = 8787;
66
+ var PROXY_PORT = 8788;
67
+ var ServiceInstall = class _ServiceInstall extends BaseCommand {
68
+ static description = "Install RuleMetric API, worker, gateway, and capture proxy as persistent macOS launchd services";
69
+ static examples = [
70
+ "<%= config.bin %> service install",
71
+ "<%= config.bin %> service install --port 3000",
72
+ "<%= config.bin %> service install --skip-build",
73
+ "<%= config.bin %> service install --no-proxy"
74
+ ];
75
+ static flags = {
76
+ port: Flags.integer({
77
+ char: "p",
78
+ default: 3e3,
79
+ description: "API server port"
80
+ }),
81
+ force: Flags.boolean({
82
+ char: "f",
83
+ default: false,
84
+ description: "Overwrite existing service configuration and reclaim conflicting ports"
85
+ }),
86
+ "skip-build": Flags.boolean({
87
+ default: false,
88
+ description: "Skip the pre-install workspace build (API/web/cli dist must already exist)"
89
+ }),
90
+ "no-proxy": Flags.boolean({
91
+ default: false,
92
+ description: "Skip gateway + mitmproxy plists (just install API + worker)"
93
+ })
94
+ };
95
+ async run() {
96
+ const { flags } = await this.parse(_ServiceInstall);
97
+ const port = flags.port;
98
+ const skipBuild = flags["skip-build"];
99
+ const noProxy = flags["no-proxy"];
100
+ if (process.platform !== "darwin") {
101
+ this.error("Service install is currently macOS-only (launchd). For Linux, use systemd manually.");
102
+ }
103
+ if (existsSync(PLIST_PATH) && !flags.force) {
104
+ this.log(`Service already installed at ${PLIST_PATH}`);
105
+ this.log("Use --force to overwrite, or run: rulemetric service status");
106
+ return;
107
+ }
108
+ try {
109
+ const res = await fetch(`http://localhost:${port}/health`);
110
+ if (res.ok && !flags.force) {
111
+ this.warn(`Port ${port} is already in use (API may be running via start.sh or in another terminal).`);
112
+ this.warn("Stop it first with scripts/stop.sh, or use --force to take over the port.");
113
+ return;
114
+ }
115
+ } catch {
116
+ }
117
+ const projectRoot = this.findProjectRoot();
118
+ if (!projectRoot) {
119
+ this.error(
120
+ "Could not find RuleMetric project root. Run this command from within the momento-mori repo, or set RULEMETRIC_PROJECT_ROOT."
121
+ );
122
+ }
123
+ const envLocal = join(projectRoot, ".env.local");
124
+ if (!existsSync(envLocal)) {
125
+ this.error(`.env.local not found at ${envLocal}. The API needs Supabase credentials to start.`);
126
+ }
127
+ const envVars = this.guardAlwaysOnDatabaseUrl(this.loadEnvVars(projectRoot));
128
+ const nodePath = this.findBinary("node");
129
+ const pnpmPath = this.findBinary("pnpm");
130
+ if (!nodePath || !pnpmPath) {
131
+ this.error("Could not find node or pnpm. Ensure they are in your PATH.");
132
+ }
133
+ let mitmdumpPath = null;
134
+ if (!noProxy) {
135
+ mitmdumpPath = this.findBinary("mitmdump");
136
+ if (!mitmdumpPath) {
137
+ this.error(
138
+ "mitmdump not found in PATH. Install with: pipx install mitmproxy (or brew install mitmproxy), then re-run.\nOr skip the capture proxy with --no-proxy."
139
+ );
140
+ }
141
+ }
142
+ if (!skipBuild) {
143
+ this.log("[..] Building workspace artifacts (api, web, cli) via turbo...");
144
+ const buildFilters = [
145
+ "--filter",
146
+ "@rulemetric/api...",
147
+ "--filter",
148
+ "@rulemetric/web...",
149
+ "--filter",
150
+ "@rulemetric/cli"
151
+ ];
152
+ const build = spawnSync(pnpmPath, ["exec", "turbo", "run", "build", ...buildFilters], {
153
+ cwd: projectRoot,
154
+ stdio: "inherit"
155
+ });
156
+ if (build.status !== 0) {
157
+ this.error(
158
+ `Workspace build failed (exit ${build.status}). Fix the build first, or use --skip-build if dist/ already exists.`
159
+ );
160
+ }
161
+ this.log("[OK] Build complete");
162
+ } else {
163
+ this.log("[..] Skipping pre-install build (--skip-build)");
164
+ }
165
+ const apiEntry = join(projectRoot, "apps", "api", "dist", "index.js");
166
+ if (!existsSync(apiEntry)) {
167
+ this.error(`API entry not found at ${apiEntry}. Re-run without --skip-build, or: pnpm --filter @rulemetric/api... build`);
168
+ }
169
+ const webIndex = join(projectRoot, "apps", "web", "dist", "index.html");
170
+ if (!existsSync(webIndex)) {
171
+ this.warn(`Web bundle not found at ${webIndex}. Dashboard at :${port} will 404 until you build apps/web.`);
172
+ }
173
+ if (!noProxy) {
174
+ const gatewayEntry = join(projectRoot, "apps", "cli", "dist", "lib", "gateway-entry.js");
175
+ if (!existsSync(gatewayEntry)) {
176
+ this.error(`Gateway entry not found at ${gatewayEntry}. Re-run without --skip-build, or: pnpm --filter @rulemetric/cli build`);
177
+ }
178
+ }
179
+ if (flags.force) {
180
+ this.killStaleProcess(port, null, "API on :" + port);
181
+ }
182
+ if (!noProxy) {
183
+ this.killStaleProcess(GATEWAY_PORT, join(CONFIG_DIR, "gateway.pid"), "gateway");
184
+ this.killStaleProcess(PROXY_PORT, join(CONFIG_DIR, "proxy.pid"), "mitmproxy");
185
+ }
186
+ mkdirSync(join(homedir(), "Library", "LaunchAgents"), { recursive: true });
187
+ mkdirSync(LOG_DIR, { recursive: true });
188
+ const uid = execSync("id -u", { encoding: "utf-8" }).trim();
189
+ const apiPlist = this.buildPlist({ port, projectRoot, nodePath, pnpmPath, envVars });
190
+ this.bootoutAndWrite(uid, PLIST_PATH, apiPlist, "API");
191
+ this.bootstrapPlist(uid, PLIST_PATH, "API");
192
+ this.log(`[..] Waiting for API on :${port}...`);
193
+ const apiStarted = await this.waitForApi(port, 15);
194
+ if (apiStarted) {
195
+ this.log(`[OK] RuleMetric API running on :${port}`);
196
+ if (existsSync(webIndex)) {
197
+ this.log(`[OK] Dashboard available at http://localhost:${port}`);
198
+ }
199
+ } else {
200
+ this.warn("API did not respond within 15s. Check logs:");
201
+ this.log(` tail -f ${LOG_DIR}/api-stdout.log`);
202
+ this.log(` tail -f ${LOG_DIR}/api-stderr.log`);
203
+ }
204
+ this.log("");
205
+ this.log("Installing worker service...");
206
+ this.killStaleAgents();
207
+ const workerPlist = this.buildWorkerPlist({ projectRoot, nodePath, pnpmPath, envVars });
208
+ this.bootoutAndWrite(uid, WORKER_PLIST_PATH, workerPlist, "Worker");
209
+ this.bootstrapPlist(uid, WORKER_PLIST_PATH, "Worker");
210
+ if (!noProxy) {
211
+ this.log("");
212
+ this.log("Installing gateway + capture proxy services...");
213
+ const gatewayPlist = this.buildGatewayPlist({ projectRoot, nodePath });
214
+ this.bootoutAndWrite(uid, GATEWAY_PLIST_PATH, gatewayPlist, "Gateway");
215
+ this.bootstrapPlist(uid, GATEWAY_PLIST_PATH, "Gateway");
216
+ const proxyPlist = this.buildProxyPlist({
217
+ projectRoot,
218
+ mitmdumpPath,
219
+ envVars
220
+ });
221
+ this.bootoutAndWrite(uid, PROXY_PLIST_PATH, proxyPlist, "Proxy");
222
+ this.bootstrapPlist(uid, PROXY_PLIST_PATH, "Proxy");
223
+ }
224
+ if (existsSync(WORKER_RESTART_PLIST_PATH)) {
225
+ try {
226
+ execFileSync("launchctl", ["bootout", `gui/${uid}`, WORKER_RESTART_PLIST_PATH], { encoding: "utf-8" });
227
+ } catch {
228
+ }
229
+ try {
230
+ execFileSync("rm", ["-f", WORKER_RESTART_PLIST_PATH]);
231
+ this.log("[OK] Removed stale daily worker-restart agent (no longer needed on agent path)");
232
+ } catch {
233
+ }
234
+ }
235
+ this.log("");
236
+ if (noProxy) {
237
+ this.log("Installed: API + worker. Gateway/proxy skipped (--no-proxy).");
238
+ } else {
239
+ this.log("Installed: API + worker + gateway + capture proxy.");
240
+ }
241
+ this.log("All services start at login, restart on crash, and pick up rebuilds via WatchPaths.");
242
+ this.log("");
243
+ this.log("NOTE: Env vars are baked in at install time. If you change");
244
+ this.log(".env.local or credentials, re-run: rulemetric service install --force");
245
+ this.log("");
246
+ this.log("Manage with:");
247
+ this.log(" rulemetric service status \u2014 check if running");
248
+ this.log(" rulemetric service uninstall \u2014 remove all services");
249
+ await bootstrapActiveOrg();
250
+ const tmux = await detectTmux();
251
+ this.log("");
252
+ if (tmux.available) {
253
+ this.log(`[OK] tmux found${tmux.version ? ` (v${tmux.version})` : ""} \u2014 live send enabled`);
254
+ } else {
255
+ this.log("[!!] tmux not found \u2014 live send will fall back to opening Terminal. Install with: brew install tmux");
256
+ }
257
+ }
258
+ findProjectRoot() {
259
+ if (process.env.RULEMETRIC_PROJECT_ROOT) {
260
+ return process.env.RULEMETRIC_PROJECT_ROOT;
261
+ }
262
+ let dir = process.cwd();
263
+ for (let i = 0; i < 10; i++) {
264
+ if (existsSync(join(dir, "apps", "api", "package.json"))) {
265
+ return dir;
266
+ }
267
+ const parent = join(dir, "..");
268
+ if (parent === dir) break;
269
+ dir = parent;
270
+ }
271
+ return null;
272
+ }
273
+ findBinary(name) {
274
+ try {
275
+ return execFileSync("which", [name], { encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }).trim() || null;
276
+ } catch {
277
+ return null;
278
+ }
279
+ }
280
+ loadEnvVars(projectRoot) {
281
+ const vars = {};
282
+ const envLocal = join(projectRoot, ".env.local");
283
+ if (existsSync(envLocal)) {
284
+ for (const line of readFileSync(envLocal, "utf-8").split("\n")) {
285
+ const trimmed = line.trim();
286
+ if (!trimmed || trimmed.startsWith("#")) continue;
287
+ const eqIdx = trimmed.indexOf("=");
288
+ if (eqIdx > 0) {
289
+ vars[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);
236
290
  }
237
- // Walk up from cwd looking for the monorepo marker
238
- let dir = process.cwd();
239
- for (let i = 0; i < 10; i++) {
240
- if (existsSync(join(dir, 'apps', 'api', 'package.json'))) {
241
- return dir;
242
- }
243
- const parent = join(dir, '..');
244
- if (parent === dir)
245
- break;
246
- dir = parent;
291
+ }
292
+ }
293
+ const globalEnv = join(CONFIG_DIR, "env");
294
+ if (existsSync(globalEnv)) {
295
+ for (const line of readFileSync(globalEnv, "utf-8").split("\n")) {
296
+ const trimmed = line.trim();
297
+ if (!trimmed || trimmed.startsWith("#")) continue;
298
+ const eqIdx = trimmed.indexOf("=");
299
+ if (eqIdx > 0) {
300
+ vars[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);
247
301
  }
248
- return null;
302
+ }
303
+ }
304
+ return Object.fromEntries(
305
+ Object.entries(vars).filter(([k]) => ALLOWED_ENV_VARS.has(k))
306
+ );
307
+ }
308
+ // Guard: the always-on API + worker MUST use the TRANSACTION-mode pooler
309
+ // (port 6543). A SESSION-mode URL (:5432, 15-slot cap) baked into these
310
+ // services was the trigger of the recurring pool saturation — a pool-cascade
311
+ // debugging override leaked into the plists through this very installer. Auto-
312
+ // correct the obvious session→transaction port and warn loudly; warn (but do
313
+ // not block) on a direct, non-pooler URL. Pool-exhaustion RCA 2026-06-21.
314
+ guardAlwaysOnDatabaseUrl(envVars) {
315
+ const url = envVars.DATABASE_URL;
316
+ if (!url) return envVars;
317
+ if (url.includes("pooler.supabase.com:5432")) {
318
+ this.warn(
319
+ "DATABASE_URL points at the SESSION-mode pooler (:5432, 15-slot cap). The always-on API/worker must use TRANSACTION mode (:6543) \u2014 auto-correcting for the installed services. Fix .env.local to silence this warning."
320
+ );
321
+ return { ...envVars, DATABASE_URL: url.replace("pooler.supabase.com:5432", "pooler.supabase.com:6543") };
322
+ }
323
+ if (/@db\.[a-z0-9]+\.supabase\.co[:/]/.test(url)) {
324
+ this.warn(
325
+ "DATABASE_URL is a DIRECT database connection (db.<ref>.supabase.co), not the pooler. Always-on services should use the transaction pooler (aws-*.pooler.supabase.com:6543) to avoid exhausting Postgres connections."
326
+ );
249
327
  }
250
- findBinary(name) {
328
+ return envVars;
329
+ }
330
+ // Reap orphaned, unsupervised `evals agent` worker processes before
331
+ // (re)bootstrapping the launchd worker. The worker holds no listening port,
332
+ // so killStaleProcess (port/pidfile based) cannot find detached agents — a
333
+ // fleet of 4 ran 3+ days and helped saturate the pool (RCA 2026-06-21). pgrep
334
+ // the command line and SIGTERM every match except ourselves; the agent's own
335
+ // single-instance lock then keeps a fresh fleet from forming.
336
+ killStaleAgents() {
337
+ try {
338
+ const out = execFileSync("pgrep", ["-f", "bin/run.js evals agent"], {
339
+ encoding: "utf-8",
340
+ stdio: ["ignore", "pipe", "ignore"]
341
+ });
342
+ const pids = out.trim().split("\n").filter(Boolean).map((s) => parseInt(s, 10)).filter((p) => !isNaN(p) && p !== process.pid);
343
+ for (const pid of pids) {
251
344
  try {
252
- return execFileSync('which', [name], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim() || null;
253
- }
254
- catch {
255
- return null;
345
+ process.kill(pid, "SIGTERM");
346
+ this.log(`[OK] Reaped orphan evals agent (PID ${pid})`);
347
+ } catch {
256
348
  }
349
+ }
350
+ if (pids.length) spawnSync("sleep", ["1"], { stdio: "ignore" });
351
+ } catch {
257
352
  }
258
- loadEnvVars(projectRoot) {
259
- const vars = {};
260
- // Load from .env.local (Supabase credentials)
261
- const envLocal = join(projectRoot, '.env.local');
262
- if (existsSync(envLocal)) {
263
- for (const line of readFileSync(envLocal, 'utf-8').split('\n')) {
264
- const trimmed = line.trim();
265
- if (!trimmed || trimmed.startsWith('#'))
266
- continue;
267
- const eqIdx = trimmed.indexOf('=');
268
- if (eqIdx > 0) {
269
- vars[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);
270
- }
271
- }
353
+ }
354
+ // Best-effort cleanup of a process that would conflict with an
355
+ // about-to-bootstrap launchd plist. Tries two routes:
356
+ // (a) the PID file written by the legacy spawn path
357
+ // (gateway-lifecycle / proxy start), if pidFile is non-null
358
+ // (b) anything actively listening on the expected port
359
+ // Either way: SIGTERM + small grace + SIGKILL fallback. Stale PID file
360
+ // gets unlinked.
361
+ killStaleProcess(port, pidFile, name) {
362
+ let killedAny = false;
363
+ if (pidFile && existsSync(pidFile)) {
364
+ try {
365
+ const pidStr = readFileSync(pidFile, "utf-8").trim();
366
+ const pid = parseInt(pidStr, 10);
367
+ if (!isNaN(pid)) {
368
+ try {
369
+ process.kill(pid, "SIGTERM");
370
+ killedAny = true;
371
+ this.log(`[OK] Stopped existing ${name} (PID ${pid} from ${pidFile})`);
372
+ } catch {
373
+ }
272
374
  }
273
- // Load from ~/.config/rulemetric/env (API key)
274
- const globalEnv = join(CONFIG_DIR, 'env');
275
- if (existsSync(globalEnv)) {
276
- for (const line of readFileSync(globalEnv, 'utf-8').split('\n')) {
277
- const trimmed = line.trim();
278
- if (!trimmed || trimmed.startsWith('#'))
279
- continue;
280
- const eqIdx = trimmed.indexOf('=');
281
- if (eqIdx > 0) {
282
- vars[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);
283
- }
284
- }
375
+ } catch {
376
+ }
377
+ try {
378
+ execFileSync("rm", ["-f", pidFile]);
379
+ } catch {
380
+ }
381
+ }
382
+ try {
383
+ const result = execFileSync("lsof", ["-ti", `:${port}`, "-sTCP:LISTEN"], {
384
+ encoding: "utf-8",
385
+ stdio: ["ignore", "pipe", "ignore"]
386
+ });
387
+ const pids = result.trim().split("\n").filter(Boolean);
388
+ for (const pidStr of pids) {
389
+ const pid = parseInt(pidStr, 10);
390
+ if (!isNaN(pid)) {
391
+ try {
392
+ process.kill(pid, "SIGTERM");
393
+ killedAny = true;
394
+ this.log(`[OK] Stopped orphan on :${port} (PID ${pid})`);
395
+ } catch {
396
+ }
285
397
  }
286
- // Only keep allowed env vars — never leak unrelated secrets
287
- return Object.fromEntries(Object.entries(vars).filter(([k]) => ALLOWED_ENV_VARS.has(k)));
288
- }
289
- buildPlist(opts) {
290
- const { port, projectRoot, nodePath, pnpmPath, envVars } = opts;
291
- // Derive PATH from resolved binary locations (works with nvm, volta, fnm, homebrew)
292
- const pathDirs = [...new Set([dirname(nodePath), dirname(pnpmPath), '/usr/local/bin', '/usr/bin', '/bin'])];
293
- // Build environment dict entries
294
- const envEntries = Object.entries({
295
- ...envVars,
296
- PORT: String(port),
297
- NODE_ENV: 'development',
298
- PATH: pathDirs.join(':'),
299
- })
300
- .map(([k, v]) => ` <key>${escapeXml(k)}</key>\n <string>${escapeXml(v)}</string>`)
301
- .join('\n');
302
- return `<?xml version="1.0" encoding="UTF-8"?>
398
+ }
399
+ } catch {
400
+ }
401
+ if (killedAny) {
402
+ spawnSync("sleep", ["1"], { stdio: "ignore" });
403
+ }
404
+ }
405
+ bootoutAndWrite(uid, plistPath, content, name) {
406
+ const benignBootoutPatterns = [
407
+ "Could not find specified service",
408
+ "No such process",
409
+ "3: No such process",
410
+ "5: Input/output error"
411
+ ];
412
+ try {
413
+ execFileSync("launchctl", ["bootout", `gui/${uid}`, plistPath], {
414
+ encoding: "utf-8",
415
+ // Capture stderr instead of letting it print to the user's terminal.
416
+ // The plist was either already-loaded (we unload it cleanly) or not
417
+ // loaded (we want to swallow the error) — the user shouldn't see
418
+ // launchctl's raw output either way.
419
+ stdio: ["ignore", "pipe", "pipe"]
420
+ });
421
+ this.log(`[OK] Unloaded existing ${name} service`);
422
+ } catch (err) {
423
+ const msg = err.message || "";
424
+ const stderr = (err.stderr ?? "").toString();
425
+ const combined = `${msg}
426
+ ${stderr}`;
427
+ if (!benignBootoutPatterns.some((p) => combined.includes(p))) {
428
+ this.warn(`Could not unload existing ${name} service: ${msg.trim()}`);
429
+ }
430
+ }
431
+ writeFileSync(plistPath, content, { mode: 384 });
432
+ this.log(`[OK] ${name} plist written to ${plistPath}`);
433
+ }
434
+ bootstrapPlist(uid, plistPath, name) {
435
+ try {
436
+ execFileSync("launchctl", ["bootstrap", `gui/${uid}`, plistPath]);
437
+ this.log(`[OK] ${name} service loaded into launchd`);
438
+ } catch (bootstrapErr) {
439
+ try {
440
+ execFileSync("launchctl", ["load", plistPath]);
441
+ this.log(`[OK] ${name} service loaded into launchd (legacy)`);
442
+ } catch (loadErr) {
443
+ this.warn(
444
+ `Could not load ${name} service.
445
+ bootstrap: ${bootstrapErr.message.trim()}
446
+ load: ${loadErr.message.trim()}`
447
+ );
448
+ }
449
+ }
450
+ }
451
+ buildPlist(opts) {
452
+ const { port, projectRoot, nodePath, pnpmPath, envVars } = opts;
453
+ const pathDirs = [.../* @__PURE__ */ new Set([dirname(nodePath), dirname(pnpmPath), "/usr/local/bin", "/usr/bin", "/bin"])];
454
+ const envEntries = Object.entries({
455
+ ...envVars,
456
+ PORT: String(port),
457
+ NODE_ENV: "production",
458
+ PATH: pathDirs.join(":"),
459
+ // Pool resilience for the always-on API (NOT the worker, which runs
460
+ // legitimately long analytics queries). A wedged Supavisor socket with
461
+ // the default max=3 pool and no query timeout hangs every authenticated
462
+ // request — the 2026-06-09 login-hang. statement_timeout lets Postgres
463
+ // cancel a stuck query so the connection returns to the pool (verified
464
+ // honored through the transaction pooler); the larger pool adds headroom.
465
+ // Both env-overridable. See packages/db/src/client.ts.
466
+ PG_POOL_MAX: envVars.PG_POOL_MAX ?? "10",
467
+ PG_STATEMENT_TIMEOUT_MS: envVars.PG_STATEMENT_TIMEOUT_MS ?? "10000",
468
+ // Keep the pool warm so the API stops reconnecting (and re-resolving the
469
+ // rotating pooler ELB) on nearly every request — the churn that exposed
470
+ // it to intermittent CONNECT_TIMEOUT/ENOTFOUND. Worker/tests keep the
471
+ // conservative 5s default. See packages/db/src/client.ts (2026-06-09).
472
+ PG_IDLE_TIMEOUT: envVars.PG_IDLE_TIMEOUT ?? "30",
473
+ // Silence per-span stdout dumps on the local API — it has no OTLP
474
+ // endpoint and a fixed (now rotated) log file; the ConsoleSpanExporter
475
+ // grew api-stdout to 370MB / ~400k spans. Fly leaves this unset so its
476
+ // console spans stay grep-able in the managed log stream.
477
+ OTEL_SPAN_EXPORT: envVars.OTEL_SPAN_EXPORT ?? "none"
478
+ }).map(([k, v]) => ` <key>${escapeXml(k)}</key>
479
+ <string>${escapeXml(v)}</string>`).join("\n");
480
+ const apiEntry = join(projectRoot, "apps", "api", "dist", "index.js");
481
+ const apiDist = join(projectRoot, "apps", "api", "dist");
482
+ return `<?xml version="1.0" encoding="UTF-8"?>
303
483
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
304
484
  <plist version="1.0">
305
485
  <dict>
@@ -308,10 +488,8 @@ export default class ServiceInstall extends BaseCommand {
308
488
 
309
489
  <key>ProgramArguments</key>
310
490
  <array>
311
- <string>${escapeXml(pnpmPath)}</string>
312
- <string>--filter</string>
313
- <string>@rulemetric/api</string>
314
- <string>dev</string>
491
+ <string>${escapeXml(nodePath)}</string>
492
+ <string>${escapeXml(apiEntry)}</string>
315
493
  </array>
316
494
 
317
495
  <key>WorkingDirectory</key>
@@ -334,40 +512,42 @@ ${envEntries}
334
512
  <key>ThrottleInterval</key>
335
513
  <integer>10</integer>
336
514
 
515
+ <key>WatchPaths</key>
516
+ <array>
517
+ <string>${escapeXml(apiDist)}</string>
518
+ </array>
519
+
337
520
  <key>StandardOutPath</key>
338
- <string>${escapeXml(join(LOG_DIR, 'api-stdout.log'))}</string>
521
+ <string>${escapeXml(join(LOG_DIR, "api-stdout.log"))}</string>
339
522
 
340
523
  <key>StandardErrorPath</key>
341
- <string>${escapeXml(join(LOG_DIR, 'api-stderr.log'))}</string>
524
+ <string>${escapeXml(join(LOG_DIR, "api-stderr.log"))}</string>
342
525
 
343
526
  <key>ProcessType</key>
344
527
  <string>Background</string>
345
528
  </dict>
346
529
  </plist>
347
530
  `;
348
- }
349
- buildWorkerPlist(opts) {
350
- const { projectRoot, nodePath, pnpmPath, envVars } = opts;
351
- const pathDirs = [...new Set([dirname(nodePath), dirname(pnpmPath), '/usr/local/bin', '/usr/bin', '/bin'])];
352
- const envEntries = Object.entries({
353
- ...envVars,
354
- NODE_ENV: 'development',
355
- PATH: pathDirs.join(':'),
356
- })
357
- .map(([k, v]) => ` <key>${escapeXml(k)}</key>\n <string>${escapeXml(v)}</string>`)
358
- .join('\n');
359
- // Run the CLI bin directly via node. Earlier this used
360
- // `pnpm --filter @rulemetric/cli exec rulemetric` but pnpm-exec couldn't
361
- // resolve the workspace bin symlink reliably under launchd, crash-looping
362
- // with `Command "rulemetric" not found`. Direct node invocation is both
363
- // simpler (one process less) and avoids the bin-symlink lookup entirely.
364
- const cliBin = join(projectRoot, 'apps', 'cli', 'bin', 'run.js');
365
- // Watch the CLI's dist directory: when `pnpm build` overwrites it, launchd
366
- // bounces the worker so a freshly-built version of the eval-worker code
367
- // (e.g. with a new job-kind capability) takes effect without a manual
368
- // kickstart. WatchPaths fires on any change beneath the directory.
369
- const cliDist = join(projectRoot, 'apps', 'cli', 'dist');
370
- return `<?xml version="1.0" encoding="UTF-8"?>
531
+ }
532
+ buildWorkerPlist(opts) {
533
+ const { projectRoot, nodePath, pnpmPath, envVars } = opts;
534
+ const pathDirs = [.../* @__PURE__ */ new Set([dirname(nodePath), dirname(pnpmPath), "/usr/local/bin", "/usr/bin", "/bin"])];
535
+ const envEntries = Object.entries({
536
+ ...envVars,
537
+ NODE_ENV: "development",
538
+ PATH: pathDirs.join(":"),
539
+ // Bound the worker's pooler footprint. The worker is mostly idle (HTTP
540
+ // long-poll); an UNPINNED pool plus the previously-missing single-instance
541
+ // guard let an orphaned fleet of agents each hold a pool and saturate
542
+ // Supavisor's 200-client cap. A small pool + short idle timeout releases
543
+ // sessions promptly. Pool-exhaustion RCA 2026-06-21.
544
+ PG_POOL_MAX: envVars.PG_POOL_MAX ?? "3",
545
+ PG_IDLE_TIMEOUT: envVars.PG_IDLE_TIMEOUT ?? "10"
546
+ }).map(([k, v]) => ` <key>${escapeXml(k)}</key>
547
+ <string>${escapeXml(v)}</string>`).join("\n");
548
+ const cliBin = join(projectRoot, "apps", "cli", "bin", "run.js");
549
+ const cliDist = join(projectRoot, "apps", "cli", "dist");
550
+ return `<?xml version="1.0" encoding="UTF-8"?>
371
551
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
372
552
  <plist version="1.0">
373
553
  <dict>
@@ -379,7 +559,7 @@ ${envEntries}
379
559
  <string>${escapeXml(nodePath)}</string>
380
560
  <string>${escapeXml(cliBin)}</string>
381
561
  <string>evals</string>
382
- <string>listen</string>
562
+ <string>agent</string>
383
563
  </array>
384
564
 
385
565
  <key>WorkingDirectory</key>
@@ -408,115 +588,169 @@ ${envEntries}
408
588
  </array>
409
589
 
410
590
  <key>StandardOutPath</key>
411
- <string>${escapeXml(join(LOG_DIR, 'worker-stdout.log'))}</string>
591
+ <string>${escapeXml(join(LOG_DIR, "worker-stdout.log"))}</string>
412
592
 
413
593
  <key>StandardErrorPath</key>
414
- <string>${escapeXml(join(LOG_DIR, 'worker-stderr.log'))}</string>
594
+ <string>${escapeXml(join(LOG_DIR, "worker-stderr.log"))}</string>
415
595
 
416
596
  <key>ProcessType</key>
417
597
  <string>Background</string>
418
598
  </dict>
419
599
  </plist>
420
600
  `;
421
- }
422
- /**
423
- * Plist for the daily worker auto-restart agent. Fires at 04:00 local
424
- * time and runs `launchctl kickstart -k gui/<uid>/com.rulemetric.worker`
425
- * which terminates the running worker process; KeepAlive on the worker
426
- * plist then respawns it clean. UID is dynamic (caller passes id -u
427
- * output) so this works on any laptop, not just the developer's.
428
- *
429
- * Without this agent, the worker silently wedges around ~25h of uptime
430
- * (graphile-worker's LISTEN socket dies, heartbeats continue, but no new
431
- * jobs claimed). The watchdog correctly refuses to suicide the process
432
- * (per the 2026-05-18 supavisor cascade lessons), so without auto-restart
433
- * the wedge sits indefinitely until an operator notices and kicks it.
434
- * End users shouldn't have to debug this — that's why it's part of
435
- * `service install`.
436
- */
437
- buildWorkerRestartPlist(opts) {
438
- const { uid } = opts;
439
- return `<?xml version="1.0" encoding="UTF-8"?>
601
+ }
602
+ // CONNECT-proxy router that fronts mitmproxy on :8787. Always-on so
603
+ // .claude/settings.json's HTTPS_PROXY pointer never resolves to a dead
604
+ // socket (which would break Claude Code entirely — see CLAUDE.md).
605
+ // NOT watched on rebuild: bouncing the gateway mid-request would drop
606
+ // in-flight streaming responses. Gateway code changes rarely; on
607
+ // upgrade, the user can `launchctl kickstart gui/<uid>/com.rulemetric.gateway`.
608
+ buildGatewayPlist(opts) {
609
+ const { projectRoot, nodePath } = opts;
610
+ const gatewayEntry = join(projectRoot, "apps", "cli", "dist", "lib", "gateway-entry.js");
611
+ const cliBin = join(projectRoot, "apps", "cli", "bin", "run.js");
612
+ const pathDirs = [.../* @__PURE__ */ new Set([dirname(nodePath), "/usr/local/bin", "/usr/bin", "/bin"])];
613
+ const env = {
614
+ RULEMETRIC_CLI_VERSION: this.config.version,
615
+ RULEMETRIC_CLI_ENTRY: cliBin,
616
+ PATH: pathDirs.join(":")
617
+ };
618
+ const envEntries = Object.entries(env).map(([k, v]) => ` <key>${escapeXml(k)}</key>
619
+ <string>${escapeXml(v)}</string>`).join("\n");
620
+ return `<?xml version="1.0" encoding="UTF-8"?>
440
621
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
441
622
  <plist version="1.0">
442
623
  <dict>
443
624
  <key>Label</key>
444
- <string>${WORKER_RESTART_PLIST_LABEL}</string>
625
+ <string>${GATEWAY_PLIST_LABEL}</string>
445
626
 
446
627
  <key>ProgramArguments</key>
447
628
  <array>
448
- <string>/bin/launchctl</string>
449
- <string>kickstart</string>
450
- <string>-k</string>
451
- <string>gui/${escapeXml(uid)}/${WORKER_PLIST_LABEL}</string>
629
+ <string>${escapeXml(nodePath)}</string>
630
+ <string>${escapeXml(gatewayEntry)}</string>
452
631
  </array>
453
632
 
454
- <!-- Fire every 6 hours (00:00, 06:00, 12:00, 18:00 local). The original
455
- daily schedule (04:00 only) capped the wedge window at <=24h, but
456
- we observed the graphile-LISTEN-wedge firing 4x in 28h during the
457
- 2026-05-24 testing — well before the 24h cap. Quartering the
458
- cadence drops the worst-case end-user-blocking window to <=6h.
459
- Each restart is ~5s of worker downtime; 4x/day = 20s/day total. -->
460
- <key>StartCalendarInterval</key>
633
+ <key>WorkingDirectory</key>
634
+ <string>${escapeXml(projectRoot)}</string>
635
+
636
+ <key>EnvironmentVariables</key>
637
+ <dict>
638
+ ${envEntries}
639
+ </dict>
640
+
641
+ <key>RunAtLoad</key>
642
+ <true/>
643
+
644
+ <key>KeepAlive</key>
645
+ <dict>
646
+ <key>SuccessfulExit</key>
647
+ <false/>
648
+ </dict>
649
+
650
+ <key>ThrottleInterval</key>
651
+ <integer>10</integer>
652
+
653
+ <key>StandardOutPath</key>
654
+ <string>${escapeXml(join(LOG_DIR, "gateway-stdout.log"))}</string>
655
+
656
+ <key>StandardErrorPath</key>
657
+ <string>${escapeXml(join(LOG_DIR, "gateway-stderr.log"))}</string>
658
+
659
+ <key>ProcessType</key>
660
+ <string>Background</string>
661
+ </dict>
662
+ </plist>
663
+ `;
664
+ }
665
+ // mitmproxy with the RuleMetric capture addon. Same invocation as
666
+ // `rulemetric proxy start` (see commands/proxy/start.ts:308) so the
667
+ // launchd path and the CLI path are interchangeable. We don't WatchPath
668
+ // the Python addon — mitmdump has its own addon reload that handles
669
+ // edits without a full process restart.
670
+ buildProxyPlist(opts) {
671
+ const { projectRoot, mitmdumpPath, envVars } = opts;
672
+ const addonPath = join(projectRoot, "packages", "proxy", "addon", "rulemetric_addon.py");
673
+ const pathDirs = [.../* @__PURE__ */ new Set([dirname(mitmdumpPath), "/usr/local/bin", "/usr/bin", "/bin"])];
674
+ const env = {
675
+ ...envVars,
676
+ RULEMETRIC_PROJECT_PATH: projectRoot,
677
+ RULEMETRIC_CLI_VERSION: this.config.version,
678
+ PATH: pathDirs.join(":")
679
+ };
680
+ const envEntries = Object.entries(env).map(([k, v]) => ` <key>${escapeXml(k)}</key>
681
+ <string>${escapeXml(v)}</string>`).join("\n");
682
+ return `<?xml version="1.0" encoding="UTF-8"?>
683
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
684
+ <plist version="1.0">
685
+ <dict>
686
+ <key>Label</key>
687
+ <string>${PROXY_PLIST_LABEL}</string>
688
+
689
+ <key>ProgramArguments</key>
461
690
  <array>
462
- <dict>
463
- <key>Hour</key>
464
- <integer>0</integer>
465
- <key>Minute</key>
466
- <integer>0</integer>
467
- </dict>
468
- <dict>
469
- <key>Hour</key>
470
- <integer>6</integer>
471
- <key>Minute</key>
472
- <integer>0</integer>
473
- </dict>
474
- <dict>
475
- <key>Hour</key>
476
- <integer>12</integer>
477
- <key>Minute</key>
478
- <integer>0</integer>
479
- </dict>
480
- <dict>
481
- <key>Hour</key>
482
- <integer>18</integer>
483
- <key>Minute</key>
484
- <integer>0</integer>
485
- </dict>
691
+ <string>${escapeXml(mitmdumpPath)}</string>
692
+ <string>--listen-port</string>
693
+ <string>${PROXY_PORT}</string>
694
+ <string>-s</string>
695
+ <string>${escapeXml(addonPath)}</string>
696
+ <string>--set</string>
697
+ <string>console_eventlog_verbosity=info</string>
486
698
  </array>
487
699
 
700
+ <key>WorkingDirectory</key>
701
+ <string>${escapeXml(projectRoot)}</string>
702
+
703
+ <key>EnvironmentVariables</key>
704
+ <dict>
705
+ ${envEntries}
706
+ </dict>
707
+
488
708
  <key>RunAtLoad</key>
489
- <false/>
709
+ <true/>
710
+
711
+ <key>KeepAlive</key>
712
+ <dict>
713
+ <key>SuccessfulExit</key>
714
+ <false/>
715
+ </dict>
716
+
717
+ <key>ThrottleInterval</key>
718
+ <integer>15</integer>
490
719
 
491
- <key>StandardErrorPath</key>
492
- <string>${escapeXml(join(LOG_DIR, 'worker-restart.log'))}</string>
493
720
  <key>StandardOutPath</key>
494
- <string>${escapeXml(join(LOG_DIR, 'worker-restart.log'))}</string>
721
+ <string>${escapeXml(join(LOG_DIR, "proxy-stdout.log"))}</string>
722
+
723
+ <key>StandardErrorPath</key>
724
+ <string>${escapeXml(join(LOG_DIR, "proxy-stderr.log"))}</string>
725
+
726
+ <key>ProcessType</key>
727
+ <string>Background</string>
495
728
  </dict>
496
729
  </plist>
497
730
  `;
731
+ }
732
+ async waitForApi(port, timeoutSecs) {
733
+ let lastError = null;
734
+ for (let i = 0; i < timeoutSecs; i++) {
735
+ try {
736
+ const res = await fetch(`http://localhost:${port}/health`);
737
+ if (res.ok) return true;
738
+ lastError = `health check returned ${res.status}`;
739
+ } catch (err) {
740
+ lastError = err.message;
741
+ }
742
+ await new Promise((r) => setTimeout(r, 1e3));
498
743
  }
499
- async waitForApi(port, timeoutSecs) {
500
- let lastError = null;
501
- for (let i = 0; i < timeoutSecs; i++) {
502
- try {
503
- const res = await fetch(`http://localhost:${port}/health`);
504
- if (res.ok)
505
- return true;
506
- lastError = `health check returned ${res.status}`;
507
- }
508
- catch (err) {
509
- lastError = err.message;
510
- }
511
- await new Promise(r => setTimeout(r, 1000));
512
- }
513
- if (lastError) {
514
- this.warn(`Last health check error: ${lastError}`);
515
- }
516
- return false;
744
+ if (lastError) {
745
+ this.warn(`Last health check error: ${lastError}`);
517
746
  }
518
- }
747
+ return false;
748
+ }
749
+ };
519
750
  function escapeXml(s) {
520
- return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
751
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
521
752
  }
522
- //# sourceMappingURL=install.js.map
753
+ export {
754
+ ServiceInstall as default
755
+ };
756
+ //# sourceMappingURL=install.js.map