@askexenow/exe-os 0.9.54 → 0.9.55

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 (59) hide show
  1. package/dist/bin/backfill-conversations.js +65 -0
  2. package/dist/bin/backfill-responses.js +65 -0
  3. package/dist/bin/backfill-vectors.js +65 -0
  4. package/dist/bin/cleanup-stale-review-tasks.js +65 -0
  5. package/dist/bin/cli.js +65 -0
  6. package/dist/bin/exe-assign.js +65 -0
  7. package/dist/bin/exe-boot.js +65 -0
  8. package/dist/bin/exe-dispatch.js +65 -0
  9. package/dist/bin/exe-doctor.js +114 -3
  10. package/dist/bin/exe-export-behaviors.js +65 -0
  11. package/dist/bin/exe-forget.js +65 -0
  12. package/dist/bin/exe-gateway.js +65 -0
  13. package/dist/bin/exe-heartbeat.js +65 -0
  14. package/dist/bin/exe-kill.js +65 -0
  15. package/dist/bin/exe-launch-agent.js +65 -0
  16. package/dist/bin/exe-pending-messages.js +65 -0
  17. package/dist/bin/exe-pending-notifications.js +65 -0
  18. package/dist/bin/exe-pending-reviews.js +65 -0
  19. package/dist/bin/exe-rename.js +65 -0
  20. package/dist/bin/exe-review.js +65 -0
  21. package/dist/bin/exe-search.js +65 -0
  22. package/dist/bin/exe-session-cleanup.js +65 -0
  23. package/dist/bin/exe-start-codex.js +65 -0
  24. package/dist/bin/exe-start-opencode.js +65 -0
  25. package/dist/bin/exe-status.js +65 -0
  26. package/dist/bin/exe-team.js +65 -0
  27. package/dist/bin/git-sweep.js +65 -0
  28. package/dist/bin/graph-backfill.js +65 -0
  29. package/dist/bin/graph-export.js +65 -0
  30. package/dist/bin/intercom-check.js +65 -0
  31. package/dist/bin/scan-tasks.js +65 -0
  32. package/dist/bin/shard-migrate.js +65 -0
  33. package/dist/gateway/index.js +65 -0
  34. package/dist/hooks/bug-report-worker.js +65 -0
  35. package/dist/hooks/codex-stop-task-finalizer.js +65 -0
  36. package/dist/hooks/commit-complete.js +65 -0
  37. package/dist/hooks/error-recall.js +65 -0
  38. package/dist/hooks/ingest.js +65 -0
  39. package/dist/hooks/instructions-loaded.js +65 -0
  40. package/dist/hooks/notification.js +65 -0
  41. package/dist/hooks/post-compact.js +65 -0
  42. package/dist/hooks/post-tool-combined.js +65 -0
  43. package/dist/hooks/pre-compact.js +65 -0
  44. package/dist/hooks/pre-tool-use.js +65 -0
  45. package/dist/hooks/prompt-submit.js +65 -0
  46. package/dist/hooks/session-end.js +65 -0
  47. package/dist/hooks/session-start.js +65 -0
  48. package/dist/hooks/stop.js +65 -0
  49. package/dist/hooks/subagent-stop.js +65 -0
  50. package/dist/hooks/summary-worker.js +65 -0
  51. package/dist/index.js +65 -0
  52. package/dist/lib/exe-daemon.js +112 -3
  53. package/dist/lib/hybrid-search.js +65 -0
  54. package/dist/lib/schedules.js +65 -0
  55. package/dist/lib/store.js +65 -0
  56. package/dist/mcp/server.js +112 -3
  57. package/dist/runtime/index.js +65 -0
  58. package/dist/tui/App.js +65 -0
  59. package/package.json +1 -1
@@ -2729,6 +2729,7 @@ var init_database = __esm({
2729
2729
  // src/lib/shard-manager.ts
2730
2730
  var shard_manager_exports = {};
2731
2731
  __export(shard_manager_exports, {
2732
+ auditShardHealth: () => auditShardHealth,
2732
2733
  disposeShards: () => disposeShards,
2733
2734
  ensureShardSchema: () => ensureShardSchema,
2734
2735
  getOpenShardCount: () => getOpenShardCount,
@@ -2795,6 +2796,70 @@ function listShards() {
2795
2796
  if (!existsSync7(SHARDS_DIR)) return [];
2796
2797
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
2797
2798
  }
2799
+ async function auditShardHealth(options = {}) {
2800
+ if (!_encryptionKey) {
2801
+ throw new Error("Shard manager not initialized. Call initShardManager() first.");
2802
+ }
2803
+ const repair = options.repair === true;
2804
+ const dryRun = options.dryRun === true;
2805
+ const names = listShards();
2806
+ const shards = [];
2807
+ for (const name of names) {
2808
+ const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
2809
+ const stat2 = statSync2(dbPath);
2810
+ const item = {
2811
+ name,
2812
+ path: dbPath,
2813
+ ok: false,
2814
+ unreadable: false,
2815
+ error: null,
2816
+ size: stat2.size,
2817
+ mtime: stat2.mtime.toISOString(),
2818
+ memoryCount: null
2819
+ };
2820
+ const client = createClient2({
2821
+ url: `file:${dbPath}`,
2822
+ encryptionKey: _encryptionKey
2823
+ });
2824
+ try {
2825
+ await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
2826
+ const hasMemories = await client.execute(
2827
+ "SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
2828
+ );
2829
+ if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
2830
+ const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
2831
+ item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
2832
+ }
2833
+ item.ok = true;
2834
+ } catch (err) {
2835
+ const message = err instanceof Error ? err.message : String(err);
2836
+ item.error = message;
2837
+ item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
2838
+ if (item.unreadable && repair && !dryRun) {
2839
+ client.close();
2840
+ _shards.delete(name);
2841
+ _shardLastAccess.delete(name);
2842
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2843
+ const archivedPath = path7.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
2844
+ renameSync3(dbPath, archivedPath);
2845
+ item.archivedPath = archivedPath;
2846
+ }
2847
+ } finally {
2848
+ try {
2849
+ client.close();
2850
+ } catch {
2851
+ }
2852
+ }
2853
+ shards.push(item);
2854
+ }
2855
+ return {
2856
+ total: shards.length,
2857
+ ok: shards.filter((s) => s.ok).length,
2858
+ unreadable: shards.filter((s) => s.unreadable).length,
2859
+ archived: shards.filter((s) => Boolean(s.archivedPath)).length,
2860
+ shards
2861
+ };
2862
+ }
2798
2863
  async function ensureShardSchema(client) {
2799
2864
  await client.execute("PRAGMA journal_mode = WAL");
2800
2865
  await client.execute("PRAGMA busy_timeout = 30000");
@@ -2729,6 +2729,7 @@ var init_database = __esm({
2729
2729
  // src/lib/shard-manager.ts
2730
2730
  var shard_manager_exports = {};
2731
2731
  __export(shard_manager_exports, {
2732
+ auditShardHealth: () => auditShardHealth,
2732
2733
  disposeShards: () => disposeShards,
2733
2734
  ensureShardSchema: () => ensureShardSchema,
2734
2735
  getOpenShardCount: () => getOpenShardCount,
@@ -2795,6 +2796,70 @@ function listShards() {
2795
2796
  if (!existsSync7(SHARDS_DIR)) return [];
2796
2797
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
2797
2798
  }
2799
+ async function auditShardHealth(options = {}) {
2800
+ if (!_encryptionKey) {
2801
+ throw new Error("Shard manager not initialized. Call initShardManager() first.");
2802
+ }
2803
+ const repair = options.repair === true;
2804
+ const dryRun = options.dryRun === true;
2805
+ const names = listShards();
2806
+ const shards = [];
2807
+ for (const name of names) {
2808
+ const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
2809
+ const stat2 = statSync2(dbPath);
2810
+ const item = {
2811
+ name,
2812
+ path: dbPath,
2813
+ ok: false,
2814
+ unreadable: false,
2815
+ error: null,
2816
+ size: stat2.size,
2817
+ mtime: stat2.mtime.toISOString(),
2818
+ memoryCount: null
2819
+ };
2820
+ const client = createClient2({
2821
+ url: `file:${dbPath}`,
2822
+ encryptionKey: _encryptionKey
2823
+ });
2824
+ try {
2825
+ await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
2826
+ const hasMemories = await client.execute(
2827
+ "SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
2828
+ );
2829
+ if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
2830
+ const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
2831
+ item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
2832
+ }
2833
+ item.ok = true;
2834
+ } catch (err) {
2835
+ const message = err instanceof Error ? err.message : String(err);
2836
+ item.error = message;
2837
+ item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
2838
+ if (item.unreadable && repair && !dryRun) {
2839
+ client.close();
2840
+ _shards.delete(name);
2841
+ _shardLastAccess.delete(name);
2842
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2843
+ const archivedPath = path7.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
2844
+ renameSync3(dbPath, archivedPath);
2845
+ item.archivedPath = archivedPath;
2846
+ }
2847
+ } finally {
2848
+ try {
2849
+ client.close();
2850
+ } catch {
2851
+ }
2852
+ }
2853
+ shards.push(item);
2854
+ }
2855
+ return {
2856
+ total: shards.length,
2857
+ ok: shards.filter((s) => s.ok).length,
2858
+ unreadable: shards.filter((s) => s.unreadable).length,
2859
+ archived: shards.filter((s) => Boolean(s.archivedPath)).length,
2860
+ shards
2861
+ };
2862
+ }
2798
2863
  async function ensureShardSchema(client) {
2799
2864
  await client.execute("PRAGMA journal_mode = WAL");
2800
2865
  await client.execute("PRAGMA busy_timeout = 30000");
@@ -2725,6 +2725,7 @@ var init_database = __esm({
2725
2725
  // src/lib/shard-manager.ts
2726
2726
  var shard_manager_exports = {};
2727
2727
  __export(shard_manager_exports, {
2728
+ auditShardHealth: () => auditShardHealth,
2728
2729
  disposeShards: () => disposeShards,
2729
2730
  ensureShardSchema: () => ensureShardSchema,
2730
2731
  getOpenShardCount: () => getOpenShardCount,
@@ -2791,6 +2792,70 @@ function listShards() {
2791
2792
  if (!existsSync7(SHARDS_DIR)) return [];
2792
2793
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
2793
2794
  }
2795
+ async function auditShardHealth(options = {}) {
2796
+ if (!_encryptionKey) {
2797
+ throw new Error("Shard manager not initialized. Call initShardManager() first.");
2798
+ }
2799
+ const repair = options.repair === true;
2800
+ const dryRun = options.dryRun === true;
2801
+ const names = listShards();
2802
+ const shards = [];
2803
+ for (const name of names) {
2804
+ const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
2805
+ const stat = statSync2(dbPath);
2806
+ const item = {
2807
+ name,
2808
+ path: dbPath,
2809
+ ok: false,
2810
+ unreadable: false,
2811
+ error: null,
2812
+ size: stat.size,
2813
+ mtime: stat.mtime.toISOString(),
2814
+ memoryCount: null
2815
+ };
2816
+ const client = createClient2({
2817
+ url: `file:${dbPath}`,
2818
+ encryptionKey: _encryptionKey
2819
+ });
2820
+ try {
2821
+ await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
2822
+ const hasMemories = await client.execute(
2823
+ "SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
2824
+ );
2825
+ if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
2826
+ const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
2827
+ item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
2828
+ }
2829
+ item.ok = true;
2830
+ } catch (err) {
2831
+ const message = err instanceof Error ? err.message : String(err);
2832
+ item.error = message;
2833
+ item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
2834
+ if (item.unreadable && repair && !dryRun) {
2835
+ client.close();
2836
+ _shards.delete(name);
2837
+ _shardLastAccess.delete(name);
2838
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2839
+ const archivedPath = path7.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
2840
+ renameSync3(dbPath, archivedPath);
2841
+ item.archivedPath = archivedPath;
2842
+ }
2843
+ } finally {
2844
+ try {
2845
+ client.close();
2846
+ } catch {
2847
+ }
2848
+ }
2849
+ shards.push(item);
2850
+ }
2851
+ return {
2852
+ total: shards.length,
2853
+ ok: shards.filter((s) => s.ok).length,
2854
+ unreadable: shards.filter((s) => s.unreadable).length,
2855
+ archived: shards.filter((s) => Boolean(s.archivedPath)).length,
2856
+ shards
2857
+ };
2858
+ }
2794
2859
  async function ensureShardSchema(client) {
2795
2860
  await client.execute("PRAGMA journal_mode = WAL");
2796
2861
  await client.execute("PRAGMA busy_timeout = 30000");
@@ -3287,6 +3287,7 @@ var init_memory_write_governor = __esm({
3287
3287
  // src/lib/shard-manager.ts
3288
3288
  var shard_manager_exports = {};
3289
3289
  __export(shard_manager_exports, {
3290
+ auditShardHealth: () => auditShardHealth,
3290
3291
  disposeShards: () => disposeShards,
3291
3292
  ensureShardSchema: () => ensureShardSchema,
3292
3293
  getOpenShardCount: () => getOpenShardCount,
@@ -3353,6 +3354,70 @@ function listShards() {
3353
3354
  if (!existsSync7(SHARDS_DIR)) return [];
3354
3355
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
3355
3356
  }
3357
+ async function auditShardHealth(options = {}) {
3358
+ if (!_encryptionKey) {
3359
+ throw new Error("Shard manager not initialized. Call initShardManager() first.");
3360
+ }
3361
+ const repair = options.repair === true;
3362
+ const dryRun = options.dryRun === true;
3363
+ const names = listShards();
3364
+ const shards = [];
3365
+ for (const name of names) {
3366
+ const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
3367
+ const stat = statSync2(dbPath);
3368
+ const item = {
3369
+ name,
3370
+ path: dbPath,
3371
+ ok: false,
3372
+ unreadable: false,
3373
+ error: null,
3374
+ size: stat.size,
3375
+ mtime: stat.mtime.toISOString(),
3376
+ memoryCount: null
3377
+ };
3378
+ const client = createClient2({
3379
+ url: `file:${dbPath}`,
3380
+ encryptionKey: _encryptionKey
3381
+ });
3382
+ try {
3383
+ await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
3384
+ const hasMemories = await client.execute(
3385
+ "SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
3386
+ );
3387
+ if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
3388
+ const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
3389
+ item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
3390
+ }
3391
+ item.ok = true;
3392
+ } catch (err) {
3393
+ const message = err instanceof Error ? err.message : String(err);
3394
+ item.error = message;
3395
+ item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
3396
+ if (item.unreadable && repair && !dryRun) {
3397
+ client.close();
3398
+ _shards.delete(name);
3399
+ _shardLastAccess.delete(name);
3400
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3401
+ const archivedPath = path7.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
3402
+ renameSync3(dbPath, archivedPath);
3403
+ item.archivedPath = archivedPath;
3404
+ }
3405
+ } finally {
3406
+ try {
3407
+ client.close();
3408
+ } catch {
3409
+ }
3410
+ }
3411
+ shards.push(item);
3412
+ }
3413
+ return {
3414
+ total: shards.length,
3415
+ ok: shards.filter((s) => s.ok).length,
3416
+ unreadable: shards.filter((s) => s.unreadable).length,
3417
+ archived: shards.filter((s) => Boolean(s.archivedPath)).length,
3418
+ shards
3419
+ };
3420
+ }
3356
3421
  async function ensureShardSchema(client) {
3357
3422
  await client.execute("PRAGMA journal_mode = WAL");
3358
3423
  await client.execute("PRAGMA busy_timeout = 30000");
package/dist/bin/cli.js CHANGED
@@ -7157,6 +7157,7 @@ var init_memory_write_governor = __esm({
7157
7157
  // src/lib/shard-manager.ts
7158
7158
  var shard_manager_exports = {};
7159
7159
  __export(shard_manager_exports, {
7160
+ auditShardHealth: () => auditShardHealth,
7160
7161
  disposeShards: () => disposeShards,
7161
7162
  ensureShardSchema: () => ensureShardSchema,
7162
7163
  getOpenShardCount: () => getOpenShardCount,
@@ -7223,6 +7224,70 @@ function listShards() {
7223
7224
  if (!existsSync15(SHARDS_DIR)) return [];
7224
7225
  return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
7225
7226
  }
7227
+ async function auditShardHealth(options = {}) {
7228
+ if (!_encryptionKey) {
7229
+ throw new Error("Shard manager not initialized. Call initShardManager() first.");
7230
+ }
7231
+ const repair = options.repair === true;
7232
+ const dryRun = options.dryRun === true;
7233
+ const names = listShards();
7234
+ const shards = [];
7235
+ for (const name of names) {
7236
+ const dbPath = path15.join(SHARDS_DIR, `${name}.db`);
7237
+ const stat2 = statSync4(dbPath);
7238
+ const item = {
7239
+ name,
7240
+ path: dbPath,
7241
+ ok: false,
7242
+ unreadable: false,
7243
+ error: null,
7244
+ size: stat2.size,
7245
+ mtime: stat2.mtime.toISOString(),
7246
+ memoryCount: null
7247
+ };
7248
+ const client = createClient2({
7249
+ url: `file:${dbPath}`,
7250
+ encryptionKey: _encryptionKey
7251
+ });
7252
+ try {
7253
+ await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
7254
+ const hasMemories = await client.execute(
7255
+ "SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
7256
+ );
7257
+ if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
7258
+ const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
7259
+ item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
7260
+ }
7261
+ item.ok = true;
7262
+ } catch (err) {
7263
+ const message = err instanceof Error ? err.message : String(err);
7264
+ item.error = message;
7265
+ item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
7266
+ if (item.unreadable && repair && !dryRun) {
7267
+ client.close();
7268
+ _shards.delete(name);
7269
+ _shardLastAccess.delete(name);
7270
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7271
+ const archivedPath = path15.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
7272
+ renameSync3(dbPath, archivedPath);
7273
+ item.archivedPath = archivedPath;
7274
+ }
7275
+ } finally {
7276
+ try {
7277
+ client.close();
7278
+ } catch {
7279
+ }
7280
+ }
7281
+ shards.push(item);
7282
+ }
7283
+ return {
7284
+ total: shards.length,
7285
+ ok: shards.filter((s) => s.ok).length,
7286
+ unreadable: shards.filter((s) => s.unreadable).length,
7287
+ archived: shards.filter((s) => Boolean(s.archivedPath)).length,
7288
+ shards
7289
+ };
7290
+ }
7226
7291
  async function ensureShardSchema(client) {
7227
7292
  await client.execute("PRAGMA journal_mode = WAL");
7228
7293
  await client.execute("PRAGMA busy_timeout = 30000");
@@ -2739,6 +2739,7 @@ var init_database = __esm({
2739
2739
  // src/lib/shard-manager.ts
2740
2740
  var shard_manager_exports = {};
2741
2741
  __export(shard_manager_exports, {
2742
+ auditShardHealth: () => auditShardHealth,
2742
2743
  disposeShards: () => disposeShards,
2743
2744
  ensureShardSchema: () => ensureShardSchema,
2744
2745
  getOpenShardCount: () => getOpenShardCount,
@@ -2805,6 +2806,70 @@ function listShards() {
2805
2806
  if (!existsSync7(SHARDS_DIR)) return [];
2806
2807
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
2807
2808
  }
2809
+ async function auditShardHealth(options = {}) {
2810
+ if (!_encryptionKey) {
2811
+ throw new Error("Shard manager not initialized. Call initShardManager() first.");
2812
+ }
2813
+ const repair = options.repair === true;
2814
+ const dryRun = options.dryRun === true;
2815
+ const names = listShards();
2816
+ const shards = [];
2817
+ for (const name of names) {
2818
+ const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
2819
+ const stat = statSync2(dbPath);
2820
+ const item = {
2821
+ name,
2822
+ path: dbPath,
2823
+ ok: false,
2824
+ unreadable: false,
2825
+ error: null,
2826
+ size: stat.size,
2827
+ mtime: stat.mtime.toISOString(),
2828
+ memoryCount: null
2829
+ };
2830
+ const client = createClient2({
2831
+ url: `file:${dbPath}`,
2832
+ encryptionKey: _encryptionKey
2833
+ });
2834
+ try {
2835
+ await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
2836
+ const hasMemories = await client.execute(
2837
+ "SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
2838
+ );
2839
+ if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
2840
+ const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
2841
+ item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
2842
+ }
2843
+ item.ok = true;
2844
+ } catch (err) {
2845
+ const message = err instanceof Error ? err.message : String(err);
2846
+ item.error = message;
2847
+ item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
2848
+ if (item.unreadable && repair && !dryRun) {
2849
+ client.close();
2850
+ _shards.delete(name);
2851
+ _shardLastAccess.delete(name);
2852
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2853
+ const archivedPath = path7.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
2854
+ renameSync3(dbPath, archivedPath);
2855
+ item.archivedPath = archivedPath;
2856
+ }
2857
+ } finally {
2858
+ try {
2859
+ client.close();
2860
+ } catch {
2861
+ }
2862
+ }
2863
+ shards.push(item);
2864
+ }
2865
+ return {
2866
+ total: shards.length,
2867
+ ok: shards.filter((s) => s.ok).length,
2868
+ unreadable: shards.filter((s) => s.unreadable).length,
2869
+ archived: shards.filter((s) => Boolean(s.archivedPath)).length,
2870
+ shards
2871
+ };
2872
+ }
2808
2873
  async function ensureShardSchema(client) {
2809
2874
  await client.execute("PRAGMA journal_mode = WAL");
2810
2875
  await client.execute("PRAGMA busy_timeout = 30000");
@@ -3520,6 +3520,7 @@ var init_memory_write_governor = __esm({
3520
3520
  // src/lib/shard-manager.ts
3521
3521
  var shard_manager_exports = {};
3522
3522
  __export(shard_manager_exports, {
3523
+ auditShardHealth: () => auditShardHealth,
3523
3524
  disposeShards: () => disposeShards,
3524
3525
  ensureShardSchema: () => ensureShardSchema,
3525
3526
  getOpenShardCount: () => getOpenShardCount,
@@ -3586,6 +3587,70 @@ function listShards() {
3586
3587
  if (!existsSync7(SHARDS_DIR)) return [];
3587
3588
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
3588
3589
  }
3590
+ async function auditShardHealth(options = {}) {
3591
+ if (!_encryptionKey) {
3592
+ throw new Error("Shard manager not initialized. Call initShardManager() first.");
3593
+ }
3594
+ const repair = options.repair === true;
3595
+ const dryRun = options.dryRun === true;
3596
+ const names = listShards();
3597
+ const shards = [];
3598
+ for (const name of names) {
3599
+ const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
3600
+ const stat = statSync2(dbPath);
3601
+ const item = {
3602
+ name,
3603
+ path: dbPath,
3604
+ ok: false,
3605
+ unreadable: false,
3606
+ error: null,
3607
+ size: stat.size,
3608
+ mtime: stat.mtime.toISOString(),
3609
+ memoryCount: null
3610
+ };
3611
+ const client = createClient2({
3612
+ url: `file:${dbPath}`,
3613
+ encryptionKey: _encryptionKey
3614
+ });
3615
+ try {
3616
+ await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
3617
+ const hasMemories = await client.execute(
3618
+ "SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
3619
+ );
3620
+ if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
3621
+ const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
3622
+ item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
3623
+ }
3624
+ item.ok = true;
3625
+ } catch (err) {
3626
+ const message = err instanceof Error ? err.message : String(err);
3627
+ item.error = message;
3628
+ item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
3629
+ if (item.unreadable && repair && !dryRun) {
3630
+ client.close();
3631
+ _shards.delete(name);
3632
+ _shardLastAccess.delete(name);
3633
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3634
+ const archivedPath = path7.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
3635
+ renameSync3(dbPath, archivedPath);
3636
+ item.archivedPath = archivedPath;
3637
+ }
3638
+ } finally {
3639
+ try {
3640
+ client.close();
3641
+ } catch {
3642
+ }
3643
+ }
3644
+ shards.push(item);
3645
+ }
3646
+ return {
3647
+ total: shards.length,
3648
+ ok: shards.filter((s) => s.ok).length,
3649
+ unreadable: shards.filter((s) => s.unreadable).length,
3650
+ archived: shards.filter((s) => Boolean(s.archivedPath)).length,
3651
+ shards
3652
+ };
3653
+ }
3589
3654
  async function ensureShardSchema(client) {
3590
3655
  await client.execute("PRAGMA journal_mode = WAL");
3591
3656
  await client.execute("PRAGMA busy_timeout = 30000");
@@ -6960,6 +6960,7 @@ var init_memory_write_governor = __esm({
6960
6960
  // src/lib/shard-manager.ts
6961
6961
  var shard_manager_exports = {};
6962
6962
  __export(shard_manager_exports, {
6963
+ auditShardHealth: () => auditShardHealth,
6963
6964
  disposeShards: () => disposeShards,
6964
6965
  ensureShardSchema: () => ensureShardSchema,
6965
6966
  getOpenShardCount: () => getOpenShardCount,
@@ -7026,6 +7027,70 @@ function listShards() {
7026
7027
  if (!existsSync16(SHARDS_DIR)) return [];
7027
7028
  return readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
7028
7029
  }
7030
+ async function auditShardHealth(options = {}) {
7031
+ if (!_encryptionKey) {
7032
+ throw new Error("Shard manager not initialized. Call initShardManager() first.");
7033
+ }
7034
+ const repair = options.repair === true;
7035
+ const dryRun = options.dryRun === true;
7036
+ const names = listShards();
7037
+ const shards = [];
7038
+ for (const name of names) {
7039
+ const dbPath = path19.join(SHARDS_DIR, `${name}.db`);
7040
+ const stat = statSync2(dbPath);
7041
+ const item = {
7042
+ name,
7043
+ path: dbPath,
7044
+ ok: false,
7045
+ unreadable: false,
7046
+ error: null,
7047
+ size: stat.size,
7048
+ mtime: stat.mtime.toISOString(),
7049
+ memoryCount: null
7050
+ };
7051
+ const client = createClient2({
7052
+ url: `file:${dbPath}`,
7053
+ encryptionKey: _encryptionKey
7054
+ });
7055
+ try {
7056
+ await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
7057
+ const hasMemories = await client.execute(
7058
+ "SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
7059
+ );
7060
+ if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
7061
+ const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
7062
+ item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
7063
+ }
7064
+ item.ok = true;
7065
+ } catch (err) {
7066
+ const message = err instanceof Error ? err.message : String(err);
7067
+ item.error = message;
7068
+ item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
7069
+ if (item.unreadable && repair && !dryRun) {
7070
+ client.close();
7071
+ _shards.delete(name);
7072
+ _shardLastAccess.delete(name);
7073
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7074
+ const archivedPath = path19.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
7075
+ renameSync4(dbPath, archivedPath);
7076
+ item.archivedPath = archivedPath;
7077
+ }
7078
+ } finally {
7079
+ try {
7080
+ client.close();
7081
+ } catch {
7082
+ }
7083
+ }
7084
+ shards.push(item);
7085
+ }
7086
+ return {
7087
+ total: shards.length,
7088
+ ok: shards.filter((s) => s.ok).length,
7089
+ unreadable: shards.filter((s) => s.unreadable).length,
7090
+ archived: shards.filter((s) => Boolean(s.archivedPath)).length,
7091
+ shards
7092
+ };
7093
+ }
7029
7094
  async function ensureShardSchema(client) {
7030
7095
  await client.execute("PRAGMA journal_mode = WAL");
7031
7096
  await client.execute("PRAGMA busy_timeout = 30000");