@askexenow/exe-os 0.9.239 → 0.9.244

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 (319) hide show
  1. package/deploy/compose/.env.customer.example +12 -0
  2. package/deploy/compose/.env.example +13 -1
  3. package/deploy/compose/cloudflared/config.yml.example +29 -5
  4. package/deploy/compose/docker-compose.yml +27 -7
  5. package/deploy/compose/generate-env.ts +49 -1
  6. package/deploy/compose/init-db.sql +10 -2
  7. package/deploy/stack-manifests/v0.9.json +113 -9
  8. package/dist/{active-agent-7MIVNARP.js → active-agent-KO4ZWDXE.js} +4 -4
  9. package/dist/{active-agent-55C5Y3XL.js → active-agent-KP2O52HA.js} +4 -4
  10. package/dist/{agentic-ontology-NCAQIQQI.js → agentic-ontology-DXE5J6I5.js} +1 -1
  11. package/dist/{backfill-metadata-3JP7EZ2U.js → backfill-metadata-DFTIGPXP.js} +7 -7
  12. package/dist/{background-jobs-RWL46VRD.js → background-jobs-CRXY7T4Y.js} +2 -2
  13. package/dist/{behaviors-6BGALYGW.js → behaviors-BL3QCHBT.js} +4 -4
  14. package/dist/bin/age-ontology-load.js +2 -2
  15. package/dist/bin/agentic-ontology-backfill.js +9 -9
  16. package/dist/bin/agentic-reflection-backfill.js +10 -10
  17. package/dist/bin/agentic-semantic-label.js +9 -9
  18. package/dist/bin/backfill-conversations.js +9 -9
  19. package/dist/bin/backfill-responses.js +9 -9
  20. package/dist/bin/backfill-vectors.js +11 -11
  21. package/dist/bin/bulk-sync-postgres.js +10 -10
  22. package/dist/bin/cc-doctor.js +3 -3
  23. package/dist/bin/cleanup-stale-review-tasks.js +13 -13
  24. package/dist/bin/cli.js +27 -22
  25. package/dist/bin/exe-agent-config.js +4 -4
  26. package/dist/bin/exe-agent.js +8 -8
  27. package/dist/bin/exe-assign.js +11 -11
  28. package/dist/bin/exe-boot.js +22 -22
  29. package/dist/bin/exe-call.js +5 -5
  30. package/dist/bin/exe-cloud.js +8 -8
  31. package/dist/bin/exe-dispatch.js +13 -13
  32. package/dist/bin/exe-doctor.js +1 -1
  33. package/dist/bin/exe-export-behaviors.js +10 -10
  34. package/dist/bin/exe-forget.js +9 -9
  35. package/dist/bin/exe-gateway.js +8 -8
  36. package/dist/bin/exe-healthcheck.js +3 -3
  37. package/dist/bin/exe-heartbeat.js +13 -13
  38. package/dist/bin/exe-kill.js +18 -18
  39. package/dist/bin/exe-launch-agent.js +22 -22
  40. package/dist/bin/exe-new-employee.js +8 -8
  41. package/dist/bin/exe-pending-messages.js +14 -14
  42. package/dist/bin/exe-pending-notifications.js +13 -13
  43. package/dist/bin/exe-pending-reviews.js +13 -13
  44. package/dist/bin/exe-rename.js +5 -5
  45. package/dist/bin/exe-review.js +17 -17
  46. package/dist/bin/exe-search.js +8 -8
  47. package/dist/bin/exe-session-cleanup.js +20 -20
  48. package/dist/bin/exe-settings.js +7 -7
  49. package/dist/bin/exe-start-codex.js +14 -14
  50. package/dist/bin/exe-start-opencode.js +11 -11
  51. package/dist/bin/exe-status.js +14 -14
  52. package/dist/bin/exe-support.js +3 -3
  53. package/dist/bin/exe-team.js +4 -4
  54. package/dist/bin/git-sweep.js +13 -13
  55. package/dist/bin/graph-backfill.js +8 -8
  56. package/dist/bin/graph-export.js +8 -8
  57. package/dist/bin/import-history.js +10 -10
  58. package/dist/bin/install.js +7 -7
  59. package/dist/bin/intercom-check.js +4 -4
  60. package/dist/bin/mcp-sessions.js +2 -2
  61. package/dist/bin/orchestration-metrics.js +5 -5
  62. package/dist/bin/postgres-agentic-reflection-backfill.js +4 -4
  63. package/dist/bin/postgres-agentic-semantic-backfill.js +3 -3
  64. package/dist/bin/registry-proxy.js +1 -1
  65. package/dist/bin/scan-tasks.js +13 -13
  66. package/dist/bin/setup.js +3 -3
  67. package/dist/bin/shard-migrate.js +8 -8
  68. package/dist/bin/stack-update.js +348 -20
  69. package/dist/bin/verify-stack.js +3 -383
  70. package/dist/bin/vps-backup.js +8 -160
  71. package/dist/bin/vps-health-gate.js +10 -220
  72. package/dist/{branding-I7YYX4FM.js → branding-XWMO5EDR.js} +1 -1
  73. package/dist/{capacity-monitor-IFCZKRPG.js → capacity-monitor-4CSBC7AP.js} +14 -14
  74. package/dist/{catchup-brief-PIDRWXOW.js → catchup-brief-LF5Z6Q6E.js} +17 -17
  75. package/dist/{chunk-FGJUGDNM.js → chunk-222SI7QC.js} +14 -14
  76. package/dist/{chunk-JZMVLAZ2.js → chunk-2WBBVEIB.js} +1 -1
  77. package/dist/{chunk-JDOE33C2.js → chunk-3V53HH5T.js} +4 -4
  78. package/dist/{chunk-2KZSKURT.js → chunk-57SULZJ2.js} +3 -3
  79. package/dist/{chunk-QI4IXJN7.js → chunk-5CHYEKMH.js} +7 -4
  80. package/dist/chunk-5DMAMQNU.js +168 -0
  81. package/dist/{chunk-PLQAFB3Z.js → chunk-5JIG2FP2.js} +1 -1
  82. package/dist/{chunk-UWQ3XCDG.js → chunk-5WK7X5CF.js} +2 -2
  83. package/dist/{chunk-DDPAQ4LT.js → chunk-6JAGJN77.js} +2 -2
  84. package/dist/{chunk-7F37NMKB.js → chunk-73UE2PHT.js} +1 -1
  85. package/dist/{chunk-JL3K5OTS.js → chunk-7IZWLMTP.js} +1 -1
  86. package/dist/{chunk-ELRRL2NC.js → chunk-A4K2ZT6N.js} +4 -4
  87. package/dist/{chunk-GWYADLIW.js → chunk-AHXEU5XB.js} +1 -1
  88. package/dist/{chunk-WSHMBME6.js → chunk-AWRL5FGM.js} +19 -78
  89. package/dist/{chunk-OMPCFLWA.js → chunk-BSPOEYAO.js} +1 -1
  90. package/dist/{chunk-F4TCKCKK.js → chunk-BYCNUKII.js} +47 -12
  91. package/dist/{chunk-DHVC4RN7.js → chunk-CBDPEJOR.js} +5 -5
  92. package/dist/{chunk-2H55BIV2.js → chunk-CEJO7244.js} +2 -2
  93. package/dist/{chunk-FKWZVO2T.js → chunk-CPXGLSIL.js} +3 -3
  94. package/dist/{chunk-HX5G4AS4.js → chunk-CWITU7DW.js} +2 -2
  95. package/dist/{chunk-5GG7MTRJ.js → chunk-DGBGIXCC.js} +4 -4
  96. package/dist/{chunk-IQXPMK46.js → chunk-DLZYAYVM.js} +60 -14
  97. package/dist/{chunk-PPYWQV2M.js → chunk-DR5BGWFR.js} +2 -2
  98. package/dist/{chunk-BZWKTFEB.js → chunk-ENVRFBTB.js} +2 -2
  99. package/dist/{chunk-DUVO2PUJ.js → chunk-F3GM6OOP.js} +4 -4
  100. package/dist/{chunk-HNLPLLE6.js → chunk-F7JLZXHC.js} +60 -26
  101. package/dist/{chunk-AL4DRC5H.js → chunk-FFLILAG6.js} +1 -1
  102. package/dist/{chunk-BZNI4OK5.js → chunk-GHEWRYMY.js} +18 -2
  103. package/dist/{chunk-C7SFJO5F.js → chunk-GHT4REOS.js} +5 -5
  104. package/dist/{chunk-FBWUJEXS.js → chunk-HANG6NLF.js} +4 -6
  105. package/dist/{chunk-5NJ4A4ZA.js → chunk-HCBMPZDT.js} +1 -1
  106. package/dist/chunk-HOGTZLVU.js +244 -0
  107. package/dist/{chunk-IQSCZDBQ.js → chunk-I5PIBL56.js} +3 -3
  108. package/dist/chunk-IRHNV4GY.js +388 -0
  109. package/dist/{chunk-4HROS3GJ.js → chunk-IZVKWBIP.js} +1 -1
  110. package/dist/{chunk-DKI5BTBC.js → chunk-J7V7LPPX.js} +2 -2
  111. package/dist/{chunk-TOZ5NN5V.js → chunk-JLKUVK5J.js} +1 -1
  112. package/dist/{chunk-4SC65UBG.js → chunk-JLNXKG3K.js} +1 -1
  113. package/dist/{chunk-KVSQOG3W.js → chunk-K2BDE2B5.js} +4 -4
  114. package/dist/{chunk-KDJRFJDL.js → chunk-K333WOW4.js} +30 -2
  115. package/dist/{chunk-6LBCUA2A.js → chunk-KEZXW3RP.js} +1 -1
  116. package/dist/{chunk-W7G3GY4I.js → chunk-KLQI7QY4.js} +3 -3
  117. package/dist/{chunk-UODVZGBQ.js → chunk-KN7LPTIB.js} +1 -1
  118. package/dist/{chunk-ESKBZN4Q.js → chunk-L4WRH3DL.js} +1 -1
  119. package/dist/{chunk-VFQKKMKE.js → chunk-LAOB5BKV.js} +2 -2
  120. package/dist/{chunk-MAN5LZQ4.js → chunk-LQSFP2BV.js} +1 -1
  121. package/dist/{chunk-EJ7LOTV2.js → chunk-LSFHEMVI.js} +9 -9
  122. package/dist/{chunk-RA2RO27E.js → chunk-MCESA5UW.js} +2 -2
  123. package/dist/{chunk-UPMHG7ET.js → chunk-MEIHREPM.js} +1 -1
  124. package/dist/{chunk-D5C56WO3.js → chunk-MOZ2YQ54.js} +1 -1
  125. package/dist/{chunk-CLGB3FGL.js → chunk-MPX3TRMQ.js} +2 -2
  126. package/dist/{chunk-5R75ODPS.js → chunk-NBY6R37W.js} +61 -232
  127. package/dist/{chunk-RWFGXC35.js → chunk-NEYQAEYU.js} +7 -7
  128. package/dist/{chunk-MBHZDXGN.js → chunk-NL35XNLI.js} +1 -1
  129. package/dist/{chunk-TPQVLYSV.js → chunk-NLGMHPEN.js} +1 -1
  130. package/dist/{chunk-5LMH4YHG.js → chunk-NRVV4Y5V.js} +4 -4
  131. package/dist/{chunk-GN5VHPPR.js → chunk-NVZR7T4E.js} +1 -1
  132. package/dist/{chunk-Y2L7RMGH.js → chunk-NWBHL5PI.js} +1 -1
  133. package/dist/{chunk-YPYDLW75.js → chunk-OEMX65EA.js} +1 -1
  134. package/dist/{chunk-UAFUGPKO.js → chunk-ONAQAL3O.js} +1 -1
  135. package/dist/{chunk-AVM7XZE4.js → chunk-OWQ3CCYJ.js} +7 -6
  136. package/dist/{chunk-K525WLL7.js → chunk-PI6V23GF.js} +5 -4
  137. package/dist/{chunk-AURM7FOT.js → chunk-Q2OAQPWY.js} +1 -1
  138. package/dist/{chunk-FB5VRO5S.js → chunk-QLDWASTX.js} +28 -32
  139. package/dist/{chunk-EPWDTS2Q.js → chunk-QMTGMCWB.js} +1 -1
  140. package/dist/{chunk-VI2FJY2M.js → chunk-QP4FHME2.js} +2 -2
  141. package/dist/{chunk-NJWK6J4N.js → chunk-QUNKPR6Y.js} +5 -5
  142. package/dist/{chunk-O6DAF2TY.js → chunk-QUZVAHO7.js} +2 -2
  143. package/dist/{chunk-VHKL4S4T.js → chunk-RRHSONV5.js} +2 -2
  144. package/dist/{chunk-GPF6X6HE.js → chunk-RYDHEWYY.js} +2 -2
  145. package/dist/{chunk-SVXDCELZ.js → chunk-SHN5O73O.js} +32 -4
  146. package/dist/chunk-TD5CADZ5.js +230 -0
  147. package/dist/{chunk-C2YS2AA6.js → chunk-U7WOVXBB.js} +2 -2
  148. package/dist/{chunk-FE45RXGC.js → chunk-V2GZMY6O.js} +1 -1
  149. package/dist/{chunk-PATCHPNY.js → chunk-VHALWCUO.js} +1 -1
  150. package/dist/{chunk-HLZSC5WK.js → chunk-VQAP35DA.js} +20 -18
  151. package/dist/{chunk-452XB7OZ.js → chunk-VRIMTCX2.js} +1 -1
  152. package/dist/{chunk-SUNYJ6YE.js → chunk-VT2B5BHM.js} +1 -1
  153. package/dist/{chunk-UZIJDYDA.js → chunk-VWVJVQDH.js} +2 -2
  154. package/dist/{chunk-TRZ5KA2R.js → chunk-VXIMSRTO.js} +2 -2
  155. package/dist/{chunk-DAZIV4QZ.js → chunk-WCXZF42W.js} +1 -1
  156. package/dist/{chunk-6OJJF4WP.js → chunk-XJUUWHVN.js} +1 -1
  157. package/dist/{chunk-F7LU65PQ.js → chunk-Y25OJWOQ.js} +14 -2
  158. package/dist/{chunk-2ORPA23Y.js → chunk-YMXXD2GW.js} +36 -8
  159. package/dist/{chunk-5WLMF6PL.js → chunk-YMZHTTOQ.js} +1 -1
  160. package/dist/{chunk-7DIDOQCX.js → chunk-YRVW57UW.js} +139 -125
  161. package/dist/{chunk-BRFH5X7G.js → chunk-Z7VDUS6L.js} +1 -1
  162. package/dist/{chunk-YFE6W75D.js → chunk-ZKFPHJIJ.js} +1 -1
  163. package/dist/{chunk-5WUTKDH6.js → chunk-ZVXJSQOR.js} +1 -1
  164. package/dist/{co-activation-VB4CJQZB.js → co-activation-L6I2LSJO.js} +3 -3
  165. package/dist/{co-occurrence-XZQJJIBM.js → co-occurrence-QARWYUAY.js} +3 -3
  166. package/dist/{code-context-index-FCQOPUEA.js → code-context-index-UIYQRDHD.js} +4 -4
  167. package/dist/{content-extractor-SPSH5X33.js → content-extractor-EYRVGD6O.js} +2 -2
  168. package/dist/{conversation-wiki-populator-YU35LNRK.js → conversation-wiki-populator-L7O6F3BB.js} +1 -1
  169. package/dist/{crdt-sync-KXETGV45.js → crdt-sync-R6YROKDH.js} +1 -1
  170. package/dist/{crm-webhook-JMOAHTJ6.js → crm-webhook-WK3PYJJK.js} +2 -2
  171. package/dist/{cto-delegation-gate-IJ3KQIKF.js → cto-delegation-gate-5JZORQIT.js} +12 -12
  172. package/dist/{daemon-auth-2IZACWSG.js → daemon-auth-2HEOL6VG.js} +2 -2
  173. package/dist/{daemon-orchestration-ZCY4GEI3.js → daemon-orchestration-BJ3T5MMF.js} +16 -15
  174. package/dist/{db-backup-HLX5OLIV.js → db-backup-EWS52P2W.js} +2 -2
  175. package/dist/{dreaming-2CJML3TU.js → dreaming-BOSBDRI3.js} +13 -13
  176. package/dist/{entity-boost-T5IYWWDZ.js → entity-boost-6ZVX7DFB.js} +26 -2
  177. package/dist/{exe-drift-P5OIRNSH.js → exe-drift-WRE6RADZ.js} +4 -4
  178. package/dist/{exe-export-QQL2H322.js → exe-export-7N5PBCMK.js} +8 -8
  179. package/dist/{exe-import-V4RJCUEP.js → exe-import-YOOE7S3H.js} +8 -8
  180. package/dist/{exe-key-MENJGDD7.js → exe-key-GXJSTCX2.js} +4 -4
  181. package/dist/{exe-org-3FNET2J7.js → exe-org-42YMQL75.js} +2 -2
  182. package/dist/{exe-snapshot-YRARQE7F.js → exe-snapshot-ODUCFW7G.js} +18 -18
  183. package/dist/{fast-db-init-HIJWWKAO.js → fast-db-init-YSR7RMVZ.js} +1 -1
  184. package/dist/{founder-context-BQ5NBDUV.js → founder-context-Q2HUCZX4.js} +2 -2
  185. package/dist/gateway/index.js +9 -9
  186. package/dist/{gateway-client-YGSA5QMC.js → gateway-client-4QXHKN5C.js} +1 -1
  187. package/dist/{git-staleness-IHTKCUMN.js → git-staleness-BJDTCDPC.js} +3 -3
  188. package/dist/{git-task-sweep-5ZPNQS7Y.js → git-task-sweep-L3U3T5HM.js} +13 -13
  189. package/dist/{global-procedures-XHDIZRJU.js → global-procedures-HCHEHKY2.js} +4 -4
  190. package/dist/{graph-auto-extract-5TPT67GP.js → graph-auto-extract-FP5C76LS.js} +3 -3
  191. package/dist/{hook-integrity-SB53Y7UK.js → hook-integrity-2OU3T6UC.js} +1 -1
  192. package/dist/hooks/bug-report-worker.js +15 -14
  193. package/dist/hooks/codex-stop-task-finalizer.js +15 -14
  194. package/dist/hooks/commit-complete.js +16 -16
  195. package/dist/hooks/error-recall.js +10 -10
  196. package/dist/hooks/exe-heartbeat-hook.js +5 -5
  197. package/dist/hooks/ingest-worker.js +8 -8
  198. package/dist/hooks/ingest.js +13 -13
  199. package/dist/hooks/instructions-loaded.js +7 -7
  200. package/dist/hooks/manifest.json +20 -20
  201. package/dist/hooks/notification.js +6 -6
  202. package/dist/hooks/post-compact.js +15 -15
  203. package/dist/hooks/post-tool-combined.js +7 -7
  204. package/dist/hooks/pre-compact.js +20 -20
  205. package/dist/hooks/pre-tool-use.js +28 -25
  206. package/dist/hooks/prompt-submit.js +62 -31
  207. package/dist/hooks/session-end.js +26 -26
  208. package/dist/hooks/session-start.js +39 -15
  209. package/dist/hooks/stop.js +22 -22
  210. package/dist/hooks/subagent-stop.js +15 -15
  211. package/dist/hooks/summary-worker.js +32 -27
  212. package/dist/index.js +21 -21
  213. package/dist/{installer-AMZM4MLS.js → installer-AWMUCRN4.js} +7 -7
  214. package/dist/{installer-KT5FW4CN.js → installer-HB3NH6FG.js} +9 -9
  215. package/dist/{installer-HW74W3IT.js → installer-RU6EVOBL.js} +6 -6
  216. package/dist/{intercom-queue-RNM6EPGA.js → intercom-queue-A6UJEFIF.js} +1 -1
  217. package/dist/{key-backup-status-OZ2CXUDW.js → key-backup-status-4YKCV4ZV.js} +1 -1
  218. package/dist/lib/agent-config.js +2 -2
  219. package/dist/lib/cloud-sync.js +10 -8
  220. package/dist/lib/config.js +1 -1
  221. package/dist/lib/consolidation.js +8 -8
  222. package/dist/lib/database.js +3 -3
  223. package/dist/lib/db-daemon-client.js +3 -3
  224. package/dist/lib/db.js +3 -3
  225. package/dist/lib/device-registry.js +1 -1
  226. package/dist/lib/embedder.js +4 -4
  227. package/dist/lib/employee-templates.js +5 -5
  228. package/dist/lib/employees.js +3 -3
  229. package/dist/lib/exe-daemon-client.js +3 -3
  230. package/dist/lib/exe-daemon.js +105 -74
  231. package/dist/lib/hybrid-search.js +8 -8
  232. package/dist/lib/identity.js +3 -3
  233. package/dist/lib/keychain.js +1 -1
  234. package/dist/lib/license.js +2 -2
  235. package/dist/lib/messaging.js +13 -13
  236. package/dist/lib/post-tool-memory.js +3 -3
  237. package/dist/lib/registry-proxy.js +1 -1
  238. package/dist/lib/reminders.js +4 -4
  239. package/dist/lib/schedules.js +8 -8
  240. package/dist/lib/session-registry.js +5 -5
  241. package/dist/lib/skill-learning.js +5 -5
  242. package/dist/lib/store.js +7 -7
  243. package/dist/lib/task-router.js +4 -4
  244. package/dist/lib/tasks.js +14 -13
  245. package/dist/lib/tmux-routing.js +12 -12
  246. package/dist/lib/token-spend.js +4 -4
  247. package/dist/lib/ws-client.js +1 -1
  248. package/dist/{license-gate-XJDIL6OZ.js → license-gate-6JQQFBHS.js} +3 -3
  249. package/dist/mcp/register-tools.js +68 -67
  250. package/dist/mcp/server.js +70 -69
  251. package/dist/mcp/tools/complete-reminder.js +5 -5
  252. package/dist/mcp/tools/create-reminder.js +5 -5
  253. package/dist/mcp/tools/create-task.js +16 -15
  254. package/dist/mcp/tools/deactivate-behavior.js +6 -6
  255. package/dist/mcp/tools/list-reminders.js +5 -5
  256. package/dist/mcp/tools/list-tasks.js +16 -15
  257. package/dist/mcp/tools/send-message.js +15 -15
  258. package/dist/mcp/tools/update-task.js +15 -14
  259. package/dist/{mcp-http-config-BXX3RZPR.js → mcp-http-config-XIJR5P2Z.js} +4 -4
  260. package/dist/{memory-cards-KRTP5GFM.js → memory-cards-H4BJJ5OK.js} +3 -3
  261. package/dist/{memory-graph-extractor-G532PUHC.js → memory-graph-extractor-SDGM3GVR.js} +4 -4
  262. package/dist/{memory-poisoning-defense-HJM3FQA3.js → memory-poisoning-defense-UVU67DGJ.js} +3 -3
  263. package/dist/{memory-queue-FTNBWLS4.js → memory-queue-FNT5WHXP.js} +2 -2
  264. package/dist/{memory-queue-client-DHSHEIHQ.js → memory-queue-client-JZCFYTWQ.js} +5 -5
  265. package/dist/{memory-reflection-RANRFUQL.js → memory-reflection-GGB5K35L.js} +3 -3
  266. package/dist/{notifications-4P2PVEOT.js → notifications-P3XQZDTH.js} +12 -12
  267. package/dist/{orchestration-events-IYTASMSN.js → orchestration-events-25WEKUKH.js} +4 -4
  268. package/dist/{orchestration-phase-SGA7PJ5G.js → orchestration-phase-C26XVKLZ.js} +2 -2
  269. package/dist/{orchestrator-VKVHZ4MV.js → orchestrator-VIXTY4E4.js} +14 -14
  270. package/dist/{pipeline-router-E4L5BDXN.js → pipeline-router-S5PE5U6B.js} +4 -4
  271. package/dist/{plan-limits-5O5QG55H.js → plan-limits-DGIVM42H.js} +5 -5
  272. package/dist/{prediction-log-OMWHW7FL.js → prediction-log-DOEOHDHS.js} +1 -1
  273. package/dist/{project-boot-WMI6CWRX.js → project-boot-4ZL2W7DN.js} +12 -2
  274. package/dist/{projection-worker-54KRNQSO.js → projection-worker-GG2W5OM3.js} +3 -3
  275. package/dist/{push-notifications-E2XXEWJZ.js → push-notifications-AMHVR6DF.js} +2 -2
  276. package/dist/{reranker-4NTUFNYT.js → reranker-UCPLQZE2.js} +2 -2
  277. package/dist/{review-polling-BFRJDLUA.js → review-polling-P2MWEXLR.js} +13 -13
  278. package/dist/runtime/index.js +15 -15
  279. package/dist/{session-events-KCZCWGE4.js → session-events-5CD66R6U.js} +13 -13
  280. package/dist/{session-kill-telemetry-TMNIDYWY.js → session-kill-telemetry-7FBHTEDN.js} +4 -4
  281. package/dist/{session-scope-DRZBQ32Y.js → session-scope-VMIPAZU7.js} +12 -12
  282. package/dist/{setup-wizard-TQKGDAHO.js → setup-wizard-BNR47URR.js} +3 -3
  283. package/dist/{shard-manager-G6MHCO7X.js → shard-manager-VGA2TYHM.js} +2 -2
  284. package/dist/{skill-refinement-Z5SWD3AM.js → skill-refinement-NRG4WWRW.js} +3 -3
  285. package/dist/stack-release-PFZI22WC.js +521 -0
  286. package/dist/{stack-update-NO5MNARG.js → stack-update-7F2E2MBJ.js} +3 -3
  287. package/dist/{steward-gate-7DWYS5AT.js → steward-gate-L7DJMF4C.js} +4 -4
  288. package/dist/{task-enforcement-2VL5J6JJ.js → task-enforcement-XQL77PZH.js} +52 -12
  289. package/dist/{task-scope-YHALISIB.js → task-scope-R3XKBIHL.js} +12 -12
  290. package/dist/{tasks-crud-JXZEBZFR.js → tasks-crud-DQOG2NPG.js} +12 -12
  291. package/dist/tasks-notify-4EQYG52H.js +37 -0
  292. package/dist/{tasks-review-PGPYJQF5.js → tasks-review-XPFJ4DSJ.js} +12 -12
  293. package/dist/{telemetry-upload-H7OJNBIF.js → telemetry-upload-OT5B5HUY.js} +7 -7
  294. package/dist/{token-budget-JJ7JQIA2.js → token-budget-D2LQKCAV.js} +3 -3
  295. package/dist/{tool-capability-index-WIV4K3FB.js → tool-capability-index-FAJ5ZHDF.js} +1 -1
  296. package/dist/{tool-telemetry-W4LFCHFT.js → tool-telemetry-QIF5BCLF.js} +1 -1
  297. package/dist/tui/App.js +26 -26
  298. package/dist/{tui-data-72U6N2DC.js → tui-data-UEV2QOR3.js} +108 -12
  299. package/dist/{whatsapp-config-W63RQ3AU.js → whatsapp-config-GOSELKTE.js} +7 -0
  300. package/dist/{worker-gate-SCSN6IHI.js → worker-gate-PRCKA23W.js} +2 -2
  301. package/dist/{workflow-engine-OICYBE4F.js → workflow-engine-7X6LLH3M.js} +2 -2
  302. package/dist/{worktree-JXN4RCWC.js → worktree-RICSCT2S.js} +5 -5
  303. package/package.json +1 -1
  304. package/release-notes.json +210 -298
  305. package/stack.release.json +4 -3
  306. package/dist/preflight-EAH2MI76.js +0 -287
  307. /package/dist/{chunk-H42LEGLB.js → chunk-AQBEG33D.js} +0 -0
  308. /package/dist/{chunk-AU5426YP.js → chunk-B7JGEDVE.js} +0 -0
  309. /package/dist/{chunk-YFDDTHNM.js → chunk-JXI4XUTV.js} +0 -0
  310. /package/dist/{chunk-SNYDRHV3.js → chunk-U3DUFHOT.js} +0 -0
  311. /package/dist/{chunk-N2XUH2HQ.js → chunk-VBPC7IC7.js} +0 -0
  312. /package/dist/{chunk-HTUJBTBM.js → chunk-VUS6WXQ3.js} +0 -0
  313. /package/dist/{chunk-NOLIN2YI.js → chunk-XAYRZHLV.js} +0 -0
  314. /package/dist/{core-memory-VOBGGB2Q.js → core-memory-4KAIKQRQ.js} +0 -0
  315. /package/dist/{message-queue-client-KAJN6TIJ.js → message-queue-client-S6W5VMJV.js} +0 -0
  316. /package/dist/{oauth-server-QEXRSXEP.js → oauth-server-2ESBZB7F.js} +0 -0
  317. /package/dist/{webhook-pipe-LY4XEDL7.js → webhook-pipe-ZRUVOG5H.js} +0 -0
  318. /package/dist/{wiki-acl-M3OR547L.js → wiki-acl-MFLSS6DE.js} +0 -0
  319. /package/dist/{wiki-client-MAFYBXCQ.js → wiki-client-GBPR45BQ.js} +0 -0
@@ -0,0 +1,244 @@
1
+ import {
2
+ employeeSessionName,
3
+ ensureEmployee,
4
+ markAsReadByTaskFile,
5
+ notifyParentExe,
6
+ resolveExeSession,
7
+ sendIntercom
8
+ } from "./chunk-F7JLZXHC.js";
9
+ import {
10
+ getTransport
11
+ } from "./chunk-MVW62NIZ.js";
12
+ import {
13
+ recordOrchestrationEventBestEffort
14
+ } from "./chunk-HCBMPZDT.js";
15
+ import {
16
+ getAgentRuntime
17
+ } from "./chunk-XJUUWHVN.js";
18
+ import {
19
+ getSessionKey
20
+ } from "./chunk-CVYC6DUW.js";
21
+ import {
22
+ isCoordinatorName,
23
+ isMultiInstance,
24
+ shouldAutoInstance
25
+ } from "./chunk-CEJO7244.js";
26
+
27
+ // src/lib/tasks-notify.ts
28
+ var VERIFY_DELAY_MS = 1e4;
29
+ var ACK_PATTERNS = [
30
+ /New task assigned/,
31
+ /START WORKING NOW/,
32
+ /marked in_progress/,
33
+ /Reading.*\.md/
34
+ ];
35
+ function resolveDispatchRuntime(agentId, override) {
36
+ if (override) return override;
37
+ try {
38
+ return getAgentRuntime(agentId).runtime ?? null;
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+ async function verifyDispatch(sessionName, delayMs = VERIFY_DELAY_MS) {
44
+ const transport = getTransport();
45
+ await new Promise((r) => setTimeout(r, delayMs));
46
+ if (!transport.isAlive(sessionName)) {
47
+ return "session_dead";
48
+ }
49
+ try {
50
+ const output = transport.capturePane(sessionName, 20);
51
+ const acked = ACK_PATTERNS.some((p) => p.test(output));
52
+ return acked ? "verified" : "sent_unverified";
53
+ } catch {
54
+ return "sent_unverified";
55
+ }
56
+ }
57
+ async function dispatchTaskToEmployee(input) {
58
+ if (isCoordinatorName(input.assignedTo)) return { dispatched: "skipped" };
59
+ const dispatchRuntime = resolveDispatchRuntime(input.assignedTo, input.spawnRuntime);
60
+ recordOrchestrationEventBestEffort({
61
+ eventType: "dispatch.attempted",
62
+ source: "tasks-notify.dispatchTaskToEmployee",
63
+ taskId: input.taskId ?? null,
64
+ agentId: input.assignedTo,
65
+ runtime: dispatchRuntime,
66
+ payload: { priority: input.priority, projectName: input.projectName }
67
+ });
68
+ let crossProject = false;
69
+ if (input.projectName) {
70
+ try {
71
+ const { assertSessionScope } = await import("./session-scope-VMIPAZU7.js");
72
+ const check = assertSessionScope("dispatch_task", input.projectName);
73
+ if (check.reason === "cross_session_denied") {
74
+ crossProject = true;
75
+ recordOrchestrationEventBestEffort({
76
+ eventType: "dispatch.failed",
77
+ source: "tasks-notify.dispatchTaskToEmployee",
78
+ taskId: input.taskId ?? null,
79
+ agentId: input.assignedTo,
80
+ runtime: dispatchRuntime,
81
+ errorCode: "cross_session_denied",
82
+ payload: { projectName: input.projectName }
83
+ });
84
+ return { dispatched: "skipped", crossProject: true };
85
+ }
86
+ } catch {
87
+ }
88
+ }
89
+ try {
90
+ const transport = getTransport();
91
+ const exeSession = resolveExeSession();
92
+ if (!exeSession) {
93
+ recordOrchestrationEventBestEffort({
94
+ eventType: "dispatch.failed",
95
+ source: "tasks-notify.dispatchTaskToEmployee",
96
+ taskId: input.taskId ?? null,
97
+ agentId: input.assignedTo,
98
+ runtime: dispatchRuntime,
99
+ errorCode: "no_exe_session"
100
+ });
101
+ return { dispatched: "session_missing" };
102
+ }
103
+ const multiInstance = isMultiInstance(input.assignedTo);
104
+ if (multiInstance) {
105
+ const projectDir = input.projectDir ?? process.cwd();
106
+ const autoOpts = shouldAutoInstance(input.assignedTo);
107
+ const result = ensureEmployee(input.assignedTo, exeSession, projectDir, {
108
+ ...autoOpts,
109
+ runtimeOverride: input.spawnRuntime,
110
+ modelOverride: input.spawnModel
111
+ });
112
+ if (result.status === "failed") {
113
+ process.stderr.write(
114
+ `[dispatch-audit] SPAWN FAILED \u2192 ${input.assignedTo} | task="${input.title}" [${input.priority}] | error=${result.error}
115
+ `
116
+ );
117
+ recordOrchestrationEventBestEffort({
118
+ eventType: "dispatch.failed",
119
+ source: "tasks-notify.dispatchTaskToEmployee",
120
+ taskId: input.taskId ?? null,
121
+ agentId: input.assignedTo,
122
+ sessionScope: exeSession,
123
+ runtime: dispatchRuntime,
124
+ errorCode: "spawn_failed",
125
+ payload: { path: "multi_instance", error: result.error }
126
+ });
127
+ return { dispatched: "session_missing" };
128
+ }
129
+ const dispatched = result.status === "intercom_sent" || result.status === "intercom_unprocessed" ? "sent_unverified" : "spawned";
130
+ process.stderr.write(
131
+ `[dispatch-audit] ${dispatched === "spawned" ? "SPAWNED" : "INTERCOM"} \u2192 ${result.sessionName} | task="${input.title}" [${input.priority}]
132
+ `
133
+ );
134
+ recordOrchestrationEventBestEffort({
135
+ eventType: "dispatch.completed",
136
+ source: "tasks-notify.dispatchTaskToEmployee",
137
+ taskId: input.taskId ?? null,
138
+ agentId: input.assignedTo,
139
+ sessionScope: exeSession,
140
+ tmuxSession: result.sessionName,
141
+ runtime: dispatchRuntime,
142
+ result: dispatched,
143
+ payload: { path: "multi_instance", priority: input.priority }
144
+ });
145
+ return { dispatched, session: result.sessionName, crossProject };
146
+ }
147
+ const sessionName = employeeSessionName(input.assignedTo, exeSession);
148
+ if (transport.isAlive(sessionName)) {
149
+ const result = sendIntercom(sessionName, { force: true });
150
+ const dispatched = result === "acknowledged" || result === "debounced" || result === "queued" ? "verified" : result === "delivered" ? "sent_unverified" : "session_dead";
151
+ process.stderr.write(
152
+ `[dispatch-audit] intercom \u2192 ${sessionName} | task="${input.title}" [${input.priority}] | result=${dispatched} (sendIntercom=${result})
153
+ `
154
+ );
155
+ recordOrchestrationEventBestEffort({
156
+ eventType: "dispatch.completed",
157
+ source: "tasks-notify.dispatchTaskToEmployee",
158
+ taskId: input.taskId ?? null,
159
+ agentId: input.assignedTo,
160
+ sessionScope: exeSession,
161
+ tmuxSession: sessionName,
162
+ runtime: dispatchRuntime,
163
+ result: dispatched,
164
+ payload: { path: "single_instance_intercom", priority: input.priority }
165
+ });
166
+ return { dispatched, session: sessionName, crossProject };
167
+ } else {
168
+ const projectDir = input.projectDir ?? process.cwd();
169
+ const result = ensureEmployee(input.assignedTo, exeSession, projectDir, {
170
+ runtimeOverride: input.spawnRuntime,
171
+ modelOverride: input.spawnModel
172
+ });
173
+ if (result.status === "failed") {
174
+ process.stderr.write(
175
+ `[dispatch-audit] SPAWN FAILED \u2192 ${input.assignedTo} | task="${input.title}" [${input.priority}] | error=${result.error}
176
+ `
177
+ );
178
+ recordOrchestrationEventBestEffort({
179
+ eventType: "dispatch.failed",
180
+ source: "tasks-notify.dispatchTaskToEmployee",
181
+ taskId: input.taskId ?? null,
182
+ agentId: input.assignedTo,
183
+ sessionScope: exeSession,
184
+ runtime: dispatchRuntime,
185
+ errorCode: "spawn_failed",
186
+ payload: { path: "single_instance_spawn", error: result.error }
187
+ });
188
+ return { dispatched: "session_missing" };
189
+ }
190
+ process.stderr.write(
191
+ `[dispatch-audit] SPAWNED \u2192 ${result.sessionName} | task="${input.title}" [${input.priority}]
192
+ `
193
+ );
194
+ recordOrchestrationEventBestEffort({
195
+ eventType: "dispatch.completed",
196
+ source: "tasks-notify.dispatchTaskToEmployee",
197
+ taskId: input.taskId ?? null,
198
+ agentId: input.assignedTo,
199
+ sessionScope: exeSession,
200
+ tmuxSession: result.sessionName,
201
+ runtime: dispatchRuntime,
202
+ result: "spawned",
203
+ payload: { path: "single_instance_spawn", priority: input.priority }
204
+ });
205
+ return { dispatched: "spawned", session: result.sessionName, crossProject };
206
+ }
207
+ } catch {
208
+ recordOrchestrationEventBestEffort({
209
+ eventType: "dispatch.failed",
210
+ source: "tasks-notify.dispatchTaskToEmployee",
211
+ taskId: input.taskId ?? null,
212
+ agentId: input.assignedTo,
213
+ runtime: dispatchRuntime,
214
+ errorCode: "exception"
215
+ });
216
+ return { dispatched: "session_missing" };
217
+ }
218
+ }
219
+ function notifyTaskDone() {
220
+ try {
221
+ const key = getSessionKey();
222
+ if (key && !process.env.VITEST) {
223
+ notifyParentExe(key);
224
+ process.stderr.write(
225
+ `[dispatch-audit] notifyTaskDone \u2192 parent coordinator (session=${key})
226
+ `
227
+ );
228
+ }
229
+ } catch {
230
+ }
231
+ }
232
+ async function markTaskNotificationsRead(taskFile) {
233
+ try {
234
+ await markAsReadByTaskFile(taskFile);
235
+ } catch {
236
+ }
237
+ }
238
+
239
+ export {
240
+ verifyDispatch,
241
+ dispatchTaskToEmployee,
242
+ notifyTaskDone,
243
+ markTaskNotificationsRead
244
+ };
@@ -3,15 +3,15 @@ import {
3
3
  getClient,
4
4
  isInitialized,
5
5
  loadEmployees
6
- } from "./chunk-2H55BIV2.js";
6
+ } from "./chunk-CEJO7244.js";
7
7
  import {
8
8
  PLAN_LIMITS,
9
9
  checkLicense,
10
10
  isFeatureAllowed
11
- } from "./chunk-D5C56WO3.js";
11
+ } from "./chunk-MOZ2YQ54.js";
12
12
  import {
13
13
  EXE_AI_DIR
14
- } from "./chunk-TRZ5KA2R.js";
14
+ } from "./chunk-VXIMSRTO.js";
15
15
 
16
16
  // src/lib/plan-limits.ts
17
17
  import { readFileSync, existsSync } from "fs";
@@ -0,0 +1,388 @@
1
+ import {
2
+ isMainModule
3
+ } from "./chunk-6Y4B3QF6.js";
4
+
5
+ // src/bin/verify-stack.ts
6
+ import { execSync } from "child_process";
7
+ import { readFileSync, existsSync } from "fs";
8
+ import http from "http";
9
+ import path from "path";
10
+ var DEFAULT_COMPOSE = "/opt/exe-stack/docker-compose.yml";
11
+ var DEFAULT_ENV = "/opt/exe-stack/.env";
12
+ var CHECK_TIMEOUT_MS = 5e3;
13
+ var TOTAL_TIMEOUT_MS = 6e4;
14
+ var SERVICE_URLS = {
15
+ "exe-os": "http://127.0.0.1:8765/health",
16
+ "exe-gateway": "http://127.0.0.1:3100/health",
17
+ "exe-wiki": "http://127.0.0.1:3001/api/ping",
18
+ "exe-crm": "http://127.0.0.1:3000/healthz",
19
+ "exe-monitor-hub": "http://127.0.0.1:8090/api/health"
20
+ };
21
+ var FRONTEND_URLS = {
22
+ "exe-crm": "http://127.0.0.1:3000",
23
+ "exe-wiki": "http://127.0.0.1:3001",
24
+ "exe-monitor-hub": "http://127.0.0.1:8090"
25
+ };
26
+ var GOTRUE_TOKEN_URL = "http://127.0.0.1:9999/token?grant_type=password";
27
+ function loadEnvFile(envPath) {
28
+ if (!existsSync(envPath)) return {};
29
+ const raw = readFileSync(envPath, "utf8");
30
+ const vars = {};
31
+ for (const line of raw.split("\n")) {
32
+ const trimmed = line.trim();
33
+ if (!trimmed || trimmed.startsWith("#")) continue;
34
+ const eqIdx = trimmed.indexOf("=");
35
+ if (eqIdx < 1) continue;
36
+ const key = trimmed.slice(0, eqIdx).trim();
37
+ let val = trimmed.slice(eqIdx + 1).trim();
38
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
39
+ val = val.slice(1, -1);
40
+ }
41
+ vars[key] = val;
42
+ }
43
+ return vars;
44
+ }
45
+ function httpGet(url, timeoutMs, headers) {
46
+ return new Promise((resolve, reject) => {
47
+ const urlObj = new URL(url);
48
+ const opts = {
49
+ hostname: urlObj.hostname,
50
+ port: urlObj.port || 80,
51
+ path: urlObj.pathname + urlObj.search,
52
+ method: "GET",
53
+ timeout: timeoutMs,
54
+ headers: headers ?? {}
55
+ };
56
+ const req = http.request(opts, (res) => {
57
+ let body = "";
58
+ res.on("data", (chunk) => {
59
+ body += chunk.toString();
60
+ });
61
+ res.on("end", () => resolve({ status: res.statusCode ?? 0, body, contentType: res.headers["content-type"] ?? "" }));
62
+ });
63
+ req.on("timeout", () => {
64
+ req.destroy();
65
+ reject(new Error(`Timeout after ${timeoutMs}ms`));
66
+ });
67
+ req.on("error", reject);
68
+ req.end();
69
+ });
70
+ }
71
+ function httpPost(url, body, contentType, timeoutMs) {
72
+ return new Promise((resolve, reject) => {
73
+ const urlObj = new URL(url);
74
+ const opts = {
75
+ hostname: urlObj.hostname,
76
+ port: urlObj.port || 80,
77
+ path: urlObj.pathname + urlObj.search,
78
+ method: "POST",
79
+ timeout: timeoutMs,
80
+ headers: {
81
+ "Content-Type": contentType,
82
+ "Content-Length": Buffer.byteLength(body)
83
+ }
84
+ };
85
+ const req = http.request(opts, (res) => {
86
+ let data = "";
87
+ res.on("data", (chunk) => {
88
+ data += chunk.toString();
89
+ });
90
+ res.on("end", () => resolve({ status: res.statusCode ?? 0, body: data }));
91
+ });
92
+ req.on("timeout", () => {
93
+ req.destroy();
94
+ reject(new Error(`Timeout after ${timeoutMs}ms`));
95
+ });
96
+ req.on("error", reject);
97
+ req.write(body);
98
+ req.end();
99
+ });
100
+ }
101
+ async function checkContainersHealthy(composeFile) {
102
+ const check = "All containers healthy";
103
+ try {
104
+ const dir = path.dirname(composeFile);
105
+ const file = path.basename(composeFile);
106
+ const raw = execSync(`docker compose -f "${file}" ps --format json`, {
107
+ cwd: dir,
108
+ timeout: CHECK_TIMEOUT_MS,
109
+ encoding: "utf8",
110
+ stdio: ["pipe", "pipe", "pipe"]
111
+ });
112
+ const lines = raw.trim().split("\n").filter(Boolean);
113
+ if (lines.length === 0) {
114
+ return { check, status: "fail", message: "No containers found" };
115
+ }
116
+ const unhealthy = [];
117
+ const notRunning = [];
118
+ for (const line of lines) {
119
+ try {
120
+ const c = JSON.parse(line);
121
+ const name = c.Name || c.name || "unknown";
122
+ const state = (c.State || c.state || "").toLowerCase();
123
+ const health = (c.Health || c.health || "").toLowerCase();
124
+ if (state !== "running") notRunning.push(name);
125
+ else if (health && health !== "healthy") unhealthy.push(name);
126
+ } catch {
127
+ }
128
+ }
129
+ if (notRunning.length > 0) {
130
+ return { check, status: "fail", message: `Not running: ${notRunning.join(", ")}` };
131
+ }
132
+ if (unhealthy.length > 0) {
133
+ return { check, status: "warn", message: `Unhealthy: ${unhealthy.join(", ")}` };
134
+ }
135
+ return { check, status: "pass", message: `${lines.length} containers running and healthy` };
136
+ } catch (err) {
137
+ return { check, status: "fail", message: err instanceof Error ? err.message : String(err) };
138
+ }
139
+ }
140
+ async function checkServiceUrls() {
141
+ const check = "All service URLs respond 200";
142
+ const failures = [];
143
+ for (const [service, url] of Object.entries(SERVICE_URLS)) {
144
+ try {
145
+ const res = await httpGet(url, CHECK_TIMEOUT_MS);
146
+ if (res.status !== 200) {
147
+ failures.push(`${service}: HTTP ${res.status}`);
148
+ }
149
+ } catch (err) {
150
+ failures.push(`${service}: ${err instanceof Error ? err.message : String(err)}`);
151
+ }
152
+ }
153
+ if (failures.length > 0) {
154
+ return { check, status: "fail", message: failures.join("; ") };
155
+ }
156
+ return { check, status: "pass", message: `${Object.keys(SERVICE_URLS).length} services responding` };
157
+ }
158
+ async function checkGoTrueLogin(env) {
159
+ const check = "GoTrue login works";
160
+ const email = env.GOTRUE_TEST_EMAIL || process.env.GOTRUE_TEST_EMAIL;
161
+ const password = env.GOTRUE_TEST_PASSWORD || process.env.GOTRUE_TEST_PASSWORD;
162
+ if (!email || !password) {
163
+ return { result: { check, status: "skip", message: "GOTRUE_TEST_EMAIL / GOTRUE_TEST_PASSWORD not set" } };
164
+ }
165
+ try {
166
+ const body = JSON.stringify({ email, password });
167
+ const res = await httpPost(GOTRUE_TOKEN_URL, body, "application/json", CHECK_TIMEOUT_MS);
168
+ if (res.status !== 200) {
169
+ return { result: { check, status: "fail", message: `HTTP ${res.status}: ${res.body.slice(0, 200)}` } };
170
+ }
171
+ const parsed = JSON.parse(res.body);
172
+ const jwt = parsed.access_token;
173
+ if (!jwt) {
174
+ return { result: { check, status: "fail", message: "No access_token in response" } };
175
+ }
176
+ return { result: { check, status: "pass", message: "Login succeeded" }, jwt };
177
+ } catch (err) {
178
+ return { result: { check, status: "fail", message: err instanceof Error ? err.message : String(err) } };
179
+ }
180
+ }
181
+ async function checkWhatsAppConnected() {
182
+ const check = "WhatsApp still connected";
183
+ try {
184
+ const res = await httpGet(SERVICE_URLS["exe-gateway"], CHECK_TIMEOUT_MS);
185
+ if (res.status !== 200) {
186
+ return { check, status: "warn", message: `Gateway health returned HTTP ${res.status}` };
187
+ }
188
+ try {
189
+ const data = JSON.parse(res.body);
190
+ const adapters = data.adapters || data.channels;
191
+ if (!adapters || !Array.isArray(adapters)) {
192
+ return { check, status: "skip", message: "No adapters array in gateway health response" };
193
+ }
194
+ const connected = adapters.filter(
195
+ (a) => a.status === "connected" || a.connected === true
196
+ );
197
+ if (connected.length === 0) {
198
+ return { check, status: "warn", message: `0/${adapters.length} adapters connected` };
199
+ }
200
+ return { check, status: "pass", message: `${connected.length}/${adapters.length} adapter(s) connected` };
201
+ } catch {
202
+ return { check, status: "skip", message: "Could not parse gateway health response" };
203
+ }
204
+ } catch (err) {
205
+ return { check, status: "fail", message: err instanceof Error ? err.message : String(err) };
206
+ }
207
+ }
208
+ async function checkFrontendsLoad() {
209
+ const check = "Each frontend loads";
210
+ const failures = [];
211
+ for (const [service, url] of Object.entries(FRONTEND_URLS)) {
212
+ try {
213
+ const res = await httpGet(url, CHECK_TIMEOUT_MS);
214
+ if (!res.contentType.includes("text/html")) {
215
+ failures.push(`${service}: Content-Type=${res.contentType} (expected text/html)`);
216
+ } else if (res.body.length < 1e3) {
217
+ failures.push(`${service}: body ${res.body.length} bytes (expected >1000)`);
218
+ }
219
+ } catch (err) {
220
+ failures.push(`${service}: ${err instanceof Error ? err.message : String(err)}`);
221
+ }
222
+ }
223
+ if (failures.length > 0) {
224
+ return { check, status: "fail", message: failures.join("; ") };
225
+ }
226
+ return { check, status: "pass", message: `${Object.keys(FRONTEND_URLS).length} frontends serving HTML` };
227
+ }
228
+ async function checkMonitorMetrics() {
229
+ const check = "Monitor reports metrics";
230
+ try {
231
+ const res = await httpGet(SERVICE_URLS["exe-monitor-hub"], CHECK_TIMEOUT_MS);
232
+ if (res.status !== 200) {
233
+ return { check, status: "fail", message: `HTTP ${res.status}` };
234
+ }
235
+ return { check, status: "pass", message: "Monitor hub health OK" };
236
+ } catch (err) {
237
+ return { check, status: "fail", message: err instanceof Error ? err.message : String(err) };
238
+ }
239
+ }
240
+ async function checkRawPipeline(env) {
241
+ const check = "Raw pipeline alive";
242
+ const dbUrl = env.DATABASE_URL || env.EXED_DATABASE_URL || process.env.DATABASE_URL;
243
+ if (!dbUrl) {
244
+ return { check, status: "skip", message: "DATABASE_URL not set" };
245
+ }
246
+ try {
247
+ const result = execSync(
248
+ `psql "${dbUrl}" -t -c "SELECT COUNT(*) FROM raw.raw_events WHERE created_at > NOW() - INTERVAL '24 hours'" 2>&1`,
249
+ { timeout: CHECK_TIMEOUT_MS, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }
250
+ );
251
+ const count = parseInt(result.trim(), 10);
252
+ if (isNaN(count)) {
253
+ return { check, status: "warn", message: `Unexpected psql output: ${result.trim().slice(0, 100)}` };
254
+ }
255
+ if (count === 0) {
256
+ return { check, status: "warn", message: "0 events in last 24h \u2014 pipeline may be idle" };
257
+ }
258
+ return { check, status: "pass", message: `${count} event(s) in last 24h` };
259
+ } catch (err) {
260
+ const msg = err instanceof Error ? err.message : String(err);
261
+ if (msg.includes("does not exist") || msg.includes("relation")) {
262
+ return { check, status: "skip", message: "raw.raw_events table does not exist" };
263
+ }
264
+ return { check, status: "fail", message: msg.slice(0, 200) };
265
+ }
266
+ }
267
+ async function checkCrossServiceAuth(jwt) {
268
+ const check = "Cross-service auth";
269
+ if (!jwt) {
270
+ return { check, status: "skip", message: "No GoTrue JWT available (check 3 skipped or failed)" };
271
+ }
272
+ const targets = {
273
+ "exe-wiki": "http://127.0.0.1:3001/api/ping",
274
+ "exe-crm": "http://127.0.0.1:3000/healthz"
275
+ };
276
+ const failures = [];
277
+ for (const [service, url] of Object.entries(targets)) {
278
+ try {
279
+ const res = await httpGet(url, CHECK_TIMEOUT_MS, { Authorization: `Bearer ${jwt}` });
280
+ if (res.status !== 200) {
281
+ failures.push(`${service}: HTTP ${res.status}`);
282
+ }
283
+ } catch (err) {
284
+ failures.push(`${service}: ${err instanceof Error ? err.message : String(err)}`);
285
+ }
286
+ }
287
+ if (failures.length > 0) {
288
+ return { check, status: "fail", message: failures.join("; ") };
289
+ }
290
+ return { check, status: "pass", message: "JWT accepted by wiki + CRM" };
291
+ }
292
+ async function runVerifyStack(options) {
293
+ const composeFile = options?.composeFile ?? DEFAULT_COMPOSE;
294
+ const envFile = options?.envFile ?? DEFAULT_ENV;
295
+ const totalTimeout = options?.timeoutMs ?? TOTAL_TIMEOUT_MS;
296
+ const env = loadEnvFile(envFile);
297
+ const results = [];
298
+ const deadline = Date.now() + totalTimeout;
299
+ const addResult = (r) => {
300
+ results.push(r);
301
+ if (Date.now() > deadline) {
302
+ results.push({ check: "Total timeout", status: "fail", message: `Exceeded ${totalTimeout}ms` });
303
+ }
304
+ };
305
+ addResult(await checkContainersHealthy(composeFile));
306
+ if (Date.now() > deadline) return summarize(results);
307
+ addResult(await checkServiceUrls());
308
+ if (Date.now() > deadline) return summarize(results);
309
+ const goTrueResult = await checkGoTrueLogin(env);
310
+ addResult(goTrueResult.result);
311
+ if (Date.now() > deadline) return summarize(results);
312
+ addResult(await checkWhatsAppConnected());
313
+ if (Date.now() > deadline) return summarize(results);
314
+ addResult(await checkFrontendsLoad());
315
+ if (Date.now() > deadline) return summarize(results);
316
+ addResult(await checkMonitorMetrics());
317
+ if (Date.now() > deadline) return summarize(results);
318
+ addResult(await checkRawPipeline(env));
319
+ if (Date.now() > deadline) return summarize(results);
320
+ addResult(await checkCrossServiceAuth(goTrueResult.jwt));
321
+ return summarize(results);
322
+ }
323
+ function summarize(results) {
324
+ return {
325
+ results,
326
+ passed: results.filter((r) => r.status === "pass").length,
327
+ failed: results.filter((r) => r.status === "fail").length,
328
+ warned: results.filter((r) => r.status === "warn").length,
329
+ skipped: results.filter((r) => r.status === "skip").length
330
+ };
331
+ }
332
+ function printReport(report) {
333
+ const icons = { pass: "\u2705", fail: "\u274C", warn: "\u26A0\uFE0F ", skip: "\u23ED\uFE0F " };
334
+ console.log("\n\x1B[1mPost-Deploy Verification\x1B[0m\n");
335
+ for (const r of report.results) {
336
+ console.log(` ${icons[r.status] ?? "?"} ${r.check}: ${r.message}`);
337
+ }
338
+ console.log(
339
+ `
340
+ Pass: ${report.passed} Fail: ${report.failed} Warn: ${report.warned} Skip: ${report.skipped}
341
+ `
342
+ );
343
+ }
344
+ function printUsage() {
345
+ console.log(`
346
+ Usage: exe-os verify-stack [options]
347
+
348
+ Post-deploy verification \u2014 8 runtime checks after stack-update.
349
+
350
+ Options:
351
+ --compose <path> Path to docker-compose.yml (default: ${DEFAULT_COMPOSE})
352
+ --env <path> Path to .env file (default: ${DEFAULT_ENV})
353
+ --help Show this help message
354
+
355
+ Checks:
356
+ 1. All containers healthy (docker compose ps)
357
+ 2. All service URLs respond 200
358
+ 3. GoTrue login works (requires GOTRUE_TEST_EMAIL + GOTRUE_TEST_PASSWORD)
359
+ 4. WhatsApp still connected (adapter status)
360
+ 5. Each frontend loads (HTML > 1000 bytes)
361
+ 6. Monitor reports metrics
362
+ 7. Raw pipeline alive (recent raw_events)
363
+ 8. Cross-service auth (JWT \u2192 wiki + CRM)
364
+ `);
365
+ }
366
+ if (isMainModule(import.meta.url) && process.argv[1]?.includes("verify-stack")) {
367
+ const args = process.argv.slice(2);
368
+ if (args.includes("--help") || args.includes("-h")) {
369
+ printUsage();
370
+ process.exit(0);
371
+ }
372
+ const composeIdx = args.indexOf("--compose");
373
+ const envIdx = args.indexOf("--env");
374
+ const options = {};
375
+ if (composeIdx >= 0 && args[composeIdx + 1]) options.composeFile = args[composeIdx + 1];
376
+ if (envIdx >= 0 && args[envIdx + 1]) options.envFile = args[envIdx + 1];
377
+ runVerifyStack(options).then((report) => {
378
+ printReport(report);
379
+ process.exit(report.failed > 0 ? 1 : 0);
380
+ }).catch((err) => {
381
+ console.error(`[verify-stack] Fatal error: ${err instanceof Error ? err.message : String(err)}`);
382
+ process.exit(1);
383
+ });
384
+ }
385
+
386
+ export {
387
+ runVerifyStack
388
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  redactSecrets
3
- } from "./chunk-F7LU65PQ.js";
3
+ } from "./chunk-Y25OJWOQ.js";
4
4
 
5
5
  // src/lib/memory-write-governor.ts
6
6
  import { createHash } from "crypto";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sessionScopeFilter
3
- } from "./chunk-HNLPLLE6.js";
3
+ } from "./chunk-F7JLZXHC.js";
4
4
 
5
5
  // src/lib/git-task-sweep.ts
6
6
  import { execSync } from "child_process";
@@ -178,7 +178,7 @@ async function sweepTasks(projectName, options = {}) {
178
178
  }
179
179
  if (!dryRun) {
180
180
  try {
181
- const { updateTaskStatus } = await import("./tasks-crud-JXZEBZFR.js");
181
+ const { updateTaskStatus } = await import("./tasks-crud-DQOG2NPG.js");
182
182
  await updateTaskStatus({
183
183
  taskId: task.id,
184
184
  status: "needs_review",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getGlobalProceduresBlock
3
- } from "./chunk-GN5VHPPR.js";
3
+ } from "./chunk-NVZR7T4E.js";
4
4
 
5
5
  // src/lib/employee-templates.ts
6
6
  var BASE_OPERATING_PROCEDURES = `
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadEmployees
3
- } from "./chunk-2H55BIV2.js";
3
+ } from "./chunk-CEJO7244.js";
4
4
 
5
5
  // src/lib/agent-symlinks.ts
6
6
  import os from "os";