@askexenow/exe-os 0.9.382 → 0.9.384

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 (493) hide show
  1. package/delivery/catalog.json +1254 -0
  2. package/deploy/compose/.env.customer.example +5 -5
  3. package/deploy/compose/.env.example +3 -3
  4. package/deploy/compose/docker-compose.yml +1 -1
  5. package/deploy/compose/generate-env.ts +65 -9
  6. package/deploy/compose/setup.sh +205 -7
  7. package/deploy/compose/sso-edge/default.conf.template +45 -0
  8. package/deploy/compose/sso-edge/sso-redirect.conf +11 -2
  9. package/deploy/stack-manifests/v0.9.30-apps.json +1 -1
  10. package/deploy/stack-manifests/v0.9.json +254 -2
  11. package/dist/.dist-verified.json +3 -3
  12. package/dist/{active-agent-GFUUCFLD.js → active-agent-F5V4E4UL.js} +7 -7
  13. package/dist/{active-agent-LE6FE6SO.js → active-agent-YTBB4ZQM.js} +7 -7
  14. package/dist/{agent-defs-generator-EIUA3SH5.js → agent-defs-generator-7TFISIJQ.js} +6 -6
  15. package/dist/{agent-loop-7ZRH56EX.js → agent-loop-EZ7LDAGD.js} +1 -1
  16. package/dist/{agentic-ontology-67JGSP7G.js → agentic-ontology-XVTUVV7W.js} +1 -1
  17. package/dist/{artifact-backup-NYXAYASJ.js → artifact-backup-TF6YWQT2.js} +5 -5
  18. package/dist/{backfill-gate-KWJQ35YX.js → backfill-gate-FWYLCGNJ.js} +3 -3
  19. package/dist/{backfill-metadata-RQYG2WUJ.js → backfill-metadata-J6MXIDCW.js} +10 -10
  20. package/dist/{background-jobs-6VMD55PK.js → background-jobs-V3DZRFKU.js} +3 -3
  21. package/dist/{backup-verify-HC4YDSGN.js → backup-verify-6DVBQMDP.js} +67 -18
  22. package/dist/{behavior-injection-6HSXP43Q.js → behavior-injection-XDA7ZCYN.js} +21 -20
  23. package/dist/{behavior-promotion-SJDQ2Y3U.js → behavior-promotion-4VLQ7LXK.js} +20 -19
  24. package/dist/{behaviors-6ITLA2CK.js → behaviors-SCCZP7RZ.js} +19 -18
  25. package/dist/bin/age-ontology-load.js +3 -3
  26. package/dist/bin/agentic-ontology-backfill.js +12 -12
  27. package/dist/bin/agentic-reflection-backfill.js +13 -13
  28. package/dist/bin/agentic-semantic-label.js +12 -12
  29. package/dist/bin/backfill-conversations.js +17 -16
  30. package/dist/bin/backfill-responses.js +17 -16
  31. package/dist/bin/backfill-vectors.js +23 -22
  32. package/dist/bin/bulk-sync-postgres.js +28 -27
  33. package/dist/bin/cc-doctor.js +17 -16
  34. package/dist/bin/cleanup-stale-review-tasks.js +29 -28
  35. package/dist/bin/cli.js +35 -26
  36. package/dist/bin/deferred-daemon-restart.js +124 -123
  37. package/dist/bin/exe-actions.js +1 -1
  38. package/dist/bin/exe-agent-config.js +6 -6
  39. package/dist/bin/exe-agent.js +22 -22
  40. package/dist/bin/exe-assign.js +19 -18
  41. package/dist/bin/exe-boot.js +57 -56
  42. package/dist/bin/exe-call.js +7 -7
  43. package/dist/bin/exe-cicd.js +38 -8
  44. package/dist/bin/exe-cloud.js +30 -29
  45. package/dist/bin/exe-config-dump.js +6 -6
  46. package/dist/bin/exe-dispatch.js +30 -29
  47. package/dist/bin/exe-doctor.js +11 -11
  48. package/dist/bin/exe-export-behaviors.js +23 -22
  49. package/dist/bin/exe-forget.js +13 -13
  50. package/dist/bin/exe-gateway.js +47 -14
  51. package/dist/bin/exe-grant.js +6 -6
  52. package/dist/bin/exe-healthcheck.js +17 -16
  53. package/dist/bin/exe-heartbeat.js +41 -35
  54. package/dist/bin/exe-kill.js +35 -34
  55. package/dist/bin/exe-launch-agent.js +43 -42
  56. package/dist/bin/exe-mcp.js +9 -9
  57. package/dist/bin/exe-memory-reads.js +10 -10
  58. package/dist/bin/exe-new-employee.js +11 -11
  59. package/dist/bin/exe-os-mcp-proxy.js +9 -9
  60. package/dist/bin/exe-pending-messages.js +30 -29
  61. package/dist/bin/exe-pending-notifications.js +29 -28
  62. package/dist/bin/exe-pending-reviews.js +30 -29
  63. package/dist/bin/exe-preflight.js +1 -1
  64. package/dist/bin/exe-rename.js +9 -9
  65. package/dist/bin/exe-review.js +34 -33
  66. package/dist/bin/exe-search.js +12 -12
  67. package/dist/bin/exe-session-cleanup.js +35 -34
  68. package/dist/bin/exe-settings.js +29 -28
  69. package/dist/bin/exe-start-codex.js +30 -29
  70. package/dist/bin/exe-start-opencode.js +27 -26
  71. package/dist/bin/exe-status.js +31 -30
  72. package/dist/bin/exe-support.js +5 -5
  73. package/dist/bin/exe-team.js +7 -7
  74. package/dist/bin/exe-verify-running-images.js +1 -1
  75. package/dist/bin/exe-watchdog.js +8 -8
  76. package/dist/bin/generate-hook-manifest.js +7 -1
  77. package/dist/bin/git-sweep.js +30 -29
  78. package/dist/bin/graph-backfill.js +12 -12
  79. package/dist/bin/graph-export.js +11 -11
  80. package/dist/bin/hooks-cli.js +1 -1
  81. package/dist/bin/import-history.js +15 -15
  82. package/dist/bin/install.js +130 -129
  83. package/dist/bin/intercom-check.js +11 -7
  84. package/dist/bin/mcp-sessions.js +2 -2
  85. package/dist/bin/orchestration-metrics.js +7 -7
  86. package/dist/bin/postgres-agentic-reflection-backfill.js +5 -5
  87. package/dist/bin/postgres-agentic-semantic-backfill.js +4 -4
  88. package/dist/bin/reconcile-backlog.js +2 -2
  89. package/dist/bin/registry-proxy.js +1 -1
  90. package/dist/bin/repair-document-chunks.js +161 -0
  91. package/dist/bin/scan-tasks.js +30 -29
  92. package/dist/bin/setup.js +5 -5
  93. package/dist/bin/shard-migrate.js +11 -11
  94. package/dist/bin/stack-update.js +625 -33
  95. package/dist/bin/update.js +96 -22
  96. package/dist/bin/verify-stack.js +2 -2
  97. package/dist/bin/vps-health-gate.js +1 -1
  98. package/dist/{boot-generation-L55QANCX.js → boot-generation-Q7LGQ3AO.js} +6 -6
  99. package/dist/{boot-review-sections-AON5ZCR2.js → boot-review-sections-G5774FR5.js} +28 -27
  100. package/dist/{branch-hygiene-QLD77IMJ.js → branch-hygiene-44WLSOZR.js} +2 -2
  101. package/dist/{branding-I6KIMB7F.js → branding-KMWCY5HZ.js} +3 -3
  102. package/dist/build-manifest.json +1259 -1219
  103. package/dist/{capability-cards-WTOXY7O6.js → capability-cards-I3RHCF4F.js} +5 -5
  104. package/dist/{capacity-monitor-ZLG7FSWM.js → capacity-monitor-7I7GDONU.js} +30 -29
  105. package/dist/{catchup-brief-QHY7D7N2.js → catchup-brief-3T5PARIR.js} +39 -36
  106. package/dist/check-image-pullability-2AIVB4BX.js +338 -0
  107. package/dist/{chunk-CTCCYKOV.js → chunk-2FKU4ZEO.js} +55 -29
  108. package/dist/{chunk-M7O7TGGU.js → chunk-2NW4LRDU.js} +1 -1
  109. package/dist/{chunk-XTFM4KMW.js → chunk-2PZTMSMG.js} +6 -6
  110. package/dist/{chunk-UWX6MMCX.js → chunk-3B6FLNLV.js} +1 -1
  111. package/dist/{chunk-GPJIBLP4.js → chunk-3DAEZILW.js} +1 -1
  112. package/dist/{chunk-NY6SBR4O.js → chunk-3FGBBJYM.js} +15 -3
  113. package/dist/{chunk-C4OZVVSG.js → chunk-3OX34OC3.js} +50 -18
  114. package/dist/{chunk-TXTXC3QG.js → chunk-3RGTLZNO.js} +12 -12
  115. package/dist/{chunk-PYRO25A5.js → chunk-3SUPEE6H.js} +10 -11
  116. package/dist/{chunk-PPMGQFLJ.js → chunk-3XY57PKT.js} +2 -2
  117. package/dist/{chunk-CRHI5QTZ.js → chunk-46VSBDUW.js} +2 -2
  118. package/dist/{chunk-VZT66WWP.js → chunk-4AAMFWJT.js} +2 -2
  119. package/dist/{chunk-4GZTBLJG.js → chunk-4AR5XKCH.js} +1 -1
  120. package/dist/{chunk-IHXW4VUI.js → chunk-5IADGFGR.js} +1 -1
  121. package/dist/{chunk-GLQEJOXE.js → chunk-5MVKTNZP.js} +57 -0
  122. package/dist/{chunk-AVMLC2MR.js → chunk-5U2IJBFV.js} +290 -41
  123. package/dist/{chunk-JUKDL5MF.js → chunk-6BJCDWSM.js} +1 -1
  124. package/dist/{chunk-6WWNK7UX.js → chunk-6FIC57PH.js} +1 -1
  125. package/dist/{chunk-ASUICGPX.js → chunk-6YDY6ZTD.js} +4 -4
  126. package/dist/{chunk-FU5O2REK.js → chunk-72V3S44T.js} +108 -29
  127. package/dist/{chunk-LTIIZHNA.js → chunk-7J2ZQ4XN.js} +1 -1
  128. package/dist/{chunk-7RI2CNXJ.js → chunk-7OTR2OET.js} +1 -1
  129. package/dist/{chunk-ZVBVPX4W.js → chunk-7UHZBVP3.js} +82 -51
  130. package/dist/{chunk-PTY2N23C.js → chunk-AGC2V7JS.js} +26 -13
  131. package/dist/{chunk-44VR3PFW.js → chunk-AHESD3KW.js} +1 -1
  132. package/dist/{chunk-NPGV4MZ3.js → chunk-ALRHGEAJ.js} +1 -1
  133. package/dist/{chunk-WJC6AAJN.js → chunk-ANVHWV2X.js} +2 -2
  134. package/dist/{chunk-AGZSGAEN.js → chunk-APL7HUE3.js} +105 -32
  135. package/dist/{chunk-7UH2JWBF.js → chunk-AZSTIAVL.js} +176 -11
  136. package/dist/chunk-AZXMR25O.js +545 -0
  137. package/dist/{chunk-WPWEBZ37.js → chunk-B7AMNZTC.js} +2 -2
  138. package/dist/{chunk-4CF5KUWH.js → chunk-BPVFZ6Q4.js} +3 -3
  139. package/dist/{chunk-XTQ7R2PA.js → chunk-BV2IET6B.js} +73 -17
  140. package/dist/{chunk-4F5CNI65.js → chunk-C5ISP5FO.js} +2 -2
  141. package/dist/{chunk-NPWNXJ3U.js → chunk-CH7BUBP3.js} +7 -7
  142. package/dist/{chunk-X5Q66EOG.js → chunk-CHIUS5QB.js} +16 -16
  143. package/dist/{chunk-ZG62LIK3.js → chunk-CIPDQRFO.js} +1 -1
  144. package/dist/{chunk-4PYIRIU6.js → chunk-CM7N5MBY.js} +5 -5
  145. package/dist/{chunk-L5YDAFUH.js → chunk-CYCIX7AW.js} +5 -5
  146. package/dist/{chunk-76YRJKKF.js → chunk-D3LXVAIQ.js} +28 -16
  147. package/dist/{chunk-2GNAHBRD.js → chunk-DMUOTCDN.js} +1 -1
  148. package/dist/{chunk-QMUFSRQX.js → chunk-DN3ZR3UE.js} +1 -1
  149. package/dist/{chunk-V3WLC5TJ.js → chunk-DRTJCG6B.js} +1 -1
  150. package/dist/{chunk-275WHBEN.js → chunk-DYVLEMKS.js} +1 -1
  151. package/dist/{chunk-O34F5EP5.js → chunk-DZN7SDY2.js} +1 -1
  152. package/dist/{chunk-ZDIXMHY7.js → chunk-E3ZM32LF.js} +8 -8
  153. package/dist/{chunk-N2HXR5MB.js → chunk-E7C2WNR5.js} +4 -4
  154. package/dist/{chunk-VVGXWVZU.js → chunk-EGOEB42T.js} +3 -3
  155. package/dist/{chunk-QV5CQLQH.js → chunk-EIOGV75A.js} +2 -2
  156. package/dist/{chunk-ZY4IGUOS.js → chunk-ELCRJGCH.js} +3 -3
  157. package/dist/{chunk-5QCIWWFA.js → chunk-ELEGH4DX.js} +130 -14
  158. package/dist/{chunk-S7CTCPSW.js → chunk-EOTZSAQL.js} +1 -1
  159. package/dist/{chunk-PPLQ4ECD.js → chunk-EUGEFBGV.js} +3 -3
  160. package/dist/{chunk-UFNCL6MS.js → chunk-EYMFVITZ.js} +1 -1
  161. package/dist/{chunk-F6H7GP2O.js → chunk-F4BBMIPG.js} +3 -3
  162. package/dist/{chunk-FNEZ4BWT.js → chunk-FEU6QEEL.js} +1 -1
  163. package/dist/{chunk-JKOC2L6P.js → chunk-FHIFTSPL.js} +1 -1
  164. package/dist/{chunk-4RTKETV3.js → chunk-FMIYFHLE.js} +3 -3
  165. package/dist/{chunk-TK544DEW.js → chunk-FVLNNNH6.js} +3 -3
  166. package/dist/{chunk-AY2U4NZ5.js → chunk-GL47M7NY.js} +85 -17
  167. package/dist/{chunk-DN24VTS5.js → chunk-GSLFH4AI.js} +25 -13
  168. package/dist/{chunk-CHO5SNWR.js → chunk-HA63SH5W.js} +1 -1
  169. package/dist/{chunk-4IK2K3B3.js → chunk-HME6ITKV.js} +1 -1
  170. package/dist/{chunk-H2T6TFJZ.js → chunk-HU3VD4MQ.js} +2 -2
  171. package/dist/{chunk-ZW32RI66.js → chunk-I5XIW2BP.js} +49 -11
  172. package/dist/{chunk-3CL2I3RG.js → chunk-IGJMS7C5.js} +2 -2
  173. package/dist/{chunk-BRPO6GOH.js → chunk-JA3Y5TV6.js} +2 -2
  174. package/dist/{chunk-SFFXAPYK.js → chunk-JDDM6C57.js} +1 -1
  175. package/dist/{chunk-W4EGAQXW.js → chunk-JFJP6ATJ.js} +2 -2
  176. package/dist/{chunk-ENCUOZXX.js → chunk-JFTUAV4J.js} +1 -1
  177. package/dist/{chunk-3UOQH2DJ.js → chunk-JJTPPAZY.js} +2568 -345
  178. package/dist/{chunk-A6QBAUJH.js → chunk-KILR4FBR.js} +4 -4
  179. package/dist/{chunk-CGFGNHSP.js → chunk-KTKIFXIP.js} +1 -1
  180. package/dist/{chunk-NCJBPXGM.js → chunk-KXYKSLW4.js} +108 -24
  181. package/dist/{chunk-3MUARHPO.js → chunk-L3VUW5M4.js} +1 -1
  182. package/dist/{chunk-GZOG2MAX.js → chunk-L5EPGGDP.js} +1 -1
  183. package/dist/{chunk-T7VSKWES.js → chunk-L63V25HS.js} +6 -5
  184. package/dist/{chunk-R4VNGRKU.js → chunk-LFBLQE2P.js} +1 -1
  185. package/dist/{chunk-W5MCOZTW.js → chunk-LFUBEHFW.js} +12 -2
  186. package/dist/{chunk-AIBIEP4R.js → chunk-LKTN22L6.js} +61 -25
  187. package/dist/{chunk-3KFQCFQB.js → chunk-LR5O2XWZ.js} +5 -5
  188. package/dist/{chunk-VUOAPKPI.js → chunk-LSNBTGW4.js} +1 -1
  189. package/dist/{chunk-P5U3GAWU.js → chunk-MB47DRF5.js} +2 -2
  190. package/dist/{chunk-HZESME3B.js → chunk-MC4IM2CC.js} +16 -13
  191. package/dist/{chunk-ZKJ5S23O.js → chunk-MFAOAIUE.js} +12 -9
  192. package/dist/{chunk-62J64CHO.js → chunk-MKM6D7JM.js} +26 -7
  193. package/dist/{chunk-ZIG7VPJV.js → chunk-MMS2HBRT.js} +15 -3
  194. package/dist/{chunk-FHSV4BSW.js → chunk-MOANZQXF.js} +12 -4
  195. package/dist/{chunk-RTZZBWQC.js → chunk-MPZ2AVNS.js} +16 -5
  196. package/dist/{chunk-AZ6KLVDX.js → chunk-MROSARM5.js} +2 -2
  197. package/dist/{chunk-RV2FFCDS.js → chunk-MUAWCFW6.js} +6 -2
  198. package/dist/{chunk-K4ESASPL.js → chunk-MUCNYSJP.js} +1 -1
  199. package/dist/{chunk-5QGKMP6T.js → chunk-NF5FOSLD.js} +1 -1
  200. package/dist/{chunk-CKOJP7JI.js → chunk-NKEFYE4R.js} +2 -2
  201. package/dist/{chunk-3SXHEQ7X.js → chunk-NPXIS2RY.js} +1 -1
  202. package/dist/{chunk-A5USSF66.js → chunk-NVFNADTX.js} +12 -8
  203. package/dist/{chunk-VVUO3RJS.js → chunk-NYLJQ2M2.js} +4 -4
  204. package/dist/{chunk-HIVOLPLD.js → chunk-OAFENIHN.js} +1 -1
  205. package/dist/{chunk-PMZHZQ6K.js → chunk-OBBO6EJR.js} +1 -1
  206. package/dist/{chunk-SS6EMDLL.js → chunk-P2UY34XE.js} +6 -6
  207. package/dist/{chunk-Y4T5IUEP.js → chunk-P3QQ52QK.js} +2 -2
  208. package/dist/{chunk-GGEKMY6G.js → chunk-P3UX5EH4.js} +4 -4
  209. package/dist/{chunk-F7IRZU5G.js → chunk-P4PIZOL2.js} +3 -3
  210. package/dist/{chunk-GEPFKUUR.js → chunk-P4XLIPB7.js} +1 -1
  211. package/dist/{chunk-GPUOUUHA.js → chunk-PCV52RYM.js} +1 -1
  212. package/dist/{chunk-XR3773KZ.js → chunk-PL4CFSQ7.js} +1 -1
  213. package/dist/{chunk-LLZNPOGB.js → chunk-PLII76NJ.js} +58 -0
  214. package/dist/{chunk-FT5PPV2C.js → chunk-PRDDPQLC.js} +5 -5
  215. package/dist/{chunk-BZ546I4Q.js → chunk-PUBA5B4M.js} +24 -0
  216. package/dist/{chunk-2TGJ5XCV.js → chunk-PWC3C5ME.js} +4 -4
  217. package/dist/{chunk-A4YCLD3L.js → chunk-QFAFKEB5.js} +40 -4
  218. package/dist/{chunk-CL4J4757.js → chunk-QH5ZQ5SJ.js} +26 -0
  219. package/dist/{chunk-UJWZYK46.js → chunk-QNZ4562V.js} +1 -1
  220. package/dist/{chunk-IPHLUZ37.js → chunk-QPTSA4PP.js} +2 -2
  221. package/dist/{chunk-O3YJTHWI.js → chunk-R5E7WNAC.js} +3 -3
  222. package/dist/{chunk-V3M4LJRA.js → chunk-RB3J2WYQ.js} +1 -1
  223. package/dist/{chunk-IUCWOI4Y.js → chunk-RDWIKDMY.js} +237 -11
  224. package/dist/{chunk-ENN6DY4T.js → chunk-RVO5O5SR.js} +46 -21
  225. package/dist/{chunk-LY4AXCYJ.js → chunk-RZN2LEAK.js} +6 -6
  226. package/dist/{chunk-2YIB75UQ.js → chunk-S26CV7BE.js} +57 -13
  227. package/dist/{chunk-XC36HYP6.js → chunk-SDYWZRPN.js} +1 -1
  228. package/dist/{chunk-PHBU4LGO.js → chunk-SNHYZYGZ.js} +1 -1
  229. package/dist/{chunk-4KTTBKWQ.js → chunk-T5FEAQES.js} +1 -1
  230. package/dist/{chunk-XU57KFD6.js → chunk-T5SM4RXY.js} +5 -1
  231. package/dist/{chunk-KUV5VBAO.js → chunk-TKAU7IJ2.js} +1 -1
  232. package/dist/{chunk-KBR5LIWD.js → chunk-TKS5GMYA.js} +1 -1
  233. package/dist/{chunk-5DFE2NAF.js → chunk-TNS63ATU.js} +96 -22
  234. package/dist/{chunk-RFPMXR6B.js → chunk-U4GMOT4M.js} +1 -1
  235. package/dist/{chunk-CO5ZVE3D.js → chunk-UOPCVFVR.js} +17 -17
  236. package/dist/{chunk-22LNFCDF.js → chunk-UX2EO653.js} +1 -1
  237. package/dist/{chunk-LGC6TBA3.js → chunk-UXN4BICC.js} +2 -2
  238. package/dist/{chunk-7J5X4AK7.js → chunk-VF2KRROX.js} +1 -1
  239. package/dist/{chunk-7THUQU44.js → chunk-VF3BZOZK.js} +5 -2
  240. package/dist/{chunk-M2B35MUK.js → chunk-VHHX4UCP.js} +1 -1
  241. package/dist/{chunk-AZBJXATK.js → chunk-VJEJ7JNB.js} +1 -1
  242. package/dist/{chunk-4TRVALTR.js → chunk-VLBHZ6TF.js} +2 -2
  243. package/dist/{chunk-7BMSBACY.js → chunk-VOVFUKEB.js} +5 -5
  244. package/dist/{chunk-MDPGZS6C.js → chunk-VROK4X2L.js} +1 -1
  245. package/dist/{chunk-J6ABJDZ4.js → chunk-W3KPQE7H.js} +4 -4
  246. package/dist/{chunk-3Q7NEDHB.js → chunk-W6BZ4UGA.js} +48 -9
  247. package/dist/{chunk-IZ3IFLL2.js → chunk-XEBKIWI7.js} +14 -14
  248. package/dist/{chunk-UZDF6FLJ.js → chunk-XHU3KOKJ.js} +1 -1
  249. package/dist/{chunk-PA37MXV5.js → chunk-XSUALA32.js} +2 -2
  250. package/dist/{chunk-GR5WJPKF.js → chunk-XUZK23V7.js} +11 -6
  251. package/dist/{chunk-IDB3EZLW.js → chunk-YLB365YX.js} +148 -5
  252. package/dist/{chunk-JDQ7JU3A.js → chunk-YLFCH3VA.js} +24 -16
  253. package/dist/{chunk-ZJJL2Z23.js → chunk-YRQ26MNP.js} +4 -4
  254. package/dist/chunk-YRUZK2QA.js +35 -0
  255. package/dist/{chunk-7HLJ4BSF.js → chunk-ZAEUEDTN.js} +2 -2
  256. package/dist/{chunk-NY74W3S4.js → chunk-ZBPZDADW.js} +313 -43
  257. package/dist/{chunk-ZLPS3GR7.js → chunk-ZJQ56DZZ.js} +42 -1
  258. package/dist/{chunk-VMZZTFXT.js → chunk-ZOTTYCP5.js} +4 -4
  259. package/dist/{chunk-MP4ST7RO.js → chunk-ZPP63JSQ.js} +51 -11
  260. package/dist/{chunk-N4J5WHO2.js → chunk-ZT4LFTUJ.js} +1 -1
  261. package/dist/{cleanup-graph-garbage-GE2DYOTB.js → cleanup-graph-garbage-VQAJ2RBT.js} +11 -11
  262. package/dist/{cloud-sync-command-T6KF3ARK.js → cloud-sync-command-J7NEFUY7.js} +2 -2
  263. package/dist/{cloud-sync-db-init-RSHCCY74.js → cloud-sync-db-init-KWEMNMGA.js} +1 -1
  264. package/dist/{cloud-sync-shutdown-6IVCSLM5.js → cloud-sync-shutdown-P63AUTUI.js} +5 -5
  265. package/dist/{co-activation-AF7RCJPX.js → co-activation-7IHRPBZN.js} +5 -5
  266. package/dist/{co-occurrence-DMOOGBVV.js → co-occurrence-R5AG4OAU.js} +9 -9
  267. package/dist/{code-context-index-LIDOFKOR.js → code-context-index-WFLLZBVB.js} +10 -9
  268. package/dist/{code-context-watcher-4F7K2N3U.js → code-context-watcher-3QAPHO7N.js} +10 -9
  269. package/dist/{codex-consolidation-SH4UKFBQ.js → codex-consolidation-ONZ2AQFX.js} +2 -2
  270. package/dist/{consent-passphrase-WV7MZPMO.js → consent-passphrase-5ZBDJ5G7.js} +2 -2
  271. package/dist/{content-extractor-DJM5EUDA.js → content-extractor-ZLXC6GNR.js} +2 -2
  272. package/dist/{conversation-entity-extractor-4UG7BKWL.js → conversation-entity-extractor-7FRKLLBD.js} +4 -4
  273. package/dist/{conversation-wiki-populator-OS4C6W54.js → conversation-wiki-populator-YAOVCUGO.js} +1 -1
  274. package/dist/{crdt-sync-VL4KXZB7.js → crdt-sync-IFRZOEIS.js} +4 -4
  275. package/dist/{crm-webhook-IDBJ7X5Y.js → crm-webhook-L2S63ASV.js} +2 -2
  276. package/dist/{cto-delegation-gate-4FLSHSLO.js → cto-delegation-gate-3WU7OHX7.js} +29 -28
  277. package/dist/{daemon-auth-PNKHERLV.js → daemon-auth-OWLFYEFR.js} +3 -3
  278. package/dist/{daemon-orchestration-HFCB6OK4.js → daemon-orchestration-3VQYKLOR.js} +33 -32
  279. package/dist/{daemon-ready-BN6EZLTQ.js → daemon-ready-VZ6ZHA2C.js} +1 -1
  280. package/dist/{db-integrity-events-GYGANKZV.js → db-integrity-events-7NKWS5MT.js} +3 -3
  281. package/dist/{db-restore-events-G6NOQOVE.js → db-restore-events-XYL6CGPC.js} +2 -2
  282. package/dist/{destructive-data-guard-HHWUBIGS.js → destructive-data-guard-JDUJ2ULM.js} +58 -2
  283. package/dist/{dispatch-ack-X4DXUSKP.js → dispatch-ack-UYEAKON5.js} +2 -1
  284. package/dist/{doc-graph-extractor-E36PQUCS.js → doc-graph-extractor-YIR5E7OF.js} +9 -9
  285. package/dist/{documents-SCKKHDR7.js → documents-QEHPTYIY.js} +19 -18
  286. package/dist/{dreaming-Q26JBH56.js → dreaming-LNFE7DTN.js} +34 -33
  287. package/dist/{employee-boot-brief-XU6EI2EO.js → employee-boot-brief-ZTXDYNWM.js} +39 -38
  288. package/dist/{entity-boost-VNQLLR3Q.js → entity-boost-R5N6JWXD.js} +1 -1
  289. package/dist/{exe-drift-YZ6OIUAY.js → exe-drift-WYSJVZFO.js} +6 -6
  290. package/dist/{exe-export-HHRQMLSS.js → exe-export-GOLNAEAV.js} +20 -19
  291. package/dist/{exe-import-5XR4NQAB.js → exe-import-U4BSI6OH.js} +20 -19
  292. package/dist/{exe-key-5XOFVP3I.js → exe-key-V42G3NGO.js} +152 -130
  293. package/dist/{exe-org-TPAX4AAK.js → exe-org-U4GLQ6OP.js} +27 -27
  294. package/dist/{exe-snapshot-GIRP3XCJ.js → exe-snapshot-U7ONBYNY.js} +38 -37
  295. package/dist/{fast-db-init-MGY6VCLG.js → fast-db-init-W3NGKAEU.js} +1 -1
  296. package/dist/{founder-context-WD72OL2P.js → founder-context-ZSIBRVDM.js} +4 -4
  297. package/dist/{founder-monitor-envelope-XGYMHT4W.js → founder-monitor-envelope-L3IWZLFY.js} +7 -7
  298. package/dist/{fts-integrity-PLAL6NMG.js → fts-integrity-PHCKKOBC.js} +3 -3
  299. package/dist/gateway/index.js +23 -22
  300. package/dist/{gateway-client-VO3BRLV5.js → gateway-client-DJFCVIPT.js} +1 -1
  301. package/dist/{git-staleness-KGZABPP3.js → git-staleness-OF24QXFZ.js} +5 -5
  302. package/dist/{global-procedures-KOU6A5E5.js → global-procedures-WSIOWO43.js} +6 -6
  303. package/dist/{graph-auto-extract-OZNRDAHE.js → graph-auto-extract-IEVVN3L3.js} +9 -9
  304. package/dist/{graph-query-36K6VXFF.js → graph-query-JDZWAVCU.js} +1 -1
  305. package/dist/{graph-rag-TZLH3CTQ.js → graph-rag-BKAD2XQA.js} +4 -4
  306. package/dist/{hook-integrity-BWFFISJV.js → hook-integrity-TPWDGX2M.js} +3 -1
  307. package/dist/{hook-prefetch-MFUJRAIM.js → hook-prefetch-FD6VGJJA.js} +29 -28
  308. package/dist/hooks/bug-report-worker.js +34 -33
  309. package/dist/hooks/codex-stop-task-finalizer.js +36 -35
  310. package/dist/hooks/commit-complete.js +40 -36
  311. package/dist/hooks/error-recall.js +15 -15
  312. package/dist/hooks/exe-heartbeat-hook.js +8 -8
  313. package/dist/hooks/ingest-worker.js +21 -20
  314. package/dist/hooks/ingest.js +23 -23
  315. package/dist/hooks/instructions-loaded.js +10 -10
  316. package/dist/hooks/manifest.json +20 -20
  317. package/dist/hooks/notification.js +9 -9
  318. package/dist/hooks/post-compact.js +8 -8
  319. package/dist/hooks/post-tool-combined.js +15 -15
  320. package/dist/hooks/pre-compact.js +33 -32
  321. package/dist/hooks/pre-tool-use.js +2 -2
  322. package/dist/hooks/prompt-submit.js +52 -51
  323. package/dist/hooks/session-end.js +38 -37
  324. package/dist/hooks/session-start.js +25 -22
  325. package/dist/hooks/stop.js +40 -39
  326. package/dist/hooks/subagent-stop.js +36 -35
  327. package/dist/hooks/summary-worker.js +41 -40
  328. package/dist/index.js +43 -42
  329. package/dist/{inrun-inbox-DRKVDPLY.js → inrun-inbox-RGNFFGMU.js} +5 -0
  330. package/dist/{installer-RM4ASY7U.js → installer-NMOBSEZ2.js} +11 -11
  331. package/dist/{installer-IESPHXVH.js → installer-OTI5SA43.js} +11 -11
  332. package/dist/{installer-SQZRVD36.js → installer-SRJGE4GU.js} +11 -11
  333. package/dist/{intercom-queue-DGLAC224.js → intercom-queue-4FFXCBHO.js} +28 -27
  334. package/dist/{key-backup-status-LQPINQ3W.js → key-backup-status-6U7D5GOD.js} +2 -2
  335. package/dist/lib/agent-config.js +3 -3
  336. package/dist/lib/cloud-sync.js +28 -27
  337. package/dist/lib/config.js +4 -2
  338. package/dist/lib/consolidation.js +14 -12
  339. package/dist/lib/crypto.js +5 -3
  340. package/dist/lib/database.js +5 -5
  341. package/dist/lib/db-backup.js +11 -3
  342. package/dist/lib/db-daemon-client.js +11 -10
  343. package/dist/lib/db-write-worker.js +4 -4
  344. package/dist/lib/db.js +5 -5
  345. package/dist/lib/delivery-catalog.js +431 -0
  346. package/dist/lib/delivery-schemas.js +62 -0
  347. package/dist/lib/delivery-truth.js +1 -1
  348. package/dist/lib/device-registry.js +3 -3
  349. package/dist/lib/embed-worker.js +2 -2
  350. package/dist/lib/embedder.js +10 -9
  351. package/dist/lib/employee-templates.js +7 -7
  352. package/dist/lib/employees.js +5 -5
  353. package/dist/lib/exe-daemon-client.js +9 -8
  354. package/dist/lib/exe-daemon.js +186 -117
  355. package/dist/lib/hybrid-search.js +12 -12
  356. package/dist/lib/identity.js +5 -5
  357. package/dist/lib/keychain.js +13 -1
  358. package/dist/lib/license.js +8 -4
  359. package/dist/lib/messaging.js +39 -30
  360. package/dist/lib/post-tool-memory.js +9 -9
  361. package/dist/lib/registry-proxy.js +9 -1
  362. package/dist/lib/reminders.js +6 -6
  363. package/dist/lib/schedules.js +11 -11
  364. package/dist/lib/session-registry.js +7 -7
  365. package/dist/lib/skill-learning.js +20 -19
  366. package/dist/lib/status-brief.js +5 -4
  367. package/dist/lib/store.js +10 -10
  368. package/dist/lib/task-router.js +6 -6
  369. package/dist/lib/tasks.js +30 -29
  370. package/dist/lib/tmux-routing.js +28 -27
  371. package/dist/lib/tmux-status.js +3 -1
  372. package/dist/lib/token-spend.js +6 -6
  373. package/dist/lib/ws-client.js +1 -1
  374. package/dist/{license-gate-E6GTRYBA.js → license-gate-R4JWTWM4.js} +5 -5
  375. package/dist/{license-recheck-RBAO6Z2H.js → license-recheck-3MBJ4IJX.js} +1 -1
  376. package/dist/{license-sync-ZCZ2LIHK.js → license-sync-BVSG3WMW.js} +4 -4
  377. package/dist/local-secret-inventory-JWNBHZZ4.js +20 -0
  378. package/dist/mailbox-inbox-MTAT4MXX.js +13 -0
  379. package/dist/{mailbox-outbox-DNDDP2HW.js → mailbox-outbox-OY4IU6S4.js} +2 -1
  380. package/dist/mcp/register-tools.js +121 -120
  381. package/dist/mcp/server.js +123 -122
  382. package/dist/mcp/tools/complete-reminder.js +7 -7
  383. package/dist/mcp/tools/create-reminder.js +7 -7
  384. package/dist/mcp/tools/create-task.js +35 -32
  385. package/dist/mcp/tools/deactivate-behavior.js +22 -21
  386. package/dist/mcp/tools/list-reminders.js +7 -7
  387. package/dist/mcp/tools/list-tasks.js +33 -32
  388. package/dist/mcp/tools/send-message.js +32 -31
  389. package/dist/mcp/tools/update-task.js +31 -30
  390. package/dist/{mcp-child-registry-DVHYAHPW.js → mcp-child-registry-TIZERM7O.js} +5 -5
  391. package/dist/{mcp-health-B5EKRCZG.js → mcp-health-4ZHU67LM.js} +9 -3
  392. package/dist/{mcp-http-config-ME67QDOF.js → mcp-http-config-VUMSFWFH.js} +12 -12
  393. package/dist/{mcp-session-identity-DNG4ULAE.js → mcp-session-identity-DZHWEJRV.js} +28 -27
  394. package/dist/{memory-cards-WCISXY62.js → memory-cards-JVXTMSAT.js} +10 -10
  395. package/dist/{memory-graph-extractor-GXIK4QUF.js → memory-graph-extractor-PPBJMYFJ.js} +10 -10
  396. package/dist/{memory-poisoning-defense-25LZ5FJI.js → memory-poisoning-defense-K5Q74XQ4.js} +5 -5
  397. package/dist/{memory-pressure-watchdog-XGXI7WGE.js → memory-pressure-watchdog-YMJH5CSA.js} +29 -28
  398. package/dist/{memory-queue-YF7IDSFY.js → memory-queue-2MA67TAA.js} +3 -3
  399. package/dist/{memory-queue-client-QC2OTMJB.js → memory-queue-client-4G7HVRSX.js} +11 -10
  400. package/dist/{memory-reflection-GFGT44NT.js → memory-reflection-7BZWIHRE.js} +10 -10
  401. package/dist/{monitor-grants-Z2SEFE6E.js → monitor-grants-Q7X3MYQP.js} +6 -6
  402. package/dist/{monitor-identity-AEMHCVHV.js → monitor-identity-ZQB4IXEE.js} +2 -2
  403. package/dist/{notification-ledger-ETQBGRP7.js → notification-ledger-XRAXL5OI.js} +32 -29
  404. package/dist/{notifications-LPRCFJYY.js → notifications-JE3PX55X.js} +28 -27
  405. package/dist/{orchestration-events-T2GXV2NG.js → orchestration-events-JCQ5F5IJ.js} +6 -6
  406. package/dist/{orchestration-phase-T2WD45UA.js → orchestration-phase-QKTGQ2YT.js} +3 -3
  407. package/dist/{orchestrator-HY2IB3NA.js → orchestrator-X65INDTR.js} +30 -29
  408. package/dist/{org-brief-session-UWFCFEEB.js → org-brief-session-3PQ22UIX.js} +19 -18
  409. package/dist/{org-consent-policy-XXMST37J.js → org-consent-policy-VGELJ7K7.js} +7 -6
  410. package/dist/{org-join-72QKM7JR.js → org-join-6TO5ZYUZ.js} +12 -12
  411. package/dist/{org-key-admin-YCIAYP7V.js → org-key-admin-XHYVRRAZ.js} +12 -12
  412. package/dist/{org-key-pin-F7BQPI5P.js → org-key-pin-TTTYGTQL.js} +6 -6
  413. package/dist/{org-membership-JQSU4Z5P.js → org-membership-Y7T2BS57.js} +7 -7
  414. package/dist/{org-partner-config-PVJ45SLC.js → org-partner-config-OP4NEUNF.js} +10 -10
  415. package/dist/{org-partner-runtime-U4CTLWLC.js → org-partner-runtime-YNVUNT2R.js} +20 -19
  416. package/dist/{org-row-visibility-WUX4N3FX.js → org-row-visibility-JBBXNYXD.js} +1 -1
  417. package/dist/{pipeline-router-2RMBCBRM.js → pipeline-router-EIBB7QNG.js} +6 -6
  418. package/dist/{plan-limits-Z47XYEJR.js → plan-limits-MEWXYLEN.js} +8 -8
  419. package/dist/{postinstall-failure-O6TSSNJB.js → postinstall-failure-VETYYWEZ.js} +3 -3
  420. package/dist/{pre-tool-use-impl-JPE6XMRJ.js → pre-tool-use-impl-C6KJY22W.js} +60 -49
  421. package/dist/{project-boot-UFQDAFU5.js → project-boot-VEYFCCSL.js} +2 -2
  422. package/dist/{project-name-V4IREGHO.js → project-name-UYORSNGE.js} +6 -6
  423. package/dist/{projection-worker-HAD6H3VJ.js → projection-worker-WYFDWS57.js} +5 -5
  424. package/dist/{prospective-memory-KIF4JLFF.js → prospective-memory-E6XBQFJA.js} +5 -5
  425. package/dist/{push-notifications-GDKRTYXH.js → push-notifications-M7YU63FY.js} +29 -28
  426. package/dist/{reproject-worktree-memories-SG4BZJ3Z.js → reproject-worktree-memories-B5XMGJSD.js} +28 -27
  427. package/dist/{reranker-G2AZ67JP.js → reranker-SRA4BR7N.js} +3 -3
  428. package/dist/{retrieval-health-GBJRXTBZ.js → retrieval-health-P2JPZUPV.js} +4 -4
  429. package/dist/{review-polling-VUZPAAGT.js → review-polling-KQPN7IQE.js} +29 -28
  430. package/dist/runtime/index.js +37 -36
  431. package/dist/{session-events-BI6NIFIR.js → session-events-6LDDKKY3.js} +29 -28
  432. package/dist/{session-kill-telemetry-HPBDOPHT.js → session-kill-telemetry-5DSRGWCL.js} +29 -28
  433. package/dist/{session-mcp-config-WFZAH6R5.js → session-mcp-config-F7RCERUG.js} +3 -3
  434. package/dist/{session-scope-UB3HA5E7.js → session-scope-XG5R3P3D.js} +28 -27
  435. package/dist/{setup-wizard-6XULOT3L.js → setup-wizard-7QFLZIKT.js} +5 -5
  436. package/dist/{shard-manager-DYEJ6ETD.js → shard-manager-HHHHV2KZ.js} +3 -3
  437. package/dist/{skill-refinement-MKBQIWZ6.js → skill-refinement-I5RMAHSC.js} +6 -6
  438. package/dist/{stack-generate-manifest-7ODQ6W2O.js → stack-generate-manifest-AKMZ3AUX.js} +246 -13
  439. package/dist/stack-init-5VKL5PL5.js +136 -0
  440. package/dist/{stack-promote-3UKJBJSP.js → stack-promote-34CE2HHF.js} +7 -6
  441. package/dist/{stack-release-5CVXMJM5.js → stack-release-5PGWV5D4.js} +123 -12
  442. package/dist/{stack-update-Z53KG2P5.js → stack-update-ZQQ5YYPJ.js} +20 -5
  443. package/dist/{steward-gate-OKUYYIX6.js → steward-gate-AQJ6KT2C.js} +6 -6
  444. package/dist/{subagent-brief-injection-T2CVQLAS.js → subagent-brief-injection-3GU7YAWY.js} +50 -42
  445. package/dist/{subagent-spawn-ledger-E6U3OY6Z.js → subagent-spawn-ledger-52I66CLW.js} +3 -3
  446. package/dist/{supervisor-handoff-SGLEPOCY.js → supervisor-handoff-BWJW6CKZ.js} +4 -4
  447. package/dist/{support-inbox-WJIDCKJC.js → support-inbox-NY5TB3FN.js} +12 -12
  448. package/dist/{support-outbox-G2NG2U5K.js → support-outbox-KNI3FR3G.js} +3 -2
  449. package/dist/{task-enforcement-JL5ADPS6.js → task-enforcement-CAA6D2MH.js} +29 -28
  450. package/dist/{task-request-inbox-54BRRFHZ.js → task-request-inbox-QBZVU66E.js} +9 -6
  451. package/dist/{task-scope-OBPZBID5.js → task-scope-NHXB4ZRN.js} +32 -27
  452. package/dist/{tasks-crud-YBCPT7TY.js → tasks-crud-JHSWL5NM.js} +28 -27
  453. package/dist/{tasks-notify-CEEQSDJF.js → tasks-notify-7PBE4U7T.js} +29 -28
  454. package/dist/{tasks-review-JIEI656P.js → tasks-review-PPPVEE62.js} +28 -27
  455. package/dist/{telemetry-upload-ZZSEZR2U.js → telemetry-upload-YU2VRNHX.js} +10 -10
  456. package/dist/{token-budget-AUFMEMQ2.js → token-budget-QCMWKG3K.js} +6 -6
  457. package/dist/{tool-capability-index-6HLZU437.js → tool-capability-index-7AWQAJRP.js} +1 -1
  458. package/dist/{tool-gates-VXITVRFQ.js → tool-gates-5Q3RSQEG.js} +1 -1
  459. package/dist/{tool-gates-JWVSAYTW.js → tool-gates-QD26D2NE.js} +1 -1
  460. package/dist/{tool-telemetry-RHSEK2TO.js → tool-telemetry-LTOIC64I.js} +1 -1
  461. package/dist/tui/App.js +43 -42
  462. package/dist/{tui-data-PBZNN5YB.js → tui-data-NDBXD6U7.js} +32 -31
  463. package/dist/{update-support-V3ZCJR6L.js → update-support-BMJM4NG7.js} +27 -26
  464. package/dist/{whatsapp-NAM2CRVQ.js → whatsapp-QQLDAHUX.js} +2 -2
  465. package/dist/{wiki-acl-NUBAPLCD.js → wiki-acl-W6WDCVCP.js} +1 -1
  466. package/dist/{work-claims-Q2NU6JON.js → work-claims-6DM32MGO.js} +6 -6
  467. package/dist/{work-state-heartbeat-HAQRV3RK.js → work-state-heartbeat-HG7D4AWJ.js} +1 -1
  468. package/dist/{worker-gate-NUUSQMBT.js → worker-gate-FTMW7GBB.js} +3 -3
  469. package/dist/{workflow-engine-GEWPU5YR.js → workflow-engine-ZWC6CCXE.js} +2 -2
  470. package/dist/{worktree-C7LFMRKW.js → worktree-EMQCPGFE.js} +7 -7
  471. package/dist/{worktree-ownership-guard-4LKMW6PW.js → worktree-ownership-guard-O6JQF2CL.js} +2 -2
  472. package/dist/{worktree-sweep-SYF62ANH.js → worktree-sweep-XVUJZBXV.js} +8 -8
  473. package/package.json +23 -7
  474. package/release-notes.json +39 -12
  475. package/stack.release.json +4 -4
  476. package/dist/mailbox-inbox-XE72D3AX.js +0 -10
  477. /package/dist/{chunk-QIEYJ4KZ.js → chunk-2KY7WZZF.js} +0 -0
  478. /package/dist/{chunk-T3667X2B.js → chunk-2Q2CD6CD.js} +0 -0
  479. /package/dist/{chunk-JZJZYKMW.js → chunk-AJK2PVQW.js} +0 -0
  480. /package/dist/{chunk-ZEGEFBZV.js → chunk-AWWDKF22.js} +0 -0
  481. /package/dist/{chunk-QNTKRGJ6.js → chunk-GIRD7O5X.js} +0 -0
  482. /package/dist/{chunk-FWA4MYTA.js → chunk-JRIH6I7D.js} +0 -0
  483. /package/dist/{chunk-C7H2D7LX.js → chunk-M4XY4JRK.js} +0 -0
  484. /package/dist/{chunk-Q3DN5J6F.js → chunk-P2VVMGMI.js} +0 -0
  485. /package/dist/{chunk-BRAIWGMF.js → chunk-Q46NYJ77.js} +0 -0
  486. /package/dist/{chunk-3LQ2N4H7.js → chunk-U2D6PJ5T.js} +0 -0
  487. /package/dist/{chunk-3O6OGZL3.js → chunk-XDVOGDBC.js} +0 -0
  488. /package/dist/{core-memory-UNCAPGD4.js → core-memory-O6D5UC3T.js} +0 -0
  489. /package/dist/{hook-tamper-log-Z4PWC7N4.js → hook-tamper-log-ARGWCXKJ.js} +0 -0
  490. /package/dist/{memory-isolation-ALPJWLR5.js → memory-isolation-EBFFC6HF.js} +0 -0
  491. /package/dist/{oauth-server-AC2KB7NB.js → oauth-server-ZKBUHDFI.js} +0 -0
  492. /package/dist/{webhook-pipe-W2FVXY7M.js → webhook-pipe-PXH5MBRM.js} +0 -0
  493. /package/dist/{wiki-client-W65IOSWF.js → wiki-client-DD2NVWK2.js} +0 -0
@@ -13,9 +13,12 @@ import {
13
13
  checkImageVersionLabels,
14
14
  isFirstPartyImage
15
15
  } from "./chunk-L25OAFOU.js";
16
+ import {
17
+ declaredArtifactsFromManifest
18
+ } from "./chunk-LFUBEHFW.js";
16
19
  import {
17
20
  loadLicense
18
- } from "./chunk-5DFE2NAF.js";
21
+ } from "./chunk-TNS63ATU.js";
19
22
 
20
23
  // src/lib/stack-update.ts
21
24
  import { execFileSync, spawnSync } from "child_process";
@@ -26,6 +29,97 @@ import https from "https";
26
29
  import net from "net";
27
30
  import path from "path";
28
31
  import { fileURLToPath } from "url";
32
+ import { parseDocument as parseYamlDocument } from "yaml";
33
+
34
+ // src/lib/service-env-contract.ts
35
+ import { parse as parseYaml } from "yaml";
36
+ var SERVICE_ENV_CONTRACT = [
37
+ {
38
+ service: "exe-gateway",
39
+ keys: ["GOTRUE_JWT_SECRET"],
40
+ consequence: "gotrue-auth.ts getSymmetricKey() refuses every HS256 GoTrue token, so all SSO-authenticated requests (including /query tenant auth and /pair-login) are rejected with 401 while the service still reports healthy"
41
+ },
42
+ {
43
+ service: "exe-crm",
44
+ keys: ["GOTRUE_JWT_SECRET"],
45
+ consequence: "getGoTrueSymmetricVerificationKey cannot verify SSO tokens, so GoTrue logins are rejected"
46
+ },
47
+ {
48
+ service: "exe-wiki",
49
+ keys: ["GOTRUE_JWT_SECRET"],
50
+ consequence: "getGoTrueJwtSecret cannot verify SSO tokens, so GoTrue logins are rejected"
51
+ }
52
+ ];
53
+ function parseComposeServiceEnvKeys(composeYaml) {
54
+ const byService = /* @__PURE__ */ new Map();
55
+ let doc;
56
+ try {
57
+ doc = parseYaml(composeYaml, { merge: true });
58
+ } catch {
59
+ return byService;
60
+ }
61
+ const services = doc?.services;
62
+ if (!services || typeof services !== "object") return byService;
63
+ for (const [name, rawDef] of Object.entries(services)) {
64
+ const keys = /* @__PURE__ */ new Set();
65
+ const env = rawDef?.environment;
66
+ if (Array.isArray(env)) {
67
+ for (const entry of env) {
68
+ if (typeof entry !== "string") continue;
69
+ const eq = entry.indexOf("=");
70
+ const key = (eq === -1 ? entry : entry.slice(0, eq)).trim();
71
+ if (key) keys.add(key);
72
+ }
73
+ } else if (env && typeof env === "object") {
74
+ for (const key of Object.keys(env)) keys.add(key);
75
+ }
76
+ byService.set(name, keys);
77
+ }
78
+ return byService;
79
+ }
80
+ function collectServiceEnvGaps(composeYaml, contract = SERVICE_ENV_CONTRACT) {
81
+ const byService = parseComposeServiceEnvKeys(composeYaml);
82
+ const gaps = [];
83
+ for (const requirement of contract) {
84
+ const declared = byService.get(requirement.service);
85
+ if (!declared) continue;
86
+ const missingKeys = requirement.keys.filter((key) => !declared.has(key));
87
+ if (missingKeys.length > 0) {
88
+ gaps.push({ service: requirement.service, missingKeys: [...missingKeys].sort(), consequence: requirement.consequence });
89
+ }
90
+ }
91
+ return gaps.sort((a, b) => a.service.localeCompare(b.service));
92
+ }
93
+ function describeGaps(gaps) {
94
+ return gaps.map((gap) => ` - ${gap.service}: ${gap.missingKeys.join(", ")}
95
+ without it, ${gap.consequence}`).join("\n");
96
+ }
97
+ function assertServiceEnvContract(composeYaml, source) {
98
+ const gaps = collectServiceEnvGaps(composeYaml);
99
+ if (gaps.length === 0) return;
100
+ throw new Error(
101
+ `Stack update aborted before any changes: ${source} does not hand ${gaps.length} service(s) an environment key they cannot work without.
102
+ ${describeGaps(gaps)}
103
+ Compose bans env_file: for these services, so a key present in .env but absent from the service's own environment: block never reaches the container. Add the key to that block.`
104
+ );
105
+ }
106
+ function reportDeployedServiceEnvGaps(deployedComposeYaml, composeFile, willRefreshTemplate, write = (line) => process.stderr.write(line)) {
107
+ const gaps = collectServiceEnvGaps(deployedComposeYaml);
108
+ if (gaps.length === 0) return gaps;
109
+ const remedy = willRefreshTemplate ? "This update refreshes the compose template, which is expected to restore the key(s); re-check after it completes." : `This update does NOT refresh ${composeFile}, so the gap will PERSIST. Update the deployed compose template.`;
110
+ write(
111
+ `
112
+ [stack-update] WARNING (bug 7e811acf): the DEPLOYED compose at ${composeFile} does not hand ${gaps.length} running service(s) an environment key they cannot work without:
113
+ ${describeGaps(gaps)}
114
+ These services do not crash without it \u2014 they return clean 401s and keep reporting healthy, which is why this can go unnoticed indefinitely.
115
+ ${remedy}
116
+
117
+ `
118
+ );
119
+ return gaps;
120
+ }
121
+
122
+ // src/lib/stack-update.ts
29
123
  var SLOW_SERVICE_HEALTH_DEFAULTS = {
30
124
  // Frappe `bench migrate` on every boot can take well over the 180s default.
31
125
  "exe-erp": 900
@@ -184,61 +278,127 @@ function isCloudflaredTunnelMisconfigured(composeFile, envFile) {
184
278
  return true;
185
279
  }
186
280
  var INGRESS_DEFAULT_PORTS = { http: 80, https: 443 };
187
- function stripYamlScalar(raw) {
188
- let v = raw.trim();
189
- v = v.replace(/\s+#.*$/, "").trim();
190
- if (v.startsWith('"') && v.endsWith('"') || v.startsWith("'") && v.endsWith("'")) {
191
- v = v.slice(1, -1);
192
- }
193
- return v.trim();
281
+ function findUnauditableIngressSyntax(configYml) {
282
+ return walkCloudflaredIngress(configYml).unmodelled;
194
283
  }
195
284
  function parseCloudflaredIngressTargets(configYml) {
196
- const lines = configYml.split(/\r?\n/);
285
+ return walkCloudflaredIngress(configYml).targets;
286
+ }
287
+ function ruleLabel(hostname, service) {
288
+ return `${hostname ? `hostname: ${hostname}` : "(no hostname)"} -> service: ${service.slice(0, 60)}`;
289
+ }
290
+ function walkCloudflaredIngress(configYml) {
197
291
  const targets = [];
198
- let inIngress = false;
199
- let ingressIndent = -1;
200
- let currentHostname;
201
- const flushService = (serviceRaw) => {
202
- const service = stripYamlScalar(serviceRaw);
203
- const m = /^([a-z][a-z0-9+.\-]*):\/\/(?:\[([^\]]+)\]|([^/:\s]+))(?::(\d+))?/i.exec(service);
204
- if (!m) return;
292
+ const rules = [];
293
+ const unmodelled = [];
294
+ const emitTarget = (service, hostname) => {
295
+ const m = /^([a-z][a-z0-9+.\-]*):\/\/(?:\[([^\]]+)\]|([^/:\s]+))(?::(\d+))?/i.exec(service.trim());
296
+ if (!m) {
297
+ rules.push({ hostname, service });
298
+ return;
299
+ }
205
300
  const scheme = (m[1] ?? "").toLowerCase();
206
301
  const host = m[2] ?? m[3] ?? "";
207
302
  const port = m[4] ? Number(m[4]) : INGRESS_DEFAULT_PORTS[scheme];
208
- if (!host) return;
303
+ if (!host) {
304
+ rules.push({ hostname, service });
305
+ return;
306
+ }
307
+ rules.push({ hostname, service, host });
209
308
  if (port === void 0 || !Number.isFinite(port) || port <= 0 || port > 65535) return;
210
- targets.push({ hostname: currentHostname, service, host, port });
309
+ targets.push({ hostname, service, host, port });
211
310
  };
212
- for (const raw of lines) {
213
- if (raw.trim() === "" || raw.trim().startsWith("#")) continue;
214
- const indent = raw.length - raw.replace(/^\s*/, "").length;
215
- if (!inIngress) {
216
- if (/^ingress\s*:\s*$/.test(raw.trim())) {
217
- inIngress = true;
218
- ingressIndent = indent;
311
+ let root;
312
+ try {
313
+ const doc = parseYamlDocument(configYml, { merge: true, uniqueKeys: true });
314
+ if (doc.errors.length > 0) {
315
+ unmodelled.push(`config.yml does not parse as YAML: ${doc.errors[0]?.message ?? "unknown error"}`);
316
+ return { targets, rules, unmodelled };
317
+ }
318
+ root = doc.toJS({ maxAliasCount: 100 });
319
+ } catch (err) {
320
+ unmodelled.push(`config.yml could not be read as YAML: ${err instanceof Error ? err.message : String(err)}`);
321
+ return { targets, rules, unmodelled };
322
+ }
323
+ if (root === null || root === void 0) return { targets, rules, unmodelled };
324
+ if (typeof root !== "object" || Array.isArray(root)) {
325
+ unmodelled.push("top level of config.yml is not a mapping, so its `ingress:` cannot be located");
326
+ return { targets, rules, unmodelled };
327
+ }
328
+ const ingress = root.ingress;
329
+ if (ingress === void 0 || ingress === null) return { targets, rules, unmodelled };
330
+ if (!Array.isArray(ingress)) {
331
+ unmodelled.push("`ingress:` is not a sequence of rules");
332
+ return { targets, rules, unmodelled };
333
+ }
334
+ for (const rule of ingress) {
335
+ if (rule === null || typeof rule !== "object" || Array.isArray(rule)) {
336
+ unmodelled.push(`ingress rule is not a mapping: ${JSON.stringify(rule).slice(0, 120)}`);
337
+ continue;
338
+ }
339
+ const entry = rule;
340
+ const rawHostname = entry.hostname;
341
+ const rawService = entry.service;
342
+ let hostname;
343
+ if (rawHostname !== void 0 && rawHostname !== null) {
344
+ if (typeof rawHostname !== "string") {
345
+ unmodelled.push(`ingress rule \`hostname:\` is not a string: ${JSON.stringify(rawHostname).slice(0, 120)}`);
346
+ continue;
347
+ }
348
+ const trimmedHostname = rawHostname.trim();
349
+ hostname = trimmedHostname === "" ? void 0 : trimmedHostname;
350
+ }
351
+ if (rawService === void 0 || rawService === null) {
352
+ if (hostname !== void 0) {
353
+ unmodelled.push(`ingress rule for ${hostname} has no \`service:\``);
219
354
  }
220
355
  continue;
221
356
  }
222
- if (indent <= ingressIndent && !raw.trim().startsWith("-")) {
223
- inIngress = false;
357
+ if (typeof rawService !== "string") {
358
+ unmodelled.push(`ingress rule \`service:\` is not a string: ${JSON.stringify(rawService).slice(0, 120)}`);
224
359
  continue;
225
360
  }
226
- const t = raw.trim();
227
- if (t.startsWith("-")) {
228
- currentHostname = void 0;
229
- const item = t.replace(/^-\s*/, "");
230
- const hm = /^hostname\s*:\s*(.+)$/i.exec(item);
231
- const sm = /^service\s*:\s*(.+)$/i.exec(item);
232
- if (hm) currentHostname = stripYamlScalar(hm[1] ?? "");
233
- else if (sm) flushService(sm[1] ?? "");
234
- } else {
235
- const hm = /^hostname\s*:\s*(.+)$/i.exec(t);
236
- const sm = /^service\s*:\s*(.+)$/i.exec(t);
237
- if (hm) currentHostname = stripYamlScalar(hm[1] ?? "");
238
- else if (sm) flushService(sm[1] ?? "");
361
+ const svc = rawService.trim();
362
+ const builtIn = /^(?:http_status:\d+|hello_world)$/i.test(svc);
363
+ const networkUrl = /^[a-z][a-z0-9+.\-]*:\/\//i.test(svc);
364
+ if (entry.path !== void 0 && entry.path !== null && !builtIn) {
365
+ unmodelled.push(
366
+ `rule ${ruleLabel(hostname, svc)}: has a \`path:\` (${JSON.stringify(entry.path).slice(0, 40)}) AND serves an application, so it covers only part of that hostname and some later rule covers the rest \u2014 which is how a path-scoped edge route hid an unrestricted direct route below it. A \`path:\` is fine on a DENY rule (\`service: http_status:404\`); on a serving rule, drop the path.`
367
+ );
368
+ continue;
239
369
  }
370
+ if (hostname !== void 0 && hostname.includes("*")) {
371
+ unmodelled.push(
372
+ `rule ${ruleLabel(hostname, svc)}: the hostname is a WILDCARD, so it serves product hostnames it does not name \u2014 including the SSO-gated ones \u2014 and which rule wins depends on ordering this gate does not resolve. Write one rule per concrete hostname.`
373
+ );
374
+ continue;
375
+ }
376
+ if (hostname === void 0) {
377
+ if (!builtIn) {
378
+ unmodelled.push(
379
+ `rule ${ruleLabel(hostname, svc)}: a CATCH-ALL (no hostname) that serves an application. It serves every product hostname no earlier rule claims, including the SSO-gated ones, so it can route a product around the edge without naming it. Give it a hostname, or make the catch-all a terminator (\`service: http_status:404\`).`
380
+ );
381
+ continue;
382
+ }
383
+ rules.push({ hostname, service: svc });
384
+ continue;
385
+ }
386
+ if (!builtIn && !networkUrl) {
387
+ unmodelled.push(
388
+ `rule ${ruleLabel(hostname, svc)}: the service is not a \`scheme://host\` URL, so this gate cannot resolve what it points at. A unix socket or bastion still serves the application, so it must not be read as serving nothing. Route it through \`http://<container>:<port>\`.`
389
+ );
390
+ continue;
391
+ }
392
+ const authority = svc.slice(svc.indexOf("://") + 3).split("/")[0] ?? "";
393
+ if (!builtIn && !/^(?:\[[0-9A-Fa-f:.]+\]|[A-Za-z0-9._-]+)(?::\d+)?$/.test(authority)) {
394
+ unmodelled.push(
395
+ `rule ${ruleLabel(hostname, svc)}: the service authority ${JSON.stringify(authority.slice(0, 60))} is not a plain \`host\` or \`host:port\`. Userinfo (\`user:pass@host\`), escapes and other URL syntax are read differently by this gate than by cloudflared \u2014 \`http://edge:tok@app:80\` names the EDGE here and routes to the APP there \u2014 so it cannot be audited. Write \`scheme://<container>:<port>\` with no credentials.`
396
+ );
397
+ continue;
398
+ }
399
+ emitTarget(rawService, hostname);
240
400
  }
241
- return targets;
401
+ return { targets, rules, unmodelled };
242
402
  }
243
403
  async function findUnreachableIngressTargets(targets, probe) {
244
404
  const results = await Promise.all(
@@ -246,6 +406,56 @@ async function findUnreachableIngressTargets(targets, probe) {
246
406
  );
247
407
  return results.filter((r) => !r.reachable).map((r) => r.t);
248
408
  }
409
+ var SSO_GATED_HOSTNAME_LABELS = ["crm", "wiki", "erp", "dashboard"];
410
+ var SSO_EDGE_SERVICE_HOST = "exe-sso-edge";
411
+ function findSsoUngatedIngressHostnames(configYml) {
412
+ const { rules } = walkCloudflaredIngress(configYml);
413
+ const offenders = [];
414
+ for (const rule of rules) {
415
+ if (!rule.hostname) continue;
416
+ const label = rule.hostname.split(".")[0]?.toLowerCase() ?? "";
417
+ if (!SSO_GATED_HOSTNAME_LABELS.includes(label)) continue;
418
+ if (rule.host === void 0) continue;
419
+ if (rule.host.toLowerCase() === SSO_EDGE_SERVICE_HOST) continue;
420
+ offenders.push({ hostname: rule.hostname, label, service: rule.service, host: rule.host });
421
+ }
422
+ return offenders;
423
+ }
424
+ function verifySsoGatedIngressRouting(configYml) {
425
+ if (!configYml || configYml.trim() === "") return;
426
+ const unmodelled = findUnauditableIngressSyntax(configYml);
427
+ if (unmodelled.length > 0) {
428
+ throw new Error(
429
+ `[stack-update] cloudflared ingress: this config cannot be audited for SSO-edge routing.
430
+
431
+ ${unmodelled.map((u) => ` - ${u}`).join("\n")}
432
+
433
+ THE SHAPE THIS GATE CAN AUDIT \u2014 one rule per concrete hostname, no \`path:\` on a rule that
434
+ serves an application, and a \`scheme://host\` service:
435
+
436
+ ingress:
437
+ - hostname: erp.example.com
438
+ service: http://exe-sso-edge:80
439
+ - hostname: monitor.example.com # a \`path:\` is fine on a DENY rule
440
+ path: /_/*
441
+ service: http_status:404
442
+ - service: http_status:404 # terminator, serves nothing
443
+
444
+ WHY IT REFUSES RATHER THAN GUESSES (bug 3fce7502): wildcards, path-scoped app routes,
445
+ app-serving catch-alls and socket services all decide which rule serves a product by rules
446
+ this gate does not resolve. Reporting "no offenders" for routing nobody could read is how a
447
+ product ends up served around the SSO edge with its cross-app logout silently dead.`
448
+ );
449
+ }
450
+ const offenders = findSsoUngatedIngressHostnames(configYml);
451
+ if (offenders.length === 0) return;
452
+ const lines = offenders.map((o) => ` - ${o.hostname} -> ${o.service} (should be http://${SSO_EDGE_SERVICE_HOST}:80)`).join("\n");
453
+ throw new Error(
454
+ `[stack-update] cloudflared ingress: SSO-gated hostname(s) bypass the SSO edge:
455
+ ${lines}
456
+ These hostnames must route through exe-sso-edge, which selects the app by Host header. Routing straight at the app container skips the unauthenticated 302 to auth.<domain> AND the cross-app-logout check, so a user who signs out at the apex stays signed in to that app (bug 3fce7502). Point the rule at http://exe-sso-edge:80 and re-deploy.`
457
+ );
458
+ }
249
459
  function resolveTransitiveDeps(selected, depsMap) {
250
460
  const resolved = new Set(selected);
251
461
  const queue = [...selected];
@@ -2139,15 +2349,39 @@ function randomSecret(bytes = 32) {
2139
2349
  function randomHexSecret(bytes = 24) {
2140
2350
  return randomBytes(bytes).toString("hex");
2141
2351
  }
2352
+ var EXTERNAL_INPUT_ENV_KEYS = /* @__PURE__ */ new Set([
2353
+ "API_ROUTER_KEY",
2354
+ "MONITOR_AGENT_KEY",
2355
+ "MONITOR_AGENT_TOKEN",
2356
+ "CLOUDFLARE_TUNNEL_TOKEN",
2357
+ "R2_MEDIA_ACCESS_KEY",
2358
+ "R2_MEDIA_SECRET_KEY",
2359
+ "SSH_PUBLIC_KEY",
2360
+ "SSH_PRIVATE_KEY"
2361
+ ]);
2362
+ function isExternalInputKey(key) {
2363
+ return EXTERNAL_INPUT_ENV_KEYS.has(key) || key.endsWith("_API_KEY");
2364
+ }
2365
+ function deriveDeviceId(domain, rand = () => randomBytes(4).toString("hex")) {
2366
+ const label = domain.trim().toLowerCase().replace(/^https?:\/\//, "").split("/")[0]?.split(".")[0] ?? "";
2367
+ const slug = label.replace(/[^a-z0-9-]/g, "");
2368
+ return slug ? `vps-${slug}` : `vps-${rand()}`;
2369
+ }
2142
2370
  function hydrateEnv(raw, opts) {
2143
2371
  let next = raw;
2144
2372
  const license = opts.licenseKey || process.env.EXE_LICENSE_KEY || loadLicense() || "";
2145
2373
  const domain = opts.domain || process.env.EXE_STACK_DOMAIN || process.env.CUSTOMER_DOMAIN || "";
2374
+ const adminEmail = (opts.adminEmail || process.env.EXE_STACK_ADMIN_EMAIL || "").trim();
2146
2375
  const replacements = {};
2147
2376
  const env = parseEnv(raw);
2377
+ const wikiProvider = (env.get("WIKI_LLM_PROVIDER") ?? "").trim().toLowerCase();
2378
+ const wikiUsesAnthropic = wikiProvider === "anthropic" || wikiProvider === "";
2148
2379
  for (const [key, value] of env.entries()) {
2149
2380
  if (!/CHANGEME/.test(value)) continue;
2150
2381
  if (key === "EXE_LICENSE_KEY" && license) replacements[key] = license;
2382
+ else if ((key === "EXE_CRM_ADMIN_EMAIL" || key === "MONITOR_HUB_ADMIN_EMAIL") && adminEmail) replacements[key] = adminEmail;
2383
+ else if (key === "EXED_DEVICE_ID") replacements[key] = deriveDeviceId(domain);
2384
+ else if (key === "WIKI_ANTHROPIC_API_KEY" && !wikiUsesAnthropic) replacements[key] = "";
2151
2385
  else if (key === "MONITOR_AGENT_TOKEN" || key === "MONITOR_AGENT_KEY") continue;
2152
2386
  else if (key === "CLOUDFLARE_TUNNEL_TOKEN") continue;
2153
2387
  else if (key === "EXE_GATEWAY_WS_RELAY_AUTH_TOKEN") replacements[key] = randomHexSecret(24);
@@ -2155,7 +2389,8 @@ function hydrateEnv(raw, opts) {
2155
2389
  else if (key.endsWith("_TOKEN")) replacements[key] = randomHexSecret(32);
2156
2390
  else if (key.endsWith("_SECRET") || key.endsWith("_SALT")) replacements[key] = randomSecret(32);
2157
2391
  else if (key === "EXE_MONITOR_KEY") replacements[key] = randomSecret(32);
2158
- else if (key.endsWith("_KEY") && key !== "EXE_LICENSE_KEY") continue;
2392
+ else if (isExternalInputKey(key)) continue;
2393
+ else if (key.endsWith("_KEY") && key !== "EXE_LICENSE_KEY") replacements[key] = randomSecret(32);
2159
2394
  }
2160
2395
  if (domain) next = next.replaceAll("CHANGEME_DOMAIN", domain);
2161
2396
  next = patchEnv(next, replacements);
@@ -2574,6 +2809,13 @@ function applyPostgresInitSql(composeArgs, envFile, composeFile, exec) {
2574
2809
  ]);
2575
2810
  console.log("[stack-update] \u2713 Postgres init SQL applied");
2576
2811
  }
2812
+ var LIVE_ARTIFACT_MATCHES_MANIFEST_CHECK = "Live artifact matches signed manifest";
2813
+ function isFatalLiveArtifactFailure(result) {
2814
+ if (result.check !== LIVE_ARTIFACT_MATCHES_MANIFEST_CHECK) return false;
2815
+ if (result.status !== "fail") return false;
2816
+ if (!result.verdicts) return true;
2817
+ return (result.verdicts.disagrees ?? 0) > 0;
2818
+ }
2577
2819
  async function runStackUpdate(options) {
2578
2820
  const exec = options.exec ?? defaultExec;
2579
2821
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
@@ -2768,6 +3010,10 @@ ${lines.join("\n")}`
2768
3010
  allowUnmanifestedServices: options.allowUnmanifestedServices
2769
3011
  });
2770
3012
  }
3013
+ if (!options.dryRun) {
3014
+ assertServiceEnvContract(stagedCompose.raw, `the compose template at ${stagedCompose.templatePath}`);
3015
+ }
3016
+ reportDeployedServiceEnvGaps(composeRaw, options.composeFile, stagedCompose.shouldRefresh);
2771
3017
  const previousVersion = readCurrentStackVersion(lockFile);
2772
3018
  if (options.verifyImages) {
2773
3019
  const endPhase = startPhase("verify images");
@@ -3246,6 +3492,7 @@ Push the missing image(s) to the registry, or re-run with --break-glass <reason>
3246
3492
  defaultIngressReachabilityProbe,
3247
3493
  makeDefaultComposeServiceProbe(composeArgs)
3248
3494
  );
3495
+ verifySsoGatedIngressRouting(cfIngressConfigYml);
3249
3496
  }
3250
3497
  const stackEnv = existsSync(options.envFile) ? parseEnv(readFileSync(options.envFile, "utf8")) : void 0;
3251
3498
  const partialRun = failedManifestServices.size > 0;
@@ -3354,7 +3601,21 @@ Push the missing image(s) to the registry, or re-run with --break-glass <reason>
3354
3601
  if (!options.verifyStack) {
3355
3602
  throw new Error("verifyStack hook not provided");
3356
3603
  }
3357
- const verifyReport = await options.verifyStack({ composeFile: options.composeFile, envFile: options.envFile });
3604
+ let expectedArtifacts;
3605
+ try {
3606
+ expectedArtifacts = declaredArtifactsFromManifest(
3607
+ { latest: plan.targetVersion, stacks: { [plan.targetVersion]: plan.release } },
3608
+ { stackVersion: plan.targetVersion }
3609
+ );
3610
+ } catch {
3611
+ expectedArtifacts = void 0;
3612
+ }
3613
+ const verifyReport = await options.verifyStack({
3614
+ composeFile: options.composeFile,
3615
+ envFile: options.envFile,
3616
+ stackVersion: plan.targetVersion,
3617
+ expectedArtifacts
3618
+ });
3358
3619
  const securityFailures = [];
3359
3620
  for (const r of verifyReport.results) {
3360
3621
  if (r.status === "fail") {
@@ -3362,6 +3623,8 @@ Push the missing image(s) to the registry, or re-run with --break-glass <reason>
3362
3623
  const isTruncatedRun = r.check === "Total timeout";
3363
3624
  if (isTruncatedRun || /security|auth|signup|password|ssl|tls|bind|exposed/i.test(r.check)) {
3364
3625
  securityFailures.push(`${r.check}: ${r.message}`);
3626
+ } else if (isFatalLiveArtifactFailure(r)) {
3627
+ securityFailures.push(`${r.check}: ${r.message}`);
3365
3628
  }
3366
3629
  }
3367
3630
  }
@@ -4121,8 +4384,11 @@ export {
4121
4384
  parseComposeServiceNames,
4122
4385
  isUsableTunnelToken,
4123
4386
  isCloudflaredTunnelMisconfigured,
4387
+ findUnauditableIngressSyntax,
4124
4388
  parseCloudflaredIngressTargets,
4125
4389
  findUnreachableIngressTargets,
4390
+ findSsoUngatedIngressHostnames,
4391
+ verifySsoGatedIngressRouting,
4126
4392
  resolveTransitiveDeps,
4127
4393
  filterServicesBySelection,
4128
4394
  buildDefaultServiceSelection,
@@ -4184,10 +4450,14 @@ export {
4184
4450
  assertImageVersionLabels,
4185
4451
  applyGatewayOverlays,
4186
4452
  backupStackConfig,
4453
+ deriveDeviceId,
4454
+ hydrateEnv,
4187
4455
  pairMonitorAgent,
4188
4456
  bootstrapStackHost,
4189
4457
  assertHostReadyForApply,
4190
4458
  hardenHost,
4459
+ LIVE_ARTIFACT_MATCHES_MANIFEST_CHECK,
4460
+ isFatalLiveArtifactFailure,
4191
4461
  runStackUpdate,
4192
4462
  readCurrentStackVersion,
4193
4463
  listAvailableVersions,
@@ -30,6 +30,16 @@ function updateLoadWindow(samples, nowMs, load1m, wallElapsedMs, keepMs) {
30
30
  blockStartMs
31
31
  };
32
32
  }
33
+ var NOT_SCHEDULED_CPU_FLOOR = 0.02;
34
+ var HOST_SUSPENDED_TICK_CEILING = 0.5;
35
+ function isHostSuspendedWindow(lagMs, severeThresholdMs, selfCpuBusyFraction, hostTickFraction, cpuFloor = NOT_SCHEDULED_CPU_FLOOR, tickCeiling = HOST_SUSPENDED_TICK_CEILING) {
36
+ if (!Number.isFinite(lagMs) || lagMs <= severeThresholdMs) return false;
37
+ if (typeof selfCpuBusyFraction !== "number" || !Number.isFinite(selfCpuBusyFraction)) return false;
38
+ if (typeof hostTickFraction !== "number" || !Number.isFinite(hostTickFraction)) return false;
39
+ const selfLimit = Number.isFinite(cpuFloor) && cpuFloor >= 0 ? cpuFloor : NOT_SCHEDULED_CPU_FLOOR;
40
+ const hostLimit = Number.isFinite(tickCeiling) && tickCeiling >= 0 ? tickCeiling : HOST_SUSPENDED_TICK_CEILING;
41
+ return selfCpuBusyFraction <= selfLimit && hostTickFraction < hostLimit;
42
+ }
33
43
  function decideDaemonSelfHeal(s) {
34
44
  const alive = s.processAlive ?? true;
35
45
  if (!alive) {
@@ -76,6 +86,16 @@ function decideDaemonSelfHeal(s) {
76
86
  selfInflictedSuppressedMsAfter: sumInWindow
77
87
  };
78
88
  }
89
+ if (isHostSuspendedWindow(
90
+ s.lagMs,
91
+ s.severeThresholdMs,
92
+ s.selfCpuBusyFraction,
93
+ s.hostTickFraction,
94
+ s.notScheduledCpuFloor,
95
+ s.hostSuspendedTickCeiling
96
+ )) {
97
+ return { restart: false, reason: "host_suspended_backoff", consecutiveSevereAfter: 0, ...carry };
98
+ }
79
99
  if (s.lagMs > s.singleBlockMs) {
80
100
  return { restart: true, reason: "single_block", consecutiveSevereAfter: 0, ...cleared };
81
101
  }
@@ -134,13 +154,34 @@ function computeBootRetryAfterSeconds(nowMs, readyEtaMs, opts = {}) {
134
154
  const maxS = opts.maxS ?? 60;
135
155
  return Math.min(maxS, Math.max(minS, Math.ceil((readyEtaMs - nowMs) / 1e3)));
136
156
  }
157
+ function totalHostCpuMs(cpus) {
158
+ if (!Array.isArray(cpus) || cpus.length === 0) return void 0;
159
+ let total = 0;
160
+ for (const c of cpus) {
161
+ const t = c?.times;
162
+ if (!t) return void 0;
163
+ total += t.user + t.nice + t.sys + t.idle + t.irq;
164
+ }
165
+ return Number.isFinite(total) ? total : void 0;
166
+ }
167
+ function hostTickFractionFor(previousTotalMs, currentTotalMs, coreCount, wallElapsedMs) {
168
+ if (typeof previousTotalMs !== "number" || !Number.isFinite(previousTotalMs)) return void 0;
169
+ if (typeof currentTotalMs !== "number" || !Number.isFinite(currentTotalMs)) return void 0;
170
+ if (typeof coreCount !== "number" || !Number.isFinite(coreCount) || coreCount <= 0) return void 0;
171
+ if (!Number.isFinite(wallElapsedMs)) return void 0;
172
+ if (wallElapsedMs <= 0) return 1;
173
+ return Math.max(0, currentTotalMs - previousTotalMs) / (coreCount * wallElapsedMs);
174
+ }
137
175
 
138
176
  export {
139
177
  isHostCpuStarved,
140
178
  updateLoadWindow,
179
+ isHostSuspendedWindow,
141
180
  decideDaemonSelfHeal,
142
181
  decideStarvationDrainGuard,
143
182
  decideOrchestrationTickSkip,
144
183
  decideBootBackoff,
145
- computeBootRetryAfterSeconds
184
+ computeBootRetryAfterSeconds,
185
+ totalHostCpuMs,
186
+ hostTickFractionFor
146
187
  };
@@ -9,17 +9,17 @@ import {
9
9
  import {
10
10
  buildClaudeHttpMcpEntry,
11
11
  buildClaudeStdioProxyMcpEntry
12
- } from "./chunk-L5YDAFUH.js";
12
+ } from "./chunk-CYCIX7AW.js";
13
13
  import {
14
14
  ensureAllAgentSymlinks
15
- } from "./chunk-JUKDL5MF.js";
15
+ } from "./chunk-6BJCDWSM.js";
16
16
  import {
17
17
  MCP_LEGACY_KEY,
18
18
  MCP_PRIMARY_KEY
19
19
  } from "./chunk-HYZV25LY.js";
20
20
  import {
21
21
  loadConfigSync
22
- } from "./chunk-ZIG7VPJV.js";
22
+ } from "./chunk-MMS2HBRT.js";
23
23
 
24
24
  // src/adapters/claude/installer.ts
25
25
  import { readFile, writeFile, mkdir, readdir, rm } from "fs/promises";
@@ -942,7 +942,7 @@ async function runInstaller(homeDir) {
942
942
  );
943
943
  }
944
944
  try {
945
- const { generateAgentDefs, summarizeAgentDefResults } = await import("./agent-defs-generator-EIUA3SH5.js");
945
+ const { generateAgentDefs, summarizeAgentDefResults } = await import("./agent-defs-generator-7TFISIJQ.js");
946
946
  const defResults = generateAgentDefs({ homeDir: resolvedHome });
947
947
  process.stderr.write(`Agent definitions: ${summarizeAgentDefResults(defResults)}
948
948
  `);