@askexenow/exe-os 0.9.38 → 0.9.39

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 (69) hide show
  1. package/dist/bin/backfill-conversations.js +34 -7
  2. package/dist/bin/backfill-responses.js +34 -7
  3. package/dist/bin/backfill-vectors.js +34 -7
  4. package/dist/bin/cleanup-stale-review-tasks.js +35 -8
  5. package/dist/bin/cli.js +72 -42
  6. package/dist/bin/exe-agent.js +11 -3
  7. package/dist/bin/exe-assign.js +34 -7
  8. package/dist/bin/exe-boot.js +48 -18
  9. package/dist/bin/exe-call.js +132 -340
  10. package/dist/bin/exe-dispatch.js +34 -7
  11. package/dist/bin/exe-doctor.js +37 -10
  12. package/dist/bin/exe-export-behaviors.js +36 -9
  13. package/dist/bin/exe-forget.js +34 -7
  14. package/dist/bin/exe-gateway.js +40 -12
  15. package/dist/bin/exe-heartbeat.js +35 -8
  16. package/dist/bin/exe-kill.js +34 -7
  17. package/dist/bin/exe-launch-agent.js +285 -1079
  18. package/dist/bin/exe-new-employee.js +29 -10
  19. package/dist/bin/exe-pending-messages.js +34 -7
  20. package/dist/bin/exe-pending-notifications.js +34 -7
  21. package/dist/bin/exe-pending-reviews.js +34 -7
  22. package/dist/bin/exe-rename.js +41 -13
  23. package/dist/bin/exe-review.js +34 -7
  24. package/dist/bin/exe-search.js +36 -9
  25. package/dist/bin/exe-session-cleanup.js +36 -9
  26. package/dist/bin/exe-start-codex.js +36 -9
  27. package/dist/bin/exe-start-opencode.js +36 -9
  28. package/dist/bin/exe-status.js +35 -8
  29. package/dist/bin/exe-team.js +34 -7
  30. package/dist/bin/git-sweep.js +34 -7
  31. package/dist/bin/graph-backfill.js +34 -7
  32. package/dist/bin/graph-export.js +34 -7
  33. package/dist/bin/install.js +2 -1
  34. package/dist/bin/intercom-check.js +36 -9
  35. package/dist/bin/scan-tasks.js +34 -7
  36. package/dist/bin/setup.js +18 -17
  37. package/dist/bin/shard-migrate.js +34 -7
  38. package/dist/gateway/index.js +38 -10
  39. package/dist/hooks/bug-report-worker.js +38 -10
  40. package/dist/hooks/codex-stop-task-finalizer.js +36 -9
  41. package/dist/hooks/commit-complete.js +34 -7
  42. package/dist/hooks/error-recall.js +36 -9
  43. package/dist/hooks/ingest.js +36 -8
  44. package/dist/hooks/instructions-loaded.js +42 -10
  45. package/dist/hooks/notification.js +34 -7
  46. package/dist/hooks/post-compact.js +34 -7
  47. package/dist/hooks/post-tool-combined.js +37 -10
  48. package/dist/hooks/pre-compact.js +35 -8
  49. package/dist/hooks/pre-tool-use.js +36 -8
  50. package/dist/hooks/prompt-submit.js +41 -13
  51. package/dist/hooks/session-end.js +35 -8
  52. package/dist/hooks/session-start.js +47 -14
  53. package/dist/hooks/stop.js +35 -8
  54. package/dist/hooks/subagent-stop.js +34 -7
  55. package/dist/hooks/summary-worker.js +43 -16
  56. package/dist/index.js +36 -8
  57. package/dist/lib/consolidation.js +2 -1
  58. package/dist/lib/employee-templates.js +2 -1
  59. package/dist/lib/employees.js +2 -1
  60. package/dist/lib/exe-daemon.js +136 -36
  61. package/dist/lib/hybrid-search.js +36 -9
  62. package/dist/lib/identity.js +8 -3
  63. package/dist/lib/schedules.js +34 -7
  64. package/dist/lib/store.js +34 -7
  65. package/dist/mcp/server.js +133 -33
  66. package/dist/mcp/tools/create-task.js +10 -4
  67. package/dist/runtime/index.js +34 -7
  68. package/dist/tui/App.js +40 -11
  69. package/package.json +1 -1
@@ -302,7 +302,8 @@ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
302
302
  }
303
303
  }
304
304
  function addEmployee(employees, employee) {
305
- const normalized = { ...employee, name: employee.name.toLowerCase() };
305
+ const { systemPrompt: _legacyPrompt, ...rest } = employee;
306
+ const normalized = { ...rest, name: employee.name.toLowerCase() };
306
307
  if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
307
308
  throw new Error(`Employee '${normalized.name}' already exists`);
308
309
  }
@@ -1034,6 +1035,9 @@ function ensureDir() {
1034
1035
  function identityPath(agentId) {
1035
1036
  return path8.join(IDENTITY_DIR2, `${agentId}.md`);
1036
1037
  }
1038
+ function sanitizeIdentityBody(body) {
1039
+ return body.replace(/<!--[\s\S]*?-->/g, "").trim();
1040
+ }
1037
1041
  function parseFrontmatter(raw) {
1038
1042
  const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
1039
1043
  if (!match) {
@@ -1046,11 +1050,11 @@ function parseFrontmatter(raw) {
1046
1050
  created_by: "system",
1047
1051
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
1048
1052
  },
1049
- body: raw
1053
+ body: sanitizeIdentityBody(raw)
1050
1054
  };
1051
1055
  }
1052
1056
  const yamlStr = match[1];
1053
- const body = match[2].trim();
1057
+ const body = sanitizeIdentityBody(match[2]);
1054
1058
  const fm = {};
1055
1059
  for (const line of yamlStr.split("\n")) {
1056
1060
  const kv = line.match(/^(\w+):\s*(.+)$/);
@@ -1115,7 +1119,9 @@ function listIdentities() {
1115
1119
  const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
1116
1120
  results.push({
1117
1121
  agentId,
1118
- title: `${identity.frontmatter.title} (${identity.frontmatter.role.toUpperCase()})`,
1122
+ // User-facing/team-facing title only. `frontmatter.role` is internal
1123
+ // routing metadata and must not leak as an external title.
1124
+ title: identity.frontmatter.title,
1119
1125
  summary
1120
1126
  });
1121
1127
  }
@@ -3179,11 +3185,12 @@ async function main() {
3179
3185
  );
3180
3186
  process.exit(1);
3181
3187
  }
3188
+ const rolePrompt = template ? personalizePrompt(template.systemPrompt, template.name, name) : buildCustomEmployeePrompt(name, "specialist");
3182
3189
  if (template) {
3190
+ const { systemPrompt: _templatePrompt, ...templateMeta } = template;
3183
3191
  newEmployee = {
3184
- ...template,
3192
+ ...templateMeta,
3185
3193
  name,
3186
- systemPrompt: personalizePrompt(template.systemPrompt, template.name, name),
3187
3194
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
3188
3195
  templateName: effectiveTemplate,
3189
3196
  templateVersion: TEMPLATE_VERSION
@@ -3192,7 +3199,6 @@ async function main() {
3192
3199
  newEmployee = {
3193
3200
  name,
3194
3201
  role: "specialist",
3195
- systemPrompt: buildCustomEmployeePrompt(name, "specialist"),
3196
3202
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
3197
3203
  templateName: "custom",
3198
3204
  templateVersion: TEMPLATE_VERSION
@@ -3227,13 +3233,26 @@ async function main() {
3227
3233
  };
3228
3234
  const templateKey = roleMap[effectiveTemplate] ?? null;
3229
3235
  const identityTemplate = templateKey ? getIdentityTemplate(templateKey) : null;
3236
+ const idPath = identityPath2(name);
3237
+ const dir = path12.dirname(idPath);
3238
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
3230
3239
  if (identityTemplate) {
3231
- const idPath = identityPath2(name);
3232
- const dir = path12.dirname(idPath);
3233
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
3234
3240
  const content = identityTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`);
3235
3241
  fs.writeFileSync(idPath, content, "utf-8");
3236
3242
  console.log(`Identity doc written: ~/.exe-os/identity/${name}.md`);
3243
+ } else if (!fs.existsSync(idPath)) {
3244
+ const content = `---
3245
+ role: specialist
3246
+ title: Specialist
3247
+ agent_id: ${name}
3248
+ org_level: specialist
3249
+ created_by: exe-new-employee
3250
+ updated_at: ${(/* @__PURE__ */ new Date()).toISOString()}
3251
+ ---
3252
+
3253
+ ${rolePrompt}`;
3254
+ fs.writeFileSync(idPath, content, "utf-8");
3255
+ console.log(`Identity doc written: ~/.exe-os/identity/${name}.md`);
3237
3256
  }
3238
3257
  } catch {
3239
3258
  }
@@ -3669,7 +3669,7 @@ __export(shard_manager_exports, {
3669
3669
  shardExists: () => shardExists
3670
3670
  });
3671
3671
  import path13 from "path";
3672
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, readdirSync as readdirSync2 } from "fs";
3672
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, readdirSync as readdirSync2, renameSync as renameSync4, statSync as statSync2 } from "fs";
3673
3673
  import { createClient as createClient2 } from "@libsql/client";
3674
3674
  function initShardManager(encryptionKey) {
3675
3675
  _encryptionKey = encryptionKey;
@@ -3691,7 +3691,7 @@ function getShardClient(projectName) {
3691
3691
  if (!_encryptionKey) {
3692
3692
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3693
3693
  }
3694
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3694
+ const safeName = safeShardName(projectName);
3695
3695
  if (!safeName || safeName === "unknown") {
3696
3696
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3697
3697
  }
@@ -3713,9 +3713,12 @@ function getShardClient(projectName) {
3713
3713
  return client;
3714
3714
  }
3715
3715
  function shardExists(projectName) {
3716
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3716
+ const safeName = safeShardName(projectName);
3717
3717
  return existsSync12(path13.join(SHARDS_DIR, `${safeName}.db`));
3718
3718
  }
3719
+ function safeShardName(projectName) {
3720
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3721
+ }
3719
3722
  function listShards() {
3720
3723
  if (!existsSync12(SHARDS_DIR)) return [];
3721
3724
  return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -3809,7 +3812,8 @@ async function ensureShardSchema(client) {
3809
3812
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
3810
3813
  "ALTER TABLE memories ADD COLUMN audience TEXT",
3811
3814
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
3812
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
3815
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
3816
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
3813
3817
  ]) {
3814
3818
  try {
3815
3819
  await client.execute(col);
@@ -3905,9 +3909,32 @@ async function ensureShardSchema(client) {
3905
3909
  }
3906
3910
  }
3907
3911
  async function getReadyShardClient(projectName) {
3908
- const client = getShardClient(projectName);
3909
- await ensureShardSchema(client);
3910
- return client;
3912
+ const safeName = safeShardName(projectName);
3913
+ let client = getShardClient(projectName);
3914
+ try {
3915
+ await ensureShardSchema(client);
3916
+ return client;
3917
+ } catch (err) {
3918
+ const message = err instanceof Error ? err.message : String(err);
3919
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
3920
+ client.close();
3921
+ _shards.delete(safeName);
3922
+ _shardLastAccess.delete(safeName);
3923
+ const dbPath = path13.join(SHARDS_DIR, `${safeName}.db`);
3924
+ if (existsSync12(dbPath)) {
3925
+ const stat = statSync2(dbPath);
3926
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3927
+ const archivedPath = path13.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3928
+ renameSync4(dbPath, archivedPath);
3929
+ process.stderr.write(
3930
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
3931
+ `
3932
+ );
3933
+ }
3934
+ client = getShardClient(projectName);
3935
+ await ensureShardSchema(client);
3936
+ return client;
3937
+ }
3911
3938
  }
3912
3939
  function evictLRU() {
3913
3940
  let oldest = null;
@@ -3735,7 +3735,7 @@ __export(shard_manager_exports, {
3735
3735
  shardExists: () => shardExists
3736
3736
  });
3737
3737
  import path14 from "path";
3738
- import { existsSync as existsSync13, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
3738
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5, readdirSync as readdirSync3, renameSync as renameSync4, statSync as statSync2 } from "fs";
3739
3739
  import { createClient as createClient2 } from "@libsql/client";
3740
3740
  function initShardManager(encryptionKey) {
3741
3741
  _encryptionKey = encryptionKey;
@@ -3757,7 +3757,7 @@ function getShardClient(projectName) {
3757
3757
  if (!_encryptionKey) {
3758
3758
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3759
3759
  }
3760
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3760
+ const safeName = safeShardName(projectName);
3761
3761
  if (!safeName || safeName === "unknown") {
3762
3762
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3763
3763
  }
@@ -3779,9 +3779,12 @@ function getShardClient(projectName) {
3779
3779
  return client;
3780
3780
  }
3781
3781
  function shardExists(projectName) {
3782
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3782
+ const safeName = safeShardName(projectName);
3783
3783
  return existsSync13(path14.join(SHARDS_DIR, `${safeName}.db`));
3784
3784
  }
3785
+ function safeShardName(projectName) {
3786
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3787
+ }
3785
3788
  function listShards() {
3786
3789
  if (!existsSync13(SHARDS_DIR)) return [];
3787
3790
  return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -3875,7 +3878,8 @@ async function ensureShardSchema(client) {
3875
3878
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
3876
3879
  "ALTER TABLE memories ADD COLUMN audience TEXT",
3877
3880
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
3878
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
3881
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
3882
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
3879
3883
  ]) {
3880
3884
  try {
3881
3885
  await client.execute(col);
@@ -3971,9 +3975,32 @@ async function ensureShardSchema(client) {
3971
3975
  }
3972
3976
  }
3973
3977
  async function getReadyShardClient(projectName) {
3974
- const client = getShardClient(projectName);
3975
- await ensureShardSchema(client);
3976
- return client;
3978
+ const safeName = safeShardName(projectName);
3979
+ let client = getShardClient(projectName);
3980
+ try {
3981
+ await ensureShardSchema(client);
3982
+ return client;
3983
+ } catch (err) {
3984
+ const message = err instanceof Error ? err.message : String(err);
3985
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
3986
+ client.close();
3987
+ _shards.delete(safeName);
3988
+ _shardLastAccess.delete(safeName);
3989
+ const dbPath = path14.join(SHARDS_DIR, `${safeName}.db`);
3990
+ if (existsSync13(dbPath)) {
3991
+ const stat = statSync2(dbPath);
3992
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3993
+ const archivedPath = path14.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3994
+ renameSync4(dbPath, archivedPath);
3995
+ process.stderr.write(
3996
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
3997
+ `
3998
+ );
3999
+ }
4000
+ client = getShardClient(projectName);
4001
+ await ensureShardSchema(client);
4002
+ return client;
4003
+ }
3977
4004
  }
3978
4005
  function evictLRU() {
3979
4006
  let oldest = null;
@@ -3774,7 +3774,7 @@ __export(shard_manager_exports, {
3774
3774
  shardExists: () => shardExists
3775
3775
  });
3776
3776
  import path15 from "path";
3777
- import { existsSync as existsSync14, mkdirSync as mkdirSync5, readdirSync as readdirSync4 } from "fs";
3777
+ import { existsSync as existsSync14, mkdirSync as mkdirSync5, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync2 } from "fs";
3778
3778
  import { createClient as createClient2 } from "@libsql/client";
3779
3779
  function initShardManager(encryptionKey) {
3780
3780
  _encryptionKey = encryptionKey;
@@ -3796,7 +3796,7 @@ function getShardClient(projectName) {
3796
3796
  if (!_encryptionKey) {
3797
3797
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3798
3798
  }
3799
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3799
+ const safeName = safeShardName(projectName);
3800
3800
  if (!safeName || safeName === "unknown") {
3801
3801
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3802
3802
  }
@@ -3818,9 +3818,12 @@ function getShardClient(projectName) {
3818
3818
  return client;
3819
3819
  }
3820
3820
  function shardExists(projectName) {
3821
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3821
+ const safeName = safeShardName(projectName);
3822
3822
  return existsSync14(path15.join(SHARDS_DIR, `${safeName}.db`));
3823
3823
  }
3824
+ function safeShardName(projectName) {
3825
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3826
+ }
3824
3827
  function listShards() {
3825
3828
  if (!existsSync14(SHARDS_DIR)) return [];
3826
3829
  return readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -3914,7 +3917,8 @@ async function ensureShardSchema(client) {
3914
3917
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
3915
3918
  "ALTER TABLE memories ADD COLUMN audience TEXT",
3916
3919
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
3917
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
3920
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
3921
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
3918
3922
  ]) {
3919
3923
  try {
3920
3924
  await client.execute(col);
@@ -4010,9 +4014,32 @@ async function ensureShardSchema(client) {
4010
4014
  }
4011
4015
  }
4012
4016
  async function getReadyShardClient(projectName) {
4013
- const client = getShardClient(projectName);
4014
- await ensureShardSchema(client);
4015
- return client;
4017
+ const safeName = safeShardName(projectName);
4018
+ let client = getShardClient(projectName);
4019
+ try {
4020
+ await ensureShardSchema(client);
4021
+ return client;
4022
+ } catch (err) {
4023
+ const message = err instanceof Error ? err.message : String(err);
4024
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
4025
+ client.close();
4026
+ _shards.delete(safeName);
4027
+ _shardLastAccess.delete(safeName);
4028
+ const dbPath = path15.join(SHARDS_DIR, `${safeName}.db`);
4029
+ if (existsSync14(dbPath)) {
4030
+ const stat = statSync2(dbPath);
4031
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4032
+ const archivedPath = path15.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
4033
+ renameSync4(dbPath, archivedPath);
4034
+ process.stderr.write(
4035
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
4036
+ `
4037
+ );
4038
+ }
4039
+ client = getShardClient(projectName);
4040
+ await ensureShardSchema(client);
4041
+ return client;
4042
+ }
4016
4043
  }
4017
4044
  function evictLRU() {
4018
4045
  let oldest = null;
@@ -3354,7 +3354,7 @@ __export(shard_manager_exports, {
3354
3354
  shardExists: () => shardExists
3355
3355
  });
3356
3356
  import path7 from "path";
3357
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
3357
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
3358
3358
  import { createClient as createClient2 } from "@libsql/client";
3359
3359
  function initShardManager(encryptionKey) {
3360
3360
  _encryptionKey = encryptionKey;
@@ -3376,7 +3376,7 @@ function getShardClient(projectName) {
3376
3376
  if (!_encryptionKey) {
3377
3377
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3378
3378
  }
3379
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3379
+ const safeName = safeShardName(projectName);
3380
3380
  if (!safeName || safeName === "unknown") {
3381
3381
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3382
3382
  }
@@ -3398,9 +3398,12 @@ function getShardClient(projectName) {
3398
3398
  return client;
3399
3399
  }
3400
3400
  function shardExists(projectName) {
3401
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3401
+ const safeName = safeShardName(projectName);
3402
3402
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
3403
3403
  }
3404
+ function safeShardName(projectName) {
3405
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3406
+ }
3404
3407
  function listShards() {
3405
3408
  if (!existsSync7(SHARDS_DIR)) return [];
3406
3409
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -3494,7 +3497,8 @@ async function ensureShardSchema(client) {
3494
3497
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
3495
3498
  "ALTER TABLE memories ADD COLUMN audience TEXT",
3496
3499
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
3497
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
3500
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
3501
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
3498
3502
  ]) {
3499
3503
  try {
3500
3504
  await client.execute(col);
@@ -3590,9 +3594,32 @@ async function ensureShardSchema(client) {
3590
3594
  }
3591
3595
  }
3592
3596
  async function getReadyShardClient(projectName) {
3593
- const client = getShardClient(projectName);
3594
- await ensureShardSchema(client);
3595
- return client;
3597
+ const safeName = safeShardName(projectName);
3598
+ let client = getShardClient(projectName);
3599
+ try {
3600
+ await ensureShardSchema(client);
3601
+ return client;
3602
+ } catch (err) {
3603
+ const message = err instanceof Error ? err.message : String(err);
3604
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
3605
+ client.close();
3606
+ _shards.delete(safeName);
3607
+ _shardLastAccess.delete(safeName);
3608
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
3609
+ if (existsSync7(dbPath)) {
3610
+ const stat = statSync2(dbPath);
3611
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3612
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3613
+ renameSync3(dbPath, archivedPath);
3614
+ process.stderr.write(
3615
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
3616
+ `
3617
+ );
3618
+ }
3619
+ client = getShardClient(projectName);
3620
+ await ensureShardSchema(client);
3621
+ return client;
3622
+ }
3596
3623
  }
3597
3624
  function evictLRU() {
3598
3625
  let oldest = null;
@@ -4277,7 +4304,7 @@ var init_store = __esm({
4277
4304
 
4278
4305
  // src/bin/exe-rename.ts
4279
4306
  init_employees();
4280
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync3, existsSync as existsSync8 } from "fs";
4307
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync as renameSync4, unlinkSync as unlinkSync3, existsSync as existsSync8 } from "fs";
4281
4308
  import { execSync as execSync3 } from "child_process";
4282
4309
  import path8 from "path";
4283
4310
  import { homedir } from "os";
@@ -4331,7 +4358,8 @@ async function renameEmployee(oldName, newName, opts = {}) {
4331
4358
  const originalName = employee.name;
4332
4359
  const originalPrompt = employee.systemPrompt;
4333
4360
  employee.name = newName;
4334
- employee.systemPrompt = personalizePrompt(originalPrompt, rosterOldName, newName);
4361
+ if (originalPrompt) employee.systemPrompt = personalizePrompt(originalPrompt, rosterOldName, newName);
4362
+ else delete employee.systemPrompt;
4335
4363
  await saveEmployees(employees, rosterPath);
4336
4364
  rollbackStack.push({
4337
4365
  description: "restore roster",
@@ -4349,14 +4377,14 @@ async function renameEmployee(oldName, newName, opts = {}) {
4349
4377
  /^(agent_id:\s*)\S+/m,
4350
4378
  `$1${newName}`
4351
4379
  );
4352
- renameSync3(oldIdentityPath, newIdentityPath);
4380
+ renameSync4(oldIdentityPath, newIdentityPath);
4353
4381
  writeFileSync3(newIdentityPath, updatedContent, "utf-8");
4354
4382
  rollbackStack.push({
4355
4383
  description: "restore identity file",
4356
4384
  undo: () => {
4357
4385
  if (existsSync8(newIdentityPath)) {
4358
4386
  writeFileSync3(newIdentityPath, content, "utf-8");
4359
- renameSync3(newIdentityPath, oldIdentityPath);
4387
+ renameSync4(newIdentityPath, oldIdentityPath);
4360
4388
  }
4361
4389
  }
4362
4390
  });
@@ -4365,12 +4393,12 @@ async function renameEmployee(oldName, newName, opts = {}) {
4365
4393
  const newAgentPath = path8.join(agentsDir, `${newName}.md`);
4366
4394
  if (existsSync8(oldAgentPath)) {
4367
4395
  const agentContent = readFileSync5(oldAgentPath, "utf-8");
4368
- renameSync3(oldAgentPath, newAgentPath);
4396
+ renameSync4(oldAgentPath, newAgentPath);
4369
4397
  rollbackStack.push({
4370
4398
  description: "restore agent file",
4371
4399
  undo: () => {
4372
4400
  if (existsSync8(newAgentPath)) {
4373
- renameSync3(newAgentPath, oldAgentPath);
4401
+ renameSync4(newAgentPath, oldAgentPath);
4374
4402
  writeFileSync3(oldAgentPath, agentContent, "utf-8");
4375
4403
  }
4376
4404
  }
@@ -3264,7 +3264,7 @@ __export(shard_manager_exports, {
3264
3264
  shardExists: () => shardExists
3265
3265
  });
3266
3266
  import path7 from "path";
3267
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
3267
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
3268
3268
  import { createClient as createClient2 } from "@libsql/client";
3269
3269
  function initShardManager(encryptionKey) {
3270
3270
  _encryptionKey = encryptionKey;
@@ -3286,7 +3286,7 @@ function getShardClient(projectName) {
3286
3286
  if (!_encryptionKey) {
3287
3287
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3288
3288
  }
3289
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3289
+ const safeName = safeShardName(projectName);
3290
3290
  if (!safeName || safeName === "unknown") {
3291
3291
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3292
3292
  }
@@ -3308,9 +3308,12 @@ function getShardClient(projectName) {
3308
3308
  return client;
3309
3309
  }
3310
3310
  function shardExists(projectName) {
3311
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3311
+ const safeName = safeShardName(projectName);
3312
3312
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
3313
3313
  }
3314
+ function safeShardName(projectName) {
3315
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3316
+ }
3314
3317
  function listShards() {
3315
3318
  if (!existsSync7(SHARDS_DIR)) return [];
3316
3319
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -3404,7 +3407,8 @@ async function ensureShardSchema(client) {
3404
3407
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
3405
3408
  "ALTER TABLE memories ADD COLUMN audience TEXT",
3406
3409
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
3407
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
3410
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
3411
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
3408
3412
  ]) {
3409
3413
  try {
3410
3414
  await client.execute(col);
@@ -3500,9 +3504,32 @@ async function ensureShardSchema(client) {
3500
3504
  }
3501
3505
  }
3502
3506
  async function getReadyShardClient(projectName) {
3503
- const client = getShardClient(projectName);
3504
- await ensureShardSchema(client);
3505
- return client;
3507
+ const safeName = safeShardName(projectName);
3508
+ let client = getShardClient(projectName);
3509
+ try {
3510
+ await ensureShardSchema(client);
3511
+ return client;
3512
+ } catch (err) {
3513
+ const message = err instanceof Error ? err.message : String(err);
3514
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
3515
+ client.close();
3516
+ _shards.delete(safeName);
3517
+ _shardLastAccess.delete(safeName);
3518
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
3519
+ if (existsSync7(dbPath)) {
3520
+ const stat = statSync2(dbPath);
3521
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3522
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3523
+ renameSync3(dbPath, archivedPath);
3524
+ process.stderr.write(
3525
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
3526
+ `
3527
+ );
3528
+ }
3529
+ client = getShardClient(projectName);
3530
+ await ensureShardSchema(client);
3531
+ return client;
3532
+ }
3506
3533
  }
3507
3534
  function evictLRU() {
3508
3535
  let oldest = null;
@@ -3239,7 +3239,7 @@ __export(shard_manager_exports, {
3239
3239
  shardExists: () => shardExists
3240
3240
  });
3241
3241
  import path7 from "path";
3242
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
3242
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
3243
3243
  import { createClient as createClient2 } from "@libsql/client";
3244
3244
  function initShardManager(encryptionKey) {
3245
3245
  _encryptionKey = encryptionKey;
@@ -3261,7 +3261,7 @@ function getShardClient(projectName) {
3261
3261
  if (!_encryptionKey) {
3262
3262
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3263
3263
  }
3264
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3264
+ const safeName = safeShardName(projectName);
3265
3265
  if (!safeName || safeName === "unknown") {
3266
3266
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3267
3267
  }
@@ -3283,9 +3283,12 @@ function getShardClient(projectName) {
3283
3283
  return client;
3284
3284
  }
3285
3285
  function shardExists(projectName) {
3286
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3286
+ const safeName = safeShardName(projectName);
3287
3287
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
3288
3288
  }
3289
+ function safeShardName(projectName) {
3290
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3291
+ }
3289
3292
  function listShards() {
3290
3293
  if (!existsSync7(SHARDS_DIR)) return [];
3291
3294
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -3379,7 +3382,8 @@ async function ensureShardSchema(client) {
3379
3382
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
3380
3383
  "ALTER TABLE memories ADD COLUMN audience TEXT",
3381
3384
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
3382
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
3385
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
3386
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
3383
3387
  ]) {
3384
3388
  try {
3385
3389
  await client.execute(col);
@@ -3475,9 +3479,32 @@ async function ensureShardSchema(client) {
3475
3479
  }
3476
3480
  }
3477
3481
  async function getReadyShardClient(projectName) {
3478
- const client = getShardClient(projectName);
3479
- await ensureShardSchema(client);
3480
- return client;
3482
+ const safeName = safeShardName(projectName);
3483
+ let client = getShardClient(projectName);
3484
+ try {
3485
+ await ensureShardSchema(client);
3486
+ return client;
3487
+ } catch (err) {
3488
+ const message = err instanceof Error ? err.message : String(err);
3489
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
3490
+ client.close();
3491
+ _shards.delete(safeName);
3492
+ _shardLastAccess.delete(safeName);
3493
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
3494
+ if (existsSync7(dbPath)) {
3495
+ const stat = statSync2(dbPath);
3496
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3497
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3498
+ renameSync3(dbPath, archivedPath);
3499
+ process.stderr.write(
3500
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
3501
+ `
3502
+ );
3503
+ }
3504
+ client = getShardClient(projectName);
3505
+ await ensureShardSchema(client);
3506
+ return client;
3507
+ }
3481
3508
  }
3482
3509
  function evictLRU() {
3483
3510
  let oldest = null;
@@ -4752,7 +4779,7 @@ __export(file_grep_exports, {
4752
4779
  grepProjectFiles: () => grepProjectFiles
4753
4780
  });
4754
4781
  import { execSync as execSync4 } from "child_process";
4755
- import { readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync2, existsSync as existsSync9 } from "fs";
4782
+ import { readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3, existsSync as existsSync9 } from "fs";
4756
4783
  import path10 from "path";
4757
4784
  import crypto2 from "crypto";
4758
4785
  function hasRipgrep() {
@@ -4869,7 +4896,7 @@ function grepWithNodeFs(pattern, projectRoot, patterns) {
4869
4896
  for (const filePath of files.slice(0, MAX_FILES)) {
4870
4897
  const absPath = path10.join(projectRoot, filePath);
4871
4898
  try {
4872
- const stat = statSync2(absPath);
4899
+ const stat = statSync3(absPath);
4873
4900
  if (stat.size > MAX_FILE_SIZE) continue;
4874
4901
  const content = readFileSync5(absPath, "utf8");
4875
4902
  const lines = content.split("\n");