@askexenow/exe-os 0.9.237 → 0.9.238

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/deploy/stack-manifests/v0.9.json +53 -1
  2. package/dist/bin/bulk-sync-postgres.js +1 -1
  3. package/dist/bin/cli.js +3 -3
  4. package/dist/bin/exe-cloud.js +1 -1
  5. package/dist/bin/exe-forget.js +1 -1
  6. package/dist/bin/exe-search.js +1 -1
  7. package/dist/bin/exe-settings.js +1 -1
  8. package/dist/bin/setup.js +1 -1
  9. package/dist/{catchup-brief-RZF7HEYB.js → catchup-brief-ZB2OR45O.js} +1 -1
  10. package/dist/{chunk-627ZOPZQ.js → chunk-C7BVANSU.js} +1 -0
  11. package/dist/{chunk-ENQIADYO.js → chunk-EPLBVWIM.js} +5 -5
  12. package/dist/{chunk-KWH6H64R.js → chunk-NBV23TC4.js} +13 -6
  13. package/dist/{chunk-QXKWSRUZ.js → chunk-U3XMIHPD.js} +3 -3
  14. package/dist/dreaming-UF4LPNLV.js +31 -0
  15. package/dist/{exe-snapshot-RKMMV52M.js → exe-snapshot-LBM3LL3I.js} +19 -1
  16. package/dist/hooks/error-recall.js +1 -1
  17. package/dist/hooks/manifest.json +5 -5
  18. package/dist/hooks/prompt-submit.js +1 -1
  19. package/dist/hooks/session-end.js +1 -1
  20. package/dist/hooks/session-start.js +1 -1
  21. package/dist/lib/cloud-sync.js +3 -1
  22. package/dist/lib/exe-daemon.js +315 -40
  23. package/dist/lib/hybrid-search.js +1 -1
  24. package/dist/mcp/register-tools.js +5 -5
  25. package/dist/mcp/server.js +5 -5
  26. package/dist/{reranker-Y2RHN7TX.js → reranker-T4A2M7K2.js} +1 -1
  27. package/dist/{setup-wizard-ZMYO7QKZ.js → setup-wizard-GQYG36KS.js} +1 -1
  28. package/dist/{telemetry-upload-NXRMUNSW.js → telemetry-upload-H6BU6QF7.js} +1 -1
  29. package/package.json +1 -1
  30. package/release-notes.json +105 -202
  31. package/dist/dreaming-WIBDVAED.js +0 -12
  32. /package/dist/{chunk-3SVQ5REQ.js → chunk-EAIZLNLP.js} +0 -0
  33. /package/dist/{chunk-CGTWFEXX.js → chunk-M5TK7JET.js} +0 -0
  34. /package/dist/{exe-key-EAQDAUPT.js → exe-key-ZVKBTZVI.js} +0 -0
@@ -544,6 +544,70 @@ async function getTmuxSessionsAsync() {
544
544
  }
545
545
  var _paneCacheMap = /* @__PURE__ */ new Map();
546
546
  var PANE_CACHE_TTL_MS = 1e4;
547
+ var _reflectionImportFailed = false;
548
+ var _intercomDedupCompleted = false;
549
+ var _sharedPaneCache = null;
550
+ var _sharedAliveSessions = null;
551
+ var _sharedAgentSessions = null;
552
+ var _sharedCacheTimestamp = 0;
553
+ var SHARED_CACHE_TTL_MS = 15e3;
554
+ async function refreshSharedOrchestrationCaches() {
555
+ const sessions = (await getTmuxSessionsAsync()).filter((s) => s.includes("-"));
556
+ const [paneCache, aliveSessions] = await Promise.all([
557
+ batchCapturePanes(sessions, 30),
558
+ batchPaneAlive(sessions)
559
+ ]);
560
+ _sharedAgentSessions = sessions;
561
+ _sharedPaneCache = paneCache;
562
+ _sharedAliveSessions = aliveSessions;
563
+ _sharedCacheTimestamp = Date.now();
564
+ return { sessions, paneCache, aliveSessions };
565
+ }
566
+ async function getSharedOrchestrationCaches() {
567
+ if (_sharedAgentSessions && _sharedPaneCache && _sharedAliveSessions && Date.now() - _sharedCacheTimestamp < SHARED_CACHE_TTL_MS) {
568
+ return {
569
+ sessions: _sharedAgentSessions,
570
+ paneCache: _sharedPaneCache,
571
+ aliveSessions: _sharedAliveSessions
572
+ };
573
+ }
574
+ return refreshSharedOrchestrationCaches();
575
+ }
576
+ var _orchestrationSteps = {
577
+ reviewPolling: null,
578
+ taskEnforcement: null,
579
+ idleKill: null,
580
+ apiWatchdog: null
581
+ };
582
+ var _orchestrationBusy = false;
583
+ var _orchestrationTickCount = 0;
584
+ async function runOrchestrationTick() {
585
+ if (_orchestrationBusy) return;
586
+ _orchestrationBusy = true;
587
+ _orchestrationTickCount++;
588
+ try {
589
+ await refreshSharedOrchestrationCaches();
590
+ await yieldToEventLoop();
591
+ if (_orchestrationSteps.reviewPolling) {
592
+ await _orchestrationSteps.reviewPolling();
593
+ await yieldToEventLoop();
594
+ }
595
+ if (_orchestrationSteps.taskEnforcement) {
596
+ await _orchestrationSteps.taskEnforcement();
597
+ await yieldToEventLoop();
598
+ }
599
+ if (_orchestrationSteps.idleKill) {
600
+ await _orchestrationSteps.idleKill();
601
+ await yieldToEventLoop();
602
+ }
603
+ if (_orchestrationSteps.apiWatchdog && _orchestrationTickCount % 2 === 0) {
604
+ await _orchestrationSteps.apiWatchdog();
605
+ await yieldToEventLoop();
606
+ }
607
+ } finally {
608
+ _orchestrationBusy = false;
609
+ }
610
+ }
547
611
  var execFileAsync = promisify(execFileNode);
548
612
  async function capturePaneAsync(session, lines = 20) {
549
613
  const cacheKey = `${session}:${lines}`;
@@ -1776,6 +1840,8 @@ async function startMcpHttpServer() {
1776
1840
  sessionLastSeen.delete(sid);
1777
1841
  sessionOwnerKeys.delete(sid);
1778
1842
  const details = sessionDetails.get(sid);
1843
+ process.stderr.write(`[exed] MCP session closed: ${sid.slice(0, 8)}\u2026 agent=${details?.agentId ?? "?"} reason=${reason} remaining=${transports.size}
1844
+ `);
1779
1845
  sessionDetails.delete(sid);
1780
1846
  const sessionMcp = sessionServers.get(sid);
1781
1847
  sessionServers.delete(sid);
@@ -1883,6 +1949,7 @@ async function startMcpHttpServer() {
1883
1949
  return;
1884
1950
  }
1885
1951
  process.stderr.write("[exed] MCP HTTP: DB ready\n");
1952
+ _storeInitialized = true;
1886
1953
  const { initLicenseGate, getCachedLicenseGate } = await import("../license-gate-XJDIL6OZ.js");
1887
1954
  const gateResult = await initLicenseGate();
1888
1955
  if (!gateResult.hasKey) {
@@ -2315,6 +2382,8 @@ async function startMcpHttpServer() {
2315
2382
  sessionDetails.set(sid, details);
2316
2383
  sessionOwnerKeys.set(sid, mcpSessionOwnerKey2(details));
2317
2384
  sessionServers.set(sid, sessionMcp);
2385
+ process.stderr.write(`[exed] MCP session opened: ${sid.slice(0, 8)}\u2026 agent=${agentId} role=${agentRole} sessions=${transports.size}
2386
+ `);
2318
2387
  recordMcpHttpEvent({
2319
2388
  level: "info",
2320
2389
  message: "session_initialized",
@@ -2590,7 +2659,14 @@ async function ensureStoreForPolling() {
2590
2659
  const { getMasterKey } = await import("./keychain.js");
2591
2660
  const config = await loadConfig();
2592
2661
  const masterKey = await getMasterKey();
2593
- if (!masterKey) throw new Error("No encryption key");
2662
+ if (!masterKey) {
2663
+ if (process.env.DATABASE_URL && process.env.EXE_CLOUD_SYNC_TO_POSTGRES) {
2664
+ process.stderr.write("[exed] No encryption key \u2014 running in PostgreSQL-only mode (VPS)\n");
2665
+ _storeInitialized = true;
2666
+ return true;
2667
+ }
2668
+ throw new Error("No encryption key");
2669
+ }
2594
2670
  await initDatabase({ dbPath: config.dbPath, encryptionKey: masterKey.toString("hex") });
2595
2671
  }
2596
2672
  _storeInitialized = true;
@@ -2618,6 +2694,8 @@ async function startReviewPolling() {
2618
2694
  try {
2619
2695
  const { getClient } = await import("./database.js");
2620
2696
  const deps = polling.createRealDeps(getClient);
2697
+ const { sessions: sharedSessions } = await getSharedOrchestrationCaches();
2698
+ deps.listTmuxSessions = () => sharedSessions;
2621
2699
  const sent = await polling.pollPendingReviews(deps, state);
2622
2700
  if (sent.length > 0) acted("review_polling");
2623
2701
  for (const s of sent) {
@@ -2640,9 +2718,8 @@ async function startReviewPolling() {
2640
2718
  `);
2641
2719
  }
2642
2720
  });
2643
- const timer = setInterval(() => void tick(), REVIEW_POLL_INTERVAL_MS);
2644
- timer.unref();
2645
- process.stderr.write(`[exed] Review polling started (every ${REVIEW_POLL_INTERVAL_MS / 6e4}m)
2721
+ _orchestrationSteps.reviewPolling = tick;
2722
+ process.stderr.write(`[exed] Review polling registered (orchestration tick)
2646
2723
  `);
2647
2724
  }
2648
2725
  var SESSION_TTL_INTERVAL_MS = 5 * 60 * 1e3;
@@ -2667,7 +2744,6 @@ function startSessionTTL() {
2667
2744
  `);
2668
2745
  }
2669
2746
  var COO_RESTART_COOLDOWN_MS = 5 * 6e4;
2670
- var IDLE_KILL_INTERVAL_MS = 30 * 1e3;
2671
2747
  var _idleTickCounts = /* @__PURE__ */ new Map();
2672
2748
  function startIdleKill() {
2673
2749
  const tick = async () => traceDaemonTimer("idle_kill", async () => {
@@ -2702,11 +2778,7 @@ function startIdleKill() {
2702
2778
  if (!cfg) return;
2703
2779
  const { getClient } = await import("./database.js");
2704
2780
  const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-P34RDHTM.js");
2705
- const liveSessions = (await getTmuxSessionsAsync()).filter((s) => s.includes("-"));
2706
- const [paneCache, aliveSessions] = await Promise.all([
2707
- batchCapturePanes(liveSessions, 5),
2708
- batchPaneAlive(liveSessions)
2709
- ]);
2781
+ const { sessions: liveSessions, paneCache, aliveSessions } = await getSharedOrchestrationCaches();
2710
2782
  const realDeps = createIdleKillRealDeps(
2711
2783
  getClient,
2712
2784
  cfg.sessionLifecycle.idleKillIntercomAckWindowMs
@@ -2734,9 +2806,8 @@ function startIdleKill() {
2734
2806
  `);
2735
2807
  }
2736
2808
  });
2737
- const timer = setInterval(() => void tick(), IDLE_KILL_INTERVAL_MS);
2738
- timer.unref();
2739
- process.stderr.write(`[exed] Idle kill started (every ${IDLE_KILL_INTERVAL_MS / 1e3}s)
2809
+ _orchestrationSteps.idleKill = tick;
2810
+ process.stderr.write(`[exed] Idle kill registered (orchestration tick)
2740
2811
  `);
2741
2812
  }
2742
2813
  function startConsolidation() {
@@ -3008,6 +3079,190 @@ function startGraphExtraction() {
3008
3079
  process.stderr.write(`[exed] GraphRAG extraction started (every ${SKILL_SWEEP_INTERVAL_MS / 36e5}h)
3009
3080
  `);
3010
3081
  }
3082
+ var GRAPH_PG_SYNC_INTERVAL_MS = 5 * 60 * 1e3;
3083
+ var _graphPgSyncInFlight = false;
3084
+ var _graphPgLastSyncedEntities = "";
3085
+ var _graphPgLastSyncedRelationships = "";
3086
+ var _graphPgLastSyncedEmCount = 0;
3087
+ function startGraphPgSync() {
3088
+ if (!process.env.DATABASE_URL || !process.env.EXE_CLOUD_SYNC_TO_POSTGRES) return;
3089
+ const tick = async () => {
3090
+ if (_graphPgSyncInFlight) return;
3091
+ _graphPgSyncInFlight = true;
3092
+ try {
3093
+ let toUuid2 = function(id) {
3094
+ const hex = String(id).replace(/-/g, "");
3095
+ if (hex.length >= 32) return String(id);
3096
+ const padded = hex.padEnd(32, "0");
3097
+ return `${padded.slice(0, 8)}-${padded.slice(8, 12)}-${padded.slice(12, 16)}-${padded.slice(16, 20)}-${padded.slice(20, 32)}`;
3098
+ };
3099
+ var toUuid = toUuid2;
3100
+ if (!await ensureStoreForPolling()) {
3101
+ process.stderr.write("[exed] Graph\u2192PG sync: ensureStoreForPolling returned false, skipping\n");
3102
+ return;
3103
+ }
3104
+ const { getClient } = await import("./database.js");
3105
+ const client = getClient();
3106
+ const isFirstRun = !_graphPgLastSyncedEntities;
3107
+ const entities = _graphPgLastSyncedEntities ? (await client.execute({ sql: "SELECT id, name, type, first_seen, last_seen, properties FROM entities WHERE last_seen > ?", args: [_graphPgLastSyncedEntities] })).rows : (await client.execute("SELECT id, name, type, first_seen, last_seen, properties FROM entities")).rows;
3108
+ await yieldToEventLoop();
3109
+ const relationships = _graphPgLastSyncedRelationships ? (await client.execute({ sql: "SELECT id, source_entity_id, target_entity_id, type, confidence, properties, timestamp FROM relationships WHERE timestamp > ?", args: [_graphPgLastSyncedRelationships] })).rows : (await client.execute("SELECT id, source_entity_id, target_entity_id, type, confidence, properties, timestamp FROM relationships")).rows;
3110
+ await yieldToEventLoop();
3111
+ const emCountResult = await client.execute("SELECT COUNT(*) as cnt FROM entity_memories");
3112
+ const currentEmCount = Number(emCountResult.rows[0]?.cnt ?? 0);
3113
+ const emCountChanged = currentEmCount !== _graphPgLastSyncedEmCount;
3114
+ let entityMemories = [];
3115
+ if (emCountChanged) {
3116
+ entityMemories = (await client.execute("SELECT entity_id, memory_id FROM entity_memories")).rows;
3117
+ }
3118
+ await yieldToEventLoop();
3119
+ if (entities.length === 0 && relationships.length === 0 && !emCountChanged) {
3120
+ if (!isFirstRun) {
3121
+ }
3122
+ return;
3123
+ }
3124
+ process.stderr.write(
3125
+ `[exed] Graph\u2192PG sync: ${isFirstRun ? "FULL" : "incremental"} \u2014 ${entities.length} entities, ${relationships.length} relationships, ${entityMemories.length} entity_memories
3126
+ `
3127
+ );
3128
+ const { loadPgClient } = await import("./cloud-sync.js");
3129
+ const pgPromise = loadPgClient();
3130
+ if (!pgPromise) return;
3131
+ const pg = await pgPromise;
3132
+ const S = "graph";
3133
+ const BATCH = 500;
3134
+ let entOk = 0;
3135
+ let relOk = 0;
3136
+ let emOk = 0;
3137
+ const esc = (v) => String(v ?? "").replace(/'/g, "''");
3138
+ const ts = (v) => {
3139
+ try {
3140
+ return v ? new Date(String(v)).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
3141
+ } catch {
3142
+ return (/* @__PURE__ */ new Date()).toISOString();
3143
+ }
3144
+ };
3145
+ for (let i = 0; i < entities.length; i += BATCH) {
3146
+ const batch = entities.slice(i, i + BATCH);
3147
+ const values = batch.map(
3148
+ (e) => `('${toUuid2(e.id)}', '${esc(e.name ?? "unknown")}', '${esc(e.type ?? "unknown")}', '${ts(e.first_seen)}'::timestamptz, '${ts(e.last_seen)}'::timestamptz, '${esc(e.properties ?? "{}")}'::jsonb)`
3149
+ ).join(",\n");
3150
+ try {
3151
+ await pg.$executeRawUnsafe(`
3152
+ INSERT INTO ${S}.entities (id, name, type, first_seen, last_seen, properties) VALUES ${values}
3153
+ ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, type = EXCLUDED.type,
3154
+ last_seen = EXCLUDED.last_seen, properties = EXCLUDED.properties`);
3155
+ entOk += batch.length;
3156
+ } catch {
3157
+ for (const e of batch) {
3158
+ try {
3159
+ await pg.$executeRawUnsafe(
3160
+ `INSERT INTO ${S}.entities (id, name, type, first_seen, last_seen, properties)
3161
+ VALUES ($1::uuid, $2, $3, $4::timestamptz, $5::timestamptz, $6::jsonb)
3162
+ ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, type = EXCLUDED.type,
3163
+ last_seen = EXCLUDED.last_seen, properties = EXCLUDED.properties`,
3164
+ toUuid2(e.id),
3165
+ String(e.name ?? "unknown"),
3166
+ String(e.type ?? "unknown"),
3167
+ ts(e.first_seen),
3168
+ ts(e.last_seen),
3169
+ String(e.properties ?? "{}")
3170
+ );
3171
+ entOk++;
3172
+ } catch {
3173
+ }
3174
+ }
3175
+ }
3176
+ await yieldToEventLoop();
3177
+ }
3178
+ for (let i = 0; i < relationships.length; i += BATCH) {
3179
+ const batch = relationships.slice(i, i + BATCH);
3180
+ const values = batch.map(
3181
+ (r) => `('${toUuid2(r.id)}', '${toUuid2(r.source_entity_id)}', '${toUuid2(r.target_entity_id)}', '${esc(r.type ?? "related_to")}', ${Number(r.confidence ?? 0.8)}, '${esc(r.properties ?? "{}")}'::jsonb)`
3182
+ ).join(",\n");
3183
+ try {
3184
+ await pg.$executeRawUnsafe(`
3185
+ INSERT INTO ${S}.relationships (id, source_entity_id, target_entity_id, type, confidence, properties) VALUES ${values}
3186
+ ON CONFLICT (id) DO UPDATE SET type = EXCLUDED.type, confidence = EXCLUDED.confidence`);
3187
+ relOk += batch.length;
3188
+ } catch {
3189
+ for (const r of batch) {
3190
+ try {
3191
+ await pg.$executeRawUnsafe(
3192
+ `INSERT INTO ${S}.relationships (id, source_entity_id, target_entity_id, type, confidence, properties)
3193
+ VALUES ($1::uuid, $2::uuid, $3::uuid, $4, $5, $6::jsonb)
3194
+ ON CONFLICT (id) DO UPDATE SET type = EXCLUDED.type, confidence = EXCLUDED.confidence`,
3195
+ toUuid2(r.id),
3196
+ toUuid2(r.source_entity_id),
3197
+ toUuid2(r.target_entity_id),
3198
+ String(r.type ?? "related_to"),
3199
+ Number(r.confidence ?? 0.8),
3200
+ String(r.properties ?? "{}")
3201
+ );
3202
+ relOk++;
3203
+ } catch {
3204
+ }
3205
+ }
3206
+ }
3207
+ await yieldToEventLoop();
3208
+ }
3209
+ for (let i = 0; i < entityMemories.length; i += BATCH) {
3210
+ const batch = entityMemories.slice(i, i + BATCH);
3211
+ const values = batch.map(
3212
+ (em) => `('${toUuid2(em.entity_id)}', '${toUuid2(em.memory_id)}')`
3213
+ ).join(",\n");
3214
+ try {
3215
+ await pg.$executeRawUnsafe(`
3216
+ INSERT INTO ${S}.entity_memories (entity_id, memory_id) VALUES ${values}
3217
+ ON CONFLICT DO NOTHING`);
3218
+ emOk += batch.length;
3219
+ } catch {
3220
+ for (const em of batch) {
3221
+ try {
3222
+ await pg.$executeRawUnsafe(
3223
+ `INSERT INTO ${S}.entity_memories (entity_id, memory_id) VALUES ($1::uuid, $2::uuid) ON CONFLICT DO NOTHING`,
3224
+ toUuid2(em.entity_id),
3225
+ toUuid2(em.memory_id)
3226
+ );
3227
+ emOk++;
3228
+ } catch {
3229
+ }
3230
+ }
3231
+ }
3232
+ await yieldToEventLoop();
3233
+ }
3234
+ if (entities.length > 0) {
3235
+ const maxLastSeen = entities.reduce((max, e) => {
3236
+ const ls = String(e.last_seen ?? "");
3237
+ return ls > max ? ls : max;
3238
+ }, _graphPgLastSyncedEntities);
3239
+ _graphPgLastSyncedEntities = maxLastSeen;
3240
+ }
3241
+ if (relationships.length > 0) {
3242
+ const maxTs = relationships.reduce((max, r) => {
3243
+ const t = String(r.timestamp ?? "");
3244
+ return t > max ? t : max;
3245
+ }, _graphPgLastSyncedRelationships);
3246
+ _graphPgLastSyncedRelationships = maxTs;
3247
+ }
3248
+ _graphPgLastSyncedEmCount = currentEmCount;
3249
+ process.stderr.write(
3250
+ `[exed] Graph\u2192PG sync: ${entOk}/${entities.length} entities, ${relOk}/${relationships.length} relationships, ${emOk}/${entityMemories.length} entity_memories
3251
+ `
3252
+ );
3253
+ } catch (err) {
3254
+ process.stderr.write(`[exed] Graph\u2192PG sync error: ${err instanceof Error ? err.message : String(err)}
3255
+ `);
3256
+ } finally {
3257
+ _graphPgSyncInFlight = false;
3258
+ }
3259
+ };
3260
+ const timer = setInterval(() => void tick(), GRAPH_PG_SYNC_INTERVAL_MS);
3261
+ timer.unref();
3262
+ setTimeout(() => void tick(), 6e4);
3263
+ process.stderr.write(`[exed] Graph\u2192PG sync started (every ${GRAPH_PG_SYNC_INTERVAL_MS / 6e4}m, first tick in 60s)
3264
+ `);
3265
+ }
3011
3266
  var AGENT_STATS_INTERVAL_MS = 60 * 1e3;
3012
3267
  var AGENT_STATS_PATH = path3.join(EXE_AI_DIR, "agent-stats.json");
3013
3268
  var _agentStatsInFlight = false;
@@ -3168,6 +3423,7 @@ var REFLECTION_SWEEP_INTERVAL_MS = 6 * 60 * 60 * 1e3;
3168
3423
  function startReflectionSweep() {
3169
3424
  const tick = async () => {
3170
3425
  fired("reflection_sweep");
3426
+ if (_reflectionImportFailed) return;
3171
3427
  if (!await ensureStoreForPolling()) return;
3172
3428
  try {
3173
3429
  const { getClient } = await import("./database.js");
@@ -3175,11 +3431,19 @@ function startReflectionSweep() {
3175
3431
  const agents = await client.execute(
3176
3432
  "SELECT DISTINCT agent_id FROM memory_cards WHERE active = 1 LIMIT 50"
3177
3433
  );
3434
+ let runReflection;
3435
+ try {
3436
+ ({ runReflection } = await import("../memory-reflection-5CVV2M3G.js"));
3437
+ } catch (importErr) {
3438
+ _reflectionImportFailed = true;
3439
+ process.stderr.write(`[exed] Reflection module unavailable (stale chunk hash?) \u2014 disabled until daemon restart: ${importErr instanceof Error ? importErr.message : String(importErr)}
3440
+ `);
3441
+ return;
3442
+ }
3178
3443
  let totalInsights = 0;
3179
3444
  for (const row of agents.rows) {
3180
3445
  const agentId = row.agent_id;
3181
3446
  try {
3182
- const { runReflection } = await import("../memory-reflection-5CVV2M3G.js");
3183
3447
  const result = await runReflection(agentId);
3184
3448
  totalInsights += result.contradictions + result.patterns + result.summaries;
3185
3449
  } catch (e) {
@@ -3552,7 +3816,6 @@ function startExternalRssWatchdog() {
3552
3816
  `);
3553
3817
  }
3554
3818
  }
3555
- var TASK_ENFORCEMENT_INTERVAL_MS = 6e4;
3556
3819
  function startTaskEnforcementScanner() {
3557
3820
  const tick = async () => traceDaemonTimer("task_enforcement", async () => {
3558
3821
  fired("task_enforcement");
@@ -3564,11 +3827,7 @@ function startTaskEnforcementScanner() {
3564
3827
  const { loadEmployeesSync } = await import("./employees.js");
3565
3828
  const { sessionScopeFilter } = await import("../task-scope-AYK6BVC7.js");
3566
3829
  const transport = getTransport();
3567
- const allSessions = (await getTmuxSessionsAsync()).filter((s) => s.includes("-"));
3568
- const [paneCache, aliveSessions] = await Promise.all([
3569
- batchCapturePanes(allSessions, 20),
3570
- batchPaneAlive(allSessions)
3571
- ]);
3830
+ const { sessions: allSessions, paneCache, aliveSessions } = await getSharedOrchestrationCaches();
3572
3831
  await yieldToEventLoop();
3573
3832
  const enforcementTransport = {
3574
3833
  listSessions: () => allSessions,
@@ -3594,9 +3853,8 @@ function startTaskEnforcementScanner() {
3594
3853
  );
3595
3854
  }
3596
3855
  });
3597
- const timer = setInterval(tick, TASK_ENFORCEMENT_INTERVAL_MS);
3598
- timer.unref();
3599
- process.stderr.write(`[exed] Task enforcement scanner started (${TASK_ENFORCEMENT_INTERVAL_MS / 1e3}s interval)
3856
+ _orchestrationSteps.taskEnforcement = tick;
3857
+ process.stderr.write(`[exed] Task enforcement scanner registered (orchestration tick)
3600
3858
  `);
3601
3859
  }
3602
3860
  function startRssWatchdog() {
@@ -3667,7 +3925,6 @@ function startRssWatchdog() {
3667
3925
  process.stderr.write(`[exed] RSS watchdog started (warn: ${(RSS_WARN_BYTES / 1024 ** 3).toFixed(1)} GB, restart: ${(RSS_RESTART_BYTES / 1024 ** 3).toFixed(1)} GB)
3668
3926
  `);
3669
3927
  }
3670
- var API_WATCHDOG_INTERVAL_MS = 3e4;
3671
3928
  var API_ERROR_PATTERNS = [
3672
3929
  /ConnectionRefused|ECONNREFUSED/i,
3673
3930
  /ETIMEDOUT|socket hang up/i,
@@ -3686,20 +3943,17 @@ function startApiWatchdog() {
3686
3943
  const cfg = await getCachedConfig();
3687
3944
  if (!cfg?.apiWatchdog?.enabled) return;
3688
3945
  const cooldownMs = (cfg.apiWatchdog.cooldownMinutes ?? 10) * 6e4;
3689
- const sessions = await getTmuxSessionsAsync();
3690
- if (sessions.length === 0) return;
3691
- const eligibleSessions = sessions.filter((session) => {
3692
- if (!session.includes("-")) return false;
3946
+ const { sessions: allSessions, paneCache } = await getSharedOrchestrationCaches();
3947
+ if (allSessions.length === 0) return;
3948
+ const eligibleSessions = allSessions.filter((session) => {
3693
3949
  const lastNudge = _apiWatchdogLastNudge.get(session) ?? 0;
3694
3950
  return Date.now() - lastNudge >= cooldownMs;
3695
3951
  });
3696
3952
  if (eligibleSessions.length === 0) return;
3697
- const paneResults = await Promise.allSettled(
3698
- eligibleSessions.map(async (session) => ({
3699
- session,
3700
- pane: await capturePaneAsync(session, 30)
3701
- }))
3702
- );
3953
+ const paneResults = eligibleSessions.map((session) => ({
3954
+ status: "fulfilled",
3955
+ value: { session, pane: paneCache.get(session) ?? "" }
3956
+ }));
3703
3957
  for (const result of paneResults) {
3704
3958
  if (result.status !== "fulfilled" || !result.value.pane) continue;
3705
3959
  const { session, pane } = result.value;
@@ -3750,7 +4004,7 @@ function startApiWatchdog() {
3750
4004
  }
3751
4005
  }
3752
4006
  }
3753
- const liveSessionSet = new Set(sessions);
4007
+ const liveSessionSet = new Set(allSessions);
3754
4008
  for (const key of _apiWatchdogLastNudge.keys()) {
3755
4009
  if (!liveSessionSet.has(key)) _apiWatchdogLastNudge.delete(key);
3756
4010
  }
@@ -3765,9 +4019,8 @@ function startApiWatchdog() {
3765
4019
  `);
3766
4020
  }
3767
4021
  });
3768
- const timer = setInterval(() => void tick(), API_WATCHDOG_INTERVAL_MS);
3769
- timer.unref();
3770
- process.stderr.write("[exed] API watchdog started (30s scan, 10m cooldown per session)\n");
4022
+ _orchestrationSteps.apiWatchdog = tick;
4023
+ process.stderr.write("[exed] API watchdog registered (orchestration tick)\n");
3771
4024
  }
3772
4025
  function startBackgroundJobGuardrails() {
3773
4026
  const tick = async () => traceDaemonTimer("background_job_guardrails", async () => {
@@ -4174,7 +4427,16 @@ try {
4174
4427
  startSessionTTL();
4175
4428
  startTaskEnforcementScanner();
4176
4429
  startApiWatchdog();
4430
+ startIdleKill();
4177
4431
  startRssWatchdog();
4432
+ setTimeout(() => {
4433
+ const orchestrationTimer = setInterval(
4434
+ () => void traceDaemonTimer("orchestration_tick", runOrchestrationTick),
4435
+ 6e4
4436
+ );
4437
+ orchestrationTimer.unref();
4438
+ process.stderr.write("[exed] Orchestration tick started (60s \u2014 review + enforcement + idle + watchdog)\n");
4439
+ }, 12e3);
4178
4440
  setTimeout(startWalCheckpoint, 5e3);
4179
4441
  setTimeout(() => void traceDaemonTimer("task_file_resync", async () => {
4180
4442
  try {
@@ -4245,7 +4507,6 @@ try {
4245
4507
  `);
4246
4508
  }
4247
4509
  }), 8e3);
4248
- setTimeout(startIdleKill, 1e4);
4249
4510
  setTimeout(() => {
4250
4511
  const BARRIER_POLL_INTERVAL_MS = 6e4;
4251
4512
  const barrierTick = async () => traceDaemonTimer("task_group_barriers", async () => {
@@ -4311,6 +4572,7 @@ try {
4311
4572
  setTimeout(startSkillSweep, 9e4);
4312
4573
  setTimeout(startSkillRefinement, 18e4);
4313
4574
  setTimeout(startGraphExtraction, 27e4);
4575
+ setTimeout(startGraphPgSync, 3e4);
4314
4576
  setTimeout(startReflectionSweep, 15e4);
4315
4577
  setTimeout(startConfidenceDecay, 18e4);
4316
4578
  setTimeout(startSoftDeletePurge, 21e4);
@@ -4322,7 +4584,14 @@ try {
4322
4584
  setTimeout(startZombieAgentReaper, 25e3);
4323
4585
  setTimeout(() => void traceDaemonTimer("intercom_dedup_cleanup", async () => {
4324
4586
  fired("intercom_dedup_cleanup");
4587
+ if (_intercomDedupCompleted) return;
4325
4588
  try {
4589
+ const { existsSync: markerExists } = await import("fs");
4590
+ const markerPath = path3.join(os2.homedir(), ".exe-os", ".intercom-dedup-done");
4591
+ if (markerExists(markerPath)) {
4592
+ _intercomDedupCompleted = true;
4593
+ return;
4594
+ }
4326
4595
  if (!await ensureStoreForPolling()) return;
4327
4596
  const { getClient } = await import("./database.js");
4328
4597
  const { deduplicateIntercomMemories } = await import("./consolidation.js");
@@ -4332,6 +4601,12 @@ try {
4332
4601
  process.stderr.write(`[exed] Intercom dedup: archived ${count} duplicate intercom memories
4333
4602
  `);
4334
4603
  }
4604
+ _intercomDedupCompleted = true;
4605
+ try {
4606
+ const { writeFileSync: writeFileSync3 } = await import("fs");
4607
+ writeFileSync3(markerPath, (/* @__PURE__ */ new Date()).toISOString(), "utf8");
4608
+ } catch {
4609
+ }
4335
4610
  } catch (err) {
4336
4611
  process.stderr.write(`[exed] Intercom dedup error: ${err instanceof Error ? err.message : String(err)}
4337
4612
  `);
@@ -4396,7 +4671,7 @@ try {
4396
4671
  const TELEMETRY_DAILY_MS = 24 * 60 * 60 * 1e3;
4397
4672
  const telemetryDaily = async () => {
4398
4673
  try {
4399
- const { sendTelemetry, isTelemetryEnabled } = await import("../telemetry-upload-NXRMUNSW.js");
4674
+ const { sendTelemetry, isTelemetryEnabled } = await import("../telemetry-upload-H6BU6QF7.js");
4400
4675
  if (!isTelemetryEnabled()) return;
4401
4676
  const { upstream } = await sendTelemetry(24);
4402
4677
  if (upstream.startsWith("sent")) {
@@ -5,7 +5,7 @@ import {
5
5
  recentRecords,
6
6
  rrfMerge,
7
7
  rrfMergeMulti
8
- } from "../chunk-QXKWSRUZ.js";
8
+ } from "../chunk-U3XMIHPD.js";
9
9
  import "../chunk-NQU2RTCP.js";
10
10
  import "../chunk-CHCA3ZM2.js";
11
11
  import "../chunk-IAPFFVYR.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  registerAllTools
3
- } from "../chunk-ENQIADYO.js";
3
+ } from "../chunk-EPLBVWIM.js";
4
4
  import "../chunk-COMWI7SO.js";
5
5
  import "../chunk-LUCHTCME.js";
6
- import "../chunk-3SVQ5REQ.js";
6
+ import "../chunk-EAIZLNLP.js";
7
7
  import "../chunk-KH5Y6RR4.js";
8
8
  import "../chunk-557C2IGL.js";
9
9
  import "../chunk-SNYDRHV3.js";
@@ -12,7 +12,7 @@ import "../chunk-7LIXU3TB.js";
12
12
  import "../chunk-JZMVLAZ2.js";
13
13
  import "../chunk-YGJTKLGM.js";
14
14
  import "../chunk-UZIJDYDA.js";
15
- import "../chunk-KWH6H64R.js";
15
+ import "../chunk-NBV23TC4.js";
16
16
  import "../chunk-CJEVAKKC.js";
17
17
  import "../chunk-JBUHOWIV.js";
18
18
  import "../chunk-MBHZDXGN.js";
@@ -44,7 +44,7 @@ import "../chunk-VI2FJY2M.js";
44
44
  import "../chunk-YUQ7GGAL.js";
45
45
  import "../chunk-PQBANSH6.js";
46
46
  import "../chunk-K77WC6HA.js";
47
- import "../chunk-627ZOPZQ.js";
47
+ import "../chunk-C7BVANSU.js";
48
48
  import "../chunk-RX2KGETT.js";
49
49
  import "../chunk-X2Z5GT3V.js";
50
50
  import "../chunk-ES5JM6V2.js";
@@ -58,7 +58,7 @@ import "../chunk-P2JDWX67.js";
58
58
  import "../chunk-UISUGXJU.js";
59
59
  import "../chunk-VHKL4S4T.js";
60
60
  import "../chunk-JL3K5OTS.js";
61
- import "../chunk-QXKWSRUZ.js";
61
+ import "../chunk-U3XMIHPD.js";
62
62
  import "../chunk-NQU2RTCP.js";
63
63
  import "../chunk-CHCA3ZM2.js";
64
64
  import "../chunk-IAPFFVYR.js";
@@ -3,10 +3,10 @@ import {
3
3
  } from "../chunk-V4TZI6EO.js";
4
4
  import {
5
5
  registerAllTools
6
- } from "../chunk-ENQIADYO.js";
6
+ } from "../chunk-EPLBVWIM.js";
7
7
  import "../chunk-COMWI7SO.js";
8
8
  import "../chunk-LUCHTCME.js";
9
- import "../chunk-3SVQ5REQ.js";
9
+ import "../chunk-EAIZLNLP.js";
10
10
  import "../chunk-KH5Y6RR4.js";
11
11
  import "../chunk-557C2IGL.js";
12
12
  import "../chunk-SNYDRHV3.js";
@@ -20,7 +20,7 @@ import {
20
20
  wrapServerWithTelemetry
21
21
  } from "../chunk-YGJTKLGM.js";
22
22
  import "../chunk-UZIJDYDA.js";
23
- import "../chunk-KWH6H64R.js";
23
+ import "../chunk-NBV23TC4.js";
24
24
  import "../chunk-CJEVAKKC.js";
25
25
  import "../chunk-JBUHOWIV.js";
26
26
  import "../chunk-MBHZDXGN.js";
@@ -52,7 +52,7 @@ import "../chunk-VI2FJY2M.js";
52
52
  import "../chunk-YUQ7GGAL.js";
53
53
  import "../chunk-PQBANSH6.js";
54
54
  import "../chunk-K77WC6HA.js";
55
- import "../chunk-627ZOPZQ.js";
55
+ import "../chunk-C7BVANSU.js";
56
56
  import "../chunk-RX2KGETT.js";
57
57
  import "../chunk-X2Z5GT3V.js";
58
58
  import "../chunk-ES5JM6V2.js";
@@ -68,7 +68,7 @@ import "../chunk-P2JDWX67.js";
68
68
  import "../chunk-UISUGXJU.js";
69
69
  import "../chunk-VHKL4S4T.js";
70
70
  import "../chunk-JL3K5OTS.js";
71
- import "../chunk-QXKWSRUZ.js";
71
+ import "../chunk-U3XMIHPD.js";
72
72
  import {
73
73
  disposeStore,
74
74
  initStore
@@ -5,7 +5,7 @@ import {
5
5
  rerank,
6
6
  rerankWithContext,
7
7
  rerankWithScores
8
- } from "./chunk-3SVQ5REQ.js";
8
+ } from "./chunk-EAIZLNLP.js";
9
9
  import "./chunk-TRZ5KA2R.js";
10
10
  import "./chunk-LYH5HE24.js";
11
11
  import "./chunk-MLKGABMK.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  runSetupWizard,
3
3
  validateModel
4
- } from "./chunk-CGTWFEXX.js";
4
+ } from "./chunk-M5TK7JET.js";
5
5
  import "./chunk-KDJRFJDL.js";
6
6
  import "./chunk-TRZ5KA2R.js";
7
7
  import "./chunk-LYH5HE24.js";
@@ -397,7 +397,7 @@ async function buildTelemetryPayload(sinceHours = 24) {
397
397
  }
398
398
  let calibration;
399
399
  try {
400
- const { DreamingEngine } = await import("./dreaming-WIBDVAED.js");
400
+ const { DreamingEngine } = await import("./dreaming-UF4LPNLV.js");
401
401
  const engine = new DreamingEngine();
402
402
  const cal = await engine.computeCalibration("*", sinceHours);
403
403
  if (cal.assertions.total > 0 || cal.estimation.total > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.237",
3
+ "version": "0.9.238",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",