@askexenow/exe-os 0.9.37 → 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 (73) hide show
  1. package/deploy/stack-manifests/v0.9.json +55 -0
  2. package/dist/bin/backfill-conversations.js +36 -9
  3. package/dist/bin/backfill-responses.js +36 -9
  4. package/dist/bin/backfill-vectors.js +36 -9
  5. package/dist/bin/cleanup-stale-review-tasks.js +37 -10
  6. package/dist/bin/cli.js +624 -204
  7. package/dist/bin/exe-agent.js +13 -5
  8. package/dist/bin/exe-assign.js +36 -9
  9. package/dist/bin/exe-boot.js +50 -20
  10. package/dist/bin/exe-call.js +134 -342
  11. package/dist/bin/exe-dispatch.js +36 -9
  12. package/dist/bin/exe-doctor.js +39 -12
  13. package/dist/bin/exe-export-behaviors.js +38 -11
  14. package/dist/bin/exe-forget.js +36 -9
  15. package/dist/bin/exe-gateway.js +64 -15
  16. package/dist/bin/exe-heartbeat.js +37 -10
  17. package/dist/bin/exe-kill.js +36 -9
  18. package/dist/bin/exe-launch-agent.js +287 -1081
  19. package/dist/bin/exe-new-employee.js +100 -14
  20. package/dist/bin/exe-pending-messages.js +36 -9
  21. package/dist/bin/exe-pending-notifications.js +36 -9
  22. package/dist/bin/exe-pending-reviews.js +36 -9
  23. package/dist/bin/exe-rename.js +1780 -204
  24. package/dist/bin/exe-review.js +36 -9
  25. package/dist/bin/exe-search.js +38 -11
  26. package/dist/bin/exe-session-cleanup.js +38 -11
  27. package/dist/bin/exe-start-codex.js +38 -11
  28. package/dist/bin/exe-start-opencode.js +38 -11
  29. package/dist/bin/exe-status.js +37 -10
  30. package/dist/bin/exe-team.js +36 -9
  31. package/dist/bin/git-sweep.js +36 -9
  32. package/dist/bin/graph-backfill.js +36 -9
  33. package/dist/bin/graph-export.js +36 -9
  34. package/dist/bin/install.js +70 -3
  35. package/dist/bin/intercom-check.js +38 -11
  36. package/dist/bin/scan-tasks.js +36 -9
  37. package/dist/bin/setup.js +20 -19
  38. package/dist/bin/shard-migrate.js +36 -9
  39. package/dist/bin/stack-update.js +308 -0
  40. package/dist/gateway/index.js +62 -13
  41. package/dist/hooks/bug-report-worker.js +40 -12
  42. package/dist/hooks/codex-stop-task-finalizer.js +38 -11
  43. package/dist/hooks/commit-complete.js +36 -9
  44. package/dist/hooks/error-recall.js +38 -11
  45. package/dist/hooks/ingest.js +38 -10
  46. package/dist/hooks/instructions-loaded.js +44 -12
  47. package/dist/hooks/notification.js +36 -9
  48. package/dist/hooks/post-compact.js +36 -9
  49. package/dist/hooks/post-tool-combined.js +39 -12
  50. package/dist/hooks/pre-compact.js +37 -10
  51. package/dist/hooks/pre-tool-use.js +38 -10
  52. package/dist/hooks/prompt-submit.js +43 -15
  53. package/dist/hooks/session-end.js +37 -10
  54. package/dist/hooks/session-start.js +49 -16
  55. package/dist/hooks/stop.js +37 -10
  56. package/dist/hooks/subagent-stop.js +36 -9
  57. package/dist/hooks/summary-worker.js +45 -18
  58. package/dist/index.js +60 -11
  59. package/dist/lib/consolidation.js +2 -1
  60. package/dist/lib/employee-templates.js +4 -3
  61. package/dist/lib/employees.js +2 -1
  62. package/dist/lib/exe-daemon.js +11229 -10537
  63. package/dist/lib/hybrid-search.js +38 -11
  64. package/dist/lib/identity.js +8 -3
  65. package/dist/lib/schedules.js +36 -9
  66. package/dist/lib/store.js +36 -9
  67. package/dist/mcp/server.js +6873 -6249
  68. package/dist/mcp/tools/create-task.js +10 -4
  69. package/dist/runtime/index.js +36 -9
  70. package/dist/tui/App.js +42 -13
  71. package/package.json +4 -1
  72. package/stack.release.json +31 -0
  73. package/stack.release.schema.json +31 -0
@@ -3238,7 +3238,7 @@ __export(shard_manager_exports, {
3238
3238
  shardExists: () => shardExists
3239
3239
  });
3240
3240
  import path7 from "path";
3241
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
3241
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
3242
3242
  import { createClient as createClient2 } from "@libsql/client";
3243
3243
  function initShardManager(encryptionKey) {
3244
3244
  _encryptionKey = encryptionKey;
@@ -3260,7 +3260,7 @@ function getShardClient(projectName) {
3260
3260
  if (!_encryptionKey) {
3261
3261
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3262
3262
  }
3263
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3263
+ const safeName = safeShardName(projectName);
3264
3264
  if (!safeName || safeName === "unknown") {
3265
3265
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3266
3266
  }
@@ -3282,9 +3282,12 @@ function getShardClient(projectName) {
3282
3282
  return client;
3283
3283
  }
3284
3284
  function shardExists(projectName) {
3285
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3285
+ const safeName = safeShardName(projectName);
3286
3286
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
3287
3287
  }
3288
+ function safeShardName(projectName) {
3289
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3290
+ }
3288
3291
  function listShards() {
3289
3292
  if (!existsSync7(SHARDS_DIR)) return [];
3290
3293
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -3378,7 +3381,8 @@ async function ensureShardSchema(client) {
3378
3381
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
3379
3382
  "ALTER TABLE memories ADD COLUMN audience TEXT",
3380
3383
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
3381
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
3384
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
3385
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
3382
3386
  ]) {
3383
3387
  try {
3384
3388
  await client.execute(col);
@@ -3474,9 +3478,32 @@ async function ensureShardSchema(client) {
3474
3478
  }
3475
3479
  }
3476
3480
  async function getReadyShardClient(projectName) {
3477
- const client = getShardClient(projectName);
3478
- await ensureShardSchema(client);
3479
- return client;
3481
+ const safeName = safeShardName(projectName);
3482
+ let client = getShardClient(projectName);
3483
+ try {
3484
+ await ensureShardSchema(client);
3485
+ return client;
3486
+ } catch (err) {
3487
+ const message = err instanceof Error ? err.message : String(err);
3488
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
3489
+ client.close();
3490
+ _shards.delete(safeName);
3491
+ _shardLastAccess.delete(safeName);
3492
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
3493
+ if (existsSync7(dbPath)) {
3494
+ const stat = statSync2(dbPath);
3495
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3496
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3497
+ renameSync3(dbPath, archivedPath);
3498
+ process.stderr.write(
3499
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
3500
+ `
3501
+ );
3502
+ }
3503
+ client = getShardClient(projectName);
3504
+ await ensureShardSchema(client);
3505
+ return client;
3506
+ }
3480
3507
  }
3481
3508
  function evictLRU() {
3482
3509
  let oldest = null;
@@ -3697,7 +3724,7 @@ var init_platform_procedures = __esm({
3697
3724
  title: "MCP tools \u2014 wiki, documents, and content",
3698
3725
  domain: "tool-use",
3699
3726
  priority: "p1",
3700
- content: "create_wiki_page: create a wiki page in exe-wiki. list_wiki_pages: browse wiki pages. get_wiki_page: read a wiki page. update_wiki_page: edit a wiki page. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
3727
+ content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
3701
3728
  },
3702
3729
  {
3703
3730
  title: "MCP tools \u2014 system, operations, and admin",
@@ -3715,7 +3742,7 @@ var init_platform_procedures = __esm({
3715
3742
  title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
3716
3743
  domain: "tool-use",
3717
3744
  priority: "p1",
3718
- content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage Layer 0 procedures (actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
3745
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
3719
3746
  }
3720
3747
  ];
3721
3748
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -4751,7 +4778,7 @@ __export(file_grep_exports, {
4751
4778
  grepProjectFiles: () => grepProjectFiles
4752
4779
  });
4753
4780
  import { execSync as execSync4 } from "child_process";
4754
- import { readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync2, existsSync as existsSync9 } from "fs";
4781
+ import { readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3, existsSync as existsSync9 } from "fs";
4755
4782
  import path10 from "path";
4756
4783
  import crypto2 from "crypto";
4757
4784
  function hasRipgrep() {
@@ -4868,7 +4895,7 @@ function grepWithNodeFs(pattern, projectRoot, patterns) {
4868
4895
  for (const filePath of files.slice(0, MAX_FILES)) {
4869
4896
  const absPath = path10.join(projectRoot, filePath);
4870
4897
  try {
4871
- const stat = statSync2(absPath);
4898
+ const stat = statSync3(absPath);
4872
4899
  if (stat.size > MAX_FILE_SIZE) continue;
4873
4900
  const content = readFileSync5(absPath, "utf8");
4874
4901
  const lines = content.split("\n");
@@ -169,6 +169,9 @@ function ensureDir() {
169
169
  function identityPath(agentId) {
170
170
  return path4.join(IDENTITY_DIR2, `${agentId}.md`);
171
171
  }
172
+ function sanitizeIdentityBody(body) {
173
+ return body.replace(/<!--[\s\S]*?-->/g, "").trim();
174
+ }
172
175
  function parseFrontmatter(raw) {
173
176
  const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
174
177
  if (!match) {
@@ -181,11 +184,11 @@ function parseFrontmatter(raw) {
181
184
  created_by: "system",
182
185
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
183
186
  },
184
- body: raw
187
+ body: sanitizeIdentityBody(raw)
185
188
  };
186
189
  }
187
190
  const yamlStr = match[1];
188
- const body = match[2].trim();
191
+ const body = sanitizeIdentityBody(match[2]);
189
192
  const fm = {};
190
193
  for (const line of yamlStr.split("\n")) {
191
194
  const kv = line.match(/^(\w+):\s*(.+)$/);
@@ -250,7 +253,9 @@ function listIdentities() {
250
253
  const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
251
254
  results.push({
252
255
  agentId,
253
- title: `${identity.frontmatter.title} (${identity.frontmatter.role.toUpperCase()})`,
256
+ // User-facing/team-facing title only. `frontmatter.role` is internal
257
+ // routing metadata and must not leak as an external title.
258
+ title: identity.frontmatter.title,
254
259
  summary
255
260
  });
256
261
  }
@@ -2600,7 +2600,7 @@ __export(shard_manager_exports, {
2600
2600
  shardExists: () => shardExists
2601
2601
  });
2602
2602
  import path7 from "path";
2603
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
2603
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
2604
2604
  import { createClient as createClient2 } from "@libsql/client";
2605
2605
  function initShardManager(encryptionKey) {
2606
2606
  _encryptionKey = encryptionKey;
@@ -2622,7 +2622,7 @@ function getShardClient(projectName) {
2622
2622
  if (!_encryptionKey) {
2623
2623
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
2624
2624
  }
2625
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2625
+ const safeName = safeShardName(projectName);
2626
2626
  if (!safeName || safeName === "unknown") {
2627
2627
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
2628
2628
  }
@@ -2644,9 +2644,12 @@ function getShardClient(projectName) {
2644
2644
  return client;
2645
2645
  }
2646
2646
  function shardExists(projectName) {
2647
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2647
+ const safeName = safeShardName(projectName);
2648
2648
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
2649
2649
  }
2650
+ function safeShardName(projectName) {
2651
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2652
+ }
2650
2653
  function listShards() {
2651
2654
  if (!existsSync7(SHARDS_DIR)) return [];
2652
2655
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -2740,7 +2743,8 @@ async function ensureShardSchema(client) {
2740
2743
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
2741
2744
  "ALTER TABLE memories ADD COLUMN audience TEXT",
2742
2745
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
2743
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
2746
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
2747
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
2744
2748
  ]) {
2745
2749
  try {
2746
2750
  await client.execute(col);
@@ -2836,9 +2840,32 @@ async function ensureShardSchema(client) {
2836
2840
  }
2837
2841
  }
2838
2842
  async function getReadyShardClient(projectName) {
2839
- const client = getShardClient(projectName);
2840
- await ensureShardSchema(client);
2841
- return client;
2843
+ const safeName = safeShardName(projectName);
2844
+ let client = getShardClient(projectName);
2845
+ try {
2846
+ await ensureShardSchema(client);
2847
+ return client;
2848
+ } catch (err) {
2849
+ const message = err instanceof Error ? err.message : String(err);
2850
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
2851
+ client.close();
2852
+ _shards.delete(safeName);
2853
+ _shardLastAccess.delete(safeName);
2854
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
2855
+ if (existsSync7(dbPath)) {
2856
+ const stat = statSync2(dbPath);
2857
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2858
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
2859
+ renameSync3(dbPath, archivedPath);
2860
+ process.stderr.write(
2861
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
2862
+ `
2863
+ );
2864
+ }
2865
+ client = getShardClient(projectName);
2866
+ await ensureShardSchema(client);
2867
+ return client;
2868
+ }
2842
2869
  }
2843
2870
  function evictLRU() {
2844
2871
  let oldest = null;
@@ -3059,7 +3086,7 @@ var init_platform_procedures = __esm({
3059
3086
  title: "MCP tools \u2014 wiki, documents, and content",
3060
3087
  domain: "tool-use",
3061
3088
  priority: "p1",
3062
- content: "create_wiki_page: create a wiki page in exe-wiki. list_wiki_pages: browse wiki pages. get_wiki_page: read a wiki page. update_wiki_page: edit a wiki page. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
3089
+ content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
3063
3090
  },
3064
3091
  {
3065
3092
  title: "MCP tools \u2014 system, operations, and admin",
@@ -3077,7 +3104,7 @@ var init_platform_procedures = __esm({
3077
3104
  title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
3078
3105
  domain: "tool-use",
3079
3106
  priority: "p1",
3080
- content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage Layer 0 procedures (actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
3107
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
3081
3108
  }
3082
3109
  ];
3083
3110
  PLATFORM_PROCEDURE_TITLES = new Set(
package/dist/lib/store.js CHANGED
@@ -2600,7 +2600,7 @@ __export(shard_manager_exports, {
2600
2600
  shardExists: () => shardExists
2601
2601
  });
2602
2602
  import path7 from "path";
2603
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
2603
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
2604
2604
  import { createClient as createClient2 } from "@libsql/client";
2605
2605
  function initShardManager(encryptionKey) {
2606
2606
  _encryptionKey = encryptionKey;
@@ -2622,7 +2622,7 @@ function getShardClient(projectName) {
2622
2622
  if (!_encryptionKey) {
2623
2623
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
2624
2624
  }
2625
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2625
+ const safeName = safeShardName(projectName);
2626
2626
  if (!safeName || safeName === "unknown") {
2627
2627
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
2628
2628
  }
@@ -2644,9 +2644,12 @@ function getShardClient(projectName) {
2644
2644
  return client;
2645
2645
  }
2646
2646
  function shardExists(projectName) {
2647
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2647
+ const safeName = safeShardName(projectName);
2648
2648
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
2649
2649
  }
2650
+ function safeShardName(projectName) {
2651
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2652
+ }
2650
2653
  function listShards() {
2651
2654
  if (!existsSync7(SHARDS_DIR)) return [];
2652
2655
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -2740,7 +2743,8 @@ async function ensureShardSchema(client) {
2740
2743
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
2741
2744
  "ALTER TABLE memories ADD COLUMN audience TEXT",
2742
2745
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
2743
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
2746
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
2747
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
2744
2748
  ]) {
2745
2749
  try {
2746
2750
  await client.execute(col);
@@ -2836,9 +2840,32 @@ async function ensureShardSchema(client) {
2836
2840
  }
2837
2841
  }
2838
2842
  async function getReadyShardClient(projectName) {
2839
- const client = getShardClient(projectName);
2840
- await ensureShardSchema(client);
2841
- return client;
2843
+ const safeName = safeShardName(projectName);
2844
+ let client = getShardClient(projectName);
2845
+ try {
2846
+ await ensureShardSchema(client);
2847
+ return client;
2848
+ } catch (err) {
2849
+ const message = err instanceof Error ? err.message : String(err);
2850
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
2851
+ client.close();
2852
+ _shards.delete(safeName);
2853
+ _shardLastAccess.delete(safeName);
2854
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
2855
+ if (existsSync7(dbPath)) {
2856
+ const stat = statSync2(dbPath);
2857
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2858
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
2859
+ renameSync3(dbPath, archivedPath);
2860
+ process.stderr.write(
2861
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
2862
+ `
2863
+ );
2864
+ }
2865
+ client = getShardClient(projectName);
2866
+ await ensureShardSchema(client);
2867
+ return client;
2868
+ }
2842
2869
  }
2843
2870
  function evictLRU() {
2844
2871
  let oldest = null;
@@ -3059,7 +3086,7 @@ var init_platform_procedures = __esm({
3059
3086
  title: "MCP tools \u2014 wiki, documents, and content",
3060
3087
  domain: "tool-use",
3061
3088
  priority: "p1",
3062
- content: "create_wiki_page: create a wiki page in exe-wiki. list_wiki_pages: browse wiki pages. get_wiki_page: read a wiki page. update_wiki_page: edit a wiki page. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
3089
+ content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
3063
3090
  },
3064
3091
  {
3065
3092
  title: "MCP tools \u2014 system, operations, and admin",
@@ -3077,7 +3104,7 @@ var init_platform_procedures = __esm({
3077
3104
  title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
3078
3105
  domain: "tool-use",
3079
3106
  priority: "p1",
3080
- content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage Layer 0 procedures (actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
3107
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
3081
3108
  }
3082
3109
  ];
3083
3110
  PLATFORM_PROCEDURE_TITLES = new Set(