@askexenow/exe-os 0.9.292 → 0.9.293
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/deploy/compose/generate-env.ts +27 -1
- package/dist/active-agent-OEJKODGY.js +27 -0
- package/dist/active-agent-PFZAEMJA.js +28 -0
- package/dist/active-agent-USK4RVP5.js +28 -0
- package/dist/active-agent-XEZTZEV7.js +27 -0
- package/dist/agentic-ontology-46PBPTLE.js +25 -0
- package/dist/agentic-ontology-WTXI6RLB.js +25 -0
- package/dist/assets/com.askexe.exed.plist +70 -0
- package/dist/backfill-metadata-IYP2QGGD.js +600 -0
- package/dist/backfill-metadata-S523IKKJ.js +600 -0
- package/dist/behaviors-GPCWN3RL.js +46 -0
- package/dist/behaviors-UYEYYVIH.js +46 -0
- package/dist/bin/agentic-ontology-backfill.js +5 -5
- package/dist/bin/agentic-reflection-backfill.js +6 -6
- package/dist/bin/agentic-semantic-label.js +5 -5
- package/dist/bin/backfill-conversations.js +6 -6
- package/dist/bin/backfill-responses.js +6 -6
- package/dist/bin/backfill-vectors.js +8 -8
- package/dist/bin/bulk-sync-postgres.js +7 -6
- package/dist/bin/cc-doctor.js +4 -4
- package/dist/bin/cleanup-stale-review-tasks.js +11 -11
- package/dist/bin/cli.js +16 -16
- package/dist/bin/deferred-daemon-restart.js +1 -1
- package/dist/bin/exe-agent-config.js +2 -2
- package/dist/bin/exe-agent.js +4 -4
- package/dist/bin/exe-assign.js +8 -8
- package/dist/bin/exe-boot.js +38 -18
- package/dist/bin/exe-call.js +4 -4
- package/dist/bin/exe-cloud.js +11 -4
- package/dist/bin/exe-dispatch.js +11 -11
- package/dist/bin/exe-doctor.js +2 -2
- package/dist/bin/exe-export-behaviors.js +7 -7
- package/dist/bin/exe-forget.js +6 -6
- package/dist/bin/exe-gateway.js +7 -7
- package/dist/bin/exe-healthcheck.js +4 -4
- package/dist/bin/exe-heartbeat.js +11 -11
- package/dist/bin/exe-kill.js +14 -14
- package/dist/bin/exe-launch-agent.js +36 -18
- package/dist/bin/exe-new-employee.js +6 -6
- package/dist/bin/exe-pending-messages.js +12 -12
- package/dist/bin/exe-pending-notifications.js +11 -11
- package/dist/bin/exe-pending-reviews.js +11 -11
- package/dist/bin/exe-rename.js +4 -4
- package/dist/bin/exe-review.js +13 -13
- package/dist/bin/exe-search.js +5 -5
- package/dist/bin/exe-session-cleanup.js +16 -16
- package/dist/bin/exe-settings.js +12 -4
- package/dist/bin/exe-start-codex.js +11 -11
- package/dist/bin/exe-start-opencode.js +8 -8
- package/dist/bin/exe-status.js +12 -12
- package/dist/bin/exe-team.js +3 -3
- package/dist/bin/git-sweep.js +12 -12
- package/dist/bin/graph-backfill.js +4 -4
- package/dist/bin/graph-export.js +5 -5
- package/dist/bin/import-history.js +7 -7
- package/dist/bin/install-launchd.js +46 -10
- package/dist/bin/install.js +8 -8
- package/dist/bin/intercom-check.js +4 -4
- package/dist/bin/mcp-sessions.js +2 -2
- package/dist/bin/orchestration-metrics.js +4 -4
- package/dist/bin/postgres-agentic-reflection-backfill.js +2 -2
- package/dist/bin/postgres-agentic-semantic-backfill.js +1 -1
- package/dist/bin/scan-tasks.js +11 -11
- package/dist/bin/setup.js +1 -1
- package/dist/bin/shard-migrate.js +4 -4
- package/dist/capability-cards-7XF2UW3Z.js +89 -0
- package/dist/capability-cards-DME6OMOK.js +89 -0
- package/dist/capacity-monitor-7SKMXRIK.js +51 -0
- package/dist/capacity-monitor-MNEA6FMY.js +51 -0
- package/dist/catchup-brief-46O3RLWO.js +175 -0
- package/dist/catchup-brief-EPEKZKRA.js +175 -0
- package/dist/chunk-2EMOVUJR.js +128 -0
- package/dist/chunk-2JE7LJCZ.js +240 -0
- package/dist/chunk-2LHQ5MGP.js +377 -0
- package/dist/chunk-2ZXMXFGH.js +4380 -0
- package/dist/chunk-3KIMGEFL.js +54 -0
- package/dist/chunk-3PY5PK75.js +14533 -0
- package/dist/chunk-3SDAK22H.js +538 -0
- package/dist/chunk-4CEGPB6F.js +240 -0
- package/dist/chunk-4HDMB2M5.js +574 -0
- package/dist/chunk-4KCLWBF6.js +197 -0
- package/dist/chunk-4WZ55DSC.js +381 -0
- package/dist/chunk-5QX4LHOF.js +668 -0
- package/dist/chunk-5RSGWGYP.js +1119 -0
- package/dist/chunk-5SWY4J5G.js +284 -0
- package/dist/chunk-5ZHIAIDE.js +424 -0
- package/dist/chunk-5ZKD5ZVT.js +33 -0
- package/dist/chunk-67X246EI.js +424 -0
- package/dist/chunk-6A56VNVX.js +448 -0
- package/dist/chunk-6EEBG6WU.js +345 -0
- package/dist/chunk-6EI5U2KJ.js +171 -0
- package/dist/chunk-6G4JWZPF.js +128 -0
- package/dist/chunk-6GTLJHAG.js +150 -0
- package/dist/chunk-6LDZPC2H.js +1079 -0
- package/dist/chunk-6PNCZTKV.js +1119 -0
- package/dist/chunk-6QPDD4BI.js +123 -0
- package/dist/chunk-6ZMLJ6ZQ.js +2129 -0
- package/dist/chunk-72O5EJ52.js +204 -0
- package/dist/chunk-737NSJT4.js +553 -0
- package/dist/chunk-7P5TUGTL.js +456 -0
- package/dist/chunk-7XDF7BZQ.js +192 -0
- package/dist/chunk-ALYNEMIH.js +150 -0
- package/dist/chunk-B4PYJHIV.js +402 -0
- package/dist/chunk-B5ZCGIYB.js +630 -0
- package/dist/chunk-BE3T47CS.js +97 -0
- package/dist/chunk-BNJ3YCPD.js +192 -0
- package/dist/chunk-BUBYDG7Q.js +1079 -0
- package/dist/chunk-CSCRGRZT.js +345 -0
- package/dist/chunk-CY4S3HMG.js +30 -0
- package/dist/chunk-D2WYUJHM.js +50 -0
- package/dist/chunk-D3X64YSB.js +377 -0
- package/dist/chunk-D6TPR4BN.js +204 -0
- package/dist/chunk-DDI57ILJ.js +38 -0
- package/dist/chunk-DQBHY3Q4.js +210 -0
- package/dist/chunk-DVFHAY2J.js +630 -0
- package/dist/chunk-DWCR5GGG.js +128 -0
- package/dist/chunk-DZJPVLVR.js +2078 -0
- package/dist/chunk-E45SQG7C.js +280 -0
- package/dist/chunk-EJ7CWALW.js +244 -0
- package/dist/chunk-EM5WXY6H.js +836 -0
- package/dist/chunk-EOVVOUXC.js +381 -0
- package/dist/chunk-EVV55PHP.js +331 -0
- package/dist/chunk-F4FMIWEL.js +214 -0
- package/dist/chunk-F5GLICUP.js +85 -0
- package/dist/chunk-F5WN7EQ2.js +333 -0
- package/dist/chunk-FVXYTNSI.js +123 -0
- package/dist/chunk-FXD5LXRD.js +8 -0
- package/dist/chunk-G53LIPLG.js +76 -0
- package/dist/chunk-GEJAUWIZ.js +1350 -0
- package/dist/chunk-GJDYAXUL.js +227 -0
- package/dist/chunk-GJS7CJRC.js +129 -0
- package/dist/chunk-GTVP4QTZ.js +362 -0
- package/dist/chunk-HG7Z7JHX.js +85 -0
- package/dist/chunk-HH3MBGMJ.js +70 -0
- package/dist/chunk-HJBKBEC4.js +58 -0
- package/dist/chunk-HKSTWZ22.js +456 -0
- package/dist/chunk-HMP5VT6A.js +118 -0
- package/dist/chunk-HN2PWLQI.js +167 -0
- package/dist/chunk-HN3HGFBL.js +20 -0
- package/dist/chunk-HREBA7BJ.js +290 -0
- package/dist/chunk-HV7F5CXJ.js +553 -0
- package/dist/chunk-HWXIMSB7.js +30 -0
- package/dist/chunk-HWY5ROLO.js +129 -0
- package/dist/chunk-IDJCLLJF.js +3298 -0
- package/dist/chunk-IPMGAQGC.js +290 -0
- package/dist/chunk-IRT55NLF.js +382 -0
- package/dist/chunk-IXZ7OTB3.js +159 -0
- package/dist/chunk-J7JVMFKR.js +262 -0
- package/dist/chunk-JABYHL7R.js +171 -0
- package/dist/chunk-JE2ICRS5.js +197 -0
- package/dist/chunk-JLH273CW.js +70 -0
- package/dist/chunk-JPTT22PI.js +54 -0
- package/dist/chunk-JVT6ONVZ.js +731 -0
- package/dist/chunk-KJEG2OQN.js +1350 -0
- package/dist/chunk-LSASGUNP.js +85 -0
- package/dist/chunk-LSTM35QE.js +1186 -0
- package/dist/chunk-LZEWGBU2.js +97 -0
- package/dist/chunk-M2IOPGVR.js +731 -0
- package/dist/chunk-MBININJN.js +2078 -0
- package/dist/chunk-MJ2MCLZH.js +402 -0
- package/dist/chunk-MX63V4YD.js +38 -0
- package/dist/chunk-N7TWCWY5.js +128 -0
- package/dist/chunk-NAKIQODV.js +331 -0
- package/dist/chunk-NMJSZ5FC.js +185 -0
- package/dist/chunk-NXCJWGAF.js +836 -0
- package/dist/chunk-OLJTE7LW.js +157 -0
- package/dist/chunk-OPDX7KTW.js +167 -0
- package/dist/chunk-OXM62MI7.js +221 -0
- package/dist/chunk-PC53GP5N.js +55 -0
- package/dist/chunk-PMMQFOER.js +81 -0
- package/dist/chunk-PVVG22J4.js +735 -0
- package/dist/chunk-Q326CKO3.js +377 -0
- package/dist/chunk-QAK47LG3.js +81 -0
- package/dist/chunk-QAWSQ5LG.js +157 -0
- package/dist/chunk-QLPHEY7D.js +668 -0
- package/dist/chunk-QV4CHWME.js +97 -0
- package/dist/chunk-QY46R3SB.js +348 -0
- package/dist/chunk-RAERYWCL.js +299 -0
- package/dist/chunk-RT5NXMH2.js +284 -0
- package/dist/chunk-RUUIZJSU.js +127 -0
- package/dist/chunk-S3PNZLTN.js +50 -0
- package/dist/chunk-S6WSWJBL.js +362 -0
- package/dist/chunk-STOZKLK6.js +1352 -0
- package/dist/chunk-SZCJI4TR.js +735 -0
- package/dist/chunk-T3FMPQOR.js +85 -0
- package/dist/chunk-T6EKR34W.js +58 -0
- package/dist/chunk-TKIOFYNW.js +1186 -0
- package/dist/chunk-TM2GZWIT.js +3313 -0
- package/dist/chunk-TWFTSIAI.js +4380 -0
- package/dist/chunk-U7BFATN7.js +538 -0
- package/dist/chunk-UAQZT24C.js +181 -0
- package/dist/chunk-UFHBNXGV.js +333 -0
- package/dist/chunk-UVN3LWCL.js +214 -0
- package/dist/chunk-UVRS32RJ.js +97 -0
- package/dist/chunk-V6R43RSE.js +227 -0
- package/dist/chunk-VHMVQUCR.js +448 -0
- package/dist/chunk-VK7NRMIW.js +2133 -0
- package/dist/chunk-VRFO3H3R.js +76 -0
- package/dist/chunk-VRZS4KWF.js +122 -0
- package/dist/chunk-WOXY76VV.js +33 -0
- package/dist/chunk-X6VOKECC.js +348 -0
- package/dist/chunk-XADXYWPE.js +280 -0
- package/dist/chunk-XCP56OMR.js +1352 -0
- package/dist/chunk-XDH5XB72.js +262 -0
- package/dist/chunk-XFPSFPVD.js +1094 -0
- package/dist/chunk-XOT6CVJA.js +244 -0
- package/dist/chunk-XWRIBBYP.js +210 -0
- package/dist/chunk-XWVCURC2.js +181 -0
- package/dist/chunk-YA6SJFNN.js +221 -0
- package/dist/chunk-YDMUHYCP.js +127 -0
- package/dist/chunk-YKQQ4UTG.js +382 -0
- package/dist/chunk-YNORJIBH.js +208 -0
- package/dist/chunk-YQ2R4BLZ.js +14533 -0
- package/dist/chunk-YUIT7Z7I.js +299 -0
- package/dist/chunk-ZD6EJ7LY.js +604 -0
- package/dist/chunk-ZHHBVPOX.js +1094 -0
- package/dist/chunk-ZNY54QWW.js +377 -0
- package/dist/chunk-ZVABYVSP.js +122 -0
- package/dist/chunk-ZVDYPSJH.js +94 -0
- package/dist/chunk-ZXNQ7GRU.js +185 -0
- package/dist/co-activation-ACVH2TL4.js +74 -0
- package/dist/co-activation-EJ63SDWZ.js +74 -0
- package/dist/co-occurrence-VKJWYROE.js +95 -0
- package/dist/co-occurrence-X2M3ASN4.js +95 -0
- package/dist/code-context-index-5EFZGRML.js +30 -0
- package/dist/core-memory-G3AEM4FY.js +110 -0
- package/dist/core-memory-GOI4WKP5.js +110 -0
- package/dist/crdt-sync-QXBHJ5GL.js +33 -0
- package/dist/crdt-sync-WX6YMYZS.js +33 -0
- package/dist/crm-webhook-EEL2F5TM.js +10 -0
- package/dist/crm-webhook-OYNQH4RZ.js +10 -0
- package/dist/cto-delegation-gate-RP4XBAZZ.js +280 -0
- package/dist/cto-delegation-gate-XOD3NAJS.js +280 -0
- package/dist/daemon-orchestration-33R5DNF2.js +139 -0
- package/dist/daemon-orchestration-EEPWOFMX.js +139 -0
- package/dist/db-backup-T4OALIZH.js +41 -0
- package/dist/db-backup-U5TNET7Z.js +41 -0
- package/dist/dispatch-ack-4S44HBWB.js +15 -0
- package/dist/doc-graph-extractor-O5EADZ3H.js +133 -0
- package/dist/doc-graph-extractor-SFMDR2SB.js +133 -0
- package/dist/dreaming-IXYC3FUN.js +34 -0
- package/dist/dreaming-ODYGZEIV.js +34 -0
- package/dist/entity-boost-XBGZKDJZ.js +375 -0
- package/dist/exe-drift-BKAGZUO2.js +70 -0
- package/dist/exe-drift-N7QYRQX7.js +70 -0
- package/dist/exe-export-AQZ3ZPSJ.js +77 -0
- package/dist/exe-export-QQGWWVZC.js +77 -0
- package/dist/exe-import-EVEGB2O4.js +80 -0
- package/dist/exe-import-RPL3RSZ2.js +80 -0
- package/dist/exe-key-5FYKRZOH.js +673 -0
- package/dist/exe-key-Y256JM3G.js +673 -0
- package/dist/exe-snapshot-AUJQ53Z7.js +338 -0
- package/dist/exe-snapshot-CSJDVWXM.js +338 -0
- package/dist/fast-db-init-57YCVJQP.js +7 -0
- package/dist/fast-db-init-VU4FDPGX.js +7 -0
- package/dist/gateway/index.js +8 -8
- package/dist/git-staleness-CR46BFAY.js +112 -0
- package/dist/git-staleness-H4NWNDJ5.js +112 -0
- package/dist/git-task-sweep-F7ASO7CZ.js +42 -0
- package/dist/git-task-sweep-XSPCOBUY.js +42 -0
- package/dist/global-procedures-7FDCJNWI.js +22 -0
- package/dist/global-procedures-GX7V5L76.js +22 -0
- package/dist/graph-auto-extract-JI3VW5KY.js +183 -0
- package/dist/graph-auto-extract-KFNHAHBK.js +183 -0
- package/dist/hooks/bug-report-worker.js +13 -13
- package/dist/hooks/codex-stop-task-finalizer.js +13 -13
- package/dist/hooks/commit-complete.js +13 -13
- package/dist/hooks/error-recall.js +6 -6
- package/dist/hooks/exe-heartbeat-hook.js +3 -3
- package/dist/hooks/ingest-worker.js +3 -3
- package/dist/hooks/ingest.js +6 -6
- package/dist/hooks/instructions-loaded.js +4 -4
- package/dist/hooks/manifest.json +20 -20
- package/dist/hooks/notification.js +4 -4
- package/dist/hooks/post-compact.js +12 -12
- package/dist/hooks/post-tool-combined.js +6 -6
- package/dist/hooks/pre-compact.js +16 -16
- package/dist/hooks/pre-tool-use.js +17 -17
- package/dist/hooks/prompt-submit.js +25 -25
- package/dist/hooks/session-end.js +23 -21
- package/dist/hooks/session-start.js +12 -12
- package/dist/hooks/stop.js +19 -19
- package/dist/hooks/subagent-stop.js +43 -13
- package/dist/hooks/summary-worker.js +19 -19
- package/dist/index.js +19 -19
- package/dist/installer-6PMCIZQZ.js +298 -0
- package/dist/installer-7ET5M2DD.js +344 -0
- package/dist/installer-K7BYY3XC.js +344 -0
- package/dist/installer-U6W7TQZU.js +40 -0
- package/dist/installer-UL4HFVPT.js +298 -0
- package/dist/installer-XMQRESAT.js +40 -0
- package/dist/lib/cloud-sync.js +12 -4
- package/dist/lib/consolidation.js +5 -5
- package/dist/lib/database.js +2 -2
- package/dist/lib/db-daemon-client.js +2 -2
- package/dist/lib/db.js +2 -2
- package/dist/lib/embedder.js +3 -3
- package/dist/lib/employee-templates.js +4 -4
- package/dist/lib/employees.js +2 -2
- package/dist/lib/exe-daemon-client.js +2 -2
- package/dist/lib/exe-daemon.js +50 -39
- package/dist/lib/hybrid-search.js +5 -5
- package/dist/lib/identity.js +2 -2
- package/dist/lib/messaging.js +11 -11
- package/dist/lib/reminders.js +3 -3
- package/dist/lib/schedules.js +5 -5
- package/dist/lib/session-registry.js +4 -4
- package/dist/lib/skill-learning.js +6 -6
- package/dist/lib/store.js +4 -4
- package/dist/lib/task-router.js +3 -3
- package/dist/lib/tasks.js +12 -12
- package/dist/lib/tmux-routing.js +10 -10
- package/dist/lib/tmux-transport.js +2 -1
- package/dist/lib/token-spend.js +3 -3
- package/dist/lib/transport.js +3 -2
- package/dist/mcp/register-tools.js +62 -62
- package/dist/mcp/server.js +63 -63
- package/dist/mcp/tools/complete-reminder.js +4 -4
- package/dist/mcp/tools/create-reminder.js +4 -4
- package/dist/mcp/tools/create-task.js +15 -15
- package/dist/mcp/tools/deactivate-behavior.js +7 -7
- package/dist/mcp/tools/list-reminders.js +4 -4
- package/dist/mcp/tools/list-tasks.js +14 -14
- package/dist/mcp/tools/send-message.js +13 -13
- package/dist/mcp/tools/update-task.js +13 -13
- package/dist/mcp-http-config-JZPO4B6K.js +29 -0
- package/dist/mcp-http-config-L6TEBZOW.js +29 -0
- package/dist/memory-cards-EIA3YLFA.js +180 -0
- package/dist/memory-cards-MDZGVJWJ.js +180 -0
- package/dist/memory-graph-extractor-BMZBK2LX.js +22 -0
- package/dist/memory-graph-extractor-U2Q7MTBZ.js +22 -0
- package/dist/memory-poisoning-defense-ORWGA4KK.js +224 -0
- package/dist/memory-poisoning-defense-ZY5P2OOG.js +224 -0
- package/dist/memory-queue-client-A2PMQVEU.js +16 -0
- package/dist/memory-reflection-35NUYL3Z.js +244 -0
- package/dist/memory-reflection-NHOC2FGF.js +244 -0
- package/dist/message-queue-client-L5VZ44IN.js +92 -0
- package/dist/notifications-7GGXNR42.js +47 -0
- package/dist/notifications-B2YCZD3T.js +47 -0
- package/dist/orchestration-events-7EQJF377.js +27 -0
- package/dist/orchestration-events-VJTAOA2R.js +27 -0
- package/dist/orchestrator-IAU2Y3K3.js +35 -0
- package/dist/orchestrator-YOM5D5EJ.js +35 -0
- package/dist/pipeline-router-ITQDOV2B.js +15 -0
- package/dist/pipeline-router-VYFAS3ZX.js +15 -0
- package/dist/plan-limits-OJQINDD3.js +28 -0
- package/dist/plan-limits-UWVCNA67.js +28 -0
- package/dist/project-boot-GSLIQJVS.js +299 -0
- package/dist/project-boot-NRU7RRED.js +299 -0
- package/dist/projection-worker-SKLKJJFA.js +1084 -0
- package/dist/projection-worker-XVOLBYQC.js +1084 -0
- package/dist/prospective-memory-JOKZL7QJ.js +232 -0
- package/dist/prospective-memory-WQSB2IPD.js +232 -0
- package/dist/reranker-5HJXM4K5.js +19 -0
- package/dist/reranker-Q7KD2VDL.js +19 -0
- package/dist/retrieval-health-BAKZOWX7.js +11 -0
- package/dist/retrieval-health-LXDMWIAZ.js +11 -0
- package/dist/review-polling-GBRSJ7X5.js +126 -0
- package/dist/review-polling-YDS35QTO.js +126 -0
- package/dist/runtime/index.js +13 -13
- package/dist/session-events-EJID2CZE.js +38 -0
- package/dist/session-events-UPXPYEA3.js +38 -0
- package/dist/session-kill-telemetry-7FP74BIM.js +31 -0
- package/dist/session-kill-telemetry-XLMNOBBQ.js +31 -0
- package/dist/session-scope-QCN23H6B.js +88 -0
- package/dist/session-scope-ZR2W2EDF.js +88 -0
- package/dist/setup-wizard-7H4CE5UL.js +12 -0
- package/dist/setup-wizard-MR3XA4BC.js +12 -0
- package/dist/skill-refinement-6UK4P4UQ.js +159 -0
- package/dist/skill-refinement-RYBLDKDP.js +159 -0
- package/dist/steward-gate-PSF4JQUC.js +15 -0
- package/dist/steward-gate-U2HQZ4LX.js +15 -0
- package/dist/task-enforcement-NL6WPS3T.js +506 -0
- package/dist/task-enforcement-RYWTWHQJ.js +506 -0
- package/dist/task-scope-43TBGXSP.js +37 -0
- package/dist/task-scope-BR4ZJLQT.js +37 -0
- package/dist/tasks-crud-AQLUDVES.js +79 -0
- package/dist/tasks-crud-LWTHIDHF.js +79 -0
- package/dist/tasks-notify-PZQMVQHI.js +40 -0
- package/dist/tasks-notify-U4QZ2FGV.js +40 -0
- package/dist/tasks-review-E3LQRBNB.js +49 -0
- package/dist/tasks-review-NIGU6K3L.js +49 -0
- package/dist/telemetry-upload-PQLC5A4D.js +741 -0
- package/dist/telemetry-upload-QOYSUDDH.js +741 -0
- package/dist/token-budget-OJGWYISJ.js +86 -0
- package/dist/token-budget-VMQLMHSU.js +86 -0
- package/dist/tool-capability-index-4M3BFQTU.js +10 -0
- package/dist/tool-telemetry-4YD2E6UU.js +17 -0
- package/dist/tool-telemetry-662N3S5Q.js +17 -0
- package/dist/tui/App.js +18 -18
- package/dist/tui-data-IIGF5XRY.js +260 -0
- package/dist/tui-data-W4INCXEA.js +260 -0
- package/dist/wiki-acl-KXXMRMIM.js +111 -0
- package/dist/wiki-acl-XSRBJSBD.js +111 -0
- package/dist/worker-gate-7GMM23JY.js +21 -0
- package/dist/worker-gate-F6LY67TM.js +21 -0
- package/dist/workflow-engine-G4JTWI5N.js +28 -0
- package/dist/workflow-engine-UHOVTA5Q.js +28 -0
- package/dist/worktree-OJMZ4RG4.js +28 -0
- package/dist/worktree-ZLF4MX6T.js +28 -0
- package/dist/worktree-sweep-5Z6V7MNJ.js +21 -0
- package/dist/worktree-sweep-M64OW2MU.js +21 -0
- package/package.json +2 -2
- package/release-notes.json +14 -14
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getGitRoot,
|
|
3
|
+
isWorktreeDirty
|
|
4
|
+
} from "./chunk-XADXYWPE.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/worktree-sweep.ts
|
|
7
|
+
import { execFileSync } from "child_process";
|
|
8
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
9
|
+
import path from "path";
|
|
10
|
+
var GIT_TIMEOUT_MS = 1e4;
|
|
11
|
+
var DIRTY_ORPHAN_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
12
|
+
function isWorktreeUnpushed(wtPath, branch) {
|
|
13
|
+
if (!branch) return false;
|
|
14
|
+
try {
|
|
15
|
+
const remote = execFileSync("git", ["-C", wtPath, "rev-parse", "--abbrev-ref", `${branch}@{upstream}`], { encoding: "utf-8", timeout: GIT_TIMEOUT_MS, stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
16
|
+
if (!remote) return true;
|
|
17
|
+
const ahead = execFileSync("git", ["-C", wtPath, "rev-list", `${remote}..${branch}`, "--count"], { encoding: "utf-8", timeout: GIT_TIMEOUT_MS, stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
18
|
+
return parseInt(ahead, 10) > 0;
|
|
19
|
+
} catch {
|
|
20
|
+
try {
|
|
21
|
+
let ahead = "";
|
|
22
|
+
try {
|
|
23
|
+
ahead = execFileSync("git", ["-C", wtPath, "rev-list", `main..${branch}`, "--count"], { encoding: "utf-8", timeout: GIT_TIMEOUT_MS, stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
24
|
+
} catch {
|
|
25
|
+
ahead = execFileSync("git", ["-C", wtPath, "rev-list", `master..${branch}`, "--count"], { encoding: "utf-8", timeout: GIT_TIMEOUT_MS, stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
26
|
+
}
|
|
27
|
+
return parseInt(ahead, 10) > 0;
|
|
28
|
+
} catch {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
var REPO_ALIASES = {
|
|
34
|
+
"exe-crm": ["openclaw", "exe-crm"],
|
|
35
|
+
"exe-wiki": ["ink", "exe-wiki"]
|
|
36
|
+
};
|
|
37
|
+
function discoverRepoPaths() {
|
|
38
|
+
const roots = [];
|
|
39
|
+
let exeOsRoot = null;
|
|
40
|
+
let dir = path.dirname(new URL(import.meta.url).pathname);
|
|
41
|
+
for (let i = 0; i < 5; i++) {
|
|
42
|
+
const pkgPath = path.join(dir, "package.json");
|
|
43
|
+
if (existsSync(pkgPath)) {
|
|
44
|
+
try {
|
|
45
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
46
|
+
if (pkg.name === "@askexenow/exe-os") {
|
|
47
|
+
exeOsRoot = dir;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
dir = path.dirname(dir);
|
|
54
|
+
}
|
|
55
|
+
if (!exeOsRoot) {
|
|
56
|
+
exeOsRoot = process.cwd();
|
|
57
|
+
}
|
|
58
|
+
roots.push(exeOsRoot);
|
|
59
|
+
const parentDir = path.dirname(exeOsRoot);
|
|
60
|
+
try {
|
|
61
|
+
const siblings = readdirSync(parentDir);
|
|
62
|
+
for (const sibling of siblings) {
|
|
63
|
+
if (sibling.startsWith(".")) continue;
|
|
64
|
+
const siblingPath = path.join(parentDir, sibling);
|
|
65
|
+
if (siblingPath === exeOsRoot) continue;
|
|
66
|
+
const root = getGitRoot(siblingPath);
|
|
67
|
+
if (root && !roots.includes(root)) {
|
|
68
|
+
roots.push(root);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
for (const aliases of Object.values(REPO_ALIASES)) {
|
|
74
|
+
for (const alias of aliases) {
|
|
75
|
+
const aliasPath = path.join(parentDir, alias);
|
|
76
|
+
if (existsSync(aliasPath)) {
|
|
77
|
+
const root = getGitRoot(aliasPath);
|
|
78
|
+
if (root && !roots.includes(root)) {
|
|
79
|
+
roots.push(root);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return roots;
|
|
85
|
+
}
|
|
86
|
+
function listWorktrees(repoRoot) {
|
|
87
|
+
try {
|
|
88
|
+
const output = execFileSync("git", ["worktree", "list", "--porcelain"], {
|
|
89
|
+
cwd: repoRoot,
|
|
90
|
+
encoding: "utf8",
|
|
91
|
+
timeout: GIT_TIMEOUT_MS,
|
|
92
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
93
|
+
});
|
|
94
|
+
const worktrees = [];
|
|
95
|
+
let currentPath = "";
|
|
96
|
+
for (const line of output.split("\n")) {
|
|
97
|
+
if (line.startsWith("worktree ")) {
|
|
98
|
+
currentPath = line.slice("worktree ".length);
|
|
99
|
+
} else if (line.startsWith("branch ") && currentPath) {
|
|
100
|
+
const branch = line.slice("branch refs/heads/".length);
|
|
101
|
+
worktrees.push({ path: currentPath, branch });
|
|
102
|
+
currentPath = "";
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return worktrees;
|
|
106
|
+
} catch {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function detectMainBranch(repoRoot) {
|
|
111
|
+
for (const candidate of ["main", "master"]) {
|
|
112
|
+
try {
|
|
113
|
+
execFileSync("git", ["rev-parse", "--verify", `refs/heads/${candidate}`], {
|
|
114
|
+
cwd: repoRoot,
|
|
115
|
+
encoding: "utf8",
|
|
116
|
+
timeout: GIT_TIMEOUT_MS,
|
|
117
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
118
|
+
});
|
|
119
|
+
return candidate;
|
|
120
|
+
} catch {
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
function isBranchMerged(repoRoot, branch, into) {
|
|
126
|
+
try {
|
|
127
|
+
const merged = execFileSync("git", ["branch", "--merged", into], {
|
|
128
|
+
cwd: repoRoot,
|
|
129
|
+
encoding: "utf8",
|
|
130
|
+
timeout: GIT_TIMEOUT_MS,
|
|
131
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
132
|
+
});
|
|
133
|
+
return merged.split("\n").map((l) => l.replace(/^[*+]?\s+/, "").trim()).includes(branch);
|
|
134
|
+
} catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function hasLiveTmuxSession(agentName) {
|
|
139
|
+
try {
|
|
140
|
+
const sessions = execFileSync("tmux", ["list-sessions", "-F", "#S"], {
|
|
141
|
+
encoding: "utf8",
|
|
142
|
+
timeout: 5e3,
|
|
143
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
144
|
+
}).trim();
|
|
145
|
+
if (!sessions) return false;
|
|
146
|
+
for (const session of sessions.split("\n")) {
|
|
147
|
+
const agentPart = session.split("-")[0];
|
|
148
|
+
if (!agentPart) continue;
|
|
149
|
+
const baseName = agentPart.replace(/\d+$/, "");
|
|
150
|
+
if (baseName === agentName || agentPart === agentName) return true;
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
} catch {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function removeWorktree(repoRoot, wtPath) {
|
|
158
|
+
try {
|
|
159
|
+
execFileSync("git", ["worktree", "remove", wtPath, "--force"], {
|
|
160
|
+
cwd: repoRoot,
|
|
161
|
+
encoding: "utf8",
|
|
162
|
+
timeout: GIT_TIMEOUT_MS,
|
|
163
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
164
|
+
});
|
|
165
|
+
return true;
|
|
166
|
+
} catch {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function deleteBranch(repoRoot, branch) {
|
|
171
|
+
try {
|
|
172
|
+
execFileSync("git", ["branch", "-D", branch], {
|
|
173
|
+
cwd: repoRoot,
|
|
174
|
+
encoding: "utf8",
|
|
175
|
+
timeout: GIT_TIMEOUT_MS,
|
|
176
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
177
|
+
});
|
|
178
|
+
return true;
|
|
179
|
+
} catch {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function deleteRemoteBranch(repoRoot, branch) {
|
|
184
|
+
try {
|
|
185
|
+
execFileSync("git", ["push", "origin", "--delete", branch], {
|
|
186
|
+
cwd: repoRoot,
|
|
187
|
+
encoding: "utf8",
|
|
188
|
+
timeout: 15e3,
|
|
189
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
190
|
+
});
|
|
191
|
+
return true;
|
|
192
|
+
} catch {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function pruneWorktreeRegistry(repoRoot) {
|
|
197
|
+
try {
|
|
198
|
+
execFileSync("git", ["worktree", "prune"], {
|
|
199
|
+
cwd: repoRoot,
|
|
200
|
+
encoding: "utf8",
|
|
201
|
+
timeout: GIT_TIMEOUT_MS,
|
|
202
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
203
|
+
});
|
|
204
|
+
} catch {
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function clearStashes(repoRoot) {
|
|
208
|
+
try {
|
|
209
|
+
const stashList = execFileSync("git", ["stash", "list"], {
|
|
210
|
+
cwd: repoRoot,
|
|
211
|
+
encoding: "utf8",
|
|
212
|
+
timeout: GIT_TIMEOUT_MS,
|
|
213
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
214
|
+
}).trim();
|
|
215
|
+
if (!stashList) return 0;
|
|
216
|
+
const count = stashList.split("\n").length;
|
|
217
|
+
execFileSync("git", ["stash", "clear"], {
|
|
218
|
+
cwd: repoRoot,
|
|
219
|
+
encoding: "utf8",
|
|
220
|
+
timeout: GIT_TIMEOUT_MS,
|
|
221
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
222
|
+
});
|
|
223
|
+
return count;
|
|
224
|
+
} catch {
|
|
225
|
+
return 0;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function parseAgentName(wtPath) {
|
|
229
|
+
const dirName = path.basename(wtPath);
|
|
230
|
+
if (!dirName) return null;
|
|
231
|
+
return dirName.replace(/\d+$/, "") || dirName;
|
|
232
|
+
}
|
|
233
|
+
function getDirMtimeMs(dirPath) {
|
|
234
|
+
try {
|
|
235
|
+
return statSync(dirPath).mtimeMs;
|
|
236
|
+
} catch {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function archiveDirtyWorktree(wtPath, agentName) {
|
|
241
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
242
|
+
const quarantineBranch = `quarantine/${agentName}-${timestamp}`;
|
|
243
|
+
try {
|
|
244
|
+
execFileSync("git", ["-C", wtPath, "checkout", "-b", quarantineBranch], {
|
|
245
|
+
encoding: "utf8",
|
|
246
|
+
timeout: GIT_TIMEOUT_MS,
|
|
247
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
248
|
+
});
|
|
249
|
+
execFileSync("git", ["-C", wtPath, "add", "-A"], {
|
|
250
|
+
encoding: "utf8",
|
|
251
|
+
timeout: GIT_TIMEOUT_MS,
|
|
252
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
253
|
+
});
|
|
254
|
+
execFileSync("git", [
|
|
255
|
+
"-C",
|
|
256
|
+
wtPath,
|
|
257
|
+
"commit",
|
|
258
|
+
"-m",
|
|
259
|
+
`[quarantine] Auto-archived dirty orphan worktree
|
|
260
|
+
|
|
261
|
+
Agent: ${agentName}
|
|
262
|
+
Original worktree: ${wtPath}
|
|
263
|
+
Archived by worktree-sweep after ${DIRTY_ORPHAN_MAX_AGE_MS / 864e5}-day dirty orphan threshold.`
|
|
264
|
+
], {
|
|
265
|
+
encoding: "utf8",
|
|
266
|
+
timeout: GIT_TIMEOUT_MS,
|
|
267
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
268
|
+
env: {
|
|
269
|
+
...process.env,
|
|
270
|
+
GIT_AUTHOR_NAME: "exe-os daemon",
|
|
271
|
+
GIT_AUTHOR_EMAIL: "daemon@exe-os.local",
|
|
272
|
+
GIT_COMMITTER_NAME: "exe-os daemon",
|
|
273
|
+
GIT_COMMITTER_EMAIL: "daemon@exe-os.local"
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
process.stderr.write(`[worktree-sweep] Archived dirty changes to branch ${quarantineBranch}
|
|
277
|
+
`);
|
|
278
|
+
return true;
|
|
279
|
+
} catch {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
async function sweepWorktrees(options = {}) {
|
|
284
|
+
const dryRun = options.dryRun ?? false;
|
|
285
|
+
const repoPaths = options.repoPaths ?? discoverRepoPaths();
|
|
286
|
+
const result = {
|
|
287
|
+
reposScanned: 0,
|
|
288
|
+
removed: [],
|
|
289
|
+
branchesDeleted: [],
|
|
290
|
+
stashesCleared: 0,
|
|
291
|
+
skipped: [],
|
|
292
|
+
errors: []
|
|
293
|
+
};
|
|
294
|
+
for (const repoPath of repoPaths) {
|
|
295
|
+
const repoRoot = getGitRoot(repoPath);
|
|
296
|
+
if (!repoRoot) continue;
|
|
297
|
+
result.reposScanned++;
|
|
298
|
+
const repoName = path.basename(repoRoot);
|
|
299
|
+
const mainBranch = detectMainBranch(repoRoot);
|
|
300
|
+
if (!dryRun) {
|
|
301
|
+
pruneWorktreeRegistry(repoRoot);
|
|
302
|
+
}
|
|
303
|
+
const worktrees = listWorktrees(repoRoot);
|
|
304
|
+
for (const wt of worktrees) {
|
|
305
|
+
if (!wt.path.includes("/.worktrees/")) continue;
|
|
306
|
+
const agentName = parseAgentName(wt.path);
|
|
307
|
+
const wtName = path.basename(wt.path);
|
|
308
|
+
if (agentName && hasLiveTmuxSession(agentName)) {
|
|
309
|
+
result.skipped.push({
|
|
310
|
+
repo: repoName,
|
|
311
|
+
worktree: wtName,
|
|
312
|
+
branch: wt.branch,
|
|
313
|
+
reason: "live tmux session"
|
|
314
|
+
});
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (existsSync(wt.path) && isWorktreeDirty(wt.path)) {
|
|
318
|
+
const mtimeMs = getDirMtimeMs(wt.path);
|
|
319
|
+
const ageMs = mtimeMs !== null ? Date.now() - mtimeMs : 0;
|
|
320
|
+
if (ageMs >= DIRTY_ORPHAN_MAX_AGE_MS && agentName && !dryRun) {
|
|
321
|
+
const ageD = Math.round(ageMs / 864e5);
|
|
322
|
+
process.stderr.write(
|
|
323
|
+
`[worktree-sweep] Dirty orphan aged out (${ageD}d), archiving: ${repoName}/.worktrees/${wtName}
|
|
324
|
+
`
|
|
325
|
+
);
|
|
326
|
+
const archived = archiveDirtyWorktree(wt.path, agentName);
|
|
327
|
+
if (archived) {
|
|
328
|
+
} else {
|
|
329
|
+
result.skipped.push({
|
|
330
|
+
repo: repoName,
|
|
331
|
+
worktree: wtName,
|
|
332
|
+
branch: wt.branch,
|
|
333
|
+
reason: `uncommitted changes (archive failed after ${ageD}d)`
|
|
334
|
+
});
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
} else if (ageMs >= DIRTY_ORPHAN_MAX_AGE_MS && dryRun) {
|
|
338
|
+
const ageD = Math.round(ageMs / 864e5);
|
|
339
|
+
result.removed.push({ repo: repoName, worktree: wtName, branch: wt.branch });
|
|
340
|
+
process.stderr.write(
|
|
341
|
+
`[worktree-sweep] [DRY-RUN] Would archive+remove dirty orphan (${ageD}d): ${repoName}/.worktrees/${wtName}
|
|
342
|
+
`
|
|
343
|
+
);
|
|
344
|
+
continue;
|
|
345
|
+
} else {
|
|
346
|
+
result.skipped.push({
|
|
347
|
+
repo: repoName,
|
|
348
|
+
worktree: wtName,
|
|
349
|
+
branch: wt.branch,
|
|
350
|
+
reason: "uncommitted changes"
|
|
351
|
+
});
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (existsSync(wt.path) && isWorktreeUnpushed(wt.path, wt.branch)) {
|
|
356
|
+
result.skipped.push({
|
|
357
|
+
repo: repoName,
|
|
358
|
+
worktree: wtName,
|
|
359
|
+
branch: wt.branch,
|
|
360
|
+
reason: "unpushed commits \u2014 push first or use --force"
|
|
361
|
+
});
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
const isMerged = mainBranch ? isBranchMerged(repoRoot, wt.branch, mainBranch) : false;
|
|
365
|
+
if (dryRun) {
|
|
366
|
+
result.removed.push({ repo: repoName, worktree: wtName, branch: wt.branch });
|
|
367
|
+
if (isMerged || !mainBranch) {
|
|
368
|
+
result.branchesDeleted.push({ repo: repoName, branch: wt.branch, remote: true });
|
|
369
|
+
} else {
|
|
370
|
+
result.branchesDeleted.push({ repo: repoName, branch: wt.branch, remote: false });
|
|
371
|
+
}
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
const removed = removeWorktree(repoRoot, wt.path);
|
|
375
|
+
if (!removed) {
|
|
376
|
+
result.errors.push(`${repoName}: failed to remove worktree ${wtName}`);
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
result.removed.push({ repo: repoName, worktree: wtName, branch: wt.branch });
|
|
380
|
+
process.stderr.write(`[worktree-sweep] Removed ${repoName}/.worktrees/${wtName} (branch: ${wt.branch})
|
|
381
|
+
`);
|
|
382
|
+
const localDeleted = deleteBranch(repoRoot, wt.branch);
|
|
383
|
+
let remoteDeleted = false;
|
|
384
|
+
if (localDeleted) {
|
|
385
|
+
remoteDeleted = deleteRemoteBranch(repoRoot, wt.branch);
|
|
386
|
+
}
|
|
387
|
+
if (localDeleted) {
|
|
388
|
+
result.branchesDeleted.push({ repo: repoName, branch: wt.branch, remote: remoteDeleted });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (!dryRun) {
|
|
392
|
+
const cleared = clearStashes(repoRoot);
|
|
393
|
+
if (cleared > 0) {
|
|
394
|
+
result.stashesCleared += cleared;
|
|
395
|
+
process.stderr.write(`[worktree-sweep] Cleared ${cleared} stash(es) in ${repoName}
|
|
396
|
+
`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (!dryRun) {
|
|
400
|
+
pruneWorktreeRegistry(repoRoot);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return result;
|
|
404
|
+
}
|
|
405
|
+
function cleanupAgentWorktree(repoRoot, agentName) {
|
|
406
|
+
const worktreesDir = path.join(repoRoot, ".worktrees");
|
|
407
|
+
if (!existsSync(worktreesDir)) return "";
|
|
408
|
+
const notes = [];
|
|
409
|
+
try {
|
|
410
|
+
const entries = readdirSync(worktreesDir);
|
|
411
|
+
for (const entry of entries) {
|
|
412
|
+
const baseName = entry.replace(/\d+$/, "") || entry;
|
|
413
|
+
const agentBase = agentName.replace(/\d+$/, "") || agentName;
|
|
414
|
+
if (baseName !== agentBase) continue;
|
|
415
|
+
const wtPath = path.join(worktreesDir, entry);
|
|
416
|
+
const branch = getWorktreeBranch(repoRoot, wtPath);
|
|
417
|
+
if (isWorktreeDirty(wtPath)) {
|
|
418
|
+
notes.push(`Worktree .worktrees/${entry} has uncommitted changes \u2014 preserved`);
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
if (isWorktreeUnpushed(wtPath, branch)) {
|
|
422
|
+
notes.push(`Worktree .worktrees/${entry} has unpushed commits \u2014 preserved`);
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
if (removeWorktree(repoRoot, wtPath)) {
|
|
426
|
+
notes.push(`Removed worktree .worktrees/${entry}`);
|
|
427
|
+
if (branch && deleteBranch(repoRoot, branch)) {
|
|
428
|
+
notes.push(`Deleted branch ${branch}`);
|
|
429
|
+
if (deleteRemoteBranch(repoRoot, branch)) {
|
|
430
|
+
notes.push(`Deleted remote branch ${branch}`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
} catch {
|
|
436
|
+
}
|
|
437
|
+
pruneWorktreeRegistry(repoRoot);
|
|
438
|
+
return notes.join("\n");
|
|
439
|
+
}
|
|
440
|
+
function getWorktreeBranch(repoRoot, wtPath) {
|
|
441
|
+
try {
|
|
442
|
+
const worktrees = listWorktrees(repoRoot);
|
|
443
|
+
for (const wt of worktrees) {
|
|
444
|
+
if (wt.path === wtPath) return wt.branch;
|
|
445
|
+
}
|
|
446
|
+
return null;
|
|
447
|
+
} catch {
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
export {
|
|
453
|
+
discoverRepoPaths,
|
|
454
|
+
sweepWorktrees,
|
|
455
|
+
cleanupAgentWorktree
|
|
456
|
+
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// src/lib/retrieval-health.ts
|
|
2
|
+
async function getRetrievalHealth() {
|
|
3
|
+
let embedDaemon = "unavailable";
|
|
4
|
+
try {
|
|
5
|
+
const { isDaemonAlive } = await import("./mcp-health-WDOB6XUB.js");
|
|
6
|
+
const { alive } = isDaemonAlive();
|
|
7
|
+
if (alive) {
|
|
8
|
+
try {
|
|
9
|
+
const { pingDaemon } = await import("./lib/exe-daemon-client.js");
|
|
10
|
+
const health = await pingDaemon();
|
|
11
|
+
if (health) {
|
|
12
|
+
const embeddingField = health.embedding;
|
|
13
|
+
if (embeddingField === "ok") {
|
|
14
|
+
embedDaemon = "running";
|
|
15
|
+
} else if (embeddingField === "disabled") {
|
|
16
|
+
embedDaemon = "disabled";
|
|
17
|
+
} else {
|
|
18
|
+
embedDaemon = "stopped";
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
embedDaemon = "stopped";
|
|
22
|
+
}
|
|
23
|
+
} catch {
|
|
24
|
+
embedDaemon = "stopped";
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
embedDaemon = "unavailable";
|
|
28
|
+
}
|
|
29
|
+
} catch {
|
|
30
|
+
embedDaemon = "unavailable";
|
|
31
|
+
}
|
|
32
|
+
let configuredSearchMode = "hybrid";
|
|
33
|
+
let selfQueryRouterEnabled = true;
|
|
34
|
+
try {
|
|
35
|
+
const { loadConfigSync } = await import("./lib/config.js");
|
|
36
|
+
const cfg = loadConfigSync();
|
|
37
|
+
configuredSearchMode = cfg.searchMode ?? "hybrid";
|
|
38
|
+
selfQueryRouterEnabled = cfg.selfQueryRouter ?? true;
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
let actualSearchMode;
|
|
42
|
+
if (configuredSearchMode === "fts") {
|
|
43
|
+
actualSearchMode = "fts+graph";
|
|
44
|
+
} else if (embedDaemon === "running") {
|
|
45
|
+
actualSearchMode = "hybrid (vector+fts+graph)";
|
|
46
|
+
} else {
|
|
47
|
+
actualSearchMode = "fts+graph (degraded from hybrid)";
|
|
48
|
+
}
|
|
49
|
+
let queryRouter;
|
|
50
|
+
if (!selfQueryRouterEnabled) {
|
|
51
|
+
queryRouter = "disabled";
|
|
52
|
+
} else if (embedDaemon === "running" || embedDaemon === "disabled") {
|
|
53
|
+
queryRouter = process.env.ANTHROPIC_API_KEY ? "active" : "fallback";
|
|
54
|
+
} else {
|
|
55
|
+
queryRouter = "fallback";
|
|
56
|
+
}
|
|
57
|
+
let totalMemories = 0;
|
|
58
|
+
let memoriesWithVectors = 0;
|
|
59
|
+
let entities = 0;
|
|
60
|
+
let relationships = 0;
|
|
61
|
+
try {
|
|
62
|
+
const { getClient } = await import("./lib/database.js");
|
|
63
|
+
const client = getClient();
|
|
64
|
+
const [totalRes, vectorRes] = await Promise.all([
|
|
65
|
+
client.execute("SELECT COUNT(*) as cnt FROM memories WHERE status IS NULL OR status != 'deleted'"),
|
|
66
|
+
client.execute("SELECT COUNT(*) as cnt FROM memories WHERE vector IS NOT NULL AND (status IS NULL OR status != 'deleted')")
|
|
67
|
+
]);
|
|
68
|
+
totalMemories = Number(totalRes.rows[0]?.cnt ?? 0);
|
|
69
|
+
memoriesWithVectors = Number(vectorRes.rows[0]?.cnt ?? 0);
|
|
70
|
+
try {
|
|
71
|
+
const { getGraphStats } = await import("./graph-query-AP5R6ZHO.js");
|
|
72
|
+
const stats = await getGraphStats(client);
|
|
73
|
+
entities = stats.entities;
|
|
74
|
+
relationships = stats.relationships;
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
const staleCount = totalMemories - memoriesWithVectors;
|
|
80
|
+
const coveragePct = totalMemories > 0 ? Math.round(memoriesWithVectors / totalMemories * 100) : null;
|
|
81
|
+
let dbRestore = { hasEvents: false, count: 0, last: null, quarantineFiles: 0 };
|
|
82
|
+
try {
|
|
83
|
+
const { getDbRestoreHealth } = await import("./db-restore-events-GNZS42YO.js");
|
|
84
|
+
dbRestore = getDbRestoreHealth();
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
87
|
+
const summary = {
|
|
88
|
+
embedDaemon,
|
|
89
|
+
searchMode: {
|
|
90
|
+
configured: configuredSearchMode,
|
|
91
|
+
actual: actualSearchMode
|
|
92
|
+
},
|
|
93
|
+
queryRouter,
|
|
94
|
+
vectorBackfill: {
|
|
95
|
+
totalMemories,
|
|
96
|
+
memoriesWithVectors,
|
|
97
|
+
staleCount,
|
|
98
|
+
coveragePct
|
|
99
|
+
},
|
|
100
|
+
graph: {
|
|
101
|
+
entities,
|
|
102
|
+
relationships
|
|
103
|
+
},
|
|
104
|
+
dbRestore
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
...summary,
|
|
108
|
+
degradations: computeDegradations(summary)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function computeDegradations(h) {
|
|
112
|
+
const out = [];
|
|
113
|
+
const isRuntimeDowngrade = h.searchMode.actual.includes("degraded");
|
|
114
|
+
if (isRuntimeDowngrade) {
|
|
115
|
+
out.push({
|
|
116
|
+
code: "retrieval_downgraded",
|
|
117
|
+
severity: "warn",
|
|
118
|
+
message: `Retrieval running as "${h.searchMode.actual}" (configured: "${h.searchMode.configured}")`,
|
|
119
|
+
remediation: h.embedDaemon === "disabled" ? "Embeddings are disabled. Enable them in settings if you want vector retrieval." : "Embed daemon is not running. Start the daemon / embed worker to restore hybrid retrieval."
|
|
120
|
+
});
|
|
121
|
+
} else if (h.searchMode.configured === "fts") {
|
|
122
|
+
out.push({
|
|
123
|
+
code: "embeddings_off",
|
|
124
|
+
severity: "info",
|
|
125
|
+
message: "Search mode is FTS-only by configuration (keyword + graph; no vector retrieval)",
|
|
126
|
+
remediation: 'Switch searchMode to "hybrid" in settings to enable vector retrieval.'
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (h.queryRouter === "fallback") {
|
|
130
|
+
out.push({
|
|
131
|
+
code: "query_router_fallback",
|
|
132
|
+
severity: "warn",
|
|
133
|
+
message: "Self-query-router using rule-based fallback (no LLM routing)",
|
|
134
|
+
remediation: "Set ANTHROPIC_API_KEY (and ensure the embed daemon is reachable) to enable LLM-based query routing."
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (h.dbRestore.hasEvents) {
|
|
138
|
+
const last = h.dbRestore.last;
|
|
139
|
+
if (last && (last.kind === "restore-failed" || last.kind === "zeroed-no-wal")) {
|
|
140
|
+
out.push({
|
|
141
|
+
code: "db_corruption_unrecovered",
|
|
142
|
+
severity: "critical",
|
|
143
|
+
message: `DB corruption could not be auto-recovered: ${last.detail ?? last.kind} (${last.at})`,
|
|
144
|
+
remediation: "Restore from a known-good backup (`exe-os cloud reupload` or restore a backup); preserved corrupt DB is in ~/.exe-os/."
|
|
145
|
+
});
|
|
146
|
+
} else if (last && (last.kind === "auto-restore" || last.kind === "wal-recovery")) {
|
|
147
|
+
out.push({
|
|
148
|
+
code: "db_auto_restored",
|
|
149
|
+
severity: "warn",
|
|
150
|
+
message: last.kind === "auto-restore" ? `DB was auto-restored from backup${last.restoredFrom ? ` (${last.restoredFrom})` : ""}${typeof last.hoursLost === "number" ? `, ~${last.hoursLost}h data-loss window` : ""} at ${last.at}` : `DB was reconstructed from WAL after a 0-byte corruption at ${last.at}`,
|
|
151
|
+
remediation: "Recent memories may be missing. Run a cloud sync to reconcile and verify recent data."
|
|
152
|
+
});
|
|
153
|
+
} else if (h.dbRestore.quarantineFiles > 0) {
|
|
154
|
+
out.push({
|
|
155
|
+
code: "db_corruption_quarantine",
|
|
156
|
+
severity: "warn",
|
|
157
|
+
message: `${h.dbRestore.quarantineFiles} quarantined corrupt DB file(s) present in ~/.exe-os/ (prior corruption event)`,
|
|
158
|
+
remediation: "Verify data integrity; remove quarantined .corrupt-*/.zeroed-* files once you've confirmed no data is needed."
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
var SEVERITY_ICON = {
|
|
165
|
+
info: "\u2139\uFE0F",
|
|
166
|
+
// ℹ️
|
|
167
|
+
warn: "\u{1F7E0}",
|
|
168
|
+
// 🟠
|
|
169
|
+
critical: "\u{1F534}"
|
|
170
|
+
// 🔴
|
|
171
|
+
};
|
|
172
|
+
function formatDegradations(degradations, heading = "Degradations") {
|
|
173
|
+
const lines = [];
|
|
174
|
+
lines.push(`### ${heading}`);
|
|
175
|
+
if (degradations.length === 0) {
|
|
176
|
+
lines.push("\u{1F7E2} None \u2014 all retrieval and storage subsystems nominal.");
|
|
177
|
+
return lines.join("\n");
|
|
178
|
+
}
|
|
179
|
+
const order = { critical: 0, warn: 1, info: 2 };
|
|
180
|
+
const sorted = [...degradations].sort((a, b) => order[a.severity] - order[b.severity]);
|
|
181
|
+
for (const d of sorted) {
|
|
182
|
+
lines.push(`${SEVERITY_ICON[d.severity]} ${d.message}`);
|
|
183
|
+
if (d.remediation) lines.push(` \u2192 ${d.remediation}`);
|
|
184
|
+
}
|
|
185
|
+
return lines.join("\n");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export {
|
|
189
|
+
getRetrievalHealth,
|
|
190
|
+
computeDegradations,
|
|
191
|
+
formatDegradations
|
|
192
|
+
};
|