@askexenow/exe-os 0.9.299 → 0.9.301

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 (499) hide show
  1. package/deploy/compose/.env.customer.example +1 -1
  2. package/deploy/compose/.env.example +1 -1
  3. package/deploy/compose/docker-compose.yml +31 -5
  4. package/deploy/compose/erp-nginx/nginx.conf +6 -3
  5. package/deploy/compose/generate-env.ts +1 -1
  6. package/deploy/compose/observability/otel-collector-config.yaml +10 -1
  7. package/deploy/compose/setup.sh +1 -1
  8. package/dist/active-agent-56J56WW5.js +27 -0
  9. package/dist/active-agent-UNJO6AJ2.js +27 -0
  10. package/dist/active-agent-VDWK7TES.js +28 -0
  11. package/dist/active-agent-Y5LSIMVC.js +28 -0
  12. package/dist/agentic-ontology-MZ4WHFDE.js +25 -0
  13. package/dist/agentic-ontology-QEV7GI3T.js +25 -0
  14. package/dist/assets/com.askexe.exed.plist +6 -5
  15. package/dist/backfill-metadata-IHKI5GXV.js +600 -0
  16. package/dist/backfill-metadata-RQZ4BN7G.js +600 -0
  17. package/dist/backfill-metadata-ZU3SZNBD.js +600 -0
  18. package/dist/behaviors-A3L5CWMK.js +46 -0
  19. package/dist/behaviors-G4KWGS24.js +46 -0
  20. package/dist/behaviors-WO67R6C4.js +46 -0
  21. package/dist/bin/agentic-ontology-backfill.js +5 -5
  22. package/dist/bin/agentic-reflection-backfill.js +6 -6
  23. package/dist/bin/agentic-semantic-label.js +5 -5
  24. package/dist/bin/backfill-conversations.js +6 -6
  25. package/dist/bin/backfill-responses.js +6 -6
  26. package/dist/bin/backfill-vectors.js +8 -8
  27. package/dist/bin/bulk-sync-postgres.js +13 -7
  28. package/dist/bin/cc-doctor.js +5 -5
  29. package/dist/bin/cleanup-stale-review-tasks.js +10 -10
  30. package/dist/bin/cli.js +16 -16
  31. package/dist/bin/deferred-daemon-restart.js +1 -1
  32. package/dist/bin/exe-agent-config.js +2 -2
  33. package/dist/bin/exe-agent.js +10 -10
  34. package/dist/bin/exe-assign.js +8 -8
  35. package/dist/bin/exe-boot.js +36 -21
  36. package/dist/bin/exe-call.js +4 -4
  37. package/dist/bin/exe-cloud.js +13 -7
  38. package/dist/bin/exe-dispatch.js +10 -10
  39. package/dist/bin/exe-doctor.js +2 -2
  40. package/dist/bin/exe-export-behaviors.js +7 -7
  41. package/dist/bin/exe-forget.js +6 -6
  42. package/dist/bin/exe-gateway.js +7 -7
  43. package/dist/bin/exe-healthcheck.js +5 -5
  44. package/dist/bin/exe-heartbeat.js +10 -10
  45. package/dist/bin/exe-kill.js +13 -13
  46. package/dist/bin/exe-launch-agent.js +29 -19
  47. package/dist/bin/exe-new-employee.js +6 -6
  48. package/dist/bin/exe-pending-messages.js +11 -11
  49. package/dist/bin/exe-pending-notifications.js +10 -10
  50. package/dist/bin/exe-pending-reviews.js +10 -10
  51. package/dist/bin/exe-rename.js +4 -4
  52. package/dist/bin/exe-review.js +12 -12
  53. package/dist/bin/exe-search.js +5 -5
  54. package/dist/bin/exe-session-cleanup.js +15 -15
  55. package/dist/bin/exe-settings.js +13 -7
  56. package/dist/bin/exe-start-codex.js +11 -11
  57. package/dist/bin/exe-start-opencode.js +8 -8
  58. package/dist/bin/exe-status.js +11 -11
  59. package/dist/bin/exe-team.js +3 -3
  60. package/dist/bin/exe-watchdog.js +3 -3
  61. package/dist/bin/git-sweep.js +11 -11
  62. package/dist/bin/graph-backfill.js +6 -6
  63. package/dist/bin/graph-export.js +5 -5
  64. package/dist/bin/import-history.js +9 -9
  65. package/dist/bin/install-launchd.js +7 -3
  66. package/dist/bin/install.js +19 -15
  67. package/dist/bin/intercom-check.js +4 -4
  68. package/dist/bin/mcp-sessions.js +2 -2
  69. package/dist/bin/orchestration-metrics.js +4 -4
  70. package/dist/bin/postgres-agentic-reflection-backfill.js +2 -2
  71. package/dist/bin/postgres-agentic-semantic-backfill.js +1 -1
  72. package/dist/bin/pre-publish.js +24 -1
  73. package/dist/bin/scan-tasks.js +10 -10
  74. package/dist/bin/setup.js +1 -1
  75. package/dist/bin/shard-migrate.js +4 -4
  76. package/dist/bin/stack-update.js +123 -3
  77. package/dist/bin/vps-health-gate.js +1 -1
  78. package/dist/capability-cards-VTGDTOZ4.js +89 -0
  79. package/dist/capability-cards-XAQSL26B.js +89 -0
  80. package/dist/capacity-monitor-6MQLFFQT.js +51 -0
  81. package/dist/capacity-monitor-BB3LKJLE.js +51 -0
  82. package/dist/capacity-monitor-G2MAJPRP.js +51 -0
  83. package/dist/catchup-brief-BQSL5M5S.js +175 -0
  84. package/dist/catchup-brief-COALBX6L.js +175 -0
  85. package/dist/catchup-brief-VBGEJQRS.js +175 -0
  86. package/dist/cc-binary-detect-B5JDCJ5J.js +19 -0
  87. package/dist/chunk-22LDUTY7.js +14597 -0
  88. package/dist/chunk-24JVDLQJ.js +345 -0
  89. package/dist/chunk-24M4AJPG.js +128 -0
  90. package/dist/chunk-2B7RCTPT.js +85 -0
  91. package/dist/chunk-2QBA6YE6.js +127 -0
  92. package/dist/chunk-2RGDEBZC.js +731 -0
  93. package/dist/chunk-2T3OYZMR.js +1158 -0
  94. package/dist/chunk-32DBQWR5.js +333 -0
  95. package/dist/chunk-3ABY3QDX.js +199 -0
  96. package/dist/chunk-3EOPMTG2.js +128 -0
  97. package/dist/chunk-3G3ECFB5.js +668 -0
  98. package/dist/chunk-3LHOFGHT.js +280 -0
  99. package/dist/chunk-3NS4V4JW.js +382 -0
  100. package/dist/chunk-3NYY2NZ3.js +836 -0
  101. package/dist/chunk-3RA62PNQ.js +58 -0
  102. package/dist/chunk-3ROUD5WA.js +97 -0
  103. package/dist/chunk-3RY2ARDN.js +129 -0
  104. package/dist/chunk-3XRS5AVV.js +567 -0
  105. package/dist/chunk-3Y5IRIRU.js +290 -0
  106. package/dist/chunk-3YK7X5FD.js +1186 -0
  107. package/dist/chunk-3ZWWUKBI.js +210 -0
  108. package/dist/chunk-463G3VAH.js +122 -0
  109. package/dist/chunk-4L6PVYFE.js +54 -0
  110. package/dist/chunk-4LC7BFI2.js +76 -0
  111. package/dist/chunk-4O67LBMK.js +377 -0
  112. package/dist/chunk-4OIU3N6U.js +167 -0
  113. package/dist/chunk-4Z3FWLOE.js +836 -0
  114. package/dist/chunk-5BAU4T5G.js +208 -0
  115. package/dist/chunk-5FP7YHCG.js +1158 -0
  116. package/dist/chunk-5SYYMNPE.js +30 -0
  117. package/dist/chunk-5TO5PH7O.js +304 -0
  118. package/dist/chunk-5U3JZP62.js +1352 -0
  119. package/dist/chunk-5VNFXIGF.js +85 -0
  120. package/dist/chunk-5XD2Y463.js +402 -0
  121. package/dist/chunk-63AENHJC.js +123 -0
  122. package/dist/chunk-673IFJYB.js +731 -0
  123. package/dist/chunk-6UVUJNLY.js +1186 -0
  124. package/dist/chunk-7AWH47AR.js +448 -0
  125. package/dist/chunk-7KPWYWYL.js +290 -0
  126. package/dist/chunk-7P4B6AEP.js +227 -0
  127. package/dist/chunk-7URNGDEY.js +2145 -0
  128. package/dist/chunk-7VHOALNC.js +244 -0
  129. package/dist/chunk-ADZQBZOX.js +122 -0
  130. package/dist/chunk-APSZAEDO.js +1186 -0
  131. package/dist/chunk-ASHF6VO4.js +2265 -0
  132. package/dist/chunk-ASJHCAVL.js +38 -0
  133. package/dist/chunk-BT2LEHIW.js +448 -0
  134. package/dist/chunk-BTS5QUWB.js +50 -0
  135. package/dist/chunk-BWJDJ3BS.js +604 -0
  136. package/dist/chunk-CME46VWP.js +150 -0
  137. package/dist/chunk-D3ICCKXY.js +54 -0
  138. package/dist/chunk-D3IOU3NO.js +377 -0
  139. package/dist/chunk-DFGXRKI2.js +221 -0
  140. package/dist/chunk-DICIFTCS.js +150 -0
  141. package/dist/chunk-DIFI5JDC.js +76 -0
  142. package/dist/chunk-DO65VHQZ.js +128 -0
  143. package/dist/chunk-DPOIJ5SM.js +284 -0
  144. package/dist/chunk-E2OMUBXQ.js +567 -0
  145. package/dist/chunk-ECMXIV6N.js +97 -0
  146. package/dist/chunk-EDMVA3PT.js +727 -0
  147. package/dist/chunk-F5OSXH4A.js +4388 -0
  148. package/dist/chunk-F5OWHPRG.js +236 -0
  149. package/dist/chunk-F7MZA3QP.js +199 -0
  150. package/dist/chunk-FAZNXNA5.js +33 -0
  151. package/dist/chunk-FCHG5RC4.js +197 -0
  152. package/dist/chunk-FFKSPZO2.js +157 -0
  153. package/dist/chunk-FNHYH5U6.js +331 -0
  154. package/dist/chunk-FRNXQSB4.js +134 -0
  155. package/dist/chunk-FTAASABV.js +362 -0
  156. package/dist/chunk-FWPDAQ6Q.js +1350 -0
  157. package/dist/chunk-FZB73QOI.js +210 -0
  158. package/dist/chunk-GBL5QSTM.js +197 -0
  159. package/dist/chunk-GJBR6QLD.js +630 -0
  160. package/dist/chunk-GRSYAHKI.js +535 -0
  161. package/dist/chunk-GRXWINOW.js +244 -0
  162. package/dist/chunk-GUPNVUG5.js +348 -0
  163. package/dist/chunk-GY66UPMX.js +167 -0
  164. package/dist/chunk-HCCG67BY.js +43 -0
  165. package/dist/chunk-HCSZZXZZ.js +197 -0
  166. package/dist/chunk-HNGNZU62.js +240 -0
  167. package/dist/chunk-HP2D5LIE.js +214 -0
  168. package/dist/chunk-HUABQHDC.js +1352 -0
  169. package/dist/chunk-HYKO2LNW.js +157 -0
  170. package/dist/chunk-IFL6DG2K.js +181 -0
  171. package/dist/chunk-IKPQRHVQ.js +304 -0
  172. package/dist/chunk-J5HFRVNW.js +362 -0
  173. package/dist/chunk-J6SD7LT2.js +171 -0
  174. package/dist/chunk-JCWA3X6A.js +402 -0
  175. package/dist/chunk-JHPK33IP.js +2162 -0
  176. package/dist/chunk-JURL2S27.js +128 -0
  177. package/dist/chunk-JWGDH5I2.js +127 -0
  178. package/dist/chunk-KBXQFXYM.js +567 -0
  179. package/dist/chunk-KGY5QIOJ.js +1350 -0
  180. package/dist/chunk-KLES22FB.js +1094 -0
  181. package/dist/chunk-KPUYYOFS.js +122 -0
  182. package/dist/chunk-KY43UELJ.js +331 -0
  183. package/dist/chunk-L32V4O5Z.js +58 -0
  184. package/dist/chunk-LAFARYU5.js +456 -0
  185. package/dist/chunk-LC7ETNTJ.js +1350 -0
  186. package/dist/chunk-LEJ5FKIK.js +55 -0
  187. package/dist/chunk-LNLLCAI4.js +377 -0
  188. package/dist/chunk-LQWZYMNU.js +448 -0
  189. package/dist/chunk-LSDXEHKL.js +381 -0
  190. package/dist/chunk-LY3SOO73.js +76 -0
  191. package/dist/chunk-M6CIHXXB.js +159 -0
  192. package/dist/chunk-MJOQ35DX.js +427 -0
  193. package/dist/chunk-MO5HER5Y.js +345 -0
  194. package/dist/chunk-MS2EOZJQ.js +290 -0
  195. package/dist/chunk-MUIMJGSQ.js +128 -0
  196. package/dist/chunk-MY4TGLT6.js +284 -0
  197. package/dist/chunk-N3ARGCVG.js +345 -0
  198. package/dist/chunk-N4XG2M2U.js +735 -0
  199. package/dist/chunk-N72JNFJ4.js +535 -0
  200. package/dist/chunk-NJMPNYBS.js +427 -0
  201. package/dist/chunk-NM3AUMFE.js +2145 -0
  202. package/dist/chunk-NPPQ3TR4.js +735 -0
  203. package/dist/chunk-NTWF4DAF.js +581 -0
  204. package/dist/chunk-NXL3VKXM.js +331 -0
  205. package/dist/chunk-OJACH2JF.js +128 -0
  206. package/dist/chunk-OMSLHEEF.js +456 -0
  207. package/dist/chunk-OO4IFABD.js +382 -0
  208. package/dist/chunk-OYIP3QVN.js +167 -0
  209. package/dist/chunk-P2IOW54H.js +668 -0
  210. package/dist/chunk-P5KXQ3RN.js +731 -0
  211. package/dist/chunk-P5UXP53T.js +81 -0
  212. package/dist/chunk-PH6VRRFR.js +395 -0
  213. package/dist/chunk-Q3GKOF7Z.js +85 -0
  214. package/dist/chunk-Q65NCNL4.js +1352 -0
  215. package/dist/chunk-QIGS2LRT.js +735 -0
  216. package/dist/chunk-QKBN3CY2.js +381 -0
  217. package/dist/chunk-QNNAVMQH.js +1094 -0
  218. package/dist/chunk-QODDW4YI.js +171 -0
  219. package/dist/chunk-QPAYPTSH.js +2162 -0
  220. package/dist/chunk-QRWDJ5RI.js +381 -0
  221. package/dist/chunk-RBFZCHVB.js +105 -0
  222. package/dist/chunk-RCEULTPF.js +185 -0
  223. package/dist/chunk-RCGHXBCX.js +630 -0
  224. package/dist/chunk-ROSCLRTH.js +204 -0
  225. package/dist/chunk-RYAOSGUW.js +227 -0
  226. package/dist/chunk-S2SPGHPY.js +38 -0
  227. package/dist/chunk-S73ZAJ2S.js +262 -0
  228. package/dist/chunk-SBPEWD7Z.js +171 -0
  229. package/dist/chunk-SDPUWZP5.js +333 -0
  230. package/dist/chunk-SJ4UF7YK.js +1094 -0
  231. package/dist/chunk-SOZ7D77I.js +204 -0
  232. package/dist/chunk-SVLSHDNL.js +54 -0
  233. package/dist/chunk-SVUYBT5N.js +262 -0
  234. package/dist/chunk-T7PTLVJV.js +284 -0
  235. package/dist/chunk-TDX2LK2M.js +240 -0
  236. package/dist/chunk-TGUSLO4B.js +50 -0
  237. package/dist/chunk-TPJH6PE6.js +1158 -0
  238. package/dist/chunk-TVW7EDOJ.js +382 -0
  239. package/dist/chunk-TYRUIE6P.js +58 -0
  240. package/dist/chunk-U5RKGLV6.js +50 -0
  241. package/dist/chunk-UFGTHBHP.js +127 -0
  242. package/dist/chunk-ULCYWCPI.js +1079 -0
  243. package/dist/chunk-UN5EPVBN.js +14597 -0
  244. package/dist/chunk-URLH7ZVR.js +70 -0
  245. package/dist/chunk-USYRTGR7.js +402 -0
  246. package/dist/chunk-V4ABCEHM.js +30 -0
  247. package/dist/chunk-V6LOEOXG.js +3372 -0
  248. package/dist/chunk-VAZOVAW4.js +2162 -0
  249. package/dist/chunk-VEUQVKKT.js +185 -0
  250. package/dist/chunk-VIDDJ5RF.js +214 -0
  251. package/dist/chunk-VKCNXOQ6.js +214 -0
  252. package/dist/chunk-VNB4ROYG.js +348 -0
  253. package/dist/chunk-VWUQFZFB.js +395 -0
  254. package/dist/chunk-W77GRCNA.js +85 -0
  255. package/dist/chunk-WB2B25UM.js +230 -0
  256. package/dist/chunk-WCUZX7F7.js +204 -0
  257. package/dist/chunk-WL5RMOZQ.js +362 -0
  258. package/dist/chunk-WPAXAOHD.js +1079 -0
  259. package/dist/chunk-WVMG4ZRH.js +14597 -0
  260. package/dist/chunk-WYVOTRRZ.js +129 -0
  261. package/dist/chunk-XABJRAUW.js +3346 -0
  262. package/dist/chunk-XQQ7D4I4.js +85 -0
  263. package/dist/chunk-YDFY6YCH.js +280 -0
  264. package/dist/chunk-YGUMRYCN.js +33 -0
  265. package/dist/chunk-YHJPTIPR.js +836 -0
  266. package/dist/chunk-YJSP5PPG.js +128 -0
  267. package/dist/chunk-YLKS7KKC.js +2145 -0
  268. package/dist/chunk-YOMETWOJ.js +4388 -0
  269. package/dist/chunk-YU3KEVCO.js +333 -0
  270. package/dist/chunk-Z4FVFSE3.js +81 -0
  271. package/dist/chunk-Z4TLSNUW.js +244 -0
  272. package/dist/chunk-ZDPU3JTF.js +221 -0
  273. package/dist/chunk-ZDY4LYAJ.js +81 -0
  274. package/dist/chunk-ZG33AACD.js +70 -0
  275. package/dist/chunk-ZKHPZ6KN.js +181 -0
  276. package/dist/chunk-ZO2TM5N5.js +97 -0
  277. package/dist/chunk-ZP6T5K6I.js +535 -0
  278. package/dist/chunk-ZR6ZJT32.js +123 -0
  279. package/dist/chunk-ZSUACDQC.js +4388 -0
  280. package/dist/co-activation-JGF5YIDU.js +74 -0
  281. package/dist/co-activation-XM25BLZM.js +74 -0
  282. package/dist/co-occurrence-CKEMDPWO.js +95 -0
  283. package/dist/co-occurrence-HLLC6GT2.js +95 -0
  284. package/dist/co-occurrence-W2LIAPHI.js +95 -0
  285. package/dist/code-context-index-FCL47WKE.js +30 -0
  286. package/dist/conversation-entity-extractor-WC2RU6RS.js +114 -0
  287. package/dist/core-memory-CRSR2PSL.js +110 -0
  288. package/dist/core-memory-VSKFRMEV.js +110 -0
  289. package/dist/core-memory-ZDA76EU3.js +110 -0
  290. package/dist/crdt-sync-6VH2YDVY.js +33 -0
  291. package/dist/crdt-sync-BJKZB6T6.js +33 -0
  292. package/dist/crm-webhook-E5PAFAUN.js +10 -0
  293. package/dist/crm-webhook-RXFPZJXP.js +10 -0
  294. package/dist/crm-webhook-Z26LEFKG.js +10 -0
  295. package/dist/cto-delegation-gate-45IBLPTK.js +280 -0
  296. package/dist/cto-delegation-gate-EMY6ZZ2F.js +280 -0
  297. package/dist/cto-delegation-gate-SF4EUB2Q.js +280 -0
  298. package/dist/daemon-orchestration-VB3BLYIT.js +143 -0
  299. package/dist/daemon-orchestration-W66UYGUD.js +143 -0
  300. package/dist/daemon-orchestration-Y5Y6YNE3.js +143 -0
  301. package/dist/db-backup-HFJ53IBU.js +43 -0
  302. package/dist/db-backup-NVUTS7L5.js +43 -0
  303. package/dist/doc-graph-extractor-ID45AQ2P.js +133 -0
  304. package/dist/doc-graph-extractor-MLYQYT4B.js +133 -0
  305. package/dist/doc-graph-extractor-SVFSXKL6.js +133 -0
  306. package/dist/dreaming-AZYRAGKA.js +34 -0
  307. package/dist/dreaming-N6B7KBIE.js +34 -0
  308. package/dist/dreaming-WG5CDUHX.js +34 -0
  309. package/dist/entity-boost-XAFCDDB6.js +375 -0
  310. package/dist/exe-drift-3SGA53CL.js +70 -0
  311. package/dist/exe-drift-CPUEAPIU.js +70 -0
  312. package/dist/exe-export-4RTGDV53.js +77 -0
  313. package/dist/exe-export-APUNLKWF.js +77 -0
  314. package/dist/exe-export-NM4SXB3P.js +77 -0
  315. package/dist/exe-import-6GLNCP62.js +80 -0
  316. package/dist/exe-import-AZMIF34Z.js +80 -0
  317. package/dist/exe-import-U4H4ES3Z.js +80 -0
  318. package/dist/exe-key-FIPXUTMF.js +673 -0
  319. package/dist/exe-key-LJV23AJI.js +673 -0
  320. package/dist/exe-key-WTLCMOYJ.js +673 -0
  321. package/dist/exe-snapshot-ILO3WSEC.js +338 -0
  322. package/dist/exe-snapshot-IODRQLBX.js +338 -0
  323. package/dist/exe-snapshot-ZOZBW7V6.js +338 -0
  324. package/dist/fast-db-init-7LYYUCSJ.js +7 -0
  325. package/dist/fast-db-init-ATRZGHOL.js +7 -0
  326. package/dist/fast-db-init-IU7GYFWB.js +7 -0
  327. package/dist/gateway/index.js +11 -11
  328. package/dist/git-staleness-GGCFPHQ5.js +112 -0
  329. package/dist/git-staleness-XNOKI4D3.js +112 -0
  330. package/dist/git-task-sweep-3MO4OVND.js +42 -0
  331. package/dist/git-task-sweep-M3SWXFKJ.js +42 -0
  332. package/dist/git-task-sweep-Y6KNWB67.js +42 -0
  333. package/dist/global-procedures-626WAU3I.js +22 -0
  334. package/dist/global-procedures-EBAPPWGZ.js +22 -0
  335. package/dist/graph-auto-extract-TKHQ4OR3.js +183 -0
  336. package/dist/graph-auto-extract-VGFEWFZX.js +183 -0
  337. package/dist/graph-auto-extract-VJOUQBPK.js +183 -0
  338. package/dist/graph-rag-KECA5TE4.js +35 -0
  339. package/dist/hooks/bug-report-worker.js +12 -12
  340. package/dist/hooks/codex-stop-task-finalizer.js +12 -12
  341. package/dist/hooks/commit-complete.js +12 -12
  342. package/dist/hooks/error-recall.js +6 -6
  343. package/dist/hooks/exe-heartbeat-hook.js +3 -3
  344. package/dist/hooks/ingest-worker.js +3 -3
  345. package/dist/hooks/ingest.js +6 -6
  346. package/dist/hooks/instructions-loaded.js +4 -4
  347. package/dist/hooks/manifest.json +20 -20
  348. package/dist/hooks/notification.js +4 -4
  349. package/dist/hooks/post-compact.js +12 -12
  350. package/dist/hooks/post-tool-combined.js +6 -6
  351. package/dist/hooks/pre-compact.js +16 -16
  352. package/dist/hooks/pre-tool-use.js +15 -15
  353. package/dist/hooks/prompt-submit.js +28 -26
  354. package/dist/hooks/session-end.js +20 -20
  355. package/dist/hooks/session-start.js +12 -12
  356. package/dist/hooks/stop.js +18 -18
  357. package/dist/hooks/subagent-stop.js +11 -11
  358. package/dist/hooks/summary-worker.js +18 -18
  359. package/dist/index.js +20 -20
  360. package/dist/installer-37KFNAWE.js +344 -0
  361. package/dist/installer-3FB5EMPB.js +40 -0
  362. package/dist/installer-BRQ42CPB.js +344 -0
  363. package/dist/installer-F55NR4E2.js +298 -0
  364. package/dist/installer-KOYBUS4J.js +40 -0
  365. package/dist/installer-PXZJG256.js +298 -0
  366. package/dist/lib/cloud-sync.js +13 -7
  367. package/dist/lib/consolidation.js +7 -7
  368. package/dist/lib/database.js +6 -4
  369. package/dist/lib/db-daemon-client.js +11 -202
  370. package/dist/lib/db.js +6 -4
  371. package/dist/lib/embedder.js +3 -3
  372. package/dist/lib/employee-templates.js +4 -4
  373. package/dist/lib/employees.js +2 -2
  374. package/dist/lib/exe-daemon-client.js +2 -2
  375. package/dist/lib/exe-daemon.js +53 -51
  376. package/dist/lib/hybrid-search.js +5 -5
  377. package/dist/lib/identity.js +2 -2
  378. package/dist/lib/messaging.js +10 -10
  379. package/dist/lib/reminders.js +3 -3
  380. package/dist/lib/schedules.js +5 -5
  381. package/dist/lib/session-registry.js +4 -4
  382. package/dist/lib/skill-learning.js +6 -6
  383. package/dist/lib/store.js +4 -4
  384. package/dist/lib/task-router.js +3 -3
  385. package/dist/lib/tasks.js +11 -11
  386. package/dist/lib/tmux-routing.js +9 -9
  387. package/dist/lib/token-spend.js +3 -3
  388. package/dist/mcp/register-tools.js +65 -63
  389. package/dist/mcp/server.js +66 -64
  390. package/dist/mcp/tools/complete-reminder.js +4 -4
  391. package/dist/mcp/tools/create-reminder.js +4 -4
  392. package/dist/mcp/tools/create-task.js +13 -13
  393. package/dist/mcp/tools/deactivate-behavior.js +7 -7
  394. package/dist/mcp/tools/list-reminders.js +4 -4
  395. package/dist/mcp/tools/list-tasks.js +13 -13
  396. package/dist/mcp/tools/send-message.js +12 -12
  397. package/dist/mcp/tools/update-task.js +12 -12
  398. package/dist/mcp-http-config-7KJZI7UD.js +31 -0
  399. package/dist/mcp-http-config-OF3MB7M5.js +31 -0
  400. package/dist/memory-cards-CPIZVXWI.js +180 -0
  401. package/dist/memory-cards-ZIT7ZKL5.js +180 -0
  402. package/dist/memory-graph-extractor-JIYWLBFF.js +22 -0
  403. package/dist/memory-graph-extractor-LY2VORZT.js +22 -0
  404. package/dist/memory-graph-extractor-MDPSLZDM.js +22 -0
  405. package/dist/memory-poisoning-defense-5UZT3WWA.js +224 -0
  406. package/dist/memory-poisoning-defense-SEM25TY5.js +224 -0
  407. package/dist/memory-queue-client-WKWRFERJ.js +16 -0
  408. package/dist/memory-reflection-J2W7CJ7C.js +244 -0
  409. package/dist/memory-reflection-TA2VQYPH.js +244 -0
  410. package/dist/message-queue-client-IFQQ2HI7.js +92 -0
  411. package/dist/notifications-CZBQ3H5T.js +47 -0
  412. package/dist/notifications-EIIL2EQV.js +47 -0
  413. package/dist/notifications-RLMSI4YE.js +47 -0
  414. package/dist/orchestration-events-TGQYA72K.js +27 -0
  415. package/dist/orchestration-events-VUYR6MXE.js +27 -0
  416. package/dist/orchestrator-JQD5G3CW.js +35 -0
  417. package/dist/orchestrator-MAMR4C37.js +35 -0
  418. package/dist/orchestrator-VE5WHEJH.js +35 -0
  419. package/dist/pipeline-router-3Q3YBYSM.js +15 -0
  420. package/dist/pipeline-router-DKXD6DJO.js +15 -0
  421. package/dist/pipeline-router-YNW63BY5.js +15 -0
  422. package/dist/plan-limits-YGXTYCW4.js +28 -0
  423. package/dist/plan-limits-ZM4MNZKY.js +28 -0
  424. package/dist/project-boot-E2TWYTAC.js +299 -0
  425. package/dist/project-boot-TDOZKKDR.js +299 -0
  426. package/dist/projection-worker-TMKUSVGD.js +1084 -0
  427. package/dist/projection-worker-WFPRM4AI.js +1084 -0
  428. package/dist/projection-worker-YKV3PFCV.js +1084 -0
  429. package/dist/prospective-memory-CNJDBNWF.js +232 -0
  430. package/dist/prospective-memory-OAFZUODU.js +232 -0
  431. package/dist/reranker-AFU75HEX.js +19 -0
  432. package/dist/reranker-RYNSJNDF.js +19 -0
  433. package/dist/reranker-YQIRNGDM.js +19 -0
  434. package/dist/retrieval-health-M5BVB7EV.js +12 -0
  435. package/dist/retrieval-health-RSQEIYIB.js +12 -0
  436. package/dist/review-polling-LGX7DUNT.js +126 -0
  437. package/dist/review-polling-MJBCYV4I.js +126 -0
  438. package/dist/review-polling-ZMB3OBPC.js +126 -0
  439. package/dist/runtime/index.js +16 -16
  440. package/dist/services/codex-reviewd/index.js +855 -0
  441. package/dist/session-events-5N47BRFK.js +38 -0
  442. package/dist/session-events-PT6SVS2P.js +38 -0
  443. package/dist/session-events-UTMCKDIN.js +38 -0
  444. package/dist/session-kill-telemetry-FRQA5MVD.js +31 -0
  445. package/dist/session-kill-telemetry-HKL2NQMR.js +31 -0
  446. package/dist/session-scope-2BD6QLNI.js +88 -0
  447. package/dist/session-scope-GQNCM6UQ.js +88 -0
  448. package/dist/session-scope-MMGM232A.js +88 -0
  449. package/dist/setup-wizard-SELXXVLD.js +12 -0
  450. package/dist/setup-wizard-W64I6SHC.js +12 -0
  451. package/dist/setup-wizard-X7YSRDNQ.js +12 -0
  452. package/dist/skill-refinement-CCP4ULZ3.js +159 -0
  453. package/dist/skill-refinement-FXCXTUS2.js +159 -0
  454. package/dist/skill-refinement-WCPDNHZ5.js +159 -0
  455. package/dist/stack-update-5VSGG36W.js +84 -0
  456. package/dist/steward-gate-JDR3SLH3.js +15 -0
  457. package/dist/steward-gate-PIXNK4BK.js +15 -0
  458. package/dist/task-enforcement-LEBWCYZT.js +506 -0
  459. package/dist/task-enforcement-VOSQRAQB.js +506 -0
  460. package/dist/task-enforcement-WCEA4FZI.js +506 -0
  461. package/dist/task-scope-CQZ33PRU.js +37 -0
  462. package/dist/task-scope-JTTEZKDU.js +37 -0
  463. package/dist/task-scope-L5GDL2AV.js +37 -0
  464. package/dist/tasks-crud-DC4GCXQQ.js +79 -0
  465. package/dist/tasks-crud-S36AFYYM.js +79 -0
  466. package/dist/tasks-crud-T32IRPXF.js +79 -0
  467. package/dist/tasks-notify-OBFVHJDP.js +40 -0
  468. package/dist/tasks-notify-OUQWUM6W.js +40 -0
  469. package/dist/tasks-notify-W2W2BJRB.js +40 -0
  470. package/dist/tasks-review-34WV7BX2.js +49 -0
  471. package/dist/tasks-review-N33MTHWJ.js +49 -0
  472. package/dist/tasks-review-OSBG2YN2.js +49 -0
  473. package/dist/telemetry-upload-3CSVO3J7.js +741 -0
  474. package/dist/telemetry-upload-EYHEWTKG.js +741 -0
  475. package/dist/telemetry-upload-XLBW4DRP.js +741 -0
  476. package/dist/token-budget-I6FMMDFX.js +86 -0
  477. package/dist/token-budget-ZG2MQ5GD.js +86 -0
  478. package/dist/tool-capability-index-IWQBQKM7.js +10 -0
  479. package/dist/tool-telemetry-2E3Z7CRV.js +17 -0
  480. package/dist/tool-telemetry-ODL4F2CW.js +17 -0
  481. package/dist/tui/App.js +17 -17
  482. package/dist/tui-data-VWT4Q5UT.js +260 -0
  483. package/dist/tui-data-XFBFBSBE.js +260 -0
  484. package/dist/tui-data-Z5UF7KEI.js +260 -0
  485. package/dist/wiki-acl-EUOPNUIQ.js +111 -0
  486. package/dist/wiki-acl-SZFHCEC4.js +111 -0
  487. package/dist/worker-gate-OOO6BWZ6.js +21 -0
  488. package/dist/worker-gate-OQMKAMP7.js +21 -0
  489. package/dist/worker-gate-ZPP3SZK6.js +21 -0
  490. package/dist/workflow-engine-P7WYJP2B.js +28 -0
  491. package/dist/workflow-engine-QY3IFFR2.js +28 -0
  492. package/dist/workflow-engine-UYNB5RTB.js +28 -0
  493. package/dist/worktree-CNOQZBNT.js +28 -0
  494. package/dist/worktree-H5C4LMQR.js +28 -0
  495. package/dist/worktree-sweep-KFWF3XZD.js +21 -0
  496. package/dist/worktree-sweep-SE7ITXC4.js +21 -0
  497. package/package.json +1 -1
  498. package/release-notes.json +117 -191
  499. package/src/commands/exe.md +18 -1
@@ -0,0 +1,1186 @@
1
+ import {
2
+ formatDegradations,
3
+ getRetrievalHealth
4
+ } from "./chunk-F7MZA3QP.js";
5
+ import {
6
+ buildRestartReport,
7
+ formatRestartReport
8
+ } from "./chunk-KQ4Z2G24.js";
9
+ import {
10
+ blobToVector
11
+ } from "./chunk-OTVEIJUQ.js";
12
+ import {
13
+ EXE_HOOK_MANIFEST,
14
+ LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS,
15
+ manifestEntryForCommand
16
+ } from "./chunk-L3TB7CC3.js";
17
+ import {
18
+ isMainModule
19
+ } from "./chunk-6Y4B3QF6.js";
20
+
21
+ // src/bin/exe-doctor.ts
22
+ import os from "os";
23
+ import { existsSync, readFileSync } from "fs";
24
+ import { spawn } from "child_process";
25
+ import path from "path";
26
+ import { randomUUID } from "crypto";
27
+
28
+ // src/lib/conflict-detector.ts
29
+ var DEFAULT_MAX_PAIRS = 100;
30
+ var SIM_LOW = 0.85;
31
+ var SIM_HIGH = 0.95;
32
+ var LLM_BATCH_SIZE = 15;
33
+ function cosineSimilarity(a, b) {
34
+ let dot = 0, normA = 0, normB = 0;
35
+ for (let i = 0; i < a.length; i++) {
36
+ dot += a[i] * b[i];
37
+ normA += a[i] * a[i];
38
+ normB += b[i] * b[i];
39
+ }
40
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
41
+ return denom === 0 ? 0 : dot / denom;
42
+ }
43
+ async function fetchMemoriesWithVectors(client, projectFilter, agentFilter2) {
44
+ let hasStatusCol = false;
45
+ try {
46
+ const info = await client.execute("PRAGMA table_info(memories)");
47
+ hasStatusCol = info.rows.some((r) => r.name === "status");
48
+ } catch {
49
+ }
50
+ const clauses = ["vector IS NOT NULL"];
51
+ if (hasStatusCol) clauses.push("status = 'active'");
52
+ const args = [];
53
+ if (projectFilter) {
54
+ clauses.push("project_name = ?");
55
+ args.push(projectFilter);
56
+ }
57
+ if (agentFilter2) {
58
+ clauses.push("agent_id = ?");
59
+ args.push(agentFilter2);
60
+ }
61
+ const where = " WHERE " + clauses.join(" AND ");
62
+ const result = await client.execute({
63
+ sql: `SELECT id, agent_id, raw_text, timestamp, project_name, vector
64
+ FROM memories${where}
65
+ ORDER BY project_name, timestamp DESC`,
66
+ args
67
+ });
68
+ const byProject = /* @__PURE__ */ new Map();
69
+ for (const row of result.rows) {
70
+ const project = row.project_name;
71
+ const vec = row.vector == null ? null : Array.isArray(row.vector) ? row.vector : blobToVector(row.vector);
72
+ if (!vec || vec.length === 0) continue;
73
+ const mem = {
74
+ id: row.id,
75
+ agent_id: row.agent_id,
76
+ raw_text: row.raw_text,
77
+ timestamp: row.timestamp,
78
+ vector: vec
79
+ };
80
+ const list = byProject.get(project);
81
+ if (list) list.push(mem);
82
+ else byProject.set(project, [mem]);
83
+ }
84
+ return byProject;
85
+ }
86
+ function findCandidatePairs(memories, maxPairs) {
87
+ const pairs = [];
88
+ for (let i = 0; i < memories.length && pairs.length < maxPairs; i++) {
89
+ for (let j = i + 1; j < memories.length && pairs.length < maxPairs; j++) {
90
+ const sim = cosineSimilarity(memories[i].vector, memories[j].vector);
91
+ if (sim >= SIM_LOW && sim <= SIM_HIGH) {
92
+ pairs.push({ a: memories[i], b: memories[j], similarity: sim });
93
+ }
94
+ }
95
+ }
96
+ pairs.sort((x, y) => y.similarity - x.similarity);
97
+ return pairs;
98
+ }
99
+ async function classifyPairsBatch(pairs) {
100
+ const Anthropic = (await import("@anthropic-ai/sdk")).default;
101
+ const client = new Anthropic();
102
+ const pairDescriptions = pairs.map(
103
+ (p, i) => `Pair ${i + 1}:
104
+ Memory A (${p.a.agent_id}, ${p.a.timestamp}): "${p.a.raw_text.slice(0, 300)}"
105
+ Memory B (${p.b.agent_id}, ${p.b.timestamp}): "${p.b.raw_text.slice(0, 300)}"`
106
+ ).join("\n\n");
107
+ const prompt = `You are classifying pairs of memory records for contradictions.
108
+
109
+ For each pair, classify as:
110
+ - AGREE: Both memories say the same thing (no action needed).
111
+ - CONFLICT: The memories contradict each other (one must be wrong).
112
+ - SUPERSEDED: One memory replaces/updates the other (the older one is outdated).
113
+
114
+ Respond with a JSON array. Each element: {"pair": <1-indexed>, "classification": "AGREE"|"CONFLICT"|"SUPERSEDED", "explanation": "<brief reason>"}
115
+
116
+ ${pairDescriptions}
117
+
118
+ Respond ONLY with the JSON array, no markdown fences.`;
119
+ const response = await client.messages.create({
120
+ model: "claude-haiku-4-5-20251001",
121
+ max_tokens: 1024,
122
+ messages: [{ role: "user", content: prompt }]
123
+ });
124
+ const text = response.content[0]?.type === "text" ? response.content[0].text : "";
125
+ try {
126
+ const parsed = JSON.parse(text);
127
+ return parsed.map((r) => ({
128
+ classification: ["AGREE", "CONFLICT", "SUPERSEDED"].includes(
129
+ r.classification
130
+ ) ? r.classification : "AGREE",
131
+ explanation: r.explanation ?? ""
132
+ }));
133
+ } catch {
134
+ return pairs.map(() => ({
135
+ classification: "AGREE",
136
+ explanation: "LLM response parse error"
137
+ }));
138
+ }
139
+ }
140
+ function recommend(classification) {
141
+ switch (classification) {
142
+ case "CONFLICT":
143
+ return "manual_review";
144
+ case "SUPERSEDED":
145
+ return "deactivate_older";
146
+ case "AGREE":
147
+ return "merge";
148
+ case "UNCLASSIFIED":
149
+ return "none";
150
+ }
151
+ }
152
+ async function detectConflicts(client, projectFilter, agentFilter2) {
153
+ const maxPairs = parseInt(
154
+ process.env.CONFLICT_MAX_PAIRS ?? String(DEFAULT_MAX_PAIRS),
155
+ 10
156
+ );
157
+ const byProject = await fetchMemoriesWithVectors(
158
+ client,
159
+ projectFilter,
160
+ agentFilter2
161
+ );
162
+ const allCandidates = [];
163
+ for (const [, memories] of byProject) {
164
+ if (memories.length < 2) continue;
165
+ const candidates2 = findCandidatePairs(
166
+ memories,
167
+ maxPairs - allCandidates.length
168
+ );
169
+ allCandidates.push(...candidates2);
170
+ if (allCandidates.length >= maxPairs) break;
171
+ }
172
+ if (allCandidates.length === 0) {
173
+ return {
174
+ candidateCount: 0,
175
+ classified: 0,
176
+ conflicts: 0,
177
+ superseded: 0,
178
+ agree: 0,
179
+ unclassified: 0,
180
+ pairs: [],
181
+ skipped: false
182
+ };
183
+ }
184
+ const truncated = allCandidates.length > maxPairs;
185
+ const candidates = allCandidates.slice(0, maxPairs);
186
+ const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
187
+ const pairs = [];
188
+ if (hasApiKey) {
189
+ for (let i = 0; i < candidates.length; i += LLM_BATCH_SIZE) {
190
+ const batch = candidates.slice(i, i + LLM_BATCH_SIZE);
191
+ try {
192
+ const results = await classifyPairsBatch(batch);
193
+ for (let j = 0; j < batch.length; j++) {
194
+ const c = batch[j];
195
+ const r = results[j] ?? {
196
+ classification: "AGREE",
197
+ explanation: "No result"
198
+ };
199
+ pairs.push({
200
+ memoryA: {
201
+ id: c.a.id,
202
+ agentId: c.a.agent_id,
203
+ text: c.a.raw_text,
204
+ timestamp: c.a.timestamp
205
+ },
206
+ memoryB: {
207
+ id: c.b.id,
208
+ agentId: c.b.agent_id,
209
+ text: c.b.raw_text,
210
+ timestamp: c.b.timestamp
211
+ },
212
+ similarity: c.similarity,
213
+ classification: r.classification,
214
+ explanation: r.explanation,
215
+ recommendation: recommend(r.classification)
216
+ });
217
+ }
218
+ } catch (err) {
219
+ for (const c of batch) {
220
+ pairs.push({
221
+ memoryA: {
222
+ id: c.a.id,
223
+ agentId: c.a.agent_id,
224
+ text: c.a.raw_text,
225
+ timestamp: c.a.timestamp
226
+ },
227
+ memoryB: {
228
+ id: c.b.id,
229
+ agentId: c.b.agent_id,
230
+ text: c.b.raw_text,
231
+ timestamp: c.b.timestamp
232
+ },
233
+ similarity: c.similarity,
234
+ classification: "UNCLASSIFIED",
235
+ explanation: `LLM error: ${err instanceof Error ? err.message : String(err)}`,
236
+ recommendation: "none"
237
+ });
238
+ }
239
+ }
240
+ }
241
+ } else {
242
+ for (const c of candidates) {
243
+ pairs.push({
244
+ memoryA: {
245
+ id: c.a.id,
246
+ agentId: c.a.agent_id,
247
+ text: c.a.raw_text,
248
+ timestamp: c.a.timestamp
249
+ },
250
+ memoryB: {
251
+ id: c.b.id,
252
+ agentId: c.b.agent_id,
253
+ text: c.b.raw_text,
254
+ timestamp: c.b.timestamp
255
+ },
256
+ similarity: c.similarity,
257
+ classification: "UNCLASSIFIED",
258
+ explanation: "ANTHROPIC_API_KEY not set \u2014 skipped LLM classification",
259
+ recommendation: "none"
260
+ });
261
+ }
262
+ }
263
+ const severityOrder = { CONFLICT: 0, SUPERSEDED: 1, UNCLASSIFIED: 2, AGREE: 3 };
264
+ pairs.sort(
265
+ (a, b) => severityOrder[a.classification] - severityOrder[b.classification]
266
+ );
267
+ const conflicts = pairs.filter((p) => p.classification === "CONFLICT").length;
268
+ const superseded = pairs.filter(
269
+ (p) => p.classification === "SUPERSEDED"
270
+ ).length;
271
+ const agree = pairs.filter((p) => p.classification === "AGREE").length;
272
+ const unclassified = pairs.filter(
273
+ (p) => p.classification === "UNCLASSIFIED"
274
+ ).length;
275
+ return {
276
+ candidateCount: candidates.length,
277
+ classified: conflicts + superseded + agree,
278
+ conflicts,
279
+ superseded,
280
+ agree,
281
+ unclassified,
282
+ pairs,
283
+ skipped: truncated,
284
+ skipReason: truncated ? `Exceeded max ${maxPairs} pairs \u2014 increase CONFLICT_MAX_PAIRS to analyze more` : void 0
285
+ };
286
+ }
287
+
288
+ // src/bin/exe-doctor.ts
289
+ function parseFlags(argv) {
290
+ const flags = { fix: false, dryRun: false, verbose: false, conflicts: false, restarts: false };
291
+ for (let i = 0; i < argv.length; i++) {
292
+ const arg = argv[i];
293
+ if (arg === "--fix") flags.fix = true;
294
+ else if (arg === "--dry-run") flags.dryRun = true;
295
+ else if (arg === "--verbose") flags.verbose = true;
296
+ else if (arg === "--conflicts") flags.conflicts = true;
297
+ else if (arg === "--restarts" || arg === "--daemon-restarts") flags.restarts = true;
298
+ else if (arg === "--agent" && argv[i + 1]) flags.agent = argv[++i];
299
+ else if (arg === "--project" && argv[i + 1]) flags.project = argv[++i];
300
+ }
301
+ return flags;
302
+ }
303
+ function agentFilter(flags) {
304
+ const clauses = [];
305
+ const args = [];
306
+ if (flags.agent) {
307
+ clauses.push("agent_id = ?");
308
+ args.push(flags.agent);
309
+ }
310
+ if (flags.project) {
311
+ clauses.push("project_name = ?");
312
+ args.push(flags.project);
313
+ }
314
+ const clause = clauses.length > 0 ? " WHERE " + clauses.join(" AND ") : "";
315
+ return { clause, args };
316
+ }
317
+ async function auditStats(client, flags) {
318
+ const { clause, args } = agentFilter(flags);
319
+ const summary = await client.execute({
320
+ sql: `SELECT COUNT(*) as total,
321
+ COUNT(DISTINCT agent_id) as agents,
322
+ COUNT(DISTINCT project_name) as projects,
323
+ MIN(timestamp) as oldest,
324
+ MAX(timestamp) as newest
325
+ FROM memories${clause}`,
326
+ args
327
+ });
328
+ const row = summary.rows[0];
329
+ const perAgent = await client.execute({
330
+ sql: `SELECT agent_id, COUNT(*) as count,
331
+ SUM(CASE WHEN vector IS NULL THEN 1 ELSE 0 END) as null_vectors
332
+ FROM memories${clause}
333
+ GROUP BY agent_id
334
+ ORDER BY count DESC`,
335
+ args
336
+ });
337
+ return {
338
+ total: Number(row.total),
339
+ agents: Number(row.agents),
340
+ projects: Number(row.projects),
341
+ oldest: row.oldest ?? null,
342
+ newest: row.newest ?? null,
343
+ perAgent: perAgent.rows.map((r) => ({
344
+ agent_id: r.agent_id,
345
+ count: Number(r.count),
346
+ null_vectors: Number(r.null_vectors)
347
+ }))
348
+ };
349
+ }
350
+ async function auditNullVectors(client, flags) {
351
+ const { clause, args } = agentFilter(flags);
352
+ const where = clause ? clause + " AND vector IS NULL" : " WHERE vector IS NULL";
353
+ const result = await client.execute({
354
+ sql: `SELECT COUNT(*) as cnt FROM memories${where}`,
355
+ args
356
+ });
357
+ return Number(result.rows[0].cnt);
358
+ }
359
+ async function auditDuplicates(client, flags) {
360
+ const { clause, args } = agentFilter(flags);
361
+ const backfillExclude = clause ? " AND tool_name != 'ConversationBackfill'" : " WHERE tool_name != 'ConversationBackfill'";
362
+ const groups = await client.execute({
363
+ sql: `SELECT SUBSTR(raw_text, 1, 200) as text_head, LENGTH(raw_text) as text_len, COUNT(*) as cnt
364
+ FROM memories${clause}${backfillExclude}
365
+ GROUP BY text_head, text_len
366
+ HAVING cnt > 1
367
+ ORDER BY cnt DESC
368
+ LIMIT 500`,
369
+ args
370
+ });
371
+ const duplicates = [];
372
+ for (const g of groups.rows) {
373
+ const textHead = g.text_head;
374
+ const textLen = Number(g.text_len);
375
+ const filterArgs = [textHead, textLen, ...args];
376
+ let filterClause = " WHERE SUBSTR(raw_text, 1, 200) = ? AND LENGTH(raw_text) = ?";
377
+ if (flags.agent) filterClause += " AND agent_id = ?";
378
+ if (flags.project) filterClause += " AND project_name = ?";
379
+ const ids = await client.execute({
380
+ sql: `SELECT id, raw_text FROM memories${filterClause} ORDER BY timestamp DESC LIMIT 10000`,
381
+ args: filterArgs
382
+ });
383
+ const byText = /* @__PURE__ */ new Map();
384
+ for (const r of ids.rows) {
385
+ const text = r.raw_text;
386
+ const id = r.id;
387
+ const existing = byText.get(text);
388
+ if (existing) existing.push(id);
389
+ else byText.set(text, [id]);
390
+ }
391
+ for (const [text, allIds] of byText) {
392
+ if (allIds.length <= 1) continue;
393
+ duplicates.push({
394
+ raw_text: text.length > 100 ? text.slice(0, 100) + "..." : text,
395
+ count: allIds.length,
396
+ keep_id: allIds[0],
397
+ delete_ids: allIds.slice(1)
398
+ });
399
+ }
400
+ }
401
+ return duplicates;
402
+ }
403
+ async function auditBloated(client, flags) {
404
+ const { clause, args } = agentFilter(flags);
405
+ const where = clause ? clause + " AND LENGTH(raw_text) > 5120 AND tool_name != 'ConversationBackfill'" : " WHERE LENGTH(raw_text) > 5120 AND tool_name != 'ConversationBackfill'";
406
+ const result = await client.execute({
407
+ sql: `SELECT id, agent_id, LENGTH(raw_text) as size, tool_name
408
+ FROM memories${where}
409
+ ORDER BY size DESC
410
+ LIMIT 100`,
411
+ args
412
+ });
413
+ return result.rows.map((r) => ({
414
+ id: r.id,
415
+ agent_id: r.agent_id,
416
+ size: Number(r.size),
417
+ tool_name: r.tool_name
418
+ }));
419
+ }
420
+ async function auditFts(client) {
421
+ const memCount = await client.execute("SELECT COUNT(*) as cnt FROM memories");
422
+ const ftsCount = await client.execute("SELECT COUNT(*) as cnt FROM memories_fts");
423
+ const mc = Number(memCount.rows[0].cnt);
424
+ const fc = Number(ftsCount.rows[0].cnt);
425
+ return { memoryCount: mc, ftsCount: fc, inSync: mc === fc };
426
+ }
427
+ async function auditOrphanedProjects(client) {
428
+ const result = await client.execute(
429
+ `SELECT project_name, COUNT(*) as cnt
430
+ FROM memories
431
+ WHERE tool_name != 'ConversationBackfill'
432
+ GROUP BY project_name
433
+ ORDER BY cnt DESC`
434
+ );
435
+ const orphans = [];
436
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
437
+ for (const row of result.rows) {
438
+ const name = row.project_name;
439
+ const count = Number(row.cnt);
440
+ const exists = existsSync(path.join(home, name)) || existsSync(path.join(home, "..", name)) || existsSync(path.join(process.cwd(), "..", name));
441
+ if (!exists) {
442
+ orphans.push({ project_name: name, count });
443
+ }
444
+ }
445
+ return orphans;
446
+ }
447
+ function auditHookHealth() {
448
+ const logPath = path.join(
449
+ process.env.HOME ?? process.env.USERPROFILE ?? "",
450
+ ".exe-os",
451
+ "logs",
452
+ "hooks.log"
453
+ );
454
+ if (!existsSync(logPath)) {
455
+ return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
456
+ }
457
+ let content;
458
+ try {
459
+ content = readFileSync(logPath, "utf-8");
460
+ } catch {
461
+ return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
462
+ }
463
+ const lines = content.split("\n").filter(Boolean);
464
+ const totalLines = lines.length;
465
+ const recent = lines.slice(-200);
466
+ const oneHourAgo = new Date(Date.now() - 36e5).toISOString();
467
+ let errorsLastHour = 0;
468
+ const patternCounts = /* @__PURE__ */ new Map();
469
+ for (const line of recent) {
470
+ const isError = /error|Error|ERR|FAIL|throw|exception|TypeError|ReferenceError|SyntaxError/i.test(line);
471
+ if (!isError) continue;
472
+ const tsMatch = line.match(/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})/);
473
+ if (tsMatch && tsMatch[1] >= oneHourAgo) {
474
+ errorsLastHour++;
475
+ } else if (!tsMatch) {
476
+ errorsLastHour++;
477
+ }
478
+ const patternMatch = line.match(/((?:TypeError|ReferenceError|SyntaxError|Error):[^\n]{0,80})/);
479
+ if (patternMatch) {
480
+ const p = patternMatch[1];
481
+ patternCounts.set(p, (patternCounts.get(p) ?? 0) + 1);
482
+ }
483
+ }
484
+ const topPatterns = [...patternCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([pattern, count]) => ({ pattern, count }));
485
+ return { logExists: true, totalLines, errorsLastHour, topPatterns };
486
+ }
487
+ function safeReadJson(filePath) {
488
+ if (!existsSync(filePath)) return null;
489
+ try {
490
+ return JSON.parse(readFileSync(filePath, "utf-8"));
491
+ } catch {
492
+ return null;
493
+ }
494
+ }
495
+ function collectHookCommandsFromClaudeSettings(settings) {
496
+ const hooks = settings?.hooks;
497
+ if (!hooks || typeof hooks !== "object") return [];
498
+ const commands = [];
499
+ for (const [event, groups] of Object.entries(hooks)) {
500
+ if (!Array.isArray(groups)) continue;
501
+ for (const group of groups) {
502
+ const hooksForGroup = group?.hooks;
503
+ if (!Array.isArray(hooksForGroup)) continue;
504
+ for (const hook of hooksForGroup) {
505
+ const command = hook?.command;
506
+ if (typeof command === "string") commands.push({ event, command });
507
+ }
508
+ }
509
+ }
510
+ return commands;
511
+ }
512
+ function collectHookCommandsFromCodexHooks(config) {
513
+ const commands = [];
514
+ if (!config || typeof config !== "object") return commands;
515
+ const root = config;
516
+ for (const [event, value] of Object.entries(root)) {
517
+ const entries = Array.isArray(value) ? value : value && typeof value === "object" ? Object.values(value) : [];
518
+ for (const entry of entries) {
519
+ if (typeof entry === "string") commands.push({ event, command: entry });
520
+ const command = entry?.command;
521
+ if (typeof command === "string") commands.push({ event, command });
522
+ }
523
+ }
524
+ return commands;
525
+ }
526
+ function buildHookOwnershipIssues(runtime, commands) {
527
+ const issues = [];
528
+ for (const marker of LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS) {
529
+ const count = commands.filter((cmd) => cmd.command.includes(marker)).length;
530
+ if (count > 0) {
531
+ issues.push({
532
+ runtime,
533
+ event: "PostToolUse",
534
+ marker,
535
+ count,
536
+ message: `Legacy split PostToolUse hook still installed: ${marker}`
537
+ });
538
+ }
539
+ }
540
+ for (const entry of EXE_HOOK_MANIFEST.filter((hook) => hook.runtimes.includes(runtime))) {
541
+ const matching = commands.filter((cmd) => cmd.command.includes(entry.commandMarker));
542
+ if (matching.length > 1) {
543
+ issues.push({
544
+ runtime,
545
+ event: entry.event,
546
+ marker: entry.commandMarker,
547
+ count: matching.length,
548
+ message: `Duplicate exe-os hook owner for ${entry.event}: ${entry.commandMarker}`
549
+ });
550
+ }
551
+ for (const cmd of matching) {
552
+ if (cmd.event !== entry.event) {
553
+ issues.push({
554
+ runtime,
555
+ event: cmd.event,
556
+ marker: entry.commandMarker,
557
+ count: 1,
558
+ message: `exe-os hook ${entry.commandMarker} is registered under ${cmd.event}, expected ${entry.event}`
559
+ });
560
+ }
561
+ }
562
+ }
563
+ for (const cmd of commands) {
564
+ if (!cmd.command.includes("dist/hooks/")) continue;
565
+ if (!cmd.command.includes("exe-os")) continue;
566
+ const entry = manifestEntryForCommand(cmd.command);
567
+ const isLegacy = LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS.some((marker) => cmd.command.includes(marker));
568
+ if (!entry && !isLegacy) {
569
+ issues.push({
570
+ runtime,
571
+ event: cmd.event,
572
+ marker: "dist/hooks/",
573
+ count: 1,
574
+ message: `Unknown exe-os hook command not present in ownership manifest: ${cmd.command.slice(0, 160)}`
575
+ });
576
+ }
577
+ }
578
+ return issues;
579
+ }
580
+ function auditHookOwnership() {
581
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
582
+ const checkedFiles = [];
583
+ const issues = [];
584
+ const claudeSettingsPath = path.join(home, ".claude", "settings.json");
585
+ const claudeSettings = safeReadJson(claudeSettingsPath);
586
+ if (claudeSettings) {
587
+ checkedFiles.push(claudeSettingsPath);
588
+ issues.push(...buildHookOwnershipIssues("claude", collectHookCommandsFromClaudeSettings(claudeSettings)));
589
+ }
590
+ const codexHooksPath = path.join(home, ".codex", "hooks.json");
591
+ const codexHooks = safeReadJson(codexHooksPath);
592
+ if (codexHooks) {
593
+ checkedFiles.push(codexHooksPath);
594
+ issues.push(...buildHookOwnershipIssues("codex", collectHookCommandsFromCodexHooks(codexHooks)));
595
+ }
596
+ return {
597
+ checkedFiles,
598
+ issues,
599
+ staleLegacyHooks: issues.filter((issue) => issue.message.includes("Legacy split"))
600
+ };
601
+ }
602
+ async function auditShards() {
603
+ try {
604
+ const { auditShardHealth } = await import("./shard-manager-P5ZJH4AX.js");
605
+ const report = await auditShardHealth();
606
+ return {
607
+ total: report.total,
608
+ ok: report.ok,
609
+ unreadable: report.unreadable,
610
+ schemaMismatches: report.schemaMismatches,
611
+ archived: report.archived,
612
+ unreadableNames: report.shards.filter((s) => s.unreadable).map((s) => s.name),
613
+ schemaIssueNames: report.shards.filter((s) => s.schemaIssues.length > 0).map((s) => `${s.name}: ${s.schemaIssues.join(", ")}`)
614
+ };
615
+ } catch {
616
+ return { total: 0, ok: 0, unreadable: 0, schemaMismatches: 0, archived: 0, unreadableNames: [], schemaIssueNames: [] };
617
+ }
618
+ }
619
+ async function auditKeyHealth() {
620
+ try {
621
+ const { getMasterKey } = await import("./lib/keychain.js");
622
+ const { getKeyBackupStatus } = await import("./key-backup-status-2EPRIAXU.js");
623
+ const key = await getMasterKey();
624
+ const backup = getKeyBackupStatus();
625
+ return {
626
+ masterKeyPresent: Boolean(key),
627
+ recoveryBackupMarked: backup.exists,
628
+ recoveryBackupConfirmedAt: backup.confirmedAt,
629
+ recoveryBackupSource: backup.source
630
+ };
631
+ } catch {
632
+ return { masterKeyPresent: false, recoveryBackupMarked: false };
633
+ }
634
+ }
635
+ async function auditOutbox() {
636
+ try {
637
+ const { getOutboxStatus } = await import("./support-outbox-QPQQK7F7.js");
638
+ return await getOutboxStatus();
639
+ } catch {
640
+ return {
641
+ bugReports: { total: 0, unsent: 0 },
642
+ featureRequests: { total: 0, unsent: 0 }
643
+ };
644
+ }
645
+ }
646
+ async function auditCpuSteal() {
647
+ try {
648
+ const { checkCpuSteal } = await import("./cpu-steal-5YKTUPWF.js");
649
+ const result = await checkCpuSteal();
650
+ return {
651
+ available: result.available,
652
+ stealPercent: result.stealPercent,
653
+ severity: result.severity,
654
+ source: result.source,
655
+ message: result.message
656
+ };
657
+ } catch {
658
+ return {
659
+ available: false,
660
+ stealPercent: null,
661
+ severity: "na",
662
+ source: "none",
663
+ message: "CPU steal check unavailable"
664
+ };
665
+ }
666
+ }
667
+ async function runAudit(client, flags) {
668
+ const runConflicts = flags.conflicts || process.env.EXE_AUDIT_CONFLICTS === "1";
669
+ const [stats, nullVectors, duplicates, bloated, fts, orphanedProjects, shards, keyHealth, outbox, cpuSteal] = await Promise.all([
670
+ auditStats(client, flags),
671
+ auditNullVectors(client, flags),
672
+ auditDuplicates(client, flags),
673
+ auditBloated(client, flags),
674
+ auditFts(client),
675
+ auditOrphanedProjects(client),
676
+ auditShards(),
677
+ auditKeyHealth(),
678
+ auditOutbox(),
679
+ auditCpuSteal()
680
+ ]);
681
+ let conflicts;
682
+ if (runConflicts) {
683
+ conflicts = await detectConflicts(client, flags.project, flags.agent);
684
+ } else {
685
+ conflicts = {
686
+ candidateCount: 0,
687
+ classified: 0,
688
+ conflicts: 0,
689
+ superseded: 0,
690
+ agree: 0,
691
+ unclassified: 0,
692
+ pairs: [],
693
+ skipped: true,
694
+ skipReason: "Conflict detection skipped (O(n\xB2) on 97K memories). Use --conflicts flag to enable."
695
+ };
696
+ }
697
+ const duplicateCount = duplicates.reduce((sum, d) => sum + d.delete_ids.length, 0);
698
+ const hookHealth = auditHookHealth();
699
+ const hookOwnership = auditHookOwnership();
700
+ let retrievalHealth;
701
+ try {
702
+ retrievalHealth = await getRetrievalHealth();
703
+ } catch {
704
+ retrievalHealth = void 0;
705
+ }
706
+ return { stats, nullVectors, duplicates, duplicateCount, bloated, fts, orphanedProjects, conflicts, hookHealth, hookOwnership, shards, keyHealth, outbox, cpuSteal, retrievalHealth };
707
+ }
708
+ function indicator(value, warn) {
709
+ if (value === 0) return "\u{1F7E2}";
710
+ if (value <= warn) return "\u{1F7E0}";
711
+ return "\u{1F534}";
712
+ }
713
+ function pct(count, total) {
714
+ if (total === 0) return "0.0%";
715
+ return (count / total * 100).toFixed(1) + "%";
716
+ }
717
+ function fmtNum(n) {
718
+ return n.toLocaleString("en-US");
719
+ }
720
+ function formatReport(report, flags) {
721
+ const lines = [];
722
+ const s = report.stats;
723
+ lines.push("");
724
+ lines.push("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
725
+ lines.push("\u2551 Memory Health Report \u2551");
726
+ lines.push("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
727
+ lines.push("");
728
+ lines.push(`Total: ${fmtNum(s.total)} memories across ${s.agents} agents, ${s.projects} projects`);
729
+ if (s.oldest && s.newest) {
730
+ lines.push(`Date range: ${s.oldest.slice(0, 10)} \u2192 ${s.newest.slice(0, 10)}`);
731
+ }
732
+ lines.push("");
733
+ if (s.perAgent.length > 0) {
734
+ lines.push("By agent:");
735
+ for (const a of s.perAgent) {
736
+ const nullNote = a.null_vectors > 0 ? ` (${fmtNum(a.null_vectors)} null vectors)` : "";
737
+ lines.push(` ${a.agent_id.padEnd(12)} ${fmtNum(a.count).padStart(8)}${nullNote}`);
738
+ }
739
+ lines.push("");
740
+ }
741
+ const totalMemGB = os.totalmem() / (1024 * 1024 * 1024);
742
+ const isLowMemSystem = totalMemGB <= 8;
743
+ if (isLowMemSystem && report.nullVectors > 0) {
744
+ lines.push(`\u{1F7E2} Null vectors: ${fmtNum(report.nullVectors)} / ${fmtNum(s.total)} (expected \u2014 8GB system, keyword search mode)`);
745
+ } else {
746
+ lines.push(`${indicator(report.nullVectors, 50)} Null vectors: ${fmtNum(report.nullVectors)} / ${fmtNum(s.total)} (${pct(report.nullVectors, s.total)})`);
747
+ }
748
+ const dupPct = s.total > 0 ? report.duplicateCount / s.total * 100 : 0;
749
+ const dupIndicator = dupPct === 0 ? "\u{1F7E2}" : dupPct <= 5 ? "\u{1F7E0}" : "\u{1F534}";
750
+ lines.push(`${dupIndicator} Duplicates: ${fmtNum(report.duplicateCount)} / ${fmtNum(s.total)} (${pct(report.duplicateCount, s.total)})`);
751
+ lines.push(`${indicator(report.bloated.length, 20)} Bloated (>5KB): ${fmtNum(report.bloated.length)} / ${fmtNum(s.total)} (${pct(report.bloated.length, s.total)})`);
752
+ const ftsIndicator = report.fts.inSync ? "\u{1F7E2}" : "\u{1F534}";
753
+ lines.push(`${ftsIndicator} FTS index: ${report.fts.inSync ? "in sync" : "OUT OF SYNC"} (${fmtNum(report.fts.memoryCount)} / ${fmtNum(report.fts.ftsCount)})`);
754
+ const kh = report.keyHealth;
755
+ if (!kh.masterKeyPresent) {
756
+ lines.push("\u{1F534} Recovery key: master key missing \u2014 import phrase or run setup before syncing");
757
+ } else if (!kh.recoveryBackupMarked) {
758
+ lines.push("\u{1F534} Recovery backup: not confirmed \u2014 run `exe-os cloud link --show-full` in your local Terminal and save the 24-word phrase");
759
+ } else {
760
+ const suffix = kh.recoveryBackupConfirmedAt ? ` (${kh.recoveryBackupConfirmedAt.slice(0, 10)}${kh.recoveryBackupSource ? ` via ${kh.recoveryBackupSource}` : ""})` : "";
761
+ lines.push(`\u{1F7E2} Recovery backup: confirmed${suffix}`);
762
+ }
763
+ if (report.orphanedProjects.length > 0) {
764
+ const orphanList = report.orphanedProjects.map((o) => `${o.project_name} \u2014 ${o.count} memories`).join(", ");
765
+ lines.push(`\u2139\uFE0F Orphaned projects: ${report.orphanedProjects.length} (${orphanList})`);
766
+ }
767
+ const cr = report.conflicts;
768
+ if (cr.candidateCount > 0) {
769
+ const conflictIndicator = cr.conflicts > 0 ? "\u{1F534}" : cr.superseded > 0 ? "\u{1F7E0}" : "\u{1F7E2}";
770
+ lines.push(`${conflictIndicator} Conflicts: ${fmtNum(cr.candidateCount)} candidate pairs`);
771
+ if (cr.classified > 0) {
772
+ lines.push(` CONFLICT: ${cr.conflicts}, SUPERSEDED: ${cr.superseded}, AGREE: ${cr.agree}`);
773
+ }
774
+ if (cr.unclassified > 0) {
775
+ lines.push(` Unclassified: ${cr.unclassified}`);
776
+ }
777
+ if (cr.skipped) {
778
+ lines.push(` \u26A0\uFE0F ${cr.skipReason}`);
779
+ }
780
+ } else {
781
+ lines.push("\u{1F7E2} Conflicts: none detected");
782
+ }
783
+ const hh = report.hookHealth;
784
+ if (!hh.logExists) {
785
+ lines.push("\u{1F7E0} Hook logs: no log file (run installer to enable stderr capture)");
786
+ } else if (hh.errorsLastHour === 0) {
787
+ lines.push(`\u{1F7E2} Hook logs: ${fmtNum(hh.totalLines)} lines, 0 errors in last hour`);
788
+ } else {
789
+ lines.push(`\u{1F534} Hook logs: ${fmtNum(hh.errorsLastHour)} errors in last hour (${fmtNum(hh.totalLines)} total lines)`);
790
+ for (const p of hh.topPatterns) {
791
+ lines.push(` ${p.count}x: ${p.pattern}`);
792
+ }
793
+ }
794
+ const ho = report.hookOwnership;
795
+ if (ho.issues.length === 0) {
796
+ lines.push(`\u{1F7E2} Hook ownership: ${ho.checkedFiles.length > 0 ? "manifest clean" : "no local hook config found"}`);
797
+ } else {
798
+ lines.push(`\u{1F534} Hook ownership: ${fmtNum(ho.issues.length)} issue(s)`);
799
+ for (const issue of ho.issues.slice(0, 5)) {
800
+ lines.push(` [${issue.runtime}/${issue.event}] ${issue.message}`);
801
+ }
802
+ }
803
+ const sh = report.shards;
804
+ if (sh.total > 0) {
805
+ if (sh.unreadable === 0 && sh.schemaMismatches === 0) {
806
+ lines.push(`\u{1F7E2} Shards: ${fmtNum(sh.ok)} / ${fmtNum(sh.total)} readable`);
807
+ } else {
808
+ const unreadable = sh.unreadableNames.slice(0, 5).join(", ");
809
+ const schema = sh.schemaIssueNames.slice(0, 3).join("; ");
810
+ const parts = [
811
+ sh.unreadable > 0 ? `${fmtNum(sh.unreadable)} unreadable (${unreadable}${sh.unreadableNames.length > 5 ? ", ..." : ""})` : null,
812
+ sh.schemaMismatches > 0 ? `${fmtNum(sh.schemaMismatches)} schema mismatch (${schema}${sh.schemaIssueNames.length > 3 ? "; ..." : ""})` : null
813
+ ].filter(Boolean);
814
+ lines.push(`\u{1F534} Shards: ${parts.join("; ")}`);
815
+ }
816
+ }
817
+ const ob = report.outbox;
818
+ const unsentTotal = ob.bugReports.unsent + ob.featureRequests.unsent;
819
+ if (unsentTotal === 0) {
820
+ lines.push("\u{1F7E2} Support outbox: all items sent");
821
+ } else {
822
+ lines.push(`\u{1F7E0} Support outbox: ${fmtNum(unsentTotal)} unsent (${ob.bugReports.unsent} bugs, ${ob.featureRequests.unsent} features)`);
823
+ }
824
+ const cs = report.cpuSteal;
825
+ if (!cs.available) {
826
+ lines.push("\u{1F7E2} CPU steal: n/a (not measurable on this platform)");
827
+ } else if (cs.severity === "critical") {
828
+ lines.push(`\u{1F534} CPU steal: ${Math.round(cs.stealPercent ?? 0)}% \u2014 ${cs.message}`);
829
+ } else if (cs.severity === "warning") {
830
+ lines.push(`\u{1F7E0} CPU steal: ${Math.round(cs.stealPercent ?? 0)}% \u2014 ${cs.message}`);
831
+ } else {
832
+ lines.push(`\u{1F7E2} CPU steal: ${Math.round(cs.stealPercent ?? 0)}% (host healthy)`);
833
+ }
834
+ const rh = report.retrievalHealth;
835
+ if (rh) {
836
+ lines.push("");
837
+ lines.push(` Search mode: ${rh.searchMode.actual}${rh.searchMode.actual !== rh.searchMode.configured ? ` (configured: ${rh.searchMode.configured})` : ""}`);
838
+ lines.push(` Embed daemon: ${rh.embedDaemon} \xB7 Query router: ${rh.queryRouter} \xB7 Vector coverage: ${rh.vectorBackfill.coveragePct ?? 0}%`);
839
+ if (rh.dbRestore.hasEvents) {
840
+ const last = rh.dbRestore.last;
841
+ lines.push(` DB restore events: ${rh.dbRestore.count}${last ? ` (last: ${last.kind} @ ${last.at})` : ""}; ${rh.dbRestore.quarantineFiles} quarantined file(s)`);
842
+ }
843
+ lines.push("");
844
+ lines.push(formatDegradations(rh.degradations, "Degradations"));
845
+ }
846
+ lines.push("");
847
+ if (flags.verbose) {
848
+ if (report.duplicates.length > 0) {
849
+ lines.push("Duplicate groups (top 10):");
850
+ for (const d of report.duplicates.slice(0, 10)) {
851
+ lines.push(` ${d.count}x: ${d.raw_text}`);
852
+ }
853
+ lines.push("");
854
+ }
855
+ if (report.bloated.length > 0) {
856
+ lines.push("Bloated records:");
857
+ for (const b of report.bloated.slice(0, 20)) {
858
+ lines.push(` ${b.id.slice(0, 8)}... ${b.agent_id} ${b.tool_name} (${fmtNum(b.size)} bytes)`);
859
+ }
860
+ lines.push("");
861
+ }
862
+ try {
863
+ const restartReport = buildRestartReport({ topTimers: 25 });
864
+ if (restartReport.logsFound) {
865
+ lines.push(formatRestartReport(restartReport).trimEnd());
866
+ lines.push("");
867
+ }
868
+ } catch {
869
+ }
870
+ const actionable = report.conflicts.pairs.filter(
871
+ (p) => p.classification === "CONFLICT" || p.classification === "SUPERSEDED"
872
+ );
873
+ if (actionable.length > 0) {
874
+ lines.push("Conflict Detection");
875
+ lines.push("==================");
876
+ for (const p of actionable.slice(0, 10)) {
877
+ const aShort = p.memoryA.text.length > 60 ? p.memoryA.text.slice(0, 60) + "..." : p.memoryA.text;
878
+ const bShort = p.memoryB.text.length > 60 ? p.memoryB.text.slice(0, 60) + "..." : p.memoryB.text;
879
+ lines.push(
880
+ ` [${p.classification}] ${p.memoryA.id.slice(0, 8)} (${p.memoryA.agentId}, ${p.memoryA.timestamp.slice(0, 10)}) vs ${p.memoryB.id.slice(0, 8)} (${p.memoryB.agentId}, ${p.memoryB.timestamp.slice(0, 10)})`
881
+ );
882
+ lines.push(` "${aShort}" vs "${bShort}"`);
883
+ lines.push(` ${p.explanation} \u2192 Recommendation: ${p.recommendation}`);
884
+ }
885
+ lines.push("");
886
+ }
887
+ }
888
+ const recs = [];
889
+ if (report.nullVectors > 0 && !isLowMemSystem) {
890
+ recs.push(`Run --fix to backfill ${fmtNum(report.nullVectors)} null vectors`);
891
+ }
892
+ if (report.duplicateCount > 0) {
893
+ recs.push(`Run --fix to remove ${fmtNum(report.duplicateCount)} duplicates`);
894
+ }
895
+ if (report.bloated.length > 0) {
896
+ recs.push(`${fmtNum(report.bloated.length)} bloated records will be split into ~2KB chunks`);
897
+ }
898
+ if (!report.fts.inSync) {
899
+ recs.push("Run --fix to rebuild FTS index");
900
+ }
901
+ if (report.shards.unreadable > 0) {
902
+ recs.push(`Run --fix to archive ${fmtNum(report.shards.unreadable)} unreadable shard(s); global DB remains authoritative`);
903
+ }
904
+ if (report.shards.schemaMismatches > 0) {
905
+ recs.push(`Run --fix to migrate ${fmtNum(report.shards.schemaMismatches)} shard schema mismatch(es) in place`);
906
+ }
907
+ if (report.orphanedProjects.length > 0) {
908
+ const names = report.orphanedProjects.map((o) => `"${o.project_name}"`).join(", ");
909
+ recs.push(`Consider /exe-forget for orphaned project${report.orphanedProjects.length > 1 ? "s" : ""} ${names}`);
910
+ }
911
+ if (report.conflicts.conflicts > 0) {
912
+ recs.push(`${fmtNum(report.conflicts.conflicts)} conflicting memory pairs need manual review`);
913
+ }
914
+ if (report.conflicts.superseded > 0) {
915
+ recs.push(`${fmtNum(report.conflicts.superseded)} superseded memories can be deactivated`);
916
+ }
917
+ if (report.hookOwnership.issues.length > 0) {
918
+ recs.push(`Run exe-os install to refresh hook config; remove stale exe-os hook commands if they remain`);
919
+ }
920
+ if (report.retrievalHealth) {
921
+ for (const d of report.retrievalHealth.degradations) {
922
+ if (d.severity === "critical" || d.severity === "warn") {
923
+ recs.push(d.remediation ? `${d.message} \u2014 ${d.remediation}` : d.message);
924
+ }
925
+ }
926
+ }
927
+ if (report.cpuSteal.available && (report.cpuSteal.severity === "warning" || report.cpuSteal.severity === "critical")) {
928
+ recs.push(`${report.cpuSteal.message} Migrate to a less oversubscribed host or contact your VPS provider \u2014 exe-os cannot fix host contention.`);
929
+ }
930
+ if (recs.length > 0) {
931
+ lines.push("Recommendations:");
932
+ for (const r of recs) {
933
+ lines.push(` \u2022 ${r}`);
934
+ }
935
+ } else {
936
+ lines.push("All clear \u2014 memory database is healthy.");
937
+ }
938
+ lines.push("");
939
+ return lines.join("\n");
940
+ }
941
+ async function fixNullVectors() {
942
+ const { tryAcquireWorkerSlot, registerWorkerPid } = await import("./worker-gate-OQMKAMP7.js");
943
+ if (!tryAcquireWorkerSlot()) {
944
+ process.stderr.write("[exe-doctor] Worker gate full \u2014 waiting for existing backfill workers to finish\n");
945
+ await new Promise((r) => setTimeout(r, 5e3));
946
+ if (!tryAcquireWorkerSlot()) {
947
+ throw new Error("Worker gate still full after 5s \u2014 try again later or kill stale workers");
948
+ }
949
+ }
950
+ const npmRoot = (await import("child_process")).execSync("npm root -g", { encoding: "utf8" }).trim();
951
+ const backfillPath = path.join(npmRoot, "exe-os", "dist", "bin", "backfill-vectors.js");
952
+ return new Promise((resolve, reject) => {
953
+ const child = spawn("node", [backfillPath], { stdio: "inherit" });
954
+ if (child.pid) registerWorkerPid(child.pid);
955
+ child.on("close", (code) => {
956
+ if (code === 0) resolve();
957
+ else reject(new Error(`backfill-vectors exited with code ${code}`));
958
+ });
959
+ child.on("error", reject);
960
+ });
961
+ }
962
+ async function fixDuplicates(client, duplicates, dryRun) {
963
+ let deleted = 0;
964
+ for (const dup of duplicates) {
965
+ if (dup.delete_ids.length === 0) continue;
966
+ if (dryRun) {
967
+ console.log(` [dry-run] Would delete ${dup.delete_ids.length} duplicates: ${dup.raw_text}`);
968
+ deleted += dup.delete_ids.length;
969
+ continue;
970
+ }
971
+ const placeholders = dup.delete_ids.map(() => "?").join(",");
972
+ const now = (/* @__PURE__ */ new Date()).toISOString();
973
+ await client.execute({
974
+ sql: `UPDATE memories SET status = 'deleted', deleted_at = ? WHERE id IN (${placeholders})`,
975
+ args: [now, ...dup.delete_ids]
976
+ });
977
+ deleted += dup.delete_ids.length;
978
+ }
979
+ return deleted;
980
+ }
981
+ async function fixBloated(client, bloated, dryRun) {
982
+ let chunksCreated = 0;
983
+ const CHUNK_SIZE = 2048;
984
+ for (const b of bloated) {
985
+ const result = await client.execute({
986
+ sql: `SELECT * FROM memories WHERE id = ?`,
987
+ args: [b.id]
988
+ });
989
+ if (result.rows.length === 0) continue;
990
+ const row = result.rows[0];
991
+ const text = row.raw_text;
992
+ const chunks = splitAtSentences(text, CHUNK_SIZE);
993
+ if (chunks.length <= 1) continue;
994
+ if (dryRun) {
995
+ console.log(` [dry-run] Would split ${b.id.slice(0, 8)}... (${fmtNum(b.size)} bytes) into ${chunks.length} chunks`);
996
+ chunksCreated += chunks.length;
997
+ continue;
998
+ }
999
+ const stmts = chunks.map((chunk, i) => ({
1000
+ sql: `INSERT INTO memories
1001
+ (id, agent_id, agent_role, session_id, timestamp,
1002
+ tool_name, project_name, has_error, raw_text, vector, version, consolidated)
1003
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, 0, 0)`,
1004
+ args: [
1005
+ randomUUID(),
1006
+ row.agent_id,
1007
+ row.agent_role,
1008
+ row.session_id,
1009
+ row.timestamp,
1010
+ row.tool_name,
1011
+ row.project_name,
1012
+ row.has_error,
1013
+ `[chunk ${i + 1}/${chunks.length} of ${b.id}] ${chunk}`
1014
+ ]
1015
+ }));
1016
+ stmts.push({
1017
+ sql: `UPDATE memories SET consolidated = 1 WHERE id = ?`,
1018
+ args: [b.id]
1019
+ });
1020
+ await client.batch(stmts, "write");
1021
+ chunksCreated += chunks.length;
1022
+ }
1023
+ return chunksCreated;
1024
+ }
1025
+ async function fixShards(dryRun) {
1026
+ const { auditShardHealth } = await import("./shard-manager-P5ZJH4AX.js");
1027
+ const report = await auditShardHealth({ repair: true, dryRun });
1028
+ return {
1029
+ total: report.total,
1030
+ ok: report.ok,
1031
+ unreadable: report.unreadable,
1032
+ schemaMismatches: report.schemaMismatches,
1033
+ archived: report.archived,
1034
+ unreadableNames: report.shards.filter((s) => s.unreadable).map((s) => s.name),
1035
+ schemaIssueNames: report.shards.filter((s) => s.schemaIssues.length > 0).map((s) => `${s.name}: ${s.schemaIssues.join(", ")}`)
1036
+ };
1037
+ }
1038
+ function splitAtSentences(text, maxChunkSize) {
1039
+ if (text.length <= maxChunkSize) return [text];
1040
+ const chunks = [];
1041
+ let remaining = text;
1042
+ while (remaining.length > 0) {
1043
+ if (remaining.length <= maxChunkSize) {
1044
+ chunks.push(remaining);
1045
+ break;
1046
+ }
1047
+ const window = remaining.slice(0, maxChunkSize);
1048
+ let splitIdx = -1;
1049
+ for (const sep of [". ", ".\n", "! ", "!\n", "? ", "?\n"]) {
1050
+ const idx = window.lastIndexOf(sep);
1051
+ if (idx > splitIdx) splitIdx = idx + sep.length;
1052
+ }
1053
+ if (splitIdx <= 0) {
1054
+ const nlIdx = window.lastIndexOf("\n");
1055
+ if (nlIdx > 0) splitIdx = nlIdx + 1;
1056
+ }
1057
+ if (splitIdx <= 0) splitIdx = maxChunkSize;
1058
+ chunks.push(remaining.slice(0, splitIdx).trimEnd());
1059
+ remaining = remaining.slice(splitIdx).trimStart();
1060
+ }
1061
+ return chunks;
1062
+ }
1063
+ function emptyAuditReport() {
1064
+ return {
1065
+ stats: { total: 0, agents: 0, projects: 0, oldest: null, newest: null, perAgent: [] },
1066
+ nullVectors: 0,
1067
+ duplicates: [],
1068
+ duplicateCount: 0,
1069
+ bloated: [],
1070
+ fts: { memoryCount: 0, ftsCount: 0, inSync: true },
1071
+ orphanedProjects: [],
1072
+ conflicts: {
1073
+ candidateCount: 0,
1074
+ classified: 0,
1075
+ conflicts: 0,
1076
+ superseded: 0,
1077
+ agree: 0,
1078
+ unclassified: 0,
1079
+ pairs: [],
1080
+ skipped: true
1081
+ },
1082
+ hookHealth: { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] },
1083
+ hookOwnership: { checkedFiles: [], issues: [], staleLegacyHooks: [] },
1084
+ shards: { total: 0, ok: 0, unreadable: 0, schemaMismatches: 0, archived: 0, unreadableNames: [], schemaIssueNames: [] },
1085
+ keyHealth: { masterKeyPresent: true, recoveryBackupMarked: true },
1086
+ outbox: { bugReports: { total: 0, unsent: 0 }, featureRequests: { total: 0, unsent: 0 } },
1087
+ cpuSteal: { available: false, stealPercent: null, severity: "na", source: "none", message: "not checked" }
1088
+ };
1089
+ }
1090
+ async function main(argv = process.argv.slice(2)) {
1091
+ const flags = parseFlags(argv);
1092
+ if (flags.restarts) {
1093
+ const restartReport = buildRestartReport({ topTimers: flags.verbose ? 25 : 10 });
1094
+ console.log(formatRestartReport(restartReport));
1095
+ return emptyAuditReport();
1096
+ }
1097
+ const { fastDbInit } = await import("./fast-db-init-IU7GYFWB.js");
1098
+ const client = await fastDbInit();
1099
+ const report = await runAudit(client, flags);
1100
+ console.log(formatReport(report, flags));
1101
+ if (flags.fix || flags.dryRun) {
1102
+ const mode = flags.dryRun ? "[dry-run]" : "[fix]";
1103
+ console.log(`
1104
+ ${mode} Applying repairs...
1105
+ `);
1106
+ if (!flags.dryRun) {
1107
+ try {
1108
+ const { createBackup } = await import("./db-backup-NVUTS7L5.js");
1109
+ const backupPath = await createBackup("pre-fix");
1110
+ if (backupPath) {
1111
+ console.log(` Backup created: ${backupPath.split("/").pop()}`);
1112
+ }
1113
+ } catch {
1114
+ console.log(" Warning: backup failed \u2014 proceeding with fix anyway");
1115
+ }
1116
+ }
1117
+ if (report.nullVectors > 0) {
1118
+ console.log(`${mode} Backfilling ${fmtNum(report.nullVectors)} null vectors...`);
1119
+ if (!flags.dryRun) {
1120
+ try {
1121
+ await fixNullVectors();
1122
+ console.log(" Done.");
1123
+ } catch (err) {
1124
+ console.error(` Failed: ${err instanceof Error ? err.message : String(err)}`);
1125
+ }
1126
+ }
1127
+ }
1128
+ if (report.duplicateCount > 0) {
1129
+ console.log(`${mode} Removing ${fmtNum(report.duplicateCount)} duplicates...`);
1130
+ const deleted = await fixDuplicates(client, report.duplicates, flags.dryRun);
1131
+ console.log(` ${flags.dryRun ? "Would remove" : "Removed"} ${fmtNum(deleted)} records.`);
1132
+ }
1133
+ if (report.bloated.length > 0) {
1134
+ console.log(`${mode} Splitting ${fmtNum(report.bloated.length)} bloated records...`);
1135
+ const chunks = await fixBloated(client, report.bloated, flags.dryRun);
1136
+ console.log(` ${flags.dryRun ? "Would create" : "Created"} ${fmtNum(chunks)} chunks.`);
1137
+ }
1138
+ if (!report.fts.inSync) {
1139
+ console.log(`${mode} Rebuilding FTS index...`);
1140
+ if (!flags.dryRun) {
1141
+ await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
1142
+ console.log(" Done.");
1143
+ }
1144
+ }
1145
+ if (report.shards.unreadable > 0 || report.shards.schemaMismatches > 0) {
1146
+ console.log(`${mode} Repairing ${fmtNum(report.shards.unreadable)} unreadable shard(s) and ${fmtNum(report.shards.schemaMismatches)} schema mismatch(es)...`);
1147
+ const fixed = await fixShards(flags.dryRun);
1148
+ console.log(
1149
+ ` ${flags.dryRun ? "Would archive" : "Archived"} ${fmtNum(flags.dryRun ? fixed.unreadable : fixed.archived)} unreadable shard(s); ${flags.dryRun ? "would migrate" : "migrated"} ${fmtNum(flags.dryRun ? fixed.schemaMismatches : report.shards.schemaMismatches - fixed.schemaMismatches)} schema mismatch(es).`
1150
+ );
1151
+ }
1152
+ console.log(`
1153
+ ${mode} Complete.`);
1154
+ }
1155
+ return report;
1156
+ }
1157
+ if (isMainModule(import.meta.url) && (process.argv[1] ?? "").includes("exe-doctor")) {
1158
+ main().catch((err) => {
1159
+ console.error(err instanceof Error ? err.message : String(err));
1160
+ process.exit(1);
1161
+ });
1162
+ }
1163
+
1164
+ export {
1165
+ parseFlags,
1166
+ auditStats,
1167
+ auditNullVectors,
1168
+ auditDuplicates,
1169
+ auditBloated,
1170
+ auditFts,
1171
+ auditOrphanedProjects,
1172
+ auditHookHealth,
1173
+ auditHookOwnership,
1174
+ auditShards,
1175
+ auditKeyHealth,
1176
+ auditOutbox,
1177
+ auditCpuSteal,
1178
+ runAudit,
1179
+ formatReport,
1180
+ fixNullVectors,
1181
+ fixDuplicates,
1182
+ fixBloated,
1183
+ fixShards,
1184
+ splitAtSentences,
1185
+ main
1186
+ };