@askexenow/exe-os 0.9.302 → 0.9.310

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 (311) hide show
  1. package/deploy/compose/.env.example +8 -2
  2. package/deploy/compose/README.md +7 -3
  3. package/deploy/compose/add-routes.sh +107 -0
  4. package/deploy/compose/docker-compose.yml +91 -18
  5. package/deploy/compose/gateway-watchdog.sh +223 -0
  6. package/deploy/compose/generate-env.ts +16 -4
  7. package/deploy/compose/setup.sh +7 -8
  8. package/deploy/stack-manifests/v0.9.json +125 -4
  9. package/dist/{active-agent-ODI6GGVD.js → active-agent-ORX47ZKW.js} +4 -3
  10. package/dist/{active-agent-GGQAP4QE.js → active-agent-S5T2YMOR.js} +4 -3
  11. package/dist/{agentic-ontology-M7T72M6V.js → agentic-ontology-6KBAXLSJ.js} +1 -1
  12. package/dist/{backfill-metadata-GSZP2BEW.js → backfill-metadata-FV7GX6AS.js} +5 -4
  13. package/dist/{behaviors-JM6KFSXL.js → behaviors-47CPEKJ7.js} +6 -5
  14. package/dist/bin/agentic-ontology-backfill.js +6 -5
  15. package/dist/bin/agentic-reflection-backfill.js +7 -6
  16. package/dist/bin/agentic-semantic-label.js +6 -5
  17. package/dist/bin/backfill-conversations.js +8 -7
  18. package/dist/bin/backfill-responses.js +8 -7
  19. package/dist/bin/backfill-vectors.js +10 -9
  20. package/dist/bin/bulk-sync-postgres.js +14 -13
  21. package/dist/bin/cc-doctor.js +5 -4
  22. package/dist/bin/cleanup-stale-review-tasks.js +13 -12
  23. package/dist/bin/cli.js +20 -17
  24. package/dist/bin/deferred-daemon-restart.js +4 -4
  25. package/dist/bin/exe-agent-config.js +3 -2
  26. package/dist/bin/exe-agent.js +12 -11
  27. package/dist/bin/exe-assign.js +10 -9
  28. package/dist/bin/exe-boot.js +21 -20
  29. package/dist/bin/exe-call.js +5 -4
  30. package/dist/bin/exe-cloud.js +14 -13
  31. package/dist/bin/exe-config-dump.js +525 -0
  32. package/dist/bin/exe-dispatch.js +13 -12
  33. package/dist/bin/exe-doctor.js +2 -2
  34. package/dist/bin/exe-export-behaviors.js +8 -7
  35. package/dist/bin/exe-forget.js +7 -6
  36. package/dist/bin/exe-gateway.js +22 -11
  37. package/dist/bin/exe-healthcheck.js +7 -4
  38. package/dist/bin/exe-heartbeat.js +13 -12
  39. package/dist/bin/exe-kill.js +16 -15
  40. package/dist/bin/exe-launch-agent.js +41 -25
  41. package/dist/bin/exe-new-employee.js +9 -8
  42. package/dist/bin/exe-pending-messages.js +14 -13
  43. package/dist/bin/exe-pending-notifications.js +13 -12
  44. package/dist/bin/exe-pending-reviews.js +13 -12
  45. package/dist/bin/exe-preflight.js +108 -0
  46. package/dist/bin/exe-rename.js +5 -4
  47. package/dist/bin/exe-review.js +15 -14
  48. package/dist/bin/exe-search-quality.js +282 -0
  49. package/dist/bin/exe-search.js +6 -5
  50. package/dist/bin/exe-session-cleanup.js +18 -17
  51. package/dist/bin/exe-settings.js +15 -14
  52. package/dist/bin/exe-start-codex.js +13 -12
  53. package/dist/bin/exe-start-opencode.js +9 -8
  54. package/dist/bin/exe-status.js +14 -13
  55. package/dist/bin/exe-support.js +4 -4
  56. package/dist/bin/exe-team.js +4 -3
  57. package/dist/bin/exe-timers.js +237 -0
  58. package/dist/bin/git-sweep.js +14 -13
  59. package/dist/bin/graph-backfill.js +7 -6
  60. package/dist/bin/graph-export.js +6 -5
  61. package/dist/bin/import-history.js +10 -9
  62. package/dist/bin/install-launchd.js +5 -2
  63. package/dist/bin/install.js +16 -15
  64. package/dist/bin/intercom-check.js +4 -4
  65. package/dist/bin/mcp-sessions.js +2 -2
  66. package/dist/bin/orchestration-metrics.js +5 -4
  67. package/dist/bin/postgres-agentic-reflection-backfill.js +2 -2
  68. package/dist/bin/postgres-agentic-semantic-backfill.js +1 -1
  69. package/dist/bin/prune-orphan-chunks.js +43 -10
  70. package/dist/bin/scan-tasks.js +13 -12
  71. package/dist/bin/setup.js +1 -1
  72. package/dist/bin/shard-migrate.js +5 -4
  73. package/dist/bin/stack-update.js +30 -5
  74. package/dist/bin/vps-health-gate.js +1 -1
  75. package/dist/{capability-cards-BCTFKT4G.js → capability-cards-WQVY7WSS.js} +3 -2
  76. package/dist/{capacity-monitor-B4S3XEDO.js → capacity-monitor-BUKYPSWR.js} +14 -13
  77. package/dist/{catchup-brief-I35KHK62.js → catchup-brief-X5IVQAOH.js} +16 -15
  78. package/dist/{chunk-74TUYU5A.js → chunk-255DIG4B.js} +1 -1
  79. package/dist/{chunk-CXKR5Z5F.js → chunk-2EJ636HI.js} +4 -0
  80. package/dist/{chunk-ST3X3YMZ.js → chunk-2NGPZCWX.js} +4 -4
  81. package/dist/{chunk-LD2JKEJT.js → chunk-2NVEKSSP.js} +7 -7
  82. package/dist/{chunk-V6P7TPPA.js → chunk-2UVN2NBN.js} +148 -2
  83. package/dist/{chunk-OZRO37JW.js → chunk-3KH6GXXX.js} +2 -2
  84. package/dist/{chunk-IMJNYREY.js → chunk-43R2GILO.js} +1 -1
  85. package/dist/{chunk-6X2YNVLB.js → chunk-4BANMHJ5.js} +3 -3
  86. package/dist/{chunk-QNJPDIWY.js → chunk-4L4R6AQJ.js} +1 -1
  87. package/dist/{chunk-QWLPAEG5.js → chunk-4Q5VNQTV.js} +3 -3
  88. package/dist/{chunk-VLSYKMCJ.js → chunk-4RJJ5FJ2.js} +14 -2
  89. package/dist/{chunk-4AN6KMVG.js → chunk-5DPE7B7K.js} +1 -1
  90. package/dist/{chunk-H7ZNSQ2E.js → chunk-62UZWGFX.js} +2 -2
  91. package/dist/{chunk-ZQ2QHGWE.js → chunk-66JPZELX.js} +20 -24
  92. package/dist/{chunk-BUGMW7YF.js → chunk-6LNSZADA.js} +11 -11
  93. package/dist/{chunk-PBCRUNIK.js → chunk-6OD2RVIA.js} +492 -157
  94. package/dist/chunk-7ODTYODO.js +350 -0
  95. package/dist/{chunk-5YL4Y27D.js → chunk-7WDIGRSO.js} +1 -1
  96. package/dist/{chunk-WIL6LXNG.js → chunk-AC6DKMVS.js} +1 -1
  97. package/dist/{chunk-HZEAAKCR.js → chunk-B2J3BBJC.js} +3 -3
  98. package/dist/{chunk-LE7CDIOA.js → chunk-BUOMSIXH.js} +1 -1
  99. package/dist/{chunk-XKGNKH6V.js → chunk-DFUCFLZH.js} +1 -1
  100. package/dist/{chunk-U724Z3S3.js → chunk-DKHBMIVE.js} +100 -37
  101. package/dist/{chunk-MY36XDUK.js → chunk-DNFU56ZS.js} +1 -1
  102. package/dist/{chunk-GSWGOGP5.js → chunk-EOS7VPVT.js} +5 -5
  103. package/dist/{chunk-P33JVGSP.js → chunk-FM7XZDZI.js} +1 -1
  104. package/dist/chunk-G6EJKYK3.js +33 -0
  105. package/dist/{chunk-OMCNFTSI.js → chunk-GMZMBLHT.js} +1 -1
  106. package/dist/{chunk-4LZ54YGA.js → chunk-GSY6HL3T.js} +5 -5
  107. package/dist/{chunk-OVKNFTCL.js → chunk-HED6D5KR.js} +132 -21
  108. package/dist/{chunk-ALH6QLYF.js → chunk-HQODUV3G.js} +2 -2
  109. package/dist/{chunk-US64UR5O.js → chunk-IIHE3FNC.js} +3 -3
  110. package/dist/{chunk-H2ISTRWU.js → chunk-IRIPGGGL.js} +1 -1
  111. package/dist/{chunk-Z3EXECOX.js → chunk-ISILDO7P.js} +1 -1
  112. package/dist/{chunk-6ERZFDBS.js → chunk-IZPO6IOZ.js} +1 -1
  113. package/dist/{chunk-W65Z4SJS.js → chunk-J3QZPDNH.js} +1 -1
  114. package/dist/{chunk-3IJCP6ZH.js → chunk-JDYO76PI.js} +1 -1
  115. package/dist/{chunk-ORNKGGFX.js → chunk-JNARUXDC.js} +1 -1
  116. package/dist/{chunk-VME3UH4D.js → chunk-JV225JBX.js} +1 -1
  117. package/dist/{chunk-EI7PBUIA.js → chunk-JZW5AOWI.js} +1 -1
  118. package/dist/{chunk-TLOILHSL.js → chunk-K7KBAJQL.js} +36 -18
  119. package/dist/{chunk-RHMWSUJB.js → chunk-KAVUTP5G.js} +2 -2
  120. package/dist/{chunk-7FNELLMX.js → chunk-KPVVTHPK.js} +8 -8
  121. package/dist/{chunk-35U72CD2.js → chunk-KSMITUGY.js} +3 -3
  122. package/dist/{chunk-D6UICP3C.js → chunk-LMX7UKGX.js} +81 -3
  123. package/dist/{chunk-7ZWC5HVG.js → chunk-MTIJ2NXY.js} +1 -1
  124. package/dist/{chunk-KVHPBQV4.js → chunk-NCC3F6GM.js} +1 -1
  125. package/dist/{chunk-AYMSIV7X.js → chunk-NIZQ3CIS.js} +1 -1
  126. package/dist/{chunk-LTI2DLHY.js → chunk-OBJXZII2.js} +2 -2
  127. package/dist/{chunk-WHOT5NZ7.js → chunk-OR3TAZL3.js} +14 -2
  128. package/dist/{chunk-RQUHAXMM.js → chunk-PHFPIUWU.js} +2 -0
  129. package/dist/{chunk-N76VTMMF.js → chunk-PMEOSD6S.js} +2 -2
  130. package/dist/{chunk-TCJEFW5V.js → chunk-PPXQE7AS.js} +4 -4
  131. package/dist/{chunk-KHZQVLNZ.js → chunk-QE7UVQDP.js} +46 -0
  132. package/dist/{chunk-SXJACGQ5.js → chunk-QEGXNJGR.js} +4 -4
  133. package/dist/{chunk-W3E4VEEJ.js → chunk-RPBTYQKJ.js} +1 -1
  134. package/dist/chunk-RQ7OVXUZ.js +81 -0
  135. package/dist/{chunk-7L2EV3XX.js → chunk-RVXWGPD3.js} +39 -6
  136. package/dist/{chunk-YNALY3SX.js → chunk-RZJ6DXVE.js} +1 -1
  137. package/dist/{chunk-P3SIFDES.js → chunk-SCYWCWKY.js} +16 -4
  138. package/dist/{chunk-7I43GVER.js → chunk-SOT23KWW.js} +3 -3
  139. package/dist/{chunk-T62GAN7I.js → chunk-SPOXL7HF.js} +7 -7
  140. package/dist/{chunk-3YJMI422.js → chunk-TN2YCFQE.js} +4 -4
  141. package/dist/{chunk-YMSWCERY.js → chunk-U63BZI2B.js} +3 -3
  142. package/dist/{chunk-KA5RK5HZ.js → chunk-V42BSVX6.js} +2 -2
  143. package/dist/{chunk-PJTRAFL4.js → chunk-V4BW5HFQ.js} +3 -3
  144. package/dist/{chunk-4FG6IX7U.js → chunk-VFSYVQX4.js} +1 -1
  145. package/dist/chunk-VQRTO7IS.js +290 -0
  146. package/dist/{chunk-OR7J7TIA.js → chunk-VT6P7FV4.js} +1 -1
  147. package/dist/{chunk-BEIYF4NS.js → chunk-W2J2RF5N.js} +3 -3
  148. package/dist/{chunk-Y5ASPRP7.js → chunk-WBJXJ2R4.js} +17 -13
  149. package/dist/chunk-WCGNCH3Q.js +72 -0
  150. package/dist/{chunk-2LJDLQNO.js → chunk-WJ2PZGRV.js} +1 -1
  151. package/dist/{chunk-AAPPSMPH.js → chunk-WZBUKC5N.js} +1 -1
  152. package/dist/{chunk-RO7EXVSJ.js → chunk-X4AFBL4N.js} +1 -1
  153. package/dist/{chunk-BR74NYEF.js → chunk-XV5HRIXG.js} +5 -5
  154. package/dist/chunk-XXJRZ75E.js +43 -0
  155. package/dist/{chunk-VDHUHXFF.js → chunk-XYG722JW.js} +2 -2
  156. package/dist/{chunk-MM7SWUQ4.js → chunk-YB7U4WTY.js} +4 -4
  157. package/dist/{chunk-RMRZXPUU.js → chunk-Z6H6Y4BS.js} +1 -1
  158. package/dist/{token-budget-UMHRRDBT.js → chunk-ZOVHXTGC.js} +2 -9
  159. package/dist/{chunk-HNLBHP6P.js → chunk-ZZXADKAP.js} +3 -3
  160. package/dist/{co-activation-OKAHEMPE.js → co-activation-WN25AJOC.js} +3 -2
  161. package/dist/{co-occurrence-IHSPB53O.js → co-occurrence-YP2Q3OEA.js} +5 -4
  162. package/dist/{code-context-index-KGY4LKCA.js → code-context-index-ZWONKBKX.js} +4 -4
  163. package/dist/{conversation-entity-extractor-KXJSHRGJ.js → conversation-entity-extractor-KYOBXNID.js} +2 -2
  164. package/dist/{crdt-sync-K2G3C6XY.js → crdt-sync-ZFIFL2QM.js} +1 -1
  165. package/dist/{crm-webhook-ERZSQ3CW.js → crm-webhook-DGPHULOO.js} +2 -2
  166. package/dist/{cto-delegation-gate-ZCJ53LBQ.js → cto-delegation-gate-OF2A3TSS.js} +12 -11
  167. package/dist/daemon-auth-N6P2MZAV.js +17 -0
  168. package/dist/{daemon-orchestration-V6HALVDS.js → daemon-orchestration-G4RRTPP7.js} +16 -15
  169. package/dist/daemon-ready-signal-3L2MJT7C.js +13 -0
  170. package/dist/{db-backup-VZHSFUVA.js → db-backup-EORG4LBO.js} +1 -1
  171. package/dist/{doc-graph-extractor-LQ2IFND2.js → doc-graph-extractor-APZS3DFD.js} +5 -4
  172. package/dist/{dreaming-QAKUASYV.js → dreaming-Q4E3WBGY.js} +13 -12
  173. package/dist/{exe-drift-H3UWNFFY.js → exe-drift-CI5R6GUT.js} +4 -3
  174. package/dist/{exe-export-MN5D4JMT.js → exe-export-HQIQASIT.js} +7 -6
  175. package/dist/{exe-import-IFFMEVD7.js → exe-import-ULZK56WC.js} +7 -6
  176. package/dist/{exe-key-RSZC72QK.js → exe-key-ILNSBGRN.js} +5 -4
  177. package/dist/{exe-snapshot-I622MPLS.js → exe-snapshot-RUZTWZOF.js} +16 -15
  178. package/dist/{factory-CTFAGZUA.js → factory-YHQZ6RZZ.js} +14 -6
  179. package/dist/{fast-db-init-QEFVT7Q3.js → fast-db-init-KNJRL7T3.js} +1 -1
  180. package/dist/{founder-context-3SOKEW76.js → founder-context-QCTMEK66.js} +2 -2
  181. package/dist/gateway/index.js +12 -11
  182. package/dist/{git-staleness-E7RPQA5U.js → git-staleness-KIA5YI4H.js} +3 -2
  183. package/dist/{git-task-sweep-D3A2C5BW.js → git-task-sweep-WH6QE7HL.js} +13 -12
  184. package/dist/{global-procedures-POG4V6IK.js → global-procedures-SYZZCGDS.js} +4 -3
  185. package/dist/{graph-auto-extract-E7KALNWA.js → graph-auto-extract-J2TIWZEE.js} +5 -4
  186. package/dist/{graph-rag-3RZN7JR3.js → graph-rag-HITZZ63L.js} +2 -2
  187. package/dist/hooks/bug-report-worker.js +15 -14
  188. package/dist/hooks/codex-stop-task-finalizer.js +15 -14
  189. package/dist/hooks/commit-complete.js +15 -14
  190. package/dist/hooks/error-recall.js +8 -7
  191. package/dist/hooks/exe-heartbeat-hook.js +4 -3
  192. package/dist/hooks/ingest-worker.js +4 -4
  193. package/dist/hooks/ingest.js +8 -7
  194. package/dist/hooks/instructions-loaded.js +5 -4
  195. package/dist/hooks/manifest.json +20 -20
  196. package/dist/hooks/notification.js +5 -4
  197. package/dist/hooks/post-compact.js +14 -13
  198. package/dist/hooks/post-tool-combined.js +7 -7
  199. package/dist/hooks/pre-compact.js +19 -18
  200. package/dist/hooks/pre-tool-use.js +18 -17
  201. package/dist/hooks/prompt-submit.js +28 -27
  202. package/dist/hooks/session-end.js +24 -23
  203. package/dist/hooks/session-start.js +46 -22
  204. package/dist/hooks/stop.js +22 -21
  205. package/dist/hooks/subagent-stop.js +14 -13
  206. package/dist/hooks/summary-worker.js +22 -21
  207. package/dist/index.js +25 -23
  208. package/dist/{installer-IXUX73JN.js → installer-3NB3IBHF.js} +10 -9
  209. package/dist/{installer-RCUPPZ7Y.js → installer-IIJFCTMH.js} +10 -9
  210. package/dist/{installer-HDD6OH5Z.js → installer-PSDYMGN7.js} +7 -6
  211. package/dist/lib/cloud-sync.js +14 -13
  212. package/dist/lib/consolidation.js +8 -7
  213. package/dist/lib/database.js +3 -2
  214. package/dist/lib/db-daemon-client.js +4 -4
  215. package/dist/lib/db.js +3 -2
  216. package/dist/lib/device-registry.js +3 -1
  217. package/dist/lib/embedder.js +4 -4
  218. package/dist/lib/employee-templates.js +5 -4
  219. package/dist/lib/employees.js +3 -2
  220. package/dist/lib/exe-daemon-client.js +3 -3
  221. package/dist/lib/exe-daemon.js +256 -406
  222. package/dist/lib/hybrid-search.js +6 -5
  223. package/dist/lib/identity.js +3 -2
  224. package/dist/lib/license.js +2 -2
  225. package/dist/lib/messaging.js +13 -12
  226. package/dist/lib/reminders.js +4 -3
  227. package/dist/lib/schedules.js +6 -5
  228. package/dist/lib/session-registry.js +5 -4
  229. package/dist/lib/skill-learning.js +7 -6
  230. package/dist/lib/store.js +7 -4
  231. package/dist/lib/task-router.js +4 -3
  232. package/dist/lib/tasks.js +14 -13
  233. package/dist/lib/tmux-routing.js +16 -11
  234. package/dist/lib/token-spend.js +4 -3
  235. package/dist/{license-gate-V2UCK4KJ.js → license-gate-7SDHCJUO.js} +3 -3
  236. package/dist/mcp/register-tools.js +74 -73
  237. package/dist/mcp/server.js +97 -79
  238. package/dist/mcp/tools/complete-reminder.js +5 -4
  239. package/dist/mcp/tools/create-reminder.js +5 -4
  240. package/dist/mcp/tools/create-task.js +16 -15
  241. package/dist/mcp/tools/deactivate-behavior.js +8 -7
  242. package/dist/mcp/tools/list-reminders.js +5 -4
  243. package/dist/mcp/tools/list-tasks.js +16 -15
  244. package/dist/mcp/tools/send-message.js +15 -14
  245. package/dist/mcp/tools/update-task.js +15 -14
  246. package/dist/{mcp-http-config-7LFFPNGV.js → mcp-http-config-QSOVFXHW.js} +4 -3
  247. package/dist/mcp-tool-surface-CSPFXL3F.js +15 -0
  248. package/dist/{memory-cards-BGI6MJRN.js → memory-cards-II67WFL2.js} +3 -2
  249. package/dist/{memory-graph-extractor-DTRRNWHZ.js → memory-graph-extractor-PM4Q2KJG.js} +6 -5
  250. package/dist/{memory-poisoning-defense-MOCWJK6S.js → memory-poisoning-defense-ECXSX7HK.js} +3 -2
  251. package/dist/{memory-queue-client-DD4E5SIZ.js → memory-queue-client-HLURQEV6.js} +4 -4
  252. package/dist/{memory-reflection-UKKTGZYR.js → memory-reflection-PXF6YFDU.js} +3 -2
  253. package/dist/{notifications-AMJ2K3MM.js → notifications-UP7WQGG4.js} +12 -11
  254. package/dist/{orchestration-events-MB4QVHTD.js → orchestration-events-PZLLPCKY.js} +4 -3
  255. package/dist/orchestration-health-read-EJWVUARG.js +191 -0
  256. package/dist/{orchestrator-M7DJH6TN.js → orchestrator-PUT45J4O.js} +14 -13
  257. package/dist/{pipeline-router-4LT5YG5P.js → pipeline-router-5CRWKESM.js} +4 -3
  258. package/dist/{plan-limits-ENS7OJWP.js → plan-limits-SH2NDFNX.js} +6 -5
  259. package/dist/{project-boot-6W5JPGSB.js → project-boot-2TCPDZ4S.js} +25 -1
  260. package/dist/{projection-worker-WWXZK7QD.js → projection-worker-HWY37MNC.js} +2 -2
  261. package/dist/{prospective-memory-VNGLPMS6.js → prospective-memory-FQSVMCGG.js} +3 -2
  262. package/dist/{reranker-6XBS55FA.js → reranker-AALRMGMM.js} +1 -1
  263. package/dist/{retrieval-health-ATX5TIQ2.js → retrieval-health-PNWJSJNG.js} +1 -1
  264. package/dist/{review-polling-E4ALHTQE.js → review-polling-65JZUE3T.js} +13 -12
  265. package/dist/runtime/index.js +24 -22
  266. package/dist/{session-events-3J6APMKN.js → session-events-EJ3OSAA6.js} +13 -12
  267. package/dist/session-kill-telemetry-3HGM7SNQ.js +63 -0
  268. package/dist/{session-scope-E54VIYTJ.js → session-scope-JGDYAMJO.js} +12 -11
  269. package/dist/{setup-wizard-XV736U5D.js → setup-wizard-44LMFM2C.js} +1 -1
  270. package/dist/shared-rate-limit-store-QZPQEVE2.js +80 -0
  271. package/dist/{skill-refinement-FTURVWFN.js → skill-refinement-DUOO6B7V.js} +3 -2
  272. package/dist/{stack-release-JZVTSBJJ.js → stack-release-XYMKU7NT.js} +53 -4
  273. package/dist/{stack-update-BIK2QHOE.js → stack-update-XHQJRJEP.js} +5 -3
  274. package/dist/{steward-gate-YGU4VXPP.js → steward-gate-6NWRDLX2.js} +4 -3
  275. package/dist/{task-enforcement-GY3VTY6L.js → task-enforcement-UOULTGFB.js} +12 -11
  276. package/dist/{task-scope-PYOK7OQ6.js → task-scope-P5STKYAC.js} +12 -11
  277. package/dist/{tasks-crud-HLJEJ2UU.js → tasks-crud-24HMTULR.js} +12 -11
  278. package/dist/{tasks-notify-NGS3DWUJ.js → tasks-notify-LAIU7UUI.js} +13 -12
  279. package/dist/{tasks-review-BP5V2X34.js → tasks-review-AFJAU2DY.js} +12 -11
  280. package/dist/{telemetry-upload-AXYPFAPS.js → telemetry-upload-DWFGC2XJ.js} +8 -7
  281. package/dist/token-budget-4RFZKWGH.js +16 -0
  282. package/dist/{tool-capability-index-RHPVMMDD.js → tool-capability-index-ZEXBWKUZ.js} +1 -1
  283. package/dist/{tool-telemetry-BLSVABFJ.js → tool-telemetry-BS5JXM5M.js} +1 -1
  284. package/dist/tui/App.js +21 -20
  285. package/dist/{tui-data-EYPOFYLS.js → tui-data-UNO5B7PU.js} +12 -11
  286. package/dist/{worker-gate-SMFOBMMX.js → worker-gate-C6CTTYMD.js} +1 -1
  287. package/dist/{workflow-engine-TDJZ3TXB.js → workflow-engine-4W2KYCDV.js} +2 -2
  288. package/dist/{worktree-XISIYRM4.js → worktree-2CXY6NEB.js} +5 -4
  289. package/dist/{worktree-sweep-AS6GAR6X.js → worktree-sweep-K3CJFSUL.js} +6 -5
  290. package/package.json +9 -4
  291. package/release-notes.json +17 -88
  292. package/stack.release.json +51 -4
  293. package/dist/chunk-PHOQAVTK.js +0 -42
  294. package/dist/daemon-auth-BK7ON5ZH.js +0 -13
  295. package/dist/session-kill-telemetry-KOAHLRBT.js +0 -31
  296. package/dist/{chunk-XDE5IGBX.js → chunk-2NS3QRMJ.js} +0 -0
  297. package/dist/{chunk-JTMKRUX6.js → chunk-A2YZG4AD.js} +0 -0
  298. package/dist/{chunk-UZATXREL.js → chunk-AE74NOE6.js} +0 -0
  299. package/dist/{chunk-LUGWK6QB.js → chunk-FF5DA4XP.js} +3 -3
  300. /package/dist/{chunk-BGOMFGSW.js → chunk-GWPICNSO.js} +0 -0
  301. /package/dist/{chunk-NLHUA3YB.js → chunk-I3DPCSDG.js} +0 -0
  302. /package/dist/{chunk-YM3367VC.js → chunk-J3SR5MGG.js} +0 -0
  303. /package/dist/{chunk-FKFVNV7X.js → chunk-K4BKJJ4F.js} +0 -0
  304. /package/dist/{chunk-PTDBHQX7.js → chunk-MQCTK6EF.js} +0 -0
  305. /package/dist/{chunk-GBV5PV5T.js → chunk-QNXM2HXW.js} +0 -0
  306. /package/dist/{chunk-GZSG2ZOX.js → chunk-YUBTHJVV.js} +0 -0
  307. /package/dist/{core-memory-4OM7LR77.js → core-memory-OC5ITKKV.js} +0 -0
  308. /package/dist/{entity-boost-SFHIRXT5.js → entity-boost-NF3LE6OJ.js} +0 -0
  309. /package/dist/{message-queue-client-QTC3VHJT.js → message-queue-client-4VDU6BZY.js} +0 -0
  310. /package/dist/{oauth-server-BPN55EJM.js → oauth-server-EWUL7DMD.js} +0 -0
  311. /package/dist/{wiki-acl-45SIGG4O.js → wiki-acl-CONNF6ES.js} +0 -0
@@ -0,0 +1,350 @@
1
+ // src/lib/preflight-checks.ts
2
+ import { readFileSync, existsSync } from "fs";
3
+ import path from "path";
4
+ var REQUIRED_INFRA = {
5
+ postgres: ["exe-db", "postgres", "db", "exe-db-jkt"],
6
+ redis: ["redis"],
7
+ clickhouse: ["clickhouse"],
8
+ "exe-sso-edge": ["exe-sso-edge", "sso-edge"],
9
+ cloudflared: ["cloudflared"]
10
+ };
11
+ var FORBIDDEN_HOST_SUBSTRINGS = ["askexe.com", "askexenow.com"];
12
+ var CLIENT_FACING_HOST_FIELDS = ["healthHost", "healthUrl"];
13
+ var BYOK_ENFORCEMENT_VARS = ["EXE_ALLOW_DIRECT_PROVIDER_KEYS", "EXE_BILLING_MODE"];
14
+ var BYOK_LEGACY_VARS = ["BYOK_ENABLED"];
15
+ function resolveDefaultManifest() {
16
+ let dir = path.dirname(new URL(import.meta.url).pathname);
17
+ for (let i = 0; i < 6; i++) {
18
+ const candidate = path.join(dir, "deploy", "stack-manifests", "v0.9.json");
19
+ if (existsSync(candidate)) return candidate;
20
+ const parent = path.dirname(dir);
21
+ if (parent === dir) break;
22
+ dir = parent;
23
+ }
24
+ return path.join(process.cwd(), "deploy", "stack-manifests", "v0.9.json");
25
+ }
26
+ function parseImageRef(image) {
27
+ const hasDigest = /@sha256:[0-9a-f]{64}/i.test(image);
28
+ const withoutDigest = image.replace(/@sha256:[0-9a-f]{64}/i, "");
29
+ const lastSlash = withoutDigest.lastIndexOf("/");
30
+ const namePart = lastSlash >= 0 ? withoutDigest.slice(lastSlash + 1) : withoutDigest;
31
+ const colonIdx = namePart.indexOf(":");
32
+ const hasTag = colonIdx >= 0;
33
+ const tag = hasTag ? namePart.slice(colonIdx + 1) : "";
34
+ return { hasDigest, hasTag, tag };
35
+ }
36
+ function loadEnvLikeFile(filePath) {
37
+ const vars = /* @__PURE__ */ new Set();
38
+ if (!filePath || !existsSync(filePath)) return { vars, exists: false };
39
+ const raw = readFileSync(filePath, "utf8");
40
+ for (const line of raw.split("\n")) {
41
+ const m = line.match(/^\s*#?\s*([A-Z][A-Z0-9_]+)\s*=/);
42
+ if (m) vars.add(m[1]);
43
+ }
44
+ return { vars, exists: true };
45
+ }
46
+ function readComposeText(composePath) {
47
+ if (!composePath || !existsSync(composePath)) return { text: "", exists: false };
48
+ return { text: readFileSync(composePath, "utf8"), exists: true };
49
+ }
50
+ function resolveStack(manifest, requested) {
51
+ if (manifest.services && !manifest.stacks) {
52
+ return { version: manifest.version ?? "(single)", services: manifest.services };
53
+ }
54
+ if (!manifest.stacks) return { version: "(none)", services: {} };
55
+ const version = requested ?? manifest.latest ?? Object.keys(manifest.stacks).sort().pop() ?? "";
56
+ const entry = manifest.stacks[version];
57
+ return { version, services: entry?.services ?? {} };
58
+ }
59
+ function checkDigestPinning(services) {
60
+ const bug = "ee16e7ef (digest-pinning)";
61
+ const offenders = [];
62
+ for (const [name, svc] of Object.entries(services)) {
63
+ if (!svc.image) continue;
64
+ const { hasDigest } = parseImageRef(svc.image);
65
+ if (!hasDigest) offenders.push(`${name}=${svc.image}`);
66
+ }
67
+ if (offenders.length > 0) {
68
+ return {
69
+ check: "digest-pinning",
70
+ status: "fail",
71
+ bug,
72
+ offenders,
73
+ message: `${offenders.length} image(s) tag-pinned WITHOUT @sha256 digest (release claims digest-pinning): ${offenders.join(", ")}`
74
+ };
75
+ }
76
+ return { check: "digest-pinning", status: "pass", bug, message: "all images @sha256 digest-pinned" };
77
+ }
78
+ function checkNoLatest(services) {
79
+ const bug = "monitor :latest / no-:latest";
80
+ const offenders = [];
81
+ for (const [name, svc] of Object.entries(services)) {
82
+ if (!svc.image) continue;
83
+ const { hasDigest, hasTag, tag } = parseImageRef(svc.image);
84
+ if (tag === "latest") offenders.push(`${name}=${svc.image}`);
85
+ else if (!hasTag && !hasDigest) offenders.push(`${name}=${svc.image} (untagged \u2192 implicit :latest)`);
86
+ }
87
+ if (offenders.length > 0) {
88
+ return {
89
+ check: "no-latest",
90
+ status: "fail",
91
+ bug,
92
+ offenders,
93
+ message: `${offenders.length} image(s) use :latest / are untagged: ${offenders.join(", ")}`
94
+ };
95
+ }
96
+ return { check: "no-latest", status: "pass", bug, message: "no :latest / untagged images" };
97
+ }
98
+ function checkDependencyClosure(services) {
99
+ const bug = "4948fc48 (dependency-closure)";
100
+ const present = /* @__PURE__ */ new Set();
101
+ for (const [name, svc] of Object.entries(services)) {
102
+ present.add(name);
103
+ if (svc.composeService) present.add(svc.composeService);
104
+ }
105
+ const missing = [];
106
+ for (const [canonical, aliases] of Object.entries(REQUIRED_INFRA)) {
107
+ if (!aliases.some((a) => present.has(a))) missing.push(canonical);
108
+ }
109
+ if (missing.length > 0) {
110
+ return {
111
+ check: "dependency-closure",
112
+ status: "fail",
113
+ bug,
114
+ offenders: missing,
115
+ message: `manifest missing required infra dependency closure \u2014 selected/fresh installs would skip: ${missing.join(", ")}`
116
+ };
117
+ }
118
+ return { check: "dependency-closure", status: "pass", bug, message: `all required infra present (${Object.keys(REQUIRED_INFRA).join(", ")})` };
119
+ }
120
+ function checkNoHardcodedHost(services) {
121
+ const bug = "ERP white-label-leak (no-hardcoded-askexe-host)";
122
+ const offenders = [];
123
+ for (const [name, svc] of Object.entries(services)) {
124
+ for (const field of CLIENT_FACING_HOST_FIELDS) {
125
+ const val = svc[field];
126
+ if (typeof val !== "string") continue;
127
+ const hit = FORBIDDEN_HOST_SUBSTRINGS.find((h) => val.includes(h));
128
+ if (hit) offenders.push(`${name}.${field}=${val}`);
129
+ }
130
+ }
131
+ if (offenders.length > 0) {
132
+ return {
133
+ check: "no-hardcoded-askexe-host",
134
+ status: "fail",
135
+ bug,
136
+ offenders,
137
+ message: `client-facing field(s) hardcode an AskExe host (white-label leak): ${offenders.join(", ")}`
138
+ };
139
+ }
140
+ return { check: "no-hardcoded-askexe-host", status: "pass", bug, message: "no hardcoded AskExe hosts in client-facing fields" };
141
+ }
142
+ function checkEnvContract(env, compose) {
143
+ const bug = "BYOK env-contract-mismatch";
144
+ if (!env.exists && !compose.exists) {
145
+ return {
146
+ check: "env-contract",
147
+ status: "warn",
148
+ bug,
149
+ message: "env example + compose not provided \u2014 BYOK enforcement contract not verified (pass --env / --compose to enforce)"
150
+ };
151
+ }
152
+ const declared = new Set(env.vars);
153
+ if (compose.exists) {
154
+ for (const m of compose.text.matchAll(/\$\{?([A-Z][A-Z0-9_]+)/g)) declared.add(m[1]);
155
+ }
156
+ const missingEnforcement = BYOK_ENFORCEMENT_VARS.filter((v) => !declared.has(v));
157
+ const exposedLegacy = BYOK_LEGACY_VARS.filter((v) => declared.has(v));
158
+ if (missingEnforcement.length > 0 && exposedLegacy.length > 0) {
159
+ return {
160
+ check: "env-contract",
161
+ status: "fail",
162
+ bug,
163
+ offenders: [...exposedLegacy.map((v) => `exposes ${v}`), ...missingEnforcement.map((v) => `missing ${v}`)],
164
+ message: `BYOK env-contract mismatch \u2014 customer surface exposes ${exposedLegacy.join("/")} but billing enforcement reads ${BYOK_ENFORCEMENT_VARS.join("+")} (absent). BYOK can bypass billing.`
165
+ };
166
+ }
167
+ if (missingEnforcement.length > 0) {
168
+ return {
169
+ check: "env-contract",
170
+ status: "warn",
171
+ bug,
172
+ offenders: missingEnforcement.map((v) => `missing ${v}`),
173
+ message: `billing enforcement vars not declared: ${missingEnforcement.join(", ")}`
174
+ };
175
+ }
176
+ return { check: "env-contract", status: "pass", bug, message: `BYOK enforcement vars present (${BYOK_ENFORCEMENT_VARS.join(", ")})` };
177
+ }
178
+ function checkNoHostNet(composeTexts) {
179
+ const bug = "monitor host-networking (no-host-net)";
180
+ const available = composeTexts.filter((c) => c.exists);
181
+ if (available.length === 0) {
182
+ return {
183
+ check: "no-host-net",
184
+ status: "warn",
185
+ bug,
186
+ message: "no compose file provided \u2014 host-networking not verified (pass --compose / --monitor-compose to enforce)"
187
+ };
188
+ }
189
+ const HOST_NET = /^\s*network_mode\s*:\s*["']?host["']?\s*$/;
190
+ const HOST_NET_FLAG = /--network(?:=|\s+)["']?host["']?/;
191
+ const offenders = [];
192
+ for (const compose of available) {
193
+ const lines = compose.text.split("\n");
194
+ let currentService = null;
195
+ let serviceIndent = -1;
196
+ for (const rawLine of lines) {
197
+ const line = rawLine.replace(/\r$/, "");
198
+ const trimmed = line.trim();
199
+ if (!trimmed || trimmed.startsWith("#")) continue;
200
+ const indent = line.match(/^(\s*)/)?.[1]?.length ?? 0;
201
+ const headerMatch = line.match(/^(\s+)([A-Za-z0-9._-]+):\s*$/);
202
+ if (headerMatch && (currentService === null || indent <= serviceIndent)) {
203
+ currentService = headerMatch[2];
204
+ serviceIndent = headerMatch[1].length;
205
+ }
206
+ if (HOST_NET.test(line) || HOST_NET_FLAG.test(line)) {
207
+ const where = currentService ? `${compose.label}:${currentService}` : compose.label;
208
+ offenders.push(`${where} (${trimmed})`);
209
+ }
210
+ }
211
+ }
212
+ if (offenders.length > 0) {
213
+ return {
214
+ check: "no-host-net",
215
+ status: "fail",
216
+ bug,
217
+ offenders,
218
+ message: `compose service(s) use host networking (network_mode: host) \u2014 bypasses Docker isolation + SSO edge: ${offenders.join(", ")}`
219
+ };
220
+ }
221
+ return { check: "no-host-net", status: "pass", bug, message: "no host networking (network_mode: host) in compose" };
222
+ }
223
+ function runChecks(services, env, compose, monitorCompose, customerComposeLabel) {
224
+ return [
225
+ checkDigestPinning(services),
226
+ checkNoLatest(services),
227
+ checkDependencyClosure(services),
228
+ checkNoHardcodedHost(services),
229
+ checkEnvContract(env, compose),
230
+ checkNoHostNet([
231
+ { label: customerComposeLabel, text: compose.text, exists: compose.exists },
232
+ monitorCompose
233
+ ])
234
+ ];
235
+ }
236
+ function tally(findings) {
237
+ const passed = findings.filter((f) => f.status === "pass").length;
238
+ const warned = findings.filter((f) => f.status === "warn").length;
239
+ const failed = findings.filter((f) => f.status === "fail").length;
240
+ const verdict = failed > 0 ? "RED" : warned > 0 ? "YELLOW" : "GREEN";
241
+ return { verdict, passed, warned, failed };
242
+ }
243
+ function runPreflight(options) {
244
+ const manifestPath = options?.manifestPath ?? resolveDefaultManifest();
245
+ if (!existsSync(manifestPath)) {
246
+ return {
247
+ verdict: "RED",
248
+ manifestPath,
249
+ stackVersion: "(missing)",
250
+ findings: [{ check: "manifest-load", status: "fail", bug: "preflight", message: `manifest not found: ${manifestPath}` }],
251
+ passed: 0,
252
+ warned: 0,
253
+ failed: 1
254
+ };
255
+ }
256
+ let manifest;
257
+ try {
258
+ manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
259
+ } catch (err) {
260
+ return {
261
+ verdict: "RED",
262
+ manifestPath,
263
+ stackVersion: "(parse-error)",
264
+ findings: [{ check: "manifest-load", status: "fail", bug: "preflight", message: `manifest parse error: ${err instanceof Error ? err.message : String(err)}` }],
265
+ passed: 0,
266
+ warned: 0,
267
+ failed: 1
268
+ };
269
+ }
270
+ const { version, services } = resolveStack(manifest, options?.stackVersion);
271
+ const repoRoot = path.resolve(path.dirname(manifestPath), "..", "..");
272
+ const envExamplePath = options?.envExamplePath ?? path.join(repoRoot, "deploy", "compose", ".env.example");
273
+ const composePath = options?.composePath ?? path.join(repoRoot, "deploy", "compose", "docker-compose.yml");
274
+ const monitorComposePath = options?.monitorComposePath ?? path.join(repoRoot, "deploy", "monitor", "docker-compose.hub.yml");
275
+ const env = loadEnvLikeFile(envExamplePath);
276
+ const compose = readComposeText(composePath);
277
+ const monitorComposeRead = readComposeText(monitorComposePath);
278
+ const monitorCompose = { label: "monitor-compose", text: monitorComposeRead.text, exists: monitorComposeRead.exists };
279
+ const findings = runChecks(services, env, compose, monitorCompose, "customer-compose");
280
+ const { verdict, passed, warned, failed } = tally(findings);
281
+ return { verdict, manifestPath, stackVersion: version, findings, passed, warned, failed };
282
+ }
283
+ function runPreflightOnManifest(input) {
284
+ const label = input.label ?? "(in-memory manifest)";
285
+ const { version, services } = resolveStack(input.manifest, input.stackVersion);
286
+ const env = loadEnvLikeFile(input.envExamplePath);
287
+ const compose = readComposeText(input.composePath);
288
+ const monitorComposeRead = readComposeText(input.monitorComposePath);
289
+ const monitorCompose = { label: "monitor-compose", text: monitorComposeRead.text, exists: monitorComposeRead.exists };
290
+ const findings = runChecks(services, env, compose, monitorCompose, "customer-compose");
291
+ const { verdict, passed, warned, failed } = tally(findings);
292
+ return { verdict, manifestPath: label, stackVersion: version, findings, passed, warned, failed };
293
+ }
294
+ var ICONS = { pass: "\u{1F7E2}", warn: "\u{1F7E0}", fail: "\u{1F534}" };
295
+ function formatPreflightFindings(report, all = false) {
296
+ const lines = [];
297
+ for (const f of report.findings) {
298
+ if (!all && f.status === "pass") continue;
299
+ lines.push(` ${ICONS[f.status]} ${f.check} [guards ${f.bug}]: ${f.message}`);
300
+ }
301
+ return lines.join("\n");
302
+ }
303
+ function isPreflightOverrideEnabled(env = process.env) {
304
+ return /^(1|true|yes|on)$/i.test((env.EXE_PREFLIGHT_OVERRIDE ?? "").trim());
305
+ }
306
+ function assertPreflightGate(report, options = {}) {
307
+ const ctx = options.context ? `[${options.context}] ` : "";
308
+ const log = options.log ?? ((m) => console.log(m));
309
+ const warn = options.warn ?? ((m) => console.warn(m));
310
+ const override = options.allowRed === true || isPreflightOverrideEnabled();
311
+ if (report.verdict === "GREEN") {
312
+ log(`${ctx}\u{1F7E2} preflight GREEN (pass ${report.passed} / warn ${report.warned} / fail ${report.failed}) \u2014 stack ${report.stackVersion}`);
313
+ return report;
314
+ }
315
+ if (report.verdict === "YELLOW") {
316
+ warn(`${ctx}\u{1F7E0} preflight YELLOW (${report.warned} warning(s)) \u2014 stack ${report.stackVersion}. Proceeding; warnings are non-blocking:`);
317
+ warn(formatPreflightFindings(report));
318
+ return report;
319
+ }
320
+ const findings = formatPreflightFindings(report);
321
+ if (override) {
322
+ warn(`${ctx}\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\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`);
323
+ warn(`${ctx}\u2551 \u26A0\uFE0F BREAK-GLASS: preflight is RED but override is engaged \u2551`);
324
+ warn(`${ctx}\u2551 A RED manifest is shipping INTENTIONALLY. This is logged. \u2551`);
325
+ warn(`${ctx}\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\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`);
326
+ warn(`${ctx}RED findings (overridden):
327
+ ${findings}`);
328
+ warn(`${ctx}Override via: ${options.allowRed === true ? "--allow-red flag" : "EXE_PREFLIGHT_OVERRIDE env"}. Remediate the manifest immediately after.`);
329
+ return report;
330
+ }
331
+ throw new Error(
332
+ `${ctx}Preflight gate FAILED (RED) \u2014 stack ${report.stackVersion}. Company procedure: no manifest published or stack-update applied until preflight is GREEN.
333
+ ${findings}
334
+ Break-glass: re-run with --allow-red or EXE_PREFLIGHT_OVERRIDE=1 to ship a RED manifest intentionally (LOUDLY logged).`
335
+ );
336
+ }
337
+
338
+ export {
339
+ resolveDefaultManifest,
340
+ resolveStack,
341
+ checkDigestPinning,
342
+ checkNoLatest,
343
+ checkDependencyClosure,
344
+ checkNoHardcodedHost,
345
+ checkEnvContract,
346
+ checkNoHostNet,
347
+ runPreflight,
348
+ runPreflightOnManifest,
349
+ assertPreflightGate
350
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  clean,
3
3
  stableId
4
- } from "./chunk-UZATXREL.js";
4
+ } from "./chunk-AE74NOE6.js";
5
5
 
6
6
  // src/lib/reflection-checkpoints.ts
7
7
  function parsePayload(payload) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  processCRMEvent
3
- } from "./chunk-XDE5IGBX.js";
3
+ } from "./chunk-2NS3QRMJ.js";
4
4
 
5
5
  // src/gateway/adapters/crm-webhook.ts
6
6
  function parseTwentyWebhook(payload) {
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  cleanupCardsForMemories,
3
3
  cleanupGraphLinksForMemories
4
- } from "./chunk-LUGWK6QB.js";
4
+ } from "./chunk-FF5DA4XP.js";
5
5
  import {
6
6
  resolveAnthropicAuth
7
7
  } from "./chunk-PROQW3NL.js";
8
8
  import {
9
9
  vectorToBlob
10
- } from "./chunk-Y5ASPRP7.js";
10
+ } from "./chunk-WBJXJ2R4.js";
11
11
  import {
12
12
  extractKeywords,
13
13
  keywordsToString
14
14
  } from "./chunk-CHCA3ZM2.js";
15
15
  import {
16
16
  isCoordinatorName
17
- } from "./chunk-P3SIFDES.js";
17
+ } from "./chunk-SCYWCWKY.js";
18
18
 
19
19
  // src/lib/consolidation.ts
20
20
  import { randomUUID } from "crypto";
@@ -9,7 +9,7 @@ import {
9
9
  getCoordinatorEmployee,
10
10
  getEmployee,
11
11
  loadEmployeesSync
12
- } from "./chunk-P3SIFDES.js";
12
+ } from "./chunk-SCYWCWKY.js";
13
13
  import {
14
14
  EXE_AI_DIR
15
15
  } from "./chunk-DFIOOK5R.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  listBehaviors
3
- } from "./chunk-N76VTMMF.js";
3
+ } from "./chunk-PMEOSD6S.js";
4
4
  import {
5
5
  loadConfigSync
6
6
  } from "./chunk-DFIOOK5R.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadLicense
3
- } from "./chunk-VME3UH4D.js";
3
+ } from "./chunk-JV225JBX.js";
4
4
 
5
5
  // src/lib/stack-update.ts
6
6
  import { execFileSync, spawnSync } from "child_process";
@@ -902,6 +902,65 @@ function refreshPackagedInitSql(dest, created = []) {
902
902
  function refreshPackagedErpNginxConf(dest, created = []) {
903
903
  copyTemplate("deploy/compose/erp-nginx/nginx.conf", dest, created, { overwrite: true });
904
904
  }
905
+ function ensureOverlayDir(dest, actions = []) {
906
+ try {
907
+ if (existsSync(dest) && !lstatSync(dest).isDirectory()) {
908
+ rmSync(dest, { force: true });
909
+ }
910
+ if (!existsSync(dest)) {
911
+ mkdirSync(dest, { recursive: true, mode: 493 });
912
+ actions.push("create_overlay_dir");
913
+ }
914
+ } catch (err) {
915
+ const reason = err instanceof Error ? err.message : String(err);
916
+ console.warn(`[stack-update] Could not ensure overlay dir ${dest} (${reason}); customer overlays may not mount.`);
917
+ }
918
+ }
919
+ function listOverlayFiles(overlayDir) {
920
+ try {
921
+ if (!existsSync(overlayDir) || !lstatSync(overlayDir).isDirectory()) return [];
922
+ return readdirSync(overlayDir).filter((name) => {
923
+ try {
924
+ return lstatSync(path.join(overlayDir, name)).isFile();
925
+ } catch {
926
+ return false;
927
+ }
928
+ }).sort();
929
+ } catch {
930
+ return [];
931
+ }
932
+ }
933
+ function composeMountsOverlay(composeRaw) {
934
+ return /\.\/overlay:\/data\/overlay/.test(composeRaw);
935
+ }
936
+ function applyGatewayOverlays(stackDir, composeRaw, exec) {
937
+ const overlayDir = path.join(stackDir, "overlay");
938
+ const overlayFiles = listOverlayFiles(overlayDir);
939
+ if (overlayFiles.length === 0) {
940
+ return { applied: false, warned: false, overlayFiles };
941
+ }
942
+ let warned = false;
943
+ if (!composeMountsOverlay(composeRaw)) {
944
+ console.warn(
945
+ `[stack-update] \u26A0 OVERLAY WARNING (bug 02bc1bb8): ${overlayFiles.length} customer overlay file(s) found in ${overlayDir} (${overlayFiles.join(", ")}), but the live docker-compose.yml does NOT bind-mount ./overlay into the gateway. These overlays will be SILENTLY DROPPED on the next container recreate. Add '- ./overlay:/data/overlay:ro' to the exe-gateway service volumes and re-deploy.`
946
+ );
947
+ warned = true;
948
+ }
949
+ const addRoutes = path.join(stackDir, "add-routes.sh");
950
+ if (!existsSync(addRoutes)) {
951
+ console.warn(`[stack-update] \u26A0 overlay re-apply hook missing at ${addRoutes}; overlays NOT re-applied. Re-run bootstrap.`);
952
+ return { applied: false, warned: true, overlayFiles };
953
+ }
954
+ try {
955
+ console.log(`[stack-update] Re-applying ${overlayFiles.length} customer overlay file(s) via add-routes.sh (bug 02bc1bb8)\u2026`);
956
+ exec("bash", [addRoutes], { cwd: stackDir });
957
+ return { applied: true, warned, overlayFiles };
958
+ } catch (err) {
959
+ const reason = err instanceof Error ? err.message : String(err);
960
+ console.warn(`[stack-update] \u26A0 Overlay re-apply failed (non-fatal): ${reason}. Overlays remain at ${overlayDir}; apply manually with: bash ${addRoutes}`);
961
+ return { applied: false, warned: true, overlayFiles };
962
+ }
963
+ }
905
964
  var BOOTSTRAP_OVERWRITTEN_CONFIG_FILES = [
906
965
  "init-db.sql",
907
966
  "erp-nginx/nginx.conf",
@@ -1009,6 +1068,7 @@ function hydrateEnv(raw, opts) {
1009
1068
  else if (key.endsWith("_PASSWORD")) replacements[key] = randomSecret(24);
1010
1069
  else if (key.endsWith("_TOKEN")) replacements[key] = randomHexSecret(32);
1011
1070
  else if (key.endsWith("_SECRET") || key.endsWith("_SALT")) replacements[key] = randomSecret(32);
1071
+ else if (key === "EXE_MONITOR_KEY") replacements[key] = randomSecret(32);
1012
1072
  else if (key.endsWith("_KEY") && key !== "EXE_LICENSE_KEY") continue;
1013
1073
  }
1014
1074
  if (domain) next = next.replaceAll("CHANGEME_DOMAIN", domain);
@@ -1016,44 +1076,23 @@ function hydrateEnv(raw, opts) {
1016
1076
  const remaining = [...parseEnv(next).entries()].filter(([, value]) => /CHANGEME/.test(value)).map(([key, value]) => `${key}=${value}`);
1017
1077
  return { raw: next, hadPlaceholders: /CHANGEME/.test(raw), remaining: [...new Set(remaining)] };
1018
1078
  }
1019
- async function pairMonitorAgent(hubUrl, licenseKey, domain, envFile) {
1020
- if (!hubUrl || !licenseKey || !domain) {
1021
- return { paired: false, error: "Missing hubUrl, licenseKey, or domain for monitor pairing" };
1079
+ async function pairMonitorAgent(hubUrl, _licenseKey, _domain, envFile) {
1080
+ if (!hubUrl) {
1081
+ return { paired: false, error: "Missing hubUrl for monitor pairing check" };
1022
1082
  }
1023
- const registrationUrl = `${hubUrl.replace(/\/+$/, "")}/api/register-agent`;
1024
- try {
1025
- const res = await fetch(registrationUrl, {
1026
- method: "POST",
1027
- headers: {
1028
- "content-type": "application/json",
1029
- authorization: `Bearer ${licenseKey}`
1030
- },
1031
- body: JSON.stringify({ name: domain, host: domain, port: 45876 }),
1032
- signal: AbortSignal.timeout(15e3)
1033
- });
1034
- if (!res.ok) {
1035
- const body = await res.text().catch(() => "");
1036
- return { paired: false, error: `Monitor hub returned HTTP ${res.status}: ${body}` };
1037
- }
1038
- const data = await res.json();
1039
- if (!data.token || !data.key) {
1040
- return { paired: false, error: "Monitor hub response missing token or key" };
1041
- }
1042
- if (existsSync(envFile)) {
1043
- const envRaw = readFileSync(envFile, "utf8");
1044
- const patched = patchEnv(envRaw, {
1045
- MONITOR_AGENT_TOKEN: data.token,
1046
- MONITOR_AGENT_KEY: data.key
1047
- });
1048
- if (patched !== envRaw) {
1049
- writeSecretFile(envFile, patched);
1050
- }
1083
+ if (existsSync(envFile)) {
1084
+ const envRaw = readFileSync(envFile, "utf8");
1085
+ const parsed = parseEnv(envRaw);
1086
+ const token = (parsed.get("MONITOR_AGENT_TOKEN") ?? "").trim();
1087
+ const key = (parsed.get("MONITOR_AGENT_KEY") ?? "").trim();
1088
+ if (token && !/CHANGEME/.test(token) && key && !/CHANGEME/.test(key)) {
1089
+ return { paired: true, systemName: "(existing credentials)" };
1051
1090
  }
1052
- return { paired: true, systemName: data.name ?? domain };
1053
- } catch (err) {
1054
- const reason = err instanceof Error ? err.message : String(err);
1055
- return { paired: false, error: `Monitor hub unreachable: ${reason}` };
1056
1091
  }
1092
+ return {
1093
+ paired: false,
1094
+ error: "The monitor hub (Beszel) does not expose a REST registration endpoint. Pair the agent manually: open the hub UI \u2192 Settings \u2192 Add System, then write the generated MONITOR_AGENT_TOKEN and MONITOR_AGENT_KEY into " + envFile
1095
+ };
1057
1096
  }
1058
1097
  function bootstrapStackHost(options) {
1059
1098
  const exec = options.exec ?? defaultExec;
@@ -1098,6 +1137,15 @@ function bootstrapStackHost(options) {
1098
1137
  path.join(path.dirname(options.composeFile), "cloudflared", "config.yml.example"),
1099
1138
  createdFiles
1100
1139
  );
1140
+ ensureOverlayDir(path.join(path.dirname(options.composeFile), "overlay"), actions);
1141
+ for (const helper of ["gateway-watchdog.sh", "add-routes.sh"]) {
1142
+ const dest = path.join(path.dirname(options.composeFile), helper);
1143
+ copyTemplate(`deploy/compose/${helper}`, dest, createdFiles, { overwrite: true });
1144
+ try {
1145
+ chmodSync(dest, 493);
1146
+ } catch {
1147
+ }
1148
+ }
1101
1149
  let envHadPlaceholders = false;
1102
1150
  let envRemainingPlaceholders = [];
1103
1151
  if (existsSync(options.envFile)) {
@@ -1504,7 +1552,7 @@ async function runStackUpdate(options) {
1504
1552
  console.log(`[stack-update] Monitor agent paired: ${result.systemName}`);
1505
1553
  } else {
1506
1554
  console.warn(
1507
- `[stack-update] \u26A0\uFE0F Monitor agent pairing FAILED \u2014 the agent is enabled (COMPOSE_PROFILES=monitor-agent) but has no usable TOKEN/KEY, so it will NOT report fleet health. Reason: ${result.error}. Fix the hub at ${hubUrl} (POST /api/register-agent) and re-run \`exe-os stack-update\`, or pair the agent manually from the hub UI and write MONITOR_AGENT_TOKEN/MONITOR_AGENT_KEY into ${options.envFile}.`
1555
+ `[stack-update] \u26A0\uFE0F Monitor agent pairing INCOMPLETE \u2014 the agent is enabled (COMPOSE_PROFILES=monitor-agent) but has no usable TOKEN/KEY, so it will NOT report fleet health. ${result.error}`
1508
1556
  );
1509
1557
  }
1510
1558
  }
@@ -1663,6 +1711,13 @@ ${lines.join("\n")}`
1663
1711
  } catch {
1664
1712
  }
1665
1713
  const updates = { ...migratedEnvVars, ...Object.fromEntries(plan.changes.map((c) => [c.key, c.after])) };
1714
+ {
1715
+ const currentMonitorKey = parseEnv(readFileSync(options.envFile, "utf8")).get("EXE_MONITOR_KEY") ?? "";
1716
+ if (!currentMonitorKey.trim() || /CHANGEME/.test(currentMonitorKey)) {
1717
+ updates.EXE_MONITOR_KEY = randomSecret(32);
1718
+ console.log("[stack-update] Generated EXE_MONITOR_KEY (bug 84d9a74a: was missing/empty \u2014 monitor error ingestion was failing 503)");
1719
+ }
1720
+ }
1666
1721
  const currentEnvMap = parseEnv(envRaw);
1667
1722
  const manifestExeOsPin = updates.EXE_OS_IMAGE_TAG ?? currentEnvMap.get("EXE_OS_IMAGE_TAG");
1668
1723
  const overrideInFile = /^\s*EXE_OS_SERVER_IMAGE_TAG\s*=/m.test(envRaw);
@@ -1956,6 +2011,13 @@ ${lines.join("\n")}`
1956
2011
  endReleasePost();
1957
2012
  }
1958
2013
  }
2014
+ try {
2015
+ const liveCompose = existsSync(options.composeFile) ? readFileSync(options.composeFile, "utf8") : composeRaw;
2016
+ applyGatewayOverlays(stackDir, liveCompose, exec);
2017
+ } catch (overlayErr) {
2018
+ const reason = overlayErr instanceof Error ? overlayErr.message : String(overlayErr);
2019
+ console.warn(`[stack-update] \u26A0 Overlay re-apply step failed (non-fatal): ${reason}`);
2020
+ }
1959
2021
  for (const serviceName of Object.keys(plan.release.services)) {
1960
2022
  updateServiceStatus(lockFile, serviceName, "completed", now);
1961
2023
  }
@@ -2488,6 +2550,7 @@ export {
2488
2550
  assertProductionDeployGate,
2489
2551
  assertBreakingChangesAllowed,
2490
2552
  verifyManifestImagesAvailable,
2553
+ applyGatewayOverlays,
2491
2554
  backupStackConfig,
2492
2555
  pairMonitorAgent,
2493
2556
  bootstrapStackHost,
@@ -6,7 +6,7 @@ import {
6
6
  connectEmbedDaemon,
7
7
  isClientConnected,
8
8
  sendDaemonRequest
9
- } from "./chunk-TCJEFW5V.js";
9
+ } from "./chunk-PPXQE7AS.js";
10
10
 
11
11
  // src/lib/db-daemon-client.ts
12
12
  function normalizeStatement(stmt) {
@@ -2,7 +2,7 @@ import {
2
2
  dispatchTaskToEmployee,
3
3
  markTaskNotificationsRead,
4
4
  notifyTaskDone
5
- } from "./chunk-3YJMI422.js";
5
+ } from "./chunk-TN2YCFQE.js";
6
6
  import {
7
7
  cleanupReviewFile,
8
8
  createTaskCore,
@@ -11,7 +11,7 @@ import {
11
11
  sessionScopeFilter,
12
12
  updateTaskStatus,
13
13
  writeNotification
14
- } from "./chunk-OVKNFTCL.js";
14
+ } from "./chunk-HED6D5KR.js";
15
15
  import {
16
16
  orgBus
17
17
  } from "./chunk-MP2AFCGL.js";
@@ -19,7 +19,7 @@ import {
19
19
  getClient,
20
20
  getCoordinatorName,
21
21
  isCoordinatorName
22
- } from "./chunk-P3SIFDES.js";
22
+ } from "./chunk-SCYWCWKY.js";
23
23
  import {
24
24
  EXE_AI_DIR
25
25
  } from "./chunk-DFIOOK5R.js";
@@ -61,7 +61,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
61
61
  }
62
62
  if (unblockedRows.rows.length > 0 && !process.env.VITEST) {
63
63
  try {
64
- const { dispatchTaskToEmployee: dispatchTaskToEmployee2 } = await import("./tasks-notify-NGS3DWUJ.js");
64
+ const { dispatchTaskToEmployee: dispatchTaskToEmployee2 } = await import("./tasks-notify-LAIU7UUI.js");
65
65
  const dispatched = /* @__PURE__ */ new Set();
66
66
  for (const ur of unblockedRows.rows) {
67
67
  const assignee = String(ur.assigned_to);
@@ -333,7 +333,7 @@ async function updateTask(input) {
333
333
  await markTaskNotificationsRead(taskFile);
334
334
  if (isCompletionReviewTransition && !isCoordinator && row.reviewer) {
335
335
  try {
336
- const { writeNotification: writeNotification2 } = await import("./notifications-AMJ2K3MM.js");
336
+ const { writeNotification: writeNotification2 } = await import("./notifications-UP7WQGG4.js");
337
337
  const reviewer = String(row.reviewer);
338
338
  await writeNotification2({
339
339
  agentId: reviewer,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  writeMemoryViaDaemon
3
- } from "./chunk-KVHPBQV4.js";
3
+ } from "./chunk-NCC3F6GM.js";
4
4
 
5
5
  // src/lib/auto-checkpoint.ts
6
6
  var FILE_RE = /(?:^|\s)([\w./-]+\.(?:ts|tsx|js|jsx|json|md|yml|yaml|sql|go|py|css|scss|html|sh))(?:\b|$)/g;