@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.
- package/README.md +159 -196
- package/deploy/compose/.env.customer.example +1 -0
- package/deploy/compose/.env.example +1 -0
- package/deploy/compose/docker-compose.yml +13 -4
- package/deploy/compose/generate-env.ts +4 -0
- package/dist/{active-agent-EC6M7KTX.js → active-agent-PVGE57FY.js} +5 -5
- package/dist/{active-agent-WHIUCHLA.js → active-agent-TNIO6IY3.js} +5 -5
- package/dist/{agentic-ontology-RNSXGXW4.js → agentic-ontology-3FXYMHKW.js} +1 -1
- package/dist/{backfill-gate-J7UXFNXU.js → backfill-gate-65LSYVE5.js} +3 -3
- package/dist/{backfill-metadata-MFY6BHKE.js → backfill-metadata-ZSMZC45J.js} +8 -8
- package/dist/{background-jobs-STURKDCS.js → background-jobs-EXR5RVGG.js} +3 -3
- package/dist/backup-verify-3Y2FHGZU.js +425 -0
- package/dist/{behaviors-HLZUJSMP.js → behaviors-KYRB3NGJ.js} +9 -9
- package/dist/bin/age-ontology-load.js +3 -3
- package/dist/bin/agentic-ontology-backfill.js +10 -10
- package/dist/bin/agentic-reflection-backfill.js +11 -11
- package/dist/bin/agentic-semantic-label.js +10 -10
- package/dist/bin/backfill-conversations.js +10 -10
- package/dist/bin/backfill-responses.js +10 -10
- package/dist/bin/backfill-vectors.js +14 -14
- package/dist/bin/bulk-sync-postgres.js +19 -19
- package/dist/bin/cc-doctor.js +10 -8
- package/dist/bin/cleanup-stale-review-tasks.js +26 -24
- package/dist/bin/cli.js +111 -25
- package/dist/bin/customer-readiness.js +1 -1
- package/dist/bin/deferred-daemon-restart.js +97 -90
- package/dist/bin/exe-agent-config.js +9 -8
- package/dist/bin/exe-agent.js +20 -20
- package/dist/bin/exe-assign.js +12 -12
- package/dist/bin/exe-boot.js +201 -68
- package/dist/bin/exe-call.js +7 -7
- package/dist/bin/exe-cloud.js +20 -20
- package/dist/bin/exe-config-dump.js +9 -8
- package/dist/bin/exe-dispatch.js +26 -24
- package/dist/bin/exe-doctor.js +10 -6
- package/dist/bin/exe-export-behaviors.js +11 -11
- package/dist/bin/exe-forget.js +12 -10
- package/dist/bin/exe-gateway.js +15 -10
- package/dist/bin/exe-grant.js +5 -5
- package/dist/bin/exe-healthcheck.js +14 -8
- package/dist/bin/exe-heartbeat.js +29 -28
- package/dist/bin/exe-kill.js +31 -29
- package/dist/bin/exe-launch-agent.js +129 -68
- package/dist/bin/exe-memory-reads.js +257 -0
- package/dist/bin/exe-new-employee.js +12 -11
- package/dist/bin/exe-pending-messages.js +27 -25
- package/dist/bin/exe-pending-notifications.js +26 -24
- package/dist/bin/exe-pending-reviews.js +26 -24
- package/dist/bin/exe-rename.js +7 -7
- package/dist/bin/exe-review.js +30 -28
- package/dist/bin/exe-search.js +11 -9
- package/dist/bin/exe-session-cleanup.js +116 -86
- package/dist/bin/exe-settings.js +24 -23
- package/dist/bin/exe-start-codex.js +163 -41
- package/dist/bin/exe-start-opencode.js +15 -15
- package/dist/bin/exe-status.js +27 -25
- package/dist/bin/exe-support.js +5 -5
- package/dist/bin/exe-team.js +5 -5
- package/dist/bin/exe-timers.js +32 -213
- package/dist/bin/exe-watchdog.js +6 -5
- package/dist/bin/git-sweep.js +27 -25
- package/dist/bin/graph-backfill.js +9 -9
- package/dist/bin/graph-export.js +9 -9
- package/dist/bin/import-history.js +11 -11
- package/dist/bin/install.js +102 -95
- package/dist/bin/intercom-check.js +4 -4
- package/dist/bin/mcp-sessions.js +2 -2
- package/dist/bin/orchestration-metrics.js +6 -6
- package/dist/bin/postgres-agentic-reflection-backfill.js +5 -5
- package/dist/bin/postgres-agentic-semantic-backfill.js +7 -7
- package/dist/bin/pre-publish.js +5 -3
- package/dist/bin/reconcile-backlog.js +484 -0
- package/dist/bin/registry-proxy.js +1 -1
- package/dist/bin/scan-tasks.js +26 -24
- package/dist/bin/setup.js +6 -5
- package/dist/bin/shard-migrate.js +9 -9
- package/dist/bin/stack-update.js +15 -9
- package/dist/bin/update.js +1 -1
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/boot-generation-BL2ISK4U.js +22 -0
- package/dist/boot-review-sections-DBMQJT5N.js +107 -0
- package/dist/branch-hygiene-TZWK6QCF.js +224 -0
- package/dist/{branding-JTEOF4ZV.js → branding-DVXBGVDH.js} +3 -3
- package/dist/{browser-session-store-CXQMOSEC.js → browser-session-store-B2NR3LIX.js} +2 -1
- package/dist/{capability-cards-YOKVMMOL.js → capability-cards-DN5UIKVN.js} +4 -4
- package/dist/{capacity-monitor-S54IOWRL.js → capacity-monitor-ZG5GGFR2.js} +27 -25
- package/dist/{catchup-brief-DRRQCMKA.js → catchup-brief-D6HH6DWS.js} +32 -29
- package/dist/{support-outbox-MGUVVGHT.js → chunk-25X4JD2V.js} +28 -12
- package/dist/{chunk-IYB2NIW3.js → chunk-2KZNGDSW.js} +1 -1
- package/dist/{chunk-FUIIVSW6.js → chunk-2WAVZ5UJ.js} +1 -1
- package/dist/{chunk-K5WFKEXQ.js → chunk-2ZYO73KO.js} +4 -3
- package/dist/{chunk-CLAYNAXC.js → chunk-3EUMUSLE.js} +1 -1
- package/dist/{chunk-BVV6NHKQ.js → chunk-3SW4OEHB.js} +5 -5
- package/dist/{task-enforcement-VI7L43DC.js → chunk-4CMVFVFC.js} +173 -69
- package/dist/{chunk-BU2QQWBQ.js → chunk-4J4PMPXZ.js} +3 -2
- package/dist/{chunk-JD5S5AAV.js → chunk-4N2NRGCM.js} +2 -2
- package/dist/chunk-4QCFFW2H.js +378 -0
- package/dist/{chunk-7EA7LYW4.js → chunk-4VSV5P4D.js} +4 -4
- package/dist/{chunk-52KNOQMK.js → chunk-4ZCD2UWW.js} +39 -10
- package/dist/{chunk-DZ6OQM67.js → chunk-5ERDIOV3.js} +2 -2
- package/dist/chunk-5H47VHB7.js +30 -0
- package/dist/{chunk-UCQITDLM.js → chunk-5TY4FPH6.js} +1 -1
- package/dist/{chunk-R44Z32O2.js → chunk-6CH3TPHR.js} +2 -2
- package/dist/{chunk-WYLV4S6A.js → chunk-6WQ3NNCE.js} +3 -3
- package/dist/{chunk-HHIBOU3P.js → chunk-6XWTQUO4.js} +1 -1
- package/dist/chunk-76CJBM36.js +88 -0
- package/dist/{chunk-H2L4PHGH.js → chunk-7CTRGNLW.js} +2 -2
- package/dist/{chunk-XUKPALWT.js → chunk-7V4JADD6.js} +2 -2
- package/dist/{chunk-RMOBQ6A5.js → chunk-AD2VCHSS.js} +1 -1
- package/dist/{chunk-QXSBB26A.js → chunk-AJYCFKJR.js} +1 -1
- package/dist/chunk-AM7S2TY6.js +54 -0
- package/dist/{chunk-HEPR6QTL.js → chunk-AOHXREB7.js} +334 -66
- package/dist/{chunk-FNZR3B7U.js → chunk-ASAFVDVR.js} +1 -1
- package/dist/{chunk-TALWBVZE.js → chunk-BUCXNV32.js} +1 -1
- package/dist/{chunk-SHIICYJW.js → chunk-BYTDMAGB.js} +4 -2
- package/dist/{chunk-32SXNM3G.js → chunk-C5QAPURN.js} +1 -1
- package/dist/{chunk-XCTGRD4S.js → chunk-CE7F6RHG.js} +587 -77
- package/dist/{chunk-7WPOJDTA.js → chunk-CNVBKDEY.js} +21 -15
- package/dist/{chunk-KPIN44GZ.js → chunk-CWXVH7WV.js} +1 -1
- package/dist/chunk-D74XYSA3.js +621 -0
- package/dist/{chunk-A47MXY2I.js → chunk-EQHQF5IM.js} +50 -32
- package/dist/{chunk-AOO77BDE.js → chunk-EUS4QUKP.js} +1 -1
- package/dist/{chunk-RLRT2BVM.js → chunk-EV46QTD3.js} +1 -1
- package/dist/{chunk-PAEXYFMY.js → chunk-F27XXN6C.js} +1 -1
- package/dist/{chunk-XQNNB5GY.js → chunk-F55P3H4S.js} +37 -2
- package/dist/{chunk-MWZFF3Q7.js → chunk-F5O7V7UK.js} +1 -1
- package/dist/{chunk-LMZISHSJ.js → chunk-FPFPLPUY.js} +6 -6
- package/dist/{chunk-7TS64TBG.js → chunk-G4RGKBCA.js} +8 -3
- package/dist/{chunk-4IYSBPX3.js → chunk-G5T6KDG4.js} +1 -1
- package/dist/{chunk-7WDXEKUL.js → chunk-GBTTBXAF.js} +4 -4
- package/dist/{chunk-6MRWJMI5.js → chunk-GDIJE6D7.js} +1 -1
- package/dist/{chunk-AVKXCSBI.js → chunk-GG5NDQNN.js} +2 -2
- package/dist/{chunk-I3XKO3KQ.js → chunk-GJ26DULE.js} +2 -2
- package/dist/chunk-GL57PO3K.js +104 -0
- package/dist/chunk-GWDSB25T.js +6 -0
- package/dist/{chunk-F55JF43M.js → chunk-H6BV5TKD.js} +39 -24
- package/dist/{chunk-HCJCW7X4.js → chunk-H7I47RS5.js} +34 -1
- package/dist/{chunk-65SVQELL.js → chunk-HA5R6USD.js} +31 -5
- package/dist/{chunk-VJHUVFIW.js → chunk-HAF2DJYV.js} +3 -3
- package/dist/chunk-HJ447YER.js +224 -0
- package/dist/chunk-HV4KESRY.js +395 -0
- package/dist/{chunk-B76TSEP3.js → chunk-I26FWCSP.js} +216 -9
- package/dist/{chunk-X2FHTDIU.js → chunk-IBYL4DHM.js} +1 -1
- package/dist/{chunk-JCBKARSK.js → chunk-IOEUAQWP.js} +1 -1
- package/dist/{chunk-MW2GJJ53.js → chunk-JGIPOUIK.js} +3 -3
- package/dist/{chunk-2233TQCA.js → chunk-JLZ4RYSD.js} +2 -2
- package/dist/{chunk-Q7L6G6KV.js → chunk-JMYHW3AL.js} +2 -2
- package/dist/{chunk-OJTJYEMX.js → chunk-JPUZPAAF.js} +4 -4
- package/dist/{chunk-XWHE4LZK.js → chunk-JTBIS4R5.js} +21 -2
- package/dist/{chunk-5Z5NATNS.js → chunk-K7KFGDWF.js} +1 -1
- package/dist/{chunk-UIV2WPBT.js → chunk-KGWRTRKC.js} +2 -2
- package/dist/{chunk-KTPG4XKI.js → chunk-KP3U5QGJ.js} +1 -1
- package/dist/{chunk-TLYAEISW.js → chunk-KW2SD2FL.js} +2 -2
- package/dist/{chunk-X7H3HMFH.js → chunk-KWZMQACA.js} +11 -7
- package/dist/{chunk-OFX5B2S7.js → chunk-L2R3LN2P.js} +1 -1
- package/dist/{chunk-T4KZ2Z2N.js → chunk-L4A5DL6Z.js} +3 -3
- package/dist/{chunk-X425OEYF.js → chunk-LU2FALL6.js} +3 -3
- package/dist/{chunk-6M36JFFD.js → chunk-MKYFAKDW.js} +4 -4
- package/dist/{chunk-I5RLNOFK.js → chunk-MOPUCPXK.js} +12 -4
- package/dist/{chunk-ZIVEA3NB.js → chunk-MR6LHP4F.js} +1 -1
- package/dist/chunk-MVYB76QG.js +341 -0
- package/dist/{chunk-2SG2UGCH.js → chunk-MZM6EJCU.js} +4 -4
- package/dist/{chunk-ZREGOV2Q.js → chunk-N7QJKQMX.js} +258 -14
- package/dist/{chunk-QLFRCA6I.js → chunk-NBZL5CGA.js} +93 -12
- package/dist/{chunk-QFPTDSY2.js → chunk-NN2B2QKU.js} +1 -1
- package/dist/chunk-NX5INHHG.js +40 -0
- package/dist/{chunk-B75BOKEI.js → chunk-NXUSDL37.js} +2 -2
- package/dist/{chunk-TPHCZDE3.js → chunk-O5V57XYE.js} +1 -1
- package/dist/chunk-O7LWR36Z.js +269 -0
- package/dist/{chunk-ATOU6CYR.js → chunk-OLMQ4UOF.js} +57 -11
- package/dist/{chunk-6HBURYON.js → chunk-OTF44GXL.js} +4 -4
- package/dist/{chunk-DILD54TU.js → chunk-OZEBAGKR.js} +277 -137
- package/dist/{chunk-DADMPMYX.js → chunk-P5HIWY2E.js} +1 -1
- package/dist/{chunk-EIF2LQHZ.js → chunk-PDWS3E22.js} +55 -4
- package/dist/{chunk-KTY7I7UH.js → chunk-PPCDBE6Z.js} +1 -1
- package/dist/{chunk-XACL67CS.js → chunk-PQIDGXSG.js} +13 -4
- package/dist/chunk-PWUFMX75.js +186 -0
- package/dist/{chunk-UPWE5NOG.js → chunk-QDGZJ653.js} +3 -3
- package/dist/{chunk-MQRFKSLI.js → chunk-QOO5RW3K.js} +6 -5
- package/dist/{chunk-KCC5A7YL.js → chunk-QQ4E2RYW.js} +95 -18
- package/dist/{chunk-BPC5LZ6Y.js → chunk-QRYVCDWS.js} +2 -2
- package/dist/{chunk-Z42MXYWW.js → chunk-QWVXN224.js} +110 -28
- package/dist/{chunk-542EWGY3.js → chunk-QYZJHTNE.js} +26 -27
- package/dist/{chunk-I7Z6KTGF.js → chunk-R2NN3JKH.js} +43 -6
- package/dist/{chunk-3OBWSCJN.js → chunk-RACAOE2Z.js} +14 -14
- package/dist/{chunk-5RACW3LX.js → chunk-RAXVPNMR.js} +1 -1
- package/dist/{chunk-2HZY3ECT.js → chunk-RHWZUUS4.js} +6 -6
- package/dist/{chunk-RNAYCUNM.js → chunk-S3THSOWV.js} +1 -1
- package/dist/{chunk-W7DHFGCB.js → chunk-S7QUM2UK.js} +2 -2
- package/dist/{chunk-SSTLTIF3.js → chunk-SKGMF2SO.js} +25 -2
- package/dist/{chunk-GN45PBWI.js → chunk-SQKXKV2Y.js} +2 -2
- package/dist/{chunk-QZLIZAS7.js → chunk-TLT7NZCW.js} +4 -4
- package/dist/chunk-TTCUG2CF.js +91 -0
- package/dist/chunk-UEA3LXOB.js +40 -0
- package/dist/{chunk-DRCRZIIJ.js → chunk-UNXQBELK.js} +1 -1
- package/dist/{chunk-PLRIJALF.js → chunk-UP75Z5X7.js} +921 -176
- package/dist/{chunk-TNJRWUCE.js → chunk-USSB56WK.js} +1 -1
- package/dist/{chunk-KMBEL7VB.js → chunk-UUEKJDK6.js} +90 -10
- package/dist/{chunk-XJI7Z6LZ.js → chunk-UUQBZPJJ.js} +1 -1
- package/dist/{chunk-RRWDYOQS.js → chunk-V3EEVY4L.js} +1 -1
- package/dist/{chunk-N5I7RL3I.js → chunk-VPZHJCKW.js} +2 -2
- package/dist/chunk-VRAQTFD6.js +265 -0
- package/dist/{chunk-H37HHX3E.js → chunk-VSRPS3J7.js} +14 -14
- package/dist/{chunk-5ZNY7IZI.js → chunk-WMESXBJM.js} +37 -3
- package/dist/{chunk-54QCG45Y.js → chunk-WOYADZF5.js} +56 -5
- package/dist/{chunk-7Y5UDEVM.js → chunk-WZHZCDDO.js} +6 -5
- package/dist/{chunk-3NGZ4PL7.js → chunk-X2Q5NLUL.js} +11 -2
- package/dist/{chunk-YE7NH53A.js → chunk-X33NYQYJ.js} +2 -2
- package/dist/{chunk-UXBD22CD.js → chunk-XHK3FS3W.js} +3 -2
- package/dist/{chunk-3QDSCJ3F.js → chunk-XZXBB3TN.js} +2 -2
- package/dist/{chunk-JSKBHUR7.js → chunk-YCANDMI2.js} +2 -2
- package/dist/{chunk-JBSCL2XT.js → chunk-YLXTKI6M.js} +1 -1
- package/dist/{chunk-G7WO77Z2.js → chunk-YTCFACP4.js} +812 -896
- package/dist/{chunk-LTVCRHHD.js → chunk-Z6RSN7KS.js} +7 -6
- package/dist/{cleanup-graph-garbage-KUABW6LS.js → cleanup-graph-garbage-XWUFAMFO.js} +6 -6
- package/dist/{co-activation-XMPHKGHR.js → co-activation-ZCHPLLP6.js} +4 -4
- package/dist/{co-occurrence-SHKSJ6CV.js → co-occurrence-KG3LKALN.js} +4 -4
- package/dist/{code-context-index-EXXDY3QZ.js → code-context-index-WSOJQ72R.js} +5 -5
- package/dist/{content-extractor-RHITF2KM.js → content-extractor-NXYNEF5K.js} +2 -2
- package/dist/{conversation-wiki-populator-WU4HEQ7C.js → conversation-wiki-populator-WQN3IUU6.js} +1 -1
- package/dist/{crdt-sync-UJELKSNX.js → crdt-sync-4PFGPZXV.js} +8 -1
- package/dist/{crm-webhook-HHNBS7LY.js → crm-webhook-II7Z45Q6.js} +2 -2
- package/dist/cto-delegation-gate-JWWOJPNC.js +669 -0
- package/dist/{daemon-auth-7IFSV5FG.js → daemon-auth-3FEAHFWC.js} +5 -3
- package/dist/{daemon-orchestration-7QB6QOXT.js → daemon-orchestration-FX4XZDR5.js} +46 -27
- package/dist/{daemon-ready-5XI5BIJD.js → daemon-ready-4JTSFKAY.js} +1 -1
- package/dist/{daemon-ready-signal-E7VMIQ6I.js → daemon-ready-signal-LPAZWQOV.js} +5 -1
- package/dist/daemon-restart-circuit-breaker-PEGEIP6H.js +35 -0
- package/dist/daemon-timer-report-NM44WQRH.js +25 -0
- package/dist/{db-backup-DLD4QZBO.js → db-backup-W2QFSYQC.js} +15 -5
- package/dist/{db-restore-events-JVEEP52Z.js → db-restore-events-MQ2DBGEQ.js} +2 -2
- package/dist/dispatch-ack-VYH3ONSS.js +27 -0
- package/dist/{doc-graph-extractor-3TRLGD7M.js → doc-graph-extractor-F6ODFIID.js} +4 -4
- package/dist/{documents-FHIBU7KJ.js → documents-23WX2FPQ.js} +12 -12
- package/dist/dreaming-NWD22UQ5.js +46 -0
- package/dist/{exe-drift-KY2KHZEL.js → exe-drift-CW72FBGE.js} +5 -5
- package/dist/{exe-export-SP6G3QF6.js → exe-export-AUJ7CV7G.js} +11 -11
- package/dist/{exe-import-KJU7FBVQ.js → exe-import-JX4I52VE.js} +11 -11
- package/dist/{exe-key-M6TYHNUW.js → exe-key-2N6LY2BU.js} +241 -226
- package/dist/{exe-org-BGZNNE4H.js → exe-org-X4CSNCKS.js} +3 -3
- package/dist/{exe-snapshot-ZNPGUKRZ.js → exe-snapshot-XZ7FVCYZ.js} +31 -29
- package/dist/{fast-db-init-QQB6IVWV.js → fast-db-init-4CWHSOOR.js} +1 -1
- package/dist/{founder-context-PQR3BUS7.js → founder-context-7L3CFPYN.js} +4 -4
- package/dist/gateway/index.js +14 -14
- package/dist/{gateway-client-GRBOJQYC.js → gateway-client-7LMZKHTH.js} +1 -1
- package/dist/git-main-guard-UZP3KXYI.js +39 -0
- package/dist/{git-staleness-UGB5J3K7.js → git-staleness-CI2R4QOJ.js} +4 -4
- package/dist/{global-procedures-R7KRREEK.js → global-procedures-XQX3LUH6.js} +6 -6
- package/dist/{graph-auto-extract-LKIQ57PL.js → graph-auto-extract-OURWMGBS.js} +4 -4
- package/dist/{hook-integrity-WURH6DS3.js → hook-integrity-XY47IM7G.js} +1 -1
- package/dist/hook-prefetch-PHRRKY4C.js +137 -0
- package/dist/hooks/bug-report-worker.js +32 -28
- package/dist/hooks/codex-stop-task-finalizer.js +32 -28
- package/dist/hooks/commit-complete.js +29 -27
- package/dist/hooks/error-recall.js +12 -11
- package/dist/hooks/exe-heartbeat-hook.js +6 -6
- package/dist/hooks/ingest-worker.js +11 -11
- package/dist/hooks/ingest.js +18 -18
- package/dist/hooks/instructions-loaded.js +7 -7
- package/dist/hooks/manifest.json +20 -20
- package/dist/hooks/notification.js +7 -7
- package/dist/hooks/post-compact.js +28 -26
- package/dist/hooks/post-tool-combined.js +12 -12
- package/dist/hooks/pre-compact.js +29 -27
- package/dist/hooks/pre-tool-use.js +180 -47
- package/dist/hooks/prompt-submit.js +324 -273
- package/dist/hooks/session-end.js +35 -33
- package/dist/hooks/session-start.js +28 -21
- package/dist/hooks/stop.js +35 -33
- package/dist/hooks/subagent-stop.js +28 -26
- package/dist/hooks/summary-worker.js +36 -34
- package/dist/index.js +39 -37
- package/dist/{installer-SB2N5NKH.js → installer-G3JAO3NT.js} +9 -9
- package/dist/{installer-MZWWBXM6.js → installer-JND3RJ6Q.js} +9 -9
- package/dist/{installer-MNPXDLGG.js → installer-L7EVH5U5.js} +9 -9
- package/dist/{intercom-queue-VU2G6F5R.js → intercom-queue-ZFEQALR3.js} +25 -23
- package/dist/{key-backup-status-TNEHXA2X.js → key-backup-status-LOSMVATJ.js} +2 -2
- package/dist/lib/agent-config.js +4 -3
- package/dist/lib/cloud-sync.js +19 -19
- package/dist/lib/config.js +2 -2
- package/dist/lib/consolidation.js +9 -9
- package/dist/lib/crypto.js +3 -3
- package/dist/lib/database.js +6 -4
- package/dist/lib/db-daemon-client.js +5 -5
- package/dist/lib/db-read-worker-client.js +9 -3
- package/dist/lib/db.js +6 -4
- package/dist/lib/device-registry.js +3 -3
- package/dist/lib/embed-worker.js +2 -2
- package/dist/lib/embedder.js +5 -5
- package/dist/lib/employee-templates.js +7 -7
- package/dist/lib/employees.js +10 -4
- package/dist/lib/exe-daemon-client.js +4 -4
- package/dist/lib/exe-daemon.js +651 -158
- package/dist/lib/hybrid-search.js +11 -9
- package/dist/lib/identity.js +4 -4
- package/dist/lib/keychain.js +1 -1
- package/dist/lib/license.js +4 -4
- package/dist/lib/messaging.js +28 -24
- package/dist/lib/post-tool-memory.js +3 -3
- package/dist/lib/registry-proxy.js +1 -1
- package/dist/lib/reminders.js +15 -7
- package/dist/lib/schedules.js +9 -9
- package/dist/lib/session-registry.js +6 -6
- package/dist/lib/skill-learning.js +10 -10
- package/dist/lib/status-brief.js +4 -4
- package/dist/lib/store.js +8 -8
- package/dist/lib/task-router.js +5 -5
- package/dist/lib/tasks.js +29 -25
- package/dist/lib/tmux-routing.js +56 -25
- package/dist/lib/tmux-status.js +9 -3
- package/dist/lib/tmux-transport.js +1 -1
- package/dist/lib/token-spend.js +5 -5
- package/dist/lib/transport.js +2 -2
- package/dist/lib/ws-client.js +1 -1
- package/dist/{license-gate-BYDMFMFT.js → license-gate-QTRQHV4F.js} +5 -5
- package/dist/{license-sync-N3RNYVP2.js → license-sync-N3UJFWAW.js} +4 -4
- package/dist/mcp/register-tools.js +96 -89
- package/dist/mcp/server.js +98 -91
- package/dist/mcp/tools/complete-reminder.js +6 -6
- package/dist/mcp/tools/create-reminder.js +6 -6
- package/dist/mcp/tools/create-task.js +37 -28
- package/dist/mcp/tools/deactivate-behavior.js +11 -11
- package/dist/mcp/tools/list-reminders.js +6 -6
- package/dist/mcp/tools/list-tasks.js +35 -29
- package/dist/mcp/tools/send-message.js +28 -26
- package/dist/mcp/tools/update-task.js +34 -28
- package/dist/{mcp-http-config-EMAVS2JI.js → mcp-http-config-BDL36JZ3.js} +6 -6
- package/dist/{mcp-port-config-FFAMMLLE.js → mcp-port-config-6HYY6J7K.js} +2 -2
- package/dist/mcp-session-identity-T7H2EKFQ.js +177 -0
- package/dist/{memory-cards-TQRLZI4D.js → memory-cards-ZRDW7QBX.js} +8 -8
- package/dist/{memory-graph-extractor-IWGNVAFU.js → memory-graph-extractor-QLXDMHRS.js} +5 -5
- package/dist/{memory-poisoning-defense-T4ITBGSG.js → memory-poisoning-defense-HJTXYCWH.js} +4 -4
- package/dist/{memory-pressure-watchdog-RRIAXPXQ.js → memory-pressure-watchdog-HN5X7AVN.js} +76 -37
- package/dist/{memory-queue-X2CSEAKE.js → memory-queue-2UOOF27L.js} +5 -3
- package/dist/{memory-queue-client-BKQHTYTH.js → memory-queue-client-O5U6F6XP.js} +6 -6
- package/dist/{memory-reflection-6N4J2FL7.js → memory-reflection-WVNFBJAA.js} +4 -4
- package/dist/{monitor-grants-RZOVSYVO.js → monitor-grants-E3ELDEWD.js} +5 -5
- package/dist/{monitor-identity-MOXISYNG.js → monitor-identity-GLFZSEAH.js} +2 -2
- package/dist/notification-ledger-SZEPGJQ7.js +409 -0
- package/dist/{notifications-KONB3C62.js → notifications-4UT53CDG.js} +25 -23
- package/dist/{orchestration-events-5SIJOE4H.js → orchestration-events-WV4NWKZH.js} +5 -5
- package/dist/{orchestration-phase-CXRCBCK7.js → orchestration-phase-AWBXPO52.js} +3 -3
- package/dist/orchestrator-UAC3RW2T.js +47 -0
- package/dist/{pipeline-router-O6HU7DKH.js → pipeline-router-LM53NMWJ.js} +5 -5
- package/dist/{plan-limits-GRNBOBB3.js → plan-limits-2FEY2GOS.js} +7 -7
- package/dist/platform-procedures-X5DFJFV7.js +13 -0
- package/dist/{preferences-TYTGDXQZ.js → preferences-TWIXZBKS.js} +2 -2
- package/dist/{project-boot-SD7GM24K.js → project-boot-4NUH5FRU.js} +2 -2
- package/dist/{projection-worker-ZVOFHTXT.js → projection-worker-FZ7YSN3G.js} +5 -5
- package/dist/{prospective-memory-W6S67LZZ.js → prospective-memory-6D2ASWM3.js} +4 -4
- package/dist/{push-notifications-W5JRXLKJ.js → push-notifications-U6FIBQRW.js} +3 -3
- package/dist/{reranker-QATGTAPC.js → reranker-GYYRPANK.js} +3 -3
- package/dist/{retrieval-health-TWHKYCRK.js → retrieval-health-4Z242P3B.js} +1 -1
- package/dist/{review-polling-PCMD5BFN.js → review-polling-HXAFJZDA.js} +26 -24
- package/dist/runtime/index.js +37 -35
- package/dist/{session-events-3LCVQEL7.js → session-events-O3BV56ZX.js} +26 -24
- package/dist/{session-kill-telemetry-CZSPN5V6.js → session-kill-telemetry-AELE4JDK.js} +26 -24
- package/dist/session-mcp-config-YKNXG5DW.js +50 -0
- package/dist/{session-scope-CFHVSVAQ.js → session-scope-5EAPUT45.js} +25 -23
- package/dist/setup-wizard-NB6R4QVS.js +14 -0
- package/dist/{shard-manager-MBWQEYNG.js → shard-manager-35PWFR3B.js} +3 -3
- package/dist/{skill-refinement-74T6VDFM.js → skill-refinement-DVSYXBBP.js} +5 -5
- package/dist/stack-promote-RSOWO6EY.js +130 -0
- package/dist/{stack-release-XXMV7SPX.js → stack-release-HGFFFCGC.js} +112 -22
- package/dist/{stack-update-E2TKHHSQ.js → stack-update-ATCJFOEK.js} +7 -5
- package/dist/{steward-gate-WT7WXQIE.js → steward-gate-3GQ5XKMJ.js} +5 -5
- package/dist/support-inbox-4L62P4EP.js +33 -0
- package/dist/support-outbox-WHGPUYL2.js +16 -0
- package/dist/task-enforcement-IPIZX2MM.js +90 -0
- package/dist/{task-scope-CQEG5SSJ.js → task-scope-FOIW25HR.js} +27 -23
- package/dist/{tasks-crud-UGK5A25L.js → tasks-crud-HBDKE6C5.js} +35 -23
- package/dist/tasks-notify-G2U2U2YA.js +53 -0
- package/dist/{tasks-review-JKBRACII.js → tasks-review-27SFX5XN.js} +27 -23
- package/dist/{telemetry-upload-7LBYGPCB.js → telemetry-upload-ZOXHRWR5.js} +9 -9
- package/dist/tmux-command-guard-KSJKIX3C.js +117 -0
- package/dist/{token-budget-QBRJR4M5.js → token-budget-5Y4YPDO3.js} +5 -5
- package/dist/{tool-capability-index-Q6YQDL7I.js → tool-capability-index-VYF5GNJ2.js} +1 -1
- package/dist/{tool-telemetry-ULIDUK3P.js → tool-telemetry-KBXSBDTK.js} +1 -1
- package/dist/tui/App.js +40 -38
- package/dist/{tui-data-NPTGKT37.js → tui-data-NLFMBIQI.js} +25 -23
- package/dist/{update-check-HFO4VHO4.js → update-check-3FHAWIG2.js} +7 -3
- package/dist/update-support-UVUSZG7R.js +355 -0
- package/dist/{whatsapp-accounts-BWRZUY23.js → whatsapp-accounts-BFIOXYW5.js} +1 -1
- package/dist/{whatsapp-config-GOSELKTE.js → whatsapp-config-FAX6EA5K.js} +20 -13
- package/dist/{worker-gate-MXUQUG4M.js → worker-gate-3KUBAU32.js} +3 -3
- package/dist/{workflow-engine-EWCOLD47.js → workflow-engine-YITHXZR5.js} +2 -2
- package/dist/{working-memory-PY4AG577.js → working-memory-NUVB5SFV.js} +1 -1
- package/dist/worktree-LL62PLQB.js +47 -0
- package/dist/{worktree-sweep-ZAG3V24E.js → worktree-sweep-WTK3MTKH.js} +7 -7
- package/package.json +3 -2
- package/release-notes.json +86 -76
- package/dist/branch-hygiene-R5NVTRAY.js +0 -138
- package/dist/chunk-6IRVGOUL.js +0 -30
- package/dist/chunk-HMP5VT6A.js +0 -118
- package/dist/chunk-PVYR4FCQ.js +0 -113
- package/dist/chunk-UFAXZ2PY.js +0 -138
- package/dist/chunk-Y25OJWOQ.js +0 -45
- package/dist/chunk-YGAAZN3E.js +0 -47
- package/dist/cto-delegation-gate-DXNF5HVW.js +0 -290
- package/dist/dispatch-ack-4S44HBWB.js +0 -15
- package/dist/dreaming-OMFUEUCQ.js +0 -44
- package/dist/orchestrator-DUUX7FQV.js +0 -45
- package/dist/setup-wizard-TOFEJPLF.js +0 -13
- package/dist/tasks-notify-SMLDFBWM.js +0 -50
- package/dist/worktree-GVF2I5FP.js +0 -31
- /package/dist/{chunk-FLNSJ2TC.js → chunk-GIBYNT6W.js} +0 -0
- /package/dist/{chunk-NQBRGXYR.js → chunk-JRM4TAGS.js} +0 -0
- /package/dist/{chunk-WHRTDN5J.js → chunk-MGGOSFCR.js} +0 -0
- /package/dist/{chunk-D3QASX2W.js → chunk-QIFYLIUF.js} +0 -0
- /package/dist/{chunk-OADURIIN.js → chunk-WTH4CSAP.js} +0 -0
- /package/dist/{core-memory-VO5ZIBKH.js → core-memory-GAC6EWOQ.js} +0 -0
- /package/dist/{entity-boost-DNI4A5I7.js → entity-boost-NT6UO2Z3.js} +0 -0
- /package/dist/{message-queue-client-Q5BW3O5W.js → message-queue-client-4EOQRUXW.js} +0 -0
- /package/dist/{oauth-server-ROQFOEMM.js → oauth-server-67YBDP32.js} +0 -0
- /package/dist/{webhook-pipe-FZYLO6RR.js → webhook-pipe-LEXMUQ5B.js} +0 -0
- /package/dist/{wiki-acl-JA5UCQZ4.js → wiki-acl-74BLWG6J.js} +0 -0
- /package/dist/{wiki-client-VNDOBK63.js → wiki-client-EAN7F5LV.js} +0 -0
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
readBreakerAlert,
|
|
3
|
+
recordDaemonRestart,
|
|
4
|
+
restartBootsInWindow,
|
|
5
|
+
restartBreakerAlertPath,
|
|
6
|
+
writeDaemonExitBreadcrumb
|
|
7
|
+
} from "../chunk-HJ447YER.js";
|
|
5
8
|
import {
|
|
6
9
|
pushNotifyAsync
|
|
7
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-3SW4OEHB.js";
|
|
11
|
+
import {
|
|
12
|
+
clearDaemonReady,
|
|
13
|
+
eventLoopHeartbeatPath,
|
|
14
|
+
writeDaemonReady
|
|
15
|
+
} from "../chunk-MOPUCPXK.js";
|
|
8
16
|
import {
|
|
9
17
|
getMcpToolFamily,
|
|
10
18
|
inferMcpRuntime,
|
|
11
19
|
recordMcpHttpEvent
|
|
12
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-RAXVPNMR.js";
|
|
13
21
|
import {
|
|
14
22
|
deserializeArgs,
|
|
15
23
|
serializeResultSet
|
|
@@ -21,8 +29,11 @@ import {
|
|
|
21
29
|
findScopedDuplicate,
|
|
22
30
|
governMemoryRecord,
|
|
23
31
|
schedulePostWriteMemoryHygiene
|
|
24
|
-
} from "../chunk-
|
|
25
|
-
import "../chunk-
|
|
32
|
+
} from "../chunk-6XWTQUO4.js";
|
|
33
|
+
import "../chunk-4QCFFW2H.js";
|
|
34
|
+
import {
|
|
35
|
+
BUSY_PATTERN
|
|
36
|
+
} from "../chunk-GWDSB25T.js";
|
|
26
37
|
import {
|
|
27
38
|
attributeSignalSource,
|
|
28
39
|
consumeRestartIntentDetail,
|
|
@@ -30,10 +41,11 @@ import {
|
|
|
30
41
|
requestRestart
|
|
31
42
|
} from "../chunk-AFNRE2RV.js";
|
|
32
43
|
import {
|
|
44
|
+
assessInitialBindIdentity,
|
|
33
45
|
ensureDaemonToken,
|
|
34
46
|
reconcileSessionAgentIdentity,
|
|
35
47
|
shouldEnforceSessionIdentity
|
|
36
|
-
} from "../chunk-
|
|
48
|
+
} from "../chunk-X2Q5NLUL.js";
|
|
37
49
|
import {
|
|
38
50
|
DAEMON_RSS_RESTART_DEBOUNCE,
|
|
39
51
|
DAEMON_RSS_STARTUP_GRACE_MS,
|
|
@@ -70,8 +82,8 @@ import {
|
|
|
70
82
|
EXE_AI_DIR,
|
|
71
83
|
MODELS_DIR,
|
|
72
84
|
resolveEmbedModelFile
|
|
73
|
-
} from "../chunk-
|
|
74
|
-
import "../chunk-
|
|
85
|
+
} from "../chunk-WZHZCDDO.js";
|
|
86
|
+
import "../chunk-BYTDMAGB.js";
|
|
75
87
|
import "../chunk-MLKGABMK.js";
|
|
76
88
|
|
|
77
89
|
// src/lib/exe-daemon.ts
|
|
@@ -79,11 +91,41 @@ import os2 from "os";
|
|
|
79
91
|
import net from "net";
|
|
80
92
|
import v8 from "v8";
|
|
81
93
|
import { createServer as createHttpServer, request as httpRequest } from "http";
|
|
82
|
-
import { randomUUID } from "crypto";
|
|
94
|
+
import { randomUUID, timingSafeEqual } from "crypto";
|
|
83
95
|
import { writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2, existsSync as existsSync4, readFileSync as readFileSync4, chmodSync, readdirSync, renameSync, statSync } from "fs";
|
|
84
96
|
import { writeFile } from "fs/promises";
|
|
85
97
|
import { execSync as execSyncNode, execFile as execFileNode } from "child_process";
|
|
86
98
|
import { promisify } from "util";
|
|
99
|
+
|
|
100
|
+
// src/lib/coo-respawn.ts
|
|
101
|
+
var NPM_ROOT_RETRY_MS = (() => {
|
|
102
|
+
const raw = process.env.EXE_NPM_ROOT_RETRY_MS;
|
|
103
|
+
const n = raw !== void 0 ? Number(raw) : NaN;
|
|
104
|
+
return Number.isFinite(n) && n >= 0 ? n : 5 * 6e4;
|
|
105
|
+
})();
|
|
106
|
+
function createMemoizedNpmGlobalRootResolver(execFile, log = (m) => void process.stderr.write(m), opts = {}) {
|
|
107
|
+
const retryMs = opts.retryMs ?? NPM_ROOT_RETRY_MS;
|
|
108
|
+
const now = opts.now ?? (() => Date.now());
|
|
109
|
+
let memo = null;
|
|
110
|
+
let failedAt = null;
|
|
111
|
+
return async () => {
|
|
112
|
+
if (memo !== null) return memo;
|
|
113
|
+
if (failedAt !== null && now() - failedAt < retryMs) return null;
|
|
114
|
+
try {
|
|
115
|
+
const { stdout } = await execFile("npm", ["root", "-g"], { timeout: 5e3, encoding: "utf8" });
|
|
116
|
+
memo = stdout.trim();
|
|
117
|
+
failedAt = null;
|
|
118
|
+
return memo;
|
|
119
|
+
} catch (err) {
|
|
120
|
+
failedAt = now();
|
|
121
|
+
log(`[exed] npm root -g resolution failed (memoized, retry after ${Math.round(retryMs / 1e3)}s): ${err instanceof Error ? err.message : String(err)}
|
|
122
|
+
`);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/lib/exe-daemon.ts
|
|
87
129
|
import path3 from "path";
|
|
88
130
|
import { fileURLToPath } from "url";
|
|
89
131
|
import { fork, spawn } from "child_process";
|
|
@@ -192,6 +234,10 @@ function validateWriteShape(maskedSql) {
|
|
|
192
234
|
}
|
|
193
235
|
return null;
|
|
194
236
|
}
|
|
237
|
+
function isOffloadableDaemonReadSql(sql) {
|
|
238
|
+
const masked = maskSqlLiteralsAndComments(sql.trim());
|
|
239
|
+
return DAEMON_READ_SQL_RE.test(masked);
|
|
240
|
+
}
|
|
195
241
|
function validateDaemonDbSql(sql) {
|
|
196
242
|
const original = sql.trim();
|
|
197
243
|
if (!original) return "empty SQL is not allowed";
|
|
@@ -330,6 +376,20 @@ async function awaitPendingMcpInit(ownerKey, requestSessionId, deps, transientMa
|
|
|
330
376
|
return null;
|
|
331
377
|
}
|
|
332
378
|
|
|
379
|
+
// src/lib/daemon-self-heal-dispatch.ts
|
|
380
|
+
function dispatchSelfHealRestart(lagMs, trigger, deps) {
|
|
381
|
+
deps.writeBreadcrumb(lagMs, trigger);
|
|
382
|
+
deps.shutdown(75);
|
|
383
|
+
}
|
|
384
|
+
function resolveSelfHealThresholds(env = process.env) {
|
|
385
|
+
return {
|
|
386
|
+
singleMs: parseFloat(env.EXE_SELF_HEAL_SINGLE_MS ?? "") || 12e4,
|
|
387
|
+
thresholdMs: parseFloat(env.EXE_SELF_HEAL_THRESHOLD_MS ?? "") || 3e4,
|
|
388
|
+
consecutive: parseInt(env.EXE_SELF_HEAL_CONSECUTIVE ?? "") || 3,
|
|
389
|
+
starvationRatio: parseFloat(env.EXE_STARVATION_LOAD_RATIO ?? "1.5")
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
333
393
|
// src/lib/daemon-restart-backoff.ts
|
|
334
394
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync, mkdirSync } from "fs";
|
|
335
395
|
import { createHash } from "crypto";
|
|
@@ -815,7 +875,7 @@ async function capturePaneAsync(session, lines = 20) {
|
|
|
815
875
|
}
|
|
816
876
|
}
|
|
817
877
|
function classifyPaneState(pane) {
|
|
818
|
-
const busyPattern =
|
|
878
|
+
const busyPattern = BUSY_PATTERN;
|
|
819
879
|
if (!pane.includes("\u276F") && !pane.includes("Claude Code") && !busyPattern.test(pane) && !/Running…/.test(pane)) {
|
|
820
880
|
if (/\$\s*$/.test(pane) || /% $/.test(pane.trimEnd())) return "no_claude";
|
|
821
881
|
}
|
|
@@ -884,7 +944,7 @@ async function batchPaneAlive(sessions) {
|
|
|
884
944
|
}
|
|
885
945
|
return alive;
|
|
886
946
|
}
|
|
887
|
-
var CACHED_SESSION_BUSY_PATTERN =
|
|
947
|
+
var CACHED_SESSION_BUSY_PATTERN = BUSY_PATTERN;
|
|
888
948
|
function getCachedSessionState(sessionName, paneCache, aliveSessions) {
|
|
889
949
|
if (!aliveSessions.has(sessionName)) return "offline";
|
|
890
950
|
const pane = paneCache.get(sessionName);
|
|
@@ -974,6 +1034,46 @@ function shouldTraceDaemonTimer(durationMs = 0) {
|
|
|
974
1034
|
return Date.now() - _startedAt2 < TIMER_TRACE_BOOT_WINDOW_MS || durationMs >= TIMER_TRACE_SLOW_MS;
|
|
975
1035
|
}
|
|
976
1036
|
var yieldToEventLoop = () => new Promise((resolve) => setImmediate(resolve));
|
|
1037
|
+
var _lastBlockingTimer = null;
|
|
1038
|
+
function getLastBlockingTimer() {
|
|
1039
|
+
return _lastBlockingTimer;
|
|
1040
|
+
}
|
|
1041
|
+
var _exitBreadcrumbWritten = false;
|
|
1042
|
+
function recordExitBreadcrumb(kind, exitCode, reason, extra) {
|
|
1043
|
+
if (_exitBreadcrumbWritten) return;
|
|
1044
|
+
_exitBreadcrumbWritten = true;
|
|
1045
|
+
let rssBytes;
|
|
1046
|
+
try {
|
|
1047
|
+
rssBytes = process.memoryUsage().rss;
|
|
1048
|
+
} catch {
|
|
1049
|
+
}
|
|
1050
|
+
const info = {
|
|
1051
|
+
exitCode,
|
|
1052
|
+
reason,
|
|
1053
|
+
kind,
|
|
1054
|
+
ts: Date.now(),
|
|
1055
|
+
uptimeMs: Date.now() - _startedAt2,
|
|
1056
|
+
...rssBytes !== void 0 ? { rssBytes } : {},
|
|
1057
|
+
...extra
|
|
1058
|
+
};
|
|
1059
|
+
writeDaemonExitBreadcrumb(info);
|
|
1060
|
+
}
|
|
1061
|
+
function recordSelfHealBreadcrumb(lagMs, trigger) {
|
|
1062
|
+
const blk = _lastBlockingTimer && Date.now() - _lastBlockingTimer.ts < 6e4 ? _lastBlockingTimer : null;
|
|
1063
|
+
recordExitBreadcrumb("self_heal", 75, `self_heal_event_loop_lag:${trigger}`, {
|
|
1064
|
+
lagMs: Math.round(lagMs),
|
|
1065
|
+
...blk ? { timerName: blk.name, timerDurationMs: blk.durationMs } : {}
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
var SELF_HEAL_ACTION_DEPS = {
|
|
1069
|
+
writeBreadcrumb: recordSelfHealBreadcrumb,
|
|
1070
|
+
shutdown: (code) => {
|
|
1071
|
+
void shutdown(code);
|
|
1072
|
+
},
|
|
1073
|
+
exit: (code) => {
|
|
1074
|
+
process.exit(code);
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
977
1077
|
async function traceDaemonTimer(name, fn) {
|
|
978
1078
|
if (_timerInFlight.has(name)) {
|
|
979
1079
|
process.stderr.write(`[exed] Timer SKIPPED (overlap): ${name} \u2014 previous tick still running
|
|
@@ -988,6 +1088,7 @@ async function traceDaemonTimer(name, fn) {
|
|
|
988
1088
|
`);
|
|
989
1089
|
}
|
|
990
1090
|
const timeoutHandle = setTimeout(() => {
|
|
1091
|
+
_lastBlockingTimer = { name, durationMs: TIMER_TIMEOUT_MS, ts: Date.now() };
|
|
991
1092
|
process.stderr.write(
|
|
992
1093
|
`[exed] Timer TIMEOUT WARNING: ${name} has been running for >${TIMER_TIMEOUT_MS / 1e3}s \u2014 likely blocking the event loop
|
|
993
1094
|
`
|
|
@@ -1008,6 +1109,9 @@ async function traceDaemonTimer(name, fn) {
|
|
|
1008
1109
|
const span = measureSpan(probe);
|
|
1009
1110
|
const durationMs = Math.round(span.monoMs);
|
|
1010
1111
|
const slept = span.sleptMs > 1e3;
|
|
1112
|
+
if (!slept && durationMs >= TIMER_TIMEOUT_MS) {
|
|
1113
|
+
_lastBlockingTimer = { name, durationMs, ts: Date.now() };
|
|
1114
|
+
}
|
|
1011
1115
|
if (shouldTraceDaemonTimer(durationMs)) {
|
|
1012
1116
|
const sleepNote = slept ? ` (wall ${Math.round(span.wallMs)}ms \u2014 host slept/clock-stepped ${Math.round(span.sleptMs)}ms; not an event-loop block)` : "";
|
|
1013
1117
|
const msg = `[exed] Timer duration: ${name} ${durationMs}ms${sleepNote}`;
|
|
@@ -1166,9 +1270,6 @@ function isEventLoopBlockedNow(freshMs = EVENT_LOOP_BLOCKED_FRESH_MS) {
|
|
|
1166
1270
|
return false;
|
|
1167
1271
|
}
|
|
1168
1272
|
}
|
|
1169
|
-
function eventLoopHeartbeatPath() {
|
|
1170
|
-
return path3.join(os2.homedir(), ".exe-os", "session-cache", "event-loop-heartbeat");
|
|
1171
|
-
}
|
|
1172
1273
|
function touchEventLoopHeartbeat() {
|
|
1173
1274
|
try {
|
|
1174
1275
|
const p = eventLoopHeartbeatPath();
|
|
@@ -1438,7 +1539,7 @@ async function loadModel() {
|
|
|
1438
1539
|
void (async () => {
|
|
1439
1540
|
try {
|
|
1440
1541
|
if (_storeInitialized) {
|
|
1441
|
-
const { writeNotification } = await import("../notifications-
|
|
1542
|
+
const { writeNotification } = await import("../notifications-4UT53CDG.js");
|
|
1442
1543
|
await writeNotification({
|
|
1443
1544
|
agentId: "exe",
|
|
1444
1545
|
agentRole: "system",
|
|
@@ -1554,7 +1655,7 @@ function disableEmbeddingsForInferenceTimeouts() {
|
|
|
1554
1655
|
void (async () => {
|
|
1555
1656
|
try {
|
|
1556
1657
|
if (_storeInitialized) {
|
|
1557
|
-
const { writeNotification } = await import("../notifications-
|
|
1658
|
+
const { writeNotification } = await import("../notifications-4UT53CDG.js");
|
|
1558
1659
|
await writeNotification({
|
|
1559
1660
|
agentId: "exe",
|
|
1560
1661
|
agentRole: "system",
|
|
@@ -1723,10 +1824,12 @@ function checkIdle() {
|
|
|
1723
1824
|
_idleTimer.unref();
|
|
1724
1825
|
}
|
|
1725
1826
|
}
|
|
1726
|
-
async function shutdown(exitCode = 0) {
|
|
1827
|
+
async function shutdown(exitCode = 0, reason = null) {
|
|
1727
1828
|
if (_shuttingDown) return;
|
|
1728
1829
|
_shuttingDown = true;
|
|
1729
1830
|
_drainingWrites = true;
|
|
1831
|
+
const _exitKind = exitCode === 0 && !reason ? "clean" : reason ? "self_exit" : "restart-intent";
|
|
1832
|
+
recordExitBreadcrumb(_exitKind, exitCode, reason);
|
|
1730
1833
|
clearDaemonReady();
|
|
1731
1834
|
if (exitCode !== 0) {
|
|
1732
1835
|
recordDaemonCrash();
|
|
@@ -1765,12 +1868,58 @@ async function shutdown(exitCode = 0) {
|
|
|
1765
1868
|
}
|
|
1766
1869
|
}
|
|
1767
1870
|
try {
|
|
1768
|
-
const {
|
|
1769
|
-
|
|
1770
|
-
|
|
1871
|
+
const {
|
|
1872
|
+
createBackupAsync,
|
|
1873
|
+
enforceRetention,
|
|
1874
|
+
hasRecentBackup,
|
|
1875
|
+
preRestartDedupWindowMs,
|
|
1876
|
+
findActiveDb,
|
|
1877
|
+
shouldSkipBackupUnderMemoryPressure
|
|
1878
|
+
} = await import("../db-backup-W2QFSYQC.js");
|
|
1879
|
+
const PRE_RESTART_DEDUP_MS = preRestartDedupWindowMs();
|
|
1880
|
+
const PRE_RESTART_STORM_CAP = (() => {
|
|
1881
|
+
const v = Number(process.env.EXE_PRE_RESTART_STORM_CAP);
|
|
1882
|
+
return Number.isFinite(v) && v > 0 ? Math.floor(v) : 3;
|
|
1883
|
+
})();
|
|
1884
|
+
let stormSkip = false;
|
|
1885
|
+
try {
|
|
1886
|
+
const recentRestarts = restartBootsInWindow();
|
|
1887
|
+
if (recentRestarts >= PRE_RESTART_STORM_CAP) {
|
|
1888
|
+
stormSkip = true;
|
|
1889
|
+
process.stderr.write(
|
|
1890
|
+
`[exed] Pre-restart backup SKIPPED \u2014 restart storm (${recentRestarts} restarts in breaker window \u2265 cap ${PRE_RESTART_STORM_CAP}). Bounding total 1.7GB backup bytes; last snapshot + daily backups remain (data-safe).
|
|
1891
|
+
`
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
} catch {
|
|
1895
|
+
}
|
|
1896
|
+
let memoryGateSkip = false;
|
|
1897
|
+
try {
|
|
1898
|
+
const dbPath = findActiveDb();
|
|
1899
|
+
let dbBytes = 0;
|
|
1900
|
+
try {
|
|
1901
|
+
dbBytes = dbPath ? statSync(dbPath).size : 0;
|
|
1902
|
+
} catch {
|
|
1903
|
+
}
|
|
1904
|
+
const { getAvailableMemoryBytesSync } = await import("../memory-pressure-watchdog-HN5X7AVN.js");
|
|
1905
|
+
const freeBytes = getAvailableMemoryBytesSync();
|
|
1906
|
+
if (shouldSkipBackupUnderMemoryPressure(freeBytes, dbBytes)) {
|
|
1907
|
+
memoryGateSkip = true;
|
|
1908
|
+
process.stderr.write(
|
|
1909
|
+
`[exed] Pre-restart backup SKIPPED under memory pressure \u2014 ${Math.round(freeBytes / 1024 / 1024)}MB free vs ${Math.round(dbBytes / 1024 / 1024)}MB DB. Skipping the copy is data-safe; OOM-killing the machine mid-copy is not.
|
|
1910
|
+
`
|
|
1911
|
+
);
|
|
1912
|
+
}
|
|
1913
|
+
} catch {
|
|
1914
|
+
}
|
|
1915
|
+
if (stormSkip) {
|
|
1916
|
+
enforceRetention("pre-restart");
|
|
1917
|
+
} else if (hasRecentBackup("pre-restart", PRE_RESTART_DEDUP_MS)) {
|
|
1771
1918
|
const deleted = enforceRetention("pre-restart");
|
|
1772
1919
|
process.stderr.write(`[exed] Pre-restart backup skipped \u2014 recent snapshot exists (crash-loop dedup)${deleted > 0 ? `; rotated ${deleted} old` : ""}.
|
|
1773
1920
|
`);
|
|
1921
|
+
} else if (memoryGateSkip) {
|
|
1922
|
+
enforceRetention("pre-restart");
|
|
1774
1923
|
} else {
|
|
1775
1924
|
const backupPath = await createBackupAsync("pre-restart");
|
|
1776
1925
|
if (backupPath) {
|
|
@@ -1796,12 +1945,12 @@ async function shutdown(exitCode = 0) {
|
|
|
1796
1945
|
`);
|
|
1797
1946
|
}
|
|
1798
1947
|
try {
|
|
1799
|
-
const { stopProjectionWorker } = await import("../projection-worker-
|
|
1948
|
+
const { stopProjectionWorker } = await import("../projection-worker-FZ7YSN3G.js");
|
|
1800
1949
|
stopProjectionWorker();
|
|
1801
1950
|
} catch {
|
|
1802
1951
|
}
|
|
1803
1952
|
try {
|
|
1804
|
-
const { disposeShards } = await import("../shard-manager-
|
|
1953
|
+
const { disposeShards } = await import("../shard-manager-35PWFR3B.js");
|
|
1805
1954
|
disposeShards();
|
|
1806
1955
|
} catch {
|
|
1807
1956
|
}
|
|
@@ -1862,7 +2011,7 @@ async function handleHealthCheck(socket, requestId) {
|
|
|
1862
2011
|
let pipelineStatus = "unknown";
|
|
1863
2012
|
if (dbConnected) {
|
|
1864
2013
|
try {
|
|
1865
|
-
await import("../pipeline-router-
|
|
2014
|
+
await import("../pipeline-router-LM53NMWJ.js");
|
|
1866
2015
|
pipelineStatus = "ok";
|
|
1867
2016
|
} catch {
|
|
1868
2017
|
pipelineStatus = "unavailable";
|
|
@@ -1967,6 +2116,18 @@ async function handleDbExecute(socket, requestId, sql, args) {
|
|
|
1967
2116
|
sendResponse(socket, { id: requestId, error: "DB not initialized" });
|
|
1968
2117
|
return;
|
|
1969
2118
|
}
|
|
2119
|
+
if (isOffloadableDaemonReadSql(sql)) {
|
|
2120
|
+
try {
|
|
2121
|
+
const { isDbReadWorkerReady, runReadQueryInWorkerSerialized } = await import("./db-read-worker-client.js");
|
|
2122
|
+
if (isDbReadWorkerReady()) {
|
|
2123
|
+
const serialized = await runReadQueryInWorkerSerialized(sql, args);
|
|
2124
|
+
_dbRequestsServed++;
|
|
2125
|
+
sendResponse(socket, { id: requestId, db: serialized });
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2128
|
+
} catch {
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
1970
2131
|
const { getClient } = await import("./database.js");
|
|
1971
2132
|
const client = getClient();
|
|
1972
2133
|
const deserializedArgs = deserializeArgs(args);
|
|
@@ -2258,7 +2419,7 @@ async function _writeMemoryRecordInner(entry) {
|
|
|
2258
2419
|
const vRow = await client.execute({ sql: "SELECT version FROM memories WHERE id = ?", args: [id] });
|
|
2259
2420
|
const version = Number(vRow.rows[0]?.version) || 0;
|
|
2260
2421
|
try {
|
|
2261
|
-
const { insertOntologyForMemory } = await import("../agentic-ontology-
|
|
2422
|
+
const { insertOntologyForMemory } = await import("../agentic-ontology-3FXYMHKW.js");
|
|
2262
2423
|
await insertOntologyForMemory({
|
|
2263
2424
|
id,
|
|
2264
2425
|
agent_id: record.agent_id,
|
|
@@ -2287,37 +2448,34 @@ function startMemoryQueueDrain() {
|
|
|
2287
2448
|
fired("memory_queue_drain");
|
|
2288
2449
|
if (!await ensureStoreForPolling()) return;
|
|
2289
2450
|
try {
|
|
2290
|
-
const { ackQueue, claimQueue, retryQueueEntries } = await import("../memory-queue-
|
|
2451
|
+
const { ackQueue, claimQueue, retryQueueEntries, processQueueEntries } = await import("../memory-queue-2UOOF27L.js");
|
|
2291
2452
|
const lease = claimQueue();
|
|
2292
2453
|
if (!lease || lease.entries.length === 0) return;
|
|
2293
2454
|
acted("memory_queue_drain");
|
|
2294
2455
|
const entries = lease.entries;
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
try {
|
|
2301
|
-
await writeMemoryRecord(entry);
|
|
2302
|
-
processed++;
|
|
2303
|
-
} catch (err) {
|
|
2304
|
-
retryEntries.push(entry);
|
|
2456
|
+
const result = await processQueueEntries(entries, (entry) => writeMemoryRecord(entry), {
|
|
2457
|
+
isDraining: () => _drainingWrites,
|
|
2458
|
+
batchSize: MEMORY_DRAIN_BATCH,
|
|
2459
|
+
yieldFn: yieldToEventLoop,
|
|
2460
|
+
onWriteError: (_entry, err) => {
|
|
2305
2461
|
process.stderr.write(
|
|
2306
2462
|
`[exed] Queue drain write error: ${err instanceof Error ? err.message : String(err)}
|
|
2463
|
+
`
|
|
2464
|
+
);
|
|
2465
|
+
},
|
|
2466
|
+
onShutdownPreserve: (count) => {
|
|
2467
|
+
process.stderr.write(
|
|
2468
|
+
`[exed] Queue drain interrupted by shutdown \u2014 ${count} entr${count === 1 ? "y" : "ies"} preserved in lease for replay after restart
|
|
2307
2469
|
`
|
|
2308
2470
|
);
|
|
2309
2471
|
}
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
await yieldToEventLoop();
|
|
2313
|
-
}
|
|
2314
|
-
}
|
|
2315
|
-
if (retryEntries.length === 0) {
|
|
2472
|
+
});
|
|
2473
|
+
if (result.retryEntries.length === 0) {
|
|
2316
2474
|
ackQueue(lease.leasePath);
|
|
2317
2475
|
} else {
|
|
2318
|
-
retryQueueEntries(lease.leasePath, retryEntries);
|
|
2476
|
+
retryQueueEntries(lease.leasePath, result.retryEntries);
|
|
2319
2477
|
}
|
|
2320
|
-
process.stderr.write(`[exed] Queue drain: processed ${processed}/${entries.length} memories
|
|
2478
|
+
process.stderr.write(`[exed] Queue drain: processed ${result.processed}/${entries.length} memories${result.preserved > 0 ? ` (${result.preserved} preserved for replay)` : ""}
|
|
2321
2479
|
`);
|
|
2322
2480
|
} catch (err) {
|
|
2323
2481
|
process.stderr.write(
|
|
@@ -2348,7 +2506,7 @@ function startMessageQueueDrain() {
|
|
|
2348
2506
|
fired("message_queue_drain");
|
|
2349
2507
|
if (!await ensureStoreForPolling()) return;
|
|
2350
2508
|
try {
|
|
2351
|
-
const { claimMessageQueue, ackMessageQueue } = await import("../message-queue-client-
|
|
2509
|
+
const { claimMessageQueue, ackMessageQueue } = await import("../message-queue-client-4EOQRUXW.js");
|
|
2352
2510
|
const lease = claimMessageQueue();
|
|
2353
2511
|
if (!lease || lease.entries.length === 0) return;
|
|
2354
2512
|
acted("message_queue_drain");
|
|
@@ -2994,7 +3152,7 @@ async function startMcpHttpServer() {
|
|
|
2994
3152
|
process.stderr.write("[exed] MCP HTTP: DB ready\n");
|
|
2995
3153
|
setBootPhase("db_ready");
|
|
2996
3154
|
_storeInitialized = true;
|
|
2997
|
-
const { initLicenseGate, getCachedLicenseGate } = await import("../license-gate-
|
|
3155
|
+
const { initLicenseGate, getCachedLicenseGate } = await import("../license-gate-QTRQHV4F.js");
|
|
2998
3156
|
const gateResult = await initLicenseGate();
|
|
2999
3157
|
if (!gateResult.hasKey) {
|
|
3000
3158
|
process.stderr.write(
|
|
@@ -3009,13 +3167,13 @@ async function startMcpHttpServer() {
|
|
|
3009
3167
|
let _cachedWrapTelemetry = null;
|
|
3010
3168
|
async function getWrapTelemetry() {
|
|
3011
3169
|
if (!_cachedWrapTelemetry) {
|
|
3012
|
-
const { wrapServerWithTelemetry } = await import("../tool-telemetry-
|
|
3170
|
+
const { wrapServerWithTelemetry } = await import("../tool-telemetry-KBXSBDTK.js");
|
|
3013
3171
|
_cachedWrapTelemetry = wrapServerWithTelemetry;
|
|
3014
3172
|
}
|
|
3015
3173
|
return _cachedWrapTelemetry;
|
|
3016
3174
|
}
|
|
3017
3175
|
Promise.all([
|
|
3018
|
-
import("../tool-capability-index-
|
|
3176
|
+
import("../tool-capability-index-VYF5GNJ2.js"),
|
|
3019
3177
|
import("../tool-gates-3IC7DK4R.js")
|
|
3020
3178
|
]).then(async ([{ getToolCapabilityIndex }, { TOOL_CATEGORIES }]) => {
|
|
3021
3179
|
const gateState = getCachedLicenseGate();
|
|
@@ -3077,9 +3235,11 @@ async function startMcpHttpServer() {
|
|
|
3077
3235
|
if (!header) return false;
|
|
3078
3236
|
const token = header.replace(/^Bearer\s+/i, "");
|
|
3079
3237
|
if (!token || token === header) return false;
|
|
3080
|
-
|
|
3238
|
+
const tokenBuf = Buffer.from(token);
|
|
3239
|
+
const expectedBuf = Buffer.from(_daemonToken);
|
|
3240
|
+
if (tokenBuf.length === expectedBuf.length && timingSafeEqual(tokenBuf, expectedBuf)) return true;
|
|
3081
3241
|
try {
|
|
3082
|
-
const { verifyAccessToken } = await import("../oauth-server-
|
|
3242
|
+
const { verifyAccessToken } = await import("../oauth-server-67YBDP32.js");
|
|
3083
3243
|
const result = verifyAccessToken(token);
|
|
3084
3244
|
return result.valid;
|
|
3085
3245
|
} catch {
|
|
@@ -3295,6 +3455,14 @@ async function startMcpHttpServer() {
|
|
|
3295
3455
|
version: PACKAGE_VERSION,
|
|
3296
3456
|
eventLoopLagMs: Math.round(elLag),
|
|
3297
3457
|
eventLoopBlockedNow: blockedNow,
|
|
3458
|
+
// Feature 9ddc55b2 (timer health dashboard): expose the names of the
|
|
3459
|
+
// timers executing RIGHT NOW. This is a plain read of the existing
|
|
3460
|
+
// in-memory overlap-guard Set (≤ ~96 short strings) on an existing
|
|
3461
|
+
// request handler — it adds ZERO work to the timer hot path. Without
|
|
3462
|
+
// it "is this timer in-flight?" is unanswerable from outside the
|
|
3463
|
+
// process: traceDaemonTimer writes tick *starts* to stderr only, never
|
|
3464
|
+
// durably. When a tick blocks the loop this is the field that names it.
|
|
3465
|
+
timersInFlight: [..._timerInFlight],
|
|
3298
3466
|
...blockedNow && { warning: "Event loop blocked marker is fresh \u2014 /mcp returning 503 Retry-After until marker clears (~10s)" },
|
|
3299
3467
|
...!blockedNow && degraded && { warning: `Event loop lag ${Math.round(elLag)}ms exceeds 5000ms threshold \u2014 daemon may be unresponsive` }
|
|
3300
3468
|
}));
|
|
@@ -3324,7 +3492,7 @@ async function startMcpHttpServer() {
|
|
|
3324
3492
|
return;
|
|
3325
3493
|
}
|
|
3326
3494
|
try {
|
|
3327
|
-
const { handleOAuthRoute } = await import("../oauth-server-
|
|
3495
|
+
const { handleOAuthRoute } = await import("../oauth-server-67YBDP32.js");
|
|
3328
3496
|
const handled = await handleOAuthRoute(req, res, url, MCP_HTTP_PORT);
|
|
3329
3497
|
if (handled) return;
|
|
3330
3498
|
} catch (err) {
|
|
@@ -3356,7 +3524,7 @@ async function startMcpHttpServer() {
|
|
|
3356
3524
|
for await (const chunk of req) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
3357
3525
|
const rawBody = Buffer.concat(chunks);
|
|
3358
3526
|
try {
|
|
3359
|
-
const { loadWebhookConfig, verifyHmac, processWebhook } = await import("../webhook-pipe-
|
|
3527
|
+
const { loadWebhookConfig, verifyHmac, processWebhook } = await import("../webhook-pipe-LEXMUQ5B.js");
|
|
3360
3528
|
const webhookConfig = await loadWebhookConfig();
|
|
3361
3529
|
const serviceConfig = webhookConfig[serviceName];
|
|
3362
3530
|
if (!serviceConfig) {
|
|
@@ -3452,7 +3620,7 @@ async function startMcpHttpServer() {
|
|
|
3452
3620
|
contextPct: body.context_pct
|
|
3453
3621
|
});
|
|
3454
3622
|
if (body.context_pct !== void 0 && body.context_pct > 70) {
|
|
3455
|
-
void import("../orchestration-events-
|
|
3623
|
+
void import("../orchestration-events-WV4NWKZH.js").then(({ recordOrchestrationEventBestEffort: recordOE }) => {
|
|
3456
3624
|
recordOE({
|
|
3457
3625
|
eventType: "context.pressure",
|
|
3458
3626
|
source: "exe-daemon.heartbeat",
|
|
@@ -3535,36 +3703,70 @@ async function startMcpHttpServer() {
|
|
|
3535
3703
|
}
|
|
3536
3704
|
const projectNameHeader = req.headers["x-project-name"] || "";
|
|
3537
3705
|
let sessionHint = req.headers["x-exe-session-name"] || req.headers["x-exe-session"] || "";
|
|
3538
|
-
if (sessionHint
|
|
3539
|
-
|
|
3706
|
+
if (sessionHint) {
|
|
3707
|
+
try {
|
|
3708
|
+
const { sanitizeSessionHintHeader, rejectForgedSessionHint } = await import("../mcp-session-identity-T7H2EKFQ.js");
|
|
3709
|
+
const rawHint = sessionHint;
|
|
3710
|
+
sessionHint = sanitizeSessionHintHeader(sessionHint);
|
|
3711
|
+
if (!sessionHint) {
|
|
3712
|
+
process.stderr.write(
|
|
3713
|
+
`[daemon] WARN: discarded malformed session identity header ${JSON.stringify(rawHint)} from agent "${agentId}"
|
|
3714
|
+
`
|
|
3715
|
+
);
|
|
3716
|
+
} else {
|
|
3717
|
+
try {
|
|
3718
|
+
const { listSessions: listRegistrySessions } = await import("./session-registry.js");
|
|
3719
|
+
const verdict = rejectForgedSessionHint({
|
|
3720
|
+
agentId,
|
|
3721
|
+
hint: sessionHint,
|
|
3722
|
+
registrySessions: listRegistrySessions()
|
|
3723
|
+
});
|
|
3724
|
+
if (verdict.rejected) {
|
|
3725
|
+
process.stderr.write(`[daemon] WARN: ${verdict.reason}
|
|
3726
|
+
`);
|
|
3727
|
+
sessionHint = "";
|
|
3728
|
+
}
|
|
3729
|
+
} catch {
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
} catch {
|
|
3733
|
+
if (sessionHint.includes("$(") || sessionHint.includes("#{") || sessionHint.includes("tmux")) {
|
|
3734
|
+
sessionHint = "";
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3540
3737
|
}
|
|
3541
3738
|
const clientProvidedSessionHint = Boolean(sessionHint);
|
|
3542
3739
|
if (!sessionHint && agentId) {
|
|
3543
3740
|
try {
|
|
3544
3741
|
const liveSessions = await getTmuxSessionsAsync();
|
|
3545
|
-
const
|
|
3546
|
-
|
|
3547
|
-
|
|
3742
|
+
const paneCommands = await getPaneCommandsAsync();
|
|
3743
|
+
const { resolveMcpSessionHint } = await import("../mcp-session-identity-T7H2EKFQ.js");
|
|
3744
|
+
let registrySessions = [];
|
|
3745
|
+
try {
|
|
3746
|
+
const { listSessions: listRegistrySessions } = await import("./session-registry.js");
|
|
3747
|
+
registrySessions = listRegistrySessions();
|
|
3748
|
+
} catch {
|
|
3548
3749
|
}
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
const
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
}
|
|
3750
|
+
let isCoordinator = false;
|
|
3751
|
+
try {
|
|
3752
|
+
const { isCoordinatorName } = await import("./employees.js");
|
|
3753
|
+
isCoordinator = isCoordinatorName(agentId);
|
|
3754
|
+
} catch {
|
|
3755
|
+
}
|
|
3756
|
+
const resolution = resolveMcpSessionHint({
|
|
3757
|
+
agentId,
|
|
3758
|
+
isCoordinator,
|
|
3759
|
+
liveTmuxSessions: liveSessions,
|
|
3760
|
+
registrySessions,
|
|
3761
|
+
// Only count coordinators that still host a LIVE agent. Orphaned
|
|
3762
|
+
// coordinator shells (agent exited, tmux shell lingers) would otherwise
|
|
3763
|
+
// inflate the count forever and spam "cannot auto-resolve" (bug 6c46d301).
|
|
3764
|
+
coordinatorHasLiveAgent: (s) => coordinatorPaneHasLiveAgent(s, paneCommands)
|
|
3765
|
+
});
|
|
3766
|
+
sessionHint = resolution.sessionHint;
|
|
3767
|
+
if (resolution.warning) {
|
|
3768
|
+
process.stderr.write(`[daemon] WARN: ${resolution.warning}
|
|
3769
|
+
`);
|
|
3568
3770
|
}
|
|
3569
3771
|
} catch {
|
|
3570
3772
|
}
|
|
@@ -3662,6 +3864,54 @@ async function startMcpHttpServer() {
|
|
|
3662
3864
|
} catch (dbInitErr) {
|
|
3663
3865
|
process.stderr.write(`[exed] DB init on new session FAILED: ${dbInitErr instanceof Error ? dbInitErr.message : String(dbInitErr)}
|
|
3664
3866
|
`);
|
|
3867
|
+
}
|
|
3868
|
+
try {
|
|
3869
|
+
const { isManagementIdentity } = await import("./employees.js");
|
|
3870
|
+
if (isManagementIdentity(agentId)) {
|
|
3871
|
+
let bindRegistry = [];
|
|
3872
|
+
let bindLive = [];
|
|
3873
|
+
try {
|
|
3874
|
+
const { listSessions: listRegistrySessions } = await import("./session-registry.js");
|
|
3875
|
+
bindRegistry = listRegistrySessions();
|
|
3876
|
+
bindLive = await getTmuxSessionsAsync();
|
|
3877
|
+
} catch {
|
|
3878
|
+
}
|
|
3879
|
+
const { isLauncherCorroboratedIdentity } = await import("../mcp-session-identity-T7H2EKFQ.js");
|
|
3880
|
+
const corroborated = isLauncherCorroboratedIdentity({
|
|
3881
|
+
agentId,
|
|
3882
|
+
registrySessions: bindRegistry,
|
|
3883
|
+
liveTmuxSessions: bindLive
|
|
3884
|
+
});
|
|
3885
|
+
const assessment = assessInitialBindIdentity({
|
|
3886
|
+
agentId,
|
|
3887
|
+
privileged: true,
|
|
3888
|
+
corroborated,
|
|
3889
|
+
enforce: shouldEnforceSessionIdentity()
|
|
3890
|
+
});
|
|
3891
|
+
if (assessment.flagged) {
|
|
3892
|
+
process.stderr.write(`[exed] SECURITY: ${assessment.reason}
|
|
3893
|
+
`);
|
|
3894
|
+
recordMcpHttpEvent({
|
|
3895
|
+
level: "warn",
|
|
3896
|
+
message: assessment.reject ? "initial_bind_identity_rejected" : "initial_bind_identity_uncorroborated",
|
|
3897
|
+
method: req.method,
|
|
3898
|
+
agentId,
|
|
3899
|
+
agentRole,
|
|
3900
|
+
runtime
|
|
3901
|
+
});
|
|
3902
|
+
}
|
|
3903
|
+
if (assessment.reject) {
|
|
3904
|
+
sendJsonRpcError2(
|
|
3905
|
+
res,
|
|
3906
|
+
403,
|
|
3907
|
+
`Refusing to bind privileged identity "${agentId}" to a new MCP session: the X-Agent-Id header claims a management role but no launcher-written session-registry entry corroborates it (bug 2138232d). Launch the agent through exe-os, or set EXE_ENFORCE_SESSION_IDENTITY=0 for warn-only.`,
|
|
3908
|
+
getJsonRpcId2(parsedBody),
|
|
3909
|
+
{ agentId, agentRole }
|
|
3910
|
+
);
|
|
3911
|
+
return;
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
} catch {
|
|
3665
3915
|
}
|
|
3666
3916
|
const initIsTransient = !clientProvidedSessionHint;
|
|
3667
3917
|
const initOwnerKey = mcpSessionOwnerKey2({ agentId, runtime, sessionHint, transient: initIsTransient });
|
|
@@ -3868,6 +4118,25 @@ async function startMcpHttpServer() {
|
|
|
3868
4118
|
effectiveSessionHint = stored.sessionHint;
|
|
3869
4119
|
}
|
|
3870
4120
|
}
|
|
4121
|
+
try {
|
|
4122
|
+
const { reconcileHintWithRegistryIdentity } = await import("../mcp-session-identity-T7H2EKFQ.js");
|
|
4123
|
+
const { listSessions: listRegistrySessions } = await import("./session-registry.js");
|
|
4124
|
+
const recon = reconcileHintWithRegistryIdentity({
|
|
4125
|
+
agentId,
|
|
4126
|
+
hint: effectiveSessionHint,
|
|
4127
|
+
clientProvided: clientProvidedSessionHint,
|
|
4128
|
+
registrySessions: listRegistrySessions(),
|
|
4129
|
+
liveTmuxSessions: await getTmuxSessionsAsync()
|
|
4130
|
+
});
|
|
4131
|
+
if (recon.message) process.stderr.write(`[daemon] ${recon.message}
|
|
4132
|
+
`);
|
|
4133
|
+
if (recon.corrected) {
|
|
4134
|
+
effectiveSessionHint = recon.sessionHint;
|
|
4135
|
+
const stored = activeRequestSessionId ? sessionDetails.get(activeRequestSessionId) : void 0;
|
|
4136
|
+
if (stored && recon.sessionHint) stored.sessionHint = recon.sessionHint;
|
|
4137
|
+
}
|
|
4138
|
+
} catch {
|
|
4139
|
+
}
|
|
3871
4140
|
try {
|
|
3872
4141
|
await runWithAgent({ agentId, agentRole, sessionHint: effectiveSessionHint, projectName: projectNameHeader || void 0 }, async () => {
|
|
3873
4142
|
if (wantsJsonOnly) {
|
|
@@ -3988,7 +4257,7 @@ async function startMcpHttpServer() {
|
|
|
3988
4257
|
`);
|
|
3989
4258
|
_boundMcpPort = MCP_HTTP_PORT;
|
|
3990
4259
|
writeDaemonReady({ pid: process.pid, port: MCP_HTTP_PORT });
|
|
3991
|
-
void import("../mcp-port-config-
|
|
4260
|
+
void import("../mcp-port-config-6HYY6J7K.js").then(({ persistMcpPortToConfig }) => persistMcpPortToConfig(String(MCP_HTTP_PORT))).catch(() => {
|
|
3992
4261
|
});
|
|
3993
4262
|
recordMcpHttpEvent({
|
|
3994
4263
|
level: "info",
|
|
@@ -4046,6 +4315,20 @@ async function ensureStoreForPolling() {
|
|
|
4046
4315
|
}
|
|
4047
4316
|
await initDatabase({ dbPath: config.dbPath, encryptionKey: masterKey.toString("hex") });
|
|
4048
4317
|
await ensureSchema();
|
|
4318
|
+
try {
|
|
4319
|
+
const { isLedgerEnabled } = await import("../notification-ledger-SZEPGJQ7.js");
|
|
4320
|
+
if (isLedgerEnabled()) {
|
|
4321
|
+
const { bumpBootGeneration } = await import("../boot-generation-BL2ISK4U.js");
|
|
4322
|
+
const { setDaemonReadyGeneration } = await import("../daemon-ready-signal-LPAZWQOV.js");
|
|
4323
|
+
const generation = await bumpBootGeneration();
|
|
4324
|
+
setDaemonReadyGeneration(generation);
|
|
4325
|
+
process.stderr.write(`[exed] notification ledger enabled \u2014 boot generation ${generation}
|
|
4326
|
+
`);
|
|
4327
|
+
}
|
|
4328
|
+
} catch (e) {
|
|
4329
|
+
process.stderr.write(`[exed] boot-generation bump failed (non-fatal): ${e instanceof Error ? e.message : String(e)}
|
|
4330
|
+
`);
|
|
4331
|
+
}
|
|
4049
4332
|
try {
|
|
4050
4333
|
const { spawnDbReadWorker } = await import("./db-read-worker-client.js");
|
|
4051
4334
|
spawnDbReadWorker(config.dbPath, masterKey.toString("hex"));
|
|
@@ -4065,13 +4348,13 @@ async function ensureStoreForPolling() {
|
|
|
4065
4348
|
}
|
|
4066
4349
|
}
|
|
4067
4350
|
async function startReviewPolling() {
|
|
4068
|
-
const polling = await import("../review-polling-
|
|
4351
|
+
const polling = await import("../review-polling-HXAFJZDA.js");
|
|
4069
4352
|
const state = {
|
|
4070
4353
|
lastIntercomSent: /* @__PURE__ */ new Map(),
|
|
4071
4354
|
lastNudgeSent: /* @__PURE__ */ new Map(),
|
|
4072
4355
|
intervalMs: REVIEW_POLL_INTERVAL_MS
|
|
4073
4356
|
};
|
|
4074
|
-
const { pollReviewNudge, createReviewNudgeRealDeps, loadNudgeState } = await import("../daemon-orchestration-
|
|
4357
|
+
const { pollReviewNudge, createReviewNudgeRealDeps, loadNudgeState } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
4075
4358
|
const nudgeState = loadNudgeState();
|
|
4076
4359
|
const tick = async () => traceDaemonTimer("review_polling", async () => {
|
|
4077
4360
|
fired("review_polling");
|
|
@@ -4109,16 +4392,17 @@ async function startReviewPolling() {
|
|
|
4109
4392
|
}
|
|
4110
4393
|
var SESSION_TTL_INTERVAL_MS = 5 * 60 * 1e3;
|
|
4111
4394
|
var SESSION_REGISTRY_MAINTENANCE_INTERVAL_MS = 5 * 60 * 1e3;
|
|
4395
|
+
var _wedgeObservations = /* @__PURE__ */ new Map();
|
|
4112
4396
|
function startSessionTTL() {
|
|
4113
4397
|
const tick = async () => traceDaemonTimer("session_ttl", async () => {
|
|
4114
4398
|
fired("session_ttl");
|
|
4115
|
-
if (!await ensureStoreForPolling()) return;
|
|
4116
|
-
if (inPostRestartDestructiveGrace("session_ttl")) return;
|
|
4117
4399
|
try {
|
|
4400
|
+
if (!await ensureStoreForPolling()) return;
|
|
4401
|
+
if (inPostRestartDestructiveGrace("session_ttl")) return;
|
|
4118
4402
|
const { getClient } = await import("./database.js");
|
|
4119
|
-
const { checkSessionTTL, createSessionTTLRealDeps } = await import("../daemon-orchestration-
|
|
4403
|
+
const { checkSessionTTL, createSessionTTLRealDeps } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
4120
4404
|
const deps = createSessionTTLRealDeps(getClient);
|
|
4121
|
-
const killed = await checkSessionTTL(deps);
|
|
4405
|
+
const killed = await checkSessionTTL(deps, _wedgeObservations);
|
|
4122
4406
|
if (killed.length > 0) acted("session_ttl");
|
|
4123
4407
|
} catch (err) {
|
|
4124
4408
|
process.stderr.write(`[exed] Session TTL error: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -4131,6 +4415,9 @@ function startSessionTTL() {
|
|
|
4131
4415
|
`);
|
|
4132
4416
|
}
|
|
4133
4417
|
var COO_RESTART_COOLDOWN_MS = 5 * 6e4;
|
|
4418
|
+
var _resolveNpmGlobalRoot = createMemoizedNpmGlobalRootResolver(
|
|
4419
|
+
(file, args, opts) => execFileAsync(file, args, opts)
|
|
4420
|
+
);
|
|
4134
4421
|
var _idleTickCounts = /* @__PURE__ */ new Map();
|
|
4135
4422
|
function startIdleKill() {
|
|
4136
4423
|
const tick = async () => traceDaemonTimer("idle_kill", async () => {
|
|
@@ -4165,7 +4452,7 @@ function startIdleKill() {
|
|
|
4165
4452
|
const cfg = await getCachedConfig();
|
|
4166
4453
|
if (!cfg) return;
|
|
4167
4454
|
const { getClient } = await import("./database.js");
|
|
4168
|
-
const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-
|
|
4455
|
+
const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
4169
4456
|
const { sessions: liveSessions, paneCache, aliveSessions } = await getSharedOrchestrationCaches();
|
|
4170
4457
|
const realDeps = createIdleKillRealDeps(
|
|
4171
4458
|
getClient,
|
|
@@ -4238,7 +4525,7 @@ function startConsolidation() {
|
|
|
4238
4525
|
`);
|
|
4239
4526
|
}
|
|
4240
4527
|
try {
|
|
4241
|
-
const { createBackupAsync, enforceRetention } = await import("../db-backup-
|
|
4528
|
+
const { createBackupAsync, enforceRetention } = await import("../db-backup-W2QFSYQC.js");
|
|
4242
4529
|
const p = await createBackupAsync("pre-consolidation");
|
|
4243
4530
|
if (p) enforceRetention("pre-consolidation");
|
|
4244
4531
|
} catch (e) {
|
|
@@ -4471,7 +4758,7 @@ function startSkillRefinement() {
|
|
|
4471
4758
|
if (!shouldRunHeavyJob("skill_refinement")) return;
|
|
4472
4759
|
try {
|
|
4473
4760
|
if (!await ensureStoreForPolling()) return;
|
|
4474
|
-
const { runSkillRefinement } = await import("../skill-refinement-
|
|
4761
|
+
const { runSkillRefinement } = await import("../skill-refinement-DVSYXBBP.js");
|
|
4475
4762
|
const result = await runSkillRefinement();
|
|
4476
4763
|
if (result.reviewed > 0) {
|
|
4477
4764
|
acted("skill_refinement");
|
|
@@ -4497,8 +4784,8 @@ function startStaleBranchSweep() {
|
|
|
4497
4784
|
const tick = async () => {
|
|
4498
4785
|
fired("stale_branch_sweep");
|
|
4499
4786
|
try {
|
|
4500
|
-
const { discoverRepoPaths } = await import("../worktree-sweep-
|
|
4501
|
-
const {
|
|
4787
|
+
const { discoverRepoPaths } = await import("../worktree-sweep-WTK3MTKH.js");
|
|
4788
|
+
const { scanUnmergedBranchesCached } = await import("../branch-hygiene-TZWK6QCF.js");
|
|
4502
4789
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4503
4790
|
for (const k of _staleBranchAlertedToday) {
|
|
4504
4791
|
if (!k.endsWith(today)) _staleBranchAlertedToday.delete(k);
|
|
@@ -4513,7 +4800,11 @@ function startStaleBranchSweep() {
|
|
|
4513
4800
|
await yieldToEventLoop();
|
|
4514
4801
|
let scan;
|
|
4515
4802
|
try {
|
|
4516
|
-
scan = await
|
|
4803
|
+
scan = await scanUnmergedBranchesCached(
|
|
4804
|
+
repo,
|
|
4805
|
+
{ staleHours: STALE_BRANCH_HOURS },
|
|
4806
|
+
{ forceRefresh: true }
|
|
4807
|
+
);
|
|
4517
4808
|
} catch {
|
|
4518
4809
|
continue;
|
|
4519
4810
|
}
|
|
@@ -4525,13 +4816,13 @@ function startStaleBranchSweep() {
|
|
|
4525
4816
|
if (!_storeInitialized) continue;
|
|
4526
4817
|
const stale = scan.branches.filter((b) => b.ageHours >= STALE_BRANCH_HOURS).slice(0, 5).map((b) => `${b.name} (+${b.ahead} commits, ${(b.ageHours / 24).toFixed(1)}d)`).join("; ");
|
|
4527
4818
|
try {
|
|
4528
|
-
const { writeNotification } = await import("../notifications-
|
|
4819
|
+
const { writeNotification } = await import("../notifications-4UT53CDG.js");
|
|
4529
4820
|
await writeNotification({
|
|
4530
4821
|
agentId: "exe",
|
|
4531
4822
|
agentRole: "system",
|
|
4532
4823
|
event: "error_spike",
|
|
4533
4824
|
project: repoName,
|
|
4534
|
-
summary: `${scan.staleCount} unmerged remote branch(es) in ${repoName} are >${STALE_BRANCH_HOURS}h old with unique work \u2014 check before starting new work to avoid redoing it. Oldest: ${stale}.
|
|
4825
|
+
summary: `${scan.staleCount} unmerged remote branch(es) in ${repoName} are >${STALE_BRANCH_HOURS}h old with unique work \u2014 check before starting new work to avoid redoing it. Oldest: ${stale}. List them with: git branch -r --no-merged origin/main`,
|
|
4535
4826
|
sessionScope: null
|
|
4536
4827
|
});
|
|
4537
4828
|
acted("stale_branch_sweep");
|
|
@@ -4982,7 +5273,7 @@ function startReflectionSweep() {
|
|
|
4982
5273
|
);
|
|
4983
5274
|
let runReflection;
|
|
4984
5275
|
try {
|
|
4985
|
-
({ runReflection } = await import("../memory-reflection-
|
|
5276
|
+
({ runReflection } = await import("../memory-reflection-WVNFBJAA.js"));
|
|
4986
5277
|
} catch (importErr) {
|
|
4987
5278
|
_reflectionImportFailed = true;
|
|
4988
5279
|
process.stderr.write(`[exed] Reflection module unavailable (stale chunk hash?) \u2014 disabled until daemon restart: ${importErr instanceof Error ? importErr.message : String(importErr)}
|
|
@@ -5023,7 +5314,7 @@ function startReflectionSweep() {
|
|
|
5023
5314
|
if (memories > 100 && cards < memories * 0.1) {
|
|
5024
5315
|
process.stderr.write(`[exed] Memory cards sparse (${cards} cards / ${memories} memories) \u2014 running backfill...
|
|
5025
5316
|
`);
|
|
5026
|
-
const { insertMemoryCardsForBatch } = await import("../memory-cards-
|
|
5317
|
+
const { insertMemoryCardsForBatch } = await import("../memory-cards-ZRDW7QBX.js");
|
|
5027
5318
|
const batchSize = 500;
|
|
5028
5319
|
let offset = 0;
|
|
5029
5320
|
let totalCards = 0;
|
|
@@ -5062,13 +5353,25 @@ function startReflectionSweep() {
|
|
|
5062
5353
|
process.stderr.write(`[exed] Reflection sweep started (every 6h)
|
|
5063
5354
|
`);
|
|
5064
5355
|
}
|
|
5065
|
-
var
|
|
5356
|
+
var DB_BACKUP_TARGET_WINDOW_MS = Number(process.env.EXE_DB_BACKUP_TARGET_WINDOW_MS) || 6 * 60 * 60 * 1e3;
|
|
5357
|
+
var DB_BACKUP_INTERVAL_MS = Math.min(60 * 60 * 1e3, DB_BACKUP_TARGET_WINDOW_MS);
|
|
5066
5358
|
function startDatabaseBackup() {
|
|
5067
5359
|
const tick = async () => {
|
|
5068
5360
|
fired("db_backup");
|
|
5069
|
-
if (!shouldRunHeavyJob("db_backup")) return;
|
|
5070
5361
|
try {
|
|
5071
|
-
const { createBackupAsync, enforceRetention, hasBackupToday } = await import("../db-backup-
|
|
5362
|
+
const { createBackupAsync, enforceRetention, hasBackupToday, hasRecentBackup } = await import("../db-backup-W2QFSYQC.js");
|
|
5363
|
+
if (!hasRecentBackup("guaranteed", DB_BACKUP_TARGET_WINDOW_MS)) {
|
|
5364
|
+
const guaranteedPath = await createBackupAsync("guaranteed");
|
|
5365
|
+
if (guaranteedPath) {
|
|
5366
|
+
acted("db_backup");
|
|
5367
|
+
const deleted = enforceRetention("guaranteed");
|
|
5368
|
+
process.stderr.write(
|
|
5369
|
+
`[exed] DB backup guaranteed: ${guaranteedPath.split("/").pop()} (target window ${Math.round(DB_BACKUP_TARGET_WINDOW_MS / 36e5)}h)${deleted > 0 ? ` (rotated ${deleted} old)` : ""}
|
|
5370
|
+
`
|
|
5371
|
+
);
|
|
5372
|
+
}
|
|
5373
|
+
}
|
|
5374
|
+
if (!shouldRunHeavyJob("db_backup_daily")) return;
|
|
5072
5375
|
if (hasBackupToday("daily")) return;
|
|
5073
5376
|
const backupPath = await createBackupAsync("daily");
|
|
5074
5377
|
if (backupPath) {
|
|
@@ -5078,6 +5381,22 @@ function startDatabaseBackup() {
|
|
|
5078
5381
|
`[exed] DB backup: ${backupPath.split("/").pop()}${deleted > 0 ? ` (rotated ${deleted} old)` : ""}
|
|
5079
5382
|
`
|
|
5080
5383
|
);
|
|
5384
|
+
try {
|
|
5385
|
+
const { maybeVerifyDailyBackup } = await import("../backup-verify-3Y2FHGZU.js");
|
|
5386
|
+
const verdict = await maybeVerifyDailyBackup(backupPath);
|
|
5387
|
+
if (verdict && !verdict.ok) {
|
|
5388
|
+
process.stderr.write(
|
|
5389
|
+
`[exed] DB backup VERIFY FAIL: ${verdict.backup} \u2014 ${verdict.reason}${verdict.detail ? `: ${verdict.detail}` : ""}
|
|
5390
|
+
`
|
|
5391
|
+
);
|
|
5392
|
+
} else if (verdict) {
|
|
5393
|
+
process.stderr.write(`[exed] DB backup verified OK (${verdict.source})
|
|
5394
|
+
`);
|
|
5395
|
+
}
|
|
5396
|
+
} catch (verr) {
|
|
5397
|
+
process.stderr.write(`[exed] DB backup verify skipped: ${verr instanceof Error ? verr.message : String(verr)}
|
|
5398
|
+
`);
|
|
5399
|
+
}
|
|
5081
5400
|
}
|
|
5082
5401
|
} catch (err) {
|
|
5083
5402
|
process.stderr.write(`[exed] DB backup error: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -5087,8 +5406,10 @@ function startDatabaseBackup() {
|
|
|
5087
5406
|
tick();
|
|
5088
5407
|
const timer = setInterval(() => void traceDaemonTimer("db_backup", tick), DB_BACKUP_INTERVAL_MS);
|
|
5089
5408
|
timer.unref();
|
|
5090
|
-
process.stderr.write(
|
|
5091
|
-
`);
|
|
5409
|
+
process.stderr.write(
|
|
5410
|
+
`[exed] Database backup started (guaranteed every \u2264${Math.round(DB_BACKUP_TARGET_WINDOW_MS / 36e5)}h; daily verify window retained)
|
|
5411
|
+
`
|
|
5412
|
+
);
|
|
5092
5413
|
}
|
|
5093
5414
|
var PURGE_INTERVAL_MS = 6 * 60 * 60 * 1e3;
|
|
5094
5415
|
function startSoftDeletePurge() {
|
|
@@ -5138,7 +5459,7 @@ function startSessionEventsRetention() {
|
|
|
5138
5459
|
if (!await ensureStoreForPolling()) return;
|
|
5139
5460
|
try {
|
|
5140
5461
|
const { getClient } = await import("./database.js");
|
|
5141
|
-
const { sweepExpiredSessionEvents, DEFAULT_SESSION_EVENTS_RETENTION_DAYS } = await import("../session-events-
|
|
5462
|
+
const { sweepExpiredSessionEvents, DEFAULT_SESSION_EVENTS_RETENTION_DAYS } = await import("../session-events-O3BV56ZX.js");
|
|
5142
5463
|
const days = SESSION_EVENTS_RETENTION_DAYS ?? DEFAULT_SESSION_EVENTS_RETENTION_DAYS;
|
|
5143
5464
|
const count = await sweepExpiredSessionEvents(getClient(), days);
|
|
5144
5465
|
if (count > 0) {
|
|
@@ -5169,11 +5490,15 @@ function startIntercomQueueDrain() {
|
|
|
5169
5490
|
const tick = async () => traceDaemonTimer("intercom_queue_drain", async () => {
|
|
5170
5491
|
fired("intercom_queue_drain");
|
|
5171
5492
|
try {
|
|
5172
|
-
const { drainQueueAsync, readQueue } = await import("../intercom-queue-
|
|
5493
|
+
const { drainQueueAsync, readQueue } = await import("../intercom-queue-ZFEQALR3.js");
|
|
5173
5494
|
const {
|
|
5174
5495
|
sendIntercomAsync: centralSendIntercomAsync,
|
|
5175
|
-
|
|
5176
|
-
|
|
5496
|
+
countScopedPendingReviews,
|
|
5497
|
+
countScopedOpenTasks,
|
|
5498
|
+
dispositionWedgedSessionTask,
|
|
5499
|
+
decideDrainSend,
|
|
5500
|
+
offlineIfEmpty,
|
|
5501
|
+
paneHasPendingInput
|
|
5177
5502
|
} = await import("./tmux-routing.js");
|
|
5178
5503
|
const { baseAgentName, getCoordinatorName } = await import("./employees.js");
|
|
5179
5504
|
const agentsWithEmptyInbox = /* @__PURE__ */ new Set();
|
|
@@ -5206,6 +5531,18 @@ function startIntercomQueueDrain() {
|
|
|
5206
5531
|
if (count !== null) pendingReviewCounts.set(target, count);
|
|
5207
5532
|
}
|
|
5208
5533
|
}
|
|
5534
|
+
const openTaskCounts = /* @__PURE__ */ new Map();
|
|
5535
|
+
{
|
|
5536
|
+
const queue = readQueue();
|
|
5537
|
+
const taskTargets = new Set(
|
|
5538
|
+
queue.filter((q) => q.intercomReason === "nudge" || q.intercomReason === "signal" || !q.intercomReason).map((q) => q.targetSession)
|
|
5539
|
+
);
|
|
5540
|
+
for (const target of taskTargets) {
|
|
5541
|
+
const agent = baseAgentName(target.split("-")[0] ?? target);
|
|
5542
|
+
const count = await countScopedOpenTasks(target, agent);
|
|
5543
|
+
if (count !== null) openTaskCounts.set(target, count);
|
|
5544
|
+
}
|
|
5545
|
+
}
|
|
5209
5546
|
const result = await drainQueueAsync(
|
|
5210
5547
|
// Bug ddbfc3f6: async busy check via the shared async pane cache —
|
|
5211
5548
|
// no sync execFileSync("tmux") per queue item on the event loop.
|
|
@@ -5217,24 +5554,52 @@ function startIntercomQueueDrain() {
|
|
|
5217
5554
|
try {
|
|
5218
5555
|
const agentRaw = session.split("-")[0] ?? session;
|
|
5219
5556
|
const agent = baseAgentName(agentRaw);
|
|
5220
|
-
const
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5557
|
+
const pane = await capturePaneAsync(session, 8);
|
|
5558
|
+
return await decideDrainSend(item, {
|
|
5559
|
+
pane,
|
|
5560
|
+
paneState: classifyPaneState(pane),
|
|
5561
|
+
hasPendingInput: paneHasPendingInput(pane),
|
|
5562
|
+
nudgeState: {
|
|
5563
|
+
hasUnreadMessages: !agentsWithEmptyInbox.has(agent),
|
|
5564
|
+
pendingReviewCount: pendingReviewCounts.get(session) ?? null,
|
|
5565
|
+
openTaskCount: openTaskCounts.get(session) ?? null,
|
|
5566
|
+
hasInProgressTask: false
|
|
5567
|
+
},
|
|
5568
|
+
deliver: (s, reason) => centralSendIntercomAsync(s, { reason }),
|
|
5569
|
+
disposition: dispositionWedgedSessionTask
|
|
5224
5570
|
});
|
|
5225
|
-
if (decision.action === "drop") {
|
|
5226
|
-
process.stderr.write(`[exe-daemon] dropping stale ${item.intercomReason ?? "nudge"} intercom for ${session} (${decision.reason})
|
|
5227
|
-
`);
|
|
5228
|
-
return true;
|
|
5229
|
-
}
|
|
5230
|
-
const outcome = await centralSendIntercomAsync(session, {
|
|
5231
|
-
reason: item.intercomReason ?? "nudge"
|
|
5232
|
-
});
|
|
5233
|
-
return outcome === "delivered" || outcome === "debounced" || outcome === "skipped_exe";
|
|
5234
5571
|
} catch (e) {
|
|
5235
5572
|
process.stderr.write("[exe-daemon] intercom send to " + session + ": " + (e instanceof Error ? e.message : String(e)) + "\n");
|
|
5236
5573
|
return false;
|
|
5237
5574
|
}
|
|
5575
|
+
},
|
|
5576
|
+
void 0,
|
|
5577
|
+
// notifyExpiry — use the module default (notifyExpiredIntercom)
|
|
5578
|
+
10,
|
|
5579
|
+
// Terminal disposition (bug e9c19ffe + e7880e0e): a nudge that has
|
|
5580
|
+
// exhausted its retry budget (or TTL-expired) against a wedged EMPLOYEE
|
|
5581
|
+
// session routes that session's in_progress task to blocked. Pure DB
|
|
5582
|
+
// write — never a keystroke, never a buffer clear — so a human
|
|
5583
|
+
// mid-typing can never be clobbered. Round 4: an empty/uncapturable pane
|
|
5584
|
+
// is OFFLINE (⇒ wedged), and only a CONFIRMED "dispositioned" removes the
|
|
5585
|
+
// item; "error" returns false so drainQueueAsync keeps it for retry.
|
|
5586
|
+
async (item) => {
|
|
5587
|
+
try {
|
|
5588
|
+
const pane = await capturePaneAsync(item.targetSession, 8);
|
|
5589
|
+
const state = offlineIfEmpty(pane, classifyPaneState(pane));
|
|
5590
|
+
const hasPendingInput = paneHasPendingInput(pane);
|
|
5591
|
+
const outcome = await dispositionWedgedSessionTask(
|
|
5592
|
+
item.targetSession,
|
|
5593
|
+
`Auto-blocked: intercom (${item.intercomReason ?? "nudge"}) undeliverable after retry budget exhausted \u2014 session wedged (state=${state}, pendingInput=${hasPendingInput}; ${item.reason}). Re-dispatch after clearing the pane.`,
|
|
5594
|
+
{ state, hasPendingInput }
|
|
5595
|
+
);
|
|
5596
|
+
if (outcome === "dispositioned") return "dispositioned";
|
|
5597
|
+
if (outcome === "error") return "error";
|
|
5598
|
+
return "declined";
|
|
5599
|
+
} catch (e) {
|
|
5600
|
+
process.stderr.write("[exe-daemon] intercom disposition for " + item.targetSession + ": " + (e instanceof Error ? e.message : String(e)) + "\n");
|
|
5601
|
+
return "error";
|
|
5602
|
+
}
|
|
5238
5603
|
}
|
|
5239
5604
|
);
|
|
5240
5605
|
if (result.drained > 0 || result.failed > 0) {
|
|
@@ -5253,12 +5618,50 @@ function startIntercomQueueDrain() {
|
|
|
5253
5618
|
process.stderr.write(`[exed] Intercom queue drain started (every ${QUEUE_DRAIN_INTERVAL_MS / 1e3}s)
|
|
5254
5619
|
`);
|
|
5255
5620
|
}
|
|
5621
|
+
function startLedgerDrain() {
|
|
5622
|
+
const tick = async () => traceDaemonTimer("ledger_drain", async () => {
|
|
5623
|
+
fired("ledger_drain");
|
|
5624
|
+
try {
|
|
5625
|
+
const { isLedgerEnabled, drainLedger } = await import("../notification-ledger-SZEPGJQ7.js");
|
|
5626
|
+
if (!isLedgerEnabled()) return;
|
|
5627
|
+
const result = await drainLedger({
|
|
5628
|
+
// Shadow "would-deliver": idle target = would-deliver, busy = retry.
|
|
5629
|
+
// No real send here — the legacy intercom path owns actual delivery.
|
|
5630
|
+
attemptDelivery: async (row) => {
|
|
5631
|
+
const session = row.targetSession;
|
|
5632
|
+
if (!session) return false;
|
|
5633
|
+
const state = classifyPaneState(await capturePaneAsync(session, 5));
|
|
5634
|
+
const busy = state === "thinking" || state === "tool";
|
|
5635
|
+
if (busy) return false;
|
|
5636
|
+
process.stderr.write(
|
|
5637
|
+
`[exed] ledger(shadow) WOULD deliver ${row.kind} \u2192 ${session} (id ${row.id}, retries ${row.retryCount})
|
|
5638
|
+
`
|
|
5639
|
+
);
|
|
5640
|
+
return true;
|
|
5641
|
+
}
|
|
5642
|
+
});
|
|
5643
|
+
if (result.delivered || result.retried || result.expired || result.escalated) {
|
|
5644
|
+
acted("ledger_drain");
|
|
5645
|
+
process.stderr.write(
|
|
5646
|
+
`[exed] Ledger(shadow): ${result.delivered} would-deliver, ${result.retried} retry, ${result.expired} expired, ${result.escalated} escalated
|
|
5647
|
+
`
|
|
5648
|
+
);
|
|
5649
|
+
}
|
|
5650
|
+
} catch (e) {
|
|
5651
|
+
process.stderr.write("[exe-daemon] ledger drain: " + (e instanceof Error ? e.message : String(e)) + "\n");
|
|
5652
|
+
}
|
|
5653
|
+
});
|
|
5654
|
+
const timer = setInterval(tick, QUEUE_DRAIN_INTERVAL_MS);
|
|
5655
|
+
timer.unref();
|
|
5656
|
+
process.stderr.write(`[exed] Notification ledger drain started (shadow, every ${QUEUE_DRAIN_INTERVAL_MS / 1e3}s)
|
|
5657
|
+
`);
|
|
5658
|
+
}
|
|
5256
5659
|
var ORPHAN_REAP_INTERVAL_MS = 5 * 60 * 1e3;
|
|
5257
5660
|
function startOrphanReaper() {
|
|
5258
5661
|
const tick = async () => traceDaemonTimer("orphan_reaper", async () => {
|
|
5259
5662
|
fired("orphan_reaper");
|
|
5260
5663
|
try {
|
|
5261
|
-
const { reapOrphanedMcpProcesses, createOrphanReaperRealDepsAsync } = await import("../daemon-orchestration-
|
|
5664
|
+
const { reapOrphanedMcpProcesses, createOrphanReaperRealDepsAsync } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
5262
5665
|
const deps = await createOrphanReaperRealDepsAsync();
|
|
5263
5666
|
const reaped = await reapOrphanedMcpProcesses(deps);
|
|
5264
5667
|
if (reaped.length > 0) acted("orphan_reaper");
|
|
@@ -5283,7 +5686,7 @@ function startZombieAgentReaper() {
|
|
|
5283
5686
|
const tick = async () => traceDaemonTimer("zombie_agent_reaper", async () => {
|
|
5284
5687
|
fired("zombie_agent_reaper");
|
|
5285
5688
|
try {
|
|
5286
|
-
const { reapZombieAgentProcesses, createZombieAgentReaperRealDepsAsync } = await import("../daemon-orchestration-
|
|
5689
|
+
const { reapZombieAgentProcesses, createZombieAgentReaperRealDepsAsync } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
5287
5690
|
const deps = await createZombieAgentReaperRealDepsAsync();
|
|
5288
5691
|
const reaped = reapZombieAgentProcesses(deps);
|
|
5289
5692
|
if (reaped.length > 0) acted("zombie_agent_reaper");
|
|
@@ -5307,7 +5710,7 @@ async function startDaemonMemoryPressureWatchdog() {
|
|
|
5307
5710
|
try {
|
|
5308
5711
|
const cfg = await getCachedConfig();
|
|
5309
5712
|
if (!cfg) return;
|
|
5310
|
-
const { startMemoryPressureWatchdog: startWatchdog, MEMORY_PRESSURE_WATCHDOG_DEFAULTS } = await import("../memory-pressure-watchdog-
|
|
5713
|
+
const { startMemoryPressureWatchdog: startWatchdog, MEMORY_PRESSURE_WATCHDOG_DEFAULTS } = await import("../memory-pressure-watchdog-HN5X7AVN.js");
|
|
5311
5714
|
const watchdogCfg = {
|
|
5312
5715
|
...MEMORY_PRESSURE_WATCHDOG_DEFAULTS,
|
|
5313
5716
|
...cfg.memoryPressureWatchdog ?? {}
|
|
@@ -5338,7 +5741,7 @@ function startWorktreeReaper() {
|
|
|
5338
5741
|
const tick = async () => traceDaemonTimer("worktree_reaper", async () => {
|
|
5339
5742
|
fired("worktree_reaper");
|
|
5340
5743
|
try {
|
|
5341
|
-
const { reapOrphanedWorktrees, createWorktreeReaperRealDeps } = await import("../daemon-orchestration-
|
|
5744
|
+
const { reapOrphanedWorktrees, createWorktreeReaperRealDeps } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
5342
5745
|
const deps = await createWorktreeReaperRealDeps();
|
|
5343
5746
|
const result = await reapOrphanedWorktrees(deps);
|
|
5344
5747
|
if (result.pruned.length > 0) {
|
|
@@ -5378,9 +5781,9 @@ function startWorktreeReaper() {
|
|
|
5378
5781
|
}
|
|
5379
5782
|
continue;
|
|
5380
5783
|
}
|
|
5381
|
-
const { cleanupAgentWorktree } = await import("../worktree-sweep-
|
|
5382
|
-
const {
|
|
5383
|
-
const repoRoot =
|
|
5784
|
+
const { cleanupAgentWorktree } = await import("../worktree-sweep-WTK3MTKH.js");
|
|
5785
|
+
const { getMainRepoRootAsync } = await import("../worktree-LL62PLQB.js");
|
|
5786
|
+
const repoRoot = await getMainRepoRootAsync(signal.worktreePath);
|
|
5384
5787
|
if (repoRoot && signal.agentId) {
|
|
5385
5788
|
const notes = await cleanupAgentWorktree(repoRoot, signal.agentId);
|
|
5386
5789
|
if (notes) {
|
|
@@ -5412,7 +5815,7 @@ function startAutoWake() {
|
|
|
5412
5815
|
if (!await ensureStoreForPolling()) return;
|
|
5413
5816
|
try {
|
|
5414
5817
|
const { getClient } = await import("./database.js");
|
|
5415
|
-
const { pollOrphanedTasks, createAutoWakeRealDeps } = await import("../daemon-orchestration-
|
|
5818
|
+
const { pollOrphanedTasks, createAutoWakeRealDeps } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
5416
5819
|
const deps = createAutoWakeRealDeps(getClient, process.cwd(), getTmuxSessionsAsync);
|
|
5417
5820
|
const woken = await pollOrphanedTasks(deps);
|
|
5418
5821
|
if (woken.length > 0) acted("auto_wake");
|
|
@@ -5424,7 +5827,7 @@ function startAutoWake() {
|
|
|
5424
5827
|
const signalBase = path3.join(os2.homedir(), ".exe-os", "task-signals");
|
|
5425
5828
|
if (existsSync4(signalBase)) {
|
|
5426
5829
|
const { readdirSync: readdirSync2, statSync: statSyncFs } = await import("fs");
|
|
5427
|
-
const { sendIntercomAsync } = await import("./tmux-routing.js");
|
|
5830
|
+
const { sendIntercomAsync, extractRootExe } = await import("./tmux-routing.js");
|
|
5428
5831
|
const sessionCache = path3.join(os2.homedir(), ".exe-os", "session-cache");
|
|
5429
5832
|
const sessions = await getTmuxSessionsAsync();
|
|
5430
5833
|
const signalDirs = [];
|
|
@@ -5463,7 +5866,7 @@ function startAutoWake() {
|
|
|
5463
5866
|
if (age > 60 * 60 * 1e3) {
|
|
5464
5867
|
try {
|
|
5465
5868
|
unlinkSync2(signalPath);
|
|
5466
|
-
void import("../orchestration-events-
|
|
5869
|
+
void import("../orchestration-events-WV4NWKZH.js").then(({ recordOrchestrationEventBestEffort: recordOE }) => {
|
|
5467
5870
|
recordOE({ eventType: "signal.stale", source: "exe-daemon.autoWake", severity: "warn", payload: { file, ageMinutes: Math.round(age / 6e4) } });
|
|
5468
5871
|
}).catch(() => {
|
|
5469
5872
|
});
|
|
@@ -5492,9 +5895,17 @@ function startAutoWake() {
|
|
|
5492
5895
|
`
|
|
5493
5896
|
);
|
|
5494
5897
|
} else {
|
|
5495
|
-
|
|
5496
|
-
|
|
5898
|
+
const nudgeScope = scope ?? extractRootExe(match) ?? null;
|
|
5899
|
+
const result = await sendIntercomAsync(match, { force: true, reason: "signal", callerSessionScope: nudgeScope });
|
|
5900
|
+
if (result === "failed") {
|
|
5901
|
+
process.stderr.write(
|
|
5902
|
+
`[exed] Signal-nudge: delivery FAILED to ${match} (signal age ${Math.round(age / 1e3)}s, scope=${nudgeScope ?? "none"}) \u2014 signal kept; will retry next tick
|
|
5903
|
+
`
|
|
5904
|
+
);
|
|
5905
|
+
} else {
|
|
5906
|
+
process.stderr.write(`[exed] Signal-nudge: ${result} intercom to ${match} (signal age ${Math.round(age / 1e3)}s)
|
|
5497
5907
|
`);
|
|
5908
|
+
}
|
|
5498
5909
|
}
|
|
5499
5910
|
}
|
|
5500
5911
|
}
|
|
@@ -5523,7 +5934,7 @@ function startWalCheckpoint() {
|
|
|
5523
5934
|
try {
|
|
5524
5935
|
const { getClient, runWalCheckpoint } = await import("./database.js");
|
|
5525
5936
|
const client = getClient();
|
|
5526
|
-
const { findActiveDb } = await import("../db-backup-
|
|
5937
|
+
const { findActiveDb } = await import("../db-backup-W2QFSYQC.js");
|
|
5527
5938
|
const dbPath = findActiveDb();
|
|
5528
5939
|
const started = Date.now();
|
|
5529
5940
|
const result = await runWalCheckpoint(client, dbPath, true);
|
|
@@ -5601,7 +6012,7 @@ function startStuckTaskRelease() {
|
|
|
5601
6012
|
createStuckTaskRealDeps,
|
|
5602
6013
|
escalateStuckBlockedTasks,
|
|
5603
6014
|
createStuckBlockedRealDeps
|
|
5604
|
-
} = await import("../daemon-orchestration-
|
|
6015
|
+
} = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
5605
6016
|
const deps = createStuckTaskRealDeps(getClient);
|
|
5606
6017
|
const released = await releaseStuckTasks(deps);
|
|
5607
6018
|
if (released.length > 0) {
|
|
@@ -5796,12 +6207,12 @@ function startTaskEnforcementScanner() {
|
|
|
5796
6207
|
const tick = async () => traceDaemonTimer("task_enforcement", async () => {
|
|
5797
6208
|
fired("task_enforcement");
|
|
5798
6209
|
try {
|
|
5799
|
-
const { runTaskEnforcementTick } = await import("../task-enforcement-
|
|
6210
|
+
const { runTaskEnforcementTick } = await import("../task-enforcement-IPIZX2MM.js");
|
|
5800
6211
|
const { getTransport } = await import("./transport.js");
|
|
5801
6212
|
const { loadAgentConfig } = await import("./agent-config.js");
|
|
5802
6213
|
const { getClient } = await import("./database.js");
|
|
5803
6214
|
const { loadEmployeesSync } = await import("./employees.js");
|
|
5804
|
-
const { sessionScopeFilter } = await import("../task-scope-
|
|
6215
|
+
const { sessionScopeFilter } = await import("../task-scope-FOIW25HR.js");
|
|
5805
6216
|
const transport = getTransport();
|
|
5806
6217
|
const { sessions: allSessions, paneCache, aliveSessions } = await getSharedOrchestrationCaches();
|
|
5807
6218
|
await yieldToEventLoop();
|
|
@@ -5812,10 +6223,10 @@ function startTaskEnforcementScanner() {
|
|
|
5812
6223
|
sendKeysLiteral: transport.sendKeysLiteral?.bind(transport),
|
|
5813
6224
|
isAlive: (session) => aliveSessions.has(session)
|
|
5814
6225
|
};
|
|
5815
|
-
const { checkAutoWakeGates } = await import("../daemon-orchestration-
|
|
5816
|
-
const { ensureEmployeeAsync, employeeSessionName } = await import("./tmux-routing.js");
|
|
6226
|
+
const { checkAutoWakeGates } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
6227
|
+
const { ensureEmployeeAsync, employeeSessionName, sendIntercomAsync } = await import("./tmux-routing.js");
|
|
5817
6228
|
const { shouldAutoInstance } = await import("./employees.js");
|
|
5818
|
-
const { recordOrchestrationEventBestEffort } = await import("../orchestration-events-
|
|
6229
|
+
const { recordOrchestrationEventBestEffort } = await import("../orchestration-events-WV4NWKZH.js");
|
|
5819
6230
|
const projectDir = process.cwd();
|
|
5820
6231
|
await runTaskEnforcementTick({
|
|
5821
6232
|
transport: enforcementTransport,
|
|
@@ -5840,6 +6251,16 @@ function startTaskEnforcementScanner() {
|
|
|
5840
6251
|
`));
|
|
5841
6252
|
return { status: "intercom_unprocessed", sessionName: employeeSessionName(reviewerName, sessionScope) };
|
|
5842
6253
|
},
|
|
6254
|
+
// Bug 018aaf31: wake a LIVE-but-idle reviewer/coordinator that owns a
|
|
6255
|
+
// needs_review item. Same intercom funnel as the worker-nudge; reason
|
|
6256
|
+
// "completion" renders "An employee completed work — review it". The
|
|
6257
|
+
// input-buffer/busy/idle/debounce guards inside sendIntercom decide
|
|
6258
|
+
// whether to type, queue, or defer — so this never splices into a founder
|
|
6259
|
+
// keystroke and never piles onto a busy reviewer.
|
|
6260
|
+
reviewerNudge: (reviewerSession, sessionScope) => {
|
|
6261
|
+
void sendIntercomAsync(reviewerSession, { callerSessionScope: sessionScope, reason: "completion" }).catch((err) => process.stderr.write(`[exed] Reviewer nudge async failed for ${reviewerSession}: ${err instanceof Error ? err.message : String(err)}
|
|
6262
|
+
`));
|
|
6263
|
+
},
|
|
5843
6264
|
zombieWorkerRecover: async (session, agentName, sessionScope, reason) => {
|
|
5844
6265
|
const gateReason = checkAutoWakeGates(`mcp-zombie::${agentName}::${sessionScope || session}`, Date.now());
|
|
5845
6266
|
if (gateReason) {
|
|
@@ -6097,7 +6518,7 @@ function startBackgroundJobGuardrails() {
|
|
|
6097
6518
|
const tick = async () => traceDaemonTimer("background_job_guardrails", async () => {
|
|
6098
6519
|
fired("background_job_guardrails");
|
|
6099
6520
|
try {
|
|
6100
|
-
const { enforceBackgroundJobGuardrailsAsync } = await import("../background-jobs-
|
|
6521
|
+
const { enforceBackgroundJobGuardrailsAsync } = await import("../background-jobs-EXR5RVGG.js");
|
|
6101
6522
|
const actions = await enforceBackgroundJobGuardrailsAsync();
|
|
6102
6523
|
if (actions.length > 0) {
|
|
6103
6524
|
acted("background_job_guardrails");
|
|
@@ -6130,11 +6551,14 @@ function handleSignalShutdown() {
|
|
|
6130
6551
|
...signalAttribution
|
|
6131
6552
|
});
|
|
6132
6553
|
logShutdown(restartIntent ? "restart shutdown" : "graceful shutdown", "SIGTERM/SIGINT", signalAttribution);
|
|
6133
|
-
void shutdown(restartIntent ? 75 : 0);
|
|
6554
|
+
void shutdown(restartIntent ? 75 : 0, restartIntent ? reason ?? "restart-intent" : null);
|
|
6134
6555
|
}
|
|
6135
6556
|
process.on("SIGINT", handleSignalShutdown);
|
|
6136
6557
|
process.on("SIGTERM", handleSignalShutdown);
|
|
6137
6558
|
process.on("exit", (code) => {
|
|
6559
|
+
if (_bootPhase !== "ready" && code !== 0) {
|
|
6560
|
+
recordExitBreadcrumb("boot-abort", code, `boot_abort:${_bootPhase}`);
|
|
6561
|
+
}
|
|
6138
6562
|
if (_bootPhase === "ready") return;
|
|
6139
6563
|
try {
|
|
6140
6564
|
logDaemonHealth({
|
|
@@ -6252,7 +6676,7 @@ function startBugAutoFix() {
|
|
|
6252
6676
|
for (const exeSession of exeSessions) {
|
|
6253
6677
|
const ctoSession = `${ctoName}-${exeSession}`;
|
|
6254
6678
|
if (sessions.includes(ctoSession)) {
|
|
6255
|
-
await sendIntercomAsync(ctoSession);
|
|
6679
|
+
await sendIntercomAsync(ctoSession, { callerSessionScope: exeSession });
|
|
6256
6680
|
break;
|
|
6257
6681
|
}
|
|
6258
6682
|
}
|
|
@@ -6428,9 +6852,9 @@ function startAutoUpdateCheck() {
|
|
|
6428
6852
|
const effectiveChannel = updateChannel ?? "stable";
|
|
6429
6853
|
if (effectiveChannel === "pinned") return;
|
|
6430
6854
|
if (!autoInstall && !config.autoUpdate.checkOnBoot) return;
|
|
6431
|
-
const {
|
|
6855
|
+
const { checkForUpdateAsync, channelToInstallTag } = await import("../update-check-3FHAWIG2.js");
|
|
6432
6856
|
const packageRoot = new URL("../..", import.meta.url).pathname;
|
|
6433
|
-
const result =
|
|
6857
|
+
const result = await checkForUpdateAsync(packageRoot, effectiveChannel);
|
|
6434
6858
|
if (!result.updateAvailable) return;
|
|
6435
6859
|
acted("auto_update_check");
|
|
6436
6860
|
const channelLabel = effectiveChannel === "canary" ? " (canary)" : "";
|
|
@@ -6531,7 +6955,7 @@ if (process.platform === "darwin") {
|
|
|
6531
6955
|
logBoot({ socketPath: SOCKET_PATH, pidPath: PID_PATH });
|
|
6532
6956
|
void (async () => {
|
|
6533
6957
|
try {
|
|
6534
|
-
const { cleanupCrashDebris } = await import("../db-backup-
|
|
6958
|
+
const { cleanupCrashDebris } = await import("../db-backup-W2QFSYQC.js");
|
|
6535
6959
|
const removed = cleanupCrashDebris();
|
|
6536
6960
|
if (removed > 0) {
|
|
6537
6961
|
process.stderr.write(`[exed] Startup cleanup: pruned ${removed} crash-debris file(s) (backups/quarantine).
|
|
@@ -6677,9 +7101,7 @@ function startEventLoopLagDetector() {
|
|
|
6677
7101
|
const SELF_INFLICTED_ROLLING_WINDOW_MS = parseFloat(process.env.EXE_SELF_INFLICTED_ROLLING_WINDOW_MS ?? "") || 3e5;
|
|
6678
7102
|
const LAG_WARN_MS = 3e3;
|
|
6679
7103
|
const LAG_CRITICAL_MS = 1e4;
|
|
6680
|
-
const SELF_HEAL_SINGLE_MS
|
|
6681
|
-
const SELF_HEAL_CONSECUTIVE = parseInt(process.env.EXE_SELF_HEAL_CONSECUTIVE ?? "") || 3;
|
|
6682
|
-
const SELF_HEAL_THRESHOLD_MS = parseFloat(process.env.EXE_SELF_HEAL_THRESHOLD_MS ?? "") || 3e4;
|
|
7104
|
+
const { singleMs: SELF_HEAL_SINGLE_MS, consecutive: SELF_HEAL_CONSECUTIVE, thresholdMs: SELF_HEAL_THRESHOLD_MS } = resolveSelfHealThresholds();
|
|
6683
7105
|
let consecutiveSevereBlocks = 0;
|
|
6684
7106
|
let selfInflictedWindow = [];
|
|
6685
7107
|
touchEventLoopHeartbeat();
|
|
@@ -6707,7 +7129,7 @@ function startEventLoopLagDetector() {
|
|
|
6707
7129
|
const msg = `[exed] EVENT LOOP BLOCKED ${(lag / 1e3).toFixed(1)}s \u2014 MCP UNRESPONSIVE. Sessions will die.`;
|
|
6708
7130
|
process.stderr.write(msg + "\n");
|
|
6709
7131
|
logDaemonHealth({ event: "event_loop_blocked", pid: process.pid, message: msg, data: { lagMs: lag } });
|
|
6710
|
-
void import("../orchestration-events-
|
|
7132
|
+
void import("../orchestration-events-WV4NWKZH.js").then(({ recordOrchestrationEventBestEffort: recordOE }) => {
|
|
6711
7133
|
recordOE({ eventType: "daemon.event_loop_blocked", source: "exe-daemon.lagDetector", severity: "error", durationMs: lag });
|
|
6712
7134
|
}).catch(() => {
|
|
6713
7135
|
});
|
|
@@ -6730,7 +7152,7 @@ function startEventLoopLagDetector() {
|
|
|
6730
7152
|
}
|
|
6731
7153
|
const load1m = os2.loadavg()[0] ?? 0;
|
|
6732
7154
|
const cpuCount = os2.cpus().length || 1;
|
|
6733
|
-
const starvationRatio =
|
|
7155
|
+
const starvationRatio = resolveSelfHealThresholds().starvationRatio;
|
|
6734
7156
|
const catchUpActive = inBootCatchUpGrace();
|
|
6735
7157
|
const decision = decideDaemonSelfHeal({
|
|
6736
7158
|
lagMs: lag,
|
|
@@ -6808,7 +7230,7 @@ function startEventLoopLagDetector() {
|
|
|
6808
7230
|
_lastSelfHealShutdownAtMs = Date.now();
|
|
6809
7231
|
process.stderr.write(healMsg + "\n");
|
|
6810
7232
|
logDaemonHealth({ event: "self_heal_restart", pid: process.pid, message: healMsg, data: { lagMs: lag, reason: "single_block" } });
|
|
6811
|
-
|
|
7233
|
+
dispatchSelfHealRestart(lag, "single_block", SELF_HEAL_ACTION_DEPS);
|
|
6812
7234
|
return;
|
|
6813
7235
|
}
|
|
6814
7236
|
if (decision.restart && decision.reason === "consecutive_blocks") {
|
|
@@ -6822,7 +7244,7 @@ function startEventLoopLagDetector() {
|
|
|
6822
7244
|
_lastSelfHealShutdownAtMs = Date.now();
|
|
6823
7245
|
process.stderr.write(healMsg + "\n");
|
|
6824
7246
|
logDaemonHealth({ event: "self_heal_restart", pid: process.pid, message: healMsg, data: { lagMs: lag, reason: "consecutive_blocks", count: consecutiveSevereBlocks } });
|
|
6825
|
-
|
|
7247
|
+
dispatchSelfHealRestart(lag, "consecutive_blocks", SELF_HEAL_ACTION_DEPS);
|
|
6826
7248
|
return;
|
|
6827
7249
|
}
|
|
6828
7250
|
} else if (lag > LAG_WARN_MS) {
|
|
@@ -6889,7 +7311,7 @@ function startTaskFileResync() {
|
|
|
6889
7311
|
});
|
|
6890
7312
|
if (Number(res.rowsAffected ?? 0) > 0) {
|
|
6891
7313
|
synced++;
|
|
6892
|
-
void import("../orchestration-events-
|
|
7314
|
+
void import("../orchestration-events-WV4NWKZH.js").then(({ recordOrchestrationEventBestEffort: recordOE }) => {
|
|
6893
7315
|
recordOE({
|
|
6894
7316
|
eventType: "task_file.resynced",
|
|
6895
7317
|
source: "exe-daemon.taskFileResync",
|
|
@@ -6926,7 +7348,7 @@ function startTaskGroupBarriers() {
|
|
|
6926
7348
|
fired("task_group_barriers");
|
|
6927
7349
|
if (!await ensureStoreForPolling()) return;
|
|
6928
7350
|
try {
|
|
6929
|
-
const { pollTaskGroupBarriers } = await import("../daemon-orchestration-
|
|
7351
|
+
const { pollTaskGroupBarriers } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
6930
7352
|
const firedCount = await pollTaskGroupBarriers();
|
|
6931
7353
|
if (firedCount > 0) {
|
|
6932
7354
|
acted("task_group_barriers");
|
|
@@ -6948,7 +7370,7 @@ function startCheckpointGc() {
|
|
|
6948
7370
|
fired("checkpoint_gc");
|
|
6949
7371
|
if (!await ensureStoreForPolling()) return;
|
|
6950
7372
|
try {
|
|
6951
|
-
const { gcStaleCheckpoints } = await import("../daemon-orchestration-
|
|
7373
|
+
const { gcStaleCheckpoints } = await import("../daemon-orchestration-FX4XZDR5.js");
|
|
6952
7374
|
const cleared = await gcStaleCheckpoints();
|
|
6953
7375
|
if (cleared > 0) {
|
|
6954
7376
|
acted("checkpoint_gc");
|
|
@@ -6979,7 +7401,7 @@ function startDaemonHeartbeat() {
|
|
|
6979
7401
|
function startDispatchAckCleanup() {
|
|
6980
7402
|
setInterval(async () => {
|
|
6981
7403
|
try {
|
|
6982
|
-
const { cleanStaleDispatchAcks } = await import("../dispatch-ack-
|
|
7404
|
+
const { cleanStaleDispatchAcks } = await import("../dispatch-ack-VYH3ONSS.js");
|
|
6983
7405
|
cleanStaleDispatchAcks();
|
|
6984
7406
|
} catch {
|
|
6985
7407
|
}
|
|
@@ -6988,14 +7410,14 @@ function startDispatchAckCleanup() {
|
|
|
6988
7410
|
function startProjectionWorkerDeferred() {
|
|
6989
7411
|
setTimeout(async () => {
|
|
6990
7412
|
try {
|
|
6991
|
-
const { startProjectionWorker } = await import("../projection-worker-
|
|
7413
|
+
const { startProjectionWorker } = await import("../projection-worker-FZ7YSN3G.js");
|
|
6992
7414
|
startProjectionWorker();
|
|
6993
7415
|
} catch {
|
|
6994
7416
|
}
|
|
6995
7417
|
}, 2e4);
|
|
6996
7418
|
}
|
|
6997
7419
|
async function startToolTelemetry() {
|
|
6998
|
-
const { startToolTelemetryFlush } = await import("../tool-telemetry-
|
|
7420
|
+
const { startToolTelemetryFlush } = await import("../tool-telemetry-KBXSBDTK.js");
|
|
6999
7421
|
startToolTelemetryFlush();
|
|
7000
7422
|
process.stderr.write("[exed] Tool telemetry started (flush every 5m)\n");
|
|
7001
7423
|
}
|
|
@@ -7026,6 +7448,7 @@ function startLocalFirstTimers() {
|
|
|
7026
7448
|
setTimeout(() => void retryPendingMessages(), 15e3);
|
|
7027
7449
|
void drainIngestOutbox();
|
|
7028
7450
|
startIntercomQueueDrain();
|
|
7451
|
+
startLedgerDrain();
|
|
7029
7452
|
startReviewPolling();
|
|
7030
7453
|
startSessionTTL();
|
|
7031
7454
|
startTaskEnforcementScanner();
|
|
@@ -7160,7 +7583,7 @@ function startLocalFirstTimers() {
|
|
|
7160
7583
|
fired("orphan_task_cleanup");
|
|
7161
7584
|
try {
|
|
7162
7585
|
if (!await ensureStoreForPolling()) return;
|
|
7163
|
-
const { cleanOrphanedTaskFiles } = await import("../tasks-crud-
|
|
7586
|
+
const { cleanOrphanedTaskFiles } = await import("../tasks-crud-HBDKE6C5.js");
|
|
7164
7587
|
const count = await cleanOrphanedTaskFiles();
|
|
7165
7588
|
if (count > 0) {
|
|
7166
7589
|
acted("orphan_task_cleanup");
|
|
@@ -7176,7 +7599,7 @@ function startLocalFirstTimers() {
|
|
|
7176
7599
|
fired("task_file_consistency");
|
|
7177
7600
|
try {
|
|
7178
7601
|
if (!await ensureStoreForPolling()) return;
|
|
7179
|
-
const { checkTaskFileConsistency } = await import("../tasks-crud-
|
|
7602
|
+
const { checkTaskFileConsistency } = await import("../tasks-crud-HBDKE6C5.js");
|
|
7180
7603
|
const mismatches = await checkTaskFileConsistency();
|
|
7181
7604
|
if (mismatches > 0) {
|
|
7182
7605
|
acted("task_file_consistency");
|
|
@@ -7195,7 +7618,7 @@ function startLocalFirstTimers() {
|
|
|
7195
7618
|
const TELEMETRY_DAILY_MS = 24 * 60 * 60 * 1e3;
|
|
7196
7619
|
const telemetryDaily = async () => {
|
|
7197
7620
|
try {
|
|
7198
|
-
const { sendTelemetry, isTelemetryEnabled } = await import("../telemetry-upload-
|
|
7621
|
+
const { sendTelemetry, isTelemetryEnabled } = await import("../telemetry-upload-ZOXHRWR5.js");
|
|
7199
7622
|
if (!isTelemetryEnabled()) return;
|
|
7200
7623
|
const { upstream } = await sendTelemetry(24);
|
|
7201
7624
|
if (upstream.startsWith("sent")) {
|
|
@@ -7307,7 +7730,76 @@ function startLocalFirstTimers() {
|
|
|
7307
7730
|
}
|
|
7308
7731
|
}, 3e4);
|
|
7309
7732
|
}
|
|
7733
|
+
async function enterDegradedBreakerMode(crashCount) {
|
|
7734
|
+
const requestedHost = process.env.EXE_MCP_HOST || "127.0.0.1";
|
|
7735
|
+
const isRemote = !["127.0.0.1", "::1", "localhost"].includes(requestedHost);
|
|
7736
|
+
const allowRemote = /^(1|true|yes|on)$/i.test(process.env.EXE_MCP_ALLOW_REMOTE ?? "");
|
|
7737
|
+
const host = isRemote && !allowRemote ? "127.0.0.1" : requestedHost;
|
|
7738
|
+
let port = 48739;
|
|
7739
|
+
try {
|
|
7740
|
+
port = await resolveAndClaimPort();
|
|
7741
|
+
} catch {
|
|
7742
|
+
}
|
|
7743
|
+
const degradedBody = () => JSON.stringify({
|
|
7744
|
+
jsonrpc: "2.0",
|
|
7745
|
+
error: {
|
|
7746
|
+
code: -32002,
|
|
7747
|
+
message: `exe-os daemon is DEGRADED \u2014 restart circuit breaker OPEN after ${crashCount} crash restarts (bug 2fee6110). Heavy work is suspended to protect system memory. Recover: 'exe-os daemon reset-breaker' then relaunch. Details: 'exe-os daemon status'.`
|
|
7748
|
+
},
|
|
7749
|
+
id: null
|
|
7750
|
+
});
|
|
7751
|
+
const srv = createHttpServer((req, res) => {
|
|
7752
|
+
try {
|
|
7753
|
+
res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1");
|
|
7754
|
+
const p = (req.url || "/").split("?")[0];
|
|
7755
|
+
if (req.method === "GET" && p === "/health") {
|
|
7756
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
7757
|
+
res.end(JSON.stringify({
|
|
7758
|
+
status: "degraded",
|
|
7759
|
+
reason: "restart_circuit_breaker_tripped",
|
|
7760
|
+
crashRestartsInWindow: crashCount,
|
|
7761
|
+
version: PACKAGE_VERSION,
|
|
7762
|
+
alert: readBreakerAlert() ?? void 0,
|
|
7763
|
+
recovery: "exe-os daemon reset-breaker"
|
|
7764
|
+
}));
|
|
7765
|
+
return;
|
|
7766
|
+
}
|
|
7767
|
+
res.writeHead(503, { "Content-Type": "application/json", "Retry-After": "300" });
|
|
7768
|
+
res.end(degradedBody());
|
|
7769
|
+
} catch {
|
|
7770
|
+
}
|
|
7771
|
+
});
|
|
7772
|
+
await new Promise((resolve) => {
|
|
7773
|
+
srv.once("error", (err) => {
|
|
7774
|
+
process.stderr.write(`[exed] Degraded health server bind failed (${err.code || err.message}) \u2014 staying alive without it.
|
|
7775
|
+
`);
|
|
7776
|
+
resolve();
|
|
7777
|
+
});
|
|
7778
|
+
srv.listen(port, host, () => {
|
|
7779
|
+
process.stderr.write(`[exed] DEGRADED health server on ${host}:${port} (breaker tripped \u2014 503 + /health only).
|
|
7780
|
+
`);
|
|
7781
|
+
resolve();
|
|
7782
|
+
});
|
|
7783
|
+
});
|
|
7784
|
+
setInterval(() => {
|
|
7785
|
+
process.stderr.write(
|
|
7786
|
+
`[exed] DEGRADED (breaker open, ${crashCount} crashes). No DB/backups/timers. Recover: 'exe-os daemon reset-breaker'. Alert: ${restartBreakerAlertPath()}
|
|
7787
|
+
`
|
|
7788
|
+
);
|
|
7789
|
+
}, 5 * 60 * 1e3);
|
|
7790
|
+
}
|
|
7310
7791
|
try {
|
|
7792
|
+
const breaker = recordDaemonRestart();
|
|
7793
|
+
process.stderr.write(
|
|
7794
|
+
`[exed] Boot classified as ${breaker.bootClass} (${breaker.reasonLabel}); crashes=${breaker.crashInWindow}/${5}, restarts=${breaker.restartsInWindow} in window.
|
|
7795
|
+
`
|
|
7796
|
+
);
|
|
7797
|
+
if (breaker.trip) {
|
|
7798
|
+
logRestartEvent("daemon_restart_breaker_tripped", { crash_in_window: breaker.crashInWindow, restarts_in_window: breaker.restartsInWindow });
|
|
7799
|
+
await enterDegradedBreakerMode(breaker.crashInWindow);
|
|
7800
|
+
await new Promise(() => {
|
|
7801
|
+
});
|
|
7802
|
+
}
|
|
7311
7803
|
const mcpRegPath = new URL("../mcp/register-tools.js", import.meta.url).href;
|
|
7312
7804
|
const { registerAllTools: regFn } = await import(
|
|
7313
7805
|
/* @vite-ignore */
|
|
@@ -7350,6 +7842,7 @@ try {
|
|
|
7350
7842
|
}
|
|
7351
7843
|
export {
|
|
7352
7844
|
decidePortHolderAction,
|
|
7845
|
+
getLastBlockingTimer,
|
|
7353
7846
|
injectRegisterAllTools,
|
|
7354
7847
|
isCrashLoopBreakerActive,
|
|
7355
7848
|
isEventLoopBlockedNow,
|