@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,40 +1,42 @@
1
1
  import {
2
+ createTask
3
+ } from "./chunk-QYZJHTNE.js";
4
+ import {
5
+ releaseDispatchClaim,
6
+ tryAcquireDispatchClaim,
2
7
  writeDispatchFailed,
3
8
  writeDispatchPending
4
- } from "./chunk-HMP5VT6A.js";
5
- import {
6
- createTask
7
- } from "./chunk-542EWGY3.js";
9
+ } from "./chunk-O7LWR36Z.js";
8
10
  import {
9
11
  getActiveAgent
10
- } from "./chunk-DZ6OQM67.js";
12
+ } from "./chunk-5ERDIOV3.js";
11
13
  import {
12
- ensureEmployee,
14
+ ensureEmployeeAsync,
13
15
  isValidSessionScope,
14
16
  logTaskDispatch,
15
17
  resolveExeSession
16
- } from "./chunk-PLRIJALF.js";
18
+ } from "./chunk-UP75Z5X7.js";
17
19
  import {
18
20
  recordOrchestrationEventBestEffort
19
- } from "./chunk-FUIIVSW6.js";
21
+ } from "./chunk-2WAVZ5UJ.js";
20
22
  import {
21
23
  getAgentRuntime,
22
24
  validateRuntimeModel
23
- } from "./chunk-65SVQELL.js";
25
+ } from "./chunk-HA5R6USD.js";
24
26
  import {
25
27
  getLicenseSync
26
- } from "./chunk-MW2GJJ53.js";
28
+ } from "./chunk-JGIPOUIK.js";
27
29
  import {
28
30
  getAgentContext
29
31
  } from "./chunk-GJV3WDWM.js";
30
32
  import {
31
33
  isCoordinatorName
32
- } from "./chunk-HEPR6QTL.js";
34
+ } from "./chunk-AOHXREB7.js";
33
35
 
34
36
  // src/mcp/tools/create-task.ts
35
37
  import { z } from "zod";
36
- import { existsSync, readdirSync, readFileSync, statSync, writeFileSync, mkdirSync, unlinkSync } from "fs";
37
- import { basename, join } from "path";
38
+ import { existsSync, readdirSync, readFileSync, realpathSync, statSync, writeFileSync, mkdirSync, unlinkSync } from "fs";
39
+ import { basename, dirname, isAbsolute, join, sep } from "path";
38
40
  import { homedir } from "os";
39
41
  function rootFromSessionName(sessionName) {
40
42
  const raw = (sessionName ?? "").trim();
@@ -55,6 +57,20 @@ function isDirectory(pathname) {
55
57
  function isGitRepoDir(pathname) {
56
58
  return isDirectory(pathname) && existsSync(join(pathname, ".git"));
57
59
  }
60
+ function realpathSafe(pathname) {
61
+ try {
62
+ return realpathSync(pathname);
63
+ } catch {
64
+ return pathname;
65
+ }
66
+ }
67
+ function isRealpathInside(candidate, scopedRoot) {
68
+ const rc = realpathSafe(candidate);
69
+ const rr = realpathSafe(scopedRoot);
70
+ if (rc === rr) return true;
71
+ const prefix = rr.endsWith(sep) ? rr : rr + sep;
72
+ return rc.startsWith(prefix);
73
+ }
58
74
  function findNestedGitRepo(parentDir) {
59
75
  const preferred = ["website", "app", "repo", "src"];
60
76
  for (const child of preferred) {
@@ -74,34 +90,72 @@ function findNestedGitRepo(parentDir) {
74
90
  function projectDirMatches(projectDir, projectName) {
75
91
  const dirBasename = basename(projectDir).toLowerCase();
76
92
  const normalizedProject = projectName.toLowerCase();
77
- return dirBasename === normalizedProject || dirBasename === normalizedProject.replace(/^exe-/, "") || `exe-${dirBasename}` === normalizedProject || projectDir.toLowerCase().includes(normalizedProject);
93
+ return dirBasename === normalizedProject || dirBasename === normalizedProject.replace(/^exe-/, "") || `exe-${dirBasename}` === normalizedProject;
94
+ }
95
+ function isSafeProjectName(projectName) {
96
+ if (typeof projectName !== "string") return false;
97
+ const name = projectName.trim();
98
+ if (name.length === 0 || name.length > 128) return false;
99
+ if (name === "." || name === "..") return false;
100
+ if (name.includes("\0")) return false;
101
+ if (isAbsolute(name)) return false;
102
+ if (name.includes("/") || name.includes("\\")) return false;
103
+ if (name.split(/[/\\]/).some((seg) => seg === "..")) return false;
104
+ return true;
78
105
  }
79
106
  function findProjectChildDir(parentDir, projectName) {
107
+ if (!isSafeProjectName(projectName)) return null;
80
108
  if (!existsSync(parentDir)) return null;
81
109
  const normalizedProject = projectName.toLowerCase();
82
110
  const aliases = /* @__PURE__ */ new Set([
83
111
  normalizedProject,
84
112
  normalizedProject.replace(/^exe-/, "")
85
113
  ]);
114
+ const accept = (candidate) => {
115
+ if (!candidate) return null;
116
+ if (!isRealpathInside(candidate, parentDir)) {
117
+ process.stderr.write(
118
+ `[create-task] rejecting "${projectName}" candidate ${candidate}: symlink resolves outside scoped root ${parentDir}.
119
+ `
120
+ );
121
+ return null;
122
+ }
123
+ return candidate;
124
+ };
86
125
  const exactCandidate = join(parentDir, projectName);
87
- if (isGitRepoDir(exactCandidate)) return exactCandidate;
88
- if (isDirectory(exactCandidate)) {
89
- const nested = findNestedGitRepo(exactCandidate);
90
- if (nested) return nested;
126
+ if (isGitRepoDir(exactCandidate)) {
127
+ const ok = accept(exactCandidate);
128
+ if (ok) return ok;
91
129
  }
130
+ const matches = /* @__PURE__ */ new Set();
131
+ const exactNested = isDirectory(exactCandidate) ? accept(findNestedGitRepo(exactCandidate)) : null;
132
+ if (exactNested) matches.add(exactNested);
92
133
  try {
93
134
  for (const entry of readdirSync(parentDir, { withFileTypes: true })) {
94
135
  if (!entry.isDirectory()) continue;
95
136
  const lower = entry.name.toLowerCase();
96
137
  if (aliases.has(lower) || `exe-${lower}` === normalizedProject) {
97
138
  const candidate = join(parentDir, entry.name);
98
- if (isGitRepoDir(candidate)) return candidate;
99
- const nested = findNestedGitRepo(candidate);
100
- if (nested) return nested;
139
+ if (isGitRepoDir(candidate)) {
140
+ const ok = accept(candidate);
141
+ if (ok) matches.add(ok);
142
+ continue;
143
+ }
144
+ const nested = accept(findNestedGitRepo(candidate));
145
+ if (nested) matches.add(nested);
101
146
  }
102
147
  }
103
148
  } catch {
104
149
  }
150
+ const sorted = [...matches].sort();
151
+ if (sorted.length === 1) return sorted[0];
152
+ if (sorted.length > 1) {
153
+ process.stderr.write(
154
+ `[create-task] ambiguous project resolution for "${projectName}" under ${parentDir}: ${sorted.length} candidates (${sorted.join(", ")}). Refusing to guess.
155
+ `
156
+ );
157
+ return null;
158
+ }
105
159
  return null;
106
160
  }
107
161
  async function listCoordinatorRoots() {
@@ -212,6 +266,13 @@ function resolveDispatchRuntime(agentId, override) {
212
266
  }
213
267
  async function resolveProjectDir(projectName, callerSession) {
214
268
  const home = homedir();
269
+ if (!isSafeProjectName(projectName)) {
270
+ process.stderr.write(
271
+ `[create-task] refusing to resolve unsafe project name "${String(projectName).slice(0, 80)}" (absolute path, path separator, or ".." segment). Rejecting.
272
+ `
273
+ );
274
+ return null;
275
+ }
215
276
  if (callerSession) {
216
277
  try {
217
278
  const { listSessions } = await import("./lib/session-registry.js");
@@ -219,15 +280,31 @@ async function resolveProjectDir(projectName, callerSession) {
219
280
  const coordName = callerSession.includes("-") ? callerSession.slice(callerSession.indexOf("-") + 1) : callerSession;
220
281
  const coordSession = sessions.find((s) => s.windowName === coordName) ?? sessions.find((s) => s.windowName === callerSession);
221
282
  if (coordSession?.projectDir && existsSync(coordSession.projectDir)) {
222
- if (projectDirMatches(coordSession.projectDir, projectName)) {
223
- return coordSession.projectDir;
283
+ const coordDir = coordSession.projectDir;
284
+ if (projectDirMatches(coordDir, projectName)) {
285
+ return coordDir;
224
286
  }
225
- const childProjectDir = findProjectChildDir(coordSession.projectDir, projectName);
226
- if (childProjectDir) {
227
- return childProjectDir;
287
+ const childUnderCoord = findProjectChildDir(coordDir, projectName);
288
+ if (childUnderCoord) return childUnderCoord;
289
+ const workspaceRoot = dirname(coordDir);
290
+ if (workspaceRoot !== coordDir) {
291
+ const sibling = findProjectChildDir(workspaceRoot, projectName);
292
+ if (sibling) {
293
+ const owner = sessions.find(
294
+ (s) => s.windowName !== coordName && s.windowName !== callerSession && s.projectDir && isRealpathInside(sibling, s.projectDir)
295
+ );
296
+ if (owner) {
297
+ process.stderr.write(
298
+ `[create-task] REFUSING cross-scope resolution: project "${projectName}" -> ${sibling} is owned by coordinator scope "${owner.windowName}", not caller "${callerSession}". Returning null.
299
+ `
300
+ );
301
+ return null;
302
+ }
303
+ return sibling;
304
+ }
228
305
  }
229
306
  process.stderr.write(
230
- `[create-task] project mismatch: coordinator dir="${coordSession.projectDir}" (${basename(coordSession.projectDir).toLowerCase()}) vs task project="${projectName}". Falling through.
307
+ `[create-task] project "${projectName}" not found within caller scope "${callerSession}" (coordinator dir "${coordDir}"). Not scanning other scopes.
231
308
  `
232
309
  );
233
310
  }
@@ -237,36 +314,36 @@ async function resolveProjectDir(projectName, callerSession) {
237
314
  `
238
315
  );
239
316
  }
317
+ process.stderr.write(
318
+ `[create-task] could not resolve project "${projectName}" within caller scope "${callerSession}". Returning null \u2014 dispatch will be refused (no $HOME/cwd fallback for a scoped caller).
319
+ `
320
+ );
321
+ return null;
240
322
  }
241
323
  try {
242
324
  const ctx = getAgentContext();
243
- if (ctx?.projectName) {
325
+ if (ctx?.projectName && isSafeProjectName(ctx.projectName)) {
244
326
  const alsCandidate = join(home, ctx.projectName);
245
327
  if (existsSync(alsCandidate)) return alsCandidate;
246
328
  }
247
329
  } catch {
248
330
  }
249
- const candidates = [
250
- join(home, projectName),
251
- join(home, projectName.replace(/^exe-/, ""))
252
- ];
253
- for (const candidate of candidates) {
331
+ for (const candidate of [join(home, projectName), join(home, projectName.replace(/^exe-/, ""))]) {
254
332
  if (existsSync(candidate)) return candidate;
255
333
  }
256
334
  const cwd = process.cwd();
257
335
  if (cwd !== home && existsSync(join(cwd, ".git"))) {
258
336
  process.stderr.write(
259
- `[create-task] WARN: could not resolve project dir for "${projectName}" \u2014 falling back to cwd (${cwd}). This may cause agents to spawn in the wrong repo.
337
+ `[create-task] WARN: resolving project "${projectName}" to cwd (${cwd}) \u2014 no caller scope.
260
338
  `
261
339
  );
262
340
  return cwd;
263
341
  }
264
- const fallback = join(home, projectName);
265
342
  process.stderr.write(
266
- `[create-task] ERROR: could not resolve project dir for "${projectName}". cwd=${cwd} is not a valid project directory. Using ${fallback} as fallback (may not exist). Ensure the project is cloned or the coordinator session registry is populated.
343
+ `[create-task] could not resolve an existing project dir for "${projectName}" (no caller scope). Returning null \u2014 dispatch will be refused.
267
344
  `
268
345
  );
269
- return fallback;
346
+ return null;
270
347
  }
271
348
  function registerCreateTask(server) {
272
349
  server.registerTool(
@@ -287,10 +364,15 @@ function registerCreateTask(server) {
287
364
  budget_tokens: z.number().optional().describe("Max tokens allowed for this task (null = unlimited)"),
288
365
  budget_fallback_model: z.string().optional().describe("Model to route to when budget is exhausted"),
289
366
  spawn_runtime: z.string().optional().describe("Override runtime for spawned session (e.g., 'claude', 'codex', 'opencode')"),
290
- spawn_model: z.string().optional().describe("Override model for spawned session (e.g., 'claude-sonnet-4.6', 'claude-haiku-4.5')")
367
+ spawn_model: z.string().optional().describe("Override model for spawned session (e.g., 'claude-sonnet-4.6', 'claude-haiku-4.5')"),
368
+ spawn_worktree: z.boolean().optional().describe(
369
+ "Worktree isolation for code-role agents. Default true (REQUIRED \u2014 a code-role agent that cannot get an isolated git worktree is refused, never spawned on main). Set false ONLY to dispatch a code-role agent into a NON-git 'automation' project (a plain folder with no repo to protect); the agent then runs in the project root and a loud worktree.bypassed event is logged. Genuine non-git projects are auto-detected, so this is rarely needed by hand."
370
+ ),
371
+ idempotency_key: z.string().optional().describe("Idempotency key (bug c06a8803): retrying create_task 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 do NOT embed a timestamp. Optional; when omitted no dedup is applied."),
372
+ idempotency_window: z.string().optional().describe("Optional nonce used to DERIVE an idempotency key when idempotency_key is not given (stable hash of assignee+title+project+session+window). Reuse the same window on a retry to dedup. When both this and idempotency_key are omitted, no dedup is applied.")
291
373
  }
292
374
  },
293
- async ({ title, assigned_to, project_name, priority, complexity, context, blocked_by, parent_task_id, reviewer, budget_tokens, budget_fallback_model, spawn_runtime, spawn_model }) => {
375
+ async ({ title, assigned_to, project_name, priority, complexity, context, blocked_by, parent_task_id, reviewer, budget_tokens, budget_fallback_model, spawn_runtime, spawn_model, spawn_worktree, idempotency_key, idempotency_window }) => {
294
376
  if (!isCoordinatorName(assigned_to)) {
295
377
  const license = getLicenseSync();
296
378
  if (license.plan === "free") {
@@ -399,6 +481,26 @@ function registerCreateTask(server) {
399
481
  effectiveSpawnModel = validated.model;
400
482
  }
401
483
  const projectDir = await resolveProjectDir(project_name, callerRoot);
484
+ if (projectDir == null && process.env.VITEST !== "true" && process.env.NODE_ENV !== "test") {
485
+ const message = `BLOCKED: create_task could not resolve an existing project directory for "${project_name}" within the caller's coordinator scope. Refusing to create/dispatch into a fabricated or cross-scope path. Clone the project (or ensure the coordinator session registry points at it) and retry. If "${project_name}" is a non-git automation project, dispatch it from a session whose coordinator dir contains it.`;
486
+ process.stderr.write(`[create_task] ${message}
487
+ `);
488
+ recordOrchestrationEventBestEffort({
489
+ eventType: "dispatch.failed",
490
+ source: "create-task.mcp",
491
+ severity: "error",
492
+ agentId: assigned_to,
493
+ sessionScope: callerRoot || null,
494
+ projectName: project_name,
495
+ errorCode: "project_dir_unresolved",
496
+ payload: { priority, callerTmux, callerSource }
497
+ });
498
+ return {
499
+ content: [{ type: "text", text: message }],
500
+ isError: true
501
+ };
502
+ }
503
+ const resolvedProjectDir = projectDir ?? process.cwd();
402
504
  let journalWarning = "";
403
505
  try {
404
506
  const orphans = findOrphanedDispatchIntents(callerRoot || null);
@@ -434,7 +536,7 @@ function registerCreateTask(server) {
434
536
  assignedBy,
435
537
  sessionScope: callerRoot || null,
436
538
  callerSource,
437
- projectDir
539
+ projectDir: resolvedProjectDir
438
540
  }
439
541
  );
440
542
  } catch (journalErr) {
@@ -453,7 +555,7 @@ function registerCreateTask(server) {
453
555
  priority,
454
556
  complexity,
455
557
  context,
456
- baseDir: projectDir,
558
+ baseDir: resolvedProjectDir,
457
559
  blockedBy: blocked_by,
458
560
  parentTaskId: parent_task_id,
459
561
  reviewer: reviewer ?? assignedBy,
@@ -461,6 +563,11 @@ function registerCreateTask(server) {
461
563
  budgetFallbackModel: budget_fallback_model,
462
564
  spawnRuntime: spawn_runtime,
463
565
  spawnModel: effectiveSpawnModel,
566
+ // Idempotency (bug c06a8803): thread the OPT-IN key/window through to
567
+ // createTaskCore so a retried tool call after a daemon transport error
568
+ // returns the original task instead of inserting a duplicate.
569
+ idempotencyKey: idempotency_key,
570
+ idempotencyWindow: idempotency_window,
464
571
  // Pass the pre-resolved caller session to tasks-crud so it doesn't
465
572
  // re-resolve independently (eliminates cross-session scope divergence).
466
573
  callerSession: callerTmux || callerRoot || void 0,
@@ -532,7 +639,7 @@ function registerCreateTask(server) {
532
639
  session_scope: sessionScope,
533
640
  created_at: (/* @__PURE__ */ new Date()).toISOString()
534
641
  }), "utf-8");
535
- const { recordOrchestrationEventBestEffort: recordOE } = await import("./orchestration-events-5SIJOE4H.js");
642
+ const { recordOrchestrationEventBestEffort: recordOE } = await import("./orchestration-events-WV4NWKZH.js");
536
643
  recordOE({
537
644
  eventType: "signal.created",
538
645
  source: "create-task.mcp",
@@ -545,7 +652,7 @@ function registerCreateTask(server) {
545
652
  }
546
653
  let dispatchStatus = "";
547
654
  let dispatchOutcome = "ok";
548
- if (task.status !== "blocked" && !process.env.VITEST) {
655
+ if (task.status !== "blocked" && !process.env.VITEST && !task.deduplicated) {
549
656
  try {
550
657
  const exeSession = task.sessionScope || callerRoot;
551
658
  const dispatchRuntime = resolveDispatchRuntime(assigned_to, spawn_runtime ?? null);
@@ -565,7 +672,7 @@ function registerCreateTask(server) {
565
672
  let projectConflictOpts = {};
566
673
  try {
567
674
  const { getClient } = await import("./lib/database.js");
568
- const { sessionScopeFilter } = await import("./task-scope-CQEG5SSJ.js");
675
+ const { sessionScopeFilter } = await import("./task-scope-FOIW25HR.js");
569
676
  const client = getClient();
570
677
  const scope = sessionScopeFilter(task.sessionScope || callerRoot || exeSession || null);
571
678
  const existing = await client.execute({
@@ -584,116 +691,142 @@ function registerCreateTask(server) {
584
691
  }
585
692
  } catch {
586
693
  }
587
- try {
588
- writeDispatchPending(task.id, assigned_to);
589
- } catch {
590
- }
591
- const result = ensureEmployee(assigned_to, exeSession, projectDir, {
592
- ...autoOpts,
593
- ...projectConflictOpts,
594
- runtimeOverride: spawn_runtime ?? void 0,
595
- modelOverride: effectiveSpawnModel ?? void 0
596
- });
597
- switch (result.status) {
598
- case "intercom_sent":
599
- dispatchStatus = `
694
+ const claimedSpawn = tryAcquireDispatchClaim(task.id, assigned_to);
695
+ if (!claimedSpawn) {
696
+ dispatchStatus = `
697
+ Dispatched: deduped \u2014 another dispatch for task ${task.id} is already in flight`;
698
+ process.stderr.write(
699
+ `[create_task] DEDUPED spawn for ${assigned_to} task ${task.id} \u2014 a fresh dispatch is already in flight; not double-spawning
700
+ `
701
+ );
702
+ recordOrchestrationEventBestEffort({
703
+ eventType: "dispatch.deduped",
704
+ source: "create-task.mcp",
705
+ severity: "info",
706
+ taskId: task.id,
707
+ agentId: assigned_to,
708
+ sessionScope: task.sessionScope || callerRoot || exeSession,
709
+ projectName: project_name,
710
+ runtime: dispatchRuntime,
711
+ result: "deduped",
712
+ payload: { priority, reason: "fresh_dispatch_in_flight" }
713
+ });
714
+ } else {
715
+ const result = await ensureEmployeeAsync(assigned_to, exeSession, resolvedProjectDir, {
716
+ ...autoOpts,
717
+ ...projectConflictOpts,
718
+ runtimeOverride: spawn_runtime ?? void 0,
719
+ modelOverride: effectiveSpawnModel ?? void 0,
720
+ // Explicit worktree opt-out (bug b65135ee) — only when the caller
721
+ // passed spawn_worktree=false; undefined keeps the refuse-in-main
722
+ // default. Non-git automation projects auto-bypass downstream.
723
+ ...spawn_worktree === false ? { spawnWorktree: false } : {}
724
+ });
725
+ switch (result.status) {
726
+ case "intercom_sent":
727
+ dispatchStatus = `
600
728
  Dispatched: intercom sent to ${result.sessionName}`;
601
- break;
602
- case "intercom_unprocessed":
603
- dispatchStatus = `
729
+ break;
730
+ case "intercom_unprocessed":
731
+ dispatchStatus = `
604
732
  Dispatched: intercom delivered to ${result.sessionName}`;
605
- break;
606
- case "spawned":
607
- dispatchStatus = `
733
+ break;
734
+ case "spawned":
735
+ dispatchStatus = `
608
736
  Dispatched: spawned ${result.sessionName}`;
609
- break;
610
- case "failed":
611
- dispatchStatus = `
737
+ break;
738
+ case "failed":
739
+ dispatchStatus = `
612
740
  Dispatch failed: ${result.error ?? "unknown"}`;
613
- break;
614
- }
615
- if (result.status === "failed") dispatchOutcome = "failed";
616
- if (result.status === "failed") {
617
- try {
618
- writeDispatchFailed(task.id, assigned_to, result.error ?? "spawn failed", result.sessionName);
619
- } catch {
741
+ break;
620
742
  }
621
- }
622
- recordOrchestrationEventBestEffort({
623
- eventType: result.status === "failed" ? "dispatch.failed" : "dispatch.completed",
624
- source: "create-task.mcp",
625
- severity: result.status === "failed" ? "warn" : "info",
626
- taskId: task.id,
627
- agentId: assigned_to,
628
- sessionScope: task.sessionScope || callerRoot || exeSession,
629
- projectName: project_name,
630
- tmuxSession: result.sessionName || null,
631
- runtime: dispatchRuntime,
632
- result: result.status,
633
- errorCode: result.status === "failed" ? "ensure_employee_failed" : null,
634
- payload: { priority, error: result.error ?? null }
635
- });
636
- try {
637
- const { sendIntercom: si } = await import("./lib/tmux-routing.js");
638
- const { listTmuxSessions } = await import("./lib/tmux-status.js");
639
- if (!autoOpts.autoInstance) {
640
- const liveSessions = listTmuxSessions();
641
- for (const s of liveSessions) {
642
- const agentPart = s.split("-")[0]?.replace(/\d+$/, "") ?? "";
643
- if (agentPart === assigned_to && s !== result.sessionName) {
644
- si(s, { force: true });
645
- }
743
+ if (result.status === "failed") dispatchOutcome = "failed";
744
+ if (result.status === "failed") {
745
+ try {
746
+ releaseDispatchClaim(task.id, assigned_to, result.error ?? "spawn failed");
747
+ } catch {
748
+ }
749
+ try {
750
+ writeDispatchFailed(task.id, assigned_to, result.error ?? "spawn failed", result.sessionName);
751
+ } catch {
646
752
  }
647
753
  }
648
- } catch {
649
- }
650
- if (result.sessionName && result.status !== "failed") {
754
+ recordOrchestrationEventBestEffort({
755
+ eventType: result.status === "failed" ? "dispatch.failed" : "dispatch.completed",
756
+ source: "create-task.mcp",
757
+ severity: result.status === "failed" ? "warn" : "info",
758
+ taskId: task.id,
759
+ agentId: assigned_to,
760
+ sessionScope: task.sessionScope || callerRoot || exeSession,
761
+ projectName: project_name,
762
+ tmuxSession: result.sessionName || null,
763
+ runtime: dispatchRuntime,
764
+ result: result.status,
765
+ errorCode: result.status === "failed" ? "ensure_employee_failed" : null,
766
+ payload: { priority, error: result.error ?? null }
767
+ });
651
768
  try {
652
- const { getClient: gc } = await import("./lib/database.js");
653
- await gc().execute({
654
- // Audited 2026: intentionally unscoped PK update. The task was
655
- // just created in this request, and WHERE id = ? binds one row.
656
- sql: `UPDATE tasks
769
+ const { sendIntercom: si } = await import("./lib/tmux-routing.js");
770
+ const { listTmuxSessions } = await import("./lib/tmux-status.js");
771
+ if (!autoOpts.autoInstance) {
772
+ const liveSessions = listTmuxSessions();
773
+ for (const s of liveSessions) {
774
+ const agentPart = s.split("-")[0]?.replace(/\d+$/, "") ?? "";
775
+ if (agentPart === assigned_to && s !== result.sessionName) {
776
+ si(s, { force: true });
777
+ }
778
+ }
779
+ }
780
+ } catch {
781
+ }
782
+ if (result.sessionName && result.status !== "failed") {
783
+ try {
784
+ const { getClient: gc } = await import("./lib/database.js");
785
+ await gc().execute({
786
+ // Audited 2026: intentionally unscoped PK update. The task was
787
+ // just created in this request, and WHERE id = ? binds one row.
788
+ sql: `UPDATE tasks
657
789
  SET instance_id = ?,
658
790
  assigned_tmux = CASE
659
791
  WHEN assigned_tmux IS NULL OR assigned_tmux = 'unknown' THEN ?
660
792
  ELSE assigned_tmux
661
793
  END
662
794
  WHERE id = ?`,
663
- args: [result.sessionName, result.sessionName, task.id]
664
- });
665
- } catch {
795
+ args: [result.sessionName, result.sessionName, task.id]
796
+ });
797
+ } catch {
798
+ }
799
+ try {
800
+ const sessionScope = task.sessionScope || callerRoot || "default";
801
+ const { taskSignalPath: getSignalPath } = await import("./signal-paths-4G53QTII.js");
802
+ const signalPath = getSignalPath(sessionScope, assigned_to, task.id);
803
+ writeFileSync(signalPath, JSON.stringify({
804
+ task_id: task.id,
805
+ title,
806
+ priority,
807
+ assigned_by: assignedBy,
808
+ session_scope: sessionScope,
809
+ instance_id: result.sessionName,
810
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
811
+ }), "utf-8");
812
+ } catch {
813
+ }
666
814
  }
667
815
  try {
668
- const sessionScope = task.sessionScope || callerRoot || "default";
669
- const { taskSignalPath: getSignalPath } = await import("./signal-paths-4G53QTII.js");
670
- const signalPath = getSignalPath(sessionScope, assigned_to, task.id);
671
- writeFileSync(signalPath, JSON.stringify({
672
- task_id: task.id,
673
- title,
674
- priority,
675
- assigned_by: assignedBy,
676
- session_scope: sessionScope,
677
- instance_id: result.sessionName,
678
- created_at: (/* @__PURE__ */ new Date()).toISOString()
679
- }), "utf-8");
816
+ writeDispatchPending(task.id, assigned_to, result.sessionName);
680
817
  } catch {
681
818
  }
819
+ logTaskDispatch({
820
+ taskId: task.id,
821
+ assignedTo: assigned_to,
822
+ callerRoot,
823
+ exeSession,
824
+ callerSource,
825
+ dispatchResult: result.status,
826
+ sessionName: result.sessionName,
827
+ error: result.error
828
+ });
682
829
  }
683
- try {
684
- writeDispatchPending(task.id, assigned_to, result.sessionName);
685
- } catch {
686
- }
687
- logTaskDispatch({
688
- taskId: task.id,
689
- assignedTo: assigned_to,
690
- callerRoot,
691
- exeSession,
692
- callerSource,
693
- dispatchResult: result.status,
694
- sessionName: result.sessionName,
695
- error: result.error
696
- });
697
830
  } else {
698
831
  const noSessionMsg = `Dispatch skipped: no coordinator session resolved (callerTmux="${callerTmux}", callerSource="${callerSource}"). Task ${task.id} created but agent ${assigned_to} was NOT spawned. Auto-wake will retry.`;
699
832
  process.stderr.write(`[create_task] ${noSessionMsg}
@@ -716,6 +849,10 @@ Dispatch deferred: no coordinator session \u2014 auto-wake will spawn ${assigned
716
849
  }
717
850
  } catch (dispatchErr) {
718
851
  dispatchOutcome = "failed";
852
+ try {
853
+ releaseDispatchClaim(task.id, assigned_to, "dispatch exception");
854
+ } catch {
855
+ }
719
856
  recordOrchestrationEventBestEffort({
720
857
  eventType: "dispatch.failed",
721
858
  source: "create-task.mcp",
@@ -734,8 +871,8 @@ ${dispatchErr instanceof Error ? dispatchErr.stack : ""}
734
871
  }
735
872
  let dupWarning = "";
736
873
  try {
737
- const { findMatchingBranches } = await import("./branch-hygiene-R5NVTRAY.js");
738
- const matches = await findMatchingBranches(projectDir, { title });
874
+ const { findMatchingBranches } = await import("./branch-hygiene-TZWK6QCF.js");
875
+ const matches = await findMatchingBranches(resolvedProjectDir, { title });
739
876
  if (matches.length > 0) {
740
877
  const top = matches.slice(0, 3).map((m) => {
741
878
  const age = m.ageHours >= 24 ? `${(m.ageHours / 24).toFixed(1)}d` : `${m.ageHours.toFixed(0)}h`;
@@ -783,11 +920,14 @@ Warning: ${task.warning}`;
783
920
  }
784
921
 
785
922
  export {
923
+ isSafeProjectName,
924
+ findProjectChildDir,
786
925
  DISPATCH_JOURNAL_ORPHAN_AGE_MS,
787
926
  dispatchJournalDir,
788
927
  journalDispatchIntent,
789
928
  updateDispatchJournalEntry,
790
929
  clearDispatchJournalEntry,
791
930
  findOrphanedDispatchIntents,
931
+ resolveProjectDir,
792
932
  registerCreateTask
793
933
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  checkLicense,
3
3
  loadLicense
4
- } from "./chunk-XACL67CS.js";
4
+ } from "./chunk-PQIDGXSG.js";
5
5
 
6
6
  // src/lib/license-gate.ts
7
7
  var _cachedLicense = null;