@askexenow/exe-os 0.9.340 → 0.9.342

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 (417) hide show
  1. package/README.md +159 -196
  2. package/deploy/compose/.env.customer.example +1 -0
  3. package/deploy/compose/.env.example +1 -0
  4. package/deploy/compose/docker-compose.yml +13 -4
  5. package/deploy/compose/generate-env.ts +4 -0
  6. package/dist/{active-agent-EC6M7KTX.js → active-agent-PVGE57FY.js} +5 -5
  7. package/dist/{active-agent-WHIUCHLA.js → active-agent-TNIO6IY3.js} +5 -5
  8. package/dist/{agentic-ontology-RNSXGXW4.js → agentic-ontology-3FXYMHKW.js} +1 -1
  9. package/dist/{backfill-gate-J7UXFNXU.js → backfill-gate-65LSYVE5.js} +3 -3
  10. package/dist/{backfill-metadata-MFY6BHKE.js → backfill-metadata-ZSMZC45J.js} +8 -8
  11. package/dist/{background-jobs-STURKDCS.js → background-jobs-EXR5RVGG.js} +3 -3
  12. package/dist/backup-verify-3Y2FHGZU.js +425 -0
  13. package/dist/{behaviors-HLZUJSMP.js → behaviors-KYRB3NGJ.js} +9 -9
  14. package/dist/bin/age-ontology-load.js +3 -3
  15. package/dist/bin/agentic-ontology-backfill.js +10 -10
  16. package/dist/bin/agentic-reflection-backfill.js +11 -11
  17. package/dist/bin/agentic-semantic-label.js +10 -10
  18. package/dist/bin/backfill-conversations.js +10 -10
  19. package/dist/bin/backfill-responses.js +10 -10
  20. package/dist/bin/backfill-vectors.js +14 -14
  21. package/dist/bin/bulk-sync-postgres.js +19 -19
  22. package/dist/bin/cc-doctor.js +10 -8
  23. package/dist/bin/cleanup-stale-review-tasks.js +26 -24
  24. package/dist/bin/cli.js +111 -25
  25. package/dist/bin/customer-readiness.js +1 -1
  26. package/dist/bin/deferred-daemon-restart.js +97 -90
  27. package/dist/bin/exe-agent-config.js +9 -8
  28. package/dist/bin/exe-agent.js +20 -20
  29. package/dist/bin/exe-assign.js +12 -12
  30. package/dist/bin/exe-boot.js +201 -68
  31. package/dist/bin/exe-call.js +7 -7
  32. package/dist/bin/exe-cloud.js +20 -20
  33. package/dist/bin/exe-config-dump.js +9 -8
  34. package/dist/bin/exe-dispatch.js +26 -24
  35. package/dist/bin/exe-doctor.js +10 -6
  36. package/dist/bin/exe-export-behaviors.js +11 -11
  37. package/dist/bin/exe-forget.js +12 -10
  38. package/dist/bin/exe-gateway.js +15 -10
  39. package/dist/bin/exe-grant.js +5 -5
  40. package/dist/bin/exe-healthcheck.js +14 -8
  41. package/dist/bin/exe-heartbeat.js +29 -28
  42. package/dist/bin/exe-kill.js +31 -29
  43. package/dist/bin/exe-launch-agent.js +129 -68
  44. package/dist/bin/exe-memory-reads.js +257 -0
  45. package/dist/bin/exe-new-employee.js +12 -11
  46. package/dist/bin/exe-pending-messages.js +27 -25
  47. package/dist/bin/exe-pending-notifications.js +26 -24
  48. package/dist/bin/exe-pending-reviews.js +26 -24
  49. package/dist/bin/exe-rename.js +7 -7
  50. package/dist/bin/exe-review.js +30 -28
  51. package/dist/bin/exe-search.js +11 -9
  52. package/dist/bin/exe-session-cleanup.js +116 -86
  53. package/dist/bin/exe-settings.js +24 -23
  54. package/dist/bin/exe-start-codex.js +163 -41
  55. package/dist/bin/exe-start-opencode.js +15 -15
  56. package/dist/bin/exe-status.js +27 -25
  57. package/dist/bin/exe-support.js +5 -5
  58. package/dist/bin/exe-team.js +5 -5
  59. package/dist/bin/exe-timers.js +32 -213
  60. package/dist/bin/exe-watchdog.js +6 -5
  61. package/dist/bin/git-sweep.js +27 -25
  62. package/dist/bin/graph-backfill.js +9 -9
  63. package/dist/bin/graph-export.js +9 -9
  64. package/dist/bin/import-history.js +11 -11
  65. package/dist/bin/install.js +102 -95
  66. package/dist/bin/intercom-check.js +4 -4
  67. package/dist/bin/mcp-sessions.js +2 -2
  68. package/dist/bin/orchestration-metrics.js +6 -6
  69. package/dist/bin/postgres-agentic-reflection-backfill.js +5 -5
  70. package/dist/bin/postgres-agentic-semantic-backfill.js +7 -7
  71. package/dist/bin/pre-publish.js +5 -3
  72. package/dist/bin/reconcile-backlog.js +484 -0
  73. package/dist/bin/registry-proxy.js +1 -1
  74. package/dist/bin/scan-tasks.js +26 -24
  75. package/dist/bin/setup.js +6 -5
  76. package/dist/bin/shard-migrate.js +9 -9
  77. package/dist/bin/stack-update.js +15 -9
  78. package/dist/bin/update.js +1 -1
  79. package/dist/bin/vps-health-gate.js +1 -1
  80. package/dist/boot-generation-BL2ISK4U.js +22 -0
  81. package/dist/boot-review-sections-DBMQJT5N.js +107 -0
  82. package/dist/branch-hygiene-TZWK6QCF.js +224 -0
  83. package/dist/{branding-JTEOF4ZV.js → branding-DVXBGVDH.js} +3 -3
  84. package/dist/{browser-session-store-CXQMOSEC.js → browser-session-store-B2NR3LIX.js} +2 -1
  85. package/dist/{capability-cards-YOKVMMOL.js → capability-cards-DN5UIKVN.js} +4 -4
  86. package/dist/{capacity-monitor-S54IOWRL.js → capacity-monitor-ZG5GGFR2.js} +27 -25
  87. package/dist/{catchup-brief-DRRQCMKA.js → catchup-brief-D6HH6DWS.js} +32 -29
  88. package/dist/{support-outbox-MGUVVGHT.js → chunk-25X4JD2V.js} +28 -12
  89. package/dist/{chunk-IYB2NIW3.js → chunk-2KZNGDSW.js} +1 -1
  90. package/dist/{chunk-FUIIVSW6.js → chunk-2WAVZ5UJ.js} +1 -1
  91. package/dist/{chunk-K5WFKEXQ.js → chunk-2ZYO73KO.js} +4 -3
  92. package/dist/{chunk-CLAYNAXC.js → chunk-3EUMUSLE.js} +1 -1
  93. package/dist/{chunk-BVV6NHKQ.js → chunk-3SW4OEHB.js} +5 -5
  94. package/dist/{task-enforcement-VI7L43DC.js → chunk-4CMVFVFC.js} +173 -69
  95. package/dist/{chunk-BU2QQWBQ.js → chunk-4J4PMPXZ.js} +3 -2
  96. package/dist/{chunk-JD5S5AAV.js → chunk-4N2NRGCM.js} +2 -2
  97. package/dist/chunk-4QCFFW2H.js +378 -0
  98. package/dist/{chunk-7EA7LYW4.js → chunk-4VSV5P4D.js} +4 -4
  99. package/dist/{chunk-52KNOQMK.js → chunk-4ZCD2UWW.js} +39 -10
  100. package/dist/{chunk-DZ6OQM67.js → chunk-5ERDIOV3.js} +2 -2
  101. package/dist/chunk-5H47VHB7.js +30 -0
  102. package/dist/{chunk-UCQITDLM.js → chunk-5TY4FPH6.js} +1 -1
  103. package/dist/{chunk-R44Z32O2.js → chunk-6CH3TPHR.js} +2 -2
  104. package/dist/{chunk-WYLV4S6A.js → chunk-6WQ3NNCE.js} +3 -3
  105. package/dist/{chunk-HHIBOU3P.js → chunk-6XWTQUO4.js} +1 -1
  106. package/dist/chunk-76CJBM36.js +88 -0
  107. package/dist/{chunk-H2L4PHGH.js → chunk-7CTRGNLW.js} +2 -2
  108. package/dist/{chunk-XUKPALWT.js → chunk-7V4JADD6.js} +2 -2
  109. package/dist/{chunk-RMOBQ6A5.js → chunk-AD2VCHSS.js} +1 -1
  110. package/dist/{chunk-QXSBB26A.js → chunk-AJYCFKJR.js} +1 -1
  111. package/dist/chunk-AM7S2TY6.js +54 -0
  112. package/dist/{chunk-HEPR6QTL.js → chunk-AOHXREB7.js} +334 -66
  113. package/dist/{chunk-FNZR3B7U.js → chunk-ASAFVDVR.js} +1 -1
  114. package/dist/{chunk-TALWBVZE.js → chunk-BUCXNV32.js} +1 -1
  115. package/dist/{chunk-SHIICYJW.js → chunk-BYTDMAGB.js} +4 -2
  116. package/dist/{chunk-32SXNM3G.js → chunk-C5QAPURN.js} +1 -1
  117. package/dist/{chunk-XCTGRD4S.js → chunk-CE7F6RHG.js} +587 -77
  118. package/dist/{chunk-7WPOJDTA.js → chunk-CNVBKDEY.js} +21 -15
  119. package/dist/{chunk-KPIN44GZ.js → chunk-CWXVH7WV.js} +1 -1
  120. package/dist/chunk-D74XYSA3.js +621 -0
  121. package/dist/{chunk-A47MXY2I.js → chunk-EQHQF5IM.js} +50 -32
  122. package/dist/{chunk-AOO77BDE.js → chunk-EUS4QUKP.js} +1 -1
  123. package/dist/{chunk-RLRT2BVM.js → chunk-EV46QTD3.js} +1 -1
  124. package/dist/{chunk-PAEXYFMY.js → chunk-F27XXN6C.js} +1 -1
  125. package/dist/{chunk-XQNNB5GY.js → chunk-F55P3H4S.js} +37 -2
  126. package/dist/{chunk-MWZFF3Q7.js → chunk-F5O7V7UK.js} +1 -1
  127. package/dist/{chunk-LMZISHSJ.js → chunk-FPFPLPUY.js} +6 -6
  128. package/dist/{chunk-7TS64TBG.js → chunk-G4RGKBCA.js} +8 -3
  129. package/dist/{chunk-4IYSBPX3.js → chunk-G5T6KDG4.js} +1 -1
  130. package/dist/{chunk-7WDXEKUL.js → chunk-GBTTBXAF.js} +4 -4
  131. package/dist/{chunk-6MRWJMI5.js → chunk-GDIJE6D7.js} +1 -1
  132. package/dist/{chunk-AVKXCSBI.js → chunk-GG5NDQNN.js} +2 -2
  133. package/dist/{chunk-I3XKO3KQ.js → chunk-GJ26DULE.js} +2 -2
  134. package/dist/chunk-GL57PO3K.js +104 -0
  135. package/dist/chunk-GWDSB25T.js +6 -0
  136. package/dist/{chunk-F55JF43M.js → chunk-H6BV5TKD.js} +39 -24
  137. package/dist/{chunk-HCJCW7X4.js → chunk-H7I47RS5.js} +34 -1
  138. package/dist/{chunk-65SVQELL.js → chunk-HA5R6USD.js} +31 -5
  139. package/dist/{chunk-VJHUVFIW.js → chunk-HAF2DJYV.js} +3 -3
  140. package/dist/chunk-HJ447YER.js +224 -0
  141. package/dist/chunk-HV4KESRY.js +395 -0
  142. package/dist/{chunk-B76TSEP3.js → chunk-I26FWCSP.js} +216 -9
  143. package/dist/{chunk-X2FHTDIU.js → chunk-IBYL4DHM.js} +1 -1
  144. package/dist/{chunk-JCBKARSK.js → chunk-IOEUAQWP.js} +1 -1
  145. package/dist/{chunk-MW2GJJ53.js → chunk-JGIPOUIK.js} +3 -3
  146. package/dist/{chunk-2233TQCA.js → chunk-JLZ4RYSD.js} +2 -2
  147. package/dist/{chunk-Q7L6G6KV.js → chunk-JMYHW3AL.js} +2 -2
  148. package/dist/{chunk-OJTJYEMX.js → chunk-JPUZPAAF.js} +4 -4
  149. package/dist/{chunk-XWHE4LZK.js → chunk-JTBIS4R5.js} +21 -2
  150. package/dist/{chunk-5Z5NATNS.js → chunk-K7KFGDWF.js} +1 -1
  151. package/dist/{chunk-UIV2WPBT.js → chunk-KGWRTRKC.js} +2 -2
  152. package/dist/{chunk-KTPG4XKI.js → chunk-KP3U5QGJ.js} +1 -1
  153. package/dist/{chunk-TLYAEISW.js → chunk-KW2SD2FL.js} +2 -2
  154. package/dist/{chunk-X7H3HMFH.js → chunk-KWZMQACA.js} +11 -7
  155. package/dist/{chunk-OFX5B2S7.js → chunk-L2R3LN2P.js} +1 -1
  156. package/dist/{chunk-T4KZ2Z2N.js → chunk-L4A5DL6Z.js} +3 -3
  157. package/dist/{chunk-X425OEYF.js → chunk-LU2FALL6.js} +3 -3
  158. package/dist/{chunk-6M36JFFD.js → chunk-MKYFAKDW.js} +4 -4
  159. package/dist/{chunk-I5RLNOFK.js → chunk-MOPUCPXK.js} +12 -4
  160. package/dist/{chunk-ZIVEA3NB.js → chunk-MR6LHP4F.js} +1 -1
  161. package/dist/chunk-MVYB76QG.js +341 -0
  162. package/dist/{chunk-2SG2UGCH.js → chunk-MZM6EJCU.js} +4 -4
  163. package/dist/{chunk-ZREGOV2Q.js → chunk-N7QJKQMX.js} +258 -14
  164. package/dist/{chunk-QLFRCA6I.js → chunk-NBZL5CGA.js} +93 -12
  165. package/dist/{chunk-QFPTDSY2.js → chunk-NN2B2QKU.js} +1 -1
  166. package/dist/chunk-NX5INHHG.js +40 -0
  167. package/dist/{chunk-B75BOKEI.js → chunk-NXUSDL37.js} +2 -2
  168. package/dist/{chunk-TPHCZDE3.js → chunk-O5V57XYE.js} +1 -1
  169. package/dist/chunk-O7LWR36Z.js +269 -0
  170. package/dist/{chunk-ATOU6CYR.js → chunk-OLMQ4UOF.js} +57 -11
  171. package/dist/{chunk-6HBURYON.js → chunk-OTF44GXL.js} +4 -4
  172. package/dist/{chunk-DILD54TU.js → chunk-OZEBAGKR.js} +277 -137
  173. package/dist/{chunk-DADMPMYX.js → chunk-P5HIWY2E.js} +1 -1
  174. package/dist/{chunk-EIF2LQHZ.js → chunk-PDWS3E22.js} +55 -4
  175. package/dist/{chunk-KTY7I7UH.js → chunk-PPCDBE6Z.js} +1 -1
  176. package/dist/{chunk-XACL67CS.js → chunk-PQIDGXSG.js} +13 -4
  177. package/dist/chunk-PWUFMX75.js +186 -0
  178. package/dist/{chunk-UPWE5NOG.js → chunk-QDGZJ653.js} +3 -3
  179. package/dist/{chunk-MQRFKSLI.js → chunk-QOO5RW3K.js} +6 -5
  180. package/dist/{chunk-KCC5A7YL.js → chunk-QQ4E2RYW.js} +95 -18
  181. package/dist/{chunk-BPC5LZ6Y.js → chunk-QRYVCDWS.js} +2 -2
  182. package/dist/{chunk-Z42MXYWW.js → chunk-QWVXN224.js} +110 -28
  183. package/dist/{chunk-542EWGY3.js → chunk-QYZJHTNE.js} +26 -27
  184. package/dist/{chunk-I7Z6KTGF.js → chunk-R2NN3JKH.js} +43 -6
  185. package/dist/{chunk-3OBWSCJN.js → chunk-RACAOE2Z.js} +14 -14
  186. package/dist/{chunk-5RACW3LX.js → chunk-RAXVPNMR.js} +1 -1
  187. package/dist/{chunk-2HZY3ECT.js → chunk-RHWZUUS4.js} +6 -6
  188. package/dist/{chunk-RNAYCUNM.js → chunk-S3THSOWV.js} +1 -1
  189. package/dist/{chunk-W7DHFGCB.js → chunk-S7QUM2UK.js} +2 -2
  190. package/dist/{chunk-SSTLTIF3.js → chunk-SKGMF2SO.js} +25 -2
  191. package/dist/{chunk-GN45PBWI.js → chunk-SQKXKV2Y.js} +2 -2
  192. package/dist/{chunk-QZLIZAS7.js → chunk-TLT7NZCW.js} +4 -4
  193. package/dist/chunk-TTCUG2CF.js +91 -0
  194. package/dist/chunk-UEA3LXOB.js +40 -0
  195. package/dist/{chunk-DRCRZIIJ.js → chunk-UNXQBELK.js} +1 -1
  196. package/dist/{chunk-PLRIJALF.js → chunk-UP75Z5X7.js} +921 -176
  197. package/dist/{chunk-TNJRWUCE.js → chunk-USSB56WK.js} +1 -1
  198. package/dist/{chunk-KMBEL7VB.js → chunk-UUEKJDK6.js} +90 -10
  199. package/dist/{chunk-XJI7Z6LZ.js → chunk-UUQBZPJJ.js} +1 -1
  200. package/dist/{chunk-RRWDYOQS.js → chunk-V3EEVY4L.js} +1 -1
  201. package/dist/{chunk-N5I7RL3I.js → chunk-VPZHJCKW.js} +2 -2
  202. package/dist/chunk-VRAQTFD6.js +265 -0
  203. package/dist/{chunk-H37HHX3E.js → chunk-VSRPS3J7.js} +14 -14
  204. package/dist/{chunk-5ZNY7IZI.js → chunk-WMESXBJM.js} +37 -3
  205. package/dist/{chunk-54QCG45Y.js → chunk-WOYADZF5.js} +56 -5
  206. package/dist/{chunk-7Y5UDEVM.js → chunk-WZHZCDDO.js} +6 -5
  207. package/dist/{chunk-3NGZ4PL7.js → chunk-X2Q5NLUL.js} +11 -2
  208. package/dist/{chunk-YE7NH53A.js → chunk-X33NYQYJ.js} +2 -2
  209. package/dist/{chunk-UXBD22CD.js → chunk-XHK3FS3W.js} +3 -2
  210. package/dist/{chunk-3QDSCJ3F.js → chunk-XZXBB3TN.js} +2 -2
  211. package/dist/{chunk-JSKBHUR7.js → chunk-YCANDMI2.js} +2 -2
  212. package/dist/{chunk-JBSCL2XT.js → chunk-YLXTKI6M.js} +1 -1
  213. package/dist/{chunk-G7WO77Z2.js → chunk-YTCFACP4.js} +812 -896
  214. package/dist/{chunk-LTVCRHHD.js → chunk-Z6RSN7KS.js} +7 -6
  215. package/dist/{cleanup-graph-garbage-KUABW6LS.js → cleanup-graph-garbage-XWUFAMFO.js} +6 -6
  216. package/dist/{co-activation-XMPHKGHR.js → co-activation-ZCHPLLP6.js} +4 -4
  217. package/dist/{co-occurrence-SHKSJ6CV.js → co-occurrence-KG3LKALN.js} +4 -4
  218. package/dist/{code-context-index-EXXDY3QZ.js → code-context-index-WSOJQ72R.js} +5 -5
  219. package/dist/{content-extractor-RHITF2KM.js → content-extractor-NXYNEF5K.js} +2 -2
  220. package/dist/{conversation-wiki-populator-WU4HEQ7C.js → conversation-wiki-populator-WQN3IUU6.js} +1 -1
  221. package/dist/{crdt-sync-UJELKSNX.js → crdt-sync-4PFGPZXV.js} +8 -1
  222. package/dist/{crm-webhook-HHNBS7LY.js → crm-webhook-II7Z45Q6.js} +2 -2
  223. package/dist/cto-delegation-gate-JWWOJPNC.js +669 -0
  224. package/dist/{daemon-auth-7IFSV5FG.js → daemon-auth-3FEAHFWC.js} +5 -3
  225. package/dist/{daemon-orchestration-7QB6QOXT.js → daemon-orchestration-FX4XZDR5.js} +46 -27
  226. package/dist/{daemon-ready-5XI5BIJD.js → daemon-ready-4JTSFKAY.js} +1 -1
  227. package/dist/{daemon-ready-signal-E7VMIQ6I.js → daemon-ready-signal-LPAZWQOV.js} +5 -1
  228. package/dist/daemon-restart-circuit-breaker-PEGEIP6H.js +35 -0
  229. package/dist/daemon-timer-report-NM44WQRH.js +25 -0
  230. package/dist/{db-backup-DLD4QZBO.js → db-backup-W2QFSYQC.js} +15 -5
  231. package/dist/{db-restore-events-JVEEP52Z.js → db-restore-events-MQ2DBGEQ.js} +2 -2
  232. package/dist/dispatch-ack-VYH3ONSS.js +27 -0
  233. package/dist/{doc-graph-extractor-3TRLGD7M.js → doc-graph-extractor-F6ODFIID.js} +4 -4
  234. package/dist/{documents-FHIBU7KJ.js → documents-23WX2FPQ.js} +12 -12
  235. package/dist/dreaming-NWD22UQ5.js +46 -0
  236. package/dist/{exe-drift-KY2KHZEL.js → exe-drift-CW72FBGE.js} +5 -5
  237. package/dist/{exe-export-SP6G3QF6.js → exe-export-AUJ7CV7G.js} +11 -11
  238. package/dist/{exe-import-KJU7FBVQ.js → exe-import-JX4I52VE.js} +11 -11
  239. package/dist/{exe-key-M6TYHNUW.js → exe-key-2N6LY2BU.js} +241 -226
  240. package/dist/{exe-org-BGZNNE4H.js → exe-org-X4CSNCKS.js} +3 -3
  241. package/dist/{exe-snapshot-ZNPGUKRZ.js → exe-snapshot-XZ7FVCYZ.js} +31 -29
  242. package/dist/{fast-db-init-QQB6IVWV.js → fast-db-init-4CWHSOOR.js} +1 -1
  243. package/dist/{founder-context-PQR3BUS7.js → founder-context-7L3CFPYN.js} +4 -4
  244. package/dist/gateway/index.js +14 -14
  245. package/dist/{gateway-client-GRBOJQYC.js → gateway-client-7LMZKHTH.js} +1 -1
  246. package/dist/git-main-guard-UZP3KXYI.js +39 -0
  247. package/dist/{git-staleness-UGB5J3K7.js → git-staleness-CI2R4QOJ.js} +4 -4
  248. package/dist/{global-procedures-R7KRREEK.js → global-procedures-XQX3LUH6.js} +6 -6
  249. package/dist/{graph-auto-extract-LKIQ57PL.js → graph-auto-extract-OURWMGBS.js} +4 -4
  250. package/dist/{hook-integrity-WURH6DS3.js → hook-integrity-XY47IM7G.js} +1 -1
  251. package/dist/hook-prefetch-PHRRKY4C.js +137 -0
  252. package/dist/hooks/bug-report-worker.js +32 -28
  253. package/dist/hooks/codex-stop-task-finalizer.js +32 -28
  254. package/dist/hooks/commit-complete.js +29 -27
  255. package/dist/hooks/error-recall.js +12 -11
  256. package/dist/hooks/exe-heartbeat-hook.js +6 -6
  257. package/dist/hooks/ingest-worker.js +11 -11
  258. package/dist/hooks/ingest.js +18 -18
  259. package/dist/hooks/instructions-loaded.js +7 -7
  260. package/dist/hooks/manifest.json +20 -20
  261. package/dist/hooks/notification.js +7 -7
  262. package/dist/hooks/post-compact.js +28 -26
  263. package/dist/hooks/post-tool-combined.js +12 -12
  264. package/dist/hooks/pre-compact.js +29 -27
  265. package/dist/hooks/pre-tool-use.js +180 -47
  266. package/dist/hooks/prompt-submit.js +324 -273
  267. package/dist/hooks/session-end.js +35 -33
  268. package/dist/hooks/session-start.js +28 -21
  269. package/dist/hooks/stop.js +35 -33
  270. package/dist/hooks/subagent-stop.js +28 -26
  271. package/dist/hooks/summary-worker.js +36 -34
  272. package/dist/index.js +39 -37
  273. package/dist/{installer-SB2N5NKH.js → installer-G3JAO3NT.js} +9 -9
  274. package/dist/{installer-MZWWBXM6.js → installer-JND3RJ6Q.js} +9 -9
  275. package/dist/{installer-MNPXDLGG.js → installer-L7EVH5U5.js} +9 -9
  276. package/dist/{intercom-queue-VU2G6F5R.js → intercom-queue-ZFEQALR3.js} +25 -23
  277. package/dist/{key-backup-status-TNEHXA2X.js → key-backup-status-LOSMVATJ.js} +2 -2
  278. package/dist/lib/agent-config.js +4 -3
  279. package/dist/lib/cloud-sync.js +19 -19
  280. package/dist/lib/config.js +2 -2
  281. package/dist/lib/consolidation.js +9 -9
  282. package/dist/lib/crypto.js +3 -3
  283. package/dist/lib/database.js +6 -4
  284. package/dist/lib/db-daemon-client.js +5 -5
  285. package/dist/lib/db-read-worker-client.js +9 -3
  286. package/dist/lib/db.js +6 -4
  287. package/dist/lib/device-registry.js +3 -3
  288. package/dist/lib/embed-worker.js +2 -2
  289. package/dist/lib/embedder.js +5 -5
  290. package/dist/lib/employee-templates.js +7 -7
  291. package/dist/lib/employees.js +10 -4
  292. package/dist/lib/exe-daemon-client.js +4 -4
  293. package/dist/lib/exe-daemon.js +651 -158
  294. package/dist/lib/hybrid-search.js +11 -9
  295. package/dist/lib/identity.js +4 -4
  296. package/dist/lib/keychain.js +1 -1
  297. package/dist/lib/license.js +4 -4
  298. package/dist/lib/messaging.js +28 -24
  299. package/dist/lib/post-tool-memory.js +3 -3
  300. package/dist/lib/registry-proxy.js +1 -1
  301. package/dist/lib/reminders.js +15 -7
  302. package/dist/lib/schedules.js +9 -9
  303. package/dist/lib/session-registry.js +6 -6
  304. package/dist/lib/skill-learning.js +10 -10
  305. package/dist/lib/status-brief.js +4 -4
  306. package/dist/lib/store.js +8 -8
  307. package/dist/lib/task-router.js +5 -5
  308. package/dist/lib/tasks.js +29 -25
  309. package/dist/lib/tmux-routing.js +56 -25
  310. package/dist/lib/tmux-status.js +9 -3
  311. package/dist/lib/tmux-transport.js +1 -1
  312. package/dist/lib/token-spend.js +5 -5
  313. package/dist/lib/transport.js +2 -2
  314. package/dist/lib/ws-client.js +1 -1
  315. package/dist/{license-gate-BYDMFMFT.js → license-gate-QTRQHV4F.js} +5 -5
  316. package/dist/{license-sync-N3RNYVP2.js → license-sync-N3UJFWAW.js} +4 -4
  317. package/dist/mcp/register-tools.js +96 -89
  318. package/dist/mcp/server.js +98 -91
  319. package/dist/mcp/tools/complete-reminder.js +6 -6
  320. package/dist/mcp/tools/create-reminder.js +6 -6
  321. package/dist/mcp/tools/create-task.js +37 -28
  322. package/dist/mcp/tools/deactivate-behavior.js +11 -11
  323. package/dist/mcp/tools/list-reminders.js +6 -6
  324. package/dist/mcp/tools/list-tasks.js +35 -29
  325. package/dist/mcp/tools/send-message.js +28 -26
  326. package/dist/mcp/tools/update-task.js +34 -28
  327. package/dist/{mcp-http-config-EMAVS2JI.js → mcp-http-config-BDL36JZ3.js} +6 -6
  328. package/dist/{mcp-port-config-FFAMMLLE.js → mcp-port-config-6HYY6J7K.js} +2 -2
  329. package/dist/mcp-session-identity-T7H2EKFQ.js +177 -0
  330. package/dist/{memory-cards-TQRLZI4D.js → memory-cards-ZRDW7QBX.js} +8 -8
  331. package/dist/{memory-graph-extractor-IWGNVAFU.js → memory-graph-extractor-QLXDMHRS.js} +5 -5
  332. package/dist/{memory-poisoning-defense-T4ITBGSG.js → memory-poisoning-defense-HJTXYCWH.js} +4 -4
  333. package/dist/{memory-pressure-watchdog-RRIAXPXQ.js → memory-pressure-watchdog-HN5X7AVN.js} +76 -37
  334. package/dist/{memory-queue-X2CSEAKE.js → memory-queue-2UOOF27L.js} +5 -3
  335. package/dist/{memory-queue-client-BKQHTYTH.js → memory-queue-client-O5U6F6XP.js} +6 -6
  336. package/dist/{memory-reflection-6N4J2FL7.js → memory-reflection-WVNFBJAA.js} +4 -4
  337. package/dist/{monitor-grants-RZOVSYVO.js → monitor-grants-E3ELDEWD.js} +5 -5
  338. package/dist/{monitor-identity-MOXISYNG.js → monitor-identity-GLFZSEAH.js} +2 -2
  339. package/dist/notification-ledger-SZEPGJQ7.js +409 -0
  340. package/dist/{notifications-KONB3C62.js → notifications-4UT53CDG.js} +25 -23
  341. package/dist/{orchestration-events-5SIJOE4H.js → orchestration-events-WV4NWKZH.js} +5 -5
  342. package/dist/{orchestration-phase-CXRCBCK7.js → orchestration-phase-AWBXPO52.js} +3 -3
  343. package/dist/orchestrator-UAC3RW2T.js +47 -0
  344. package/dist/{pipeline-router-O6HU7DKH.js → pipeline-router-LM53NMWJ.js} +5 -5
  345. package/dist/{plan-limits-GRNBOBB3.js → plan-limits-2FEY2GOS.js} +7 -7
  346. package/dist/platform-procedures-X5DFJFV7.js +13 -0
  347. package/dist/{preferences-TYTGDXQZ.js → preferences-TWIXZBKS.js} +2 -2
  348. package/dist/{project-boot-SD7GM24K.js → project-boot-4NUH5FRU.js} +2 -2
  349. package/dist/{projection-worker-ZVOFHTXT.js → projection-worker-FZ7YSN3G.js} +5 -5
  350. package/dist/{prospective-memory-W6S67LZZ.js → prospective-memory-6D2ASWM3.js} +4 -4
  351. package/dist/{push-notifications-W5JRXLKJ.js → push-notifications-U6FIBQRW.js} +3 -3
  352. package/dist/{reranker-QATGTAPC.js → reranker-GYYRPANK.js} +3 -3
  353. package/dist/{retrieval-health-TWHKYCRK.js → retrieval-health-4Z242P3B.js} +1 -1
  354. package/dist/{review-polling-PCMD5BFN.js → review-polling-HXAFJZDA.js} +26 -24
  355. package/dist/runtime/index.js +37 -35
  356. package/dist/{session-events-3LCVQEL7.js → session-events-O3BV56ZX.js} +26 -24
  357. package/dist/{session-kill-telemetry-CZSPN5V6.js → session-kill-telemetry-AELE4JDK.js} +26 -24
  358. package/dist/session-mcp-config-YKNXG5DW.js +50 -0
  359. package/dist/{session-scope-CFHVSVAQ.js → session-scope-5EAPUT45.js} +25 -23
  360. package/dist/setup-wizard-NB6R4QVS.js +14 -0
  361. package/dist/{shard-manager-MBWQEYNG.js → shard-manager-35PWFR3B.js} +3 -3
  362. package/dist/{skill-refinement-74T6VDFM.js → skill-refinement-DVSYXBBP.js} +5 -5
  363. package/dist/stack-promote-RSOWO6EY.js +130 -0
  364. package/dist/{stack-release-XXMV7SPX.js → stack-release-HGFFFCGC.js} +112 -22
  365. package/dist/{stack-update-E2TKHHSQ.js → stack-update-ATCJFOEK.js} +7 -5
  366. package/dist/{steward-gate-WT7WXQIE.js → steward-gate-3GQ5XKMJ.js} +5 -5
  367. package/dist/support-inbox-4L62P4EP.js +33 -0
  368. package/dist/support-outbox-WHGPUYL2.js +16 -0
  369. package/dist/task-enforcement-IPIZX2MM.js +90 -0
  370. package/dist/{task-scope-CQEG5SSJ.js → task-scope-FOIW25HR.js} +27 -23
  371. package/dist/{tasks-crud-UGK5A25L.js → tasks-crud-HBDKE6C5.js} +35 -23
  372. package/dist/tasks-notify-G2U2U2YA.js +53 -0
  373. package/dist/{tasks-review-JKBRACII.js → tasks-review-27SFX5XN.js} +27 -23
  374. package/dist/{telemetry-upload-7LBYGPCB.js → telemetry-upload-ZOXHRWR5.js} +9 -9
  375. package/dist/tmux-command-guard-KSJKIX3C.js +117 -0
  376. package/dist/{token-budget-QBRJR4M5.js → token-budget-5Y4YPDO3.js} +5 -5
  377. package/dist/{tool-capability-index-Q6YQDL7I.js → tool-capability-index-VYF5GNJ2.js} +1 -1
  378. package/dist/{tool-telemetry-ULIDUK3P.js → tool-telemetry-KBXSBDTK.js} +1 -1
  379. package/dist/tui/App.js +40 -38
  380. package/dist/{tui-data-NPTGKT37.js → tui-data-NLFMBIQI.js} +25 -23
  381. package/dist/{update-check-HFO4VHO4.js → update-check-3FHAWIG2.js} +7 -3
  382. package/dist/update-support-UVUSZG7R.js +355 -0
  383. package/dist/{whatsapp-accounts-BWRZUY23.js → whatsapp-accounts-BFIOXYW5.js} +1 -1
  384. package/dist/{whatsapp-config-GOSELKTE.js → whatsapp-config-FAX6EA5K.js} +20 -13
  385. package/dist/{worker-gate-MXUQUG4M.js → worker-gate-3KUBAU32.js} +3 -3
  386. package/dist/{workflow-engine-EWCOLD47.js → workflow-engine-YITHXZR5.js} +2 -2
  387. package/dist/{working-memory-PY4AG577.js → working-memory-NUVB5SFV.js} +1 -1
  388. package/dist/worktree-LL62PLQB.js +47 -0
  389. package/dist/{worktree-sweep-ZAG3V24E.js → worktree-sweep-WTK3MTKH.js} +7 -7
  390. package/package.json +3 -2
  391. package/release-notes.json +86 -76
  392. package/dist/branch-hygiene-R5NVTRAY.js +0 -138
  393. package/dist/chunk-6IRVGOUL.js +0 -30
  394. package/dist/chunk-HMP5VT6A.js +0 -118
  395. package/dist/chunk-PVYR4FCQ.js +0 -113
  396. package/dist/chunk-UFAXZ2PY.js +0 -138
  397. package/dist/chunk-Y25OJWOQ.js +0 -45
  398. package/dist/chunk-YGAAZN3E.js +0 -47
  399. package/dist/cto-delegation-gate-DXNF5HVW.js +0 -290
  400. package/dist/dispatch-ack-4S44HBWB.js +0 -15
  401. package/dist/dreaming-OMFUEUCQ.js +0 -44
  402. package/dist/orchestrator-DUUX7FQV.js +0 -45
  403. package/dist/setup-wizard-TOFEJPLF.js +0 -13
  404. package/dist/tasks-notify-SMLDFBWM.js +0 -50
  405. package/dist/worktree-GVF2I5FP.js +0 -31
  406. /package/dist/{chunk-FLNSJ2TC.js → chunk-GIBYNT6W.js} +0 -0
  407. /package/dist/{chunk-NQBRGXYR.js → chunk-JRM4TAGS.js} +0 -0
  408. /package/dist/{chunk-WHRTDN5J.js → chunk-MGGOSFCR.js} +0 -0
  409. /package/dist/{chunk-D3QASX2W.js → chunk-QIFYLIUF.js} +0 -0
  410. /package/dist/{chunk-OADURIIN.js → chunk-WTH4CSAP.js} +0 -0
  411. /package/dist/{core-memory-VO5ZIBKH.js → core-memory-GAC6EWOQ.js} +0 -0
  412. /package/dist/{entity-boost-DNI4A5I7.js → entity-boost-NT6UO2Z3.js} +0 -0
  413. /package/dist/{message-queue-client-Q5BW3O5W.js → message-queue-client-4EOQRUXW.js} +0 -0
  414. /package/dist/{oauth-server-ROQFOEMM.js → oauth-server-67YBDP32.js} +0 -0
  415. /package/dist/{webhook-pipe-FZYLO6RR.js → webhook-pipe-LEXMUQ5B.js} +0 -0
  416. /package/dist/{wiki-acl-JA5UCQZ4.js → wiki-acl-74BLWG6J.js} +0 -0
  417. /package/dist/{wiki-client-VNDOBK63.js → wiki-client-EAN7F5LV.js} +0 -0
@@ -1,14 +1,37 @@
1
- import {
2
- runDriftProbes
3
- } from "./chunk-XJI7Z6LZ.js";
4
1
  import {
5
2
  exportOrchestration,
6
3
  importOrchestration,
7
4
  validatePackage
8
- } from "./chunk-QZLIZAS7.js";
5
+ } from "./chunk-TLT7NZCW.js";
6
+ import {
7
+ runDriftProbes
8
+ } from "./chunk-UUQBZPJJ.js";
9
+ import {
10
+ registerAddBugReportComment,
11
+ registerGetBugReport,
12
+ registerGetBugReportComments,
13
+ registerGetFeatureRequest,
14
+ registerGetReview,
15
+ registerListBugReports,
16
+ registerListFeatureRequests,
17
+ registerListReviews,
18
+ registerTriageBugReport,
19
+ registerTriageFeatureRequest,
20
+ registerTriageReview
21
+ } from "./chunk-HV4KESRY.js";
22
+ import {
23
+ persistSupportArtifact
24
+ } from "./chunk-TTCUG2CF.js";
25
+ import {
26
+ supportCommitSchema,
27
+ supportIdSchema,
28
+ supportProductSchema,
29
+ supportTaskIdSchema,
30
+ supportVersionSchema
31
+ } from "./chunk-5H47VHB7.js";
9
32
  import {
10
33
  StewardGate
11
- } from "./chunk-AOO77BDE.js";
34
+ } from "./chunk-EUS4QUKP.js";
12
35
  import {
13
36
  DEFAULT_LIST_LIMIT,
14
37
  MAX_IMPORTANCE,
@@ -17,11 +40,11 @@ import {
17
40
  ingestDocument,
18
41
  listDocumentsByWorkspace,
19
42
  updateChunksImportance
20
- } from "./chunk-6M36JFFD.js";
43
+ } from "./chunk-MKYFAKDW.js";
21
44
  import {
22
45
  isRerankerAvailable,
23
46
  rerankWithScores
24
- } from "./chunk-DRCRZIIJ.js";
47
+ } from "./chunk-UNXQBELK.js";
25
48
  import {
26
49
  getEntityByName,
27
50
  getEntityNeighbors,
@@ -38,32 +61,32 @@ import {
38
61
  searchCodeContext,
39
62
  searchCodeContextSemantic,
40
63
  traceCodeSymbol
41
- } from "./chunk-W7DHFGCB.js";
64
+ } from "./chunk-S7QUM2UK.js";
42
65
  import {
43
- DEFAULT_EXPLORE_DURATION_MS,
44
- getPlayMode,
45
- listExploreSessions,
46
- setPlayMode
47
- } from "./chunk-PVYR4FCQ.js";
66
+ listRecentSessionEvents
67
+ } from "./chunk-NN2B2QKU.js";
48
68
  import {
49
69
  DreamingEngine
50
- } from "./chunk-VJHUVFIW.js";
70
+ } from "./chunk-HAF2DJYV.js";
51
71
  import {
52
72
  AUTO_WAKE_MAX_RETRIES
53
- } from "./chunk-XCTGRD4S.js";
73
+ } from "./chunk-CE7F6RHG.js";
54
74
  import {
55
- listRecentSessionEvents
56
- } from "./chunk-QFPTDSY2.js";
75
+ DEFAULT_EXPLORE_DURATION_MS,
76
+ getPlayMode,
77
+ listExploreSessions,
78
+ setPlayMode
79
+ } from "./chunk-4CMVFVFC.js";
57
80
  import {
58
81
  getCachedLicenseGate,
59
82
  refreshLicenseGate
60
- } from "./chunk-DADMPMYX.js";
83
+ } from "./chunk-P5HIWY2E.js";
61
84
  import {
62
85
  getToolUsageStats
63
- } from "./chunk-NQBRGXYR.js";
86
+ } from "./chunk-JRM4TAGS.js";
64
87
  import {
65
88
  getToolCapabilityIndex
66
- } from "./chunk-WHRTDN5J.js";
89
+ } from "./chunk-MGGOSFCR.js";
67
90
  import {
68
91
  isToolAllowed,
69
92
  isToolAllowedForPlan
@@ -71,58 +94,59 @@ import {
71
94
  import {
72
95
  loadOrchestrationPhase,
73
96
  setOrchestrationPhase
74
- } from "./chunk-32SXNM3G.js";
97
+ } from "./chunk-C5QAPURN.js";
75
98
  import {
76
99
  createOrRefreshResumeTask
77
- } from "./chunk-LMZISHSJ.js";
100
+ } from "./chunk-FPFPLPUY.js";
101
+ import {
102
+ registerSendMessage
103
+ } from "./chunk-JMYHW3AL.js";
104
+ import {
105
+ registerCreateTask,
106
+ resolveProjectDir
107
+ } from "./chunk-OZEBAGKR.js";
78
108
  import {
79
109
  registerListTasks
80
- } from "./chunk-MQRFKSLI.js";
110
+ } from "./chunk-QOO5RW3K.js";
81
111
  import {
82
112
  registerUpdateTask
83
- } from "./chunk-LTVCRHHD.js";
113
+ } from "./chunk-Z6RSN7KS.js";
84
114
  import {
85
115
  registerCreateReminder
86
- } from "./chunk-6IRVGOUL.js";
116
+ } from "./chunk-NX5INHHG.js";
87
117
  import {
88
118
  registerListReminders
89
- } from "./chunk-BU2QQWBQ.js";
119
+ } from "./chunk-4J4PMPXZ.js";
90
120
  import {
91
121
  registerCompleteReminder
92
- } from "./chunk-PAEXYFMY.js";
93
- import {
94
- registerDeactivateBehavior
95
- } from "./chunk-2SG2UGCH.js";
122
+ } from "./chunk-F27XXN6C.js";
96
123
  import {
97
124
  completeReminder,
98
125
  createReminder,
99
126
  listReminders
100
- } from "./chunk-KMBEL7VB.js";
101
- import {
102
- registerImportConversations
103
- } from "./chunk-WYLV4S6A.js";
127
+ } from "./chunk-UUEKJDK6.js";
104
128
  import {
105
- registerSendMessage
106
- } from "./chunk-Q7L6G6KV.js";
129
+ registerDeactivateBehavior
130
+ } from "./chunk-MZM6EJCU.js";
107
131
  import {
108
- registerCreateTask
109
- } from "./chunk-DILD54TU.js";
132
+ registerImportConversations
133
+ } from "./chunk-6WQ3NNCE.js";
110
134
  import {
111
135
  TOKENS_PER_IDLE_MINUTE,
112
136
  countKillsSince,
113
137
  sumTokensSavedSince
114
- } from "./chunk-T4KZ2Z2N.js";
138
+ } from "./chunk-L4A5DL6Z.js";
115
139
  import {
116
140
  createSchedule,
117
141
  parseHumanCron
118
- } from "./chunk-GN45PBWI.js";
142
+ } from "./chunk-SQKXKV2Y.js";
119
143
  import {
120
144
  status
121
- } from "./chunk-OJTJYEMX.js";
145
+ } from "./chunk-JPUZPAAF.js";
122
146
  import {
123
147
  evaluateGlobalSpendCap,
124
148
  getAgentSpend
125
- } from "./chunk-BPC5LZ6Y.js";
149
+ } from "./chunk-QRYVCDWS.js";
126
150
  import {
127
151
  exportGraphHTML,
128
152
  generateGraphReport
@@ -135,14 +159,14 @@ import {
135
159
  formatReport,
136
160
  runAudit,
137
161
  shouldFixShards
138
- } from "./chunk-KCC5A7YL.js";
162
+ } from "./chunk-QQ4E2RYW.js";
139
163
  import {
140
164
  formatDegradations,
141
165
  getRetrievalHealth
142
- } from "./chunk-IYB2NIW3.js";
166
+ } from "./chunk-2KZNGDSW.js";
143
167
  import {
144
168
  runHealthCheck
145
- } from "./chunk-EIF2LQHZ.js";
169
+ } from "./chunk-PDWS3E22.js";
146
170
  import {
147
171
  checkCpuStealSync
148
172
  } from "./chunk-SSC7EKY2.js";
@@ -150,7 +174,7 @@ import {
150
174
  hasFailures,
151
175
  runHealth,
152
176
  runTest
153
- } from "./chunk-6HBURYON.js";
177
+ } from "./chunk-OTF44GXL.js";
154
178
  import {
155
179
  isSupportReportSentStatus,
156
180
  markSupportReportSent
@@ -161,28 +185,28 @@ import {
161
185
  } from "./chunk-2XZ6X3PJ.js";
162
186
  import {
163
187
  renderClientCOOTemplate
164
- } from "./chunk-UXBD22CD.js";
188
+ } from "./chunk-XHK3FS3W.js";
165
189
  import {
166
190
  deactivateGlobalProcedure,
167
191
  loadGlobalProcedures,
168
192
  storeGlobalProcedure
169
- } from "./chunk-I3XKO3KQ.js";
193
+ } from "./chunk-GJ26DULE.js";
170
194
  import {
171
195
  PLATFORM_PROCEDURES
172
- } from "./chunk-A47MXY2I.js";
196
+ } from "./chunk-EQHQF5IM.js";
173
197
  import {
174
198
  clearCloudReuploadRequired,
175
199
  cloudSync,
176
200
  getCloudReuploadRequired,
177
201
  markCloudReuploadRequired
178
- } from "./chunk-7WPOJDTA.js";
202
+ } from "./chunk-CNVBKDEY.js";
179
203
  import {
180
204
  createARecord
181
205
  } from "./chunk-X2Z5GT3V.js";
182
206
  import {
183
207
  findSimilarTrajectories,
184
208
  hashSignature
185
- } from "./chunk-UPWE5NOG.js";
209
+ } from "./chunk-QDGZJ653.js";
186
210
  import {
187
211
  GHOST_BEHAVIOR_SQL,
188
212
  deactivateBehavior,
@@ -191,40 +215,40 @@ import {
191
215
  reactivateBehavior,
192
216
  storeBehavior,
193
217
  storeReflexBehavior
194
- } from "./chunk-TLYAEISW.js";
218
+ } from "./chunk-KW2SD2FL.js";
195
219
  import {
196
220
  countUnconsolidated,
197
221
  groupMemories,
198
222
  runConsolidation,
199
223
  selectUnconsolidated
200
- } from "./chunk-R44Z32O2.js";
224
+ } from "./chunk-6CH3TPHR.js";
201
225
  import {
202
226
  entityId,
203
227
  mergeEntities
204
228
  } from "./chunk-A4DVMPYB.js";
205
229
  import {
206
230
  embed
207
- } from "./chunk-3QDSCJ3F.js";
231
+ } from "./chunk-XZXBB3TN.js";
208
232
  import {
209
233
  detectDcrIncompatibleConnectorsFromDisk,
210
234
  detectExternalMcpFailures,
211
235
  readMcpHttpEvents,
212
236
  summarizeMcpTransport,
213
237
  writeMcpTransportSummary
214
- } from "./chunk-5RACW3LX.js";
238
+ } from "./chunk-RAXVPNMR.js";
215
239
  import {
216
240
  updateTask
217
- } from "./chunk-542EWGY3.js";
241
+ } from "./chunk-QYZJHTNE.js";
218
242
  import {
219
243
  fastDbInit
220
- } from "./chunk-UFAXZ2PY.js";
244
+ } from "./chunk-PWUFMX75.js";
221
245
  import {
222
246
  MAX_CONCURRENT_WORKERS
223
- } from "./chunk-N5I7RL3I.js";
247
+ } from "./chunk-VPZHJCKW.js";
224
248
  import {
225
249
  hybridSearch,
226
250
  recentRecords
227
- } from "./chunk-ZREGOV2Q.js";
251
+ } from "./chunk-N7QJKQMX.js";
228
252
  import {
229
253
  buildFtsMatch,
230
254
  tokenizeForFts
@@ -234,10 +258,21 @@ import {
234
258
  flushBatch,
235
259
  initStore,
236
260
  writeMemory
237
- } from "./chunk-H37HHX3E.js";
261
+ } from "./chunk-VSRPS3J7.js";
238
262
  import {
239
263
  getActiveAgent
240
- } from "./chunk-DZ6OQM67.js";
264
+ } from "./chunk-5ERDIOV3.js";
265
+ import {
266
+ UPSTREAM_ATTACHMENT_MAX_CHARS,
267
+ isTelemetryRedactionEnabled,
268
+ redactSecrets,
269
+ redactedToolResult,
270
+ sanitizeProductFilter,
271
+ sanitizeUpstreamId,
272
+ sanitizeUpstreamPayload,
273
+ sanitizeVersionField,
274
+ sanitizedUpstreamBody
275
+ } from "./chunk-4QCFFW2H.js";
241
276
  import {
242
277
  getMySession,
243
278
  resolveExeSession,
@@ -246,13 +281,13 @@ import {
246
281
  sessionScopeFilter,
247
282
  updateTaskStatus,
248
283
  writeCheckpoint
249
- } from "./chunk-PLRIJALF.js";
284
+ } from "./chunk-UP75Z5X7.js";
250
285
  import {
251
286
  listSessions
252
- } from "./chunk-UIV2WPBT.js";
287
+ } from "./chunk-KGWRTRKC.js";
253
288
  import {
254
289
  recordOrchestrationEventBestEffort
255
- } from "./chunk-FUIIVSW6.js";
290
+ } from "./chunk-2WAVZ5UJ.js";
256
291
  import {
257
292
  DEFAULT_MODELS,
258
293
  KNOWN_RUNTIMES,
@@ -260,35 +295,33 @@ import {
260
295
  getAgentRuntime,
261
296
  loadAgentConfig,
262
297
  setAgentRuntime
263
- } from "./chunk-65SVQELL.js";
264
- import {
265
- DEFAULT_RUNTIME
266
- } from "./chunk-NGP6LSV2.js";
298
+ } from "./chunk-HA5R6USD.js";
267
299
  import {
268
300
  PlanLimitError,
269
301
  assertEmployeeLimit,
270
302
  assertFeature,
271
303
  assertMemoryLimit
272
- } from "./chunk-MW2GJJ53.js";
304
+ } from "./chunk-JGIPOUIK.js";
273
305
  import {
274
306
  getProjectName
275
307
  } from "./chunk-OPU3NYOO.js";
276
308
  import {
277
309
  readDaemonToken
278
- } from "./chunk-3NGZ4PL7.js";
310
+ } from "./chunk-X2Q5NLUL.js";
279
311
  import {
280
312
  getAgentContext
281
313
  } from "./chunk-GJV3WDWM.js";
282
314
  import {
315
+ _resetCache,
283
316
  getAccountByName,
284
317
  getDefaultAccount
285
- } from "./chunk-YGAAZN3E.js";
318
+ } from "./chunk-GL57PO3K.js";
286
319
  import {
287
320
  createNewTrigger,
288
321
  isScheduledTrigger,
289
322
  loadTriggers,
290
323
  sanitizeParam
291
- } from "./chunk-KTPG4XKI.js";
324
+ } from "./chunk-KP3U5QGJ.js";
292
325
  import {
293
326
  pushConversationToCRM
294
327
  } from "./chunk-ML4S5SHZ.js";
@@ -306,10 +339,11 @@ import {
306
339
  isInitialized,
307
340
  listIdentities,
308
341
  loadEmployees,
342
+ loadEmployeesState,
309
343
  loadEmployeesSync,
310
344
  saveEmployees,
311
345
  updateIdentity
312
- } from "./chunk-HEPR6QTL.js";
346
+ } from "./chunk-AOHXREB7.js";
313
347
  import {
314
348
  getEventLoopLagMs,
315
349
  isDaemonAlive,
@@ -317,10 +351,13 @@ import {
317
351
  } from "./chunk-7HLWBYH7.js";
318
352
  import {
319
353
  getMasterKey
320
- } from "./chunk-Z42MXYWW.js";
354
+ } from "./chunk-QWVXN224.js";
355
+ import {
356
+ DEFAULT_RUNTIME
357
+ } from "./chunk-NGP6LSV2.js";
321
358
  import {
322
359
  checkForUpdate
323
- } from "./chunk-XQNNB5GY.js";
360
+ } from "./chunk-F55P3H4S.js";
324
361
  import {
325
362
  PLAN_LIMITS,
326
363
  checkLicense,
@@ -331,15 +368,15 @@ import {
331
368
  refreshLicense,
332
369
  saveLicense,
333
370
  validateLicense
334
- } from "./chunk-XACL67CS.js";
371
+ } from "./chunk-PQIDGXSG.js";
335
372
  import {
336
373
  EXE_AI_DIR,
337
374
  loadConfig
338
- } from "./chunk-7Y5UDEVM.js";
375
+ } from "./chunk-WZHZCDDO.js";
339
376
 
340
377
  // src/mcp/register-tools.ts
341
- import { readFileSync as readFileSync8 } from "fs";
342
- import { join as join5 } from "path";
378
+ import { readFileSync as readFileSync7 } from "fs";
379
+ import { join as join4 } from "path";
343
380
  import { homedir as homedir5 } from "os";
344
381
 
345
382
  // src/mcp/tools/memory.ts
@@ -515,7 +552,7 @@ function registerRecallMyMemory(server) {
515
552
  }) => {
516
553
  try {
517
554
  if (!isInitialized()) {
518
- const { fastDbInit: fastDbInit2 } = await import("./fast-db-init-QQB6IVWV.js");
555
+ const { fastDbInit: fastDbInit2 } = await import("./fast-db-init-4CWHSOOR.js");
519
556
  await fastDbInit2();
520
557
  }
521
558
  if (!recent && !query) {
@@ -562,7 +599,7 @@ function registerRecallMyMemory(server) {
562
599
  let federatedCount = 0;
563
600
  if (!recent && query && results.length < FEDERATION_THRESHOLD) {
564
601
  try {
565
- const { searchCodeContextSemantic: searchCodeContextSemantic2 } = await import("./code-context-index-EXXDY3QZ.js");
602
+ const { searchCodeContextSemantic: searchCodeContextSemantic2 } = await import("./code-context-index-WSOJQ72R.js");
566
603
  const codeResults = await Promise.race([
567
604
  searchCodeContextSemantic2(query, { limit: 5 }),
568
605
  new Promise((_, rej) => setTimeout(() => rej(new Error("timeout")), 2e3))
@@ -800,7 +837,7 @@ function registerStoreMemory(server) {
800
837
  }
801
838
  const { agentId, agentRole } = getActiveAgent();
802
839
  if (kind === "prospective") {
803
- const { createProspectiveMemory } = await import("./prospective-memory-W6S67LZZ.js");
840
+ const { createProspectiveMemory } = await import("./prospective-memory-6D2ASWM3.js");
804
841
  let sessionScope = null;
805
842
  try {
806
843
  const { resolveExeSession: resolveExeSession2 } = await import("./lib/tmux-routing.js");
@@ -900,7 +937,7 @@ function registerCommitMemory(server) {
900
937
  project: z4.string().optional().describe("Project name (auto-detected if omitted)"),
901
938
  key_decisions: z4.array(z4.string()).optional().describe("List of key decisions made in this session"),
902
939
  metadata_tags: z4.array(z4.string()).optional().describe("Tags for categorization (e.g., 'architecture', 'bugfix', 'design')"),
903
- topic: z4.string().optional().describe("Topic heading, e.g. 'HYGO Phase 2 architecture decisions'"),
940
+ topic: z4.string().optional().describe("Topic heading, e.g. 'Acme Phase 2 architecture decisions'"),
904
941
  current_state: z4.string().optional().describe("What is true NOW \u2014 snapshot of current system state"),
905
942
  historical_context: z4.string().optional().describe("What led here \u2014 decisions, trade-offs, prior approaches"),
906
943
  importance: z4.number().min(1).max(10).optional().describe("Override importance (default 9)"),
@@ -1066,7 +1103,7 @@ async function searchConversations(query, limit) {
1066
1103
  }
1067
1104
  async function searchWiki(query, limit) {
1068
1105
  try {
1069
- const { createWikiClient, chatInWorkspace, listWorkspaces } = await import("./wiki-client-VNDOBK63.js");
1106
+ const { createWikiClient, chatInWorkspace, listWorkspaces } = await import("./wiki-client-EAN7F5LV.js");
1070
1107
  const client = await createWikiClient();
1071
1108
  if (!client) return [];
1072
1109
  const workspaces = await listWorkspaces(client);
@@ -1462,7 +1499,7 @@ function registerGetMemoryCardinality(server) {
1462
1499
  title: "Get Memory Cardinality",
1463
1500
  description: "Get memory counts: total active memories and per-project breakdown. Optionally filter by agent.",
1464
1501
  inputSchema: {
1465
- agent_id: z9.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'exe')")
1502
+ agent_id: z9.string().optional().describe("Filter to a specific agent (e.g. 'engineer', 'coordinator')")
1466
1503
  }
1467
1504
  },
1468
1505
  async ({ agent_id }) => {
@@ -1786,7 +1823,7 @@ async function handleSupersede(input) {
1786
1823
  }
1787
1824
  try {
1788
1825
  const { getClient: getClient2 } = await import("./lib/database.js");
1789
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
1826
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
1790
1827
  const { writeMemory: writeMemory2, flushBatch: flushBatch2 } = await import("./lib/store.js");
1791
1828
  const { randomUUID: randomUUID2 } = await import("crypto");
1792
1829
  const client = getClient2();
@@ -1839,7 +1876,7 @@ New memory id: ${newId}`
1839
1876
  }
1840
1877
  async function handleResonanceQuery(input) {
1841
1878
  try {
1842
- const { getHotPairs, getCoActivationNeighbors } = await import("./co-activation-XMPHKGHR.js");
1879
+ const { getHotPairs, getCoActivationNeighbors } = await import("./co-activation-ZCHPLLP6.js");
1843
1880
  const subAction = input.resonance_action ?? "hot_pairs";
1844
1881
  const limit = input.limit ?? 20;
1845
1882
  if (subAction === "hot_pairs") {
@@ -1867,7 +1904,7 @@ function registerMemory(server) {
1867
1904
  title: "Memory",
1868
1905
  description: "Consolidated memory domain tool. Actions: recall, ask_team, store, commit, search, session_context, get_by_id, consolidate, cardinality, supersede, decision_store, decision_get, resonance_query. Legacy memory tools remain available during migration.",
1869
1906
  inputSchema: {
1870
- action: z12.enum(["recall", "ask_team", "store", "commit", "search", "session_context", "consolidate", "cardinality", "supersede", "core_get", "core_set", "core_delete", "update_working_memory", "get_working_memory", "decision_store", "decision_get", "resonance_query"]).describe("Memory operation to perform. core_get/core_set/core_delete manage always-in-context key facts. update_working_memory/get_working_memory manage the runtime scratchpad. decision_store/decision_get manage authoritative decisions. resonance_query queries co-activation network."),
1907
+ action: z12.enum(["recall", "ask_team", "store", "commit", "search", "session_context", "get_by_id", "consolidate", "cardinality", "supersede", "core_get", "core_set", "core_delete", "update_working_memory", "get_working_memory", "decision_store", "decision_get", "resonance_query"]).describe("Memory operation to perform. core_get/core_set/core_delete manage always-in-context key facts. update_working_memory/get_working_memory manage the runtime scratchpad. decision_store/decision_get manage authoritative decisions. resonance_query queries co-activation network."),
1871
1908
  query: z12.string().optional().describe("Search query. Also accepted as store text alias."),
1872
1909
  text: z12.string().optional().describe("Memory text for action=store"),
1873
1910
  summary: z12.string().optional().describe("High-importance summary for action=commit"),
@@ -1898,6 +1935,9 @@ function registerMemory(server) {
1898
1935
  session_id: z12.string().optional().describe("Session ID for action=session_context"),
1899
1936
  target_timestamp: z12.string().optional().describe("Center timestamp for action=session_context"),
1900
1937
  window_size: z12.number().optional().describe("Window size for action=session_context"),
1938
+ id: z12.string().optional().describe("Memory UUID for action=get_by_id."),
1939
+ max_chars: z12.coerce.number().int().min(100).max(5e4).optional().describe("Max characters per memory body for action=recall/session_context. Use higher values for long runbooks."),
1940
+ body_chars: z12.coerce.number().int().min(100).max(5e4).optional().describe("Alias for max_chars for action=recall/session_context."),
1901
1941
  max_clusters: z12.coerce.number().optional().describe("Max clusters for action=consolidate"),
1902
1942
  model: z12.string().optional().describe("Model for action=consolidate"),
1903
1943
  agent_id: z12.string().optional().describe("Agent filter for action=cardinality"),
@@ -1934,9 +1974,9 @@ function registerMemory(server) {
1934
1974
  return handleResonanceQuery(input);
1935
1975
  }
1936
1976
  if (action === "update_working_memory" || action === "get_working_memory") {
1937
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
1977
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
1938
1978
  const { agentId } = getActiveAgent2();
1939
- const { readWorkingMemoryWithMeta, writeWorkingMemory, WORKING_MEMORY_MAX_BYTES } = await import("./working-memory-PY4AG577.js");
1979
+ const { readWorkingMemoryWithMeta, writeWorkingMemory, WORKING_MEMORY_MAX_BYTES } = await import("./working-memory-NUVB5SFV.js");
1940
1980
  if (action === "get_working_memory") {
1941
1981
  const wm = readWorkingMemoryWithMeta(agentId);
1942
1982
  if (!wm) {
@@ -1960,9 +2000,9 @@ function registerMemory(server) {
1960
2000
  }
1961
2001
  }
1962
2002
  if (action === "core_get" || action === "core_set" || action === "core_delete") {
1963
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
2003
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
1964
2004
  const { agentId } = getActiveAgent2();
1965
- const { getCoreMemory, setCoreMemory, deleteCoreMemory, formatCoreMemoryBlock } = await import("./core-memory-VO5ZIBKH.js");
2005
+ const { getCoreMemory, setCoreMemory, deleteCoreMemory, formatCoreMemoryBlock } = await import("./core-memory-GAC6EWOQ.js");
1966
2006
  if (action === "core_get") {
1967
2007
  const entries = await getCoreMemory(agentId);
1968
2008
  const block = formatCoreMemoryBlock(entries);
@@ -2014,12 +2054,12 @@ function registerMemory(server) {
2014
2054
  if (!storeTrigger || !storeTriggerAction) {
2015
2055
  return errorResult('memory action "store" with kind="reflex" requires trigger and trigger_action fields');
2016
2056
  }
2017
- const { formatReflexContent, storeReflexBehavior: storeReflexBehavior2 } = await import("./behaviors-HLZUJSMP.js");
2057
+ const { formatReflexContent, storeReflexBehavior: storeReflexBehavior2 } = await import("./behaviors-KYRB3NGJ.js");
2018
2058
  const reflexText = formatReflexContent(storeTrigger, storeTriggerAction);
2019
2059
  legacyArgs.text ??= reflexText;
2020
2060
  legacyArgs.query ??= reflexText;
2021
2061
  try {
2022
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
2062
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
2023
2063
  const { getProjectName: getProjectName2 } = await import("./project-name-EWG5KAZP.js");
2024
2064
  const agent = getActiveAgent2();
2025
2065
  const behaviorId = await storeReflexBehavior2({
@@ -2360,6 +2400,82 @@ function registerGetTask(server) {
2360
2400
  import { z as z15 } from "zod";
2361
2401
  var CLOSE_TASK_ALLOWED_ROLES = /* @__PURE__ */ new Set(["CTO"]);
2362
2402
  var CLOSEABLE_STATUSES = /* @__PURE__ */ new Set(["needs_review", "done"]);
2403
+ async function respawnAssigneeAfterClose(input) {
2404
+ const { resolveExeSession: resolveExeSession2, employeeSessionName, ensureEmployee } = await import("./lib/tmux-routing.js");
2405
+ const { shouldAutoInstance } = await import("./lib/employees.js");
2406
+ const exeSession = input.taskScope ?? resolveExeSession2();
2407
+ if (!exeSession) return { respawned: false, reason: "no coordinator session" };
2408
+ if (!input.projectName) {
2409
+ process.stderr.write(
2410
+ `[close-task] respawn SKIPPED for ${input.assignee}: task has no project_name to resolve \u2014 never respawning into process.cwd().
2411
+ `
2412
+ );
2413
+ return { respawned: false, reason: "task has no project_name" };
2414
+ }
2415
+ const { resolveProjectDir: resolveProjectDir2 } = await import("./mcp/tools/create-task.js");
2416
+ const projectDir = await resolveProjectDir2(input.projectName, exeSession);
2417
+ if (!projectDir) {
2418
+ process.stderr.write(
2419
+ `[close-task] respawn SKIPPED for ${input.assignee}: could not resolve project dir for "${input.projectName}" in scope ${exeSession} \u2014 never respawning into process.cwd(). Manual nudge can follow.
2420
+ `
2421
+ );
2422
+ return { respawned: false, reason: "project dir unresolved" };
2423
+ }
2424
+ const oldSession = employeeSessionName(input.assignee, exeSession);
2425
+ const { execSync } = await import("child_process");
2426
+ try {
2427
+ execSync(`tmux kill-session -t ${oldSession} 2>/dev/null`, { timeout: 3e3 });
2428
+ } catch {
2429
+ }
2430
+ try {
2431
+ const { cleanupAgentWorktree } = await import("./worktree-sweep-WTK3MTKH.js");
2432
+ const { getGitRoot } = await import("./worktree-LL62PLQB.js");
2433
+ const root = getGitRoot(projectDir);
2434
+ if (root) {
2435
+ const notes = await cleanupAgentWorktree(root, input.assignee);
2436
+ if (notes) process.stderr.write(`[close-task] Deferred worktree cleanup: ${notes.replace(/\n/g, "; ")}
2437
+ `);
2438
+ }
2439
+ } catch {
2440
+ }
2441
+ if (!input.topTaskId) {
2442
+ process.stderr.write(
2443
+ `[close-task] Deferred respawn SKIPPED for ${input.assignee} \u2014 no open task id to gate the claim on; auto-wake will cover any orphan
2444
+ `
2445
+ );
2446
+ return { respawned: false, reason: "no open task id to gate the claim on" };
2447
+ }
2448
+ const { tryAcquireDispatchClaim, releaseDispatchClaim } = await import("./dispatch-ack-VYH3ONSS.js");
2449
+ if (!tryAcquireDispatchClaim(input.topTaskId, input.assignee, exeSession)) {
2450
+ process.stderr.write(
2451
+ `[close-task] Deferred respawn DEDUPED for ${input.assignee} task ${input.topTaskId} \u2014 another dispatch is already in flight
2452
+ `
2453
+ );
2454
+ return { respawned: false, reason: "another dispatch holds the claim" };
2455
+ }
2456
+ let result3;
2457
+ try {
2458
+ result3 = ensureEmployee(input.assignee, exeSession, projectDir, shouldAutoInstance(input.assignee));
2459
+ } catch (spawnErr) {
2460
+ try {
2461
+ releaseDispatchClaim(input.topTaskId, input.assignee, "respawn threw");
2462
+ } catch {
2463
+ }
2464
+ throw spawnErr;
2465
+ }
2466
+ if (result3.status === "failed") {
2467
+ try {
2468
+ releaseDispatchClaim(input.topTaskId, input.assignee, result3.error ?? "respawn failed");
2469
+ } catch {
2470
+ }
2471
+ return { respawned: false, reason: result3.error ?? "respawn failed", projectDir };
2472
+ }
2473
+ process.stderr.write(
2474
+ `[close-task] Deferred respawn complete: ${result3.sessionName ?? "fresh instance"} in ${projectDir}
2475
+ `
2476
+ );
2477
+ return { respawned: true, projectDir };
2478
+ }
2363
2479
  function registerCloseTask(server) {
2364
2480
  server.registerTool(
2365
2481
  "close_task",
@@ -2375,7 +2491,7 @@ function registerCloseTask(server) {
2375
2491
  async ({ task_id, result: result3, status: status2 }) => {
2376
2492
  const agent = getActiveAgent();
2377
2493
  try {
2378
- const { StewardGate: StewardGate2 } = await import("./steward-gate-WT7WXQIE.js");
2494
+ const { StewardGate: StewardGate2 } = await import("./steward-gate-3GQ5XKMJ.js");
2379
2495
  const steward = new StewardGate2();
2380
2496
  const gateDecision = await steward.checkAuthority(agent.agentId || "unknown", "close_task", task_id);
2381
2497
  if (!gateDecision.allowed) {
@@ -2556,8 +2672,8 @@ ${preflightWarnings.join("\n")}`;
2556
2672
  if (mergeNote) text5 += mergeNote;
2557
2673
  if (status2 === "closed" && assignee) {
2558
2674
  try {
2559
- const { cleanupAgentWorktree } = await import("./worktree-sweep-ZAG3V24E.js");
2560
- const { getGitRoot } = await import("./worktree-GVF2I5FP.js");
2675
+ const { cleanupAgentWorktree } = await import("./worktree-sweep-WTK3MTKH.js");
2676
+ const { getGitRoot } = await import("./worktree-LL62PLQB.js");
2561
2677
  const repoRoot = getGitRoot(baseDir);
2562
2678
  if (repoRoot) {
2563
2679
  const cleanupNotes = await cleanupAgentWorktree(repoRoot, assignee);
@@ -2585,6 +2701,16 @@ ${preflightWarnings.join("\n")}`;
2585
2701
  });
2586
2702
  const count = Number(remaining.rows[0]?.cnt ?? 0);
2587
2703
  if (count > 0) {
2704
+ let topOpenTaskId;
2705
+ try {
2706
+ const topRes = await client.execute({
2707
+ sql: `SELECT id FROM tasks WHERE assigned_to = ? AND status = 'open' ${respawnScope.sql}
2708
+ ORDER BY CASE priority WHEN 'p0' THEN 0 WHEN 'p1' THEN 1 WHEN 'p2' THEN 2 ELSE 3 END, created_at ASC LIMIT 1`,
2709
+ args: [closedAssignee, ...respawnScope.args]
2710
+ });
2711
+ topOpenTaskId = topRes.rows[0]?.id != null ? String(topRes.rows[0].id) : void 0;
2712
+ } catch {
2713
+ }
2588
2714
  try {
2589
2715
  const { isMultiInstance } = await import("./lib/employees.js");
2590
2716
  if (isMultiInstance(closedAssignee)) {
@@ -2592,37 +2718,14 @@ ${preflightWarnings.join("\n")}`;
2592
2718
 
2593
2719
  \u{1F504} Auto-respawn: ${closedAssignee} has ${count} more task(s). Respawn scheduled (deferred to avoid MCP disruption).`;
2594
2720
  const _assignee = closedAssignee;
2595
- const _baseDir = baseDir;
2596
- setTimeout(async () => {
2597
- try {
2598
- const { resolveExeSession: resolveExeSession2, employeeSessionName, ensureEmployee } = await import("./lib/tmux-routing.js");
2599
- const { shouldAutoInstance } = await import("./lib/employees.js");
2600
- const exeSession = resolveExeSession2();
2601
- if (!exeSession) return;
2602
- const oldSession = employeeSessionName(_assignee, exeSession);
2603
- const { execSync } = await import("child_process");
2604
- try {
2605
- execSync(`tmux kill-session -t ${oldSession} 2>/dev/null`, { timeout: 3e3 });
2606
- } catch {
2607
- }
2608
- try {
2609
- const { cleanupAgentWorktree } = await import("./worktree-sweep-ZAG3V24E.js");
2610
- const { getGitRoot } = await import("./worktree-GVF2I5FP.js");
2611
- const root = getGitRoot(_baseDir);
2612
- if (root) {
2613
- const notes = await cleanupAgentWorktree(root, _assignee);
2614
- if (notes) process.stderr.write(`[close-task] Deferred worktree cleanup: ${notes.replace(/\n/g, "; ")}
2615
- `);
2616
- }
2617
- } catch {
2618
- }
2619
- const result4 = ensureEmployee(_assignee, exeSession, _baseDir, shouldAutoInstance(_assignee));
2620
- process.stderr.write(`[close-task] Deferred respawn complete: ${result4.sessionName ?? "fresh instance"}
2621
- `);
2622
- } catch (e) {
2623
- process.stderr.write(`[close-task] Deferred respawn failed: ${e instanceof Error ? e.message : String(e)}
2624
- `);
2625
- }
2721
+ const _topTaskId = topOpenTaskId ?? null;
2722
+ const _projectName = row.project_name != null ? String(row.project_name) : null;
2723
+ const _taskScope = sanitizeSessionScope(row.session_scope == null ? null : String(row.session_scope));
2724
+ setTimeout(() => {
2725
+ respawnAssigneeAfterClose({ assignee: _assignee, projectName: _projectName, taskScope: _taskScope, topTaskId: _topTaskId }).catch((e) => process.stderr.write(
2726
+ `[close-task] Deferred respawn failed: ${e instanceof Error ? e.message : String(e)}
2727
+ `
2728
+ ));
2626
2729
  }, 500);
2627
2730
  }
2628
2731
  } catch {
@@ -2696,6 +2799,7 @@ function registerCheckpointTask(server) {
2696
2799
 
2697
2800
  // src/mcp/tools/resume-employee.ts
2698
2801
  import { z as z17 } from "zod";
2802
+ import { homedir } from "os";
2699
2803
  var RESUME_CONTEXT_TASK_LIMIT = 10;
2700
2804
  function registerResumeEmployee(server) {
2701
2805
  server.registerTool(
@@ -2710,7 +2814,7 @@ function registerResumeEmployee(server) {
2710
2814
  },
2711
2815
  async ({ agent_id, project_name }) => {
2712
2816
  if (!isInitialized()) {
2713
- const { fastDbInit: fastDbInit2 } = await import("./fast-db-init-QQB6IVWV.js");
2817
+ const { fastDbInit: fastDbInit2 } = await import("./fast-db-init-4CWHSOOR.js");
2714
2818
  await fastDbInit2();
2715
2819
  }
2716
2820
  const client = getClient();
@@ -2736,7 +2840,7 @@ function registerResumeEmployee(server) {
2736
2840
  };
2737
2841
  }
2738
2842
  try {
2739
- const { isTmuxSessionAlive } = await import("./tasks-crud-UGK5A25L.js");
2843
+ const { isTmuxSessionAlive } = await import("./tasks-crud-HBDKE6C5.js");
2740
2844
  const now = (/* @__PURE__ */ new Date()).toISOString();
2741
2845
  for (const row of openTasks.rows) {
2742
2846
  const status2 = String(row.status);
@@ -2764,7 +2868,7 @@ function registerResumeEmployee(server) {
2764
2868
  }
2765
2869
  let checkpointInfo = "";
2766
2870
  try {
2767
- const { readLatestCheckpoint } = await import("./tasks-crud-UGK5A25L.js");
2871
+ const { readLatestCheckpoint } = await import("./tasks-crud-HBDKE6C5.js");
2768
2872
  const checkpoint = await readLatestCheckpoint(agent_id);
2769
2873
  if (checkpoint) {
2770
2874
  const filesTouched = checkpoint.files_touched?.length > 0 ? checkpoint.files_touched.join(", ") : "none";
@@ -2781,9 +2885,18 @@ function registerResumeEmployee(server) {
2781
2885
  }
2782
2886
  } catch {
2783
2887
  }
2888
+ let callerScope;
2889
+ try {
2890
+ const { getAgentContext: getAgentContext2 } = await import("./agent-context-AZTTMUHP.js");
2891
+ const hint = getAgentContext2()?.sessionHint;
2892
+ if (hint) callerScope = hint;
2893
+ } catch {
2894
+ }
2895
+ if (!callerScope) callerScope = process.env.EXE_SESSION_NAME || process.env.EXE_SESSION || void 0;
2896
+ const resumeProjectDir = await resolveProjectDir(project_name, callerScope);
2784
2897
  const { created, taskId } = await createOrRefreshResumeTask(
2785
2898
  agent_id,
2786
- process.cwd(),
2899
+ resumeProjectDir ?? homedir(),
2787
2900
  openTasks.rows
2788
2901
  );
2789
2902
  if (checkpointInfo && taskId) {
@@ -2805,7 +2918,7 @@ function registerResumeEmployee(server) {
2805
2918
  }
2806
2919
  let dispatchStatus = "";
2807
2920
  try {
2808
- const { ensureEmployee, resolveExeSession: resolveExeSession2 } = await import("./lib/tmux-routing.js");
2921
+ const { ensureEmployeeAsync, resolveExeSession: resolveExeSession2 } = await import("./lib/tmux-routing.js");
2809
2922
  let taskScope = null;
2810
2923
  if (taskId) {
2811
2924
  try {
@@ -2821,17 +2934,60 @@ function registerResumeEmployee(server) {
2821
2934
  }
2822
2935
  const exeSession = taskScope ?? resolveExeSession2();
2823
2936
  if (!exeSession) throw new Error("No coordinator session found");
2937
+ if (!resumeProjectDir) {
2938
+ throw new Error(
2939
+ `could not resolve project dir for "${project_name}" within scope \u2014 RESUME task left for manual dispatch`
2940
+ );
2941
+ }
2824
2942
  process.stderr.write(
2825
2943
  `[resume_employee] dispatch lane=${exeSession} source=${taskScope ? "task.session_scope" : "caller.resolveExeSession (task has no scope)"} task=${taskId} agent=${agent_id}
2826
2944
  `
2827
2945
  );
2828
2946
  const { shouldAutoInstance } = await import("./lib/employees.js");
2829
- const result3 = ensureEmployee(agent_id, exeSession, process.cwd(), shouldAutoInstance(agent_id));
2947
+ const { tryAcquireDispatchClaim, releaseDispatchClaim } = await import("./dispatch-ack-VYH3ONSS.js");
2948
+ let claimedResume = false;
2949
+ if (taskId) {
2950
+ claimedResume = tryAcquireDispatchClaim(taskId, agent_id, exeSession);
2951
+ if (!claimedResume) {
2952
+ dispatchStatus = `
2953
+ Dispatched: deduped \u2014 another dispatch for task ${taskId} is already in flight`;
2954
+ process.stderr.write(`[resume_employee] DEDUPED spawn for ${agent_id} task ${taskId} \u2014 a fresh dispatch is already in flight
2955
+ `);
2956
+ throw new Error("dispatch deduped");
2957
+ }
2958
+ }
2959
+ let result3;
2960
+ try {
2961
+ result3 = await ensureEmployeeAsync(
2962
+ agent_id,
2963
+ exeSession,
2964
+ resumeProjectDir,
2965
+ shouldAutoInstance(agent_id)
2966
+ );
2967
+ } catch (spawnErr) {
2968
+ if (taskId && claimedResume) {
2969
+ try {
2970
+ releaseDispatchClaim(taskId, agent_id, "resume spawn threw");
2971
+ } catch {
2972
+ }
2973
+ }
2974
+ throw spawnErr;
2975
+ }
2976
+ if (result3.status === "failed" && taskId && claimedResume) {
2977
+ try {
2978
+ releaseDispatchClaim(taskId, agent_id, result3.error ?? "resume spawn failed");
2979
+ } catch {
2980
+ }
2981
+ }
2830
2982
  switch (result3.status) {
2831
2983
  case "intercom_sent":
2832
2984
  dispatchStatus = `
2833
2985
  Dispatched: intercom sent to ${result3.sessionName}`;
2834
2986
  break;
2987
+ case "intercom_unprocessed":
2988
+ dispatchStatus = `
2989
+ Dispatched: intercom delivered to ${result3.sessionName}`;
2990
+ break;
2835
2991
  case "spawned":
2836
2992
  dispatchStatus = `
2837
2993
  Dispatched: spawned ${result3.sessionName}`;
@@ -3115,6 +3271,8 @@ function registerTask(server) {
3115
3271
  budget_fallback_model: z19.string().optional().describe("Fallback model for action=create"),
3116
3272
  spawn_runtime: z19.string().optional().describe("Override runtime for spawned session (e.g., 'claude', 'codex', 'opencode') for action=create"),
3117
3273
  spawn_model: z19.string().optional().describe("Override model for spawned session (e.g., 'claude-sonnet-4.6') for action=create"),
3274
+ idempotency_key: z19.string().optional().describe("Idempotency key for action=create (bug c06a8803): retrying with the SAME key returns the ORIGINAL task instead of creating a duplicate + duplicate spawn. Must be stable across the original call and its retry \u2014 no timestamp. Optional; omitted = no dedup."),
3275
+ idempotency_window: z19.string().optional().describe("Optional nonce to DERIVE an idempotency key for action=create when idempotency_key is not given. Reuse the same window on a retry to dedup."),
3118
3276
  status: z19.enum(["open", "in_progress", "done", "needs_review", "blocked", "cancelled", "closed"]).optional().describe("Status for action=update/list/close"),
3119
3277
  result: z19.string().optional().describe("Result summary for action=update or action=close"),
3120
3278
  step: z19.string().optional().describe("Checkpoint step for action=checkpoint"),
@@ -3129,6 +3287,7 @@ function registerTask(server) {
3129
3287
  // Reminder params (absorbed from standalone reminder tool)
3130
3288
  text: z19.string().optional().describe("Reminder text for action=reminder_create"),
3131
3289
  due_date: z19.string().optional().describe("Optional due date \u2014 ISO date (2026-04-01) or null for persistent (reminder_create)"),
3290
+ daily_push: z19.string().optional().describe('Optional daily push schedule for action=reminder_create \u2014 JSON {"hours":[9,18]} (0\u201323, founder timezone). A gateway channel pushes this reminder at those hours. Omit for a normal boot-brief-only reminder.'),
3132
3291
  reminder_id: z19.string().optional().describe("Reminder UUID or text substring to match (reminder_complete)"),
3133
3292
  include_completed: z19.boolean().optional().describe("Include completed reminders (reminder_list). Default: false.")
3134
3293
  }
@@ -3139,9 +3298,15 @@ function registerTask(server) {
3139
3298
  const args = input;
3140
3299
  const reminderText = args.text;
3141
3300
  if (!reminderText) return errorResult2('task action "reminder_create" requires text');
3142
- const reminder = await createReminder(reminderText, args.due_date);
3301
+ let reminder;
3302
+ try {
3303
+ reminder = await createReminder(reminderText, args.due_date, args.daily_push);
3304
+ } catch (err) {
3305
+ return errorResult2(err instanceof Error ? err.message : String(err));
3306
+ }
3143
3307
  const dueStr = reminder.dueDate ? ` (due: ${reminder.dueDate})` : "";
3144
- return { content: [{ type: "text", text: `Reminder set: "${reminder.text}"${dueStr}` }] };
3308
+ const pushStr = reminder.dailyPush ? ` (daily push: ${reminder.dailyPush})` : "";
3309
+ return { content: [{ type: "text", text: `Reminder set: "${reminder.text}"${dueStr}${pushStr}` }] };
3145
3310
  }
3146
3311
  if (action === "reminder_list") {
3147
3312
  const args = input;
@@ -3149,8 +3314,9 @@ function registerTask(server) {
3149
3314
  if (reminders.length === 0) return { content: [{ type: "text", text: "No active reminders." }] };
3150
3315
  const lines = reminders.map((r) => {
3151
3316
  const due = r.dueDate ? ` (due: ${r.dueDate})` : "";
3317
+ const push = r.dailyPush ? ` (daily push: ${r.dailyPush})` : "";
3152
3318
  const done = r.completedAt ? " [DONE]" : "";
3153
- return `\u2022 ${r.text}${due}${done} [id: ${r.id.slice(0, 8)}]`;
3319
+ return `\u2022 ${r.text}${due}${push}${done} [id: ${r.id.slice(0, 8)}]`;
3154
3320
  });
3155
3321
  return { content: [{ type: "text", text: lines.join("\n") }] };
3156
3322
  }
@@ -3166,7 +3332,7 @@ function registerTask(server) {
3166
3332
  const taskId = input.task_id;
3167
3333
  if (!taskId) return errorResult2("verify_dispatch requires task_id");
3168
3334
  try {
3169
- const { checkDispatchStatus } = await import("./dispatch-ack-4S44HBWB.js");
3335
+ const { checkDispatchStatus } = await import("./dispatch-ack-VYH3ONSS.js");
3170
3336
  const result4 = checkDispatchStatus(taskId);
3171
3337
  return {
3172
3338
  content: [{ type: "text", text: JSON.stringify(result4, null, 2) }]
@@ -3180,7 +3346,7 @@ function registerTask(server) {
3180
3346
  const missing2 = missingRequiredFields2(args, REQUIRED_FIELDS2.create_group);
3181
3347
  if (missing2.length > 0) return errorResult2(`task action "create_group" missing required field(s): ${missing2.join(", ")}`);
3182
3348
  try {
3183
- const { createTaskGroup } = await import("./tasks-crud-UGK5A25L.js");
3349
+ const { createTaskGroup } = await import("./tasks-crud-HBDKE6C5.js");
3184
3350
  const group = await createTaskGroup({
3185
3351
  title: args.title,
3186
3352
  coordinator: args.coordinator,
@@ -3199,7 +3365,7 @@ function registerTask(server) {
3199
3365
  const missing2 = missingRequiredFields2(args, REQUIRED_FIELDS2.group_status);
3200
3366
  if (missing2.length > 0) return errorResult2(`task action "group_status" missing required field(s): ${missing2.join(", ")}`);
3201
3367
  try {
3202
- const { getGroupStatus } = await import("./tasks-crud-UGK5A25L.js");
3368
+ const { getGroupStatus } = await import("./tasks-crud-HBDKE6C5.js");
3203
3369
  const status2 = await getGroupStatus(args.group_id);
3204
3370
  return { content: [{ type: "text", text: JSON.stringify(status2, null, 2) }] };
3205
3371
  } catch (err) {
@@ -3211,7 +3377,7 @@ function registerTask(server) {
3211
3377
  const missing2 = missingRequiredFields2(args, REQUIRED_FIELDS2.group_results);
3212
3378
  if (missing2.length > 0) return errorResult2(`task action "group_results" missing required field(s): ${missing2.join(", ")}`);
3213
3379
  try {
3214
- const { getGroupResults } = await import("./tasks-crud-UGK5A25L.js");
3380
+ const { getGroupResults } = await import("./tasks-crud-HBDKE6C5.js");
3215
3381
  const results = await getGroupResults(args.group_id);
3216
3382
  return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
3217
3383
  } catch (err) {
@@ -3462,7 +3628,7 @@ function registerMessage(server) {
3462
3628
  if (msgType && msgPayload) {
3463
3629
  try {
3464
3630
  const { buildTypedMessage, serializeMessage } = await import("./typed-messages-TKDGVPHS.js");
3465
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
3631
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
3466
3632
  const { sendMessage } = await import("./lib/messaging.js");
3467
3633
  const { agentId } = getActiveAgent2();
3468
3634
  const envelope = buildTypedMessage({
@@ -3496,9 +3662,11 @@ ID: ${msg.id}`
3496
3662
  if (action === "read") {
3497
3663
  try {
3498
3664
  const { getPendingMessages } = await import("./lib/messaging.js");
3499
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
3665
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
3666
+ const { resolveExeSession: resolveExeSession2 } = await import("./lib/tmux-routing.js");
3500
3667
  const { agentId } = getActiveAgent2();
3501
- const messages = await getPendingMessages(agentId);
3668
+ const callerScope = resolveExeSession2() ?? void 0;
3669
+ const messages = await getPendingMessages(agentId, callerScope);
3502
3670
  if (messages.length === 0) {
3503
3671
  return {
3504
3672
  content: [{ type: "text", text: `No pending messages for ${agentId}.` }]
@@ -3859,8 +4027,8 @@ function registerIngestDocument(server) {
3859
4027
  },
3860
4028
  async (input) => {
3861
4029
  try {
3862
- const { assertFeature: assertFeature2 } = await import("./plan-limits-GRNBOBB3.js");
3863
- const { assertMemoryLimit: assertMemoryLimit2 } = await import("./plan-limits-GRNBOBB3.js");
4030
+ const { assertFeature: assertFeature2 } = await import("./plan-limits-2FEY2GOS.js");
4031
+ const { assertMemoryLimit: assertMemoryLimit2 } = await import("./plan-limits-2FEY2GOS.js");
3864
4032
  await assertFeature2("wiki");
3865
4033
  await assertMemoryLimit2();
3866
4034
  const result3 = await ingestDocument(input);
@@ -3931,8 +4099,8 @@ function registerPurgeDocument(server) {
3931
4099
  },
3932
4100
  async ({ document_id }) => {
3933
4101
  try {
3934
- const { StewardGate: StewardGate2 } = await import("./steward-gate-WT7WXQIE.js");
3935
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
4102
+ const { StewardGate: StewardGate2 } = await import("./steward-gate-3GQ5XKMJ.js");
4103
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
3936
4104
  const steward = new StewardGate2();
3937
4105
  const agent = getActiveAgent2();
3938
4106
  const gateDecision = await steward.checkAuthority(agent.agentId || "unknown", "purge_document", document_id);
@@ -4102,7 +4270,7 @@ function registerDocument(server) {
4102
4270
  const { action: _action, ...legacyArgs } = input;
4103
4271
  if (action === "list" && (legacyArgs.workspace_id === void 0 || legacyArgs.workspace_id === null || legacyArgs.workspace_id === "")) {
4104
4272
  try {
4105
- const { resolveDefaultWorkspaceId, listWorkspaces } = await import("./documents-FHIBU7KJ.js");
4273
+ const { resolveDefaultWorkspaceId, listWorkspaces } = await import("./documents-23WX2FPQ.js");
4106
4274
  const defaultId = await resolveDefaultWorkspaceId();
4107
4275
  if (defaultId) {
4108
4276
  legacyArgs.workspace_id = defaultId;
@@ -4140,14 +4308,14 @@ ${lines.join("\n")}`
4140
4308
 
4141
4309
  // src/mcp/tools/gateway.ts
4142
4310
  import { z as z40 } from "zod";
4143
- import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3, mkdirSync } from "fs";
4311
+ import { chmodSync, existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3, mkdirSync } from "fs";
4144
4312
  import { join as join2 } from "path";
4145
- import { homedir as homedir2 } from "os";
4313
+ import { homedir as homedir3 } from "os";
4146
4314
 
4147
4315
  // src/mcp/tools/send-whatsapp.ts
4148
4316
  import { z as z33 } from "zod";
4149
4317
  import { existsSync, readFileSync } from "fs";
4150
- import { homedir } from "os";
4318
+ import { homedir as homedir2 } from "os";
4151
4319
  import { join } from "path";
4152
4320
  var GRAPH_API_VERSION = "v21.0";
4153
4321
  var GRAPH_API_BASE = `https://graph.facebook.com/${GRAPH_API_VERSION}`;
@@ -4203,7 +4371,7 @@ function normalizeGatewaySendUrl(value) {
4203
4371
  return `${raw}/api/send`;
4204
4372
  }
4205
4373
  function loadGatewayJson() {
4206
- const configPath = process.env.EXE_GATEWAY_CONFIG?.trim() || process.env.EXE_GATEWAY_CONFIG_PATH?.trim() || join(homedir(), ".exe-os", "gateway.json");
4374
+ const configPath = process.env.EXE_GATEWAY_CONFIG?.trim() || process.env.EXE_GATEWAY_CONFIG_PATH?.trim() || join(homedir2(), ".exe-os", "gateway.json");
4207
4375
  if (!existsSync(configPath)) return {};
4208
4376
  try {
4209
4377
  return JSON.parse(readFileSync(configPath, "utf8"));
@@ -4772,12 +4940,12 @@ async function validateGoTrueToken(token, gotrueUrl) {
4772
4940
  }
4773
4941
  async function getGoTrueUser(userId, gotrueUrl) {
4774
4942
  const url = gotrueUrl ?? process.env.GOTRUE_URL ?? process.env.EXE_GOTRUE_URL;
4775
- const adminToken2 = process.env.GOTRUE_ADMIN_TOKEN ?? process.env.EXE_GOTRUE_ADMIN_TOKEN;
4776
- if (!url || !adminToken2) return null;
4943
+ const adminToken = process.env.GOTRUE_ADMIN_TOKEN ?? process.env.EXE_GOTRUE_ADMIN_TOKEN;
4944
+ if (!url || !adminToken) return null;
4777
4945
  try {
4778
4946
  const res = await fetch(`${url}/admin/users/${userId}`, {
4779
4947
  headers: {
4780
- Authorization: `Bearer ${adminToken2}`,
4948
+ Authorization: `Bearer ${adminToken}`,
4781
4949
  "Content-Type": "application/json"
4782
4950
  },
4783
4951
  signal: AbortSignal.timeout(GOTRUE_TIMEOUT_MS)
@@ -5129,7 +5297,7 @@ async function handleTrigger(limit) {
5129
5297
  if (rows.rows.length === 0) {
5130
5298
  return text3("No conversations found to re-process.");
5131
5299
  }
5132
- const { ingest } = await import("./pipeline-router-O6HU7DKH.js");
5300
+ const { ingest } = await import("./pipeline-router-LM53NMWJ.js");
5133
5301
  const results = [];
5134
5302
  for (const row of rows.rows) {
5135
5303
  const r = row;
@@ -5221,7 +5389,7 @@ function registerPipeline(server) {
5221
5389
  }
5222
5390
 
5223
5391
  // src/mcp/tools/gateway.ts
5224
- var GATEWAY_CONFIG_PATH = join2(homedir2(), ".exe-os", "gateway.json");
5392
+ var GATEWAY_CONFIG_PATH = join2(homedir3(), ".exe-os", "gateway.json");
5225
5393
  function okResult(text5) {
5226
5394
  return { content: [{ type: "text", text: text5 }] };
5227
5395
  }
@@ -5251,9 +5419,17 @@ function loadGatewayConfig() {
5251
5419
  return {};
5252
5420
  }
5253
5421
  function saveGatewayConfig(config) {
5254
- const dir = join2(homedir2(), ".exe-os");
5255
- mkdirSync(dir, { recursive: true });
5256
- writeFileSync3(GATEWAY_CONFIG_PATH, JSON.stringify(config, null, 2), "utf8");
5422
+ const dir = join2(homedir3(), ".exe-os");
5423
+ mkdirSync(dir, { recursive: true, mode: 448 });
5424
+ try {
5425
+ chmodSync(dir, 448);
5426
+ } catch {
5427
+ }
5428
+ writeFileSync3(GATEWAY_CONFIG_PATH, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
5429
+ try {
5430
+ chmodSync(GATEWAY_CONFIG_PATH, 384);
5431
+ } catch {
5432
+ }
5257
5433
  }
5258
5434
  function registerGateway(server) {
5259
5435
  const legacy = buildHandlers3();
@@ -5311,7 +5487,7 @@ function registerGateway(server) {
5311
5487
  'gateway action "configure_whatsapp" requires phone_number_id, access_token, and verify_token'
5312
5488
  );
5313
5489
  }
5314
- const { configureWhatsApp } = await import("./whatsapp-config-GOSELKTE.js");
5490
+ const { configureWhatsApp } = await import("./whatsapp-config-FAX6EA5K.js");
5315
5491
  const result3 = await configureWhatsApp({
5316
5492
  phoneNumberId,
5317
5493
  accessToken,
@@ -5332,7 +5508,7 @@ Phone: ${result3.phoneDisplay ?? "verified"}
5332
5508
  );
5333
5509
  }
5334
5510
  if (action === "whatsapp_status") {
5335
- const { getWhatsAppStatus } = await import("./whatsapp-config-GOSELKTE.js");
5511
+ const { getWhatsAppStatus } = await import("./whatsapp-config-FAX6EA5K.js");
5336
5512
  const status2 = getWhatsAppStatus();
5337
5513
  if (!status2.connected) {
5338
5514
  return okResult(
@@ -5371,6 +5547,7 @@ Accounts: ${status2.accounts}
5371
5547
  adapterConfig.accounts = accounts;
5372
5548
  config.adapters = adapters;
5373
5549
  saveGatewayConfig(config);
5550
+ _resetCache();
5374
5551
  return okResult(
5375
5552
  `Account "${accountName}" added to ${accountPlatform} in gateway.json.
5376
5553
  Note: Restart the gateway process for changes to take effect.`
@@ -5399,6 +5576,7 @@ Note: Restart the gateway process for changes to take effect.`
5399
5576
  }
5400
5577
  config.adapters = adapters;
5401
5578
  saveGatewayConfig(config);
5579
+ _resetCache();
5402
5580
  return okResult(
5403
5581
  `Account "${accountName}" removed from gateway.json.
5404
5582
  Note: Restart the gateway process for changes to take effect.`
@@ -5760,8 +5938,8 @@ function registerMergeEntities(server) {
5760
5938
  },
5761
5939
  async ({ source_name, source_type, target_name, target_type }) => {
5762
5940
  try {
5763
- const { StewardGate: StewardGate2 } = await import("./steward-gate-WT7WXQIE.js");
5764
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
5941
+ const { StewardGate: StewardGate2 } = await import("./steward-gate-3GQ5XKMJ.js");
5942
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
5765
5943
  const steward = new StewardGate2();
5766
5944
  const agent = getActiveAgent2();
5767
5945
  const gateDecision = await steward.checkAuthority(agent.agentId || "unknown", "merge_entities", `${source_name}\u2192${target_name}`);
@@ -5969,7 +6147,7 @@ async function handleExtractFromDocument(args) {
5969
6147
  return errorResult7('graph action "extract_from_document" requires document_id');
5970
6148
  }
5971
6149
  try {
5972
- const { extractGraphFromExistingDocument } = await import("./doc-graph-extractor-3TRLGD7M.js");
6150
+ const { extractGraphFromExistingDocument } = await import("./doc-graph-extractor-F6ODFIID.js");
5973
6151
  const result3 = await extractGraphFromExistingDocument(documentId);
5974
6152
  const lines = [
5975
6153
  `## Graph Extraction for Document ${documentId}`,
@@ -5996,7 +6174,7 @@ async function handleCleanupGarbage(args) {
5996
6174
  const doMerge = !garbageOnly;
5997
6175
  let mod;
5998
6176
  try {
5999
- mod = await import("./cleanup-graph-garbage-KUABW6LS.js");
6177
+ mod = await import("./cleanup-graph-garbage-XWUFAMFO.js");
6000
6178
  } catch (err) {
6001
6179
  return errorResult7(`cleanup_garbage: failed to load cleanup module \u2014 ${err instanceof Error ? err.message : String(err)}`);
6002
6180
  }
@@ -6150,7 +6328,7 @@ function registerSetAgentConfig(server) {
6150
6328
  inputSchema: {
6151
6329
  agent_id: z48.string().optional().describe("Agent name, or 'default' for org-wide default. Omit to view all agents."),
6152
6330
  runtime: z48.string().optional().describe(`Runtime: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`),
6153
- model: z48.string().optional().describe("Model name (e.g. claude-opus-4, gpt-5.4, anthropic/claude-sonnet-4-6)"),
6331
+ model: z48.string().optional().describe("Model name (e.g. claude-opus-4, gpt-5.5, anthropic/claude-sonnet-4-6). Codex model availability depends on auth type (ChatGPT account vs OpenAI API key); gpt-5.5 is the verified-usable Codex default."),
6154
6332
  reasoning_effort: z48.string().optional().describe("Codex reasoning effort: low, medium, high, xhigh. Per-agent override for thinking/reasoning depth."),
6155
6333
  mcps: z48.array(z48.string()).optional().describe("MCP server allowlist. Only these servers load for this agent. exe-os always included. Omit to load all MCPs.")
6156
6334
  }
@@ -6358,7 +6536,7 @@ function registerGetAgentSpend(server) {
6358
6536
  description: "Get per-agent token spend attribution. Shows input, output, and cache tokens consumed by each agent over a time period, with estimated cost.",
6359
6537
  inputSchema: {
6360
6538
  period: z50.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to query"),
6361
- agent_id: z50.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'yoshi')")
6539
+ agent_id: z50.string().optional().describe("Filter to a specific agent (e.g. 'engineer', 'architect')")
6362
6540
  }
6363
6541
  },
6364
6542
  async ({ period, agent_id }) => {
@@ -6876,7 +7054,7 @@ async function getAgentSessionLoad() {
6876
7054
  return { sessions: [], totalLive: 0, busySessions: 0, idleSessions: 0 };
6877
7055
  }
6878
7056
  const { getClient: getClient2 } = await import("./lib/database.js");
6879
- const { sessionScopeFilter: sessionScopeFilter2 } = await import("./task-scope-CQEG5SSJ.js");
7057
+ const { sessionScopeFilter: sessionScopeFilter2 } = await import("./task-scope-FOIW25HR.js");
6880
7058
  const client = getClient2();
6881
7059
  const scope = sessionScopeFilter2();
6882
7060
  for (const s of liveAgentSessions) {
@@ -6975,27 +7153,40 @@ function registerRunMemoryAudit(server) {
6975
7153
  agent_id: z57.string().optional().describe("Filter audit to a specific agent"),
6976
7154
  project_name: z57.string().optional().describe("Filter audit to a specific project"),
6977
7155
  fix: z57.boolean().optional().default(false).describe("Apply fixes: delete duplicates, chunk bloated records, rebuild FTS, archive shards"),
6978
- dry_run: z57.boolean().optional().default(false).describe("Preview fixes without applying them")
7156
+ dry_run: z57.boolean().optional().default(false).describe("Preview fixes without applying them"),
7157
+ bounded: z57.boolean().optional().default(true).describe("Cap expensive scans so large memory DBs return promptly. Set false for full CLI-equivalent audit."),
7158
+ duplicate_group_limit: z57.number().int().positive().max(500).optional().describe("Bounded mode: maximum duplicate candidate buckets to inspect"),
7159
+ duplicate_member_limit: z57.number().int().positive().max(1e4).optional().describe("Bounded mode: maximum rows to inspect inside each duplicate candidate bucket")
6979
7160
  }
6980
7161
  },
6981
- async ({ agent_id, project_name, fix, dry_run }) => {
7162
+ async ({ agent_id, project_name, fix, dry_run, bounded, duplicate_group_limit, duplicate_member_limit }) => {
6982
7163
  try {
6983
7164
  const client = getClient();
6984
7165
  const shouldFix = fix === true;
6985
7166
  const isDryRun = dry_run === true;
7167
+ const boundedAudit = bounded !== false;
6986
7168
  const flags = {
6987
7169
  fix: shouldFix,
6988
7170
  dryRun: isDryRun,
6989
- verbose: true,
7171
+ verbose: !boundedAudit,
6990
7172
  conflicts: false,
6991
7173
  // O(n²) — opt-in only via CLI --conflicts
6992
7174
  restarts: false,
6993
7175
  // daemon restart report is a separate CLI mode
6994
7176
  agent: agent_id,
6995
- project: project_name
7177
+ project: project_name,
7178
+ bounded: boundedAudit,
7179
+ duplicateGroupLimit: duplicate_group_limit,
7180
+ duplicateMemberLimit: duplicate_member_limit,
7181
+ deleteLocalSecretResidue: false
6996
7182
  };
6997
7183
  const report = await runAudit(client, flags);
6998
7184
  let formatted = formatReport(report, flags);
7185
+ if (boundedAudit) {
7186
+ formatted += `
7187
+
7188
+ Bounded MCP mode: duplicate scan is capped (${duplicate_group_limit ?? 25} bucket(s), ${duplicate_member_limit ?? 250} row(s)/bucket). Set bounded=false for a full audit or run \`exe-os doctor --verbose\` locally.`;
7189
+ }
6999
7190
  if (shouldFix || isDryRun) {
7000
7191
  const mode = isDryRun ? "[dry-run]" : "[fix]";
7001
7192
  const fixLog = [`
@@ -7003,7 +7194,7 @@ ${mode} Applying repairs...
7003
7194
  `];
7004
7195
  if (!isDryRun) {
7005
7196
  try {
7006
- const { createBackup: createBackup2 } = await import("./db-backup-DLD4QZBO.js");
7197
+ const { createBackup: createBackup2 } = await import("./db-backup-W2QFSYQC.js");
7007
7198
  const backupPath = await createBackup2("pre-fix");
7008
7199
  if (backupPath) {
7009
7200
  fixLog.push(` Backup created: ${backupPath.split("/").pop()}`);
@@ -7242,7 +7433,7 @@ async function cloudStatusText() {
7242
7433
  if (lastReuploadedAt) lines.push(`- Last re-upload: ${lastReuploadedAt}`);
7243
7434
  lines.push("");
7244
7435
  try {
7245
- const { getRetrievalHealth: getRetrievalHealth2, formatDegradations: formatDegradations2 } = await import("./retrieval-health-TWHKYCRK.js");
7436
+ const { getRetrievalHealth: getRetrievalHealth2, formatDegradations: formatDegradations2 } = await import("./retrieval-health-4Z242P3B.js");
7246
7437
  const h = await getRetrievalHealth2();
7247
7438
  lines.push(formatDegradations2(h.degradations, "Health / Degradations"));
7248
7439
  lines.push("");
@@ -8611,11 +8802,11 @@ async function sendSetPlan(payload) {
8611
8802
  }
8612
8803
  const config = await loadConfig();
8613
8804
  const routerUrl = process.env.API_ROUTER_URL?.replace(/\/+$/, "");
8614
- const endpoint2 = process.env.EXE_SET_CUSTOMER_PLAN_ENDPOINT || (routerUrl ? `${routerUrl}/admin/customer/plan` : "https://api.askexe.com/admin/customer/plan");
8805
+ const endpoint = process.env.EXE_SET_CUSTOMER_PLAN_ENDPOINT || (routerUrl ? `${routerUrl}/admin/customer/plan` : "https://api.askexe.com/admin/customer/plan");
8615
8806
  const licenseKey = loadLicense() || process.env.EXE_LICENSE_KEY || config.cloud?.apiKey;
8616
8807
  const licenseToken = readCachedLicenseToken();
8617
8808
  try {
8618
- const parsed = new URL(endpoint2);
8809
+ const parsed = new URL(endpoint);
8619
8810
  if (parsed.protocol !== "https:" && !["localhost", "127.0.0.1", "::1"].includes(parsed.hostname)) {
8620
8811
  return { status: "failed: insecure endpoint rejected" };
8621
8812
  }
@@ -8737,7 +8928,7 @@ function registerCreateTrigger(server) {
8737
8928
  }
8738
8929
  },
8739
8930
  async ({ name, event, conditions, actions, project, enabled, schedule, query }) => {
8740
- const { assertFeature: assertFeature2 } = await import("./plan-limits-GRNBOBB3.js");
8931
+ const { assertFeature: assertFeature2 } = await import("./plan-limits-2FEY2GOS.js");
8741
8932
  const gatedActions = {
8742
8933
  send_whatsapp: "external_agents",
8743
8934
  update_wiki: "wiki"
@@ -9196,8 +9387,8 @@ ${err.message}`
9196
9387
  import { z as z72 } from "zod";
9197
9388
  import { readFileSync as readFileSync4, readdirSync as readdirSync3, statSync } from "fs";
9198
9389
  import path10 from "path";
9199
- import { homedir as homedir3 } from "os";
9200
- var SKILLS_DIR = path10.join(homedir3(), ".claude", "skills");
9390
+ import { homedir as homedir4 } from "os";
9391
+ var SKILLS_DIR = path10.join(homedir4(), ".claude", "skills");
9201
9392
  function listAvailableSkills() {
9202
9393
  try {
9203
9394
  const entries = readdirSync3(SKILLS_DIR);
@@ -9707,8 +9898,8 @@ function buildHandlers5() {
9707
9898
  }
9708
9899
  async function handleDreaming(action, args) {
9709
9900
  try {
9710
- const { DreamingEngine: DreamingEngine2 } = await import("./dreaming-OMFUEUCQ.js");
9711
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
9901
+ const { DreamingEngine: DreamingEngine2 } = await import("./dreaming-NWD22UQ5.js");
9902
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
9712
9903
  const { getClient: getClient2 } = await import("./lib/database.js");
9713
9904
  const agentId = args.agent_id ?? getActiveAgent2().agentId;
9714
9905
  if (action === "dreaming_run") {
@@ -9866,8 +10057,8 @@ function registerConfig(server) {
9866
10057
  }
9867
10058
  if (action === "closeout") {
9868
10059
  try {
9869
- const { DreamingEngine: DreamingEngine2 } = await import("./dreaming-OMFUEUCQ.js");
9870
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
10060
+ const { DreamingEngine: DreamingEngine2 } = await import("./dreaming-NWD22UQ5.js");
10061
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
9871
10062
  const { writeMemory: writeMemory2, flushBatch: flushBatch2 } = await import("./lib/store.js");
9872
10063
  const { randomUUID: randomUUID2 } = await import("crypto");
9873
10064
  const { getProjectName: getProjectName2 } = await import("./project-name-EWG5KAZP.js");
@@ -9938,7 +10129,7 @@ function registerConfig(server) {
9938
10129
  }
9939
10130
  if (action === "capability_cards") {
9940
10131
  try {
9941
- const { getAllCapabilityCards, findAgentForTask } = await import("./capability-cards-YOKVMMOL.js");
10132
+ const { getAllCapabilityCards, findAgentForTask } = await import("./capability-cards-DN5UIKVN.js");
9942
10133
  const cards = getAllCapabilityCards();
9943
10134
  const taskQuery = args.query;
9944
10135
  if (taskQuery) {
@@ -9989,7 +10180,7 @@ function registerConfig(server) {
9989
10180
  const existing = loadEmployeesSync2();
9990
10181
  if (existing.some((e) => e.name === employeeName)) return errorResult8(`Employee "${employeeName}" already exists.`);
9991
10182
  try {
9992
- const { assertEmployeeLimit: assertEmployeeLimit2 } = await import("./plan-limits-GRNBOBB3.js");
10183
+ const { assertEmployeeLimit: assertEmployeeLimit2 } = await import("./plan-limits-2FEY2GOS.js");
9993
10184
  await assertEmployeeLimit2();
9994
10185
  } catch (e) {
9995
10186
  return errorResult8(e instanceof Error ? e.message : "Employee limit reached.");
@@ -10030,7 +10221,7 @@ You are ${employeeName}. Role: ${role}.`, "utf-8");
10030
10221
  }
10031
10222
  try {
10032
10223
  const { generateSessionWrappers } = await import("./lib/session-wrappers.js");
10033
- const { resolvePackageRoot } = await import("./installer-MNPXDLGG.js");
10224
+ const { resolvePackageRoot } = await import("./installer-L7EVH5U5.js");
10034
10225
  generateSessionWrappers(resolvePackageRoot());
10035
10226
  } catch {
10036
10227
  }
@@ -10117,7 +10308,7 @@ function registerListWikiPages(server) {
10117
10308
  }
10118
10309
  },
10119
10310
  async ({ workspace, folder }) => {
10120
- const { assertFeature: assertFeature2 } = await import("./plan-limits-GRNBOBB3.js");
10311
+ const { assertFeature: assertFeature2 } = await import("./plan-limits-2FEY2GOS.js");
10121
10312
  await assertFeature2("wiki");
10122
10313
  const apiUrl = process.env.EXE_WIKI_API_URL;
10123
10314
  const apiKey = process.env.EXE_WIKI_API_KEY;
@@ -10217,7 +10408,7 @@ function registerGetWikiPage(server) {
10217
10408
  }
10218
10409
  },
10219
10410
  async ({ workspace, document_id, title }) => {
10220
- const { assertFeature: assertFeature2 } = await import("./plan-limits-GRNBOBB3.js");
10411
+ const { assertFeature: assertFeature2 } = await import("./plan-limits-2FEY2GOS.js");
10221
10412
  await assertFeature2("wiki");
10222
10413
  const apiUrl = process.env.EXE_WIKI_API_URL;
10223
10414
  const apiKey = process.env.EXE_WIKI_API_KEY;
@@ -10411,10 +10602,10 @@ async function handleWikiSearch(input) {
10411
10602
  const userId = input.user_id;
10412
10603
  if (!workspace) return errorResult9('wiki action "search" requires workspace');
10413
10604
  if (!query) return errorResult9('wiki action "search" requires query');
10414
- const { assertFeature: assertFeature2 } = await import("./plan-limits-GRNBOBB3.js");
10605
+ const { assertFeature: assertFeature2 } = await import("./plan-limits-2FEY2GOS.js");
10415
10606
  await assertFeature2("wiki");
10416
10607
  if (userId) {
10417
- const { checkWikiAccess } = await import("./wiki-acl-JA5UCQZ4.js");
10608
+ const { checkWikiAccess } = await import("./wiki-acl-74BLWG6J.js");
10418
10609
  const { allowed } = await checkWikiAccess(String(userId), String(workspace), "read");
10419
10610
  if (!allowed) {
10420
10611
  return errorResult9(`Access denied: user "${userId}" does not have read access to workspace "${workspace}"`);
@@ -10517,7 +10708,7 @@ function registerWiki(server) {
10517
10708
  return errorResult9('wiki action "document_rerank" requires at least one candidate');
10518
10709
  }
10519
10710
  if (user_id && legacyArgs.workspace) {
10520
- const { checkWikiAccess } = await import("./wiki-acl-JA5UCQZ4.js");
10711
+ const { checkWikiAccess } = await import("./wiki-acl-74BLWG6J.js");
10521
10712
  const { allowed } = await checkWikiAccess(
10522
10713
  String(user_id),
10523
10714
  String(legacyArgs.workspace),
@@ -10698,12 +10889,22 @@ ${lines.join("\n")}`
10698
10889
  };
10699
10890
  }
10700
10891
  const caller2 = getActiveAgent();
10701
- const roster = loadEmployeesSync();
10892
+ const rosterState = loadEmployeesState();
10893
+ const roster = rosterState.employees;
10702
10894
  const rawAgent = agent_id ?? caller2.agentId;
10703
10895
  const resolvedAgent = baseAgentName(rawAgent, roster);
10704
10896
  const callerBase = baseAgentName(caller2.agentId, roster);
10705
10897
  const isCrossAgentWrite = resolvedAgent !== callerBase;
10706
10898
  if (isCrossAgentWrite) {
10899
+ if (rosterState.status === "error") {
10900
+ return {
10901
+ content: [{
10902
+ type: "text",
10903
+ text: `Permission denied: the employee roster is unreadable or corrupt, so the chain of command cannot be verified. Cross-agent behavior writes are blocked until the roster (exe-employees.json) is repaired.`
10904
+ }],
10905
+ isError: true
10906
+ };
10907
+ }
10707
10908
  const allowed2 = canManage(callerBase, caller2.agentRole, resolvedAgent, roster);
10708
10909
  if (!allowed2) {
10709
10910
  return {
@@ -10838,7 +11039,7 @@ Use /exe-forget to remove any that this supersedes.`;
10838
11039
  }]
10839
11040
  };
10840
11041
  }
10841
- const { bulkPurgeGhostBehaviors } = await import("./behaviors-HLZUJSMP.js");
11042
+ const { bulkPurgeGhostBehaviors } = await import("./behaviors-KYRB3NGJ.js");
10842
11043
  const res = await bulkPurgeGhostBehaviors({ batchSize: 5e3, vacuum: true });
10843
11044
  return {
10844
11045
  content: [{
@@ -10949,7 +11150,7 @@ Use /exe-forget to remove any that this supersedes.`;
10949
11150
  return { content: [{ type: "text", text: `Behavior not found: ${behavior_id}` }], isError: true };
10950
11151
  }
10951
11152
  const row2 = result4.rows[0];
10952
- const { reactivateBehavior: reactivateBehavior2 } = await import("./behaviors-HLZUJSMP.js");
11153
+ const { reactivateBehavior: reactivateBehavior2 } = await import("./behaviors-KYRB3NGJ.js");
10953
11154
  const wasReactivated = await reactivateBehavior2(behavior_id);
10954
11155
  if (!wasReactivated) {
10955
11156
  return { content: [{ type: "text", text: `Behavior ${behavior_id} is already active.` }] };
@@ -11030,11 +11231,12 @@ function registerReminder(server) {
11030
11231
  action: z82.enum(["create", "list", "complete"]).describe("Action to perform"),
11031
11232
  text: z82.string().optional().describe("What to remind about (create)"),
11032
11233
  due_date: z82.string().optional().describe("Optional due date \u2014 ISO date (2026-04-01) or null for persistent (create)"),
11234
+ daily_push: z82.string().optional().describe('Optional daily push schedule (create) \u2014 JSON {"hours":[9,18]} (0\u201323, founder timezone). A gateway channel pushes this reminder at those hours.'),
11033
11235
  reminder_id: z82.string().optional().describe("Reminder UUID or text substring to match (complete)"),
11034
11236
  include_completed: z82.boolean().optional().default(false).describe("Include completed reminders (list)")
11035
11237
  }
11036
11238
  },
11037
- async ({ action, text: text5, due_date, reminder_id, include_completed }) => {
11239
+ async ({ action, text: text5, due_date, daily_push, reminder_id, include_completed }) => {
11038
11240
  if (action === "create") {
11039
11241
  if (!text5) {
11040
11242
  return {
@@ -11042,10 +11244,19 @@ function registerReminder(server) {
11042
11244
  isError: true
11043
11245
  };
11044
11246
  }
11045
- const reminder2 = await createReminder(text5, due_date);
11247
+ let reminder2;
11248
+ try {
11249
+ reminder2 = await createReminder(text5, due_date, daily_push);
11250
+ } catch (err) {
11251
+ return {
11252
+ content: [{ type: "text", text: err instanceof Error ? err.message : String(err) }],
11253
+ isError: true
11254
+ };
11255
+ }
11046
11256
  const dueStr = reminder2.dueDate ? ` (due: ${reminder2.dueDate})` : "";
11257
+ const pushStr = reminder2.dailyPush ? ` (daily push: ${reminder2.dailyPush})` : "";
11047
11258
  return {
11048
- content: [{ type: "text", text: `Reminder set: "${reminder2.text}"${dueStr}` }]
11259
+ content: [{ type: "text", text: `Reminder set: "${reminder2.text}"${dueStr}${pushStr}` }]
11049
11260
  };
11050
11261
  }
11051
11262
  if (action === "list") {
@@ -11057,8 +11268,9 @@ function registerReminder(server) {
11057
11268
  }
11058
11269
  const lines = reminders.map((r) => {
11059
11270
  const due = r.dueDate ? ` (due: ${r.dueDate})` : "";
11271
+ const push = r.dailyPush ? ` (daily push: ${r.dailyPush})` : "";
11060
11272
  const done = r.completedAt ? " [DONE]" : "";
11061
- return `\u2022 ${r.text}${due}${done} [id: ${r.id.slice(0, 8)}]`;
11273
+ return `\u2022 ${r.text}${due}${push}${done} [id: ${r.id.slice(0, 8)}]`;
11062
11274
  });
11063
11275
  return {
11064
11276
  content: [{ type: "text", text: lines.join("\n") }]
@@ -11470,7 +11682,7 @@ function registerWorkflowTool(server) {
11470
11682
  getWorkflowInstance,
11471
11683
  listWorkflowInstances,
11472
11684
  approveWorkflowStep
11473
- } = await import("./workflow-engine-EWCOLD47.js");
11685
+ } = await import("./workflow-engine-YITHXZR5.js");
11474
11686
  try {
11475
11687
  switch (input.action) {
11476
11688
  case "create_workflow": {
@@ -11595,7 +11807,6 @@ function formatInstanceStatus(inst, def) {
11595
11807
  // src/mcp/tools/create-bug-report.ts
11596
11808
  import { z as z88 } from "zod";
11597
11809
  import crypto4 from "crypto";
11598
- import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
11599
11810
  import path13 from "path";
11600
11811
  var CLASSIFICATION = z88.enum([
11601
11812
  "upstream_bug",
@@ -11650,7 +11861,12 @@ function buildMarkdown(input) {
11650
11861
  function prepareUpstreamPayload(payload) {
11651
11862
  const cleaned = { ...payload };
11652
11863
  delete cleaned.agent_role;
11653
- return { body: JSON.stringify(cleaned), contentType: "application/json", encrypted: false };
11864
+ if (!isTelemetryRedactionEnabled()) {
11865
+ console.error("[bug-report] WARNING: EXE_TELEMETRY_REDACT=off \u2014 sending UNREDACTED payload upstream");
11866
+ return { body: JSON.stringify(cleaned), contentType: "application/json", encrypted: false, redactedCount: 0, truncatedCount: 0 };
11867
+ }
11868
+ const { payload: sanitized, redactedCount, truncatedCount } = sanitizeUpstreamPayload(cleaned);
11869
+ return { body: JSON.stringify(sanitized), contentType: "application/json", encrypted: false, redactedCount, truncatedCount };
11654
11870
  }
11655
11871
  async function maybeSendUpstream(payload) {
11656
11872
  if (process.env.VITEST || process.env.NODE_ENV === "test") {
@@ -11658,19 +11874,19 @@ async function maybeSendUpstream(payload) {
11658
11874
  }
11659
11875
  const config = await loadConfig();
11660
11876
  const routerUrl = process.env.API_ROUTER_URL?.replace(/\/+$/, "");
11661
- const endpoint2 = config.support?.bugReportEndpoint || process.env.EXE_BUG_REPORT_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/bug-reports` : "https://api.askexe.com/v1/support/bug-reports");
11877
+ const endpoint = config.support?.bugReportEndpoint || process.env.EXE_BUG_REPORT_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/bug-reports` : "https://api.askexe.com/v1/support/bug-reports");
11662
11878
  const token = config.support?.bugReportToken || process.env.EXE_BUG_REPORT_TOKEN;
11663
11879
  const licenseKey = loadLicense() || process.env.EXE_LICENSE_KEY || config.cloud?.apiKey;
11664
11880
  const licenseToken = readCachedLicenseToken();
11665
- if (!endpoint2) {
11881
+ if (!endpoint) {
11666
11882
  return "not_configured";
11667
11883
  }
11668
11884
  try {
11669
- const parsed = new URL(endpoint2);
11885
+ const parsed = new URL(endpoint);
11670
11886
  if (parsed.protocol !== "https:" && !["localhost", "127.0.0.1", "::1"].includes(parsed.hostname)) {
11671
11887
  return "failed: insecure endpoint rejected";
11672
11888
  }
11673
- const { body, contentType, encrypted } = prepareUpstreamPayload(payload);
11889
+ const { body, contentType, encrypted, redactedCount, truncatedCount } = prepareUpstreamPayload(payload);
11674
11890
  const response = await fetch(parsed, {
11675
11891
  method: "POST",
11676
11892
  headers: {
@@ -11685,7 +11901,11 @@ async function maybeSendUpstream(payload) {
11685
11901
  signal: AbortSignal.timeout(1e4)
11686
11902
  });
11687
11903
  if (!response.ok) return `failed: HTTP ${response.status}`;
11688
- return encrypted ? "sent (encrypted)" : "sent (redacted)";
11904
+ if (encrypted) return "sent (encrypted)";
11905
+ const parts = ["sanitized"];
11906
+ if (redactedCount > 0) parts.push(`${redactedCount} secret${redactedCount === 1 ? "" : "s"} redacted`);
11907
+ if (truncatedCount > 0) parts.push(`${truncatedCount} field${truncatedCount === 1 ? "" : "s"} truncated`);
11908
+ return `sent (${parts.join(", ")})`;
11689
11909
  } catch (err) {
11690
11910
  return `failed: ${err instanceof Error ? err.message : String(err)}`;
11691
11911
  }
@@ -11710,7 +11930,7 @@ function registerCreateBugReport(server) {
11710
11930
  files_changed: z88.array(z88.string()).optional().describe("Files changed or suspected"),
11711
11931
  workaround: z88.string().optional().describe("Temporary local workaround/hotfix, if any"),
11712
11932
  local_patch_diff: z88.string().optional().describe("Small local diff or patch summary"),
11713
- product: z88.string().optional().describe("Product this bug is for: exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build. Defaults to exe-os."),
11933
+ product: supportProductSchema.optional().describe("Product this bug is for: exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build. Defaults to exe-os."),
11714
11934
  package_version: z88.string().optional().describe("Installed package version"),
11715
11935
  project_name: z88.string().optional().describe("Project/customer context"),
11716
11936
  implementing_branch: z88.string().optional().describe("Branch name or PR URL that implements/fixes this bug. Recorded on the report so future work can find existing fixes instead of redoing them (bug e324f244)."),
@@ -11722,6 +11942,7 @@ function registerCreateBugReport(server) {
11722
11942
  on_behalf_of_email: z88.string().email().optional().describe("ADMIN ONLY: file this request owned by another customer's license email; ignored unless caller holds the support admin token")
11723
11943
  }
11724
11944
  },
11945
+ // Structural sink guard (round 6): deep-redact the whole return object + errors.
11725
11946
  async ({
11726
11947
  title,
11727
11948
  classification,
@@ -11741,7 +11962,7 @@ function registerCreateBugReport(server) {
11741
11962
  attachments,
11742
11963
  send_upstream,
11743
11964
  on_behalf_of_email
11744
- }) => {
11965
+ }) => redactedToolResult(async () => {
11745
11966
  if (!summary || summary.trim().length === 0) {
11746
11967
  return {
11747
11968
  content: [{
@@ -11754,10 +11975,10 @@ function registerCreateBugReport(server) {
11754
11975
  const { agentId, agentRole } = getActiveAgent();
11755
11976
  const id = crypto4.randomUUID();
11756
11977
  const resolvedProduct = product ?? "exe-os";
11757
- const version = package_version ?? "unknown";
11978
+ const version = sanitizeVersionField(package_version) ?? "unknown";
11758
11979
  let metricsSnapshot = "";
11759
11980
  try {
11760
- const { getOrchestrationMetrics, formatOrchestrationMetrics } = await import("./orchestration-events-5SIJOE4H.js");
11981
+ const { getOrchestrationMetrics, formatOrchestrationMetrics } = await import("./orchestration-events-WV4NWKZH.js");
11761
11982
  const sinceIso = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
11762
11983
  const metrics = await getOrchestrationMetrics({ sinceIso });
11763
11984
  if (metrics.totalEvents > 0) {
@@ -11803,51 +12024,41 @@ ${formatOrchestrationMetrics(metrics)}
11803
12024
  }
11804
12025
  const fullMarkdown = markdown + metricsSnapshot + attachmentSection;
11805
12026
  const outDir = path13.join(EXE_AI_DIR, "bug-reports");
11806
- await mkdir2(outDir, { recursive: true });
11807
- const reportPath = path13.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify(title)}-${id.slice(0, 8)}.md`);
11808
- await writeFile2(reportPath, fullMarkdown, "utf-8");
11809
- if (attachments && attachments.length > 0) {
11810
- const attachDir = path13.join(outDir, `${id.slice(0, 8)}-attachments`);
11811
- await mkdir2(attachDir, { recursive: true });
11812
- for (const att of attachments) {
11813
- const safeName = att.filename.replace(/[/\\]/g, "_").replace(/\.\./g, "_");
11814
- const attPath = path13.join(attachDir, safeName);
11815
- await writeFile2(attPath, att.content, "utf-8");
11816
- savedAttachmentPaths.push(attPath);
12027
+ const reportPath = path13.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify(redactSecrets(title).text)}-${id.slice(0, 8)}.md`);
12028
+ const attachDir = path13.join(outDir, `${id.slice(0, 8)}-attachments`);
12029
+ const persistAttachments = (attachments ?? []).map((att) => ({
12030
+ // Sanitize filename — redact secrets first (F6: filename lands on disk),
12031
+ // then strip path separators to prevent directory traversal.
12032
+ path: path13.join(attachDir, redactSecrets(att.filename).text.replace(/[/\\]/g, "_").replace(/\.\./g, "_")),
12033
+ content: att.content
12034
+ }));
12035
+ const persisted = await persistSupportArtifact({
12036
+ memoryText: fullMarkdown,
12037
+ file: { path: reportPath, content: fullMarkdown },
12038
+ attachments: persistAttachments,
12039
+ memory: {
12040
+ id,
12041
+ agent_id: agentId,
12042
+ agent_role: agentRole,
12043
+ session_id: process.env.SESSION_ID ?? "manual",
12044
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12045
+ tool_name: "create_bug_report",
12046
+ project_name: project_name ?? "support",
12047
+ has_error: classification === "upstream_bug" || classification === "emergency_hotfix",
12048
+ source_path: reportPath,
12049
+ source_type: "bug_report",
12050
+ memory_type: "bug_report",
12051
+ tier: 1,
12052
+ importance: severity === "p0" ? 10 : severity === "p1" ? 9 : 7,
12053
+ intent: "report",
12054
+ domain: "support",
12055
+ file_paths: files_changed ? JSON.stringify(files_changed) : null
11817
12056
  }
11818
- }
11819
- let vector = null;
11820
- try {
11821
- vector = await embed(fullMarkdown);
11822
- } catch {
11823
- vector = null;
11824
- }
11825
- await writeMemory({
11826
- id,
11827
- agent_id: agentId,
11828
- agent_role: agentRole,
11829
- session_id: process.env.SESSION_ID ?? "manual",
11830
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
11831
- tool_name: "create_bug_report",
11832
- project_name: project_name ?? "support",
11833
- has_error: classification === "upstream_bug" || classification === "emergency_hotfix",
11834
- raw_text: fullMarkdown,
11835
- vector,
11836
- source_path: reportPath,
11837
- source_type: "bug_report",
11838
- memory_type: "bug_report",
11839
- tier: 1,
11840
- importance: severity === "p0" ? 10 : severity === "p1" ? 9 : 7,
11841
- intent: "report",
11842
- domain: "support",
11843
- file_paths: files_changed ? JSON.stringify(files_changed) : null
11844
12057
  });
11845
- await flushBatch();
11846
- const UPSTREAM_ATTACHMENT_MAX_CHARS = 4096;
12058
+ savedAttachmentPaths.push(...persisted.attachmentPaths);
11847
12059
  const upstreamAttachments = attachments?.map((att) => ({
11848
12060
  filename: att.filename,
11849
- content: att.content.length > UPSTREAM_ATTACHMENT_MAX_CHARS ? att.content.slice(0, UPSTREAM_ATTACHMENT_MAX_CHARS) + `
11850
- ... [truncated, ${att.content.length} chars total]` : att.content,
12061
+ content: att.content,
11851
12062
  truncated: att.content.length > UPSTREAM_ATTACHMENT_MAX_CHARS,
11852
12063
  original_size: att.content.length
11853
12064
  }));
@@ -11893,14 +12104,13 @@ Upstream status: ${upstreamStatus}`
11893
12104
  }
11894
12105
  ]
11895
12106
  };
11896
- }
12107
+ })
11897
12108
  );
11898
12109
  }
11899
12110
 
11900
12111
  // src/mcp/tools/create-feature-request.ts
11901
12112
  import { z as z89 } from "zod";
11902
12113
  import crypto5 from "crypto";
11903
- import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
11904
12114
  import path14 from "path";
11905
12115
  var CATEGORY = z89.enum([
11906
12116
  "upstream_feature",
@@ -11945,18 +12155,30 @@ async function maybeSendUpstream2(payload) {
11945
12155
  }
11946
12156
  const config = await loadConfig();
11947
12157
  const routerUrl = process.env.API_ROUTER_URL?.replace(/\/+$/, "");
11948
- const endpoint2 = config.support?.featureRequestEndpoint || process.env.EXE_FEATURE_REQUEST_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/feature-requests` : "https://api.askexe.com/v1/support/feature-requests");
12158
+ const endpoint = config.support?.featureRequestEndpoint || process.env.EXE_FEATURE_REQUEST_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/feature-requests` : "https://api.askexe.com/v1/support/feature-requests");
11949
12159
  const token = config.support?.featureRequestToken || process.env.EXE_FEATURE_REQUEST_TOKEN;
11950
12160
  const licenseKey = loadLicense() || process.env.EXE_LICENSE_KEY || config.cloud?.apiKey;
11951
12161
  const licenseToken = readCachedLicenseToken();
11952
- if (!endpoint2) {
12162
+ if (!endpoint) {
11953
12163
  return "not_configured";
11954
12164
  }
11955
12165
  try {
11956
- const parsed = new URL(endpoint2);
12166
+ const parsed = new URL(endpoint);
11957
12167
  if (parsed.protocol !== "https:" && !["localhost", "127.0.0.1", "::1"].includes(parsed.hostname)) {
11958
12168
  return "failed: insecure endpoint rejected";
11959
12169
  }
12170
+ let outboundBody;
12171
+ let redactedCount = 0;
12172
+ let truncatedCount = 0;
12173
+ if (isTelemetryRedactionEnabled()) {
12174
+ const sanitized = sanitizeUpstreamPayload(payload);
12175
+ outboundBody = JSON.stringify(sanitized.payload);
12176
+ redactedCount = sanitized.redactedCount;
12177
+ truncatedCount = sanitized.truncatedCount;
12178
+ } else {
12179
+ console.error("[feature-request] WARNING: EXE_TELEMETRY_REDACT=off \u2014 sending UNREDACTED payload upstream");
12180
+ outboundBody = JSON.stringify(payload);
12181
+ }
11960
12182
  const response = await fetch(parsed, {
11961
12183
  method: "POST",
11962
12184
  headers: {
@@ -11966,11 +12188,14 @@ async function maybeSendUpstream2(payload) {
11966
12188
  ...licenseToken ? { "x-exe-license-token": licenseToken } : {},
11967
12189
  ...supportAdminHeaders(config)
11968
12190
  },
11969
- body: JSON.stringify(payload),
12191
+ body: outboundBody,
11970
12192
  signal: AbortSignal.timeout(1e4)
11971
12193
  });
11972
12194
  if (!response.ok) return `failed: HTTP ${response.status}`;
11973
- return "sent";
12195
+ const parts = ["sanitized"];
12196
+ if (redactedCount > 0) parts.push(`${redactedCount} secret${redactedCount === 1 ? "" : "s"} redacted`);
12197
+ if (truncatedCount > 0) parts.push(`${truncatedCount} field${truncatedCount === 1 ? "" : "s"} truncated`);
12198
+ return `sent (${parts.join(", ")})`;
11974
12199
  } catch (err) {
11975
12200
  return `failed: ${err instanceof Error ? err.message : String(err)}`;
11976
12201
  }
@@ -11992,7 +12217,7 @@ function registerCreateFeatureRequest(server) {
11992
12217
  current_workaround: z89.string().optional().describe("How the need is currently addressed, if at all"),
11993
12218
  proposed_solution: z89.string().optional().describe("Suggested implementation approach"),
11994
12219
  business_impact: z89.string().optional().describe("Impact on business/workflow if this ships"),
11995
- product: z89.string().optional().describe("Product this feature is for: exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build. Defaults to exe-os."),
12220
+ product: supportProductSchema.optional().describe("Product this feature is for: exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build. Defaults to exe-os."),
11996
12221
  package_version: z89.string().optional().describe("Installed package version"),
11997
12222
  project_name: z89.string().optional().describe("Project/customer context"),
11998
12223
  implementing_branch: z89.string().optional().describe("Branch name or PR URL that implements this feature. Recorded on the request so future work can find existing implementations instead of redoing them (bug e324f244)."),
@@ -12004,6 +12229,7 @@ function registerCreateFeatureRequest(server) {
12004
12229
  on_behalf_of_email: z89.string().email().optional().describe("ADMIN ONLY: file this request owned by another customer's license email; ignored unless caller holds the support admin token")
12005
12230
  }
12006
12231
  },
12232
+ // Structural sink guard (round 6): deep-redact the whole return object + errors.
12007
12233
  async ({
12008
12234
  title,
12009
12235
  category,
@@ -12020,11 +12246,11 @@ function registerCreateFeatureRequest(server) {
12020
12246
  attachments,
12021
12247
  send_upstream,
12022
12248
  on_behalf_of_email
12023
- }) => {
12249
+ }) => redactedToolResult(async () => {
12024
12250
  const { agentId, agentRole } = getActiveAgent();
12025
12251
  const id = crypto5.randomUUID();
12026
12252
  const resolvedProduct = product ?? "exe-os";
12027
- const version = package_version ?? "unknown";
12253
+ const version = sanitizeVersionField(package_version) ?? "unknown";
12028
12254
  const markdownBase = buildMarkdown2({
12029
12255
  id,
12030
12256
  title,
@@ -12054,51 +12280,40 @@ function registerCreateFeatureRequest(server) {
12054
12280
  }
12055
12281
  const markdown = markdownBase + attachmentSection;
12056
12282
  const outDir = path14.join(EXE_AI_DIR, "feature-requests");
12057
- await mkdir3(outDir, { recursive: true });
12058
- const reportPath = path14.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(title)}-${id.slice(0, 8)}.md`);
12059
- await writeFile3(reportPath, markdown, "utf-8");
12060
- if (attachments && attachments.length > 0) {
12061
- const attachDir = path14.join(outDir, `${id.slice(0, 8)}-attachments`);
12062
- await mkdir3(attachDir, { recursive: true });
12063
- for (const att of attachments) {
12064
- const safeName = att.filename.replace(/[/\\]/g, "_").replace(/\.\./g, "_");
12065
- const attPath = path14.join(attachDir, safeName);
12066
- await writeFile3(attPath, att.content, "utf-8");
12067
- savedAttachmentPaths.push(attPath);
12283
+ const reportPath = path14.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(redactSecrets(title).text)}-${id.slice(0, 8)}.md`);
12284
+ const attachDir = path14.join(outDir, `${id.slice(0, 8)}-attachments`);
12285
+ const persistAttachments = (attachments ?? []).map((att) => ({
12286
+ // F6: redact secrets from the filename before it lands on disk.
12287
+ path: path14.join(attachDir, redactSecrets(att.filename).text.replace(/[/\\]/g, "_").replace(/\.\./g, "_")),
12288
+ content: att.content
12289
+ }));
12290
+ const persisted = await persistSupportArtifact({
12291
+ memoryText: markdown,
12292
+ file: { path: reportPath, content: markdown },
12293
+ attachments: persistAttachments,
12294
+ memory: {
12295
+ id,
12296
+ agent_id: agentId,
12297
+ agent_role: agentRole,
12298
+ session_id: process.env.SESSION_ID ?? "manual",
12299
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12300
+ tool_name: "create_feature_request",
12301
+ project_name: project_name ?? "support",
12302
+ has_error: false,
12303
+ source_path: reportPath,
12304
+ source_type: "feature_request",
12305
+ memory_type: "feature_request",
12306
+ tier: 1,
12307
+ importance: priority === "p0" ? 10 : priority === "p1" ? 9 : priority === "p2" ? 7 : 5,
12308
+ intent: "request",
12309
+ domain: "support",
12310
+ file_paths: null
12068
12311
  }
12069
- }
12070
- let vector = null;
12071
- try {
12072
- vector = await embed(markdown);
12073
- } catch {
12074
- vector = null;
12075
- }
12076
- await writeMemory({
12077
- id,
12078
- agent_id: agentId,
12079
- agent_role: agentRole,
12080
- session_id: process.env.SESSION_ID ?? "manual",
12081
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12082
- tool_name: "create_feature_request",
12083
- project_name: project_name ?? "support",
12084
- has_error: false,
12085
- raw_text: markdown,
12086
- vector,
12087
- source_path: reportPath,
12088
- source_type: "feature_request",
12089
- memory_type: "feature_request",
12090
- tier: 1,
12091
- importance: priority === "p0" ? 10 : priority === "p1" ? 9 : priority === "p2" ? 7 : 5,
12092
- intent: "request",
12093
- domain: "support",
12094
- file_paths: null
12095
12312
  });
12096
- await flushBatch();
12097
- const UPSTREAM_ATTACHMENT_MAX_CHARS = 4096;
12313
+ savedAttachmentPaths.push(...persisted.attachmentPaths);
12098
12314
  const upstreamAttachments = attachments?.map((att) => ({
12099
12315
  filename: att.filename,
12100
- content: att.content.length > UPSTREAM_ATTACHMENT_MAX_CHARS ? att.content.slice(0, UPSTREAM_ATTACHMENT_MAX_CHARS) + `
12101
- ... [truncated, ${att.content.length} chars total]` : att.content,
12316
+ content: att.content,
12102
12317
  truncated: att.content.length > UPSTREAM_ATTACHMENT_MAX_CHARS,
12103
12318
  original_size: att.content.length
12104
12319
  }));
@@ -12152,13 +12367,13 @@ Upstream status: ${upstreamStatus}`
12152
12367
  }
12153
12368
  ]
12154
12369
  };
12155
- }
12370
+ })
12156
12371
  );
12157
12372
  }
12158
12373
 
12159
12374
  // src/mcp/tools/update-bug-report.ts
12160
12375
  import { z as z90 } from "zod";
12161
- import { readdir, readFile as readFile2, writeFile as writeFile4 } from "fs/promises";
12376
+ import { readdir, readFile as readFile2 } from "fs/promises";
12162
12377
  import path15 from "path";
12163
12378
  var STATUS = z90.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
12164
12379
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
@@ -12208,8 +12423,13 @@ async function findReportFile(id) {
12208
12423
  }
12209
12424
  return null;
12210
12425
  }
12211
- async function appendUpdateSection(filePath, opts) {
12212
- const existing = await readFile2(filePath, "utf-8");
12426
+ async function buildUpdateSection(filePath, opts) {
12427
+ let existing = "";
12428
+ try {
12429
+ existing = await readFile2(filePath, "utf-8");
12430
+ } catch {
12431
+ existing = "";
12432
+ }
12213
12433
  const heading = opts.reopen ? "Reopen Request" : "Status Update";
12214
12434
  const updateBlock = [
12215
12435
  "",
@@ -12221,37 +12441,39 @@ async function appendUpdateSection(filePath, opts) {
12221
12441
  ...opts.evidence ? [``, `Evidence: ${opts.evidence}`] : []
12222
12442
  ].join("\n");
12223
12443
  const titleMatch = existing.match(/^# Bug Report — (.+)$/m);
12224
- await writeFile4(filePath, existing + updateBlock, "utf-8");
12225
- return titleMatch?.[1] ?? "Unknown bug";
12444
+ return { title: titleMatch?.[1] ?? "Unknown bug", updateBlock };
12226
12445
  }
12227
12446
  async function sendUpstream(payload, isAdmin) {
12228
12447
  const config = await loadConfig();
12229
12448
  const routerUrl = process.env.API_ROUTER_URL?.replace(/\/+$/, "");
12230
- const adminToken2 = resolveSupportAdminToken(config);
12449
+ const adminToken = resolveSupportAdminToken(config);
12231
12450
  const support = config.support;
12232
- const baseEndpoint = isAdmin && adminToken2 ? process.env.ASKEXE_SUPPORT_ADMIN_ENDPOINT || support?.adminEndpoint || support?.admin_endpoint || "https://api.askexe.com/admin/support/bug-reports" : config.support?.bugReportEndpoint || process.env.EXE_BUG_REPORT_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/bug-reports` : "https://api.askexe.com/v1/support/bug-reports");
12451
+ const baseEndpoint = isAdmin && adminToken ? process.env.ASKEXE_SUPPORT_ADMIN_ENDPOINT || support?.adminEndpoint || support?.admin_endpoint || "https://api.askexe.com/admin/support/bug-reports" : config.support?.bugReportEndpoint || process.env.EXE_BUG_REPORT_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/bug-reports` : "https://api.askexe.com/v1/support/bug-reports");
12233
12452
  const licenseKey = loadLicense() || process.env.EXE_LICENSE_KEY || config.cloud?.apiKey;
12234
12453
  const licenseToken = readCachedLicenseToken();
12235
12454
  if (!baseEndpoint) return "not_configured";
12236
12455
  try {
12237
12456
  const base = baseEndpoint.replace(/\/+$/, "");
12238
- const url = `${base}/${encodeURIComponent(payload.id)}`;
12457
+ const url = `${base}/${encodeURIComponent(sanitizeUpstreamId(payload.id))}`;
12239
12458
  const parsed = new URL(url);
12240
12459
  if (parsed.protocol !== "https:" && !["localhost", "127.0.0.1", "::1"].includes(parsed.hostname)) {
12241
12460
  return "failed: insecure endpoint rejected";
12242
12461
  }
12243
- const adminHeaders = isAdmin && adminToken2 ? { authorization: `Bearer ${adminToken2}`, ...supportAdminHeaders(config) } : {};
12462
+ const adminHeaders = isAdmin && adminToken ? { authorization: `Bearer ${adminToken}`, ...supportAdminHeaders(config) } : {};
12244
12463
  const response = await fetch(parsed, {
12245
12464
  method: "PATCH",
12246
12465
  headers: {
12247
12466
  "content-type": "application/json",
12248
- ...isAdmin && adminToken2 ? {} : {
12467
+ ...isAdmin && adminToken ? {} : {
12249
12468
  ...licenseKey ? { "x-exe-license-key": licenseKey, authorization: `Bearer ${licenseKey}` } : {},
12250
12469
  ...licenseToken ? { "x-exe-license-token": licenseToken } : {}
12251
12470
  },
12252
12471
  ...adminHeaders
12253
12472
  },
12254
- body: JSON.stringify(payload),
12473
+ // Egress redaction gate (dc16fee4) — add_evidence ("logs, repro details,
12474
+ // stack traces"), add_note, and triage_notes are the most secret-dense
12475
+ // support fields; redact before the network send.
12476
+ body: sanitizedUpstreamBody(payload, "update-bug-report"),
12255
12477
  signal: AbortSignal.timeout(1e4)
12256
12478
  });
12257
12479
  if (!response.ok) return `failed: HTTP ${response.status}`;
@@ -12267,12 +12489,12 @@ function registerUpdateBugReport(server) {
12267
12489
  title: "Update Bug Report",
12268
12490
  description: "Update a previously filed bug report. As the filing customer (owner) you can add follow-up notes (notes/add_note), attach additional evidence (add_evidence), and request a reopen on a recurring fixed bug (reopen_request). AskExe support (with an admin token) can also move status: open \u2192 triaged \u2192 fixed \u2192 closed (or wontfix). Updates the local file, POSTs the change to AskExe support, and stores a memory.",
12269
12491
  inputSchema: {
12270
- id: z90.string().min(8).describe("Bug report UUID (full or 8-char prefix)"),
12492
+ id: supportIdSchema.describe("Bug report UUID (full or 8-char prefix)"),
12271
12493
  status: STATUS.optional().describe(
12272
12494
  "New status (admin only): open, triaged, fixed, closed, wontfix. Owners cannot set this \u2014 use reopen_request instead."
12273
12495
  ),
12274
- fix_version: z90.string().optional().describe("Version that fixes this bug (admin only, e.g. '0.9.161')"),
12275
- product: z90.string().optional().describe("Re-label this bug's product (admin only): exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build, exe-chat, exe-auth, exe-monitor, exe-db, exe-erp"),
12496
+ fix_version: supportVersionSchema.optional().describe("Version that fixes this bug (admin only, e.g. '0.9.161')"),
12497
+ product: supportProductSchema.optional().describe("Re-label this bug's product (admin only): exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build, exe-chat, exe-auth, exe-monitor, exe-db, exe-erp"),
12276
12498
  notes: z90.string().optional().describe("Follow-up notes about the bug or status change"),
12277
12499
  add_note: z90.string().optional().describe("Owner follow-up note (alias of notes)"),
12278
12500
  add_evidence: z90.string().optional().describe("Additional evidence: logs, repro details, stack traces"),
@@ -12281,7 +12503,7 @@ function registerUpdateBugReport(server) {
12281
12503
  send_upstream: z90.boolean().default(true).describe("POST the change to AskExe support endpoint")
12282
12504
  }
12283
12505
  },
12284
- async ({ id, status: status2, fix_version, product, notes, add_note, add_evidence, reopen_request, reopen_reason, send_upstream }) => {
12506
+ async ({ id, status: status2, fix_version, product, notes, add_note, add_evidence, reopen_request, reopen_reason, send_upstream }) => redactedToolResult(async () => {
12285
12507
  const { agentId, agentRole } = getActiveAgent();
12286
12508
  const config = await loadConfig();
12287
12509
  const isAdmin = !!resolveSupportAdminToken(config);
@@ -12307,67 +12529,69 @@ These do not match \u2014 not updating to avoid mutating the wrong bug. Verify t
12307
12529
  }
12308
12530
  const fullId = resolved?.fullId ?? id;
12309
12531
  let localTitle = "Unknown bug";
12532
+ let updateBlock = null;
12310
12533
  if (localFile) {
12311
12534
  try {
12312
- localTitle = await appendUpdateSection(localFile, {
12535
+ const built = await buildUpdateSection(localFile, {
12313
12536
  status: reopen ? "open" : status2,
12314
12537
  notes: followUpNote,
12315
12538
  fixVersion: fix_version,
12316
12539
  evidence: add_evidence,
12317
12540
  reopen
12318
12541
  });
12542
+ localTitle = built.title;
12543
+ updateBlock = built.updateBlock;
12319
12544
  } catch {
12320
12545
  }
12321
12546
  }
12322
12547
  const changeParts = [];
12323
12548
  if (reopen) changeParts.push("reopen requested");
12324
12549
  else if (status2) changeParts.push(`marked ${status2}`);
12325
- if (fix_version) changeParts.push(`fix v${fix_version}`);
12550
+ if (fix_version) changeParts.push(`fix v ${fix_version}`);
12326
12551
  if (product) changeParts.push(`product \u2192 ${product}`);
12327
12552
  if (add_evidence) changeParts.push("evidence added");
12328
12553
  if (followUpNote && !reopen && !status2) changeParts.push("note added");
12329
12554
  const change = changeParts.length > 0 ? changeParts.join(", ") : "updated";
12330
12555
  const memoryText = `Bug "${localTitle}" (${fullId.slice(0, 8)}) ${change}` + (reopen_reason ? `. Reopen reason: ${reopen_reason}` : "") + (followUpNote ? `. Notes: ${followUpNote}` : "");
12331
- let vector = null;
12332
- try {
12333
- vector = await embed(memoryText);
12334
- } catch {
12335
- vector = null;
12336
- }
12337
12556
  const memoryId = `${fullId}-update-${Date.now()}`;
12338
- await writeMemory({
12339
- id: memoryId,
12340
- agent_id: agentId,
12341
- agent_role: agentRole,
12342
- session_id: process.env.SESSION_ID ?? "manual",
12343
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12344
- tool_name: "update_bug_report",
12345
- project_name: "support",
12346
- has_error: false,
12347
- raw_text: memoryText,
12348
- vector,
12349
- source_path: localFile ?? null,
12350
- source_type: "bug_report",
12351
- memory_type: "bug_report",
12352
- tier: 1,
12353
- importance: status2 === "fixed" || status2 === "closed" ? 8 : 6,
12354
- intent: "update",
12355
- domain: "support",
12356
- file_paths: null
12557
+ await persistSupportArtifact({
12558
+ memoryText,
12559
+ file: localFile && updateBlock !== null ? { path: localFile, content: updateBlock, append: true } : void 0,
12560
+ memory: {
12561
+ id: memoryId,
12562
+ agent_id: agentId,
12563
+ agent_role: agentRole,
12564
+ session_id: process.env.SESSION_ID ?? "manual",
12565
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12566
+ tool_name: "update_bug_report",
12567
+ project_name: "support",
12568
+ has_error: false,
12569
+ source_path: localFile ?? null,
12570
+ source_type: "bug_report",
12571
+ memory_type: "bug_report",
12572
+ tier: 1,
12573
+ importance: status2 === "fixed" || status2 === "closed" ? 8 : 6,
12574
+ intent: "update",
12575
+ domain: "support",
12576
+ file_paths: null
12577
+ }
12357
12578
  });
12358
- await flushBatch();
12359
12579
  const payload = {
12360
- id: fullId,
12580
+ // Body belt (round 9): even past ingress validation, sanitize the id so a
12581
+ // value from a non-schema caller can't put a raw id in the JSON body.
12582
+ id: sanitizeUpstreamId(fullId),
12361
12583
  updated_at: (/* @__PURE__ */ new Date()).toISOString(),
12362
12584
  agent_id: agentId
12363
12585
  };
12364
12586
  if (isAdmin) {
12365
12587
  if (status2) payload.status = status2;
12366
- if (fix_version) {
12367
- payload.fixed_version = fix_version;
12368
- payload.fix_version = fix_version;
12588
+ const safeFixVersion = sanitizeVersionField(fix_version);
12589
+ if (safeFixVersion) {
12590
+ payload.fixed_version = safeFixVersion;
12591
+ payload.fix_version = safeFixVersion;
12369
12592
  }
12370
- if (product) payload.product = product;
12593
+ const safeProduct = sanitizeProductFilter(product);
12594
+ if (safeProduct) payload.product = safeProduct;
12371
12595
  if (followUpNote) payload.triage_notes = followUpNote;
12372
12596
  } else {
12373
12597
  if (followUpNote) payload.add_note = followUpNote;
@@ -12397,13 +12621,13 @@ Upstream status: ${upstreamStatus}`
12397
12621
  }
12398
12622
  ]
12399
12623
  };
12400
- }
12624
+ })
12401
12625
  );
12402
12626
  }
12403
12627
 
12404
12628
  // src/mcp/tools/update-feature-request.ts
12405
12629
  import { z as z91 } from "zod";
12406
- import { readdir as readdir2, readFile as readFile3, writeFile as writeFile5 } from "fs/promises";
12630
+ import { readdir as readdir2, readFile as readFile3 } from "fs/promises";
12407
12631
  import path16 from "path";
12408
12632
  var STATUS2 = z91.enum(["open", "planned", "in_progress", "shipped", "closed", "wontdo"]);
12409
12633
  async function findRequestFile(id) {
@@ -12417,9 +12641,8 @@ async function findRequestFile(id) {
12417
12641
  return null;
12418
12642
  }
12419
12643
  }
12420
- async function appendStatusUpdate(filePath, status2, notes, shippedVersion) {
12421
- const existing = await readFile3(filePath, "utf-8");
12422
- const updateBlock = [
12644
+ function buildStatusUpdate(status2, notes, shippedVersion) {
12645
+ return [
12423
12646
  "",
12424
12647
  `## Status Update \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}`,
12425
12648
  "",
@@ -12427,20 +12650,19 @@ async function appendStatusUpdate(filePath, status2, notes, shippedVersion) {
12427
12650
  ...shippedVersion ? [`shipped_version: ${shippedVersion}`] : [],
12428
12651
  ...notes ? [``, `${notes}`] : []
12429
12652
  ].join("\n");
12430
- await writeFile5(filePath, existing + updateBlock, "utf-8");
12431
12653
  }
12432
12654
  async function sendUpstream2(payload) {
12433
12655
  const config = await loadConfig();
12434
12656
  const routerUrl = process.env.API_ROUTER_URL?.replace(/\/+$/, "");
12435
- const adminToken2 = resolveSupportAdminToken(config);
12657
+ const adminToken = resolveSupportAdminToken(config);
12436
12658
  const support = config.support;
12437
- const baseEndpoint = adminToken2 ? process.env.ASKEXE_SUPPORT_ADMIN_FEATURE_ENDPOINT || support?.adminFeatureEndpoint || support?.admin_feature_endpoint || "https://api.askexe.com/admin/support/feature-requests" : config.support?.featureRequestEndpoint || process.env.EXE_FEATURE_REQUEST_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/feature-requests` : "https://api.askexe.com/v1/support/feature-requests");
12659
+ const baseEndpoint = adminToken ? process.env.ASKEXE_SUPPORT_ADMIN_FEATURE_ENDPOINT || support?.adminFeatureEndpoint || support?.admin_feature_endpoint || "https://api.askexe.com/admin/support/feature-requests" : config.support?.featureRequestEndpoint || process.env.EXE_FEATURE_REQUEST_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/feature-requests` : "https://api.askexe.com/v1/support/feature-requests");
12438
12660
  const licenseKey = loadLicense() || process.env.EXE_LICENSE_KEY || config.cloud?.apiKey;
12439
12661
  const licenseToken = readCachedLicenseToken();
12440
12662
  if (!baseEndpoint) return "not_configured";
12441
12663
  try {
12442
12664
  const base = baseEndpoint.replace(/\/+$/, "");
12443
- const url = `${base}/${encodeURIComponent(payload.id)}`;
12665
+ const url = `${base}/${encodeURIComponent(sanitizeUpstreamId(payload.id))}`;
12444
12666
  const parsed = new URL(url);
12445
12667
  if (parsed.protocol !== "https:" && !["localhost", "127.0.0.1", "::1"].includes(parsed.hostname)) {
12446
12668
  return "failed: insecure endpoint rejected";
@@ -12449,12 +12671,14 @@ async function sendUpstream2(payload) {
12449
12671
  method: "PATCH",
12450
12672
  headers: {
12451
12673
  "content-type": "application/json",
12452
- ...adminToken2 ? { authorization: `Bearer ${adminToken2}`, ...supportAdminHeaders(config) } : {
12674
+ ...adminToken ? { authorization: `Bearer ${adminToken}`, ...supportAdminHeaders(config) } : {
12453
12675
  ...licenseKey ? { "x-exe-license-key": licenseKey, authorization: `Bearer ${licenseKey}` } : {},
12454
12676
  ...licenseToken ? { "x-exe-license-token": licenseToken } : {}
12455
12677
  }
12456
12678
  },
12457
- body: JSON.stringify(payload),
12679
+ // Egress redaction gate (dc16fee4) — redact response_notes/add_note
12680
+ // before the network send.
12681
+ body: sanitizedUpstreamBody(payload, "update-feature-request"),
12458
12682
  signal: AbortSignal.timeout(1e4)
12459
12683
  });
12460
12684
  if (!response.ok) return `failed: HTTP ${response.status}`;
@@ -12470,59 +12694,59 @@ function registerUpdateFeatureRequest(server) {
12470
12694
  title: "Update Feature Request",
12471
12695
  description: "Update the status of a previously filed feature request. Updates local file, POSTs change to AskExe support, and stores a memory. Status flow: open \u2192 planned \u2192 in_progress \u2192 shipped \u2192 closed (or wontdo at any point).",
12472
12696
  inputSchema: {
12473
- id: z91.string().min(8).describe("Feature request UUID (full or 8-char prefix)"),
12697
+ id: supportIdSchema.describe("Feature request UUID (full or 8-char prefix)"),
12474
12698
  status: STATUS2.describe("New status: open, planned, in_progress, shipped, closed, wontdo"),
12475
- shipped_version: z91.string().optional().describe("Version that ships this feature (e.g. '0.9.161')"),
12699
+ shipped_version: supportVersionSchema.optional().describe("Version that ships this feature (e.g. '0.9.161')"),
12476
12700
  notes: z91.string().optional().describe("Notes about the status change"),
12477
12701
  send_upstream: z91.boolean().default(true).describe("POST status change to AskExe support endpoint")
12478
12702
  }
12479
12703
  },
12480
- async ({ id, status: status2, shipped_version, notes, send_upstream }) => {
12704
+ async ({ id, status: status2, shipped_version, notes, send_upstream }) => redactedToolResult(async () => {
12481
12705
  const { agentId, agentRole } = getActiveAgent();
12482
12706
  const localFile = await findRequestFile(id);
12483
12707
  let localTitle = "Unknown feature";
12708
+ let updateBlock = null;
12484
12709
  if (localFile) {
12485
12710
  try {
12486
12711
  const content = await readFile3(localFile, "utf-8");
12487
12712
  const titleMatch = content.match(/^# Feature Request — (.+)$/m);
12488
12713
  if (titleMatch?.[1]) localTitle = titleMatch[1];
12489
- await appendStatusUpdate(localFile, status2, notes, shipped_version);
12714
+ updateBlock = buildStatusUpdate(status2, notes, shipped_version);
12490
12715
  } catch {
12491
12716
  }
12492
12717
  }
12493
- const memoryText = `Feature "${localTitle}" (${id.slice(0, 8)}) marked ${status2}` + (shipped_version ? ` in v${shipped_version}` : "") + (notes ? `. Notes: ${notes}` : "");
12494
- let vector = null;
12495
- try {
12496
- vector = await embed(memoryText);
12497
- } catch {
12498
- vector = null;
12499
- }
12718
+ const memoryText = `Feature "${localTitle}" (${id.slice(0, 8)}) marked ${status2}` + (shipped_version ? ` in v ${shipped_version}` : "") + (notes ? `. Notes: ${notes}` : "");
12500
12719
  const memoryId = `${id}-update-${Date.now()}`;
12501
- await writeMemory({
12502
- id: memoryId,
12503
- agent_id: agentId,
12504
- agent_role: agentRole,
12505
- session_id: process.env.SESSION_ID ?? "manual",
12506
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12507
- tool_name: "update_feature_request",
12508
- project_name: "support",
12509
- has_error: false,
12510
- raw_text: memoryText,
12511
- vector,
12512
- source_path: localFile ?? null,
12513
- source_type: "feature_request",
12514
- memory_type: "feature_request",
12515
- tier: 1,
12516
- importance: status2 === "shipped" || status2 === "closed" ? 8 : 6,
12517
- intent: "update",
12518
- domain: "support",
12519
- file_paths: null
12720
+ await persistSupportArtifact({
12721
+ memoryText,
12722
+ file: localFile && updateBlock !== null ? { path: localFile, content: updateBlock, append: true } : void 0,
12723
+ memory: {
12724
+ id: memoryId,
12725
+ agent_id: agentId,
12726
+ agent_role: agentRole,
12727
+ session_id: process.env.SESSION_ID ?? "manual",
12728
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12729
+ tool_name: "update_feature_request",
12730
+ project_name: "support",
12731
+ has_error: false,
12732
+ source_path: localFile ?? null,
12733
+ source_type: "feature_request",
12734
+ memory_type: "feature_request",
12735
+ tier: 1,
12736
+ importance: status2 === "shipped" || status2 === "closed" ? 8 : 6,
12737
+ intent: "update",
12738
+ domain: "support",
12739
+ file_paths: null
12740
+ }
12520
12741
  });
12521
- await flushBatch();
12522
12742
  const upstreamStatus = send_upstream ? await sendUpstream2({
12523
- id,
12743
+ // Body belt (round 9): sanitize the id so a non-schema caller can't put
12744
+ // a raw id in the JSON body (the URL is sanitized separately).
12745
+ id: sanitizeUpstreamId(id),
12524
12746
  status: status2,
12525
- shipped_version,
12747
+ // Body belt (round 10): shape-validate the version so a schema-bypassing
12748
+ // caller can't put a raw credential-shaped version in the body.
12749
+ shipped_version: sanitizeVersionField(shipped_version),
12526
12750
  notes,
12527
12751
  updated_at: (/* @__PURE__ */ new Date()).toISOString(),
12528
12752
  agent_id: agentId
@@ -12541,7 +12765,7 @@ Upstream status: ${upstreamStatus}`
12541
12765
  }
12542
12766
  ]
12543
12767
  };
12544
- }
12768
+ })
12545
12769
  );
12546
12770
  }
12547
12771
 
@@ -12619,10 +12843,10 @@ function registerSupportTools(server) {
12619
12843
  isError: true
12620
12844
  };
12621
12845
  }
12622
- const endpoint2 = new URL("https://api.askexe.com/v1/support/my-reports");
12623
- endpoint2.searchParams.set("status", status2);
12624
- endpoint2.searchParams.set("limit", String(limit));
12625
- endpoint2.searchParams.set("offset", String(offset));
12846
+ const endpoint = new URL("https://api.askexe.com/v1/support/my-reports");
12847
+ endpoint.searchParams.set("status", status2);
12848
+ endpoint.searchParams.set("limit", String(limit));
12849
+ endpoint.searchParams.set("offset", String(offset));
12626
12850
  const headers = { "content-type": "application/json" };
12627
12851
  if (licenseKey) {
12628
12852
  headers["authorization"] = `Bearer ${licenseKey}`;
@@ -12630,7 +12854,7 @@ function registerSupportTools(server) {
12630
12854
  }
12631
12855
  if (licenseToken) headers["x-exe-license-token"] = licenseToken;
12632
12856
  try {
12633
- const res = await fetch(endpoint2.toString(), { method: "GET", headers, signal: AbortSignal.timeout(15e3) });
12857
+ const res = await fetch(endpoint.toString(), { method: "GET", headers, signal: AbortSignal.timeout(15e3) });
12634
12858
  if (!res.ok) {
12635
12859
  const body = await res.text().catch(() => "");
12636
12860
  return {
@@ -12691,10 +12915,10 @@ function registerSupportTools(server) {
12691
12915
  isError: true
12692
12916
  };
12693
12917
  }
12694
- const endpoint2 = new URL("https://api.askexe.com/v1/support/my-feature-requests");
12695
- endpoint2.searchParams.set("status", status2);
12696
- endpoint2.searchParams.set("limit", String(limit));
12697
- endpoint2.searchParams.set("offset", String(offset));
12918
+ const endpoint = new URL("https://api.askexe.com/v1/support/my-feature-requests");
12919
+ endpoint.searchParams.set("status", status2);
12920
+ endpoint.searchParams.set("limit", String(limit));
12921
+ endpoint.searchParams.set("offset", String(offset));
12698
12922
  const headers = { "content-type": "application/json" };
12699
12923
  if (licenseKey) {
12700
12924
  headers["authorization"] = `Bearer ${licenseKey}`;
@@ -12702,7 +12926,7 @@ function registerSupportTools(server) {
12702
12926
  }
12703
12927
  if (licenseToken) headers["x-exe-license-token"] = licenseToken;
12704
12928
  try {
12705
- const res = await fetch(endpoint2.toString(), { method: "GET", headers, signal: AbortSignal.timeout(15e3) });
12929
+ const res = await fetch(endpoint.toString(), { method: "GET", headers, signal: AbortSignal.timeout(15e3) });
12706
12930
  if (!res.ok) {
12707
12931
  const body = await res.text().catch(() => "");
12708
12932
  return {
@@ -12763,9 +12987,9 @@ function registerSupportTools(server) {
12763
12987
  isError: true
12764
12988
  };
12765
12989
  }
12766
- const endpoint2 = new URL("https://api.askexe.com/v1/support/my-reviews");
12767
- endpoint2.searchParams.set("status", status2);
12768
- endpoint2.searchParams.set("limit", String(limit));
12990
+ const endpoint = new URL("https://api.askexe.com/v1/support/my-reviews");
12991
+ endpoint.searchParams.set("status", status2);
12992
+ endpoint.searchParams.set("limit", String(limit));
12769
12993
  const headers = { "content-type": "application/json" };
12770
12994
  if (licenseKey) {
12771
12995
  headers["authorization"] = `Bearer ${licenseKey}`;
@@ -12773,7 +12997,7 @@ function registerSupportTools(server) {
12773
12997
  }
12774
12998
  if (licenseToken) headers["x-exe-license-token"] = licenseToken;
12775
12999
  try {
12776
- const res = await fetch(endpoint2.toString(), { method: "GET", headers, signal: AbortSignal.timeout(15e3) });
13000
+ const res = await fetch(endpoint.toString(), { method: "GET", headers, signal: AbortSignal.timeout(15e3) });
12777
13001
  if (!res.ok) {
12778
13002
  const body = await res.text().catch(() => "");
12779
13003
  if (res.status === 500 || res.status === 404) {
@@ -13031,7 +13255,7 @@ function registerCliParityTools(server) {
13031
13255
  const out = await runCommand("exe-os", ["cloud", "status"], 45e3);
13032
13256
  let healthSection = "";
13033
13257
  try {
13034
- const { getRetrievalHealth: getRetrievalHealth2, formatDegradations: formatDegradations2 } = await import("./retrieval-health-TWHKYCRK.js");
13258
+ const { getRetrievalHealth: getRetrievalHealth2, formatDegradations: formatDegradations2 } = await import("./retrieval-health-4Z242P3B.js");
13035
13259
  const h = await getRetrievalHealth2();
13036
13260
  const lines = [
13037
13261
  "",
@@ -13099,7 +13323,7 @@ function registerCodeContext(server) {
13099
13323
  const index = buildCodeContextIndex(opts);
13100
13324
  let graphExtract;
13101
13325
  try {
13102
- const { autoExtractGraphEntities } = await import("./graph-auto-extract-LKIQ57PL.js");
13326
+ const { autoExtractGraphEntities } = await import("./graph-auto-extract-OURWMGBS.js");
13103
13327
  graphExtract = await autoExtractGraphEntities(opts.projectRoot);
13104
13328
  } catch {
13105
13329
  }
@@ -13173,355 +13397,8 @@ function registerCodeContext(server) {
13173
13397
  });
13174
13398
  }
13175
13399
 
13176
- // src/mcp/tools/support-inbox.ts
13177
- import { z as z95 } from "zod";
13178
- import { readFileSync as readFileSync7 } from "fs";
13179
- import { join as join4 } from "path";
13180
- import { homedir as homedir4 } from "os";
13181
- var DEFAULT_ENDPOINT = "https://api.askexe.com/admin/support/bug-reports";
13182
- var DEFAULT_OWNER_ENDPOINT = "https://api.askexe.com/v1/support/bug-reports";
13183
- var STATUS3 = z95.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
13184
- function adminToken() {
13185
- if (process.env.ASKEXE_SUPPORT_ADMIN_TOKEN) return process.env.ASKEXE_SUPPORT_ADMIN_TOKEN;
13186
- if (process.env.EXE_SUPPORT_ADMIN_TOKEN) return process.env.EXE_SUPPORT_ADMIN_TOKEN;
13187
- try {
13188
- const configPath = join4(process.env.EXE_OS_DIR ?? join4(homedir4(), ".exe-os"), "config.json");
13189
- const config = JSON.parse(readFileSync7(configPath, "utf-8"));
13190
- return config.support?.adminToken || config.support?.admin_token;
13191
- } catch {
13192
- return void 0;
13193
- }
13194
- }
13195
- function endpoint() {
13196
- return (process.env.ASKEXE_SUPPORT_ADMIN_ENDPOINT || DEFAULT_ENDPOINT).replace(/\/+$/, "");
13197
- }
13198
- function ownerEndpoint() {
13199
- const routerUrl = process.env.API_ROUTER_URL?.replace(/\/+$/, "");
13200
- let configured;
13201
- try {
13202
- const configPath = join4(process.env.EXE_OS_DIR ?? join4(homedir4(), ".exe-os"), "config.json");
13203
- const config = JSON.parse(readFileSync7(configPath, "utf-8"));
13204
- configured = config.support?.bugReportEndpoint;
13205
- } catch {
13206
- }
13207
- const base = configured || process.env.EXE_BUG_REPORT_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/bug-reports` : DEFAULT_OWNER_ENDPOINT);
13208
- return base.replace(/\/+$/, "");
13209
- }
13210
- function ownerAuthHeaders() {
13211
- let cloudApiKey;
13212
- try {
13213
- const configPath = join4(process.env.EXE_OS_DIR ?? join4(homedir4(), ".exe-os"), "config.json");
13214
- const config = JSON.parse(readFileSync7(configPath, "utf-8"));
13215
- cloudApiKey = config.cloud?.apiKey;
13216
- } catch {
13217
- }
13218
- const licenseKey = loadLicense() || process.env.EXE_LICENSE_KEY || cloudApiKey;
13219
- const licenseToken = readCachedLicenseToken();
13220
- const headers = {};
13221
- if (licenseKey) {
13222
- headers["x-exe-license-key"] = licenseKey;
13223
- headers.authorization = `Bearer ${licenseKey}`;
13224
- }
13225
- if (licenseToken) headers["x-exe-license-token"] = licenseToken;
13226
- return headers;
13227
- }
13228
- function assertInternal() {
13229
- const token = adminToken();
13230
- if (!token) throw new Error("AskExe support admin token not configured");
13231
- return token;
13232
- }
13233
- async function requestJson(url, init) {
13234
- const token = assertInternal();
13235
- const res = await fetch(url, {
13236
- ...init,
13237
- headers: {
13238
- "content-type": "application/json",
13239
- authorization: `Bearer ${token}`,
13240
- ...init?.headers ?? {}
13241
- },
13242
- signal: AbortSignal.timeout(1e4)
13243
- });
13244
- const text5 = await res.text();
13245
- let data = text5;
13246
- try {
13247
- data = text5 ? JSON.parse(text5) : {};
13248
- } catch {
13249
- }
13250
- if (!res.ok) throw new Error(`HTTP ${res.status}: ${typeof data === "string" ? data : JSON.stringify(data)}`);
13251
- return data;
13252
- }
13253
- async function fetchJson(url, headers, init) {
13254
- const res = await fetch(url, {
13255
- ...init,
13256
- headers: { "content-type": "application/json", ...headers, ...init?.headers ?? {} },
13257
- signal: AbortSignal.timeout(1e4)
13258
- });
13259
- const text5 = await res.text();
13260
- let data = text5;
13261
- try {
13262
- data = text5 ? JSON.parse(text5) : {};
13263
- } catch {
13264
- }
13265
- if (!res.ok) throw new Error(`HTTP ${res.status}: ${typeof data === "string" ? data : JSON.stringify(data)}`);
13266
- return data;
13267
- }
13268
- async function commentRequestJson(bugId, init) {
13269
- const token = adminToken();
13270
- if (token) {
13271
- const url2 = `${endpoint()}/${encodeURIComponent(bugId)}/comments`;
13272
- return fetchJson(url2, { authorization: `Bearer ${token}` }, init);
13273
- }
13274
- const ownerHeaders = ownerAuthHeaders();
13275
- if (!ownerHeaders.authorization && !ownerHeaders["x-exe-license-token"]) {
13276
- throw new Error(
13277
- "Not authenticated for support comments. Run `exe-os login` (GoTrue) or set a license key, or configure an AskExe admin token (ASKEXE_SUPPORT_ADMIN_TOKEN)."
13278
- );
13279
- }
13280
- const url = `${ownerEndpoint()}/${encodeURIComponent(bugId)}/comments`;
13281
- return fetchJson(url, ownerHeaders, init);
13282
- }
13283
- function registerListBugReports(server) {
13284
- server.registerTool(
13285
- "list_bug_reports",
13286
- {
13287
- title: "List Bug Reports",
13288
- description: "AskExe-internal only: list incoming customer bug reports from the support inbox.",
13289
- inputSchema: {
13290
- status: z95.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
13291
- severity: z95.enum(["p0", "p1", "p2", "p3"]).optional(),
13292
- limit: z95.number().int().min(1).max(100).default(25)
13293
- }
13294
- },
13295
- async ({ status: status2, severity, limit }) => {
13296
- const url = new URL(endpoint());
13297
- url.searchParams.set("status", status2);
13298
- url.searchParams.set("limit", String(limit));
13299
- if (severity) url.searchParams.set("severity", severity);
13300
- const data = await requestJson(url.toString());
13301
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13302
- }
13303
- );
13304
- }
13305
- function parseComments(row) {
13306
- if (!row || typeof row !== "object") return [];
13307
- const raw = row.progress_log;
13308
- if (typeof raw !== "string" || !raw.trim()) return [];
13309
- try {
13310
- const parsed = JSON.parse(raw);
13311
- return Array.isArray(parsed) ? parsed : [];
13312
- } catch {
13313
- return [];
13314
- }
13315
- }
13316
- function registerGetBugReport(server) {
13317
- server.registerTool(
13318
- "get_bug_report",
13319
- {
13320
- title: "Get Bug Report",
13321
- description: "AskExe-internal only: fetch one customer bug report with full markdown payload and comments thread.",
13322
- inputSchema: { id: z95.string().min(8) }
13323
- },
13324
- async ({ id }) => {
13325
- const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`);
13326
- const comments = parseComments(data);
13327
- const enriched = data && typeof data === "object" ? { ...data, comments } : { id, comments };
13328
- return { content: [{ type: "text", text: JSON.stringify(enriched, null, 2) }] };
13329
- }
13330
- );
13331
- }
13332
- function registerAddBugReportComment(server) {
13333
- server.registerTool(
13334
- "add_bug_report_comment",
13335
- {
13336
- title: "Add Bug Report Comment",
13337
- description: "AskExe-internal only: append a comment to a bug report's thread (POST /comments). Non-destructive \u2014 does not touch triage_notes or status.",
13338
- inputSchema: {
13339
- id: z95.string().min(8),
13340
- comment: z95.string().min(1).describe("Comment text to append to the bug report thread")
13341
- }
13342
- },
13343
- async ({ id, comment }) => {
13344
- const data = await commentRequestJson(id, {
13345
- method: "POST",
13346
- body: JSON.stringify({ comment })
13347
- });
13348
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13349
- }
13350
- );
13351
- }
13352
- function registerGetBugReportComments(server) {
13353
- server.registerTool(
13354
- "get_bug_report_comments",
13355
- {
13356
- title: "Get Bug Report Comments",
13357
- description: "AskExe-internal only: list the comments thread on a bug report (GET /comments).",
13358
- inputSchema: { id: z95.string().min(8) }
13359
- },
13360
- async ({ id }) => {
13361
- const data = await commentRequestJson(id);
13362
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13363
- }
13364
- );
13365
- }
13366
- function registerTriageBugReport(server) {
13367
- server.registerTool(
13368
- "triage_bug_report",
13369
- {
13370
- title: "Triage Bug Report",
13371
- description: "AskExe-internal only: update bug report status and link task/commit/release metadata.",
13372
- inputSchema: {
13373
- id: z95.string().min(8),
13374
- status: STATUS3.optional(),
13375
- triage_notes: z95.string().optional(),
13376
- add_note: z95.string().optional().describe("Append a timestamped progress note without changing status or replacing triage_notes"),
13377
- linked_task_id: z95.string().optional(),
13378
- linked_commit: z95.string().optional(),
13379
- fixed_version: z95.string().optional(),
13380
- product: z95.string().optional().describe("Re-label this bug's product: exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build, exe-chat, exe-auth, exe-monitor, exe-db, exe-erp")
13381
- }
13382
- },
13383
- async ({ id, status: status2, triage_notes, add_note, linked_task_id, linked_commit, fixed_version, product }) => {
13384
- const effectiveStatus = fixed_version && !status2 ? "closed" : status2;
13385
- const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`, {
13386
- method: "PATCH",
13387
- body: JSON.stringify({ status: effectiveStatus, triage_notes, add_note, linked_task_id, linked_commit, fixed_version, product })
13388
- });
13389
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13390
- }
13391
- );
13392
- }
13393
- var FEATURE_STATUS = z95.enum(["open", "planned", "in_progress", "shipped", "closed", "wontdo"]);
13394
- function featureEndpoint() {
13395
- return endpoint().replace(/\/bug-reports\/?$/, "/feature-requests");
13396
- }
13397
- function registerListFeatureRequests(server) {
13398
- server.registerTool(
13399
- "list_feature_requests",
13400
- {
13401
- title: "List Feature Requests",
13402
- description: "AskExe-internal only: list incoming customer feature requests from the support inbox.",
13403
- inputSchema: {
13404
- status: z95.enum(["all", "open", "planned", "in_progress", "shipped", "closed", "wontdo"]).default("open"),
13405
- priority: z95.enum(["p0", "p1", "p2", "p3"]).optional(),
13406
- limit: z95.number().int().min(1).max(100).default(25)
13407
- }
13408
- },
13409
- async ({ status: status2, priority, limit }) => {
13410
- const url = new URL(featureEndpoint());
13411
- url.searchParams.set("status", status2);
13412
- url.searchParams.set("limit", String(limit));
13413
- if (priority) url.searchParams.set("priority", priority);
13414
- const data = await requestJson(url.toString());
13415
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13416
- }
13417
- );
13418
- }
13419
- function registerGetFeatureRequest(server) {
13420
- server.registerTool(
13421
- "get_feature_request",
13422
- {
13423
- title: "Get Feature Request",
13424
- description: "AskExe-internal only: fetch one customer feature request with full payload.",
13425
- inputSchema: { id: z95.string().min(8) }
13426
- },
13427
- async ({ id }) => {
13428
- const data = await requestJson(`${featureEndpoint()}/${encodeURIComponent(id)}`);
13429
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13430
- }
13431
- );
13432
- }
13433
- function registerTriageFeatureRequest(server) {
13434
- server.registerTool(
13435
- "triage_feature_request",
13436
- {
13437
- title: "Triage Feature Request",
13438
- description: "AskExe-internal only: update feature request status, response notes, and version metadata.",
13439
- inputSchema: {
13440
- id: z95.string().min(8),
13441
- status: FEATURE_STATUS.optional(),
13442
- response_notes: z95.string().optional(),
13443
- add_note: z95.string().optional().describe("Append a timestamped progress note without changing status or replacing response_notes"),
13444
- target_version: z95.string().optional(),
13445
- shipped_version: z95.string().optional()
13446
- }
13447
- },
13448
- async ({ id, status: status2, response_notes, add_note, target_version, shipped_version }) => {
13449
- const effectiveStatus = shipped_version && !status2 ? "shipped" : status2;
13450
- const data = await requestJson(`${featureEndpoint()}/${encodeURIComponent(id)}`, {
13451
- method: "PATCH",
13452
- body: JSON.stringify({ status: effectiveStatus, response_notes, add_note, target_version, shipped_version })
13453
- });
13454
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13455
- }
13456
- );
13457
- }
13458
- var REVIEW_STATUS = z95.enum(["open", "in_review", "approved", "merged", "closed", "rejected"]);
13459
- function reviewEndpoint() {
13460
- return endpoint().replace(/\/bug-reports\/?$/, "/reviews");
13461
- }
13462
- function registerListReviews(server) {
13463
- server.registerTool(
13464
- "list_reviews",
13465
- {
13466
- title: "List Reviews",
13467
- description: "AskExe-internal only: list incoming review requests from the support inbox.",
13468
- inputSchema: {
13469
- status: z95.enum(["all", "open", "in_review", "approved", "merged", "closed", "rejected"]).default("open"),
13470
- priority: z95.enum(["p0", "p1", "p2", "p3"]).optional(),
13471
- limit: z95.number().int().min(1).max(100).default(25)
13472
- }
13473
- },
13474
- async ({ status: status2, priority, limit }) => {
13475
- const url = new URL(reviewEndpoint());
13476
- url.searchParams.set("status", status2);
13477
- url.searchParams.set("limit", String(limit));
13478
- if (priority) url.searchParams.set("priority", priority);
13479
- const data = await requestJson(url.toString());
13480
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13481
- }
13482
- );
13483
- }
13484
- function registerGetReview(server) {
13485
- server.registerTool(
13486
- "get_review",
13487
- {
13488
- title: "Get Review",
13489
- description: "AskExe-internal only: fetch one review with full payload.",
13490
- inputSchema: { id: z95.string().min(8) }
13491
- },
13492
- async ({ id }) => {
13493
- const data = await requestJson(`${reviewEndpoint()}/${encodeURIComponent(id)}`);
13494
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13495
- }
13496
- );
13497
- }
13498
- function registerTriageReview(server) {
13499
- server.registerTool(
13500
- "triage_review",
13501
- {
13502
- title: "Triage Review",
13503
- description: "AskExe-internal only: update review status, response notes, and resolution.",
13504
- inputSchema: {
13505
- id: z95.string().min(8),
13506
- status: REVIEW_STATUS.optional(),
13507
- response_notes: z95.string().optional(),
13508
- add_note: z95.string().optional().describe("Append a timestamped progress note without changing status or replacing response_notes"),
13509
- resolution: z95.string().optional(),
13510
- pr_url: z95.string().optional()
13511
- }
13512
- },
13513
- async ({ id, status: status2, response_notes, add_note, resolution, pr_url }) => {
13514
- const data = await requestJson(`${reviewEndpoint()}/${encodeURIComponent(id)}`, {
13515
- method: "PATCH",
13516
- body: JSON.stringify({ status: status2, response_notes, add_note, resolution, pr_url })
13517
- });
13518
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
13519
- }
13520
- );
13521
- }
13522
-
13523
13400
  // src/mcp/tools/decision.ts
13524
- import { z as z96 } from "zod";
13401
+ import { z as z95 } from "zod";
13525
13402
  function buildHandlers6() {
13526
13403
  const tools = /* @__PURE__ */ new Map();
13527
13404
  const fake = {
@@ -13545,12 +13422,12 @@ function registerDecision(server) {
13545
13422
  title: "Decision",
13546
13423
  description: "Store or retrieve authoritative decisions. Actions: store (persist a decision by domain), get (look up a decision by domain/query).",
13547
13424
  inputSchema: {
13548
- action: z96.enum(["store", "get"]).describe("Decision operation"),
13549
- domain: z96.string().optional().describe("Decision domain (e.g. 'architecture', 'hiring')"),
13550
- decision: z96.string().optional().describe("Decision text for action=store"),
13551
- rationale: z96.string().optional().describe("Why this decision was made (action=store)"),
13552
- query: z96.string().optional().describe("Search query for action=get"),
13553
- limit: z96.coerce.number().optional().describe("Max results for action=get")
13425
+ action: z95.enum(["store", "get"]).describe("Decision operation"),
13426
+ domain: z95.string().optional().describe("Decision domain (e.g. 'architecture', 'hiring')"),
13427
+ decision: z95.string().optional().describe("Decision text for action=store"),
13428
+ rationale: z95.string().optional().describe("Why this decision was made (action=store)"),
13429
+ query: z95.string().optional().describe("Search query for action=get"),
13430
+ limit: z95.coerce.number().optional().describe("Max results for action=get")
13554
13431
  }
13555
13432
  },
13556
13433
  async (input, extra) => {
@@ -13566,7 +13443,7 @@ function registerDecision(server) {
13566
13443
  }
13567
13444
 
13568
13445
  // src/mcp/tools/session.ts
13569
- import { z as z97 } from "zod";
13446
+ import { z as z96 } from "zod";
13570
13447
  function buildHandlers7() {
13571
13448
  const tools = /* @__PURE__ */ new Map();
13572
13449
  const fake = {
@@ -13614,17 +13491,17 @@ function registerSession(server) {
13614
13491
  title: "Session",
13615
13492
  description: "Session tools. Actions: events (session event log), last_response (most recent assistant text), set_mode (enter explore or task mode), get_mode (query current mode and active explore sessions).",
13616
13493
  inputSchema: {
13617
- action: z97.enum(["events", "last_response", "set_mode", "get_mode"]).describe("Session operation"),
13618
- session_id: z97.string().optional().describe("Session ID for action=events"),
13619
- limit: z97.coerce.number().optional().describe("Max events for action=events"),
13494
+ action: z96.enum(["events", "last_response", "set_mode", "get_mode"]).describe("Session operation"),
13495
+ session_id: z96.string().optional().describe("Session ID for action=events"),
13496
+ limit: z96.coerce.number().optional().describe("Max events for action=events"),
13620
13497
  // set_mode params
13621
- mode: z97.enum(["explore", "task"]).optional().describe(
13498
+ mode: z96.enum(["explore", "task"]).optional().describe(
13622
13499
  "Mode for action=set_mode. 'explore' = divergent, no deliverable, nudges suppressed. 'task' = default convergent behaviour (resets any active explore session)."
13623
13500
  ),
13624
- duration_minutes: z97.number().optional().describe(
13501
+ duration_minutes: z96.number().optional().describe(
13625
13502
  `How long to stay in explore mode in minutes (action=set_mode, mode=explore). Default: ${DEFAULT_EXPLORE_DURATION_MS / 6e4} minutes (1 hour).`
13626
13503
  ),
13627
- notes: z97.string().optional().describe("Optional notes about this explore session (action=set_mode)")
13504
+ notes: z96.string().optional().describe("Optional notes about this explore session (action=set_mode)")
13628
13505
  }
13629
13506
  },
13630
13507
  async (input, extra) => {
@@ -13689,14 +13566,13 @@ All active explore sessions (${active.length}):
13689
13566
  }
13690
13567
 
13691
13568
  // src/mcp/tools/support-consolidated.ts
13692
- import { z as z99 } from "zod";
13569
+ import { z as z98 } from "zod";
13693
13570
 
13694
13571
  // src/mcp/tools/create-review.ts
13695
- import { z as z98 } from "zod";
13572
+ import { z as z97 } from "zod";
13696
13573
  import crypto6 from "crypto";
13697
- import { mkdir as mkdir4, writeFile as writeFile6 } from "fs/promises";
13698
13574
  import path17 from "path";
13699
- var PRIORITY2 = z98.enum(["p0", "p1", "p2", "p3"]);
13575
+ var PRIORITY2 = z97.enum(["p0", "p1", "p2", "p3"]);
13700
13576
  function slugify3(input) {
13701
13577
  return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "review";
13702
13578
  }
@@ -13725,15 +13601,15 @@ function buildMarkdown3(input) {
13725
13601
  async function maybeSendUpstream3(payload) {
13726
13602
  const config = await loadConfig();
13727
13603
  const routerUrl = process.env.API_ROUTER_URL?.replace(/\/+$/, "");
13728
- const endpoint2 = config.support?.reviewEndpoint || process.env.EXE_REVIEW_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/reviews` : "https://api.askexe.com/v1/support/reviews");
13604
+ const endpoint = config.support?.reviewEndpoint || process.env.EXE_REVIEW_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support/reviews` : "https://api.askexe.com/v1/support/reviews");
13729
13605
  const token = config.support?.reviewToken || process.env.EXE_REVIEW_TOKEN;
13730
13606
  const licenseKey = loadLicense() || process.env.EXE_LICENSE_KEY || config.cloud?.apiKey;
13731
13607
  const licenseToken = readCachedLicenseToken();
13732
- if (!endpoint2) {
13608
+ if (!endpoint) {
13733
13609
  return "not_configured";
13734
13610
  }
13735
13611
  try {
13736
- const parsed = new URL(endpoint2);
13612
+ const parsed = new URL(endpoint);
13737
13613
  if (parsed.protocol !== "https:" && !["localhost", "127.0.0.1", "::1"].includes(parsed.hostname)) {
13738
13614
  return "failed: insecure endpoint rejected";
13739
13615
  }
@@ -13746,7 +13622,10 @@ async function maybeSendUpstream3(payload) {
13746
13622
  ...licenseToken ? { "x-exe-license-token": licenseToken } : {},
13747
13623
  ...supportAdminHeaders(config)
13748
13624
  },
13749
- body: JSON.stringify(payload),
13625
+ // Egress redaction gate (dc16fee4) — redact secrets from description +
13626
+ // rendered markdown before the network send. No disk outbox for reviews,
13627
+ // so this direct send is the only path.
13628
+ body: sanitizedUpstreamBody(payload, "create-review"),
13750
13629
  signal: AbortSignal.timeout(1e4)
13751
13630
  });
13752
13631
  if (!response.ok) return `failed: HTTP ${response.status}`;
@@ -13762,17 +13641,18 @@ function registerCreateReview(server) {
13762
13641
  title: "Create Review",
13763
13642
  description: "File a review request (code review, self-improvement findings, PR review needs). Writes a local report, stores memory, and optionally sends to AskExe support.",
13764
13643
  inputSchema: {
13765
- title: z98.string().min(3).describe("Short descriptive title"),
13766
- description: z98.string().optional().describe("What needs review and why"),
13644
+ title: z97.string().min(3).describe("Short descriptive title"),
13645
+ description: z97.string().optional().describe("What needs review and why"),
13767
13646
  priority: PRIORITY2.default("p1").describe("p0 critical -> p3 low"),
13768
- source: z98.string().optional().describe("Source: self-improve, manual, ci, etc."),
13769
- pr_url: z98.string().optional().describe("PR URL if applicable"),
13770
- product: z98.string().optional().describe("Product: exe-os (default), exe-create, exe-wiki, exe-gateway, exe-crm, exe-build"),
13771
- package_version: z98.string().optional().describe("Installed package version"),
13772
- project_name: z98.string().optional().describe("Project/customer context"),
13773
- send_upstream: z98.boolean().default(false).describe("Attempt to POST to configured AskExe support endpoint (disabled by default \u2014 review route not yet live)")
13647
+ source: z97.string().optional().describe("Source: self-improve, manual, ci, etc."),
13648
+ pr_url: z97.string().optional().describe("PR URL if applicable"),
13649
+ product: supportProductSchema.optional().describe("Product: exe-os (default), exe-create, exe-wiki, exe-gateway, exe-crm, exe-build"),
13650
+ package_version: z97.string().optional().describe("Installed package version"),
13651
+ project_name: z97.string().optional().describe("Project/customer context"),
13652
+ send_upstream: z97.boolean().default(false).describe("Attempt to POST to configured AskExe support endpoint (disabled by default \u2014 review route not yet live)")
13774
13653
  }
13775
13654
  },
13655
+ // Structural sink guard (round 6): deep-redact the whole return object + errors.
13776
13656
  async ({
13777
13657
  title,
13778
13658
  description,
@@ -13783,11 +13663,11 @@ function registerCreateReview(server) {
13783
13663
  package_version,
13784
13664
  project_name,
13785
13665
  send_upstream
13786
- }) => {
13666
+ }) => redactedToolResult(async () => {
13787
13667
  const { agentId, agentRole } = getActiveAgent();
13788
13668
  const id = crypto6.randomUUID();
13789
13669
  const resolvedProduct = product ?? "exe-os";
13790
- const version = package_version ?? "unknown";
13670
+ const version = sanitizeVersionField(package_version) ?? "unknown";
13791
13671
  const markdown = buildMarkdown3({
13792
13672
  id,
13793
13673
  title,
@@ -13802,36 +13682,29 @@ function registerCreateReview(server) {
13802
13682
  projectName: project_name
13803
13683
  });
13804
13684
  const outDir = path17.join(EXE_AI_DIR, "reviews");
13805
- await mkdir4(outDir, { recursive: true });
13806
- const reportPath = path17.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify3(title)}-${id.slice(0, 8)}.md`);
13807
- await writeFile6(reportPath, markdown, "utf-8");
13808
- let vector = null;
13809
- try {
13810
- vector = await embed(markdown);
13811
- } catch {
13812
- vector = null;
13813
- }
13814
- await writeMemory({
13815
- id,
13816
- agent_id: agentId,
13817
- agent_role: agentRole,
13818
- session_id: process.env.SESSION_ID ?? "manual",
13819
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13820
- tool_name: "create_review",
13821
- project_name: project_name ?? "support",
13822
- has_error: false,
13823
- raw_text: markdown,
13824
- vector,
13825
- source_path: reportPath,
13826
- source_type: "review",
13827
- memory_type: "review",
13828
- tier: 1,
13829
- importance: priority === "p0" ? 10 : priority === "p1" ? 9 : priority === "p2" ? 7 : 5,
13830
- intent: "review",
13831
- domain: "support",
13832
- file_paths: null
13685
+ const reportPath = path17.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify3(redactSecrets(title).text)}-${id.slice(0, 8)}.md`);
13686
+ await persistSupportArtifact({
13687
+ memoryText: markdown,
13688
+ file: { path: reportPath, content: markdown },
13689
+ memory: {
13690
+ id,
13691
+ agent_id: agentId,
13692
+ agent_role: agentRole,
13693
+ session_id: process.env.SESSION_ID ?? "manual",
13694
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13695
+ tool_name: "create_review",
13696
+ project_name: project_name ?? "support",
13697
+ has_error: false,
13698
+ source_path: reportPath,
13699
+ source_type: "review",
13700
+ memory_type: "review",
13701
+ tier: 1,
13702
+ importance: priority === "p0" ? 10 : priority === "p1" ? 9 : priority === "p2" ? 7 : 5,
13703
+ intent: "review",
13704
+ domain: "support",
13705
+ file_paths: null
13706
+ }
13833
13707
  });
13834
- await flushBatch();
13835
13708
  const upstreamPayload = {
13836
13709
  id,
13837
13710
  title,
@@ -13864,7 +13737,7 @@ Upstream status: ${upstreamStatus}`
13864
13737
  }
13865
13738
  ]
13866
13739
  };
13867
- }
13740
+ })
13868
13741
  );
13869
13742
  }
13870
13743
 
@@ -13924,9 +13797,9 @@ function registerSupportConsolidated(server) {
13924
13797
  "support",
13925
13798
  {
13926
13799
  title: "Support",
13927
- description: "Bug reports, feature requests, reviews, and support system. Actions: create_bug, create_feature, create_review, update_bug, update_feature, list_my_bugs, list_my_features, list_my_reviews, list_bugs, get_bug, add_comment, get_comments, triage_bug, list_features, get_feature, triage_feature, list_reviews, get_review, triage_review, health, test. Use 'product' param to file bugs for any AskExe product.",
13800
+ description: "Bug reports, feature requests, reviews, and support system. Actions: create_bug, create_feature, create_review, update_bug, update_feature, list_my_bugs, list_my_features, list_my_reviews, list_bugs, get_bug, add_comment, get_comments, triage_bug, list_features, get_feature, triage_feature, list_reviews, get_review, triage_review, health, test. Use 'product' param to file/route bugs AND feature requests for any AskExe product.",
13928
13801
  inputSchema: {
13929
- action: z99.enum([
13802
+ action: z98.enum([
13930
13803
  "create_bug",
13931
13804
  "create_feature",
13932
13805
  "create_review",
@@ -13949,40 +13822,68 @@ function registerSupportConsolidated(server) {
13949
13822
  "health",
13950
13823
  "test"
13951
13824
  ]).describe("Support operation"),
13952
- title: z99.string().optional().describe("Bug/feature title"),
13953
- description: z99.string().optional().describe("Bug/feature description"),
13954
- steps_to_reproduce: z99.string().optional().describe("Steps to reproduce (bugs)"),
13955
- expected_behavior: z99.string().optional().describe("Expected behavior (bugs)"),
13956
- actual_behavior: z99.string().optional().describe("Actual behavior (bugs)"),
13957
- severity: z99.string().optional().describe("Severity: p0/p1/p2/p3"),
13958
- product: z99.string().optional().describe("Product (create_bug default exe-os; also re-labels a bug via update_bug, admin only): exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build, exe-chat, exe-auth, exe-monitor, exe-db, exe-erp"),
13959
- use_case: z99.string().optional().describe("Use case (features)"),
13960
- proposed_solution: z99.string().optional().describe("Proposed solution (features)"),
13961
- priority: z99.string().optional().describe("Priority (features)"),
13962
- on_behalf_of_email: z99.string().email().optional().describe("ADMIN ONLY: file this request owned by another customer's license email; ignored unless caller holds the support admin token (create_bug/create_feature)"),
13963
- id: z99.string().optional().describe("Bug/feature ID for get/triage/add_comment/get_comments"),
13964
- comment: z99.string().optional().describe("Comment text to append to a bug report thread (add_comment)"),
13965
- status: z99.string().optional().describe("Filter by status"),
13966
- classification: z99.string().optional().describe("Triage classification"),
13967
- resolution: z99.string().optional().describe("Triage resolution"),
13968
- notes: z99.string().optional().describe("Triage notes (mapped to triage_notes for bug/feature triage)"),
13969
- triage_notes: z99.string().optional().describe("Triage notes (legacy field name)"),
13970
- linked_task_id: z99.string().optional().describe("Linked task ID for triage"),
13971
- linked_commit: z99.string().optional().describe("Linked commit hash for triage"),
13972
- fixed_version: z99.string().optional().describe("Version that fixes this bug"),
13973
- shipped_version: z99.string().optional().describe("Version that ships this feature (features only)"),
13974
- add_evidence: z99.string().optional().describe("Owner self-service: additional evidence (logs, repro, stack traces) for update_bug"),
13975
- reopen_request: z99.boolean().optional().describe("Owner self-service: request a reopen on a recurring fixed bug (update_bug)"),
13976
- reopen_reason: z99.string().optional().describe("Owner self-service: why the bug should be reopened (update_bug)"),
13977
- attachments: z99.array(z99.object({
13978
- filename: z99.string().min(1).describe("Filename for the attachment"),
13979
- content: z99.string().min(1).describe("File content \u2014 plain text")
13825
+ title: z98.string().optional().describe("Bug/feature title"),
13826
+ description: z98.string().optional().describe("Bug/feature description"),
13827
+ steps_to_reproduce: z98.string().optional().describe("Steps to reproduce (bugs)"),
13828
+ expected_behavior: z98.string().optional().describe("Expected behavior (bugs)"),
13829
+ actual_behavior: z98.string().optional().describe("Actual behavior (bugs)"),
13830
+ // Round 10: these are ENUM fields — on list actions they reach the vendor URL
13831
+ // query, and on triage/create the body. Constrained to the UNION of valid values
13832
+ // across bug/feature/review actions so a non-enum value is rejected at ingress.
13833
+ severity: z98.enum(["p0", "p1", "p2", "p3"]).optional().describe("Severity: p0/p1/p2/p3"),
13834
+ // bug b8e990ed: product works for BOTH bugs and features (create default exe-os;
13835
+ // list_bugs/list_features filter; triage_bug/triage_feature admin re-label).
13836
+ // Kept on the strict ingress schema (round 10) rather than a loose string.
13837
+ product: supportProductSchema.optional().describe("Product \u2014 works for BOTH bugs and features (create default exe-os; list_bugs/list_features filter; triage_bug/triage_feature admin re-label): exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build, exe-chat, exe-auth, exe-monitor, exe-db, exe-erp"),
13838
+ use_case: z98.string().optional().describe("Use case (features)"),
13839
+ proposed_solution: z98.string().optional().describe("Proposed solution (features)"),
13840
+ priority: z98.enum(["p0", "p1", "p2", "p3"]).optional().describe("Priority (features)"),
13841
+ on_behalf_of_email: z98.string().email().optional().describe("ADMIN ONLY: file this request owned by another customer's license email; ignored unless caller holds the support admin token (create_bug/create_feature)"),
13842
+ // Round 10: constrained fields are shape-validated at ingress (this is the
13843
+ // DEFAULT surface and calls handlers directly, bypassing their per-tool schemas).
13844
+ id: supportIdSchema.optional().describe("Bug/feature ID for get/triage/add_comment/get_comments"),
13845
+ comment: z98.string().optional().describe("Comment text to append to a bug report thread (add_comment)"),
13846
+ status: z98.enum([
13847
+ "all",
13848
+ "open",
13849
+ "triaged",
13850
+ "fixed",
13851
+ "closed",
13852
+ "wontfix",
13853
+ "planned",
13854
+ "in_progress",
13855
+ "shipped",
13856
+ "wontdo",
13857
+ "in_review",
13858
+ "approved",
13859
+ "merged",
13860
+ "rejected"
13861
+ ]).optional().describe("Filter by status (union across bug/feature/review)"),
13862
+ classification: z98.enum([
13863
+ "upstream_bug",
13864
+ "customer_customization",
13865
+ "emergency_hotfix",
13866
+ "unclear"
13867
+ ]).optional().describe("Triage classification"),
13868
+ resolution: z98.string().optional().describe("Triage resolution"),
13869
+ notes: z98.string().optional().describe("Triage notes (mapped to triage_notes for bug/feature triage)"),
13870
+ triage_notes: z98.string().optional().describe("Triage notes (legacy field name)"),
13871
+ linked_task_id: supportTaskIdSchema.optional().describe("Linked task ID for triage"),
13872
+ linked_commit: supportCommitSchema.optional().describe("Linked commit hash for triage"),
13873
+ fixed_version: supportVersionSchema.optional().describe("Version that fixes this bug"),
13874
+ shipped_version: supportVersionSchema.optional().describe("Version that ships this feature (features only)"),
13875
+ add_evidence: z98.string().optional().describe("Owner self-service: additional evidence (logs, repro, stack traces) for update_bug"),
13876
+ reopen_request: z98.boolean().optional().describe("Owner self-service: request a reopen on a recurring fixed bug (update_bug)"),
13877
+ reopen_reason: z98.string().optional().describe("Owner self-service: why the bug should be reopened (update_bug)"),
13878
+ attachments: z98.array(z98.object({
13879
+ filename: z98.string().min(1).describe("Filename for the attachment"),
13880
+ content: z98.string().min(1).describe("File content \u2014 plain text")
13980
13881
  })).optional().describe("File attachments for bug reports / feature requests (diffs, logs, config snippets)"),
13981
- source: z99.string().optional().describe("Review source: self-improve, manual, ci"),
13982
- pr_url: z99.string().optional().describe("PR URL (reviews)"),
13983
- review_resolution: z99.string().optional().describe("Resolution text (reviews)"),
13984
- limit: z99.coerce.number().optional().describe("Max results per page (up to 500)"),
13985
- offset: z99.coerce.number().optional().describe("Number of results to skip for pagination (list_my_bugs/list_my_features). Use next_offset from a prior response.")
13882
+ source: z98.string().optional().describe("Review source: self-improve, manual, ci"),
13883
+ pr_url: z98.string().optional().describe("PR URL (reviews)"),
13884
+ review_resolution: z98.string().optional().describe("Resolution text (reviews)"),
13885
+ limit: z98.coerce.number().int().min(1).max(500).optional().describe("Max results per page (up to 500)"),
13886
+ offset: z98.coerce.number().int().min(0).optional().describe("Number of results to skip for pagination (list_bugs, list_features, list_reviews, list_my_bugs, list_my_features). Use next_offset from a prior response.")
13986
13887
  }
13987
13888
  },
13988
13889
  async (input, extra) => {
@@ -14068,7 +13969,7 @@ function registerSupportConsolidated(server) {
14068
13969
  }
14069
13970
 
14070
13971
  // src/mcp/tools/diagnostics.ts
14071
- import { z as z100 } from "zod";
13972
+ import { z as z99 } from "zod";
14072
13973
  function buildHandlers9() {
14073
13974
  const tools = /* @__PURE__ */ new Map();
14074
13975
  const fake = {
@@ -14082,28 +13983,28 @@ function buildHandlers9() {
14082
13983
  function registerDiagnostics(server) {
14083
13984
  const handlers = buildHandlers9();
14084
13985
  const toolNames = Array.from(handlers.keys());
14085
- toolNames.push("tool_search", "drift", "merge_agent_memories", "agent_liveness", "steward_check", "steward_audit_log", "steward_override", "daemon_restarts", "spawn_failures", "orchestration_health", "work_map");
13986
+ toolNames.push("tool_search", "drift", "merge_agent_memories", "agent_liveness", "steward_check", "steward_audit_log", "steward_override", "daemon_restarts", "timers", "spawn_failures", "orchestration_health", "work_map");
14086
13987
  server.registerTool(
14087
13988
  "diagnostics",
14088
13989
  {
14089
13990
  title: "Diagnostics",
14090
- description: `System diagnostics and admin operations. Actions: ${toolNames.join(", ")}. Covers health checks, update status, cloud status, key management, employee rename, semantic tool discovery (tool_search), identity drift detection (drift), agent liveness monitoring (agent_liveness), agent memory reassignment (merge_agent_memories), steward identity gate (steward_check, steward_audit_log, steward_override), daemon restart forensics (daemon_restarts \u2014 'why did the daemon restart?': restart-cause breakdown, slowest-timer leaderboard, event-loop-block frequency), and orchestration-health visibility: spawn_failures ('why did dispatch fail?': tmux spawn fail count + cause breakdown path_not_found/claude_launch_failed/timeout + success-vs-fail ratio), orchestration_health ('is the box healthy / is the spiral happening?': load/core, event-loop lag, direct-SQLite-fallback count, event-loop blocks), and work_map ('who's doing what / who died and why?': live sessions \xD7 role \xD7 task \xD7 worktree flag, plus recent session deaths with cause/load + worktree violations).`,
13991
+ description: `System diagnostics and admin operations. Actions: ${toolNames.join(", ")}. Covers health checks, update status, cloud status, key management, employee rename, semantic tool discovery (tool_search), identity drift detection (drift), agent liveness monitoring (agent_liveness), agent memory reassignment (merge_agent_memories), steward identity gate (steward_check, steward_audit_log, steward_override), daemon restart forensics (daemon_restarts \u2014 'why did the daemon restart?': restart-cause breakdown, slowest-timer leaderboard, event-loop-block frequency), timer health dashboard (timers \u2014 'which background timer is about to take the daemon down?': per-timer last/avg/p95/max tick duration, watchdog trips past the 10s event-loop-block budget, whether the timer is executing right now, projected next fire \u2014 sorted worst-first; read-only over already-emitted daemon health logs), and orchestration-health visibility: spawn_failures ('why did dispatch fail?': tmux spawn fail count + cause breakdown path_not_found/claude_launch_failed/timeout + success-vs-fail ratio), orchestration_health ('is the box healthy / is the spiral happening?': load/core, event-loop lag, direct-SQLite-fallback count, event-loop blocks), and work_map ('who's doing what / who died and why?': live sessions \xD7 role \xD7 task \xD7 worktree flag, plus recent session deaths with cause/load + worktree violations).`,
14091
13992
  inputSchema: {
14092
- action: z100.string().describe(`Diagnostic operation: ${toolNames.join(", ")}`),
13993
+ action: z99.string().describe(`Diagnostic operation: ${toolNames.join(", ")}`),
14093
13994
  // Pass-through params used by various sub-tools
14094
- agent_id: z100.string().optional().describe("Agent to probe (drift). Defaults to all agents."),
14095
- name: z100.string().optional().describe("Employee name (rename_employee)"),
14096
- new_name: z100.string().optional().describe("New employee name (rename_employee)"),
14097
- query: z100.string().optional().describe("Search/filter query, or natural language for tool_search"),
14098
- format: z100.string().optional().describe("Output format"),
14099
- limit: z100.coerce.number().int().min(1).max(100).optional().describe("Max results for tool_search (default 20)"),
14100
- from_agent_id: z100.string().optional().describe("Source agent ID to merge from (merge_agent_memories)"),
14101
- to_agent_id: z100.string().optional().describe("Target agent ID to merge into (merge_agent_memories)"),
14102
- dry_run: z100.boolean().optional().default(true).describe("Preview mode \u2014 show count without changing (merge_agent_memories). Default: true"),
13995
+ agent_id: z99.string().optional().describe("Agent to probe (drift). Defaults to all agents."),
13996
+ name: z99.string().optional().describe("Employee name (rename_employee)"),
13997
+ new_name: z99.string().optional().describe("New employee name (rename_employee)"),
13998
+ query: z99.string().optional().describe("Search/filter query, or natural language for tool_search"),
13999
+ format: z99.string().optional().describe("Output format"),
14000
+ limit: z99.coerce.number().int().min(1).max(100).optional().describe("Max results for tool_search (default 20)"),
14001
+ from_agent_id: z99.string().optional().describe("Source agent ID to merge from (merge_agent_memories)"),
14002
+ to_agent_id: z99.string().optional().describe("Target agent ID to merge into (merge_agent_memories)"),
14003
+ dry_run: z99.boolean().optional().default(true).describe("Preview mode \u2014 show count without changing (merge_agent_memories). Default: true"),
14103
14004
  // Steward params (absorbed from steward tool)
14104
- operation: z100.string().optional().describe("Operation name for steward_check/steward_override"),
14105
- target: z100.string().optional().describe("Target resource for steward_check/steward_override"),
14106
- reason: z100.string().optional().describe("Override reason for steward_override")
14005
+ operation: z99.string().optional().describe("Operation name for steward_check/steward_override"),
14006
+ target: z99.string().optional().describe("Target resource for steward_check/steward_override"),
14007
+ reason: z99.string().optional().describe("Override reason for steward_override")
14107
14008
  }
14108
14009
  },
14109
14010
  async (input, extra) => {
@@ -14136,6 +14037,21 @@ function registerDiagnostics(server) {
14136
14037
  return { content: [{ type: "text", text: `daemon_restarts failed: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
14137
14038
  }
14138
14039
  }
14040
+ if (action === "timers") {
14041
+ try {
14042
+ const { buildLiveTimerReport, formatTimerReport } = await import("./daemon-timer-report-NM44WQRH.js");
14043
+ const report = await buildLiveTimerReport();
14044
+ const asJson = input.format === "json";
14045
+ return {
14046
+ content: [{
14047
+ type: "text",
14048
+ text: asJson ? JSON.stringify(report, null, 2) : formatTimerReport(report)
14049
+ }]
14050
+ };
14051
+ } catch (err) {
14052
+ return { content: [{ type: "text", text: `timers failed: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
14053
+ }
14054
+ }
14139
14055
  if (action === "spawn_failures") {
14140
14056
  return handleSpawnFailures();
14141
14057
  }
@@ -14268,7 +14184,7 @@ async function handleMergeAgentMemories(input) {
14268
14184
  }
14269
14185
  async function handleSpawnFailures() {
14270
14186
  try {
14271
- const { getOrchestrationMetrics } = await import("./orchestration-events-5SIJOE4H.js");
14187
+ const { getOrchestrationMetrics } = await import("./orchestration-events-WV4NWKZH.js");
14272
14188
  const metrics = await getOrchestrationMetrics();
14273
14189
  const c = metrics.counts;
14274
14190
  const attempted = c.tmuxSpawnAttempted;
@@ -14370,7 +14286,7 @@ async function handleOrchestrationHealth() {
14370
14286
  async function handleWorkMap() {
14371
14287
  try {
14372
14288
  const { getAgentLivenessReport } = await import("./agent-heartbeat-I5UPGXAU.js");
14373
- const { classifyRole } = await import("./session-kill-telemetry-CZSPN5V6.js");
14289
+ const { classifyRole } = await import("./session-kill-telemetry-AELE4JDK.js");
14374
14290
  const { buildSessionDeathSummary } = await import("./orchestration-health-read-EJWVUARG.js");
14375
14291
  const { getPaneCwd } = await import("./lib/tmux-status.js");
14376
14292
  const live = getAgentLivenessReport();
@@ -14505,7 +14421,7 @@ async function handleDrift(input) {
14505
14421
  }
14506
14422
  async function handleSteward(action, input) {
14507
14423
  const gate = new StewardGate();
14508
- const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-EC6M7KTX.js");
14424
+ const { getActiveAgent: getActiveAgent2 } = await import("./active-agent-PVGE57FY.js");
14509
14425
  const inputAgent = input.agent_id;
14510
14426
  const operation = input.operation;
14511
14427
  const target = input.target;
@@ -14553,7 +14469,7 @@ async function handleSteward(action, input) {
14553
14469
  }
14554
14470
 
14555
14471
  // src/mcp/tools/dreaming.ts
14556
- import { z as z101 } from "zod";
14472
+ import { z as z100 } from "zod";
14557
14473
  function registerDreaming(server) {
14558
14474
  server.registerTool(
14559
14475
  "dreaming",
@@ -14561,10 +14477,10 @@ function registerDreaming(server) {
14561
14477
  title: "Dreaming",
14562
14478
  description: "Self-improvement loop \u2014 reviews recent work, identifies patterns, proposes behavior changes, and detects identity drift. Actions: run (execute dream cycle), status (last cycle result), history (past cycles).",
14563
14479
  inputSchema: {
14564
- action: z101.enum(["run", "status", "history"]).describe("Action to perform"),
14565
- agent_id: z101.string().optional().describe("Agent to analyze. Defaults to calling agent."),
14566
- hours: z101.coerce.number().min(1).max(720).optional().describe("Lookback window in hours (run). Default 24."),
14567
- limit: z101.coerce.number().int().min(1).max(50).optional().describe("Max results for history. Default 10.")
14480
+ action: z100.enum(["run", "status", "history"]).describe("Action to perform"),
14481
+ agent_id: z100.string().optional().describe("Agent to analyze. Defaults to calling agent."),
14482
+ hours: z100.coerce.number().min(1).max(720).optional().describe("Lookback window in hours (run). Default 24."),
14483
+ limit: z100.coerce.number().int().min(1).max(50).optional().describe("Max results for history. Default 10.")
14568
14484
  }
14569
14485
  },
14570
14486
  async ({ action, agent_id, hours, limit }) => {
@@ -14687,7 +14603,7 @@ ${String(row.raw_text)}`
14687
14603
  }
14688
14604
 
14689
14605
  // src/mcp/tools/steward.ts
14690
- import { z as z102 } from "zod";
14606
+ import { z as z101 } from "zod";
14691
14607
  function errorResult11(text5) {
14692
14608
  return { content: [{ type: "text", text: text5 }], isError: true };
14693
14609
  }
@@ -14699,12 +14615,12 @@ function registerSteward(server) {
14699
14615
  title: "Steward Identity Gate",
14700
14616
  description: "Constitutional check before destructive operations. action=check: verify agent authority for an operation. action=audit_log: query the audit trail. action=override: coordinator-only bypass with reason.",
14701
14617
  inputSchema: {
14702
- action: z102.enum(["check", "audit_log", "override"]).describe("Steward operation to perform"),
14703
- agent: z102.string().optional().describe("Agent to check (defaults to calling agent for action=check)"),
14704
- operation: z102.string().optional().describe("Operation name (required for check/override)"),
14705
- target: z102.string().optional().describe("Target resource (required for check/override)"),
14706
- reason: z102.string().optional().describe("Override reason (required for action=override)"),
14707
- limit: z102.number().optional().describe("Max audit entries to return (default: 50)")
14618
+ action: z101.enum(["check", "audit_log", "override"]).describe("Steward operation to perform"),
14619
+ agent: z101.string().optional().describe("Agent to check (defaults to calling agent for action=check)"),
14620
+ operation: z101.string().optional().describe("Operation name (required for check/override)"),
14621
+ target: z101.string().optional().describe("Target resource (required for check/override)"),
14622
+ reason: z101.string().optional().describe("Override reason (required for action=override)"),
14623
+ limit: z101.number().optional().describe("Max audit entries to return (default: 50)")
14708
14624
  }
14709
14625
  },
14710
14626
  async (input) => {
@@ -14787,7 +14703,7 @@ function registerSteward(server) {
14787
14703
  }
14788
14704
 
14789
14705
  // src/mcp/tools/resonance.ts
14790
- import { z as z103 } from "zod";
14706
+ import { z as z102 } from "zod";
14791
14707
  function text4(content, isError = false) {
14792
14708
  return { content: [{ type: "text", text: content }], ...isError ? { isError: true } : {} };
14793
14709
  }
@@ -14796,14 +14712,14 @@ function registerResonance(server) {
14796
14712
  title: "Resonance Network",
14797
14713
  description: "Co-activation network queries. Actions: hot_pairs (top co-activated memory pairs), neighbors (co-activation neighbors for a specific memory).",
14798
14714
  inputSchema: {
14799
- action: z103.enum(["hot_pairs", "neighbors"]).describe("Resonance query type"),
14800
- memory_id: z103.string().optional().describe("Memory ID for neighbors action"),
14801
- entity_id: z103.string().optional().describe("Deprecated alias for memory_id on neighbors action"),
14802
- limit: z103.number().optional().describe("Max results (default 20)")
14715
+ action: z102.enum(["hot_pairs", "neighbors"]).describe("Resonance query type"),
14716
+ memory_id: z102.string().optional().describe("Memory ID for neighbors action"),
14717
+ entity_id: z102.string().optional().describe("Deprecated alias for memory_id on neighbors action"),
14718
+ limit: z102.number().optional().describe("Max results (default 20)")
14803
14719
  }
14804
14720
  }, async ({ action, memory_id, entity_id, limit }) => {
14805
14721
  try {
14806
- const { getHotPairs, getCoActivationNeighbors } = await import("./co-activation-XMPHKGHR.js");
14722
+ const { getHotPairs, getCoActivationNeighbors } = await import("./co-activation-ZCHPLLP6.js");
14807
14723
  if (action === "hot_pairs") {
14808
14724
  const pairs = await getHotPairs(limit ?? 20);
14809
14725
  if (pairs.length === 0) return text4("No co-activation data yet. Pairs are recorded as memories are accessed together in searches.");
@@ -15217,7 +15133,7 @@ ${err.stack ?? ""}` : String(err);
15217
15133
  gate("registerSupportTools", registerSupportTools);
15218
15134
  const hasAdminToken = !!(process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN || (() => {
15219
15135
  try {
15220
- const c = JSON.parse(readFileSync8(join5(process.env.EXE_OS_DIR ?? join5(homedir5(), ".exe-os"), "config.json"), "utf-8"));
15136
+ const c = JSON.parse(readFileSync7(join4(process.env.EXE_OS_DIR ?? join4(homedir5(), ".exe-os"), "config.json"), "utf-8"));
15221
15137
  return c.support?.adminToken || c.support?.admin_token;
15222
15138
  } catch {
15223
15139
  return "";