@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
@@ -1458,9 +1458,79 @@ __export(database_exports, {
1458
1458
  isInitialized: () => isInitialized,
1459
1459
  setExternalClient: () => setExternalClient
1460
1460
  });
1461
- import { chmodSync as chmodSync2 } from "fs";
1461
+ import { chmodSync as chmodSync2, existsSync as existsSync6, statSync as statSync2, copyFileSync, unlinkSync as unlinkSync3, openSync as openSync2, closeSync as closeSync2, mkdirSync as mkdirSync2 } from "fs";
1462
1462
  import { createClient } from "@libsql/client";
1463
+ import { homedir } from "os";
1464
+ import { join } from "path";
1465
+ function logCatchDebug(context, err) {
1466
+ if (_debugDb) {
1467
+ process.stderr.write(
1468
+ `[database] ${context}: ${err instanceof Error ? err.message : String(err)}
1469
+ `
1470
+ );
1471
+ }
1472
+ }
1473
+ function acquireDbLock() {
1474
+ mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
1475
+ try {
1476
+ _lockFd = openSync2(DB_LOCK_PATH, "wx");
1477
+ } catch (err) {
1478
+ if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
1479
+ try {
1480
+ const lockStat = statSync2(DB_LOCK_PATH);
1481
+ if (Date.now() - lockStat.mtimeMs > 6e4) {
1482
+ unlinkSync3(DB_LOCK_PATH);
1483
+ _lockFd = openSync2(DB_LOCK_PATH, "wx");
1484
+ return;
1485
+ }
1486
+ } catch (e) {
1487
+ logCatchDebug("stale lock check", e);
1488
+ }
1489
+ process.stderr.write(
1490
+ "[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
1491
+ );
1492
+ return;
1493
+ }
1494
+ throw err;
1495
+ }
1496
+ }
1497
+ function releaseDbLock() {
1498
+ if (_lockFd !== null) {
1499
+ try {
1500
+ closeSync2(_lockFd);
1501
+ } catch (e) {
1502
+ logCatchDebug("lock close", e);
1503
+ }
1504
+ _lockFd = null;
1505
+ }
1506
+ try {
1507
+ unlinkSync3(DB_LOCK_PATH);
1508
+ } catch (e) {
1509
+ logCatchDebug("lock unlink", e);
1510
+ }
1511
+ }
1463
1512
  async function initDatabase(config) {
1513
+ acquireDbLock();
1514
+ if (existsSync6(config.dbPath)) {
1515
+ const dbStat = statSync2(config.dbPath);
1516
+ if (dbStat.size === 0) {
1517
+ const walPath = config.dbPath + "-wal";
1518
+ if (existsSync6(walPath) && statSync2(walPath).size > 0) {
1519
+ const backupPath = config.dbPath + ".zeroed-" + Date.now();
1520
+ copyFileSync(config.dbPath, backupPath);
1521
+ unlinkSync3(config.dbPath);
1522
+ process.stderr.write(
1523
+ `[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
1524
+ `
1525
+ );
1526
+ } else {
1527
+ process.stderr.write(
1528
+ `[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
1529
+ `
1530
+ );
1531
+ }
1532
+ }
1533
+ }
1464
1534
  if (_walCheckpointTimer) {
1465
1535
  clearInterval(_walCheckpointTimer);
1466
1536
  _walCheckpointTimer = null;
@@ -1487,10 +1557,8 @@ async function initDatabase(config) {
1487
1557
  _client = createClient(opts);
1488
1558
  _resilientClient = wrapWithRetry(_client);
1489
1559
  _adapterClient = _resilientClient;
1490
- _client.execute("PRAGMA busy_timeout = 30000").catch(() => {
1491
- });
1492
- _client.execute("PRAGMA journal_mode = WAL").catch(() => {
1493
- });
1560
+ await _client.execute("PRAGMA busy_timeout = 30000");
1561
+ await _client.execute("PRAGMA journal_mode = WAL");
1494
1562
  if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
1495
1563
  _walCheckpointTimer = setInterval(() => {
1496
1564
  _client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
@@ -1505,11 +1573,16 @@ async function initDatabase(config) {
1505
1573
  for (const suffix of ["-wal", "-shm"]) {
1506
1574
  try {
1507
1575
  chmodSync2(config.dbPath + suffix, 384);
1508
- } catch {
1576
+ } catch (chmodErr) {
1577
+ process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
1578
+ `);
1509
1579
  }
1510
1580
  }
1511
- } catch {
1581
+ } catch (chmodErr) {
1582
+ process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
1583
+ `);
1512
1584
  }
1585
+ releaseDbLock();
1513
1586
  }
1514
1587
  function isInitialized() {
1515
1588
  return _adapterClient !== null || _client !== null;
@@ -1564,7 +1637,8 @@ async function ensureSchema() {
1564
1637
  await client.execute("PRAGMA wal_autocheckpoint = 1000");
1565
1638
  try {
1566
1639
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
1567
- } catch {
1640
+ } catch (e) {
1641
+ logCatchDebug("migration", e);
1568
1642
  }
1569
1643
  await client.executeMultiple(`
1570
1644
  CREATE TABLE IF NOT EXISTS memories (
@@ -1629,6 +1703,23 @@ async function ensureSchema() {
1629
1703
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1630
1704
  END;
1631
1705
  `);
1706
+ try {
1707
+ await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
1708
+ } catch (ftsErr) {
1709
+ process.stderr.write(
1710
+ `[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
1711
+ `
1712
+ );
1713
+ try {
1714
+ await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
1715
+ process.stderr.write("[database] FTS index rebuilt successfully.\n");
1716
+ } catch (rebuildErr) {
1717
+ process.stderr.write(
1718
+ `[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
1719
+ `
1720
+ );
1721
+ }
1722
+ }
1632
1723
  await client.executeMultiple(`
1633
1724
  CREATE TABLE IF NOT EXISTS sync_meta (
1634
1725
  key TEXT PRIMARY KEY,
@@ -1687,35 +1778,40 @@ async function ensureSchema() {
1687
1778
  });
1688
1779
  }
1689
1780
  }
1690
- } catch {
1781
+ } catch (seedErr) {
1782
+ logCatchDebug("behavior seed", seedErr);
1691
1783
  }
1692
1784
  try {
1693
1785
  await client.execute({
1694
1786
  sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
1695
1787
  args: []
1696
1788
  });
1697
- } catch {
1789
+ } catch (e) {
1790
+ logCatchDebug("migration", e);
1698
1791
  }
1699
1792
  try {
1700
1793
  await client.execute({
1701
1794
  sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
1702
1795
  args: []
1703
1796
  });
1704
- } catch {
1797
+ } catch (e) {
1798
+ logCatchDebug("migration", e);
1705
1799
  }
1706
1800
  try {
1707
1801
  await client.execute({
1708
1802
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
1709
1803
  args: []
1710
1804
  });
1711
- } catch {
1805
+ } catch (e) {
1806
+ logCatchDebug("migration", e);
1712
1807
  }
1713
1808
  try {
1714
1809
  await client.execute({
1715
1810
  sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
1716
1811
  args: []
1717
1812
  });
1718
- } catch {
1813
+ } catch (e) {
1814
+ logCatchDebug("migration", e);
1719
1815
  }
1720
1816
  try {
1721
1817
  await client.execute({
@@ -1724,98 +1820,112 @@ async function ensureSchema() {
1724
1820
  WHERE parent_task_id IS NOT NULL`,
1725
1821
  args: []
1726
1822
  });
1727
- } catch {
1823
+ } catch (e) {
1824
+ logCatchDebug("migration", e);
1728
1825
  }
1729
1826
  try {
1730
1827
  await client.execute({
1731
1828
  sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
1732
1829
  args: []
1733
1830
  });
1734
- } catch {
1831
+ } catch (e) {
1832
+ logCatchDebug("migration", e);
1735
1833
  }
1736
1834
  try {
1737
1835
  await client.execute({
1738
1836
  sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
1739
1837
  args: []
1740
1838
  });
1741
- } catch {
1839
+ } catch (e) {
1840
+ logCatchDebug("migration", e);
1742
1841
  }
1743
1842
  try {
1744
1843
  await client.execute({
1745
1844
  sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
1746
1845
  args: []
1747
1846
  });
1748
- } catch {
1847
+ } catch (e) {
1848
+ logCatchDebug("migration", e);
1749
1849
  }
1750
1850
  try {
1751
1851
  await client.execute({
1752
1852
  sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
1753
1853
  args: []
1754
1854
  });
1755
- } catch {
1855
+ } catch (e) {
1856
+ logCatchDebug("migration", e);
1756
1857
  }
1757
1858
  try {
1758
1859
  await client.execute({
1759
1860
  sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
1760
1861
  args: []
1761
1862
  });
1762
- } catch {
1863
+ } catch (e) {
1864
+ logCatchDebug("migration", e);
1763
1865
  }
1764
1866
  try {
1765
1867
  await client.execute({
1766
1868
  sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
1767
1869
  args: []
1768
1870
  });
1769
- } catch {
1871
+ } catch (e) {
1872
+ logCatchDebug("migration", e);
1770
1873
  }
1771
1874
  try {
1772
1875
  await client.execute({
1773
1876
  sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
1774
1877
  args: []
1775
1878
  });
1776
- } catch {
1879
+ } catch (e) {
1880
+ logCatchDebug("migration", e);
1777
1881
  }
1778
1882
  try {
1779
1883
  await client.execute({
1780
1884
  sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
1781
1885
  args: []
1782
1886
  });
1783
- } catch {
1887
+ } catch (e) {
1888
+ logCatchDebug("migration", e);
1784
1889
  }
1785
1890
  try {
1786
1891
  await client.execute({
1787
1892
  sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
1788
1893
  args: []
1789
1894
  });
1790
- } catch {
1895
+ } catch (e) {
1896
+ logCatchDebug("migration", e);
1791
1897
  }
1792
1898
  try {
1793
1899
  await client.execute({
1794
1900
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
1795
1901
  args: []
1796
1902
  });
1797
- } catch {
1903
+ } catch (e) {
1904
+ logCatchDebug("migration", e);
1798
1905
  }
1799
1906
  try {
1800
1907
  await client.execute({
1801
1908
  sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
1802
1909
  args: []
1803
1910
  });
1804
- } catch {
1911
+ } catch (e) {
1912
+ logCatchDebug("migration", e);
1805
1913
  }
1806
1914
  try {
1807
1915
  await client.execute({
1808
1916
  sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
1809
1917
  args: []
1810
1918
  });
1811
- } catch {
1919
+ } catch (e) {
1920
+ logCatchDebug("migration", e);
1812
1921
  }
1813
1922
  try {
1814
1923
  await client.execute({
1815
1924
  sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
1816
1925
  args: []
1817
1926
  });
1818
- } catch {
1927
+ } catch (e) {
1928
+ logCatchDebug("migration", e);
1819
1929
  }
1820
1930
  await client.executeMultiple(`
1821
1931
  CREATE TABLE IF NOT EXISTS consolidations (
@@ -1920,14 +2030,16 @@ async function ensureSchema() {
1920
2030
  sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
1921
2031
  args: []
1922
2032
  });
1923
- } catch {
2033
+ } catch (e) {
2034
+ logCatchDebug("migration", e);
1924
2035
  }
1925
2036
  try {
1926
2037
  await client.execute({
1927
2038
  sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
1928
2039
  args: []
1929
2040
  });
1930
- } catch {
2041
+ } catch (e) {
2042
+ logCatchDebug("migration", e);
1931
2043
  }
1932
2044
  await client.executeMultiple(`
1933
2045
  CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
@@ -1953,7 +2065,8 @@ async function ensureSchema() {
1953
2065
  sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
1954
2066
  args: []
1955
2067
  });
1956
- } catch {
2068
+ } catch (e) {
2069
+ logCatchDebug("migration", e);
1957
2070
  }
1958
2071
  await client.executeMultiple(`
1959
2072
  CREATE TABLE IF NOT EXISTS trajectories (
@@ -1977,7 +2090,8 @@ async function ensureSchema() {
1977
2090
  `);
1978
2091
  try {
1979
2092
  await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
1980
- } catch {
2093
+ } catch (e) {
2094
+ logCatchDebug("migration", e);
1981
2095
  }
1982
2096
  await client.executeMultiple(`
1983
2097
  CREATE TABLE IF NOT EXISTS consolidations (
@@ -2014,63 +2128,72 @@ async function ensureSchema() {
2014
2128
  sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
2015
2129
  args: []
2016
2130
  });
2017
- } catch {
2131
+ } catch (e) {
2132
+ logCatchDebug("migration", e);
2018
2133
  }
2019
2134
  try {
2020
2135
  await client.execute({
2021
2136
  sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
2022
2137
  args: []
2023
2138
  });
2024
- } catch {
2139
+ } catch (e) {
2140
+ logCatchDebug("migration", e);
2025
2141
  }
2026
2142
  try {
2027
2143
  await client.execute({
2028
2144
  sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
2029
2145
  args: []
2030
2146
  });
2031
- } catch {
2147
+ } catch (e) {
2148
+ logCatchDebug("migration", e);
2032
2149
  }
2033
2150
  try {
2034
2151
  await client.execute({
2035
2152
  sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2036
2153
  args: []
2037
2154
  });
2038
- } catch {
2155
+ } catch (e) {
2156
+ logCatchDebug("migration", e);
2039
2157
  }
2040
2158
  try {
2041
2159
  await client.execute({
2042
2160
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
2043
2161
  args: []
2044
2162
  });
2045
- } catch {
2163
+ } catch (e) {
2164
+ logCatchDebug("migration", e);
2046
2165
  }
2047
2166
  try {
2048
2167
  await client.execute({
2049
2168
  sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
2050
2169
  args: []
2051
2170
  });
2052
- } catch {
2171
+ } catch (e) {
2172
+ logCatchDebug("migration", e);
2053
2173
  }
2054
2174
  try {
2055
2175
  await client.execute({
2056
2176
  sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
2057
2177
  args: []
2058
2178
  });
2059
- } catch {
2179
+ } catch (e) {
2180
+ logCatchDebug("migration", e);
2060
2181
  }
2061
2182
  try {
2062
2183
  await client.execute({
2063
2184
  sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
2064
2185
  args: []
2065
2186
  });
2066
- } catch {
2187
+ } catch (e) {
2188
+ logCatchDebug("migration", e);
2067
2189
  }
2068
2190
  try {
2069
2191
  await client.execute({
2070
2192
  sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
2071
2193
  args: []
2072
2194
  });
2073
- } catch {
2195
+ } catch (e) {
2196
+ logCatchDebug("migration", e);
2074
2197
  }
2075
2198
  for (const col of [
2076
2199
  "ALTER TABLE memories ADD COLUMN content_hash TEXT",
@@ -2078,14 +2201,16 @@ async function ensureSchema() {
2078
2201
  ]) {
2079
2202
  try {
2080
2203
  await client.execute(col);
2081
- } catch {
2204
+ } catch (e) {
2205
+ logCatchDebug("migration", e);
2082
2206
  }
2083
2207
  }
2084
2208
  try {
2085
2209
  await client.execute(
2086
2210
  `CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
2087
2211
  );
2088
- } catch {
2212
+ } catch (e) {
2213
+ logCatchDebug("migration", e);
2089
2214
  }
2090
2215
  try {
2091
2216
  await client.execute(
@@ -2093,7 +2218,8 @@ async function ensureSchema() {
2093
2218
  ON memories(content_hash, agent_id, project_name, memory_type)
2094
2219
  WHERE content_hash IS NOT NULL`
2095
2220
  );
2096
- } catch {
2221
+ } catch (e) {
2222
+ logCatchDebug("migration", e);
2097
2223
  }
2098
2224
  await client.executeMultiple(`
2099
2225
  CREATE TABLE IF NOT EXISTS entities (
@@ -2169,7 +2295,8 @@ async function ensureSchema() {
2169
2295
  `);
2170
2296
  try {
2171
2297
  await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
2172
- } catch {
2298
+ } catch (e) {
2299
+ logCatchDebug("migration", e);
2173
2300
  }
2174
2301
  await client.executeMultiple(`
2175
2302
  CREATE TABLE IF NOT EXISTS entity_aliases (
@@ -2184,14 +2311,16 @@ async function ensureSchema() {
2184
2311
  ]) {
2185
2312
  try {
2186
2313
  await client.execute(col);
2187
- } catch {
2314
+ } catch (e) {
2315
+ logCatchDebug("migration", e);
2188
2316
  }
2189
2317
  }
2190
2318
  try {
2191
2319
  await client.execute(
2192
2320
  `CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
2193
2321
  );
2194
- } catch {
2322
+ } catch (e) {
2323
+ logCatchDebug("migration", e);
2195
2324
  }
2196
2325
  await client.executeMultiple(`
2197
2326
  CREATE TABLE IF NOT EXISTS identity (
@@ -2290,7 +2419,8 @@ async function ensureSchema() {
2290
2419
  sql: `ALTER TABLE memories ADD COLUMN ${column}`,
2291
2420
  args: []
2292
2421
  });
2293
- } catch {
2422
+ } catch (e) {
2423
+ logCatchDebug("migration", e);
2294
2424
  }
2295
2425
  }
2296
2426
  for (const col of [
@@ -2299,7 +2429,8 @@ async function ensureSchema() {
2299
2429
  ]) {
2300
2430
  try {
2301
2431
  await client.execute(col);
2302
- } catch {
2432
+ } catch (e) {
2433
+ logCatchDebug("migration", e);
2303
2434
  }
2304
2435
  }
2305
2436
  await client.executeMultiple(`
@@ -2484,56 +2615,64 @@ async function ensureSchema() {
2484
2615
  args: []
2485
2616
  });
2486
2617
  }
2487
- } catch {
2618
+ } catch (e) {
2619
+ logCatchDebug("session_agent_map backfill", e);
2488
2620
  }
2489
2621
  try {
2490
2622
  await client.execute({
2491
2623
  sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
2492
2624
  args: []
2493
2625
  });
2494
- } catch {
2626
+ } catch (e) {
2627
+ logCatchDebug("migration", e);
2495
2628
  }
2496
2629
  try {
2497
2630
  await client.execute({
2498
2631
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
2499
2632
  args: []
2500
2633
  });
2501
- } catch {
2634
+ } catch (e) {
2635
+ logCatchDebug("migration", e);
2502
2636
  }
2503
2637
  try {
2504
2638
  await client.execute({
2505
2639
  sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
2506
2640
  args: []
2507
2641
  });
2508
- } catch {
2642
+ } catch (e) {
2643
+ logCatchDebug("migration", e);
2509
2644
  }
2510
2645
  try {
2511
2646
  await client.execute({
2512
2647
  sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
2513
2648
  args: []
2514
2649
  });
2515
- } catch {
2650
+ } catch (e) {
2651
+ logCatchDebug("migration", e);
2516
2652
  }
2517
2653
  try {
2518
2654
  await client.execute({
2519
2655
  sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
2520
2656
  args: []
2521
2657
  });
2522
- } catch {
2658
+ } catch (e) {
2659
+ logCatchDebug("migration", e);
2523
2660
  }
2524
2661
  try {
2525
2662
  await client.execute({
2526
2663
  sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2527
2664
  args: []
2528
2665
  });
2529
- } catch {
2666
+ } catch (e) {
2667
+ logCatchDebug("migration", e);
2530
2668
  }
2531
2669
  try {
2532
2670
  await client.execute({
2533
2671
  sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2534
2672
  args: []
2535
2673
  });
2536
- } catch {
2674
+ } catch (e) {
2675
+ logCatchDebug("migration", e);
2537
2676
  }
2538
2677
  await client.executeMultiple(`
2539
2678
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
@@ -2732,13 +2871,15 @@ async function ensureSchema() {
2732
2871
  sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
2733
2872
  args: []
2734
2873
  });
2735
- } catch {
2874
+ } catch (e) {
2875
+ logCatchDebug("migration", e);
2736
2876
  }
2737
2877
  try {
2738
2878
  await client.execute(
2739
2879
  `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
2740
2880
  );
2741
- } catch {
2881
+ } catch (e) {
2882
+ logCatchDebug("migration", e);
2742
2883
  }
2743
2884
  try {
2744
2885
  await client.execute({
@@ -2749,20 +2890,23 @@ async function ensureSchema() {
2749
2890
  sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
2750
2891
  args: []
2751
2892
  });
2752
- } catch {
2893
+ } catch (e) {
2894
+ logCatchDebug("migration", e);
2753
2895
  }
2754
2896
  try {
2755
2897
  await client.execute({
2756
2898
  sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
2757
2899
  args: []
2758
2900
  });
2759
- } catch {
2901
+ } catch (e) {
2902
+ logCatchDebug("migration", e);
2760
2903
  }
2761
2904
  try {
2762
2905
  await client.execute(
2763
2906
  `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
2764
2907
  );
2765
- } catch {
2908
+ } catch (e) {
2909
+ logCatchDebug("migration", e);
2766
2910
  }
2767
2911
  for (const col of [
2768
2912
  "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
@@ -2770,7 +2914,8 @@ async function ensureSchema() {
2770
2914
  ]) {
2771
2915
  try {
2772
2916
  await client.execute(col);
2773
- } catch {
2917
+ } catch (e) {
2918
+ logCatchDebug("migration", e);
2774
2919
  }
2775
2920
  }
2776
2921
  try {
@@ -2778,13 +2923,15 @@ async function ensureSchema() {
2778
2923
  sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
2779
2924
  args: []
2780
2925
  });
2781
- } catch {
2926
+ } catch (e) {
2927
+ logCatchDebug("migration", e);
2782
2928
  }
2783
2929
  try {
2784
2930
  await client.execute(
2785
2931
  `CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
2786
2932
  );
2787
- } catch {
2933
+ } catch (e) {
2934
+ logCatchDebug("migration", e);
2788
2935
  }
2789
2936
  for (const col of [
2790
2937
  "ALTER TABLE memories ADD COLUMN valid_from TEXT",
@@ -2792,7 +2939,8 @@ async function ensureSchema() {
2792
2939
  ]) {
2793
2940
  try {
2794
2941
  await client.execute(col);
2795
- } catch {
2942
+ } catch (e) {
2943
+ logCatchDebug("migration", e);
2796
2944
  }
2797
2945
  }
2798
2946
  try {
@@ -2800,27 +2948,31 @@ async function ensureSchema() {
2800
2948
  sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
2801
2949
  args: []
2802
2950
  });
2803
- } catch {
2951
+ } catch (e) {
2952
+ logCatchDebug("migration", e);
2804
2953
  }
2805
2954
  try {
2806
2955
  await client.execute({
2807
2956
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
2808
2957
  args: []
2809
2958
  });
2810
- } catch {
2959
+ } catch (e) {
2960
+ logCatchDebug("migration", e);
2811
2961
  }
2812
2962
  try {
2813
2963
  await client.execute(
2814
2964
  `CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
2815
2965
  );
2816
- } catch {
2966
+ } catch (e) {
2967
+ logCatchDebug("migration", e);
2817
2968
  }
2818
2969
  try {
2819
2970
  await client.execute({
2820
2971
  sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
2821
2972
  args: []
2822
2973
  });
2823
- } catch {
2974
+ } catch (e) {
2975
+ logCatchDebug("migration", e);
2824
2976
  }
2825
2977
  for (const col of [
2826
2978
  "ALTER TABLE memories ADD COLUMN intent TEXT",
@@ -2841,7 +2993,8 @@ async function ensureSchema() {
2841
2993
  ]) {
2842
2994
  try {
2843
2995
  await client.execute(col);
2844
- } catch {
2996
+ } catch (e) {
2997
+ logCatchDebug("migration", e);
2845
2998
  }
2846
2999
  }
2847
3000
  try {
@@ -2849,14 +3002,16 @@ async function ensureSchema() {
2849
3002
  sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
2850
3003
  args: []
2851
3004
  });
2852
- } catch {
3005
+ } catch (e) {
3006
+ logCatchDebug("migration", e);
2853
3007
  }
2854
3008
  try {
2855
3009
  await client.execute({
2856
3010
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
2857
3011
  args: []
2858
3012
  });
2859
- } catch {
3013
+ } catch (e) {
3014
+ logCatchDebug("migration", e);
2860
3015
  }
2861
3016
  }
2862
3017
  async function disposeDatabase() {
@@ -2867,7 +3022,8 @@ async function disposeDatabase() {
2867
3022
  if (_client) {
2868
3023
  try {
2869
3024
  await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
2870
- } catch {
3025
+ } catch (e) {
3026
+ logCatchDebug("WAL checkpoint", e);
2871
3027
  }
2872
3028
  }
2873
3029
  if (_daemonClient) {
@@ -2883,8 +3039,9 @@ async function disposeDatabase() {
2883
3039
  _client = null;
2884
3040
  _resilientClient = null;
2885
3041
  }
3042
+ releaseDbLock();
2886
3043
  }
2887
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
3044
+ var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
2888
3045
  var init_database = __esm({
2889
3046
  "src/lib/database.ts"() {
2890
3047
  "use strict";
@@ -2892,11 +3049,14 @@ var init_database = __esm({
2892
3049
  init_employees();
2893
3050
  init_database_adapter();
2894
3051
  init_memory();
3052
+ _debugDb = process.env.EXE_DEBUG === "1";
2895
3053
  _client = null;
2896
3054
  _resilientClient = null;
2897
3055
  _walCheckpointTimer = null;
2898
3056
  _daemonClient = null;
2899
3057
  _adapterClient = null;
3058
+ _lockFd = null;
3059
+ DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
2900
3060
  initTurso = initDatabase;
2901
3061
  SOFT_DELETE_RETENTION_DAYS = 7;
2902
3062
  disposeTurso = disposeDatabase;
@@ -2905,7 +3065,7 @@ var init_database = __esm({
2905
3065
 
2906
3066
  // src/lib/keychain.ts
2907
3067
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2908
- import { existsSync as existsSync6, statSync as statSync2 } from "fs";
3068
+ import { existsSync as existsSync7, statSync as statSync3 } from "fs";
2909
3069
  import { execSync as execSync3 } from "child_process";
2910
3070
  import path6 from "path";
2911
3071
  import os5 from "os";
@@ -2940,7 +3100,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
2940
3100
  if (process.platform !== "linux") return false;
2941
3101
  try {
2942
3102
  const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
2943
- const st = statSync2(keyPath);
3103
+ const st = statSync3(keyPath);
2944
3104
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
2945
3105
  if (uid === 0) return true;
2946
3106
  const exeOsDir = process.env.EXE_OS_DIR;
@@ -3141,7 +3301,7 @@ async function getMasterKey() {
3141
3301
  }
3142
3302
  }
3143
3303
  const keyPath = getKeyPath();
3144
- if (!existsSync6(keyPath)) {
3304
+ if (!existsSync7(keyPath)) {
3145
3305
  process.stderr.write(
3146
3306
  `[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
3147
3307
  `
@@ -3227,18 +3387,54 @@ __export(shard_manager_exports, {
3227
3387
  shardExists: () => shardExists
3228
3388
  });
3229
3389
  import path7 from "path";
3230
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync3 } from "fs";
3390
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync4 } from "fs";
3231
3391
  import { createClient as createClient2 } from "@libsql/client";
3232
3392
  function initShardManager(encryptionKey) {
3233
3393
  _encryptionKey = encryptionKey;
3234
- if (!existsSync7(SHARDS_DIR)) {
3235
- mkdirSync2(SHARDS_DIR, { recursive: true });
3394
+ _keyValidated = false;
3395
+ _keyValidationPromise = null;
3396
+ if (!existsSync8(SHARDS_DIR)) {
3397
+ mkdirSync3(SHARDS_DIR, { recursive: true });
3398
+ }
3399
+ const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
3400
+ if (existingShards.length === 0) {
3401
+ _keyValidated = true;
3236
3402
  }
3237
3403
  _shardingEnabled = true;
3238
3404
  if (_evictionTimer) clearInterval(_evictionTimer);
3239
3405
  _evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
3240
3406
  _evictionTimer.unref();
3241
3407
  }
3408
+ async function validateEncryptionKey() {
3409
+ if (_keyValidated) return true;
3410
+ if (!_encryptionKey) return false;
3411
+ const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
3412
+ if (existingShards.length === 0) {
3413
+ _keyValidated = true;
3414
+ return true;
3415
+ }
3416
+ for (const shardFile of existingShards.slice(0, 3)) {
3417
+ const dbPath = path7.join(SHARDS_DIR, shardFile);
3418
+ const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
3419
+ try {
3420
+ await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
3421
+ testClient.close();
3422
+ _keyValidated = true;
3423
+ return true;
3424
+ } catch {
3425
+ try {
3426
+ testClient.close();
3427
+ } catch {
3428
+ }
3429
+ }
3430
+ }
3431
+ process.stderr.write(
3432
+ `[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.
3433
+ `
3434
+ );
3435
+ _shardingEnabled = false;
3436
+ return false;
3437
+ }
3242
3438
  function isShardingEnabled() {
3243
3439
  return _shardingEnabled;
3244
3440
  }
@@ -3272,13 +3468,13 @@ function getShardClient(projectName) {
3272
3468
  }
3273
3469
  function shardExists(projectName) {
3274
3470
  const safeName = safeShardName(projectName);
3275
- return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
3471
+ return existsSync8(path7.join(SHARDS_DIR, `${safeName}.db`));
3276
3472
  }
3277
3473
  function safeShardName(projectName) {
3278
3474
  return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3279
3475
  }
3280
3476
  function listShards() {
3281
- if (!existsSync7(SHARDS_DIR)) return [];
3477
+ if (!existsSync8(SHARDS_DIR)) return [];
3282
3478
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
3283
3479
  }
3284
3480
  async function auditShardHealth(options = {}) {
@@ -3291,7 +3487,7 @@ async function auditShardHealth(options = {}) {
3291
3487
  const shards = [];
3292
3488
  for (const name of names) {
3293
3489
  const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
3294
- const stat = statSync3(dbPath);
3490
+ const stat = statSync4(dbPath);
3295
3491
  const item = {
3296
3492
  name,
3297
3493
  path: dbPath,
@@ -3531,6 +3727,17 @@ async function ensureShardSchema(client) {
3531
3727
  }
3532
3728
  }
3533
3729
  async function getReadyShardClient(projectName) {
3730
+ if (!_keyValidated) {
3731
+ if (!_keyValidationPromise) {
3732
+ _keyValidationPromise = validateEncryptionKey();
3733
+ }
3734
+ const valid = await _keyValidationPromise;
3735
+ if (!valid) {
3736
+ throw new Error(
3737
+ `Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
3738
+ );
3739
+ }
3740
+ }
3534
3741
  const safeName = safeShardName(projectName);
3535
3742
  let client = getShardClient(projectName);
3536
3743
  try {
@@ -3543,8 +3750,8 @@ async function getReadyShardClient(projectName) {
3543
3750
  _shards.delete(safeName);
3544
3751
  _shardLastAccess.delete(safeName);
3545
3752
  const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
3546
- if (existsSync7(dbPath)) {
3547
- const stat = statSync3(dbPath);
3753
+ if (existsSync8(dbPath)) {
3754
+ const stat = statSync4(dbPath);
3548
3755
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3549
3756
  const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3550
3757
  renameSync3(dbPath, archivedPath);
@@ -3609,7 +3816,7 @@ function disposeShards() {
3609
3816
  _shardingEnabled = false;
3610
3817
  _encryptionKey = null;
3611
3818
  }
3612
- var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
3819
+ var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
3613
3820
  var init_shard_manager = __esm({
3614
3821
  "src/lib/shard-manager.ts"() {
3615
3822
  "use strict";
@@ -3623,6 +3830,8 @@ var init_shard_manager = __esm({
3623
3830
  _evictionTimer = null;
3624
3831
  _encryptionKey = null;
3625
3832
  _shardingEnabled = false;
3833
+ _keyValidated = false;
3834
+ _keyValidationPromise = null;
3626
3835
  }
3627
3836
  });
3628
3837
 
@@ -3818,6 +4027,18 @@ var init_platform_procedures = __esm({
3818
4027
  priority: "p0",
3819
4028
  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.'"
3820
4029
  },
4030
+ {
4031
+ title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
4032
+ domain: "workflow",
4033
+ priority: "p0",
4034
+ 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."
4035
+ },
4036
+ {
4037
+ title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4038
+ domain: "workflow",
4039
+ priority: "p0",
4040
+ 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."
4041
+ },
3821
4042
  {
3822
4043
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3823
4044
  domain: "architecture",
@@ -4399,14 +4620,14 @@ var init_agentic_ontology = __esm({
4399
4620
 
4400
4621
  // src/lib/crdt-sync.ts
4401
4622
  import * as Y from "yjs";
4402
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync9, mkdirSync as mkdirSync4, unlinkSync as unlinkSync3 } from "fs";
4623
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync10, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4 } from "fs";
4403
4624
  import path9 from "path";
4404
- import { homedir } from "os";
4625
+ import { homedir as homedir2 } from "os";
4405
4626
  var DEFAULT_STATE_PATH;
4406
4627
  var init_crdt_sync = __esm({
4407
4628
  "src/lib/crdt-sync.ts"() {
4408
4629
  "use strict";
4409
- DEFAULT_STATE_PATH = path9.join(homedir(), ".exe-os", "crdt-state.bin");
4630
+ DEFAULT_STATE_PATH = path9.join(homedir2(), ".exe-os", "crdt-state.bin");
4410
4631
  }
4411
4632
  });
4412
4633
 
@@ -4563,6 +4784,13 @@ function schedulePostWriteMemoryHygiene(memoryIds) {
4563
4784
  }
4564
4785
 
4565
4786
  // src/lib/store.ts
4787
+ var _debugStore = process.env.EXE_DEBUG === "1";
4788
+ function logStoreWarn(context, err) {
4789
+ process.stderr.write(
4790
+ `[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
4791
+ `
4792
+ );
4793
+ }
4566
4794
  var INIT_MAX_RETRIES = 3;
4567
4795
  var INIT_RETRY_DELAY_MS = 1e3;
4568
4796
  function isBusyError2(err) {
@@ -4625,13 +4853,15 @@ async function initStore(options) {
4625
4853
  try {
4626
4854
  const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
4627
4855
  await initDaemonClient2();
4628
- } catch {
4856
+ } catch (e) {
4857
+ logStoreWarn("catch", e);
4629
4858
  }
4630
4859
  if (!options?.lightweight) {
4631
4860
  try {
4632
4861
  const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
4633
4862
  initShardManager2(hexKey);
4634
- } catch {
4863
+ } catch (e) {
4864
+ logStoreWarn("catch", e);
4635
4865
  }
4636
4866
  const client = getClient();
4637
4867
  const vResult = await retryOnBusy2(
@@ -4642,7 +4872,8 @@ async function initStore(options) {
4642
4872
  try {
4643
4873
  const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
4644
4874
  await loadGlobalProcedures2();
4645
- } catch {
4875
+ } catch (e) {
4876
+ logStoreWarn("catch", e);
4646
4877
  }
4647
4878
  }
4648
4879
  }
@@ -4770,12 +5001,14 @@ async function flushBatch() {
4770
5001
  try {
4771
5002
  const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
4772
5003
  await insertMemoryCardsForBatch2(batch);
4773
- } catch {
5004
+ } catch (e) {
5005
+ logStoreWarn("catch", e);
4774
5006
  }
4775
5007
  try {
4776
5008
  const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
4777
5009
  await insertOntologyForBatch2(batch);
4778
- } catch {
5010
+ } catch (e) {
5011
+ logStoreWarn("catch", e);
4779
5012
  }
4780
5013
  schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
4781
5014
  _pendingRecords.splice(0, batch.length);
@@ -4814,7 +5047,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
4814
5047
  }
4815
5048
  }
4816
5049
  }
4817
- } catch {
5050
+ } catch (e) {
5051
+ logStoreWarn("catch", e);
4818
5052
  }
4819
5053
  return batch.length;
4820
5054
  } finally {
@@ -4843,10 +5077,10 @@ init_database();
4843
5077
 
4844
5078
  // src/lib/cloud-sync.ts
4845
5079
  init_database();
4846
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync10, readdirSync as readdirSync2, mkdirSync as mkdirSync5, appendFileSync, unlinkSync as unlinkSync4, openSync as openSync2, closeSync as closeSync2, statSync as statSync4 } from "fs";
5080
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync11, readdirSync as readdirSync2, mkdirSync as mkdirSync6, appendFileSync, unlinkSync as unlinkSync5, openSync as openSync3, closeSync as closeSync3, statSync as statSync5 } from "fs";
4847
5081
  import crypto3 from "crypto";
4848
5082
  import path10 from "path";
4849
- import { homedir as homedir2 } from "os";
5083
+ import { homedir as homedir3 } from "os";
4850
5084
 
4851
5085
  // src/lib/crypto.ts
4852
5086
  import crypto2 from "crypto";
@@ -4856,7 +5090,7 @@ import { brotliCompressSync, brotliDecompressSync, constants } from "zlib";
4856
5090
 
4857
5091
  // src/lib/license.ts
4858
5092
  init_config();
4859
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync8, mkdirSync as mkdirSync3 } from "fs";
5093
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync9, mkdirSync as mkdirSync4 } from "fs";
4860
5094
  import { randomUUID as randomUUID3 } from "crypto";
4861
5095
  import { createRequire as createRequire2 } from "module";
4862
5096
  import { pathToFileURL as pathToFileURL2 } from "url";
@@ -4885,7 +5119,7 @@ function loadPgClient() {
4885
5119
  let cloudPostgresUrl;
4886
5120
  let configEnabled = false;
4887
5121
  try {
4888
- if (existsSync10(configPath)) {
5122
+ if (existsSync11(configPath)) {
4889
5123
  const cfg = JSON.parse(readFileSync7(configPath, "utf8"));
4890
5124
  cloudPostgresUrl = cfg.cloud?.postgresUrl;
4891
5125
  configEnabled = cfg.cloud?.syncToPostgres === true;
@@ -4913,9 +5147,9 @@ function loadPgClient() {
4913
5147
  if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
4914
5148
  return new Ctor();
4915
5149
  }
4916
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path10.join(homedir2(), "exe-db");
5150
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path10.join(homedir3(), "exe-db");
4917
5151
  const packagePath = path10.join(exeDbRoot, "package.json");
4918
- if (existsSync10(packagePath)) {
5152
+ if (existsSync11(packagePath)) {
4919
5153
  const req = createRequire3(packagePath);
4920
5154
  const entry = req.resolve("@prisma/client");
4921
5155
  const mod = await import(pathToFileURL3(entry).href);