@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
@@ -1598,9 +1598,79 @@ __export(database_exports, {
1598
1598
  isInitialized: () => isInitialized,
1599
1599
  setExternalClient: () => setExternalClient
1600
1600
  });
1601
- import { chmodSync as chmodSync2 } from "fs";
1601
+ 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";
1602
1602
  import { createClient } from "@libsql/client";
1603
+ import { homedir } from "os";
1604
+ import { join } from "path";
1605
+ function logCatchDebug(context, err) {
1606
+ if (_debugDb) {
1607
+ process.stderr.write(
1608
+ `[database] ${context}: ${err instanceof Error ? err.message : String(err)}
1609
+ `
1610
+ );
1611
+ }
1612
+ }
1613
+ function acquireDbLock() {
1614
+ mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
1615
+ try {
1616
+ _lockFd = openSync2(DB_LOCK_PATH, "wx");
1617
+ } catch (err) {
1618
+ if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
1619
+ try {
1620
+ const lockStat = statSync2(DB_LOCK_PATH);
1621
+ if (Date.now() - lockStat.mtimeMs > 6e4) {
1622
+ unlinkSync3(DB_LOCK_PATH);
1623
+ _lockFd = openSync2(DB_LOCK_PATH, "wx");
1624
+ return;
1625
+ }
1626
+ } catch (e) {
1627
+ logCatchDebug("stale lock check", e);
1628
+ }
1629
+ process.stderr.write(
1630
+ "[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
1631
+ );
1632
+ return;
1633
+ }
1634
+ throw err;
1635
+ }
1636
+ }
1637
+ function releaseDbLock() {
1638
+ if (_lockFd !== null) {
1639
+ try {
1640
+ closeSync2(_lockFd);
1641
+ } catch (e) {
1642
+ logCatchDebug("lock close", e);
1643
+ }
1644
+ _lockFd = null;
1645
+ }
1646
+ try {
1647
+ unlinkSync3(DB_LOCK_PATH);
1648
+ } catch (e) {
1649
+ logCatchDebug("lock unlink", e);
1650
+ }
1651
+ }
1603
1652
  async function initDatabase(config) {
1653
+ acquireDbLock();
1654
+ if (existsSync6(config.dbPath)) {
1655
+ const dbStat = statSync2(config.dbPath);
1656
+ if (dbStat.size === 0) {
1657
+ const walPath = config.dbPath + "-wal";
1658
+ if (existsSync6(walPath) && statSync2(walPath).size > 0) {
1659
+ const backupPath = config.dbPath + ".zeroed-" + Date.now();
1660
+ copyFileSync(config.dbPath, backupPath);
1661
+ unlinkSync3(config.dbPath);
1662
+ process.stderr.write(
1663
+ `[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
1664
+ `
1665
+ );
1666
+ } else {
1667
+ process.stderr.write(
1668
+ `[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
1669
+ `
1670
+ );
1671
+ }
1672
+ }
1673
+ }
1604
1674
  if (_walCheckpointTimer) {
1605
1675
  clearInterval(_walCheckpointTimer);
1606
1676
  _walCheckpointTimer = null;
@@ -1627,10 +1697,8 @@ async function initDatabase(config) {
1627
1697
  _client = createClient(opts);
1628
1698
  _resilientClient = wrapWithRetry(_client);
1629
1699
  _adapterClient = _resilientClient;
1630
- _client.execute("PRAGMA busy_timeout = 30000").catch(() => {
1631
- });
1632
- _client.execute("PRAGMA journal_mode = WAL").catch(() => {
1633
- });
1700
+ await _client.execute("PRAGMA busy_timeout = 30000");
1701
+ await _client.execute("PRAGMA journal_mode = WAL");
1634
1702
  if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
1635
1703
  _walCheckpointTimer = setInterval(() => {
1636
1704
  _client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
@@ -1645,11 +1713,16 @@ async function initDatabase(config) {
1645
1713
  for (const suffix of ["-wal", "-shm"]) {
1646
1714
  try {
1647
1715
  chmodSync2(config.dbPath + suffix, 384);
1648
- } catch {
1716
+ } catch (chmodErr) {
1717
+ process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
1718
+ `);
1649
1719
  }
1650
1720
  }
1651
- } catch {
1721
+ } catch (chmodErr) {
1722
+ process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
1723
+ `);
1652
1724
  }
1725
+ releaseDbLock();
1653
1726
  }
1654
1727
  function isInitialized() {
1655
1728
  return _adapterClient !== null || _client !== null;
@@ -1704,7 +1777,8 @@ async function ensureSchema() {
1704
1777
  await client.execute("PRAGMA wal_autocheckpoint = 1000");
1705
1778
  try {
1706
1779
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
1707
- } catch {
1780
+ } catch (e) {
1781
+ logCatchDebug("migration", e);
1708
1782
  }
1709
1783
  await client.executeMultiple(`
1710
1784
  CREATE TABLE IF NOT EXISTS memories (
@@ -1769,6 +1843,23 @@ async function ensureSchema() {
1769
1843
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1770
1844
  END;
1771
1845
  `);
1846
+ try {
1847
+ await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
1848
+ } catch (ftsErr) {
1849
+ process.stderr.write(
1850
+ `[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
1851
+ `
1852
+ );
1853
+ try {
1854
+ await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
1855
+ process.stderr.write("[database] FTS index rebuilt successfully.\n");
1856
+ } catch (rebuildErr) {
1857
+ process.stderr.write(
1858
+ `[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
1859
+ `
1860
+ );
1861
+ }
1862
+ }
1772
1863
  await client.executeMultiple(`
1773
1864
  CREATE TABLE IF NOT EXISTS sync_meta (
1774
1865
  key TEXT PRIMARY KEY,
@@ -1827,35 +1918,40 @@ async function ensureSchema() {
1827
1918
  });
1828
1919
  }
1829
1920
  }
1830
- } catch {
1921
+ } catch (seedErr) {
1922
+ logCatchDebug("behavior seed", seedErr);
1831
1923
  }
1832
1924
  try {
1833
1925
  await client.execute({
1834
1926
  sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
1835
1927
  args: []
1836
1928
  });
1837
- } catch {
1929
+ } catch (e) {
1930
+ logCatchDebug("migration", e);
1838
1931
  }
1839
1932
  try {
1840
1933
  await client.execute({
1841
1934
  sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
1842
1935
  args: []
1843
1936
  });
1844
- } catch {
1937
+ } catch (e) {
1938
+ logCatchDebug("migration", e);
1845
1939
  }
1846
1940
  try {
1847
1941
  await client.execute({
1848
1942
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
1849
1943
  args: []
1850
1944
  });
1851
- } catch {
1945
+ } catch (e) {
1946
+ logCatchDebug("migration", e);
1852
1947
  }
1853
1948
  try {
1854
1949
  await client.execute({
1855
1950
  sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
1856
1951
  args: []
1857
1952
  });
1858
- } catch {
1953
+ } catch (e) {
1954
+ logCatchDebug("migration", e);
1859
1955
  }
1860
1956
  try {
1861
1957
  await client.execute({
@@ -1864,98 +1960,112 @@ async function ensureSchema() {
1864
1960
  WHERE parent_task_id IS NOT NULL`,
1865
1961
  args: []
1866
1962
  });
1867
- } catch {
1963
+ } catch (e) {
1964
+ logCatchDebug("migration", e);
1868
1965
  }
1869
1966
  try {
1870
1967
  await client.execute({
1871
1968
  sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
1872
1969
  args: []
1873
1970
  });
1874
- } catch {
1971
+ } catch (e) {
1972
+ logCatchDebug("migration", e);
1875
1973
  }
1876
1974
  try {
1877
1975
  await client.execute({
1878
1976
  sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
1879
1977
  args: []
1880
1978
  });
1881
- } catch {
1979
+ } catch (e) {
1980
+ logCatchDebug("migration", e);
1882
1981
  }
1883
1982
  try {
1884
1983
  await client.execute({
1885
1984
  sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
1886
1985
  args: []
1887
1986
  });
1888
- } catch {
1987
+ } catch (e) {
1988
+ logCatchDebug("migration", e);
1889
1989
  }
1890
1990
  try {
1891
1991
  await client.execute({
1892
1992
  sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
1893
1993
  args: []
1894
1994
  });
1895
- } catch {
1995
+ } catch (e) {
1996
+ logCatchDebug("migration", e);
1896
1997
  }
1897
1998
  try {
1898
1999
  await client.execute({
1899
2000
  sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
1900
2001
  args: []
1901
2002
  });
1902
- } catch {
2003
+ } catch (e) {
2004
+ logCatchDebug("migration", e);
1903
2005
  }
1904
2006
  try {
1905
2007
  await client.execute({
1906
2008
  sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
1907
2009
  args: []
1908
2010
  });
1909
- } catch {
2011
+ } catch (e) {
2012
+ logCatchDebug("migration", e);
1910
2013
  }
1911
2014
  try {
1912
2015
  await client.execute({
1913
2016
  sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
1914
2017
  args: []
1915
2018
  });
1916
- } catch {
2019
+ } catch (e) {
2020
+ logCatchDebug("migration", e);
1917
2021
  }
1918
2022
  try {
1919
2023
  await client.execute({
1920
2024
  sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
1921
2025
  args: []
1922
2026
  });
1923
- } catch {
2027
+ } catch (e) {
2028
+ logCatchDebug("migration", e);
1924
2029
  }
1925
2030
  try {
1926
2031
  await client.execute({
1927
2032
  sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
1928
2033
  args: []
1929
2034
  });
1930
- } catch {
2035
+ } catch (e) {
2036
+ logCatchDebug("migration", e);
1931
2037
  }
1932
2038
  try {
1933
2039
  await client.execute({
1934
2040
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
1935
2041
  args: []
1936
2042
  });
1937
- } catch {
2043
+ } catch (e) {
2044
+ logCatchDebug("migration", e);
1938
2045
  }
1939
2046
  try {
1940
2047
  await client.execute({
1941
2048
  sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
1942
2049
  args: []
1943
2050
  });
1944
- } catch {
2051
+ } catch (e) {
2052
+ logCatchDebug("migration", e);
1945
2053
  }
1946
2054
  try {
1947
2055
  await client.execute({
1948
2056
  sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
1949
2057
  args: []
1950
2058
  });
1951
- } catch {
2059
+ } catch (e) {
2060
+ logCatchDebug("migration", e);
1952
2061
  }
1953
2062
  try {
1954
2063
  await client.execute({
1955
2064
  sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
1956
2065
  args: []
1957
2066
  });
1958
- } catch {
2067
+ } catch (e) {
2068
+ logCatchDebug("migration", e);
1959
2069
  }
1960
2070
  await client.executeMultiple(`
1961
2071
  CREATE TABLE IF NOT EXISTS consolidations (
@@ -2060,14 +2170,16 @@ async function ensureSchema() {
2060
2170
  sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
2061
2171
  args: []
2062
2172
  });
2063
- } catch {
2173
+ } catch (e) {
2174
+ logCatchDebug("migration", e);
2064
2175
  }
2065
2176
  try {
2066
2177
  await client.execute({
2067
2178
  sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
2068
2179
  args: []
2069
2180
  });
2070
- } catch {
2181
+ } catch (e) {
2182
+ logCatchDebug("migration", e);
2071
2183
  }
2072
2184
  await client.executeMultiple(`
2073
2185
  CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
@@ -2093,7 +2205,8 @@ async function ensureSchema() {
2093
2205
  sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
2094
2206
  args: []
2095
2207
  });
2096
- } catch {
2208
+ } catch (e) {
2209
+ logCatchDebug("migration", e);
2097
2210
  }
2098
2211
  await client.executeMultiple(`
2099
2212
  CREATE TABLE IF NOT EXISTS trajectories (
@@ -2117,7 +2230,8 @@ async function ensureSchema() {
2117
2230
  `);
2118
2231
  try {
2119
2232
  await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
2120
- } catch {
2233
+ } catch (e) {
2234
+ logCatchDebug("migration", e);
2121
2235
  }
2122
2236
  await client.executeMultiple(`
2123
2237
  CREATE TABLE IF NOT EXISTS consolidations (
@@ -2154,63 +2268,72 @@ async function ensureSchema() {
2154
2268
  sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
2155
2269
  args: []
2156
2270
  });
2157
- } catch {
2271
+ } catch (e) {
2272
+ logCatchDebug("migration", e);
2158
2273
  }
2159
2274
  try {
2160
2275
  await client.execute({
2161
2276
  sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
2162
2277
  args: []
2163
2278
  });
2164
- } catch {
2279
+ } catch (e) {
2280
+ logCatchDebug("migration", e);
2165
2281
  }
2166
2282
  try {
2167
2283
  await client.execute({
2168
2284
  sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
2169
2285
  args: []
2170
2286
  });
2171
- } catch {
2287
+ } catch (e) {
2288
+ logCatchDebug("migration", e);
2172
2289
  }
2173
2290
  try {
2174
2291
  await client.execute({
2175
2292
  sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2176
2293
  args: []
2177
2294
  });
2178
- } catch {
2295
+ } catch (e) {
2296
+ logCatchDebug("migration", e);
2179
2297
  }
2180
2298
  try {
2181
2299
  await client.execute({
2182
2300
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
2183
2301
  args: []
2184
2302
  });
2185
- } catch {
2303
+ } catch (e) {
2304
+ logCatchDebug("migration", e);
2186
2305
  }
2187
2306
  try {
2188
2307
  await client.execute({
2189
2308
  sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
2190
2309
  args: []
2191
2310
  });
2192
- } catch {
2311
+ } catch (e) {
2312
+ logCatchDebug("migration", e);
2193
2313
  }
2194
2314
  try {
2195
2315
  await client.execute({
2196
2316
  sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
2197
2317
  args: []
2198
2318
  });
2199
- } catch {
2319
+ } catch (e) {
2320
+ logCatchDebug("migration", e);
2200
2321
  }
2201
2322
  try {
2202
2323
  await client.execute({
2203
2324
  sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
2204
2325
  args: []
2205
2326
  });
2206
- } catch {
2327
+ } catch (e) {
2328
+ logCatchDebug("migration", e);
2207
2329
  }
2208
2330
  try {
2209
2331
  await client.execute({
2210
2332
  sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
2211
2333
  args: []
2212
2334
  });
2213
- } catch {
2335
+ } catch (e) {
2336
+ logCatchDebug("migration", e);
2214
2337
  }
2215
2338
  for (const col of [
2216
2339
  "ALTER TABLE memories ADD COLUMN content_hash TEXT",
@@ -2218,14 +2341,16 @@ async function ensureSchema() {
2218
2341
  ]) {
2219
2342
  try {
2220
2343
  await client.execute(col);
2221
- } catch {
2344
+ } catch (e) {
2345
+ logCatchDebug("migration", e);
2222
2346
  }
2223
2347
  }
2224
2348
  try {
2225
2349
  await client.execute(
2226
2350
  `CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
2227
2351
  );
2228
- } catch {
2352
+ } catch (e) {
2353
+ logCatchDebug("migration", e);
2229
2354
  }
2230
2355
  try {
2231
2356
  await client.execute(
@@ -2233,7 +2358,8 @@ async function ensureSchema() {
2233
2358
  ON memories(content_hash, agent_id, project_name, memory_type)
2234
2359
  WHERE content_hash IS NOT NULL`
2235
2360
  );
2236
- } catch {
2361
+ } catch (e) {
2362
+ logCatchDebug("migration", e);
2237
2363
  }
2238
2364
  await client.executeMultiple(`
2239
2365
  CREATE TABLE IF NOT EXISTS entities (
@@ -2309,7 +2435,8 @@ async function ensureSchema() {
2309
2435
  `);
2310
2436
  try {
2311
2437
  await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
2312
- } catch {
2438
+ } catch (e) {
2439
+ logCatchDebug("migration", e);
2313
2440
  }
2314
2441
  await client.executeMultiple(`
2315
2442
  CREATE TABLE IF NOT EXISTS entity_aliases (
@@ -2324,14 +2451,16 @@ async function ensureSchema() {
2324
2451
  ]) {
2325
2452
  try {
2326
2453
  await client.execute(col);
2327
- } catch {
2454
+ } catch (e) {
2455
+ logCatchDebug("migration", e);
2328
2456
  }
2329
2457
  }
2330
2458
  try {
2331
2459
  await client.execute(
2332
2460
  `CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
2333
2461
  );
2334
- } catch {
2462
+ } catch (e) {
2463
+ logCatchDebug("migration", e);
2335
2464
  }
2336
2465
  await client.executeMultiple(`
2337
2466
  CREATE TABLE IF NOT EXISTS identity (
@@ -2430,7 +2559,8 @@ async function ensureSchema() {
2430
2559
  sql: `ALTER TABLE memories ADD COLUMN ${column}`,
2431
2560
  args: []
2432
2561
  });
2433
- } catch {
2562
+ } catch (e) {
2563
+ logCatchDebug("migration", e);
2434
2564
  }
2435
2565
  }
2436
2566
  for (const col of [
@@ -2439,7 +2569,8 @@ async function ensureSchema() {
2439
2569
  ]) {
2440
2570
  try {
2441
2571
  await client.execute(col);
2442
- } catch {
2572
+ } catch (e) {
2573
+ logCatchDebug("migration", e);
2443
2574
  }
2444
2575
  }
2445
2576
  await client.executeMultiple(`
@@ -2624,56 +2755,64 @@ async function ensureSchema() {
2624
2755
  args: []
2625
2756
  });
2626
2757
  }
2627
- } catch {
2758
+ } catch (e) {
2759
+ logCatchDebug("session_agent_map backfill", e);
2628
2760
  }
2629
2761
  try {
2630
2762
  await client.execute({
2631
2763
  sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
2632
2764
  args: []
2633
2765
  });
2634
- } catch {
2766
+ } catch (e) {
2767
+ logCatchDebug("migration", e);
2635
2768
  }
2636
2769
  try {
2637
2770
  await client.execute({
2638
2771
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
2639
2772
  args: []
2640
2773
  });
2641
- } catch {
2774
+ } catch (e) {
2775
+ logCatchDebug("migration", e);
2642
2776
  }
2643
2777
  try {
2644
2778
  await client.execute({
2645
2779
  sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
2646
2780
  args: []
2647
2781
  });
2648
- } catch {
2782
+ } catch (e) {
2783
+ logCatchDebug("migration", e);
2649
2784
  }
2650
2785
  try {
2651
2786
  await client.execute({
2652
2787
  sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
2653
2788
  args: []
2654
2789
  });
2655
- } catch {
2790
+ } catch (e) {
2791
+ logCatchDebug("migration", e);
2656
2792
  }
2657
2793
  try {
2658
2794
  await client.execute({
2659
2795
  sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
2660
2796
  args: []
2661
2797
  });
2662
- } catch {
2798
+ } catch (e) {
2799
+ logCatchDebug("migration", e);
2663
2800
  }
2664
2801
  try {
2665
2802
  await client.execute({
2666
2803
  sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2667
2804
  args: []
2668
2805
  });
2669
- } catch {
2806
+ } catch (e) {
2807
+ logCatchDebug("migration", e);
2670
2808
  }
2671
2809
  try {
2672
2810
  await client.execute({
2673
2811
  sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2674
2812
  args: []
2675
2813
  });
2676
- } catch {
2814
+ } catch (e) {
2815
+ logCatchDebug("migration", e);
2677
2816
  }
2678
2817
  await client.executeMultiple(`
2679
2818
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
@@ -2872,13 +3011,15 @@ async function ensureSchema() {
2872
3011
  sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
2873
3012
  args: []
2874
3013
  });
2875
- } catch {
3014
+ } catch (e) {
3015
+ logCatchDebug("migration", e);
2876
3016
  }
2877
3017
  try {
2878
3018
  await client.execute(
2879
3019
  `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
2880
3020
  );
2881
- } catch {
3021
+ } catch (e) {
3022
+ logCatchDebug("migration", e);
2882
3023
  }
2883
3024
  try {
2884
3025
  await client.execute({
@@ -2889,20 +3030,23 @@ async function ensureSchema() {
2889
3030
  sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
2890
3031
  args: []
2891
3032
  });
2892
- } catch {
3033
+ } catch (e) {
3034
+ logCatchDebug("migration", e);
2893
3035
  }
2894
3036
  try {
2895
3037
  await client.execute({
2896
3038
  sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
2897
3039
  args: []
2898
3040
  });
2899
- } catch {
3041
+ } catch (e) {
3042
+ logCatchDebug("migration", e);
2900
3043
  }
2901
3044
  try {
2902
3045
  await client.execute(
2903
3046
  `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
2904
3047
  );
2905
- } catch {
3048
+ } catch (e) {
3049
+ logCatchDebug("migration", e);
2906
3050
  }
2907
3051
  for (const col of [
2908
3052
  "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
@@ -2910,7 +3054,8 @@ async function ensureSchema() {
2910
3054
  ]) {
2911
3055
  try {
2912
3056
  await client.execute(col);
2913
- } catch {
3057
+ } catch (e) {
3058
+ logCatchDebug("migration", e);
2914
3059
  }
2915
3060
  }
2916
3061
  try {
@@ -2918,13 +3063,15 @@ async function ensureSchema() {
2918
3063
  sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
2919
3064
  args: []
2920
3065
  });
2921
- } catch {
3066
+ } catch (e) {
3067
+ logCatchDebug("migration", e);
2922
3068
  }
2923
3069
  try {
2924
3070
  await client.execute(
2925
3071
  `CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
2926
3072
  );
2927
- } catch {
3073
+ } catch (e) {
3074
+ logCatchDebug("migration", e);
2928
3075
  }
2929
3076
  for (const col of [
2930
3077
  "ALTER TABLE memories ADD COLUMN valid_from TEXT",
@@ -2932,7 +3079,8 @@ async function ensureSchema() {
2932
3079
  ]) {
2933
3080
  try {
2934
3081
  await client.execute(col);
2935
- } catch {
3082
+ } catch (e) {
3083
+ logCatchDebug("migration", e);
2936
3084
  }
2937
3085
  }
2938
3086
  try {
@@ -2940,27 +3088,31 @@ async function ensureSchema() {
2940
3088
  sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
2941
3089
  args: []
2942
3090
  });
2943
- } catch {
3091
+ } catch (e) {
3092
+ logCatchDebug("migration", e);
2944
3093
  }
2945
3094
  try {
2946
3095
  await client.execute({
2947
3096
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
2948
3097
  args: []
2949
3098
  });
2950
- } catch {
3099
+ } catch (e) {
3100
+ logCatchDebug("migration", e);
2951
3101
  }
2952
3102
  try {
2953
3103
  await client.execute(
2954
3104
  `CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
2955
3105
  );
2956
- } catch {
3106
+ } catch (e) {
3107
+ logCatchDebug("migration", e);
2957
3108
  }
2958
3109
  try {
2959
3110
  await client.execute({
2960
3111
  sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
2961
3112
  args: []
2962
3113
  });
2963
- } catch {
3114
+ } catch (e) {
3115
+ logCatchDebug("migration", e);
2964
3116
  }
2965
3117
  for (const col of [
2966
3118
  "ALTER TABLE memories ADD COLUMN intent TEXT",
@@ -2981,7 +3133,8 @@ async function ensureSchema() {
2981
3133
  ]) {
2982
3134
  try {
2983
3135
  await client.execute(col);
2984
- } catch {
3136
+ } catch (e) {
3137
+ logCatchDebug("migration", e);
2985
3138
  }
2986
3139
  }
2987
3140
  try {
@@ -2989,14 +3142,16 @@ async function ensureSchema() {
2989
3142
  sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
2990
3143
  args: []
2991
3144
  });
2992
- } catch {
3145
+ } catch (e) {
3146
+ logCatchDebug("migration", e);
2993
3147
  }
2994
3148
  try {
2995
3149
  await client.execute({
2996
3150
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
2997
3151
  args: []
2998
3152
  });
2999
- } catch {
3153
+ } catch (e) {
3154
+ logCatchDebug("migration", e);
3000
3155
  }
3001
3156
  }
3002
3157
  async function disposeDatabase() {
@@ -3007,7 +3162,8 @@ async function disposeDatabase() {
3007
3162
  if (_client) {
3008
3163
  try {
3009
3164
  await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
3010
- } catch {
3165
+ } catch (e) {
3166
+ logCatchDebug("WAL checkpoint", e);
3011
3167
  }
3012
3168
  }
3013
3169
  if (_daemonClient) {
@@ -3023,8 +3179,9 @@ async function disposeDatabase() {
3023
3179
  _client = null;
3024
3180
  _resilientClient = null;
3025
3181
  }
3182
+ releaseDbLock();
3026
3183
  }
3027
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
3184
+ var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
3028
3185
  var init_database = __esm({
3029
3186
  "src/lib/database.ts"() {
3030
3187
  "use strict";
@@ -3032,11 +3189,14 @@ var init_database = __esm({
3032
3189
  init_employees();
3033
3190
  init_database_adapter();
3034
3191
  init_memory();
3192
+ _debugDb = process.env.EXE_DEBUG === "1";
3035
3193
  _client = null;
3036
3194
  _resilientClient = null;
3037
3195
  _walCheckpointTimer = null;
3038
3196
  _daemonClient = null;
3039
3197
  _adapterClient = null;
3198
+ _lockFd = null;
3199
+ DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
3040
3200
  initTurso = initDatabase;
3041
3201
  SOFT_DELETE_RETENTION_DAYS = 7;
3042
3202
  disposeTurso = disposeDatabase;
@@ -3059,18 +3219,54 @@ __export(shard_manager_exports, {
3059
3219
  shardExists: () => shardExists
3060
3220
  });
3061
3221
  import path7 from "path";
3062
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync3 } from "fs";
3222
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync4 } from "fs";
3063
3223
  import { createClient as createClient2 } from "@libsql/client";
3064
3224
  function initShardManager(encryptionKey) {
3065
3225
  _encryptionKey = encryptionKey;
3066
- if (!existsSync7(SHARDS_DIR)) {
3067
- mkdirSync2(SHARDS_DIR, { recursive: true });
3226
+ _keyValidated = false;
3227
+ _keyValidationPromise = null;
3228
+ if (!existsSync8(SHARDS_DIR)) {
3229
+ mkdirSync3(SHARDS_DIR, { recursive: true });
3230
+ }
3231
+ const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
3232
+ if (existingShards.length === 0) {
3233
+ _keyValidated = true;
3068
3234
  }
3069
3235
  _shardingEnabled = true;
3070
3236
  if (_evictionTimer) clearInterval(_evictionTimer);
3071
3237
  _evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
3072
3238
  _evictionTimer.unref();
3073
3239
  }
3240
+ async function validateEncryptionKey() {
3241
+ if (_keyValidated) return true;
3242
+ if (!_encryptionKey) return false;
3243
+ const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
3244
+ if (existingShards.length === 0) {
3245
+ _keyValidated = true;
3246
+ return true;
3247
+ }
3248
+ for (const shardFile of existingShards.slice(0, 3)) {
3249
+ const dbPath = path7.join(SHARDS_DIR, shardFile);
3250
+ const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
3251
+ try {
3252
+ await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
3253
+ testClient.close();
3254
+ _keyValidated = true;
3255
+ return true;
3256
+ } catch {
3257
+ try {
3258
+ testClient.close();
3259
+ } catch {
3260
+ }
3261
+ }
3262
+ }
3263
+ process.stderr.write(
3264
+ `[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.
3265
+ `
3266
+ );
3267
+ _shardingEnabled = false;
3268
+ return false;
3269
+ }
3074
3270
  function isShardingEnabled() {
3075
3271
  return _shardingEnabled;
3076
3272
  }
@@ -3104,13 +3300,13 @@ function getShardClient(projectName) {
3104
3300
  }
3105
3301
  function shardExists(projectName) {
3106
3302
  const safeName = safeShardName(projectName);
3107
- return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
3303
+ return existsSync8(path7.join(SHARDS_DIR, `${safeName}.db`));
3108
3304
  }
3109
3305
  function safeShardName(projectName) {
3110
3306
  return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3111
3307
  }
3112
3308
  function listShards() {
3113
- if (!existsSync7(SHARDS_DIR)) return [];
3309
+ if (!existsSync8(SHARDS_DIR)) return [];
3114
3310
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
3115
3311
  }
3116
3312
  async function auditShardHealth(options = {}) {
@@ -3123,7 +3319,7 @@ async function auditShardHealth(options = {}) {
3123
3319
  const shards = [];
3124
3320
  for (const name of names) {
3125
3321
  const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
3126
- const stat2 = statSync3(dbPath);
3322
+ const stat2 = statSync4(dbPath);
3127
3323
  const item = {
3128
3324
  name,
3129
3325
  path: dbPath,
@@ -3363,6 +3559,17 @@ async function ensureShardSchema(client) {
3363
3559
  }
3364
3560
  }
3365
3561
  async function getReadyShardClient(projectName) {
3562
+ if (!_keyValidated) {
3563
+ if (!_keyValidationPromise) {
3564
+ _keyValidationPromise = validateEncryptionKey();
3565
+ }
3566
+ const valid = await _keyValidationPromise;
3567
+ if (!valid) {
3568
+ throw new Error(
3569
+ `Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
3570
+ );
3571
+ }
3572
+ }
3366
3573
  const safeName = safeShardName(projectName);
3367
3574
  let client = getShardClient(projectName);
3368
3575
  try {
@@ -3375,8 +3582,8 @@ async function getReadyShardClient(projectName) {
3375
3582
  _shards.delete(safeName);
3376
3583
  _shardLastAccess.delete(safeName);
3377
3584
  const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
3378
- if (existsSync7(dbPath)) {
3379
- const stat2 = statSync3(dbPath);
3585
+ if (existsSync8(dbPath)) {
3586
+ const stat2 = statSync4(dbPath);
3380
3587
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3381
3588
  const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3382
3589
  renameSync3(dbPath, archivedPath);
@@ -3441,7 +3648,7 @@ function disposeShards() {
3441
3648
  _shardingEnabled = false;
3442
3649
  _encryptionKey = null;
3443
3650
  }
3444
- var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
3651
+ var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
3445
3652
  var init_shard_manager = __esm({
3446
3653
  "src/lib/shard-manager.ts"() {
3447
3654
  "use strict";
@@ -3455,6 +3662,8 @@ var init_shard_manager = __esm({
3455
3662
  _evictionTimer = null;
3456
3663
  _encryptionKey = null;
3457
3664
  _shardingEnabled = false;
3665
+ _keyValidated = false;
3666
+ _keyValidationPromise = null;
3458
3667
  }
3459
3668
  });
3460
3669
 
@@ -3650,6 +3859,18 @@ var init_platform_procedures = __esm({
3650
3859
  priority: "p0",
3651
3860
  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.'"
3652
3861
  },
3862
+ {
3863
+ title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
3864
+ domain: "workflow",
3865
+ priority: "p0",
3866
+ 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."
3867
+ },
3868
+ {
3869
+ title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3870
+ domain: "workflow",
3871
+ priority: "p0",
3872
+ 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."
3873
+ },
3653
3874
  {
3654
3875
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3655
3876
  domain: "architecture",
@@ -4235,7 +4456,7 @@ import { createReadStream } from "fs";
4235
4456
  import { readdir, stat } from "fs/promises";
4236
4457
  import path8 from "path";
4237
4458
  import { createInterface } from "readline";
4238
- import { homedir } from "os";
4459
+ import { homedir as homedir2 } from "os";
4239
4460
  import { parseArgs } from "util";
4240
4461
 
4241
4462
  // src/lib/store.ts
@@ -4244,7 +4465,7 @@ init_database();
4244
4465
 
4245
4466
  // src/lib/keychain.ts
4246
4467
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
4247
- import { existsSync as existsSync6, statSync as statSync2 } from "fs";
4468
+ import { existsSync as existsSync7, statSync as statSync3 } from "fs";
4248
4469
  import { execSync as execSync3 } from "child_process";
4249
4470
  import path6 from "path";
4250
4471
  import os5 from "os";
@@ -4283,7 +4504,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
4283
4504
  if (process.platform !== "linux") return false;
4284
4505
  try {
4285
4506
  const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
4286
- const st = statSync2(keyPath);
4507
+ const st = statSync3(keyPath);
4287
4508
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
4288
4509
  if (uid === 0) return true;
4289
4510
  const exeOsDir = process.env.EXE_OS_DIR;
@@ -4485,7 +4706,7 @@ async function getMasterKey() {
4485
4706
  }
4486
4707
  }
4487
4708
  const keyPath = getKeyPath();
4488
- if (!existsSync6(keyPath)) {
4709
+ if (!existsSync7(keyPath)) {
4489
4710
  process.stderr.write(
4490
4711
  `[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
4491
4712
  `
@@ -4785,6 +5006,13 @@ function schedulePostWriteMemoryHygiene(memoryIds) {
4785
5006
  }
4786
5007
 
4787
5008
  // src/lib/store.ts
5009
+ var _debugStore = process.env.EXE_DEBUG === "1";
5010
+ function logStoreWarn(context, err) {
5011
+ process.stderr.write(
5012
+ `[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
5013
+ `
5014
+ );
5015
+ }
4788
5016
  var INIT_MAX_RETRIES = 3;
4789
5017
  var INIT_RETRY_DELAY_MS = 1e3;
4790
5018
  function isBusyError2(err) {
@@ -4847,13 +5075,15 @@ async function initStore(options) {
4847
5075
  try {
4848
5076
  const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
4849
5077
  await initDaemonClient2();
4850
- } catch {
5078
+ } catch (e) {
5079
+ logStoreWarn("catch", e);
4851
5080
  }
4852
5081
  if (!options?.lightweight) {
4853
5082
  try {
4854
5083
  const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
4855
5084
  initShardManager2(hexKey);
4856
- } catch {
5085
+ } catch (e) {
5086
+ logStoreWarn("catch", e);
4857
5087
  }
4858
5088
  const client = getClient();
4859
5089
  const vResult = await retryOnBusy2(
@@ -4864,7 +5094,8 @@ async function initStore(options) {
4864
5094
  try {
4865
5095
  const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
4866
5096
  await loadGlobalProcedures2();
4867
- } catch {
5097
+ } catch (e) {
5098
+ logStoreWarn("catch", e);
4868
5099
  }
4869
5100
  }
4870
5101
  }
@@ -4924,7 +5155,8 @@ async function writeMemory(record) {
4924
5155
  memoryType
4925
5156
  });
4926
5157
  if (existing) return;
4927
- } catch {
5158
+ } catch (e) {
5159
+ logStoreWarn("catch", e);
4928
5160
  }
4929
5161
  const dbRow = {
4930
5162
  id: record.id,
@@ -5125,12 +5357,14 @@ async function flushBatch() {
5125
5357
  try {
5126
5358
  const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
5127
5359
  await insertMemoryCardsForBatch2(batch);
5128
- } catch {
5360
+ } catch (e) {
5361
+ logStoreWarn("catch", e);
5129
5362
  }
5130
5363
  try {
5131
5364
  const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
5132
5365
  await insertOntologyForBatch2(batch);
5133
- } catch {
5366
+ } catch (e) {
5367
+ logStoreWarn("catch", e);
5134
5368
  }
5135
5369
  schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
5136
5370
  _pendingRecords.splice(0, batch.length);
@@ -5169,7 +5403,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
5169
5403
  }
5170
5404
  }
5171
5405
  }
5172
- } catch {
5406
+ } catch (e) {
5407
+ logStoreWarn("catch", e);
5173
5408
  }
5174
5409
  return batch.length;
5175
5410
  } finally {
@@ -5208,7 +5443,7 @@ var MIN_MESSAGES = 3;
5208
5443
  var MAX_SUMMARY_LENGTH = 4e3;
5209
5444
  var MAX_WALK_DEPTH = 10;
5210
5445
  async function findJsonlFiles(sinceDate, projectFilter) {
5211
- const projectsDir = path8.join(homedir(), ".claude", "projects");
5446
+ const projectsDir = path8.join(homedir2(), ".claude", "projects");
5212
5447
  const files = [];
5213
5448
  async function walk(dir, depth = 0) {
5214
5449
  if (depth > MAX_WALK_DEPTH) return;
@@ -5253,7 +5488,7 @@ async function findJsonlFiles(sinceDate, projectFilter) {
5253
5488
  return files;
5254
5489
  }
5255
5490
  function decodeProjectDir(dirName) {
5256
- const homeEncoded = homedir().replaceAll("/", "-");
5491
+ const homeEncoded = homedir2().replaceAll("/", "-");
5257
5492
  if (dirName.startsWith(homeEncoded + "-")) {
5258
5493
  return dirName.slice(homeEncoded.length + 1);
5259
5494
  }
@@ -5261,7 +5496,7 @@ function decodeProjectDir(dirName) {
5261
5496
  return dirName;
5262
5497
  }
5263
5498
  function projectNameFromPath(filePath) {
5264
- const projectsDir = path8.join(homedir(), ".claude", "projects");
5499
+ const projectsDir = path8.join(homedir2(), ".claude", "projects");
5265
5500
  const relative = path8.relative(projectsDir, filePath);
5266
5501
  const projectDir = relative.split(path8.sep)[0] ?? "unknown";
5267
5502
  return decodeProjectDir(projectDir);