@askexenow/exe-os 0.9.102 → 0.9.104

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 (92) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +334 -100
  2. package/dist/bin/agentic-reflection-backfill.js +328 -97
  3. package/dist/bin/agentic-semantic-label.js +328 -97
  4. package/dist/bin/backfill-conversations.js +332 -97
  5. package/dist/bin/backfill-responses.js +332 -97
  6. package/dist/bin/backfill-vectors.js +337 -106
  7. package/dist/bin/bulk-sync-postgres.js +335 -101
  8. package/dist/bin/cleanup-stale-review-tasks.js +356 -108
  9. package/dist/bin/cli.js +653 -405
  10. package/dist/bin/exe-agent.js +21 -3
  11. package/dist/bin/exe-assign.js +338 -94
  12. package/dist/bin/exe-boot.js +472 -239
  13. package/dist/bin/exe-call.js +22 -5
  14. package/dist/bin/exe-cloud.js +404 -158
  15. package/dist/bin/exe-dispatch.js +390 -142
  16. package/dist/bin/exe-doctor.js +349 -103
  17. package/dist/bin/exe-export-behaviors.js +351 -105
  18. package/dist/bin/exe-forget.js +352 -103
  19. package/dist/bin/exe-gateway.js +420 -172
  20. package/dist/bin/exe-heartbeat.js +361 -113
  21. package/dist/bin/exe-kill.js +344 -98
  22. package/dist/bin/exe-launch-agent.js +375 -129
  23. package/dist/bin/exe-new-employee.js +83 -67
  24. package/dist/bin/exe-pending-messages.js +356 -108
  25. package/dist/bin/exe-pending-notifications.js +358 -110
  26. package/dist/bin/exe-pending-reviews.js +359 -111
  27. package/dist/bin/exe-rename.js +354 -108
  28. package/dist/bin/exe-review.js +343 -97
  29. package/dist/bin/exe-search.js +363 -113
  30. package/dist/bin/exe-session-cleanup.js +403 -155
  31. package/dist/bin/exe-settings.js +14 -9
  32. package/dist/bin/exe-start-codex.js +365 -131
  33. package/dist/bin/exe-start-opencode.js +359 -125
  34. package/dist/bin/exe-status.js +356 -108
  35. package/dist/bin/exe-team.js +343 -97
  36. package/dist/bin/git-sweep.js +390 -142
  37. package/dist/bin/graph-backfill.js +334 -100
  38. package/dist/bin/graph-export.js +346 -100
  39. package/dist/bin/install.js +1 -0
  40. package/dist/bin/intercom-check.js +403 -155
  41. package/dist/bin/pre-publish.js +12 -0
  42. package/dist/bin/scan-tasks.js +393 -145
  43. package/dist/bin/setup.js +331 -159
  44. package/dist/bin/shard-migrate.js +328 -94
  45. package/dist/gateway/index.js +406 -158
  46. package/dist/hooks/bug-report-worker.js +396 -148
  47. package/dist/hooks/codex-stop-task-finalizer.js +374 -126
  48. package/dist/hooks/commit-complete.js +390 -142
  49. package/dist/hooks/error-recall.js +365 -115
  50. package/dist/hooks/ingest.js +357 -111
  51. package/dist/hooks/instructions-loaded.js +351 -105
  52. package/dist/hooks/notification.js +343 -97
  53. package/dist/hooks/post-compact.js +358 -110
  54. package/dist/hooks/post-tool-combined.js +384 -132
  55. package/dist/hooks/pre-compact.js +391 -143
  56. package/dist/hooks/pre-tool-use.js +362 -114
  57. package/dist/hooks/prompt-submit.js +422 -170
  58. package/dist/hooks/session-end.js +393 -145
  59. package/dist/hooks/session-start.js +390 -138
  60. package/dist/hooks/stop.js +361 -113
  61. package/dist/hooks/subagent-stop.js +354 -106
  62. package/dist/hooks/summary-worker.js +418 -185
  63. package/dist/index.js +400 -152
  64. package/dist/lib/cloud-sync.js +291 -131
  65. package/dist/lib/consolidation.js +8 -2
  66. package/dist/lib/database.js +233 -73
  67. package/dist/lib/db.js +233 -73
  68. package/dist/lib/device-registry.js +237 -77
  69. package/dist/lib/employee-templates.js +19 -1
  70. package/dist/lib/exe-daemon.js +705 -409
  71. package/dist/lib/hybrid-search.js +363 -113
  72. package/dist/lib/identity.js +9 -5
  73. package/dist/lib/messaging.js +26 -20
  74. package/dist/lib/reminders.js +5 -1
  75. package/dist/lib/schedules.js +320 -89
  76. package/dist/lib/skill-learning.js +28 -24
  77. package/dist/lib/store.js +342 -96
  78. package/dist/lib/tasks.js +82 -76
  79. package/dist/lib/tmux-routing.js +74 -68
  80. package/dist/lib/token-spend.js +5 -1
  81. package/dist/mcp/server.js +628 -355
  82. package/dist/mcp/tools/complete-reminder.js +5 -1
  83. package/dist/mcp/tools/create-reminder.js +5 -1
  84. package/dist/mcp/tools/create-task.js +89 -83
  85. package/dist/mcp/tools/deactivate-behavior.js +7 -3
  86. package/dist/mcp/tools/list-reminders.js +5 -1
  87. package/dist/mcp/tools/list-tasks.js +28 -21
  88. package/dist/mcp/tools/send-message.js +28 -22
  89. package/dist/mcp/tools/update-task.js +89 -83
  90. package/dist/runtime/index.js +390 -142
  91. package/dist/tui/App.js +437 -189
  92. package/package.json +1 -1
@@ -2328,9 +2328,79 @@ __export(database_exports, {
2328
2328
  isInitialized: () => isInitialized,
2329
2329
  setExternalClient: () => setExternalClient
2330
2330
  });
2331
- import { chmodSync as chmodSync2 } from "fs";
2331
+ import { chmodSync as chmodSync2, existsSync as existsSync7, statSync as statSync2, copyFileSync, unlinkSync as unlinkSync3, openSync as openSync2, closeSync as closeSync2, mkdirSync as mkdirSync2 } from "fs";
2332
2332
  import { createClient } from "@libsql/client";
2333
+ import { homedir } from "os";
2334
+ import { join } from "path";
2335
+ function logCatchDebug(context, err) {
2336
+ if (_debugDb) {
2337
+ process.stderr.write(
2338
+ `[database] ${context}: ${err instanceof Error ? err.message : String(err)}
2339
+ `
2340
+ );
2341
+ }
2342
+ }
2343
+ function acquireDbLock() {
2344
+ mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
2345
+ try {
2346
+ _lockFd = openSync2(DB_LOCK_PATH, "wx");
2347
+ } catch (err) {
2348
+ if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
2349
+ try {
2350
+ const lockStat = statSync2(DB_LOCK_PATH);
2351
+ if (Date.now() - lockStat.mtimeMs > 6e4) {
2352
+ unlinkSync3(DB_LOCK_PATH);
2353
+ _lockFd = openSync2(DB_LOCK_PATH, "wx");
2354
+ return;
2355
+ }
2356
+ } catch (e) {
2357
+ logCatchDebug("stale lock check", e);
2358
+ }
2359
+ process.stderr.write(
2360
+ "[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
2361
+ );
2362
+ return;
2363
+ }
2364
+ throw err;
2365
+ }
2366
+ }
2367
+ function releaseDbLock() {
2368
+ if (_lockFd !== null) {
2369
+ try {
2370
+ closeSync2(_lockFd);
2371
+ } catch (e) {
2372
+ logCatchDebug("lock close", e);
2373
+ }
2374
+ _lockFd = null;
2375
+ }
2376
+ try {
2377
+ unlinkSync3(DB_LOCK_PATH);
2378
+ } catch (e) {
2379
+ logCatchDebug("lock unlink", e);
2380
+ }
2381
+ }
2333
2382
  async function initDatabase(config2) {
2383
+ acquireDbLock();
2384
+ if (existsSync7(config2.dbPath)) {
2385
+ const dbStat = statSync2(config2.dbPath);
2386
+ if (dbStat.size === 0) {
2387
+ const walPath = config2.dbPath + "-wal";
2388
+ if (existsSync7(walPath) && statSync2(walPath).size > 0) {
2389
+ const backupPath = config2.dbPath + ".zeroed-" + Date.now();
2390
+ copyFileSync(config2.dbPath, backupPath);
2391
+ unlinkSync3(config2.dbPath);
2392
+ process.stderr.write(
2393
+ `[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
2394
+ `
2395
+ );
2396
+ } else {
2397
+ process.stderr.write(
2398
+ `[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config2.dbPath}.bak
2399
+ `
2400
+ );
2401
+ }
2402
+ }
2403
+ }
2334
2404
  if (_walCheckpointTimer) {
2335
2405
  clearInterval(_walCheckpointTimer);
2336
2406
  _walCheckpointTimer = null;
@@ -2357,10 +2427,8 @@ async function initDatabase(config2) {
2357
2427
  _client = createClient(opts);
2358
2428
  _resilientClient = wrapWithRetry(_client);
2359
2429
  _adapterClient = _resilientClient;
2360
- _client.execute("PRAGMA busy_timeout = 30000").catch(() => {
2361
- });
2362
- _client.execute("PRAGMA journal_mode = WAL").catch(() => {
2363
- });
2430
+ await _client.execute("PRAGMA busy_timeout = 30000");
2431
+ await _client.execute("PRAGMA journal_mode = WAL");
2364
2432
  if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
2365
2433
  _walCheckpointTimer = setInterval(() => {
2366
2434
  _client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
@@ -2375,11 +2443,16 @@ async function initDatabase(config2) {
2375
2443
  for (const suffix of ["-wal", "-shm"]) {
2376
2444
  try {
2377
2445
  chmodSync2(config2.dbPath + suffix, 384);
2378
- } catch {
2446
+ } catch (chmodErr) {
2447
+ process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
2448
+ `);
2379
2449
  }
2380
2450
  }
2381
- } catch {
2451
+ } catch (chmodErr) {
2452
+ process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
2453
+ `);
2382
2454
  }
2455
+ releaseDbLock();
2383
2456
  }
2384
2457
  function isInitialized() {
2385
2458
  return _adapterClient !== null || _client !== null;
@@ -2434,7 +2507,8 @@ async function ensureSchema() {
2434
2507
  await client.execute("PRAGMA wal_autocheckpoint = 1000");
2435
2508
  try {
2436
2509
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
2437
- } catch {
2510
+ } catch (e) {
2511
+ logCatchDebug("migration", e);
2438
2512
  }
2439
2513
  await client.executeMultiple(`
2440
2514
  CREATE TABLE IF NOT EXISTS memories (
@@ -2499,6 +2573,23 @@ async function ensureSchema() {
2499
2573
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
2500
2574
  END;
2501
2575
  `);
2576
+ try {
2577
+ await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
2578
+ } catch (ftsErr) {
2579
+ process.stderr.write(
2580
+ `[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
2581
+ `
2582
+ );
2583
+ try {
2584
+ await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
2585
+ process.stderr.write("[database] FTS index rebuilt successfully.\n");
2586
+ } catch (rebuildErr) {
2587
+ process.stderr.write(
2588
+ `[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
2589
+ `
2590
+ );
2591
+ }
2592
+ }
2502
2593
  await client.executeMultiple(`
2503
2594
  CREATE TABLE IF NOT EXISTS sync_meta (
2504
2595
  key TEXT PRIMARY KEY,
@@ -2557,35 +2648,40 @@ async function ensureSchema() {
2557
2648
  });
2558
2649
  }
2559
2650
  }
2560
- } catch {
2651
+ } catch (seedErr) {
2652
+ logCatchDebug("behavior seed", seedErr);
2561
2653
  }
2562
2654
  try {
2563
2655
  await client.execute({
2564
2656
  sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
2565
2657
  args: []
2566
2658
  });
2567
- } catch {
2659
+ } catch (e) {
2660
+ logCatchDebug("migration", e);
2568
2661
  }
2569
2662
  try {
2570
2663
  await client.execute({
2571
2664
  sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
2572
2665
  args: []
2573
2666
  });
2574
- } catch {
2667
+ } catch (e) {
2668
+ logCatchDebug("migration", e);
2575
2669
  }
2576
2670
  try {
2577
2671
  await client.execute({
2578
2672
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
2579
2673
  args: []
2580
2674
  });
2581
- } catch {
2675
+ } catch (e) {
2676
+ logCatchDebug("migration", e);
2582
2677
  }
2583
2678
  try {
2584
2679
  await client.execute({
2585
2680
  sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
2586
2681
  args: []
2587
2682
  });
2588
- } catch {
2683
+ } catch (e) {
2684
+ logCatchDebug("migration", e);
2589
2685
  }
2590
2686
  try {
2591
2687
  await client.execute({
@@ -2594,98 +2690,112 @@ async function ensureSchema() {
2594
2690
  WHERE parent_task_id IS NOT NULL`,
2595
2691
  args: []
2596
2692
  });
2597
- } catch {
2693
+ } catch (e) {
2694
+ logCatchDebug("migration", e);
2598
2695
  }
2599
2696
  try {
2600
2697
  await client.execute({
2601
2698
  sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
2602
2699
  args: []
2603
2700
  });
2604
- } catch {
2701
+ } catch (e) {
2702
+ logCatchDebug("migration", e);
2605
2703
  }
2606
2704
  try {
2607
2705
  await client.execute({
2608
2706
  sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
2609
2707
  args: []
2610
2708
  });
2611
- } catch {
2709
+ } catch (e) {
2710
+ logCatchDebug("migration", e);
2612
2711
  }
2613
2712
  try {
2614
2713
  await client.execute({
2615
2714
  sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
2616
2715
  args: []
2617
2716
  });
2618
- } catch {
2717
+ } catch (e) {
2718
+ logCatchDebug("migration", e);
2619
2719
  }
2620
2720
  try {
2621
2721
  await client.execute({
2622
2722
  sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
2623
2723
  args: []
2624
2724
  });
2625
- } catch {
2725
+ } catch (e) {
2726
+ logCatchDebug("migration", e);
2626
2727
  }
2627
2728
  try {
2628
2729
  await client.execute({
2629
2730
  sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
2630
2731
  args: []
2631
2732
  });
2632
- } catch {
2733
+ } catch (e) {
2734
+ logCatchDebug("migration", e);
2633
2735
  }
2634
2736
  try {
2635
2737
  await client.execute({
2636
2738
  sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
2637
2739
  args: []
2638
2740
  });
2639
- } catch {
2741
+ } catch (e) {
2742
+ logCatchDebug("migration", e);
2640
2743
  }
2641
2744
  try {
2642
2745
  await client.execute({
2643
2746
  sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
2644
2747
  args: []
2645
2748
  });
2646
- } catch {
2749
+ } catch (e) {
2750
+ logCatchDebug("migration", e);
2647
2751
  }
2648
2752
  try {
2649
2753
  await client.execute({
2650
2754
  sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
2651
2755
  args: []
2652
2756
  });
2653
- } catch {
2757
+ } catch (e) {
2758
+ logCatchDebug("migration", e);
2654
2759
  }
2655
2760
  try {
2656
2761
  await client.execute({
2657
2762
  sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
2658
2763
  args: []
2659
2764
  });
2660
- } catch {
2765
+ } catch (e) {
2766
+ logCatchDebug("migration", e);
2661
2767
  }
2662
2768
  try {
2663
2769
  await client.execute({
2664
2770
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
2665
2771
  args: []
2666
2772
  });
2667
- } catch {
2773
+ } catch (e) {
2774
+ logCatchDebug("migration", e);
2668
2775
  }
2669
2776
  try {
2670
2777
  await client.execute({
2671
2778
  sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
2672
2779
  args: []
2673
2780
  });
2674
- } catch {
2781
+ } catch (e) {
2782
+ logCatchDebug("migration", e);
2675
2783
  }
2676
2784
  try {
2677
2785
  await client.execute({
2678
2786
  sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
2679
2787
  args: []
2680
2788
  });
2681
- } catch {
2789
+ } catch (e) {
2790
+ logCatchDebug("migration", e);
2682
2791
  }
2683
2792
  try {
2684
2793
  await client.execute({
2685
2794
  sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
2686
2795
  args: []
2687
2796
  });
2688
- } catch {
2797
+ } catch (e) {
2798
+ logCatchDebug("migration", e);
2689
2799
  }
2690
2800
  await client.executeMultiple(`
2691
2801
  CREATE TABLE IF NOT EXISTS consolidations (
@@ -2790,14 +2900,16 @@ async function ensureSchema() {
2790
2900
  sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
2791
2901
  args: []
2792
2902
  });
2793
- } catch {
2903
+ } catch (e) {
2904
+ logCatchDebug("migration", e);
2794
2905
  }
2795
2906
  try {
2796
2907
  await client.execute({
2797
2908
  sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
2798
2909
  args: []
2799
2910
  });
2800
- } catch {
2911
+ } catch (e) {
2912
+ logCatchDebug("migration", e);
2801
2913
  }
2802
2914
  await client.executeMultiple(`
2803
2915
  CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
@@ -2823,7 +2935,8 @@ async function ensureSchema() {
2823
2935
  sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
2824
2936
  args: []
2825
2937
  });
2826
- } catch {
2938
+ } catch (e) {
2939
+ logCatchDebug("migration", e);
2827
2940
  }
2828
2941
  await client.executeMultiple(`
2829
2942
  CREATE TABLE IF NOT EXISTS trajectories (
@@ -2847,7 +2960,8 @@ async function ensureSchema() {
2847
2960
  `);
2848
2961
  try {
2849
2962
  await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
2850
- } catch {
2963
+ } catch (e) {
2964
+ logCatchDebug("migration", e);
2851
2965
  }
2852
2966
  await client.executeMultiple(`
2853
2967
  CREATE TABLE IF NOT EXISTS consolidations (
@@ -2884,63 +2998,72 @@ async function ensureSchema() {
2884
2998
  sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
2885
2999
  args: []
2886
3000
  });
2887
- } catch {
3001
+ } catch (e) {
3002
+ logCatchDebug("migration", e);
2888
3003
  }
2889
3004
  try {
2890
3005
  await client.execute({
2891
3006
  sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
2892
3007
  args: []
2893
3008
  });
2894
- } catch {
3009
+ } catch (e) {
3010
+ logCatchDebug("migration", e);
2895
3011
  }
2896
3012
  try {
2897
3013
  await client.execute({
2898
3014
  sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
2899
3015
  args: []
2900
3016
  });
2901
- } catch {
3017
+ } catch (e) {
3018
+ logCatchDebug("migration", e);
2902
3019
  }
2903
3020
  try {
2904
3021
  await client.execute({
2905
3022
  sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2906
3023
  args: []
2907
3024
  });
2908
- } catch {
3025
+ } catch (e) {
3026
+ logCatchDebug("migration", e);
2909
3027
  }
2910
3028
  try {
2911
3029
  await client.execute({
2912
3030
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
2913
3031
  args: []
2914
3032
  });
2915
- } catch {
3033
+ } catch (e) {
3034
+ logCatchDebug("migration", e);
2916
3035
  }
2917
3036
  try {
2918
3037
  await client.execute({
2919
3038
  sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
2920
3039
  args: []
2921
3040
  });
2922
- } catch {
3041
+ } catch (e) {
3042
+ logCatchDebug("migration", e);
2923
3043
  }
2924
3044
  try {
2925
3045
  await client.execute({
2926
3046
  sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
2927
3047
  args: []
2928
3048
  });
2929
- } catch {
3049
+ } catch (e) {
3050
+ logCatchDebug("migration", e);
2930
3051
  }
2931
3052
  try {
2932
3053
  await client.execute({
2933
3054
  sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
2934
3055
  args: []
2935
3056
  });
2936
- } catch {
3057
+ } catch (e) {
3058
+ logCatchDebug("migration", e);
2937
3059
  }
2938
3060
  try {
2939
3061
  await client.execute({
2940
3062
  sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
2941
3063
  args: []
2942
3064
  });
2943
- } catch {
3065
+ } catch (e) {
3066
+ logCatchDebug("migration", e);
2944
3067
  }
2945
3068
  for (const col of [
2946
3069
  "ALTER TABLE memories ADD COLUMN content_hash TEXT",
@@ -2948,14 +3071,16 @@ async function ensureSchema() {
2948
3071
  ]) {
2949
3072
  try {
2950
3073
  await client.execute(col);
2951
- } catch {
3074
+ } catch (e) {
3075
+ logCatchDebug("migration", e);
2952
3076
  }
2953
3077
  }
2954
3078
  try {
2955
3079
  await client.execute(
2956
3080
  `CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
2957
3081
  );
2958
- } catch {
3082
+ } catch (e) {
3083
+ logCatchDebug("migration", e);
2959
3084
  }
2960
3085
  try {
2961
3086
  await client.execute(
@@ -2963,7 +3088,8 @@ async function ensureSchema() {
2963
3088
  ON memories(content_hash, agent_id, project_name, memory_type)
2964
3089
  WHERE content_hash IS NOT NULL`
2965
3090
  );
2966
- } catch {
3091
+ } catch (e) {
3092
+ logCatchDebug("migration", e);
2967
3093
  }
2968
3094
  await client.executeMultiple(`
2969
3095
  CREATE TABLE IF NOT EXISTS entities (
@@ -3039,7 +3165,8 @@ async function ensureSchema() {
3039
3165
  `);
3040
3166
  try {
3041
3167
  await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
3042
- } catch {
3168
+ } catch (e) {
3169
+ logCatchDebug("migration", e);
3043
3170
  }
3044
3171
  await client.executeMultiple(`
3045
3172
  CREATE TABLE IF NOT EXISTS entity_aliases (
@@ -3054,14 +3181,16 @@ async function ensureSchema() {
3054
3181
  ]) {
3055
3182
  try {
3056
3183
  await client.execute(col);
3057
- } catch {
3184
+ } catch (e) {
3185
+ logCatchDebug("migration", e);
3058
3186
  }
3059
3187
  }
3060
3188
  try {
3061
3189
  await client.execute(
3062
3190
  `CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
3063
3191
  );
3064
- } catch {
3192
+ } catch (e) {
3193
+ logCatchDebug("migration", e);
3065
3194
  }
3066
3195
  await client.executeMultiple(`
3067
3196
  CREATE TABLE IF NOT EXISTS identity (
@@ -3160,7 +3289,8 @@ async function ensureSchema() {
3160
3289
  sql: `ALTER TABLE memories ADD COLUMN ${column}`,
3161
3290
  args: []
3162
3291
  });
3163
- } catch {
3292
+ } catch (e) {
3293
+ logCatchDebug("migration", e);
3164
3294
  }
3165
3295
  }
3166
3296
  for (const col of [
@@ -3169,7 +3299,8 @@ async function ensureSchema() {
3169
3299
  ]) {
3170
3300
  try {
3171
3301
  await client.execute(col);
3172
- } catch {
3302
+ } catch (e) {
3303
+ logCatchDebug("migration", e);
3173
3304
  }
3174
3305
  }
3175
3306
  await client.executeMultiple(`
@@ -3354,56 +3485,64 @@ async function ensureSchema() {
3354
3485
  args: []
3355
3486
  });
3356
3487
  }
3357
- } catch {
3488
+ } catch (e) {
3489
+ logCatchDebug("session_agent_map backfill", e);
3358
3490
  }
3359
3491
  try {
3360
3492
  await client.execute({
3361
3493
  sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
3362
3494
  args: []
3363
3495
  });
3364
- } catch {
3496
+ } catch (e) {
3497
+ logCatchDebug("migration", e);
3365
3498
  }
3366
3499
  try {
3367
3500
  await client.execute({
3368
3501
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
3369
3502
  args: []
3370
3503
  });
3371
- } catch {
3504
+ } catch (e) {
3505
+ logCatchDebug("migration", e);
3372
3506
  }
3373
3507
  try {
3374
3508
  await client.execute({
3375
3509
  sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
3376
3510
  args: []
3377
3511
  });
3378
- } catch {
3512
+ } catch (e) {
3513
+ logCatchDebug("migration", e);
3379
3514
  }
3380
3515
  try {
3381
3516
  await client.execute({
3382
3517
  sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
3383
3518
  args: []
3384
3519
  });
3385
- } catch {
3520
+ } catch (e) {
3521
+ logCatchDebug("migration", e);
3386
3522
  }
3387
3523
  try {
3388
3524
  await client.execute({
3389
3525
  sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
3390
3526
  args: []
3391
3527
  });
3392
- } catch {
3528
+ } catch (e) {
3529
+ logCatchDebug("migration", e);
3393
3530
  }
3394
3531
  try {
3395
3532
  await client.execute({
3396
3533
  sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
3397
3534
  args: []
3398
3535
  });
3399
- } catch {
3536
+ } catch (e) {
3537
+ logCatchDebug("migration", e);
3400
3538
  }
3401
3539
  try {
3402
3540
  await client.execute({
3403
3541
  sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
3404
3542
  args: []
3405
3543
  });
3406
- } catch {
3544
+ } catch (e) {
3545
+ logCatchDebug("migration", e);
3407
3546
  }
3408
3547
  await client.executeMultiple(`
3409
3548
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
@@ -3602,13 +3741,15 @@ async function ensureSchema() {
3602
3741
  sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
3603
3742
  args: []
3604
3743
  });
3605
- } catch {
3744
+ } catch (e) {
3745
+ logCatchDebug("migration", e);
3606
3746
  }
3607
3747
  try {
3608
3748
  await client.execute(
3609
3749
  `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
3610
3750
  );
3611
- } catch {
3751
+ } catch (e) {
3752
+ logCatchDebug("migration", e);
3612
3753
  }
3613
3754
  try {
3614
3755
  await client.execute({
@@ -3619,20 +3760,23 @@ async function ensureSchema() {
3619
3760
  sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
3620
3761
  args: []
3621
3762
  });
3622
- } catch {
3763
+ } catch (e) {
3764
+ logCatchDebug("migration", e);
3623
3765
  }
3624
3766
  try {
3625
3767
  await client.execute({
3626
3768
  sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
3627
3769
  args: []
3628
3770
  });
3629
- } catch {
3771
+ } catch (e) {
3772
+ logCatchDebug("migration", e);
3630
3773
  }
3631
3774
  try {
3632
3775
  await client.execute(
3633
3776
  `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
3634
3777
  );
3635
- } catch {
3778
+ } catch (e) {
3779
+ logCatchDebug("migration", e);
3636
3780
  }
3637
3781
  for (const col of [
3638
3782
  "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
@@ -3640,7 +3784,8 @@ async function ensureSchema() {
3640
3784
  ]) {
3641
3785
  try {
3642
3786
  await client.execute(col);
3643
- } catch {
3787
+ } catch (e) {
3788
+ logCatchDebug("migration", e);
3644
3789
  }
3645
3790
  }
3646
3791
  try {
@@ -3648,13 +3793,15 @@ async function ensureSchema() {
3648
3793
  sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
3649
3794
  args: []
3650
3795
  });
3651
- } catch {
3796
+ } catch (e) {
3797
+ logCatchDebug("migration", e);
3652
3798
  }
3653
3799
  try {
3654
3800
  await client.execute(
3655
3801
  `CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
3656
3802
  );
3657
- } catch {
3803
+ } catch (e) {
3804
+ logCatchDebug("migration", e);
3658
3805
  }
3659
3806
  for (const col of [
3660
3807
  "ALTER TABLE memories ADD COLUMN valid_from TEXT",
@@ -3662,7 +3809,8 @@ async function ensureSchema() {
3662
3809
  ]) {
3663
3810
  try {
3664
3811
  await client.execute(col);
3665
- } catch {
3812
+ } catch (e) {
3813
+ logCatchDebug("migration", e);
3666
3814
  }
3667
3815
  }
3668
3816
  try {
@@ -3670,27 +3818,31 @@ async function ensureSchema() {
3670
3818
  sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3671
3819
  args: []
3672
3820
  });
3673
- } catch {
3821
+ } catch (e) {
3822
+ logCatchDebug("migration", e);
3674
3823
  }
3675
3824
  try {
3676
3825
  await client.execute({
3677
3826
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
3678
3827
  args: []
3679
3828
  });
3680
- } catch {
3829
+ } catch (e) {
3830
+ logCatchDebug("migration", e);
3681
3831
  }
3682
3832
  try {
3683
3833
  await client.execute(
3684
3834
  `CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
3685
3835
  );
3686
- } catch {
3836
+ } catch (e) {
3837
+ logCatchDebug("migration", e);
3687
3838
  }
3688
3839
  try {
3689
3840
  await client.execute({
3690
3841
  sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
3691
3842
  args: []
3692
3843
  });
3693
- } catch {
3844
+ } catch (e) {
3845
+ logCatchDebug("migration", e);
3694
3846
  }
3695
3847
  for (const col of [
3696
3848
  "ALTER TABLE memories ADD COLUMN intent TEXT",
@@ -3711,7 +3863,8 @@ async function ensureSchema() {
3711
3863
  ]) {
3712
3864
  try {
3713
3865
  await client.execute(col);
3714
- } catch {
3866
+ } catch (e) {
3867
+ logCatchDebug("migration", e);
3715
3868
  }
3716
3869
  }
3717
3870
  try {
@@ -3719,14 +3872,16 @@ async function ensureSchema() {
3719
3872
  sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3720
3873
  args: []
3721
3874
  });
3722
- } catch {
3875
+ } catch (e) {
3876
+ logCatchDebug("migration", e);
3723
3877
  }
3724
3878
  try {
3725
3879
  await client.execute({
3726
3880
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
3727
3881
  args: []
3728
3882
  });
3729
- } catch {
3883
+ } catch (e) {
3884
+ logCatchDebug("migration", e);
3730
3885
  }
3731
3886
  }
3732
3887
  async function disposeDatabase() {
@@ -3737,7 +3892,8 @@ async function disposeDatabase() {
3737
3892
  if (_client) {
3738
3893
  try {
3739
3894
  await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
3740
- } catch {
3895
+ } catch (e) {
3896
+ logCatchDebug("WAL checkpoint", e);
3741
3897
  }
3742
3898
  }
3743
3899
  if (_daemonClient) {
@@ -3753,8 +3909,9 @@ async function disposeDatabase() {
3753
3909
  _client = null;
3754
3910
  _resilientClient = null;
3755
3911
  }
3912
+ releaseDbLock();
3756
3913
  }
3757
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
3914
+ var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
3758
3915
  var init_database = __esm({
3759
3916
  "src/lib/database.ts"() {
3760
3917
  "use strict";
@@ -3762,11 +3919,14 @@ var init_database = __esm({
3762
3919
  init_employees();
3763
3920
  init_database_adapter();
3764
3921
  init_memory();
3922
+ _debugDb = process.env.EXE_DEBUG === "1";
3765
3923
  _client = null;
3766
3924
  _resilientClient = null;
3767
3925
  _walCheckpointTimer = null;
3768
3926
  _daemonClient = null;
3769
3927
  _adapterClient = null;
3928
+ _lockFd = null;
3929
+ DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
3770
3930
  initTurso = initDatabase;
3771
3931
  SOFT_DELETE_RETENTION_DAYS = 7;
3772
3932
  disposeTurso = disposeDatabase;
@@ -3810,10 +3970,10 @@ async function disposeEmbedder() {
3810
3970
  async function embedDirect(text) {
3811
3971
  const llamaCpp = await import("node-llama-cpp");
3812
3972
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
3813
- const { existsSync: existsSync19 } = await import("fs");
3973
+ const { existsSync: existsSync20 } = await import("fs");
3814
3974
  const path23 = await import("path");
3815
3975
  const modelPath = path23.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
3816
- if (!existsSync19(modelPath)) {
3976
+ if (!existsSync20(modelPath)) {
3817
3977
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
3818
3978
  }
3819
3979
  const llama = await llamaCpp.getLlama();
@@ -3843,7 +4003,7 @@ var init_embedder = __esm({
3843
4003
 
3844
4004
  // src/lib/keychain.ts
3845
4005
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3846
- import { existsSync as existsSync7, statSync as statSync2 } from "fs";
4006
+ import { existsSync as existsSync8, statSync as statSync3 } from "fs";
3847
4007
  import { execSync as execSync3 } from "child_process";
3848
4008
  import path7 from "path";
3849
4009
  import os5 from "os";
@@ -3878,7 +4038,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
3878
4038
  if (process.platform !== "linux") return false;
3879
4039
  try {
3880
4040
  const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3881
- const st = statSync2(keyPath);
4041
+ const st = statSync3(keyPath);
3882
4042
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3883
4043
  if (uid === 0) return true;
3884
4044
  const exeOsDir = process.env.EXE_OS_DIR;
@@ -4079,7 +4239,7 @@ async function getMasterKey() {
4079
4239
  }
4080
4240
  }
4081
4241
  const keyPath = getKeyPath();
4082
- if (!existsSync7(keyPath)) {
4242
+ if (!existsSync8(keyPath)) {
4083
4243
  process.stderr.write(
4084
4244
  `[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
4085
4245
  `
@@ -4359,18 +4519,54 @@ __export(shard_manager_exports, {
4359
4519
  shardExists: () => shardExists
4360
4520
  });
4361
4521
  import path8 from "path";
4362
- import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync3 } from "fs";
4522
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync4 } from "fs";
4363
4523
  import { createClient as createClient2 } from "@libsql/client";
4364
4524
  function initShardManager(encryptionKey) {
4365
4525
  _encryptionKey = encryptionKey;
4366
- if (!existsSync8(SHARDS_DIR)) {
4367
- mkdirSync2(SHARDS_DIR, { recursive: true });
4526
+ _keyValidated = false;
4527
+ _keyValidationPromise = null;
4528
+ if (!existsSync9(SHARDS_DIR)) {
4529
+ mkdirSync3(SHARDS_DIR, { recursive: true });
4530
+ }
4531
+ const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
4532
+ if (existingShards.length === 0) {
4533
+ _keyValidated = true;
4368
4534
  }
4369
4535
  _shardingEnabled = true;
4370
4536
  if (_evictionTimer) clearInterval(_evictionTimer);
4371
4537
  _evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
4372
4538
  _evictionTimer.unref();
4373
4539
  }
4540
+ async function validateEncryptionKey() {
4541
+ if (_keyValidated) return true;
4542
+ if (!_encryptionKey) return false;
4543
+ const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
4544
+ if (existingShards.length === 0) {
4545
+ _keyValidated = true;
4546
+ return true;
4547
+ }
4548
+ for (const shardFile of existingShards.slice(0, 3)) {
4549
+ const dbPath = path8.join(SHARDS_DIR, shardFile);
4550
+ const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
4551
+ try {
4552
+ await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
4553
+ testClient.close();
4554
+ _keyValidated = true;
4555
+ return true;
4556
+ } catch {
4557
+ try {
4558
+ testClient.close();
4559
+ } catch {
4560
+ }
4561
+ }
4562
+ }
4563
+ process.stderr.write(
4564
+ `[shard-manager] WARNING: encryption key cannot read any existing shards (${existingShards.length} found). New shard creation disabled to prevent stranded files. Run /exe-doctor to audit.
4565
+ `
4566
+ );
4567
+ _shardingEnabled = false;
4568
+ return false;
4569
+ }
4374
4570
  function isShardingEnabled() {
4375
4571
  return _shardingEnabled;
4376
4572
  }
@@ -4404,13 +4600,13 @@ function getShardClient(projectName) {
4404
4600
  }
4405
4601
  function shardExists(projectName) {
4406
4602
  const safeName = safeShardName(projectName);
4407
- return existsSync8(path8.join(SHARDS_DIR, `${safeName}.db`));
4603
+ return existsSync9(path8.join(SHARDS_DIR, `${safeName}.db`));
4408
4604
  }
4409
4605
  function safeShardName(projectName) {
4410
4606
  return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
4411
4607
  }
4412
4608
  function listShards() {
4413
- if (!existsSync8(SHARDS_DIR)) return [];
4609
+ if (!existsSync9(SHARDS_DIR)) return [];
4414
4610
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
4415
4611
  }
4416
4612
  async function auditShardHealth(options = {}) {
@@ -4423,7 +4619,7 @@ async function auditShardHealth(options = {}) {
4423
4619
  const shards = [];
4424
4620
  for (const name of names) {
4425
4621
  const dbPath = path8.join(SHARDS_DIR, `${name}.db`);
4426
- const stat = statSync3(dbPath);
4622
+ const stat = statSync4(dbPath);
4427
4623
  const item = {
4428
4624
  name,
4429
4625
  path: dbPath,
@@ -4663,6 +4859,17 @@ async function ensureShardSchema(client) {
4663
4859
  }
4664
4860
  }
4665
4861
  async function getReadyShardClient(projectName) {
4862
+ if (!_keyValidated) {
4863
+ if (!_keyValidationPromise) {
4864
+ _keyValidationPromise = validateEncryptionKey();
4865
+ }
4866
+ const valid = await _keyValidationPromise;
4867
+ if (!valid) {
4868
+ throw new Error(
4869
+ `Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
4870
+ );
4871
+ }
4872
+ }
4666
4873
  const safeName = safeShardName(projectName);
4667
4874
  let client = getShardClient(projectName);
4668
4875
  try {
@@ -4675,8 +4882,8 @@ async function getReadyShardClient(projectName) {
4675
4882
  _shards.delete(safeName);
4676
4883
  _shardLastAccess.delete(safeName);
4677
4884
  const dbPath = path8.join(SHARDS_DIR, `${safeName}.db`);
4678
- if (existsSync8(dbPath)) {
4679
- const stat = statSync3(dbPath);
4885
+ if (existsSync9(dbPath)) {
4886
+ const stat = statSync4(dbPath);
4680
4887
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4681
4888
  const archivedPath = path8.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
4682
4889
  renameSync3(dbPath, archivedPath);
@@ -4741,7 +4948,7 @@ function disposeShards() {
4741
4948
  _shardingEnabled = false;
4742
4949
  _encryptionKey = null;
4743
4950
  }
4744
- var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
4951
+ var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
4745
4952
  var init_shard_manager = __esm({
4746
4953
  "src/lib/shard-manager.ts"() {
4747
4954
  "use strict";
@@ -4755,6 +4962,8 @@ var init_shard_manager = __esm({
4755
4962
  _evictionTimer = null;
4756
4963
  _encryptionKey = null;
4757
4964
  _shardingEnabled = false;
4965
+ _keyValidated = false;
4966
+ _keyValidationPromise = null;
4758
4967
  }
4759
4968
  });
4760
4969
 
@@ -4950,6 +5159,18 @@ var init_platform_procedures = __esm({
4950
5159
  priority: "p0",
4951
5160
  content: "create_task is dispatch + delivery. Task lifecycle: open \u2192 in_progress (you start) \u2192 done (update_task when finished) \u2192 needs_review (reviewer nudged) \u2192 closed (COO only via close_task). DB is the reliable delivery \u2014 intercom is just a speedup nudge. If you finish a task, self-chain: check for next task immediately (step 7). Never wait for a nudge. Never say 'standing by.'"
4952
5161
  },
5162
+ {
5163
+ title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
5164
+ domain: "workflow",
5165
+ priority: "p0",
5166
+ content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
5167
+ },
5168
+ {
5169
+ title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
5170
+ domain: "workflow",
5171
+ priority: "p0",
5172
+ content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
5173
+ },
4953
5174
  {
4954
5175
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4955
5176
  domain: "architecture",
@@ -5547,6 +5768,20 @@ __export(store_exports, {
5547
5768
  vectorToBlob: () => vectorToBlob,
5548
5769
  writeMemory: () => writeMemory
5549
5770
  });
5771
+ function logStoreDebug(context, err) {
5772
+ if (_debugStore) {
5773
+ process.stderr.write(
5774
+ `[store] ${context}: ${err instanceof Error ? err.message : String(err)}
5775
+ `
5776
+ );
5777
+ }
5778
+ }
5779
+ function logStoreWarn(context, err) {
5780
+ process.stderr.write(
5781
+ `[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
5782
+ `
5783
+ );
5784
+ }
5550
5785
  function isBusyError2(err) {
5551
5786
  if (err instanceof Error) {
5552
5787
  const msg = err.message.toLowerCase();
@@ -5601,13 +5836,15 @@ async function initStore(options) {
5601
5836
  try {
5602
5837
  const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
5603
5838
  await initDaemonClient2();
5604
- } catch {
5839
+ } catch (e) {
5840
+ logStoreWarn("catch", e);
5605
5841
  }
5606
5842
  if (!options?.lightweight) {
5607
5843
  try {
5608
5844
  const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
5609
5845
  initShardManager2(hexKey);
5610
- } catch {
5846
+ } catch (e) {
5847
+ logStoreWarn("catch", e);
5611
5848
  }
5612
5849
  const client = getClient();
5613
5850
  const vResult = await retryOnBusy2(
@@ -5618,7 +5855,8 @@ async function initStore(options) {
5618
5855
  try {
5619
5856
  const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
5620
5857
  await loadGlobalProcedures2();
5621
- } catch {
5858
+ } catch (e) {
5859
+ logStoreWarn("catch", e);
5622
5860
  }
5623
5861
  }
5624
5862
  }
@@ -5678,7 +5916,8 @@ async function writeMemory(record) {
5678
5916
  memoryType
5679
5917
  });
5680
5918
  if (existing) return;
5681
- } catch {
5919
+ } catch (e) {
5920
+ logStoreWarn("catch", e);
5682
5921
  }
5683
5922
  const dbRow = {
5684
5923
  id: record.id,
@@ -5879,12 +6118,14 @@ async function flushBatch() {
5879
6118
  try {
5880
6119
  const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
5881
6120
  await insertMemoryCardsForBatch2(batch);
5882
- } catch {
6121
+ } catch (e) {
6122
+ logStoreWarn("catch", e);
5883
6123
  }
5884
6124
  try {
5885
6125
  const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
5886
6126
  await insertOntologyForBatch2(batch);
5887
- } catch {
6127
+ } catch (e) {
6128
+ logStoreWarn("catch", e);
5888
6129
  }
5889
6130
  schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
5890
6131
  _pendingRecords.splice(0, batch.length);
@@ -5923,7 +6164,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
5923
6164
  }
5924
6165
  }
5925
6166
  }
5926
- } catch {
6167
+ } catch (e) {
6168
+ logStoreWarn("catch", e);
5927
6169
  }
5928
6170
  return batch.length;
5929
6171
  } finally {
@@ -5965,7 +6207,8 @@ async function searchMemories(queryVector, agentId, options) {
5965
6207
  } else {
5966
6208
  client = getClient();
5967
6209
  }
5968
- } catch {
6210
+ } catch (e) {
6211
+ logStoreDebug("shard routing fallback", e);
5969
6212
  client = getClient();
5970
6213
  }
5971
6214
  const limit = options?.limit ?? 10;
@@ -6081,7 +6324,8 @@ async function attachDocumentMetadata(records) {
6081
6324
  if (!record.document_id) continue;
6082
6325
  record.document_metadata = byId.get(record.document_id) ?? null;
6083
6326
  }
6084
- } catch {
6327
+ } catch (e) {
6328
+ logStoreWarn("catch", e);
6085
6329
  }
6086
6330
  return records;
6087
6331
  }
@@ -6142,11 +6386,12 @@ async function getMemoryCardinality(agentId) {
6142
6386
  args: [agentId]
6143
6387
  });
6144
6388
  return Number(result.rows[0]?.cnt) || 0;
6145
- } catch {
6389
+ } catch (e) {
6390
+ logStoreWarn("getMemoryCardinality", e);
6146
6391
  return 0;
6147
6392
  }
6148
6393
  }
6149
- var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
6394
+ var _debugStore, INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
6150
6395
  var init_store = __esm({
6151
6396
  "src/lib/store.ts"() {
6152
6397
  "use strict";
@@ -6156,6 +6401,7 @@ var init_store = __esm({
6156
6401
  init_config();
6157
6402
  init_state_bus();
6158
6403
  init_memory_write_governor();
6404
+ _debugStore = process.env.EXE_DEBUG === "1";
6159
6405
  INIT_MAX_RETRIES = 3;
6160
6406
  INIT_RETRY_DELAY_MS = 1e3;
6161
6407
  _pendingRecords = [];
@@ -7319,8 +7565,8 @@ __export(whatsapp_accounts_exports, {
7319
7565
  loadAccounts: () => loadAccounts
7320
7566
  });
7321
7567
  import { readFileSync as readFileSync6 } from "fs";
7322
- import { join as join2 } from "path";
7323
- import { homedir as homedir2 } from "os";
7568
+ import { join as join3 } from "path";
7569
+ import { homedir as homedir3 } from "os";
7324
7570
  function loadAccounts() {
7325
7571
  if (cachedAccounts !== null) return cachedAccounts;
7326
7572
  try {
@@ -7358,19 +7604,19 @@ var CONFIG_PATH2, cachedAccounts;
7358
7604
  var init_whatsapp_accounts = __esm({
7359
7605
  "src/gateway/whatsapp-accounts.ts"() {
7360
7606
  "use strict";
7361
- CONFIG_PATH2 = join2(homedir2(), ".exe-os", "whatsapp-accounts.json");
7607
+ CONFIG_PATH2 = join3(homedir3(), ".exe-os", "whatsapp-accounts.json");
7362
7608
  cachedAccounts = null;
7363
7609
  }
7364
7610
  });
7365
7611
 
7366
7612
  // src/lib/session-registry.ts
7367
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync9 } from "fs";
7613
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync10 } from "fs";
7368
7614
  import path10 from "path";
7369
7615
  import os7 from "os";
7370
7616
  function registerSession(entry) {
7371
7617
  const dir = path10.dirname(REGISTRY_PATH);
7372
- if (!existsSync9(dir)) {
7373
- mkdirSync4(dir, { recursive: true });
7618
+ if (!existsSync10(dir)) {
7619
+ mkdirSync5(dir, { recursive: true });
7374
7620
  }
7375
7621
  const sessions = listSessions();
7376
7622
  const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
@@ -7664,16 +7910,16 @@ __export(intercom_queue_exports, {
7664
7910
  queueIntercom: () => queueIntercom,
7665
7911
  readQueue: () => readQueue
7666
7912
  });
7667
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, renameSync as renameSync4, existsSync as existsSync10, mkdirSync as mkdirSync5 } from "fs";
7913
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, renameSync as renameSync4, existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
7668
7914
  import path11 from "path";
7669
7915
  import os8 from "os";
7670
7916
  function ensureDir() {
7671
7917
  const dir = path11.dirname(QUEUE_PATH);
7672
- if (!existsSync10(dir)) mkdirSync5(dir, { recursive: true });
7918
+ if (!existsSync11(dir)) mkdirSync6(dir, { recursive: true });
7673
7919
  }
7674
7920
  function readQueue() {
7675
7921
  try {
7676
- if (!existsSync10(QUEUE_PATH)) return [];
7922
+ if (!existsSync11(QUEUE_PATH)) return [];
7677
7923
  return JSON.parse(readFileSync8(QUEUE_PATH, "utf8"));
7678
7924
  } catch {
7679
7925
  return [];
@@ -7782,7 +8028,7 @@ var init_intercom_queue = __esm({
7782
8028
  });
7783
8029
 
7784
8030
  // src/lib/license.ts
7785
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
8031
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, existsSync as existsSync12, mkdirSync as mkdirSync7 } from "fs";
7786
8032
  import { randomUUID as randomUUID11 } from "crypto";
7787
8033
  import { createRequire as createRequire2 } from "module";
7788
8034
  import { pathToFileURL as pathToFileURL2 } from "url";
@@ -7809,11 +8055,11 @@ var init_license = __esm({
7809
8055
  });
7810
8056
 
7811
8057
  // src/lib/plan-limits.ts
7812
- import { readFileSync as readFileSync10, existsSync as existsSync12 } from "fs";
8058
+ import { readFileSync as readFileSync10, existsSync as existsSync13 } from "fs";
7813
8059
  import path13 from "path";
7814
8060
  function getLicenseSync() {
7815
8061
  try {
7816
- if (!existsSync12(CACHE_PATH2)) return freeLicense();
8062
+ if (!existsSync13(CACHE_PATH2)) return freeLicense();
7817
8063
  const raw = JSON.parse(readFileSync10(CACHE_PATH2, "utf8"));
7818
8064
  if (!raw.token || typeof raw.token !== "string") return freeLicense();
7819
8065
  const parts = raw.token.split(".");
@@ -7852,7 +8098,7 @@ function assertEmployeeLimitSync(rosterPath) {
7852
8098
  const filePath = rosterPath ?? EMPLOYEES_PATH;
7853
8099
  let count = 0;
7854
8100
  try {
7855
- if (existsSync12(filePath)) {
8101
+ if (existsSync13(filePath)) {
7856
8102
  const raw = readFileSync10(filePath, "utf8");
7857
8103
  const employees = JSON.parse(raw);
7858
8104
  count = Array.isArray(employees) ? employees.length : 0;
@@ -7890,9 +8136,9 @@ var init_plan_limits = __esm({
7890
8136
  import os10 from "os";
7891
8137
  import path14 from "path";
7892
8138
  import {
7893
- existsSync as existsSync13,
8139
+ existsSync as existsSync14,
7894
8140
  lstatSync,
7895
- mkdirSync as mkdirSync7,
8141
+ mkdirSync as mkdirSync8,
7896
8142
  readlinkSync as readlinkSync2,
7897
8143
  symlinkSync as symlinkSync2
7898
8144
  } from "fs";
@@ -7908,8 +8154,8 @@ function claudeAgentLinkPath(homeDir, agentId) {
7908
8154
  function ensureAgentSymlink(agentId, homeDir = os10.homedir()) {
7909
8155
  const target = identitySourcePath(homeDir, agentId);
7910
8156
  const link = claudeAgentLinkPath(homeDir, agentId);
7911
- mkdirSync7(claudeAgentsDir(homeDir), { recursive: true });
7912
- if (existsSync13(link)) {
8157
+ mkdirSync8(claudeAgentsDir(homeDir), { recursive: true });
8158
+ if (existsSync14(link)) {
7913
8159
  let stat;
7914
8160
  try {
7915
8161
  stat = lstatSync(link);
@@ -7990,8 +8236,8 @@ import os11 from "os";
7990
8236
  import {
7991
8237
  readFileSync as readFileSync11,
7992
8238
  readdirSync as readdirSync2,
7993
- unlinkSync as unlinkSync3,
7994
- existsSync as existsSync14,
8239
+ unlinkSync as unlinkSync4,
8240
+ existsSync as existsSync15,
7995
8241
  rmdirSync
7996
8242
  } from "fs";
7997
8243
  async function writeNotification(notification) {
@@ -8184,7 +8430,7 @@ import path17 from "path";
8184
8430
  import os12 from "os";
8185
8431
  import { execSync as execSync7 } from "child_process";
8186
8432
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
8187
- import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
8433
+ import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
8188
8434
  async function writeCheckpoint(input) {
8189
8435
  const client = getClient();
8190
8436
  const row = await resolveTask(client, input.taskId);
@@ -8425,7 +8671,7 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
8425
8671
  const EXE_OS_DIR = path17.join(os12.homedir(), ".exe-os");
8426
8672
  const mdPath = path17.join(EXE_OS_DIR, taskFile);
8427
8673
  const mdDir = path17.dirname(mdPath);
8428
- if (!existsSync15(mdDir)) await mkdir4(mdDir, { recursive: true });
8674
+ if (!existsSync16(mdDir)) await mkdir4(mdDir, { recursive: true });
8429
8675
  const reviewer = input.reviewer ?? input.assignedBy;
8430
8676
  const mdContent = `# ${input.title}
8431
8677
 
@@ -8731,7 +8977,7 @@ async function deleteTaskCore(taskId, _baseDir) {
8731
8977
  async function ensureArchitectureDoc(baseDir, projectName) {
8732
8978
  const archPath = path17.join(baseDir, "exe", "ARCHITECTURE.md");
8733
8979
  try {
8734
- if (existsSync15(archPath)) return;
8980
+ if (existsSync16(archPath)) return;
8735
8981
  const template = [
8736
8982
  `# ${projectName} \u2014 System Architecture`,
8737
8983
  "",
@@ -8766,7 +9012,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
8766
9012
  async function ensureGitignoreExe(baseDir) {
8767
9013
  const gitignorePath = path17.join(baseDir, ".gitignore");
8768
9014
  try {
8769
- if (existsSync15(gitignorePath)) {
9015
+ if (existsSync16(gitignorePath)) {
8770
9016
  const content = readFileSync12(gitignorePath, "utf-8");
8771
9017
  if (/^\/?exe\/?$/m.test(content)) return;
8772
9018
  await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
@@ -8811,7 +9057,7 @@ __export(tasks_review_exports, {
8811
9057
  listPendingReviews: () => listPendingReviews
8812
9058
  });
8813
9059
  import path18 from "path";
8814
- import { existsSync as existsSync16, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
9060
+ import { existsSync as existsSync17, readdirSync as readdirSync3, unlinkSync as unlinkSync5 } from "fs";
8815
9061
  function formatAge(isoTimestamp) {
8816
9062
  if (!isoTimestamp) return "";
8817
9063
  const ms = Date.now() - new Date(isoTimestamp).getTime();
@@ -9081,10 +9327,10 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
9081
9327
  }
9082
9328
  try {
9083
9329
  const cacheDir = path18.join(EXE_AI_DIR, "session-cache");
9084
- if (existsSync16(cacheDir)) {
9330
+ if (existsSync17(cacheDir)) {
9085
9331
  for (const f of readdirSync3(cacheDir)) {
9086
9332
  if (f.startsWith("review-notified-")) {
9087
- unlinkSync4(path18.join(cacheDir, f));
9333
+ unlinkSync5(path18.join(cacheDir, f));
9088
9334
  }
9089
9335
  }
9090
9336
  }
@@ -9609,7 +9855,7 @@ __export(tasks_exports, {
9609
9855
  writeCheckpoint: () => writeCheckpoint
9610
9856
  });
9611
9857
  import path20 from "path";
9612
- import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, unlinkSync as unlinkSync5 } from "fs";
9858
+ import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync9, unlinkSync as unlinkSync6 } from "fs";
9613
9859
  async function createTask(input) {
9614
9860
  const result = await createTaskCore(input);
9615
9861
  if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
@@ -9631,11 +9877,11 @@ async function updateTask(input) {
9631
9877
  const cacheDir = path20.join(EXE_AI_DIR, "session-cache");
9632
9878
  const cachePath = path20.join(cacheDir, `current-task-${agent}.json`);
9633
9879
  if (input.status === "in_progress") {
9634
- mkdirSync8(cacheDir, { recursive: true });
9880
+ mkdirSync9(cacheDir, { recursive: true });
9635
9881
  writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
9636
9882
  } else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
9637
9883
  try {
9638
- unlinkSync5(cachePath);
9884
+ unlinkSync6(cachePath);
9639
9885
  } catch {
9640
9886
  }
9641
9887
  }
@@ -10103,11 +10349,11 @@ __export(tmux_routing_exports, {
10103
10349
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
10104
10350
  });
10105
10351
  import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
10106
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, existsSync as existsSync17, appendFileSync, readdirSync as readdirSync4 } from "fs";
10352
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, mkdirSync as mkdirSync10, existsSync as existsSync18, appendFileSync, readdirSync as readdirSync4 } from "fs";
10107
10353
  import path21 from "path";
10108
10354
  import os13 from "os";
10109
10355
  import { fileURLToPath as fileURLToPath2 } from "url";
10110
- import { unlinkSync as unlinkSync6 } from "fs";
10356
+ import { unlinkSync as unlinkSync7 } from "fs";
10111
10357
  function spawnLockPath(sessionName) {
10112
10358
  return path21.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
10113
10359
  }
@@ -10120,11 +10366,11 @@ function isProcessAlive(pid) {
10120
10366
  }
10121
10367
  }
10122
10368
  function acquireSpawnLock2(sessionName) {
10123
- if (!existsSync17(SPAWN_LOCK_DIR)) {
10124
- mkdirSync9(SPAWN_LOCK_DIR, { recursive: true });
10369
+ if (!existsSync18(SPAWN_LOCK_DIR)) {
10370
+ mkdirSync10(SPAWN_LOCK_DIR, { recursive: true });
10125
10371
  }
10126
10372
  const lockFile = spawnLockPath(sessionName);
10127
- if (existsSync17(lockFile)) {
10373
+ if (existsSync18(lockFile)) {
10128
10374
  try {
10129
10375
  const lock = JSON.parse(readFileSync13(lockFile, "utf8"));
10130
10376
  const age = Date.now() - lock.timestamp;
@@ -10139,7 +10385,7 @@ function acquireSpawnLock2(sessionName) {
10139
10385
  }
10140
10386
  function releaseSpawnLock2(sessionName) {
10141
10387
  try {
10142
- unlinkSync6(spawnLockPath(sessionName));
10388
+ unlinkSync7(spawnLockPath(sessionName));
10143
10389
  } catch {
10144
10390
  }
10145
10391
  }
@@ -10152,7 +10398,7 @@ function resolveBehaviorsExporterScript() {
10152
10398
  "bin",
10153
10399
  "exe-export-behaviors.js"
10154
10400
  );
10155
- return existsSync17(scriptPath) ? scriptPath : null;
10401
+ return existsSync18(scriptPath) ? scriptPath : null;
10156
10402
  } catch {
10157
10403
  return null;
10158
10404
  }
@@ -10218,8 +10464,8 @@ function extractRootExe(name) {
10218
10464
  return parts.length > 0 ? parts[parts.length - 1] : null;
10219
10465
  }
10220
10466
  function registerParentExe(sessionKey, parentExe, dispatchedBy) {
10221
- if (!existsSync17(SESSION_CACHE)) {
10222
- mkdirSync9(SESSION_CACHE, { recursive: true });
10467
+ if (!existsSync18(SESSION_CACHE)) {
10468
+ mkdirSync10(SESSION_CACHE, { recursive: true });
10223
10469
  }
10224
10470
  const rootExe = extractRootExe(parentExe) ?? parentExe;
10225
10471
  const filePath = path21.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
@@ -10249,11 +10495,13 @@ function getDispatchedBy(sessionKey) {
10249
10495
  }
10250
10496
  }
10251
10497
  function resolveExeSession() {
10252
- if (process.env.EXE_SESSION_NAME) {
10253
- return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
10254
- }
10255
10498
  const mySession = getMySession();
10256
- if (!mySession) return null;
10499
+ if (!mySession) {
10500
+ if (process.env.EXE_SESSION_NAME) {
10501
+ return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
10502
+ }
10503
+ return null;
10504
+ }
10257
10505
  const fromSessionName = extractRootExe(mySession);
10258
10506
  let candidate = null;
10259
10507
  try {
@@ -10348,7 +10596,7 @@ async function verifyPaneAtCapacity(sessionName) {
10348
10596
  }
10349
10597
  function readDebounceState() {
10350
10598
  try {
10351
- if (!existsSync17(DEBOUNCE_FILE)) return {};
10599
+ if (!existsSync18(DEBOUNCE_FILE)) return {};
10352
10600
  const raw = JSON.parse(readFileSync13(DEBOUNCE_FILE, "utf8"));
10353
10601
  const state = {};
10354
10602
  for (const [key, val] of Object.entries(raw)) {
@@ -10365,7 +10613,7 @@ function readDebounceState() {
10365
10613
  }
10366
10614
  function writeDebounceState(state) {
10367
10615
  try {
10368
- if (!existsSync17(SESSION_CACHE)) mkdirSync9(SESSION_CACHE, { recursive: true });
10616
+ if (!existsSync18(SESSION_CACHE)) mkdirSync10(SESSION_CACHE, { recursive: true });
10369
10617
  writeFileSync8(DEBOUNCE_FILE, JSON.stringify(state));
10370
10618
  } catch {
10371
10619
  }
@@ -10466,7 +10714,7 @@ function sendIntercom(targetSession) {
10466
10714
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
10467
10715
  const agent = baseAgentName(rawAgent);
10468
10716
  const markerPath = path21.join(SESSION_CACHE, `current-task-${agent}.json`);
10469
- if (existsSync17(markerPath)) {
10717
+ if (existsSync18(markerPath)) {
10470
10718
  logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
10471
10719
  return "debounced";
10472
10720
  }
@@ -10477,7 +10725,7 @@ function sendIntercom(targetSession) {
10477
10725
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
10478
10726
  const agent = baseAgentName(rawAgent);
10479
10727
  const taskDir = path21.join(process.cwd(), "exe", agent);
10480
- if (existsSync17(taskDir)) {
10728
+ if (existsSync18(taskDir)) {
10481
10729
  const files = readdirSync4(taskDir).filter(
10482
10730
  (f) => f.endsWith(".md") && f !== "DONE.txt"
10483
10731
  );
@@ -10638,15 +10886,15 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
10638
10886
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
10639
10887
  const logDir = path21.join(os13.homedir(), ".exe-os", "session-logs");
10640
10888
  const logFile = path21.join(logDir, `${instanceLabel}-${Date.now()}.log`);
10641
- if (!existsSync17(logDir)) {
10642
- mkdirSync9(logDir, { recursive: true });
10889
+ if (!existsSync18(logDir)) {
10890
+ mkdirSync10(logDir, { recursive: true });
10643
10891
  }
10644
10892
  transport.kill(sessionName);
10645
10893
  let cleanupSuffix = "";
10646
10894
  try {
10647
10895
  const thisFile = fileURLToPath2(import.meta.url);
10648
10896
  const cleanupScript = path21.join(path21.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
10649
- if (existsSync17(cleanupScript)) {
10897
+ if (existsSync18(cleanupScript)) {
10650
10898
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
10651
10899
  }
10652
10900
  } catch {
@@ -10701,7 +10949,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
10701
10949
  if (changed) {
10702
10950
  perms.allow = allow;
10703
10951
  settings.permissions = perms;
10704
- mkdirSync9(projSettingsDir, { recursive: true });
10952
+ mkdirSync10(projSettingsDir, { recursive: true });
10705
10953
  writeFileSync8(settingsPath, JSON.stringify(settings, null, 2) + "\n");
10706
10954
  }
10707
10955
  } catch {
@@ -10739,7 +10987,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
10739
10987
  `
10740
10988
  );
10741
10989
  }
10742
- } else if (existsSync17(identityPath)) {
10990
+ } else if (existsSync18(identityPath)) {
10743
10991
  identityFlag = ` --append-system-prompt-file ${identityPath}`;
10744
10992
  legacyFallbackWarned = true;
10745
10993
  }
@@ -10761,7 +11009,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
10761
11009
  let sessionContextFlag = "";
10762
11010
  try {
10763
11011
  const ctxDir = path21.join(os13.homedir(), ".exe-os", "session-cache");
10764
- mkdirSync9(ctxDir, { recursive: true });
11012
+ mkdirSync10(ctxDir, { recursive: true });
10765
11013
  const ctxFile = path21.join(ctxDir, `session-context-${sessionName}.md`);
10766
11014
  const ctxContent = [
10767
11015
  `## Session Context`,
@@ -12842,14 +13090,14 @@ var OllamaProvider = class {
12842
13090
 
12843
13091
  // src/gateway/adapters/whatsapp.ts
12844
13092
  import { randomUUID as randomUUID5 } from "crypto";
12845
- import { homedir } from "os";
12846
- import { join } from "path";
12847
- import { mkdirSync as mkdirSync3 } from "fs";
13093
+ import { homedir as homedir2 } from "os";
13094
+ import { join as join2 } from "path";
13095
+ import { mkdirSync as mkdirSync4 } from "fs";
12848
13096
  var INITIAL_BACKOFF_MS = 1e3;
12849
13097
  var MAX_BACKOFF_MS = 3e5;
12850
13098
  var BACKOFF_MULTIPLIER = 2;
12851
13099
  var JITTER_FACTOR = 0.25;
12852
- var AUTH_DIR = join(homedir(), ".exe-os", "whatsapp-auth");
13100
+ var AUTH_DIR = join2(homedir2(), ".exe-os", "whatsapp-auth");
12853
13101
  function createBaileysLogger(accountName) {
12854
13102
  const prefix = accountName ? `[whatsapp:${accountName}]` : "[whatsapp]";
12855
13103
  let logger;
@@ -12889,7 +13137,7 @@ var WhatsAppAdapter = class {
12889
13137
  disconnectedAt = 0;
12890
13138
  async connect(config2) {
12891
13139
  this.authDir = config2.credentials.authDir ?? AUTH_DIR;
12892
- mkdirSync3(this.authDir, { recursive: true });
13140
+ mkdirSync4(this.authDir, { recursive: true });
12893
13141
  const baileys = await import("@whiskeysockets/baileys");
12894
13142
  const { makeWASocket, useMultiFileAuthState, fetchLatestBaileysVersion, DisconnectReason, makeCacheableSignalKeyStore } = baileys;
12895
13143
  const { state, saveCreds } = await useMultiFileAuthState(this.authDir);
@@ -15023,7 +15271,7 @@ async function ensureCRMContact(info) {
15023
15271
  }
15024
15272
 
15025
15273
  // src/automation/trigger-engine.ts
15026
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, existsSync as existsSync18, mkdirSync as mkdirSync10 } from "fs";
15274
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, existsSync as existsSync19, mkdirSync as mkdirSync11 } from "fs";
15027
15275
  import { randomUUID as randomUUID12 } from "crypto";
15028
15276
  import path22 from "path";
15029
15277
  import os14 from "os";
@@ -15081,7 +15329,7 @@ function evaluateConditions(conditions, record) {
15081
15329
  return conditions.every((c) => evaluateCondition(c, record));
15082
15330
  }
15083
15331
  function loadTriggers(project) {
15084
- if (!existsSync18(TRIGGERS_PATH)) return [];
15332
+ if (!existsSync19(TRIGGERS_PATH)) return [];
15085
15333
  try {
15086
15334
  const raw = readFileSync14(TRIGGERS_PATH, "utf-8");
15087
15335
  const all = JSON.parse(raw);