@askexenow/exe-os 0.9.16 → 0.9.18

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 (97) hide show
  1. package/dist/bin/backfill-conversations.js +1242 -909
  2. package/dist/bin/backfill-responses.js +1245 -912
  3. package/dist/bin/backfill-vectors.js +1244 -906
  4. package/dist/bin/cleanup-stale-review-tasks.js +1870 -417
  5. package/dist/bin/cli.js +217 -107
  6. package/dist/bin/exe-agent-config.js +2 -2
  7. package/dist/bin/exe-agent.js +62 -0
  8. package/dist/bin/exe-assign.js +346 -10
  9. package/dist/bin/exe-boot.js +387 -32
  10. package/dist/bin/exe-call.js +72 -2
  11. package/dist/bin/exe-cloud.js +8 -0
  12. package/dist/bin/exe-dispatch.js +1821 -225
  13. package/dist/bin/exe-doctor.js +720 -52
  14. package/dist/bin/exe-export-behaviors.js +1429 -148
  15. package/dist/bin/exe-forget.js +1408 -34
  16. package/dist/bin/exe-gateway.js +1629 -1295
  17. package/dist/bin/exe-heartbeat.js +1899 -448
  18. package/dist/bin/exe-kill.js +1624 -346
  19. package/dist/bin/exe-launch-agent.js +726 -90
  20. package/dist/bin/exe-link.js +27 -8
  21. package/dist/bin/exe-new-employee.js +75 -9
  22. package/dist/bin/exe-pending-messages.js +2769 -1316
  23. package/dist/bin/exe-pending-notifications.js +2829 -1376
  24. package/dist/bin/exe-pending-reviews.js +2847 -1392
  25. package/dist/bin/exe-rename.js +89 -8
  26. package/dist/bin/exe-review.js +1494 -312
  27. package/dist/bin/exe-search.js +1608 -1300
  28. package/dist/bin/exe-session-cleanup.js +194 -91
  29. package/dist/bin/exe-settings.js +10 -2
  30. package/dist/bin/exe-start-codex.js +769 -120
  31. package/dist/bin/exe-start-opencode.js +763 -108
  32. package/dist/bin/exe-status.js +1887 -434
  33. package/dist/bin/exe-team.js +1782 -324
  34. package/dist/bin/git-sweep.js +408 -33
  35. package/dist/bin/graph-backfill.js +681 -27
  36. package/dist/bin/graph-export.js +1419 -141
  37. package/dist/bin/install.js +4 -8
  38. package/dist/bin/intercom-check.js +8641 -0
  39. package/dist/bin/scan-tasks.js +553 -38
  40. package/dist/bin/setup.js +82 -10
  41. package/dist/bin/shard-migrate.js +682 -28
  42. package/dist/gateway/index.js +1629 -1295
  43. package/dist/hooks/bug-report-worker.js +1136 -183
  44. package/dist/hooks/codex-stop-task-finalizer.js +1060 -107
  45. package/dist/hooks/commit-complete.js +408 -33
  46. package/dist/hooks/error-recall.js +1608 -1300
  47. package/dist/hooks/ingest-worker.js +250 -7966
  48. package/dist/hooks/ingest.js +707 -119
  49. package/dist/hooks/instructions-loaded.js +383 -20
  50. package/dist/hooks/notification.js +383 -20
  51. package/dist/hooks/post-compact.js +384 -21
  52. package/dist/hooks/{response-ingest-worker.js → post-tool-combined.js} +4157 -1716
  53. package/dist/hooks/pre-compact.js +486 -45
  54. package/dist/hooks/pre-tool-use.js +385 -22
  55. package/dist/hooks/prompt-submit.js +291 -96
  56. package/dist/hooks/session-end.js +490 -48
  57. package/dist/hooks/session-start.js +236 -22
  58. package/dist/hooks/stop.js +192 -50
  59. package/dist/hooks/subagent-stop.js +95 -18
  60. package/dist/hooks/summary-worker.js +205 -361
  61. package/dist/index.js +221 -105
  62. package/dist/lib/agent-config.js +2 -2
  63. package/dist/lib/cloud-sync.js +27 -8
  64. package/dist/lib/consolidation.js +437 -41
  65. package/dist/lib/database.js +20 -8
  66. package/dist/lib/db-daemon-client.js +2 -2
  67. package/dist/lib/db.js +20 -8
  68. package/dist/lib/device-registry.js +27 -8
  69. package/dist/lib/employee-templates.js +62 -0
  70. package/dist/lib/employees.js +2 -2
  71. package/dist/lib/exe-daemon.js +6703 -6259
  72. package/dist/lib/hybrid-search.js +1608 -1300
  73. package/dist/lib/identity.js +1 -1
  74. package/dist/lib/messaging.js +11 -3
  75. package/dist/lib/reminders.js +1 -1
  76. package/dist/lib/schedules.js +718 -26
  77. package/dist/lib/session-registry.js +11 -0
  78. package/dist/lib/skill-learning.js +639 -9
  79. package/dist/lib/store.js +676 -27
  80. package/dist/lib/tasks.js +665 -27
  81. package/dist/lib/tmux-routing.js +732 -94
  82. package/dist/lib/token-spend.js +1 -1
  83. package/dist/mcp/server.js +856 -383
  84. package/dist/mcp/tools/complete-reminder.js +1 -1
  85. package/dist/mcp/tools/create-reminder.js +1 -1
  86. package/dist/mcp/tools/create-task.js +616 -46
  87. package/dist/mcp/tools/deactivate-behavior.js +9 -1
  88. package/dist/mcp/tools/list-reminders.js +1 -1
  89. package/dist/mcp/tools/list-tasks.js +10 -2
  90. package/dist/mcp/tools/send-message.js +11 -3
  91. package/dist/mcp/tools/update-task.js +677 -39
  92. package/dist/runtime/index.js +425 -37
  93. package/dist/tui/App.js +365 -34
  94. package/package.json +5 -2
  95. package/src/commands/exe/intercom.md +6 -17
  96. package/dist/bin/wiki-sync.js +0 -2991
  97. package/dist/hooks/prompt-ingest-worker.js +0 -3979
@@ -313,7 +313,7 @@ var init_config = __esm({
313
313
  });
314
314
 
315
315
  // src/lib/daemon-auth.ts
316
- import crypto2 from "crypto";
316
+ import crypto from "crypto";
317
317
  import path2 from "path";
318
318
  import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
319
319
  function normalizeToken(token) {
@@ -332,7 +332,7 @@ function readDaemonToken() {
332
332
  function ensureDaemonToken(seed) {
333
333
  const existing = readDaemonToken();
334
334
  if (existing) return existing;
335
- const token = normalizeToken(seed) ?? crypto2.randomBytes(32).toString("hex");
335
+ const token = normalizeToken(seed) ?? crypto.randomBytes(32).toString("hex");
336
336
  ensurePrivateDirSync(EXE_AI_DIR);
337
337
  writeFileSync(DAEMON_TOKEN_PATH, `${token}
338
338
  `, "utf8");
@@ -850,8 +850,8 @@ async function embedDirect(text) {
850
850
  const llamaCpp = await import("node-llama-cpp");
851
851
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
852
852
  const { existsSync: existsSync34 } = await import("fs");
853
- const path45 = await import("path");
854
- const modelPath = path45.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
853
+ const path44 = await import("path");
854
+ const modelPath = path44.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
855
855
  if (!existsSync34(modelPath)) {
856
856
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
857
857
  }
@@ -929,9 +929,9 @@ var MAX_RETRIES, BASE_DELAY_MS, MAX_JITTER_MS;
929
929
  var init_db_retry = __esm({
930
930
  "src/lib/db-retry.ts"() {
931
931
  "use strict";
932
- MAX_RETRIES = 3;
933
- BASE_DELAY_MS = 200;
934
- MAX_JITTER_MS = 300;
932
+ MAX_RETRIES = 5;
933
+ BASE_DELAY_MS = 250;
934
+ MAX_JITTER_MS = 400;
935
935
  }
936
936
  });
937
937
 
@@ -1034,7 +1034,7 @@ var init_agent_config = __esm({
1034
1034
  init_secure_files();
1035
1035
  AGENT_CONFIG_PATH = path4.join(EXE_AI_DIR, "agent-config.json");
1036
1036
  KNOWN_RUNTIMES = {
1037
- claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
1037
+ claude: ["claude-opus-4.6", "claude-opus-4", "claude-sonnet-4.6", "claude-sonnet-4", "claude-haiku-4.5"],
1038
1038
  codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
1039
1039
  opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
1040
1040
  };
@@ -1044,7 +1044,7 @@ var init_agent_config = __esm({
1044
1044
  opencode: "OpenCode (open source)"
1045
1045
  };
1046
1046
  DEFAULT_MODELS = {
1047
- claude: "claude-opus-4",
1047
+ claude: "claude-opus-4.6",
1048
1048
  codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
1049
1049
  opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
1050
1050
  };
@@ -1993,7 +1993,7 @@ function createDaemonDbClient(fallbackClient) {
1993
1993
  });
1994
1994
  if (response.error) {
1995
1995
  const errMsg = String(response.error);
1996
- if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed") {
1996
+ if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed" || errMsg === "DB not initialized") {
1997
1997
  process.stderr.write(`[db-daemon] Transport error (${errMsg}), falling back to direct
1998
1998
  `);
1999
1999
  return fallbackClient.execute(stmt);
@@ -2018,7 +2018,7 @@ function createDaemonDbClient(fallbackClient) {
2018
2018
  });
2019
2019
  if (response.error) {
2020
2020
  const errMsg = String(response.error);
2021
- if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed") {
2021
+ if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed" || errMsg === "DB not initialized") {
2022
2022
  process.stderr.write(`[db-daemon] Batch transport error (${errMsg}), falling back to direct
2023
2023
  `);
2024
2024
  return fallbackClient.batch(stmts, mode);
@@ -2141,7 +2141,7 @@ async function initDatabase(config2) {
2141
2141
  });
2142
2142
  }, 3e4);
2143
2143
  _walCheckpointTimer.unref();
2144
- if (process.env.DATABASE_URL) {
2144
+ if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
2145
2145
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
2146
2146
  }
2147
2147
  }
@@ -2152,7 +2152,7 @@ function getClient() {
2152
2152
  if (!_adapterClient) {
2153
2153
  throw new Error("Database client not initialized. Call initDatabase() first.");
2154
2154
  }
2155
- if (process.env.DATABASE_URL) {
2155
+ if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
2156
2156
  return _adapterClient;
2157
2157
  }
2158
2158
  if (process.env.EXE_IS_DAEMON === "1") {
@@ -2164,9 +2164,11 @@ function getClient() {
2164
2164
  return _resilientClient;
2165
2165
  }
2166
2166
  async function initDaemonClient() {
2167
- if (process.env.DATABASE_URL) return;
2167
+ if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
2168
2168
  if (process.env.EXE_IS_DAEMON === "1") return;
2169
+ if (process.env.VITEST) return;
2169
2170
  if (!_resilientClient) return;
2171
+ if (_daemonClient) return;
2170
2172
  try {
2171
2173
  const { initDaemonDbClient: initDaemonDbClient2 } = await Promise.resolve().then(() => (init_db_daemon_client(), db_daemon_client_exports));
2172
2174
  _daemonClient = await initDaemonDbClient2(_resilientClient);
@@ -2315,6 +2317,13 @@ async function ensureSchema() {
2315
2317
  });
2316
2318
  } catch {
2317
2319
  }
2320
+ try {
2321
+ await client.execute({
2322
+ sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
2323
+ args: []
2324
+ });
2325
+ } catch {
2326
+ }
2318
2327
  try {
2319
2328
  await client.execute({
2320
2329
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
@@ -3185,6 +3194,7 @@ var init_database = __esm({
3185
3194
  init_db_retry();
3186
3195
  init_employees();
3187
3196
  init_database_adapter();
3197
+ init_memory();
3188
3198
  _client = null;
3189
3199
  _resilientClient = null;
3190
3200
  _walCheckpointTimer = null;
@@ -3803,6 +3813,68 @@ var init_platform_procedures = __esm({
3803
3813
  domain: "architecture",
3804
3814
  priority: "p0",
3805
3815
  content: "Tasks live in the DB. Intercom (tmux send-keys) is fire-and-forget \u2014 it may fail, get garbled, or arrive mid-work. Never rely on intercom for task delivery. The UserPromptSubmit hook checks the DB for new tasks on every prompt. Your operating procedures step 7 says check for next work. The daemon nudges idle agents as a speedup. If you have no tasks, you found them all."
3816
+ },
3817
+ // --- MCP is the ONLY data interface ---
3818
+ {
3819
+ title: "MCP disconnect \u2014 ask the user, never work around it",
3820
+ domain: "workflow",
3821
+ priority: "p0",
3822
+ content: "If MCP tools are unavailable, disconnected, or returning connection errors: STOP. Tell the user clearly: 'MCP server is disconnected. Please run /mcp to reconnect.' Do NOT attempt workarounds \u2014 no raw Node imports, no direct DB access, no CLI hacks, no daemon socket calls. MCP is the ONLY data interface. Working around it wastes time, hits bundling issues, and bypasses the contract boundary. Ask once, wait, proceed when reconnected."
3823
+ },
3824
+ // --- MCP Tool Catalog (Layer 0 — every agent knows what tools exist) ---
3825
+ {
3826
+ title: "MCP tools \u2014 memory and search",
3827
+ domain: "tool-use",
3828
+ priority: "p1",
3829
+ content: "recall_my_memory: search your own memories (semantic + FTS). ask_team_memory: search a colleague's memories by agent name. store_memory: persist a memory (decisions, summaries, context). commit_memory: high-importance memory that survives consolidation. search_everything: unified search across memories, tasks, entities, conversations. get_session_context: temporal window of memories around a timestamp. consolidate_memories: merge duplicate/related memories into insights. get_memory_cardinality: count memories per agent (health check)."
3830
+ },
3831
+ {
3832
+ title: "MCP tools \u2014 task orchestration",
3833
+ domain: "tool-use",
3834
+ priority: "p1",
3835
+ content: "create_task: dispatch work to an employee (auto-spawns session). The ONLY dispatch path. list_tasks: query tasks by status, assignee, project. get_task: fetch full task details by ID. update_task: change status (in_progress, done, blocked, cancelled) + add result summary. close_task: finalize a reviewed task (COO only). checkpoint_task: save progress state for crash recovery. resume_employee: re-spawn an employee session for an existing task."
3836
+ },
3837
+ {
3838
+ title: "MCP tools \u2014 knowledge graph (GraphRAG)",
3839
+ domain: "tool-use",
3840
+ priority: "p1",
3841
+ content: "query_relationships: find connections between entities in the knowledge graph. get_entity_neighbors: explore an entity's direct connections. get_hot_entities: find most-referenced entities (trending topics). get_graph_stats: graph health \u2014 entity/relationship counts, density. export_graph: export graph data for visualization. merge_entities: deduplicate entities (alias resolution). find_similar_trajectories: match tool-call patterns to past task solutions."
3842
+ },
3843
+ {
3844
+ title: "MCP tools \u2014 identity, behavior, and decisions",
3845
+ domain: "tool-use",
3846
+ priority: "p1",
3847
+ content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query."
3848
+ },
3849
+ {
3850
+ title: "MCP tools \u2014 communication and messaging",
3851
+ domain: "tool-use",
3852
+ priority: "p1",
3853
+ content: "send_message: send supplementary context to another agent (NOT for actionable work \u2014 use create_task). acknowledge_messages: mark messages as read. send_whatsapp: send WhatsApp message via gateway (customer-facing alerts). query_conversations: search ingested conversations across all channels (WhatsApp, email, etc.)."
3854
+ },
3855
+ {
3856
+ title: "MCP tools \u2014 wiki, documents, and content",
3857
+ domain: "tool-use",
3858
+ priority: "p1",
3859
+ 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."
3860
+ },
3861
+ {
3862
+ title: "MCP tools \u2014 system, operations, and admin",
3863
+ domain: "tool-use",
3864
+ priority: "p1",
3865
+ content: "get_agent_spend: token usage per agent/session (cost tracking). list_agent_sessions: view agent session history. get_session_kills: audit log of killed sessions. get_daemon_health: check exed daemon status. get_auto_wake_status: daemon auto-wake configuration. get_worker_gate: check worker deployment gates. run_memory_audit: health check \u2014 duplicates, null vectors, orphaned rows. run_consolidation: trigger sleep-time memory consolidation. cloud_sync: force a cloud sync cycle. backup_vps: trigger VPS backup."
3866
+ },
3867
+ {
3868
+ title: "MCP tools \u2014 config, licensing, and team",
3869
+ domain: "tool-use",
3870
+ priority: "p1",
3871
+ content: "set_agent_config: view/change per-agent runtime and model settings. list_employees: view the employee roster. add_person: add a person to the CRM contacts roster. list_people: browse CRM contacts. get_person: fetch contact details. get_license_status: check license validity. create_license: generate a new license key (admin). list_licenses: view all issued licenses. activate_license: activate a license on a device."
3872
+ },
3873
+ {
3874
+ title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
3875
+ domain: "tool-use",
3876
+ priority: "p1",
3877
+ 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."
3806
3878
  }
3807
3879
  ];
3808
3880
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -3952,6 +4024,11 @@ async function initStore(options) {
3952
4024
  encryptionKey: hexKey
3953
4025
  });
3954
4026
  await retryOnBusy2(() => ensureSchema(), "ensureSchema");
4027
+ try {
4028
+ const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
4029
+ await initDaemonClient2();
4030
+ } catch {
4031
+ }
3955
4032
  if (!options?.lightweight) {
3956
4033
  try {
3957
4034
  const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
@@ -4742,7 +4819,7 @@ __export(file_grep_exports, {
4742
4819
  import { execSync as execSync3 } from "child_process";
4743
4820
  import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync2, existsSync as existsSync10 } from "fs";
4744
4821
  import path11 from "path";
4745
- import crypto3 from "crypto";
4822
+ import crypto2 from "crypto";
4746
4823
  function hasRipgrep() {
4747
4824
  if (_hasRg === null) {
4748
4825
  try {
@@ -4775,7 +4852,7 @@ async function grepProjectFiles(query, projectRoot, options) {
4775
4852
  const chunkCtx = getChunkContext(hit.filePath, hit.lineNumber);
4776
4853
  const prefix = chunkCtx ? `[file: ${hit.filePath}:${hit.lineNumber} in ${chunkCtx}]` : `[file: ${hit.filePath}:${hit.lineNumber}]`;
4777
4854
  return {
4778
- id: crypto3.createHash("sha256").update(`${hit.filePath}:${hit.lineNumber}`).digest("hex").slice(0, 36),
4855
+ id: crypto2.createHash("sha256").update(`${hit.filePath}:${hit.lineNumber}`).digest("hex").slice(0, 36),
4779
4856
  agent_id: "project",
4780
4857
  agent_role: "file",
4781
4858
  session_id: "file-grep",
@@ -5714,10 +5791,10 @@ async function hybridSearch(queryText, agentId, options) {
5714
5791
  };
5715
5792
  try {
5716
5793
  const fs = await import("fs");
5717
- const path45 = await import("path");
5718
- const os19 = await import("os");
5719
- const logPath = path45.join(os19.homedir(), ".exe-os", "search-quality.jsonl");
5720
- fs.mkdirSync(path45.dirname(logPath), { recursive: true });
5794
+ const path44 = await import("path");
5795
+ const os18 = await import("os");
5796
+ const logPath = path44.join(os18.homedir(), ".exe-os", "search-quality.jsonl");
5797
+ fs.mkdirSync(path44.dirname(logPath), { recursive: true });
5721
5798
  fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
5722
5799
  } catch {
5723
5800
  }
@@ -5812,7 +5889,7 @@ function rrfMergeMulti(lists, limit, k = RRF_K, weights) {
5812
5889
  const importance = normalizedImportance(e.record.importance);
5813
5890
  const confidence = sourceConfidence(e.record);
5814
5891
  const frecency = frecencyBoost(e.record.last_accessed, e.record.timestamp);
5815
- const baseScore = e.rrfScore * 0.35 + recency * 0.14 + importance * 0.21 + confidence * 0.3;
5892
+ const baseScore = e.rrfScore * 0.45 + recency * 0.24 + importance * 0.21 + confidence * 0.1;
5816
5893
  const finalScore = baseScore * (1 + 0.3 * frecency);
5817
5894
  return { score: finalScore, record: e.record };
5818
5895
  });
@@ -7324,7 +7401,7 @@ var init_intercom_queue = __esm({
7324
7401
  });
7325
7402
 
7326
7403
  // src/lib/session-kill-telemetry.ts
7327
- import crypto6 from "crypto";
7404
+ import crypto5 from "crypto";
7328
7405
  async function recordSessionKill(input) {
7329
7406
  try {
7330
7407
  const client = getClient();
@@ -7334,7 +7411,7 @@ async function recordSessionKill(input) {
7334
7411
  ticks_idle, estimated_tokens_saved)
7335
7412
  VALUES (?, ?, ?, ?, ?, ?, ?)`,
7336
7413
  args: [
7337
- crypto6.randomUUID(),
7414
+ crypto5.randomUUID(),
7338
7415
  input.sessionName,
7339
7416
  input.agentId,
7340
7417
  (/* @__PURE__ */ new Date()).toISOString(),
@@ -8295,7 +8372,7 @@ function isSessionBusy(sessionName) {
8295
8372
  function isExeSession(sessionName) {
8296
8373
  const matchesBaseWithInstance = (baseName) => sessionName === baseName || sessionName.startsWith(baseName) && /^\d+$/.test(sessionName.slice(baseName.length));
8297
8374
  const coordinatorName = getCoordinatorName();
8298
- return matchesBaseWithInstance(coordinatorName) || matchesBaseWithInstance("exe");
8375
+ return matchesBaseWithInstance(coordinatorName);
8299
8376
  }
8300
8377
  function sendIntercom(targetSession) {
8301
8378
  const transport = getTransport();
@@ -8833,7 +8910,7 @@ var init_task_scope = __esm({
8833
8910
  });
8834
8911
 
8835
8912
  // src/lib/notifications.ts
8836
- import crypto7 from "crypto";
8913
+ import crypto6 from "crypto";
8837
8914
  import path21 from "path";
8838
8915
  import os10 from "os";
8839
8916
  import {
@@ -8846,7 +8923,7 @@ import {
8846
8923
  async function writeNotification(notification) {
8847
8924
  try {
8848
8925
  const client = getClient();
8849
- const id = crypto7.randomUUID();
8926
+ const id = crypto6.randomUUID();
8850
8927
  const now = (/* @__PURE__ */ new Date()).toISOString();
8851
8928
  const sessionScope = notification.sessionScope === void 0 ? getCurrentSessionScope() : notification.sessionScope;
8852
8929
  await client.execute({
@@ -8968,7 +9045,7 @@ __export(tasks_crud_exports, {
8968
9045
  updateTaskStatus: () => updateTaskStatus,
8969
9046
  writeCheckpoint: () => writeCheckpoint
8970
9047
  });
8971
- import crypto8 from "crypto";
9048
+ import crypto7 from "crypto";
8972
9049
  import path22 from "path";
8973
9050
  import os11 from "os";
8974
9051
  import { execSync as execSync8 } from "child_process";
@@ -9089,7 +9166,7 @@ async function resolveTask(client, identifier, scopeSession) {
9089
9166
  }
9090
9167
  async function createTaskCore(input) {
9091
9168
  const client = getClient();
9092
- const id = crypto8.randomUUID();
9169
+ const id = crypto7.randomUUID();
9093
9170
  const now = (/* @__PURE__ */ new Date()).toISOString();
9094
9171
  const slug = slugify(input.title);
9095
9172
  let earlySessionScope = null;
@@ -9098,15 +9175,20 @@ async function createTaskCore(input) {
9098
9175
  const { resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
9099
9176
  const resolved = resolveExeSession2();
9100
9177
  if (resolved && input.projectName) {
9101
- const { getSessionProject: getSessionProject2 } = await Promise.resolve().then(() => (init_session_scope(), session_scope_exports));
9102
- const sessionProject = getSessionProject2(resolved);
9103
- if (sessionProject && sessionProject !== input.projectName) {
9104
- scopeMismatchWarning = `session/project mismatch: session "${resolved}" owns "${sessionProject}" but task targets "${input.projectName}". Routed to default scope.`;
9105
- process.stderr.write(`[create_task] ${scopeMismatchWarning}
9106
- `);
9107
- earlySessionScope = null;
9108
- } else {
9178
+ const isCoordinatorSession = !resolved.includes("-");
9179
+ if (isCoordinatorSession) {
9109
9180
  earlySessionScope = resolved;
9181
+ } else {
9182
+ const { getSessionProject: getSessionProject2 } = await Promise.resolve().then(() => (init_session_scope(), session_scope_exports));
9183
+ const sessionProject = getSessionProject2(resolved);
9184
+ if (sessionProject && sessionProject !== input.projectName) {
9185
+ scopeMismatchWarning = `session/project mismatch: session "${resolved}" owns "${sessionProject}" but task targets "${input.projectName}". Routed to default scope.`;
9186
+ process.stderr.write(`[create_task] ${scopeMismatchWarning}
9187
+ `);
9188
+ earlySessionScope = null;
9189
+ } else {
9190
+ earlySessionScope = resolved;
9191
+ }
9110
9192
  }
9111
9193
  } else {
9112
9194
  earlySessionScope = resolved;
@@ -9683,6 +9765,10 @@ async function dispatchTaskToEmployee(input) {
9683
9765
  if (transport.isAlive(sessionName)) {
9684
9766
  const result = sendIntercom(sessionName);
9685
9767
  const dispatched = result === "acknowledged" || result === "debounced" || result === "queued" ? "verified" : result === "delivered" ? "sent_unverified" : "session_dead";
9768
+ process.stderr.write(
9769
+ `[dispatch-audit] intercom \u2192 ${sessionName} | task="${input.title}" [${input.priority}] | result=${dispatched} (sendIntercom=${result})
9770
+ `
9771
+ );
9686
9772
  return { dispatched, session: sessionName, crossProject };
9687
9773
  } else {
9688
9774
  const projectDir = input.projectDir ?? process.cwd();
@@ -9691,11 +9777,15 @@ async function dispatchTaskToEmployee(input) {
9691
9777
  });
9692
9778
  if (result.status === "failed") {
9693
9779
  process.stderr.write(
9694
- `[dispatch] Failed to spawn ${input.assignedTo}: ${result.error}
9780
+ `[dispatch-audit] SPAWN FAILED \u2192 ${input.assignedTo} | task="${input.title}" [${input.priority}] | error=${result.error}
9695
9781
  `
9696
9782
  );
9697
9783
  return { dispatched: "session_missing" };
9698
9784
  }
9785
+ process.stderr.write(
9786
+ `[dispatch-audit] SPAWNED \u2192 ${result.sessionName} | task="${input.title}" [${input.priority}]
9787
+ `
9788
+ );
9699
9789
  return { dispatched: "spawned", session: result.sessionName, crossProject };
9700
9790
  }
9701
9791
  } catch {
@@ -9705,7 +9795,13 @@ async function dispatchTaskToEmployee(input) {
9705
9795
  function notifyTaskDone() {
9706
9796
  try {
9707
9797
  const key = getSessionKey();
9708
- if (key && !process.env.VITEST) notifyParentExe(key);
9798
+ if (key && !process.env.VITEST) {
9799
+ notifyParentExe(key);
9800
+ process.stderr.write(
9801
+ `[dispatch-audit] notifyTaskDone \u2192 parent coordinator (session=${key})
9802
+ `
9803
+ );
9804
+ }
9709
9805
  } catch {
9710
9806
  }
9711
9807
  }
@@ -9727,22 +9823,29 @@ var init_tasks_notify = __esm({
9727
9823
  });
9728
9824
 
9729
9825
  // src/lib/behaviors.ts
9730
- import crypto9 from "crypto";
9826
+ import crypto8 from "crypto";
9731
9827
  async function storeBehavior(opts) {
9732
9828
  const client = getClient();
9733
- const id = crypto9.randomUUID();
9829
+ const id = crypto8.randomUUID();
9734
9830
  const now = (/* @__PURE__ */ new Date()).toISOString();
9831
+ let vector = null;
9832
+ try {
9833
+ const { embed: embed2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
9834
+ const vec = await embed2(opts.content);
9835
+ vector = new Float32Array(vec);
9836
+ } catch {
9837
+ }
9735
9838
  await client.execute({
9736
- sql: `INSERT INTO behaviors (id, agent_id, project_name, domain, priority, content, active, created_at, updated_at)
9737
- VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?)`,
9738
- args: [id, opts.agentId, opts.projectName ?? null, opts.domain ?? null, opts.priority ?? "p1", opts.content, now, now]
9839
+ sql: `INSERT INTO behaviors (id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector)
9840
+ VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?, ?)`,
9841
+ args: [id, opts.agentId, opts.projectName ?? null, opts.domain ?? null, opts.priority ?? "p1", opts.content, now, now, vector ? vector.buffer : null]
9739
9842
  });
9740
9843
  return id;
9741
9844
  }
9742
9845
  async function listBehaviorsByDomain(agentId, domain) {
9743
9846
  const client = getClient();
9744
9847
  const result = await client.execute({
9745
- sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at
9848
+ sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector
9746
9849
  FROM behaviors
9747
9850
  WHERE agent_id = ? AND domain = ? AND active = 1`,
9748
9851
  args: [agentId, domain]
@@ -9756,7 +9859,8 @@ async function listBehaviorsByDomain(agentId, domain) {
9756
9859
  content: String(r.content),
9757
9860
  active: Number(r.active),
9758
9861
  created_at: String(r.created_at),
9759
- updated_at: String(r.updated_at)
9862
+ updated_at: String(r.updated_at),
9863
+ vector: r.vector ? Array.from(new Float32Array(r.vector)) : null
9760
9864
  }));
9761
9865
  }
9762
9866
  async function deactivateBehavior(id) {
@@ -9787,7 +9891,7 @@ __export(skill_learning_exports, {
9787
9891
  storeTrajectory: () => storeTrajectory,
9788
9892
  sweepTrajectories: () => sweepTrajectories
9789
9893
  });
9790
- import crypto10 from "crypto";
9894
+ import crypto9 from "crypto";
9791
9895
  async function extractTrajectory(taskId, agentId) {
9792
9896
  const client = getClient();
9793
9897
  const result = await client.execute({
@@ -9816,11 +9920,11 @@ async function extractTrajectory(taskId, agentId) {
9816
9920
  return signature;
9817
9921
  }
9818
9922
  function hashSignature(signature) {
9819
- return crypto10.createHash("sha256").update(signature.join("|")).digest("hex").slice(0, 16);
9923
+ return crypto9.createHash("sha256").update(signature.join("|")).digest("hex").slice(0, 16);
9820
9924
  }
9821
9925
  async function storeTrajectory(opts) {
9822
9926
  const client = getClient();
9823
- const id = crypto10.randomUUID();
9927
+ const id = crypto9.randomUUID();
9824
9928
  const now = (/* @__PURE__ */ new Date()).toISOString();
9825
9929
  const signatureHash = hashSignature(opts.signature);
9826
9930
  await client.execute({
@@ -10943,10 +11047,10 @@ ${PLAN_MODE_COMPAT}
10943
11047
  });
10944
11048
 
10945
11049
  // src/lib/messaging.ts
10946
- import crypto11 from "crypto";
11050
+ import crypto10 from "crypto";
10947
11051
  function generateUlid() {
10948
11052
  const timestamp = Date.now().toString(36).padStart(10, "0");
10949
- const random = crypto11.randomBytes(10).toString("hex").slice(0, 16);
11053
+ const random = crypto10.randomBytes(10).toString("hex").slice(0, 16);
10950
11054
  return (timestamp + random).toUpperCase();
10951
11055
  }
10952
11056
  function rowToMessage(row) {
@@ -11157,7 +11261,6 @@ async function selectUnconsolidated(client, limit = 200) {
11157
11261
  sql: `SELECT id, agent_id, project_name, tool_name, raw_text, timestamp
11158
11262
  FROM memories
11159
11263
  WHERE consolidated = 0
11160
- AND timestamp >= datetime('now', '-7 days')
11161
11264
  ORDER BY timestamp DESC
11162
11265
  LIMIT ?`,
11163
11266
  args: [limit]
@@ -11212,11 +11315,12 @@ function groupMemories(memories) {
11212
11315
  }
11213
11316
  return clusters;
11214
11317
  }
11215
- function buildConsolidationPrompt(cluster) {
11318
+ function buildConsolidationPrompt(cluster, agentRole) {
11216
11319
  const snippets = cluster.memories.map((m, i) => {
11217
11320
  const text = m.raw_text.length > 200 ? m.raw_text.slice(0, 200) + "..." : m.raw_text;
11218
11321
  return `${i + 1}. [${m.tool_name}] ${text}`;
11219
11322
  }).join("\n");
11323
+ const rolePrompt = agentRole && ROLE_PROMPTS[agentRole] || DEFAULT_ROLE_PROMPT;
11220
11324
  return `You are reviewing a set of work memories from an AI coding agent.
11221
11325
  These are raw tool call records from ${cluster.dateRange}.
11222
11326
 
@@ -11225,19 +11329,15 @@ Agent: ${cluster.agentId} | Project: ${cluster.projectName} | Date: ${cluster.da
11225
11329
  MEMORIES:
11226
11330
  ${snippets}
11227
11331
 
11228
- Extract EXACTLY THREE types of insights:
11229
-
11230
- 1. KEY DECISIONS \u2014 choices that were made and why (at most 3)
11231
- 2. RECURRING PATTERNS \u2014 actions or approaches that repeated (at most 3)
11232
- 3. OPEN QUESTIONS \u2014 things that seem unresolved or risky (at most 2)
11332
+ ${rolePrompt}
11233
11333
 
11234
11334
  Format each as a single sentence. Be specific \u2014 include file names,
11235
11335
  function names, and concrete details. Skip if no insight for a category.`;
11236
11336
  }
11237
- async function consolidateCluster(cluster, model) {
11337
+ async function consolidateCluster(cluster, model, agentRole) {
11238
11338
  const Anthropic = (await import("@anthropic-ai/sdk")).default;
11239
11339
  const client = new Anthropic();
11240
- const prompt = buildConsolidationPrompt(cluster);
11340
+ const prompt = buildConsolidationPrompt(cluster, agentRole);
11241
11341
  const response = await client.messages.create({
11242
11342
  model,
11243
11343
  max_tokens: 300,
@@ -11380,6 +11480,15 @@ async function runConsolidation(client, options) {
11380
11480
  if (memories.length < 20) {
11381
11481
  return { clustersProcessed: 0, memoriesConsolidated: 0 };
11382
11482
  }
11483
+ let roleMap = {};
11484
+ try {
11485
+ const { loadEmployeesSync: loadEmployeesSync2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
11486
+ const employees = loadEmployeesSync2();
11487
+ for (const e of employees) {
11488
+ roleMap[e.name] = e.role;
11489
+ }
11490
+ } catch {
11491
+ }
11383
11492
  const clusters = groupMemories(memories);
11384
11493
  let clustersProcessed = 0;
11385
11494
  let memoriesConsolidated = 0;
@@ -11388,21 +11497,27 @@ async function runConsolidation(client, options) {
11388
11497
  if (cluster.memories.length < 3) continue;
11389
11498
  try {
11390
11499
  const isCoordinator = isCoordinatorName(cluster.agentId);
11391
- if (isCoordinator) {
11392
- const synthesis = await consolidateCluster(cluster, options.model);
11393
- if (!synthesis.trim()) continue;
11394
- const result = await storeConsolidation(client, cluster, synthesis, options.embedFn);
11395
- if (options.wikiConfig) {
11396
- await pushToWiki(
11397
- { ...result, projectName: cluster.projectName },
11398
- options.wikiConfig
11399
- ).catch((err) => {
11400
- process.stderr.write(
11401
- `[consolidation] Wiki push error (non-fatal): ${err instanceof Error ? err.message : String(err)}
11500
+ const agentRole = roleMap[cluster.agentId];
11501
+ const dedupCount = await dedupCluster(client, cluster, options.embedFn);
11502
+ memoriesConsolidated += dedupCount;
11503
+ const synthesis = await consolidateCluster(cluster, options.model, agentRole);
11504
+ if (!synthesis.trim()) {
11505
+ if (dedupCount > 0) clustersProcessed++;
11506
+ continue;
11507
+ }
11508
+ const result = await storeConsolidation(client, cluster, synthesis, options.embedFn);
11509
+ if (isCoordinator && options.wikiConfig) {
11510
+ await pushToWiki(
11511
+ { ...result, projectName: cluster.projectName },
11512
+ options.wikiConfig
11513
+ ).catch((err) => {
11514
+ process.stderr.write(
11515
+ `[consolidation] Wiki push error (non-fatal): ${err instanceof Error ? err.message : String(err)}
11402
11516
  `
11403
- );
11404
- });
11405
- }
11517
+ );
11518
+ });
11519
+ }
11520
+ if (isCoordinator) {
11406
11521
  const sourceIds = result.sourceIds;
11407
11522
  if (sourceIds.length > 0) {
11408
11523
  const placeholders = sourceIds.map(() => "?").join(",");
@@ -11411,13 +11526,9 @@ async function runConsolidation(client, options) {
11411
11526
  args: sourceIds
11412
11527
  });
11413
11528
  }
11414
- } else {
11415
- const dedupCount = await dedupCluster(client, cluster, options.embedFn);
11416
- memoriesConsolidated += dedupCount;
11417
- if (dedupCount === 0) continue;
11418
11529
  }
11419
11530
  clustersProcessed++;
11420
- memoriesConsolidated += isCoordinator ? cluster.memories.length : 0;
11531
+ memoriesConsolidated += cluster.memories.length;
11421
11532
  } catch (err) {
11422
11533
  process.stderr.write(
11423
11534
  `[consolidation] Cluster failed (${cluster.projectName}/${cluster.dateRange}): ${err instanceof Error ? err.message : String(err)}
@@ -11493,18 +11604,47 @@ async function isUserIdle(client, idleMinutes = 30) {
11493
11604
  async function countUnconsolidated(client) {
11494
11605
  const result = await client.execute({
11495
11606
  sql: `SELECT COUNT(*) as cnt FROM memories
11496
- WHERE consolidated = 0
11497
- AND timestamp >= datetime('now', '-7 days')`,
11607
+ WHERE consolidated = 0`,
11498
11608
  args: []
11499
11609
  });
11500
11610
  return Number(result.rows[0]?.cnt ?? 0);
11501
11611
  }
11502
- var WIKI_FETCH_TIMEOUT_MS;
11612
+ var ROLE_PROMPTS, DEFAULT_ROLE_PROMPT, WIKI_FETCH_TIMEOUT_MS;
11503
11613
  var init_consolidation = __esm({
11504
11614
  "src/lib/consolidation.ts"() {
11505
11615
  "use strict";
11506
11616
  init_store();
11507
11617
  init_employees();
11618
+ ROLE_PROMPTS = {
11619
+ "COO": `Extract EXACTLY THREE types of insights:
11620
+ 1. KEY DECISIONS \u2014 choices that were made and why (at most 3)
11621
+ 2. RECURRING PATTERNS \u2014 actions or approaches that repeated (at most 3)
11622
+ 3. OPEN QUESTIONS \u2014 things that seem unresolved or risky (at most 2)`,
11623
+ "CTO": `Extract EXACTLY THREE types of insights:
11624
+ 1. ARCHITECTURE DECISIONS \u2014 design choices, tradeoffs, delegation patterns (at most 3)
11625
+ 2. REVIEW OUTCOMES \u2014 what was approved, rejected, or flagged during code review (at most 3)
11626
+ 3. TECHNICAL DEBT \u2014 unresolved issues, deferred work, risks identified (at most 2)`,
11627
+ "Principal Engineer": `Extract EXACTLY THREE types of insights:
11628
+ 1. CODE DECISIONS \u2014 implementation choices, patterns used, bugs fixed (at most 3)
11629
+ 2. FILE CHANGES \u2014 key files modified and why (at most 3)
11630
+ 3. BLOCKERS \u2014 things that slowed down or prevented progress (at most 2)`,
11631
+ "Staff Code Reviewer": `Extract EXACTLY THREE types of insights:
11632
+ 1. AUDIT FINDINGS \u2014 issues found, severity, fix status (at most 3)
11633
+ 2. RECURRING ISSUES \u2014 patterns that keep appearing across reviews (at most 3)
11634
+ 3. QUALITY SIGNALS \u2014 areas of the codebase that are strong or weak (at most 2)`,
11635
+ "CMO": `Extract EXACTLY THREE types of insights:
11636
+ 1. DESIGN DECISIONS \u2014 brand, layout, typography, or content choices made (at most 3)
11637
+ 2. CONTENT STRATEGY \u2014 messaging, SEO, platform-specific decisions (at most 3)
11638
+ 3. BRAND ALIGNMENT \u2014 consistency issues or guidelines established (at most 2)`,
11639
+ "AI Product Lead": `Extract EXACTLY THREE types of insights:
11640
+ 1. RESEARCH FINDINGS \u2014 tools, repos, or models evaluated with conclusions (at most 3)
11641
+ 2. COMPETITIVE GAPS \u2014 features or patterns worth adopting from competitors (at most 3)
11642
+ 3. BUILD RECOMMENDATIONS \u2014 what to build, skip, or watch (at most 2)`
11643
+ };
11644
+ DEFAULT_ROLE_PROMPT = `Extract EXACTLY THREE types of insights:
11645
+ 1. KEY DECISIONS \u2014 choices that were made and why (at most 3)
11646
+ 2. RECURRING PATTERNS \u2014 actions or approaches that repeated (at most 3)
11647
+ 3. OPEN QUESTIONS \u2014 things that seem unresolved or risky (at most 2)`;
11508
11648
  WIKI_FETCH_TIMEOUT_MS = 1e4;
11509
11649
  }
11510
11650
  });
@@ -11518,8 +11658,8 @@ __export(wiki_client_exports, {
11518
11658
  listDocuments: () => listDocuments,
11519
11659
  listWorkspaces: () => listWorkspaces
11520
11660
  });
11521
- async function wikiFetch(config2, path45, method = "GET", body) {
11522
- const url = `${config2.baseUrl}/api/v1${path45}`;
11661
+ async function wikiFetch(config2, path44, method = "GET", body) {
11662
+ const url = `${config2.baseUrl}/api/v1${path44}`;
11523
11663
  const headers = {
11524
11664
  Authorization: `Bearer ${config2.apiKey}`,
11525
11665
  "Content-Type": "application/json"
@@ -11552,7 +11692,7 @@ async function wikiFetch(config2, path45, method = "GET", body) {
11552
11692
  }
11553
11693
  }
11554
11694
  if (!response.ok) {
11555
- throw new Error(`Wiki API ${method} ${path45}: ${response.status} ${response.statusText}`);
11695
+ throw new Error(`Wiki API ${method} ${path44}: ${response.status} ${response.statusText}`);
11556
11696
  }
11557
11697
  return response.json();
11558
11698
  } finally {
@@ -11995,7 +12135,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
11995
12135
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11996
12136
  import { spawn as spawn4 } from "child_process";
11997
12137
  import { existsSync as existsSync33, openSync as openSync3, mkdirSync as mkdirSync17, closeSync as closeSync3 } from "fs";
11998
- import path44 from "path";
12138
+ import path43 from "path";
11999
12139
  import { fileURLToPath as fileURLToPath5 } from "url";
12000
12140
 
12001
12141
  // src/mcp/tools/recall-my-memory.ts
@@ -12304,7 +12444,7 @@ init_store();
12304
12444
  init_active_agent();
12305
12445
  init_plan_limits();
12306
12446
  import { z as z4 } from "zod";
12307
- import crypto4 from "crypto";
12447
+ import crypto3 from "crypto";
12308
12448
  import { writeFileSync as writeFileSync6 } from "fs";
12309
12449
  import path15 from "path";
12310
12450
  function registerStoreMemory(server2) {
@@ -12355,7 +12495,7 @@ function registerStoreMemory(server2) {
12355
12495
  vector = null;
12356
12496
  needsBackfill = true;
12357
12497
  }
12358
- const memoryId = crypto4.randomUUID();
12498
+ const memoryId = crypto3.randomUUID();
12359
12499
  await writeMemory({
12360
12500
  id: memoryId,
12361
12501
  agent_id: agentId,
@@ -12398,7 +12538,7 @@ init_plan_limits();
12398
12538
  init_active_agent();
12399
12539
  init_employees();
12400
12540
  import { z as z5 } from "zod";
12401
- import crypto5 from "crypto";
12541
+ import crypto4 from "crypto";
12402
12542
  import { writeFileSync as writeFileSync7 } from "fs";
12403
12543
  import path16 from "path";
12404
12544
  function registerCommitMemory(server2) {
@@ -12447,7 +12587,7 @@ function registerCommitMemory(server2) {
12447
12587
  vector = null;
12448
12588
  needsBackfill = true;
12449
12589
  }
12450
- const memoryId = crypto5.randomUUID();
12590
+ const memoryId = crypto4.randomUUID();
12451
12591
  await assertMemoryLimit();
12452
12592
  const memoryType = canCoordinate(agentId, agentRole) ? "adr" : "raw";
12453
12593
  await writeMemory({
@@ -13383,10 +13523,10 @@ import { z as z16 } from "zod";
13383
13523
 
13384
13524
  // src/lib/reminders.ts
13385
13525
  init_database();
13386
- import crypto12 from "crypto";
13526
+ import crypto11 from "crypto";
13387
13527
  async function createReminder(text, dueDate) {
13388
13528
  const client = getClient();
13389
- const id = crypto12.randomUUID();
13529
+ const id = crypto11.randomUUID();
13390
13530
  const now = (/* @__PURE__ */ new Date()).toISOString();
13391
13531
  await client.execute({
13392
13532
  sql: `INSERT INTO reminders (id, text, created_at, due_date) VALUES (?, ?, ?, ?)`,
@@ -13523,7 +13663,9 @@ function rowToBehavior(r) {
13523
13663
  priority: r.priority ? String(r.priority) : "p1",
13524
13664
  active: Number(r.active),
13525
13665
  created_at: String(r.created_at),
13526
- updated_at: String(r.updated_at)
13666
+ updated_at: String(r.updated_at),
13667
+ vector: null
13668
+ // Not needed for listing
13527
13669
  };
13528
13670
  }
13529
13671
  function registerListBehaviors(server2) {
@@ -13770,7 +13912,7 @@ import { z as z23 } from "zod";
13770
13912
  init_database();
13771
13913
  init_embedder();
13772
13914
  init_store();
13773
- import crypto13 from "crypto";
13915
+ import crypto12 from "crypto";
13774
13916
  var WIKI_AGENT_ID = "wiki";
13775
13917
  var WIKI_AGENT_ROLE = "Knowledge";
13776
13918
  var WIKI_TOOL_NAME = "ingest_document";
@@ -13824,7 +13966,7 @@ async function resolveWorkspace(slug_or_id, name) {
13824
13966
  if (existing.rows.length > 0) {
13825
13967
  return rowToWorkspace(existing.rows[0]);
13826
13968
  }
13827
- const id = crypto13.randomUUID();
13969
+ const id = crypto12.randomUUID();
13828
13970
  const now = (/* @__PURE__ */ new Date()).toISOString();
13829
13971
  const resolvedName = name ?? slug_or_id;
13830
13972
  await client.execute({
@@ -13915,13 +14057,13 @@ async function ingestDocument(input) {
13915
14057
  }));
13916
14058
  const vectors = await embedTexts(enrichedChunks.map((c) => c.text));
13917
14059
  const client = getClient();
13918
- const documentId = crypto13.randomUUID();
14060
+ const documentId = crypto12.randomUUID();
13919
14061
  const uploadedAt = (/* @__PURE__ */ new Date()).toISOString();
13920
14062
  const mime = input.mime ?? null;
13921
14063
  const sourceType = input.source_type ?? DEFAULT_SOURCE_TYPE;
13922
14064
  const userId = input.user_id ?? null;
13923
14065
  const documentMetadata = input.document_metadata != null ? JSON.stringify(input.document_metadata) : null;
13924
- const chunkIds = input.chunks.map(() => crypto13.randomUUID());
14066
+ const chunkIds = input.chunks.map(() => crypto12.randomUUID());
13925
14067
  const versions = reserveVersions(input.chunks.length);
13926
14068
  const documentStmt = {
13927
14069
  sql: `INSERT INTO documents
@@ -14593,8 +14735,18 @@ function isScheduledTrigger(trigger) {
14593
14735
  // src/lib/schedules.ts
14594
14736
  init_database();
14595
14737
  init_store();
14596
- import crypto14 from "crypto";
14738
+ import crypto13 from "crypto";
14597
14739
  import { execSync as execSync9 } from "child_process";
14740
+ var CRON_FIELD = /^[\d*/,\-]+$/;
14741
+ function isValidCron(cron) {
14742
+ const fields = cron.trim().split(/\s+/);
14743
+ if (fields.length !== 5) return false;
14744
+ return fields.every((f) => CRON_FIELD.test(f));
14745
+ }
14746
+ var SAFE_ID = /^[a-zA-Z0-9_\-]+$/;
14747
+ function isValidScheduleId(id) {
14748
+ return SAFE_ID.test(id) && id.length <= 128;
14749
+ }
14598
14750
  async function ensureDb() {
14599
14751
  if (!isInitialized()) {
14600
14752
  await initStore();
@@ -14660,9 +14812,12 @@ function parseHumanCron(input) {
14660
14812
  return `${minute} ${hour} * * ${dow}`;
14661
14813
  }
14662
14814
  async function createSchedule(input) {
14815
+ if (!isValidCron(input.cron)) {
14816
+ throw new Error(`Invalid cron expression: ${input.cron}. Must be 5 fields with only digits, *, /, -, comma.`);
14817
+ }
14663
14818
  await ensureDb();
14664
14819
  const client = getClient();
14665
- const id = crypto14.randomUUID().slice(0, 8);
14820
+ const id = crypto13.randomUUID().slice(0, 8);
14666
14821
  const now = (/* @__PURE__ */ new Date()).toISOString();
14667
14822
  const prompt = input.prompt ?? input.description;
14668
14823
  await client.execute({
@@ -14697,6 +14852,12 @@ async function createSchedule(input) {
14697
14852
  };
14698
14853
  }
14699
14854
  function addToCrontab(id, cron, prompt, projectDir) {
14855
+ if (!isValidCron(cron)) {
14856
+ throw new Error(`Invalid cron expression: ${cron}`);
14857
+ }
14858
+ if (!isValidScheduleId(id)) {
14859
+ throw new Error(`Invalid schedule ID: ${id}`);
14860
+ }
14700
14861
  try {
14701
14862
  const cwd = projectDir ? `cd ${JSON.stringify(projectDir)} && ` : "";
14702
14863
  const escapedPrompt = prompt.replace(/"/g, '\\"');
@@ -14705,7 +14866,8 @@ function addToCrontab(id, cron, prompt, projectDir) {
14705
14866
  `(crontab -l 2>/dev/null; echo ${JSON.stringify(entry)}) | crontab -`,
14706
14867
  { timeout: 5e3, stdio: "ignore" }
14707
14868
  );
14708
- } catch {
14869
+ } catch (err) {
14870
+ if (err instanceof Error && err.message.startsWith("Invalid")) throw err;
14709
14871
  }
14710
14872
  }
14711
14873
 
@@ -15320,7 +15482,7 @@ init_database();
15320
15482
  import { z as z32 } from "zod";
15321
15483
 
15322
15484
  // src/lib/graph-rag.ts
15323
- import crypto15 from "crypto";
15485
+ import crypto14 from "crypto";
15324
15486
 
15325
15487
  // src/lib/code-chunker.ts
15326
15488
  import ts from "typescript";
@@ -15331,7 +15493,7 @@ function normalizeEntityName(name) {
15331
15493
  }
15332
15494
  function entityId(name, type) {
15333
15495
  const normalized = normalizeEntityName(name);
15334
- return crypto15.createHash("sha256").update(`${normalized}::${type.toLowerCase()}`).digest("hex").slice(0, 16);
15496
+ return crypto14.createHash("sha256").update(`${normalized}::${type.toLowerCase()}`).digest("hex").slice(0, 16);
15335
15497
  }
15336
15498
  async function registerAlias(client, alias, canonicalEntityId) {
15337
15499
  const normalized = normalizeEntityName(alias);
@@ -16065,9 +16227,9 @@ var HostingerApiClient = class {
16065
16227
  }
16066
16228
  this.lastRequestTime = Date.now();
16067
16229
  }
16068
- async request(method, path45, body) {
16230
+ async request(method, path44, body) {
16069
16231
  await this.rateLimit();
16070
- const url = `${this.baseUrl}${path45}`;
16232
+ const url = `${this.baseUrl}${path44}`;
16071
16233
  const headers = {
16072
16234
  Authorization: `Bearer ${this.apiKey}`,
16073
16235
  "Content-Type": "application/json",
@@ -16140,8 +16302,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
16140
16302
  }
16141
16303
  return envelope.result;
16142
16304
  }
16143
- function buildUrl(zoneId, path45 = "/dns_records", query) {
16144
- const normalizedPath = path45.startsWith("/") ? path45 : `/${path45}`;
16305
+ function buildUrl(zoneId, path44 = "/dns_records", query) {
16306
+ const normalizedPath = path44.startsWith("/") ? path44 : `/${path44}`;
16145
16307
  const url = new URL(
16146
16308
  `${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
16147
16309
  );
@@ -17164,65 +17326,467 @@ Consolidated summaries stored as tier-1 (importance=9) memories.`
17164
17326
  );
17165
17327
  }
17166
17328
 
17167
- // src/mcp/tools/store-global-procedure.ts
17168
- init_global_procedures();
17329
+ // src/mcp/tools/behavior.ts
17330
+ init_behaviors();
17169
17331
  init_active_agent();
17332
+ init_project_name();
17333
+ init_database();
17170
17334
  init_employees();
17171
17335
  import { z as z43 } from "zod";
17172
- function registerStoreGlobalProcedure(server2) {
17336
+ function rowToBehavior2(r) {
17337
+ return {
17338
+ id: String(r.id),
17339
+ agent_id: String(r.agent_id),
17340
+ project_name: r.project_name ? String(r.project_name) : null,
17341
+ domain: r.domain ? String(r.domain) : null,
17342
+ content: String(r.content),
17343
+ priority: r.priority ? String(r.priority) : "p1",
17344
+ active: Number(r.active),
17345
+ created_at: String(r.created_at),
17346
+ updated_at: String(r.updated_at),
17347
+ vector: null
17348
+ };
17349
+ }
17350
+ function registerBehavior(server2) {
17173
17351
  server2.registerTool(
17174
- "store_global_procedure",
17352
+ "behavior",
17175
17353
  {
17176
- title: "Store Global Procedure",
17177
- description: "Create an organization-wide procedure (Layer 0) that supersedes identity, expertise, and experience. Use for hard rules that every employee must follow. RESTRICTED: only coordinator or founder sessions.",
17354
+ title: "Behavior",
17355
+ description: "Manage behavioral patterns, corrections, and reusable procedures for employees. Actions: store (create new), list (query existing), deactivate (soft-delete, restricted).",
17178
17356
  inputSchema: {
17179
- title: z43.string().describe("Short title for the procedure"),
17180
- content: z43.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
17181
- priority: z43.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
17182
- domain: z43.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
17357
+ action: z43.enum(["store", "list", "deactivate"]).describe("Action to perform"),
17358
+ content: z43.string().max(500).optional().describe("The behavioral instruction \u2014 one clear sentence (store)"),
17359
+ domain: z43.string().optional().describe("Category: workflow, code-style, tool-use, communication, architecture, testing"),
17360
+ priority: z43.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always included. p1 = standard (default). p2 = nice-to-have."),
17361
+ agent_id: z43.string().optional().describe("Employee name. Defaults to current agent. Pass 'all' to list everyone's (list only)."),
17362
+ project_name: z43.string().optional().describe("Defaults to current project. Pass 'global' for a behavior that applies everywhere (store)."),
17363
+ behavior_id: z43.string().optional().describe("UUID of the behavior (deactivate)")
17183
17364
  }
17184
17365
  },
17185
- async ({ title, content, priority, domain }) => {
17366
+ async ({ action, content, domain, priority, agent_id, project_name, behavior_id }) => {
17367
+ if (action === "list") {
17368
+ const client2 = getClient();
17369
+ const conditions = ["active = 1"];
17370
+ const args = [];
17371
+ if (agent_id !== "all") {
17372
+ const resolvedAgent = agent_id ?? getActiveAgent().agentId;
17373
+ conditions.push("agent_id = ?");
17374
+ args.push(resolvedAgent);
17375
+ }
17376
+ if (domain) {
17377
+ conditions.push("domain = ?");
17378
+ args.push(domain);
17379
+ }
17380
+ if (project_name) {
17381
+ conditions.push("(project_name IS NULL OR project_name = ?)");
17382
+ args.push(project_name);
17383
+ } else if (!agent_id || agent_id !== "all") {
17384
+ const proj = getProjectName();
17385
+ conditions.push("(project_name IS NULL OR project_name = ?)");
17386
+ args.push(proj);
17387
+ }
17388
+ const where = conditions.join(" AND ");
17389
+ const result2 = await client2.execute({
17390
+ sql: `SELECT id, agent_id, project_name, domain, content, active, created_at, updated_at
17391
+ FROM behaviors
17392
+ WHERE ${where}
17393
+ ORDER BY agent_id, domain, updated_at DESC
17394
+ LIMIT 50`,
17395
+ args
17396
+ });
17397
+ const behaviors = result2.rows.map((r) => rowToBehavior2(r));
17398
+ if (behaviors.length === 0) {
17399
+ return {
17400
+ content: [{ type: "text", text: "No behaviors found." }]
17401
+ };
17402
+ }
17403
+ const lines = behaviors.map((b) => {
17404
+ const scope = b.project_name ?? "global";
17405
+ const dom = b.domain ?? "general";
17406
+ return `- [${b.agent_id}] [${dom}] (${scope}) ${b.content}
17407
+ ID: ${b.id}`;
17408
+ });
17409
+ return {
17410
+ content: [{
17411
+ type: "text",
17412
+ text: `${behaviors.length} behavior(s):
17413
+ ${lines.join("\n")}`
17414
+ }]
17415
+ };
17416
+ }
17417
+ if (action === "store") {
17418
+ if (!content) {
17419
+ return {
17420
+ content: [{
17421
+ type: "text",
17422
+ text: "Missing required field: content is required for store action."
17423
+ }],
17424
+ isError: true
17425
+ };
17426
+ }
17427
+ const resolvedAgent = agent_id ?? getActiveAgent().agentId;
17428
+ if (agent_id) {
17429
+ const caller2 = getActiveAgent();
17430
+ if (agent_id !== caller2.agentId) {
17431
+ const allowed2 = canCoordinate(caller2.agentId, caller2.agentRole);
17432
+ if (!allowed2) {
17433
+ return {
17434
+ content: [{
17435
+ type: "text",
17436
+ text: `Permission denied. Only the coordinator or founder sessions can store behaviors for other agents. You are "${caller2.agentId}".`
17437
+ }],
17438
+ isError: true
17439
+ };
17440
+ }
17441
+ }
17442
+ }
17443
+ let resolvedProject;
17444
+ if (project_name === "global" || project_name === null) {
17445
+ resolvedProject = void 0;
17446
+ } else if (project_name) {
17447
+ resolvedProject = project_name;
17448
+ } else {
17449
+ resolvedProject = getProjectName();
17450
+ }
17451
+ const id = await storeBehavior({
17452
+ agentId: resolvedAgent,
17453
+ content,
17454
+ domain: domain ?? void 0,
17455
+ projectName: resolvedProject,
17456
+ priority: priority ?? void 0
17457
+ });
17458
+ let responseText = `Behavior stored for ${resolvedAgent}. ID: ${id}`;
17459
+ if (domain) {
17460
+ const existing = await listBehaviorsByDomain(resolvedAgent, domain);
17461
+ const others = existing.filter((b) => b.id !== id);
17462
+ if (others.length > 0) {
17463
+ const list = others.map((b) => ` - [${b.id}] ${b.content}`).join("\n");
17464
+ responseText += `
17465
+
17466
+ Existing behaviors in [${domain}] domain:
17467
+ ${list}
17468
+ Use /exe-forget to remove any that this supersedes.`;
17469
+ }
17470
+ }
17471
+ return {
17472
+ content: [{ type: "text", text: responseText }]
17473
+ };
17474
+ }
17186
17475
  const caller = getActiveAgent();
17187
17476
  const allowed = canCoordinate(caller.agentId, caller.agentRole);
17188
17477
  if (!allowed) {
17189
17478
  return {
17190
17479
  content: [{
17191
17480
  type: "text",
17192
- text: `Permission denied. Only the coordinator or founder sessions can create global procedures. You are "${caller.agentId}".`
17481
+ text: `Permission denied. Only the coordinator or founder sessions can deactivate behaviors. You are "${caller.agentId}".`
17193
17482
  }],
17194
17483
  isError: true
17195
17484
  };
17196
17485
  }
17197
- const id = await storeGlobalProcedure({
17198
- title,
17199
- content,
17200
- priority: priority ?? "p0",
17201
- domain: domain ?? void 0
17486
+ if (!behavior_id) {
17487
+ return {
17488
+ content: [{
17489
+ type: "text",
17490
+ text: "Missing required field: behavior_id is required for deactivate action."
17491
+ }],
17492
+ isError: true
17493
+ };
17494
+ }
17495
+ const client = getClient();
17496
+ const result = await client.execute({
17497
+ sql: "SELECT id, agent_id, content, domain, priority FROM behaviors WHERE id = ?",
17498
+ args: [behavior_id]
17202
17499
  });
17500
+ if (result.rows.length === 0) {
17501
+ return {
17502
+ content: [{
17503
+ type: "text",
17504
+ text: `Behavior not found: ${behavior_id}`
17505
+ }],
17506
+ isError: true
17507
+ };
17508
+ }
17509
+ const row = result.rows[0];
17510
+ const wasActive = await deactivateBehavior(behavior_id);
17511
+ if (!wasActive) {
17512
+ return {
17513
+ content: [{
17514
+ type: "text",
17515
+ text: `Behavior ${behavior_id} was already inactive.`
17516
+ }]
17517
+ };
17518
+ }
17203
17519
  return {
17204
17520
  content: [{
17205
17521
  type: "text",
17206
- text: `Global procedure stored.
17207
- ID: ${id}
17208
- Title: ${title}
17209
- Priority: ${priority ?? "p0"}
17210
- Domain: ${domain ?? "none"}`
17522
+ text: `Deactivated behavior for ${row.agent_id}.
17523
+ ID: ${row.id}
17524
+ Domain: ${row.domain ?? "none"}
17525
+ Priority: ${row.priority}
17526
+ Content: ${row.content}`
17211
17527
  }]
17212
17528
  };
17213
17529
  }
17214
17530
  );
17215
17531
  }
17216
17532
 
17217
- // src/mcp/tools/list-global-procedures.ts
17218
- init_global_procedures();
17219
- init_platform_procedures();
17220
- function registerListGlobalProcedures(server2) {
17533
+ // src/mcp/tools/reminder.ts
17534
+ import { z as z44 } from "zod";
17535
+ function registerReminder(server2) {
17221
17536
  server2.registerTool(
17222
- "list_global_procedures",
17537
+ "reminder",
17223
17538
  {
17224
- title: "List Global Procedures",
17225
- description: "List all active organization-wide procedures (Layer 0). Shows platform procedures (shipped with exe-os, updated via exe-os update) and customer procedures (stored in DB, cloud-synced). These supersede identity, expertise, and experience.",
17539
+ title: "Reminder",
17540
+ description: "Manage reminders for the founder. Shown in the boot brief every session. Actions: create (set new), list (view active), complete (mark done).",
17541
+ inputSchema: {
17542
+ action: z44.enum(["create", "list", "complete"]).describe("Action to perform"),
17543
+ text: z44.string().optional().describe("What to remind about (create)"),
17544
+ due_date: z44.string().optional().describe("Optional due date \u2014 ISO date (2026-04-01) or null for persistent (create)"),
17545
+ reminder_id: z44.string().optional().describe("Reminder UUID or text substring to match (complete)"),
17546
+ include_completed: z44.boolean().optional().default(false).describe("Include completed reminders (list)")
17547
+ }
17548
+ },
17549
+ async ({ action, text, due_date, reminder_id, include_completed }) => {
17550
+ if (action === "create") {
17551
+ if (!text) {
17552
+ return {
17553
+ content: [{ type: "text", text: "Missing required field: text is required for create action." }],
17554
+ isError: true
17555
+ };
17556
+ }
17557
+ const reminder2 = await createReminder(text, due_date);
17558
+ const dueStr = reminder2.dueDate ? ` (due: ${reminder2.dueDate})` : "";
17559
+ return {
17560
+ content: [{ type: "text", text: `Reminder set: "${reminder2.text}"${dueStr}` }]
17561
+ };
17562
+ }
17563
+ if (action === "list") {
17564
+ const reminders = await listReminders(include_completed);
17565
+ if (reminders.length === 0) {
17566
+ return {
17567
+ content: [{ type: "text", text: "No active reminders." }]
17568
+ };
17569
+ }
17570
+ const lines = reminders.map((r) => {
17571
+ const due = r.dueDate ? ` (due: ${r.dueDate})` : "";
17572
+ const done = r.completedAt ? " [DONE]" : "";
17573
+ return `\u2022 ${r.text}${due}${done} [id: ${r.id.slice(0, 8)}]`;
17574
+ });
17575
+ return {
17576
+ content: [{ type: "text", text: lines.join("\n") }]
17577
+ };
17578
+ }
17579
+ if (!reminder_id) {
17580
+ return {
17581
+ content: [{ type: "text", text: "Missing required field: reminder_id is required for complete action." }],
17582
+ isError: true
17583
+ };
17584
+ }
17585
+ const reminder = await completeReminder(reminder_id);
17586
+ if (!reminder) {
17587
+ return {
17588
+ content: [{ type: "text", text: `No active reminder matching "${reminder_id}".` }]
17589
+ };
17590
+ }
17591
+ return {
17592
+ content: [{ type: "text", text: `Reminder completed: "${reminder.text}"` }]
17593
+ };
17594
+ }
17595
+ );
17596
+ }
17597
+
17598
+ // src/mcp/tools/global-procedure.ts
17599
+ init_global_procedures();
17600
+ init_platform_procedures();
17601
+ init_active_agent();
17602
+ init_database();
17603
+ init_employees();
17604
+ import { z as z45 } from "zod";
17605
+ function registerGlobalProcedure(server2) {
17606
+ server2.registerTool(
17607
+ "global_procedure",
17608
+ {
17609
+ title: "Global Procedure",
17610
+ description: "Manage organization-wide procedures (Layer 0) that supersede identity, expertise, and experience. Actions: store (create new, restricted), list (view all, open), deactivate (soft-delete, restricted).",
17611
+ inputSchema: {
17612
+ action: z45.enum(["store", "list", "deactivate"]).describe("Action to perform"),
17613
+ title: z45.string().optional().describe("Short title for the procedure (store)"),
17614
+ content: z45.string().max(500).optional().describe("The procedure content \u2014 clear, actionable instruction (store)"),
17615
+ priority: z45.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
17616
+ domain: z45.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security"),
17617
+ procedure_id: z45.string().optional().describe("UUID of the global procedure (deactivate)")
17618
+ }
17619
+ },
17620
+ async ({ action, title, content, priority, domain, procedure_id }) => {
17621
+ if (action === "list") {
17622
+ const customerProcs = await loadGlobalProcedures();
17623
+ if (customerProcs.length === 0) {
17624
+ return {
17625
+ content: [{
17626
+ type: "text",
17627
+ text: `No custom procedures. ${PLATFORM_PROCEDURES.length} platform procedures are active (shipped with exe-os, not editable).
17628
+ Use global_procedure with action "store" to add org-specific rules.`
17629
+ }]
17630
+ };
17631
+ }
17632
+ const lines = customerProcs.map(
17633
+ (p) => `[${p.id}] (${p.priority}) ${p.title}${p.domain ? ` [${p.domain}]` : ""}
17634
+ ${p.content}`
17635
+ );
17636
+ return {
17637
+ content: [{
17638
+ type: "text",
17639
+ text: `Custom procedures (${customerProcs.length}) + ${PLATFORM_PROCEDURES.length} platform procedures (built-in):
17640
+
17641
+ ${lines.join("\n\n")}`
17642
+ }]
17643
+ };
17644
+ }
17645
+ const caller = getActiveAgent();
17646
+ const allowed = canCoordinate(caller.agentId, caller.agentRole);
17647
+ if (!allowed) {
17648
+ return {
17649
+ content: [{
17650
+ type: "text",
17651
+ text: `Permission denied. Only the coordinator or founder sessions can ${action} global procedures. You are "${caller.agentId}".`
17652
+ }],
17653
+ isError: true
17654
+ };
17655
+ }
17656
+ if (action === "store") {
17657
+ if (!title || !content) {
17658
+ return {
17659
+ content: [{
17660
+ type: "text",
17661
+ text: "Missing required fields: title and content are required for store action."
17662
+ }],
17663
+ isError: true
17664
+ };
17665
+ }
17666
+ const id = await storeGlobalProcedure({
17667
+ title,
17668
+ content,
17669
+ priority: priority ?? "p0",
17670
+ domain: domain ?? void 0
17671
+ });
17672
+ return {
17673
+ content: [{
17674
+ type: "text",
17675
+ text: `Global procedure stored.
17676
+ ID: ${id}
17677
+ Title: ${title}
17678
+ Priority: ${priority ?? "p0"}
17679
+ Domain: ${domain ?? "none"}`
17680
+ }]
17681
+ };
17682
+ }
17683
+ if (!procedure_id) {
17684
+ return {
17685
+ content: [{
17686
+ type: "text",
17687
+ text: "Missing required field: procedure_id is required for deactivate action."
17688
+ }],
17689
+ isError: true
17690
+ };
17691
+ }
17692
+ const client = getClient();
17693
+ const result = await client.execute({
17694
+ sql: "SELECT id, title, content, priority, domain FROM global_procedures WHERE id = ?",
17695
+ args: [procedure_id]
17696
+ });
17697
+ if (result.rows.length === 0) {
17698
+ return {
17699
+ content: [{
17700
+ type: "text",
17701
+ text: `Global procedure not found: ${procedure_id}`
17702
+ }],
17703
+ isError: true
17704
+ };
17705
+ }
17706
+ const row = result.rows[0];
17707
+ const wasActive = await deactivateGlobalProcedure(procedure_id);
17708
+ if (!wasActive) {
17709
+ return {
17710
+ content: [{
17711
+ type: "text",
17712
+ text: `Global procedure ${procedure_id} was already inactive.`
17713
+ }]
17714
+ };
17715
+ }
17716
+ return {
17717
+ content: [{
17718
+ type: "text",
17719
+ text: `Deactivated global procedure.
17720
+ ID: ${row.id}
17721
+ Title: ${row.title}
17722
+ Priority: ${row.priority}
17723
+ Domain: ${row.domain ?? "none"}
17724
+ Content: ${row.content}`
17725
+ }]
17726
+ };
17727
+ }
17728
+ );
17729
+ }
17730
+
17731
+ // src/mcp/tools/store-global-procedure.ts
17732
+ init_global_procedures();
17733
+ init_active_agent();
17734
+ init_employees();
17735
+ import { z as z46 } from "zod";
17736
+ function registerStoreGlobalProcedure(server2) {
17737
+ server2.registerTool(
17738
+ "store_global_procedure",
17739
+ {
17740
+ title: "Store Global Procedure (use global_procedure instead)",
17741
+ description: "DEPRECATED \u2014 use global_procedure with action='store'. Create an organization-wide procedure (Layer 0). RESTRICTED: only coordinator or founder sessions.",
17742
+ inputSchema: {
17743
+ title: z46.string().describe("Short title for the procedure"),
17744
+ content: z46.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
17745
+ priority: z46.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default)."),
17746
+ domain: z46.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
17747
+ }
17748
+ },
17749
+ async ({ title, content, priority, domain }) => {
17750
+ const caller = getActiveAgent();
17751
+ const allowed = canCoordinate(caller.agentId, caller.agentRole);
17752
+ if (!allowed) {
17753
+ return {
17754
+ content: [{
17755
+ type: "text",
17756
+ text: `Permission denied. Only the coordinator or founder sessions can create global procedures. You are "${caller.agentId}".`
17757
+ }],
17758
+ isError: true
17759
+ };
17760
+ }
17761
+ const id = await storeGlobalProcedure({
17762
+ title,
17763
+ content,
17764
+ priority: priority ?? "p0",
17765
+ domain: domain ?? void 0
17766
+ });
17767
+ return {
17768
+ content: [{
17769
+ type: "text",
17770
+ text: `Global procedure stored.
17771
+ ID: ${id}
17772
+ Title: ${title}
17773
+ Priority: ${priority ?? "p0"}
17774
+ Domain: ${domain ?? "none"}`
17775
+ }]
17776
+ };
17777
+ }
17778
+ );
17779
+ }
17780
+
17781
+ // src/mcp/tools/list-global-procedures.ts
17782
+ init_global_procedures();
17783
+ init_platform_procedures();
17784
+ function registerListGlobalProcedures(server2) {
17785
+ server2.registerTool(
17786
+ "list_global_procedures",
17787
+ {
17788
+ title: "List Global Procedures (use global_procedure instead)",
17789
+ description: "DEPRECATED \u2014 use global_procedure with action='list'. List all active organization-wide procedures (Layer 0).",
17226
17790
  inputSchema: {}
17227
17791
  },
17228
17792
  async () => {
@@ -17232,7 +17796,7 @@ function registerListGlobalProcedures(server2) {
17232
17796
  content: [{
17233
17797
  type: "text",
17234
17798
  text: `No custom procedures. ${PLATFORM_PROCEDURES.length} platform procedures are active (shipped with exe-os, not editable).
17235
- Use store_global_procedure to add org-specific rules.`
17799
+ Use global_procedure with action "store" to add org-specific rules.`
17236
17800
  }]
17237
17801
  };
17238
17802
  }
@@ -17257,15 +17821,15 @@ init_global_procedures();
17257
17821
  init_active_agent();
17258
17822
  init_database();
17259
17823
  init_employees();
17260
- import { z as z44 } from "zod";
17824
+ import { z as z47 } from "zod";
17261
17825
  function registerDeactivateGlobalProcedure(server2) {
17262
17826
  server2.registerTool(
17263
17827
  "deactivate_global_procedure",
17264
17828
  {
17265
- title: "Deactivate Global Procedure",
17266
- description: "Soft-delete a global procedure by setting active = 0. RESTRICTED: only coordinator or founder sessions. Use list_global_procedures to find the procedure ID first.",
17829
+ title: "Deactivate Global Procedure (use global_procedure instead)",
17830
+ description: "DEPRECATED \u2014 use global_procedure with action='deactivate'. Soft-delete a global procedure. RESTRICTED: only coordinator or founder sessions.",
17267
17831
  inputSchema: {
17268
- procedure_id: z44.string().describe("UUID of the global procedure to deactivate")
17832
+ procedure_id: z47.string().describe("UUID of the global procedure to deactivate")
17269
17833
  }
17270
17834
  },
17271
17835
  async ({ procedure_id }) => {
@@ -17320,7 +17884,7 @@ Content: ${row.content}`
17320
17884
  }
17321
17885
 
17322
17886
  // src/mcp/tools/search-everything.ts
17323
- import { z as z45 } from "zod";
17887
+ import { z as z48 } from "zod";
17324
17888
 
17325
17889
  // src/lib/unified-search.ts
17326
17890
  var DEFAULT_LIMIT = 10;
@@ -17487,11 +18051,11 @@ function registerSearchEverything(server2) {
17487
18051
  title: "Search Everything",
17488
18052
  description: "Search across all data stores \u2014 memories, conversations, and wiki \u2014 in one query. Returns merged results sorted by relevance with entity links.",
17489
18053
  inputSchema: {
17490
- query: z45.string().describe("What to search for across all data stores"),
17491
- sources: z45.array(z45.enum(["memory", "conversations", "wiki"])).optional().describe(
18054
+ query: z48.string().describe("What to search for across all data stores"),
18055
+ sources: z48.array(z48.enum(["memory", "conversations", "wiki"])).optional().describe(
17492
18056
  "Which sources to search (default: all). Options: memory, conversations, wiki"
17493
18057
  ),
17494
- limit: z45.coerce.number().int().min(1).max(50).optional().default(10).describe("Max results to return (default 10, max 50)")
18058
+ limit: z48.coerce.number().int().min(1).max(50).optional().default(10).describe("Max results to return (default 10, max 50)")
17495
18059
  }
17496
18060
  },
17497
18061
  async (params) => {
@@ -17552,8 +18116,8 @@ init_store();
17552
18116
  init_active_agent();
17553
18117
  init_database();
17554
18118
  init_plan_limits();
17555
- import { z as z46 } from "zod";
17556
- import crypto16 from "crypto";
18119
+ import { z as z49 } from "zod";
18120
+ import crypto15 from "crypto";
17557
18121
  function registerStoreDecision(server2) {
17558
18122
  server2.registerTool(
17559
18123
  "store_decision",
@@ -17561,13 +18125,13 @@ function registerStoreDecision(server2) {
17561
18125
  title: "Store Decision",
17562
18126
  description: "Store an authoritative decision keyed by domain. Use this when a decision is made that should be canonical \u2014 future lookups via get_decision return the latest decision for that domain. Supports supersession chains.",
17563
18127
  inputSchema: {
17564
- domain: z46.string().describe(
18128
+ domain: z49.string().describe(
17565
18129
  "Domain key, e.g. 'auth-strategy', 'db-migration-approach', 'api-versioning'"
17566
18130
  ),
17567
- decision: z46.string().describe("The decision text \u2014 what was decided"),
17568
- rationale: z46.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
17569
- supersedes: z46.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
17570
- project_name: z46.string().optional().describe("Project name")
18131
+ decision: z49.string().describe("The decision text \u2014 what was decided"),
18132
+ rationale: z49.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
18133
+ supersedes: z49.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
18134
+ project_name: z49.string().optional().describe("Project name")
17571
18135
  }
17572
18136
  },
17573
18137
  async ({ domain, decision, rationale, supersedes, project_name }) => {
@@ -17591,7 +18155,7 @@ function registerStoreDecision(server2) {
17591
18155
  } catch {
17592
18156
  vector = null;
17593
18157
  }
17594
- const memoryId = crypto16.randomUUID();
18158
+ const memoryId = crypto15.randomUUID();
17595
18159
  if (supersedes) {
17596
18160
  try {
17597
18161
  const client = getClient();
@@ -17635,7 +18199,7 @@ Supersedes: ${supersedes}` : ""}`
17635
18199
 
17636
18200
  // src/mcp/tools/get-decision.ts
17637
18201
  init_database();
17638
- import { z as z47 } from "zod";
18202
+ import { z as z50 } from "zod";
17639
18203
  function registerGetDecision(server2) {
17640
18204
  server2.registerTool(
17641
18205
  "get_decision",
@@ -17643,7 +18207,7 @@ function registerGetDecision(server2) {
17643
18207
  title: "Get Decision",
17644
18208
  description: "Retrieve the latest authoritative decision for a domain. Returns the current active decision and the supersession history.",
17645
18209
  inputSchema: {
17646
- domain: z47.string().describe(
18210
+ domain: z50.string().describe(
17647
18211
  "Domain key to look up, e.g. 'auth-strategy', 'db-migration-approach'"
17648
18212
  )
17649
18213
  }
@@ -17706,7 +18270,7 @@ function registerGetDecision(server2) {
17706
18270
  }
17707
18271
 
17708
18272
  // src/mcp/tools/get-agent-spend.ts
17709
- import { z as z48 } from "zod";
18273
+ import { z as z51 } from "zod";
17710
18274
 
17711
18275
  // src/lib/token-spend.ts
17712
18276
  init_database();
@@ -17876,8 +18440,8 @@ function registerGetAgentSpend(server2) {
17876
18440
  title: "Get Agent Spend",
17877
18441
  description: "Get per-agent token spend attribution. Shows input, output, and cache tokens consumed by each agent over a time period, with estimated cost.",
17878
18442
  inputSchema: {
17879
- period: z48.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to query"),
17880
- agent_id: z48.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'yoshi')")
18443
+ period: z51.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to query"),
18444
+ agent_id: z51.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'yoshi')")
17881
18445
  }
17882
18446
  },
17883
18447
  async ({ period, agent_id }) => {
@@ -17943,7 +18507,7 @@ function registerGetAgentSpend(server2) {
17943
18507
  // src/mcp/tools/get-graph-stats.ts
17944
18508
  init_database();
17945
18509
  init_graph_query();
17946
- import { z as z49 } from "zod";
18510
+ import { z as z52 } from "zod";
17947
18511
  function registerGetGraphStats(server2) {
17948
18512
  server2.registerTool(
17949
18513
  "get_graph_stats",
@@ -17951,7 +18515,7 @@ function registerGetGraphStats(server2) {
17951
18515
  title: "Get Graph Stats",
17952
18516
  description: "Get knowledge graph summary statistics: entity count, relationship count, and entity type breakdown.",
17953
18517
  inputSchema: {
17954
- _dummy: z49.string().optional().describe("Unused \u2014 no input required")
18518
+ _dummy: z52.string().optional().describe("Unused \u2014 no input required")
17955
18519
  }
17956
18520
  },
17957
18521
  async () => {
@@ -17993,7 +18557,7 @@ function registerGetGraphStats(server2) {
17993
18557
  // src/mcp/tools/get-entity-neighbors.ts
17994
18558
  init_database();
17995
18559
  init_graph_query();
17996
- import { z as z50 } from "zod";
18560
+ import { z as z53 } from "zod";
17997
18561
  function registerGetEntityNeighbors(server2) {
17998
18562
  server2.registerTool(
17999
18563
  "get_entity_neighbors",
@@ -18001,7 +18565,7 @@ function registerGetEntityNeighbors(server2) {
18001
18565
  title: "Get Entity Neighbors",
18002
18566
  description: "Get connected entities for a given entity name. Returns neighbors with relationship types, directions, and weights.",
18003
18567
  inputSchema: {
18004
- entity_name: z50.string().describe("Name of the entity to find neighbors for")
18568
+ entity_name: z53.string().describe("Name of the entity to find neighbors for")
18005
18569
  }
18006
18570
  },
18007
18571
  async ({ entity_name }) => {
@@ -18070,7 +18634,7 @@ function registerGetEntityNeighbors(server2) {
18070
18634
  // src/mcp/tools/get-hot-entities.ts
18071
18635
  init_database();
18072
18636
  init_graph_query();
18073
- import { z as z51 } from "zod";
18637
+ import { z as z54 } from "zod";
18074
18638
  var PERIOD_MS = {
18075
18639
  "24h": 24 * 60 * 60 * 1e3,
18076
18640
  "7d": 7 * 24 * 60 * 60 * 1e3,
@@ -18083,8 +18647,8 @@ function registerGetHotEntities(server2) {
18083
18647
  title: "Get Hot Entities",
18084
18648
  description: "Get trending entities \u2014 those with the most new relationships in a time period. Surfaces what's most active in the knowledge graph.",
18085
18649
  inputSchema: {
18086
- period: z51.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to look back"),
18087
- limit: z51.number().int().min(1).max(50).default(10).describe("Max entities to return")
18650
+ period: z54.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to look back"),
18651
+ limit: z54.number().int().min(1).max(50).default(10).describe("Max entities to return")
18088
18652
  }
18089
18653
  },
18090
18654
  async ({ period, limit }) => {
@@ -18132,7 +18696,7 @@ function registerGetHotEntities(server2) {
18132
18696
 
18133
18697
  // src/mcp/tools/export-graph.ts
18134
18698
  init_database();
18135
- import { z as z52 } from "zod";
18699
+ import { z as z55 } from "zod";
18136
18700
 
18137
18701
  // src/lib/graph-export.ts
18138
18702
  async function loadGraphData(client) {
@@ -18345,7 +18909,7 @@ function registerExportGraph(server2) {
18345
18909
  title: "Export Graph",
18346
18910
  description: "Export the knowledge graph as a markdown report (inline) or an interactive HTML visualization (writes file, returns path).",
18347
18911
  inputSchema: {
18348
- format: z52.enum(["html", "markdown"]).default("markdown").describe("Export format: markdown (inline) or html (file)")
18912
+ format: z55.enum(["html", "markdown"]).default("markdown").describe("Export format: markdown (inline) or html (file)")
18349
18913
  }
18350
18914
  },
18351
18915
  async ({ format }) => {
@@ -18359,12 +18923,12 @@ function registerExportGraph(server2) {
18359
18923
  }
18360
18924
  const html = await exportGraphHTML(client);
18361
18925
  const fs = await import("fs");
18362
- const path45 = await import("path");
18363
- const os19 = await import("os");
18364
- const outDir = path45.join(os19.homedir(), ".exe-os", "exports");
18926
+ const path44 = await import("path");
18927
+ const os18 = await import("os");
18928
+ const outDir = path44.join(os18.homedir(), ".exe-os", "exports");
18365
18929
  fs.mkdirSync(outDir, { recursive: true });
18366
18930
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
18367
- const filePath = path45.join(outDir, `graph-${timestamp}.html`);
18931
+ const filePath = path44.join(outDir, `graph-${timestamp}.html`);
18368
18932
  fs.writeFileSync(filePath, html, "utf-8");
18369
18933
  return {
18370
18934
  content: [
@@ -18395,7 +18959,7 @@ Open in a browser to explore interactively.`
18395
18959
 
18396
18960
  // src/mcp/tools/find-similar-trajectories.ts
18397
18961
  init_skill_learning();
18398
- import { z as z53 } from "zod";
18962
+ import { z as z56 } from "zod";
18399
18963
  function registerFindSimilarTrajectories(server2) {
18400
18964
  server2.registerTool(
18401
18965
  "find_similar_trajectories",
@@ -18403,7 +18967,7 @@ function registerFindSimilarTrajectories(server2) {
18403
18967
  title: "Find Similar Trajectories",
18404
18968
  description: 'Find past task trajectories that match a described tool sequence. Input a comma-separated tool sequence (e.g. "Read, Edit, Bash, Read") to find similar past workflows.',
18405
18969
  inputSchema: {
18406
- description: z53.string().describe(
18970
+ description: z56.string().describe(
18407
18971
  'Tool sequence to match \u2014 comma-separated tool names (e.g. "Read, Grep, Edit, Bash:npm, Bash:git")'
18408
18972
  )
18409
18973
  }
@@ -18474,7 +19038,7 @@ ${withSkill.length} trajectory(s) already extracted into skill(s).`
18474
19038
 
18475
19039
  // src/mcp/tools/get-session-kills.ts
18476
19040
  init_session_kill_telemetry();
18477
- import { z as z54 } from "zod";
19041
+ import { z as z57 } from "zod";
18478
19042
  var PERIOD_MS2 = {
18479
19043
  "24h": 24 * 60 * 60 * 1e3,
18480
19044
  "7d": 7 * 24 * 60 * 60 * 1e3,
@@ -18490,7 +19054,7 @@ function registerGetSessionKills(server2) {
18490
19054
  title: "Get Session Kills",
18491
19055
  description: "Get session kill telemetry: how many idle/TTL sessions were killed, tokens saved, and estimated cost savings over a time period.",
18492
19056
  inputSchema: {
18493
- period: z54.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to query")
19057
+ period: z57.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to query")
18494
19058
  }
18495
19059
  },
18496
19060
  async ({ period }) => {
@@ -18530,7 +19094,7 @@ function registerGetSessionKills(server2) {
18530
19094
 
18531
19095
  // src/mcp/tools/list-agent-sessions.ts
18532
19096
  init_session_registry();
18533
- import { z as z55 } from "zod";
19097
+ import { z as z58 } from "zod";
18534
19098
  function registerListAgentSessions(server2) {
18535
19099
  server2.registerTool(
18536
19100
  "list_agent_sessions",
@@ -18538,7 +19102,7 @@ function registerListAgentSessions(server2) {
18538
19102
  title: "List Agent Sessions",
18539
19103
  description: "List all registered agent sessions with their agent ID, project, PID, and registration time.",
18540
19104
  inputSchema: {
18541
- _placeholder: z55.string().optional().describe("No input required")
19105
+ _placeholder: z58.string().optional().describe("No input required")
18542
19106
  }
18543
19107
  },
18544
19108
  async () => {
@@ -18584,7 +19148,7 @@ function registerListAgentSessions(server2) {
18584
19148
  }
18585
19149
 
18586
19150
  // src/mcp/tools/get-daemon-health.ts
18587
- import { z as z56 } from "zod";
19151
+ import { z as z59 } from "zod";
18588
19152
  import { existsSync as existsSync25, readFileSync as readFileSync22 } from "fs";
18589
19153
  import path34 from "path";
18590
19154
  import { homedir as homedir3 } from "os";
@@ -18615,7 +19179,7 @@ function registerGetDaemonHealth(server2) {
18615
19179
  title: "Get Daemon Health",
18616
19180
  description: "Check the embedding daemon (exed) health: whether it's running, its PID, uptime, and requests served.",
18617
19181
  inputSchema: {
18618
- _placeholder: z56.string().optional().describe("No input required")
19182
+ _placeholder: z59.string().optional().describe("No input required")
18619
19183
  }
18620
19184
  },
18621
19185
  async () => {
@@ -18667,7 +19231,7 @@ function registerGetDaemonHealth(server2) {
18667
19231
  // src/mcp/tools/get-auto-wake-status.ts
18668
19232
  init_database();
18669
19233
  init_session_registry();
18670
- import { z as z57 } from "zod";
19234
+ import { z as z60 } from "zod";
18671
19235
 
18672
19236
  // src/lib/daemon-orchestration.ts
18673
19237
  init_tmux_routing();
@@ -18695,7 +19259,7 @@ function registerGetAutoWakeStatus(server2) {
18695
19259
  title: "Get Auto-Wake Status",
18696
19260
  description: "Check auto-wake status: orphaned tasks (assigned agent has no running session), tasks blocked by auto-wake retry limit, and session activity.",
18697
19261
  inputSchema: {
18698
- _placeholder: z57.string().optional().describe("No input required")
19262
+ _placeholder: z60.string().optional().describe("No input required")
18699
19263
  }
18700
19264
  },
18701
19265
  async () => {
@@ -18776,7 +19340,7 @@ function registerGetAutoWakeStatus(server2) {
18776
19340
  // src/mcp/tools/get-worker-gate.ts
18777
19341
  init_worker_gate();
18778
19342
  init_config();
18779
- import { z as z58 } from "zod";
19343
+ import { z as z61 } from "zod";
18780
19344
  import { readdirSync as readdirSync11, existsSync as existsSync28 } from "fs";
18781
19345
  import path36 from "path";
18782
19346
  var WORKER_PID_DIR2 = path36.join(EXE_AI_DIR, "worker-pids");
@@ -18814,7 +19378,7 @@ function registerGetWorkerGate(server2) {
18814
19378
  title: "Get Worker Gate",
18815
19379
  description: "Check worker concurrency gate status: how many worker slots are in use, the maximum allowed, and whether new workers can spawn.",
18816
19380
  inputSchema: {
18817
- _placeholder: z58.string().optional().describe("No input required")
19381
+ _placeholder: z61.string().optional().describe("No input required")
18818
19382
  }
18819
19383
  },
18820
19384
  async () => {
@@ -18850,7 +19414,7 @@ function registerGetWorkerGate(server2) {
18850
19414
 
18851
19415
  // src/mcp/tools/run-memory-audit.ts
18852
19416
  init_database();
18853
- import { z as z59 } from "zod";
19417
+ import { z as z62 } from "zod";
18854
19418
 
18855
19419
  // src/bin/exe-doctor.ts
18856
19420
  init_store();
@@ -19654,8 +20218,8 @@ function registerRunMemoryAudit(server2) {
19654
20218
  title: "Run Memory Audit",
19655
20219
  description: "Run a memory health audit: total counts, per-agent breakdown, null vectors, duplicates, FTS sync status, bloated records, and conflict detection (contradictory/superseded memories).",
19656
20220
  inputSchema: {
19657
- agent_id: z59.string().optional().describe("Filter audit to a specific agent"),
19658
- project_name: z59.string().optional().describe("Filter audit to a specific project")
20221
+ agent_id: z62.string().optional().describe("Filter audit to a specific agent"),
20222
+ project_name: z62.string().optional().describe("Filter audit to a specific project")
19659
20223
  }
19660
20224
  },
19661
20225
  async ({ agent_id, project_name }) => {
@@ -19688,17 +20252,17 @@ function registerRunMemoryAudit(server2) {
19688
20252
  }
19689
20253
 
19690
20254
  // src/mcp/tools/cloud-sync.ts
19691
- import { z as z60 } from "zod";
20255
+ import { z as z63 } from "zod";
19692
20256
 
19693
20257
  // src/lib/cloud-sync.ts
19694
20258
  init_database();
19695
20259
  import { readFileSync as readFileSync26, writeFileSync as writeFileSync20, existsSync as existsSync31, readdirSync as readdirSync12, mkdirSync as mkdirSync16, appendFileSync as appendFileSync2, unlinkSync as unlinkSync10, openSync as openSync2, closeSync as closeSync2 } from "fs";
19696
- import crypto18 from "crypto";
20260
+ import crypto17 from "crypto";
19697
20261
  import path39 from "path";
19698
20262
  import { homedir as homedir6 } from "os";
19699
20263
 
19700
20264
  // src/lib/crypto.ts
19701
- import crypto17 from "crypto";
20265
+ import crypto16 from "crypto";
19702
20266
  var ALGORITHM = "aes-256-gcm";
19703
20267
  var IV_LENGTH = 12;
19704
20268
  var TAG_LENGTH = 16;
@@ -19709,7 +20273,7 @@ function initSyncCrypto(masterKey) {
19709
20273
  throw new Error(`Master key must be 32 bytes, got ${masterKey.length}`);
19710
20274
  }
19711
20275
  _syncKey = Buffer.from(
19712
- crypto17.hkdfSync("sha256", masterKey, "", SYNC_HKDF_INFO, 32)
20276
+ crypto16.hkdfSync("sha256", masterKey, "", SYNC_HKDF_INFO, 32)
19713
20277
  );
19714
20278
  }
19715
20279
  function isSyncCryptoInitialized() {
@@ -19723,8 +20287,8 @@ function requireSyncKey() {
19723
20287
  }
19724
20288
  function encryptSyncBlob(data) {
19725
20289
  const key = requireSyncKey();
19726
- const iv = crypto17.randomBytes(IV_LENGTH);
19727
- const cipher = crypto17.createCipheriv(ALGORITHM, key, iv);
20290
+ const iv = crypto16.randomBytes(IV_LENGTH);
20291
+ const cipher = crypto16.createCipheriv(ALGORITHM, key, iv);
19728
20292
  const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
19729
20293
  const tag = cipher.getAuthTag();
19730
20294
  return Buffer.concat([iv, encrypted, tag]).toString("base64");
@@ -19738,7 +20302,7 @@ function decryptSyncBlob(ciphertext) {
19738
20302
  const iv = combined.subarray(0, IV_LENGTH);
19739
20303
  const tag = combined.subarray(combined.length - TAG_LENGTH);
19740
20304
  const encrypted = combined.subarray(IV_LENGTH, combined.length - TAG_LENGTH);
19741
- const decipher = crypto17.createDecipheriv(ALGORITHM, key, iv);
20305
+ const decipher = crypto16.createDecipheriv(ALGORITHM, key, iv);
19742
20306
  decipher.setAuthTag(tag);
19743
20307
  return Buffer.concat([decipher.update(encrypted), decipher.final()]);
19744
20308
  }
@@ -19805,12 +20369,12 @@ function loadPgClient() {
19805
20369
  }
19806
20370
  if (!_pgPromise) {
19807
20371
  _pgPromise = (async () => {
19808
- const { createRequire: createRequire6 } = await import("module");
19809
- const { pathToFileURL: pathToFileURL6 } = await import("url");
20372
+ const { createRequire: createRequire5 } = await import("module");
20373
+ const { pathToFileURL: pathToFileURL5 } = await import("url");
19810
20374
  const exeDbRoot = process.env.EXE_DB_ROOT ?? path39.join(homedir6(), "exe-db");
19811
- const req = createRequire6(path39.join(exeDbRoot, "package.json"));
20375
+ const req = createRequire5(path39.join(exeDbRoot, "package.json"));
19812
20376
  const entry = req.resolve("@prisma/client");
19813
- const mod = await import(pathToFileURL6(entry).href);
20377
+ const mod = await import(pathToFileURL5(entry).href);
19814
20378
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
19815
20379
  if (!Ctor) throw new Error("No PrismaClient");
19816
20380
  return new Ctor();
@@ -20315,7 +20879,7 @@ function buildRosterBlob(paths) {
20315
20879
  }
20316
20880
  const deletedNames = consumeRosterDeletions();
20317
20881
  const content = JSON.stringify({ roster, identities, config: config2, agentConfig, deletedNames });
20318
- const hash = crypto18.createHash("sha256").update(content).digest("hex").slice(0, 16);
20882
+ const hash = crypto17.createHash("sha256").update(content).digest("hex").slice(0, 16);
20319
20883
  return { roster, identities, config: config2, agentConfig, deletedNames, version: hash };
20320
20884
  }
20321
20885
  async function cloudPushRoster(config2) {
@@ -20902,7 +21466,7 @@ function registerCloudSync(server2) {
20902
21466
  title: "Cloud Sync",
20903
21467
  description: "Trigger a cloud sync cycle \u2014 pulls remote changes then pushes local. Reports pushed/pulled counts for memories, behaviors, graph, tasks, and more.",
20904
21468
  inputSchema: {
20905
- force: z60.boolean().default(false).describe("Force sync even if recently synced")
21469
+ force: z63.boolean().default(false).describe("Force sync even if recently synced")
20906
21470
  }
20907
21471
  },
20908
21472
  async () => {
@@ -20955,7 +21519,7 @@ function registerCloudSync(server2) {
20955
21519
 
20956
21520
  // src/mcp/tools/get-memory-cardinality.ts
20957
21521
  init_database();
20958
- import { z as z61 } from "zod";
21522
+ import { z as z64 } from "zod";
20959
21523
  function registerGetMemoryCardinality(server2) {
20960
21524
  server2.registerTool(
20961
21525
  "get_memory_cardinality",
@@ -20963,7 +21527,7 @@ function registerGetMemoryCardinality(server2) {
20963
21527
  title: "Get Memory Cardinality",
20964
21528
  description: "Get memory counts: total active memories and per-project breakdown. Optionally filter by agent.",
20965
21529
  inputSchema: {
20966
- agent_id: z61.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'exe')")
21530
+ agent_id: z64.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'exe')")
20967
21531
  }
20968
21532
  },
20969
21533
  async ({ agent_id }) => {
@@ -21046,7 +21610,7 @@ function registerGetMemoryCardinality(server2) {
21046
21610
  init_database();
21047
21611
  init_consolidation();
21048
21612
  init_config();
21049
- import { z as z62 } from "zod";
21613
+ import { z as z65 } from "zod";
21050
21614
  function registerRunConsolidation(server2) {
21051
21615
  server2.registerTool(
21052
21616
  "run_consolidation",
@@ -21054,7 +21618,7 @@ function registerRunConsolidation(server2) {
21054
21618
  title: "Run Consolidation",
21055
21619
  description: "Run memory consolidation \u2014 synthesizes unconsolidated memories into meta-insights. Use dry_run=true (default) to preview without executing.",
21056
21620
  inputSchema: {
21057
- dry_run: z62.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
21621
+ dry_run: z65.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
21058
21622
  }
21059
21623
  },
21060
21624
  async ({ dry_run }) => {
@@ -21123,7 +21687,7 @@ function registerRunConsolidation(server2) {
21123
21687
 
21124
21688
  // src/mcp/tools/get-license-status.ts
21125
21689
  init_license();
21126
- import { z as z63 } from "zod";
21690
+ import { z as z66 } from "zod";
21127
21691
  var FEATURES = [
21128
21692
  "cloud_sync",
21129
21693
  "external_agents",
@@ -21137,7 +21701,7 @@ function registerGetLicenseStatus(server2) {
21137
21701
  title: "Get License Status",
21138
21702
  description: "Get current license status: plan, validity, feature gates, limits, and expiry.",
21139
21703
  inputSchema: {
21140
- _dummy: z63.string().optional().describe("Unused \u2014 no input required")
21704
+ _dummy: z66.string().optional().describe("Unused \u2014 no input required")
21141
21705
  }
21142
21706
  },
21143
21707
  async () => {
@@ -21190,7 +21754,7 @@ function registerGetLicenseStatus(server2) {
21190
21754
 
21191
21755
  // src/mcp/tools/backup-vps.ts
21192
21756
  init_keychain();
21193
- import { z as z64 } from "zod";
21757
+ import { z as z67 } from "zod";
21194
21758
 
21195
21759
  // src/lib/vps-backup.ts
21196
21760
  import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
@@ -21515,43 +22079,43 @@ function registerBackupVps(server2) {
21515
22079
  {
21516
22080
  title: "VPS Backup",
21517
22081
  description: "Run VPS Postgres backup/restore workflows and check status.",
21518
- inputSchema: z64.discriminatedUnion("action", [
21519
- z64.object({
21520
- action: z64.literal("backup"),
21521
- databaseUrl: z64.string().min(1).describe("Postgres DATABASE_URL to dump from"),
21522
- encryptionKeyB64: z64.string().min(1).max(4096).optional().describe(
22082
+ inputSchema: z67.discriminatedUnion("action", [
22083
+ z67.object({
22084
+ action: z67.literal("backup"),
22085
+ databaseUrl: z67.string().min(1).describe("Postgres DATABASE_URL to dump from"),
22086
+ encryptionKeyB64: z67.string().min(1).max(4096).optional().describe(
21523
22087
  "Base64 AES-256 key (defaults to local master key if omitted)"
21524
22088
  ),
21525
- r2Bucket: z64.string().min(1).describe("R2 bucket name"),
21526
- r2Endpoint: z64.string().min(1).describe("R2 endpoint URL"),
21527
- r2AccessKeyId: z64.string().min(1).describe("R2 access key ID"),
21528
- r2SecretAccessKey: z64.string().min(1).describe("R2 secret access key")
22089
+ r2Bucket: z67.string().min(1).describe("R2 bucket name"),
22090
+ r2Endpoint: z67.string().min(1).describe("R2 endpoint URL"),
22091
+ r2AccessKeyId: z67.string().min(1).describe("R2 access key ID"),
22092
+ r2SecretAccessKey: z67.string().min(1).describe("R2 secret access key")
21529
22093
  }),
21530
- z64.object({
21531
- action: z64.literal("restore"),
21532
- databaseUrl: z64.string().min(1).describe("Target Postgres DATABASE_URL for restore"),
21533
- backupKey: z64.string().min(1).describe("R2 object key to restore from"),
21534
- encryptionKeyB64: z64.string().min(1).max(4096).optional().describe(
22094
+ z67.object({
22095
+ action: z67.literal("restore"),
22096
+ databaseUrl: z67.string().min(1).describe("Target Postgres DATABASE_URL for restore"),
22097
+ backupKey: z67.string().min(1).describe("R2 object key to restore from"),
22098
+ encryptionKeyB64: z67.string().min(1).max(4096).optional().describe(
21535
22099
  "Base64 AES-256 key (defaults to local master key if omitted)"
21536
22100
  ),
21537
- r2Bucket: z64.string().min(1).describe("R2 bucket name"),
21538
- r2Endpoint: z64.string().min(1).describe("R2 endpoint URL"),
21539
- r2AccessKeyId: z64.string().min(1).describe("R2 access key ID"),
21540
- r2SecretAccessKey: z64.string().min(1).describe("R2 secret access key")
22101
+ r2Bucket: z67.string().min(1).describe("R2 bucket name"),
22102
+ r2Endpoint: z67.string().min(1).describe("R2 endpoint URL"),
22103
+ r2AccessKeyId: z67.string().min(1).describe("R2 access key ID"),
22104
+ r2SecretAccessKey: z67.string().min(1).describe("R2 secret access key")
21541
22105
  }),
21542
- z64.object({
21543
- action: z64.literal("list"),
21544
- r2Bucket: z64.string().min(1).describe("R2 bucket name"),
21545
- r2Endpoint: z64.string().min(1).describe("R2 endpoint URL"),
21546
- r2AccessKeyId: z64.string().min(1).describe("R2 access key ID"),
21547
- r2SecretAccessKey: z64.string().min(1).describe("R2 secret access key")
22106
+ z67.object({
22107
+ action: z67.literal("list"),
22108
+ r2Bucket: z67.string().min(1).describe("R2 bucket name"),
22109
+ r2Endpoint: z67.string().min(1).describe("R2 endpoint URL"),
22110
+ r2AccessKeyId: z67.string().min(1).describe("R2 access key ID"),
22111
+ r2SecretAccessKey: z67.string().min(1).describe("R2 secret access key")
21548
22112
  }),
21549
- z64.object({
21550
- action: z64.literal("health"),
21551
- r2Bucket: z64.string().min(1).describe("R2 bucket name"),
21552
- r2Endpoint: z64.string().min(1).describe("R2 endpoint URL"),
21553
- r2AccessKeyId: z64.string().min(1).describe("R2 access key ID"),
21554
- r2SecretAccessKey: z64.string().min(1).describe("R2 secret access key")
22113
+ z67.object({
22114
+ action: z67.literal("health"),
22115
+ r2Bucket: z67.string().min(1).describe("R2 bucket name"),
22116
+ r2Endpoint: z67.string().min(1).describe("R2 endpoint URL"),
22117
+ r2AccessKeyId: z67.string().min(1).describe("R2 access key ID"),
22118
+ r2SecretAccessKey: z67.string().min(1).describe("R2 secret access key")
21555
22119
  })
21556
22120
  ])
21557
22121
  },
@@ -21689,7 +22253,7 @@ async function resolveEncryptionKey(providedB64) {
21689
22253
  }
21690
22254
 
21691
22255
  // src/mcp/tools/people-roster.ts
21692
- import { z as z65 } from "zod";
22256
+ import { z as z68 } from "zod";
21693
22257
 
21694
22258
  // src/lib/people.ts
21695
22259
  init_config();
@@ -21737,10 +22301,10 @@ function registerAddPerson(server2) {
21737
22301
  title: "Add Person",
21738
22302
  description: "Add or update a key human in the people roster. Used for co-founders, partners, customers \u2014 anyone agents need to know about.",
21739
22303
  inputSchema: {
21740
- name: z65.string().describe("Person's name"),
21741
- role: z65.string().describe("Their role (e.g. co-founder, customer, partner)"),
21742
- relationship: z65.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
21743
- notes: z65.string().optional().describe("Additional context about this person")
22304
+ name: z68.string().describe("Person's name"),
22305
+ role: z68.string().describe("Their role (e.g. co-founder, customer, partner)"),
22306
+ relationship: z68.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
22307
+ notes: z68.string().optional().describe("Additional context about this person")
21744
22308
  }
21745
22309
  },
21746
22310
  async ({ name, role, relationship, notes }) => {
@@ -21786,7 +22350,7 @@ function registerGetPerson(server2) {
21786
22350
  title: "Get Person",
21787
22351
  description: "Look up a specific person by name from the people roster.",
21788
22352
  inputSchema: {
21789
- name: z65.string().describe("Person's name to look up")
22353
+ name: z68.string().describe("Person's name to look up")
21790
22354
  }
21791
22355
  },
21792
22356
  async ({ name }) => {
@@ -21814,7 +22378,7 @@ init_active_agent();
21814
22378
  init_agent_config();
21815
22379
  init_runtime_table();
21816
22380
  init_employees();
21817
- import { z as z66 } from "zod";
22381
+ import { z as z69 } from "zod";
21818
22382
  function registerSetAgentConfig(server2) {
21819
22383
  server2.registerTool(
21820
22384
  "set_agent_config",
@@ -21822,10 +22386,10 @@ function registerSetAgentConfig(server2) {
21822
22386
  title: "Set Agent Config",
21823
22387
  description: "Set or view per-agent runtime + model configuration. Controls which runtime (claude, codex, opencode) and model each agent uses when dispatched. COO-only. Omit runtime/model to view current config for an agent or all agents.",
21824
22388
  inputSchema: {
21825
- agent_id: z66.string().optional().describe("Agent name, or 'default' for org-wide default. Omit to view all agents."),
21826
- runtime: z66.string().optional().describe(`Runtime: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`),
21827
- model: z66.string().optional().describe("Model name (e.g. claude-opus-4, gpt-5.4, anthropic/claude-sonnet-4-6)"),
21828
- reasoning_effort: z66.string().optional().describe("Codex reasoning effort: low, medium, high, xhigh. Per-agent override for thinking/reasoning depth.")
22389
+ agent_id: z69.string().optional().describe("Agent name, or 'default' for org-wide default. Omit to view all agents."),
22390
+ runtime: z69.string().optional().describe(`Runtime: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`),
22391
+ model: z69.string().optional().describe("Model name (e.g. claude-opus-4, gpt-5.4, anthropic/claude-sonnet-4-6)"),
22392
+ reasoning_effort: z69.string().optional().describe("Codex reasoning effort: low, medium, high, xhigh. Per-agent override for thinking/reasoning depth.")
21829
22393
  }
21830
22394
  },
21831
22395
  async ({ agent_id, runtime, model, reasoning_effort }) => {
@@ -21923,7 +22487,7 @@ function registerSetAgentConfig(server2) {
21923
22487
  // src/mcp/tools/list-employees.ts
21924
22488
  init_employees();
21925
22489
  init_agent_config();
21926
- import { z as z67 } from "zod";
22490
+ import { z as z70 } from "zod";
21927
22491
  function registerListEmployees(server2) {
21928
22492
  server2.registerTool(
21929
22493
  "list_employees",
@@ -21931,7 +22495,7 @@ function registerListEmployees(server2) {
21931
22495
  title: "List Employees",
21932
22496
  description: "List all AI employees in the organization with their role, runtime, and model configuration. Use to see who's on the team and how they're configured.",
21933
22497
  inputSchema: {
21934
- role: z67.string().optional().describe("Filter by role (case-insensitive)")
22498
+ role: z70.string().optional().describe("Filter by role (case-insensitive)")
21935
22499
  }
21936
22500
  },
21937
22501
  async ({ role }) => {
@@ -21986,12 +22550,14 @@ function registerListEmployees(server2) {
21986
22550
  );
21987
22551
  }
21988
22552
 
21989
- // src/mcp/tools/ingest-raw.ts
22553
+ // src/mcp/tools/create-license.ts
22554
+ init_license();
21990
22555
  import os16 from "os";
21991
22556
  import path41 from "path";
22557
+ import { randomBytes as randomBytes2, randomUUID as randomUUID8 } from "crypto";
21992
22558
  import { createRequire as createRequire3 } from "module";
21993
22559
  import { pathToFileURL as pathToFileURL3 } from "url";
21994
- import { z as z68 } from "zod";
22560
+ import { z as z71 } from "zod";
21995
22561
  var prismaPromise = null;
21996
22562
  function loadPrisma() {
21997
22563
  if (!prismaPromise) {
@@ -22014,101 +22580,6 @@ function loadPrisma() {
22014
22580
  }
22015
22581
  return prismaPromise;
22016
22582
  }
22017
- function registerIngestRaw(server2) {
22018
- server2.registerTool(
22019
- "ingest_raw",
22020
- {
22021
- title: "Ingest Raw Event",
22022
- description: "Insert a raw event into the landing pad (raw.raw_events). Used by the gateway, external agents, and webhooks to push data into the Company Brain. Background projection workers process unprocessed events and route to curated schemas.",
22023
- inputSchema: {
22024
- source: z68.string().describe(
22025
- 'Event source identifier: "whatsapp", "shopify", "asana", "email", "external_agent", etc.'
22026
- ),
22027
- event_type: z68.string().describe(
22028
- 'Event type: "message", "order", "task_update", "webhook", etc.'
22029
- ),
22030
- payload: z68.record(z68.string(), z68.unknown()).describe(
22031
- "Exact raw JSON payload \u2014 stored verbatim, never modified."
22032
- ),
22033
- source_id: z68.string().optional().describe(
22034
- "External reference ID for deduplication (e.g., WhatsApp message ID, Shopify order ID)."
22035
- ),
22036
- metadata: z68.record(z68.string(), z68.unknown()).optional().describe(
22037
- "Source-specific metadata (account info, adapter version, etc.)."
22038
- )
22039
- }
22040
- },
22041
- async ({ source, event_type, payload, source_id, metadata }) => {
22042
- try {
22043
- const prisma = await loadPrisma();
22044
- const id = crypto.randomUUID();
22045
- await prisma.$executeRawUnsafe(
22046
- `INSERT INTO "raw"."raw_events" ("id", "source", "source_id", "event_type", "payload", "metadata", "timestamp")
22047
- VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, NOW())
22048
- ON CONFLICT ("source", "source_id", "event_type") DO NOTHING`,
22049
- id,
22050
- source,
22051
- source_id ?? null,
22052
- event_type,
22053
- JSON.stringify(payload),
22054
- metadata ? JSON.stringify(metadata) : null
22055
- );
22056
- return {
22057
- content: [{
22058
- type: "text",
22059
- text: JSON.stringify({
22060
- event_id: id,
22061
- source,
22062
- event_type,
22063
- source_id: source_id ?? null,
22064
- status: "ingested"
22065
- })
22066
- }]
22067
- };
22068
- } catch (err) {
22069
- const message = err instanceof Error ? err.message : String(err);
22070
- return {
22071
- content: [{
22072
- type: "text",
22073
- text: `Error ingesting raw event: ${message}`
22074
- }],
22075
- isError: true
22076
- };
22077
- }
22078
- }
22079
- );
22080
- }
22081
-
22082
- // src/mcp/tools/create-license.ts
22083
- init_license();
22084
- import os17 from "os";
22085
- import path42 from "path";
22086
- import { randomBytes as randomBytes2, randomUUID as randomUUID8 } from "crypto";
22087
- import { createRequire as createRequire4 } from "module";
22088
- import { pathToFileURL as pathToFileURL4 } from "url";
22089
- import { z as z69 } from "zod";
22090
- var prismaPromise2 = null;
22091
- function loadPrisma2() {
22092
- if (!prismaPromise2) {
22093
- prismaPromise2 = (async () => {
22094
- const explicitPath = process.env.EXE_OS_PRISMA_CLIENT_PATH;
22095
- if (explicitPath) {
22096
- const mod2 = await import(pathToFileURL4(explicitPath).href);
22097
- const Ctor2 = mod2.PrismaClient ?? mod2.default?.PrismaClient;
22098
- if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
22099
- return new Ctor2();
22100
- }
22101
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path42.join(os17.homedir(), "exe-db");
22102
- const req = createRequire4(path42.join(exeDbRoot, "package.json"));
22103
- const entry = req.resolve("@prisma/client");
22104
- const mod = await import(pathToFileURL4(entry).href);
22105
- const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
22106
- if (!Ctor) throw new Error(`No PrismaClient in ${entry}`);
22107
- return new Ctor();
22108
- })();
22109
- }
22110
- return prismaPromise2;
22111
- }
22112
22583
  function generateKey() {
22113
22584
  return `exe_sk_${randomBytes2(16).toString("hex")}`;
22114
22585
  }
@@ -22119,15 +22590,15 @@ function registerCreateLicense(server2) {
22119
22590
  title: "Create License",
22120
22591
  description: "Generate an exe_sk_* license key for a user. Stores in billing.licenses. Returns the key to give to the customer.",
22121
22592
  inputSchema: {
22122
- email: z69.string().email().describe("Customer email address"),
22123
- name: z69.string().optional().describe("Customer name"),
22124
- plan: z69.enum(["free", "pro", "team", "agency", "enterprise"]).default("pro").describe("License plan tier"),
22125
- expires_in_days: z69.number().int().positive().default(365).describe("Days until expiration (default 365)")
22593
+ email: z71.string().email().describe("Customer email address"),
22594
+ name: z71.string().optional().describe("Customer name"),
22595
+ plan: z71.enum(["free", "pro", "team", "agency", "enterprise"]).default("pro").describe("License plan tier"),
22596
+ expires_in_days: z71.number().int().positive().default(365).describe("Days until expiration (default 365)")
22126
22597
  }
22127
22598
  },
22128
22599
  async ({ email, name, plan, expires_in_days }) => {
22129
22600
  try {
22130
- const prisma = await loadPrisma2();
22601
+ const prisma = await loadPrisma();
22131
22602
  const id = randomUUID8();
22132
22603
  const key = generateKey();
22133
22604
  const limits = PLAN_LIMITS[plan];
@@ -22173,32 +22644,32 @@ Give this key to the customer. They paste it during \`exe-os setup\`.`);
22173
22644
  }
22174
22645
 
22175
22646
  // src/mcp/tools/list-licenses.ts
22176
- import os18 from "os";
22177
- import path43 from "path";
22178
- import { createRequire as createRequire5 } from "module";
22179
- import { pathToFileURL as pathToFileURL5 } from "url";
22180
- import { z as z70 } from "zod";
22181
- var prismaPromise3 = null;
22182
- function loadPrisma3() {
22183
- if (!prismaPromise3) {
22184
- prismaPromise3 = (async () => {
22647
+ import os17 from "os";
22648
+ import path42 from "path";
22649
+ import { createRequire as createRequire4 } from "module";
22650
+ import { pathToFileURL as pathToFileURL4 } from "url";
22651
+ import { z as z72 } from "zod";
22652
+ var prismaPromise2 = null;
22653
+ function loadPrisma2() {
22654
+ if (!prismaPromise2) {
22655
+ prismaPromise2 = (async () => {
22185
22656
  const explicitPath = process.env.EXE_OS_PRISMA_CLIENT_PATH;
22186
22657
  if (explicitPath) {
22187
- const mod2 = await import(pathToFileURL5(explicitPath).href);
22658
+ const mod2 = await import(pathToFileURL4(explicitPath).href);
22188
22659
  const Ctor2 = mod2.PrismaClient ?? mod2.default?.PrismaClient;
22189
22660
  if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
22190
22661
  return new Ctor2();
22191
22662
  }
22192
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path43.join(os18.homedir(), "exe-db");
22193
- const req = createRequire5(path43.join(exeDbRoot, "package.json"));
22663
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path42.join(os17.homedir(), "exe-db");
22664
+ const req = createRequire4(path42.join(exeDbRoot, "package.json"));
22194
22665
  const entry = req.resolve("@prisma/client");
22195
- const mod = await import(pathToFileURL5(entry).href);
22666
+ const mod = await import(pathToFileURL4(entry).href);
22196
22667
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
22197
22668
  if (!Ctor) throw new Error(`No PrismaClient in ${entry}`);
22198
22669
  return new Ctor();
22199
22670
  })();
22200
22671
  }
22201
- return prismaPromise3;
22672
+ return prismaPromise2;
22202
22673
  }
22203
22674
  function registerListLicenses(server2) {
22204
22675
  server2.registerTool(
@@ -22207,12 +22678,12 @@ function registerListLicenses(server2) {
22207
22678
  title: "List Licenses",
22208
22679
  description: "List all issued licenses with status (active/expired/revoked). Optionally filter by plan.",
22209
22680
  inputSchema: {
22210
- plan: z70.enum(["free", "pro", "team", "agency", "enterprise"]).optional().describe("Filter by plan tier (omit for all)")
22681
+ plan: z72.enum(["free", "pro", "team", "agency", "enterprise"]).optional().describe("Filter by plan tier (omit for all)")
22211
22682
  }
22212
22683
  },
22213
22684
  async ({ plan }) => {
22214
22685
  try {
22215
- const prisma = await loadPrisma3();
22686
+ const prisma = await loadPrisma2();
22216
22687
  let rows;
22217
22688
  if (plan) {
22218
22689
  rows = await prisma.$queryRawUnsafe(
@@ -22258,7 +22729,7 @@ function registerListLicenses(server2) {
22258
22729
 
22259
22730
  // src/mcp/tools/activate-license.ts
22260
22731
  init_license();
22261
- import { z as z71 } from "zod";
22732
+ import { z as z73 } from "zod";
22262
22733
  function registerActivateLicense(server2) {
22263
22734
  server2.registerTool(
22264
22735
  "activate_license",
@@ -22266,7 +22737,7 @@ function registerActivateLicense(server2) {
22266
22737
  title: "Activate License",
22267
22738
  description: "Activate an exe_sk_* license key on this device. Writes to ~/.exe-os/license.key, validates against Postgres, and caches the result.",
22268
22739
  inputSchema: {
22269
- key: z71.string().startsWith("exe_sk_").describe("License key (exe_sk_*)")
22740
+ key: z73.string().startsWith("exe_sk_").describe("License key (exe_sk_*)")
22270
22741
  }
22271
22742
  },
22272
22743
  async ({ key }) => {
@@ -22313,9 +22784,9 @@ Key saved to ~/.exe-os/license.key. Device ID: ${deviceId}`);
22313
22784
 
22314
22785
  // src/mcp/tools/query-company-brain.ts
22315
22786
  init_config();
22316
- import { z as z72 } from "zod";
22787
+ import { z as z74 } from "zod";
22317
22788
  var FETCH_TIMEOUT_MS5 = 1e4;
22318
- var QUERY_SCOPE = z72.enum(["raw", "wiki", "memory", "gateway", "all"]);
22789
+ var QUERY_SCOPE = z74.enum(["raw", "wiki", "memory", "gateway", "all"]);
22319
22790
  function formatSuccess(query, scope, payload) {
22320
22791
  const pretty = typeof payload === "string" ? payload : JSON.stringify(payload, null, 2);
22321
22792
  return [
@@ -22334,10 +22805,10 @@ function registerQueryCompanyBrain(server2) {
22334
22805
  title: "Query Company Brain",
22335
22806
  description: "Search the Company Brain \u2014 queries across all data (raw events, wiki docs, agent memories, gateway messages).",
22336
22807
  inputSchema: {
22337
- query: z72.string().min(1).describe("Search text"),
22808
+ query: z74.string().min(1).describe("Search text"),
22338
22809
  scope: QUERY_SCOPE.default("all").describe("Which data scope to search"),
22339
- source: z72.string().optional().describe("Filter raw events by source (shopify, asana, etc.)"),
22340
- limit: z72.coerce.number().int().min(1).max(100).default(20).describe("Max results per scope")
22810
+ source: z74.string().optional().describe("Filter raw events by source (shopify, asana, etc.)"),
22811
+ limit: z74.coerce.number().int().min(1).max(100).default(20).describe("Max results per scope")
22341
22812
  }
22342
22813
  },
22343
22814
  async ({ query, scope, source, limit }) => {
@@ -22492,15 +22963,11 @@ registerCloseTask(server);
22492
22963
  registerGetTask(server);
22493
22964
  registerCheckpointTask(server);
22494
22965
  registerResumeEmployee(server);
22495
- registerStoreBehavior(server);
22966
+ registerBehavior(server);
22496
22967
  registerSendMessage(server);
22497
- registerCreateReminder(server);
22498
- registerListReminders(server);
22499
- registerCompleteReminder(server);
22500
- registerListBehaviors(server);
22968
+ registerReminder(server);
22501
22969
  registerGetIdentity(server);
22502
22970
  registerUpdateIdentity(server);
22503
- registerDeactivateBehavior(server);
22504
22971
  registerIngestDocument(server);
22505
22972
  registerListDocuments(server);
22506
22973
  registerPurgeDocument(server);
@@ -22522,9 +22989,16 @@ registerImportOrchestration(server);
22522
22989
  registerQueryConversations(server);
22523
22990
  registerLoadSkill(server);
22524
22991
  registerConsolidateMemories(server);
22992
+ registerGlobalProcedure(server);
22525
22993
  registerStoreGlobalProcedure(server);
22526
22994
  registerListGlobalProcedures(server);
22527
22995
  registerDeactivateGlobalProcedure(server);
22996
+ registerStoreBehavior(server);
22997
+ registerListBehaviors(server);
22998
+ registerDeactivateBehavior(server);
22999
+ registerCreateReminder(server);
23000
+ registerListReminders(server);
23001
+ registerCompleteReminder(server);
22528
23002
  registerSearchEverything(server);
22529
23003
  registerStoreDecision(server);
22530
23004
  registerGetDecision(server);
@@ -22550,7 +23024,6 @@ registerListPeople(server);
22550
23024
  registerGetPerson(server);
22551
23025
  registerSetAgentConfig(server);
22552
23026
  registerListEmployees(server);
22553
- registerIngestRaw(server);
22554
23027
  registerCreateLicense(server);
22555
23028
  registerListLicenses(server);
22556
23029
  registerActivateLicense(server);
@@ -22623,14 +23096,14 @@ try {
22623
23096
  `
22624
23097
  );
22625
23098
  const thisFile = fileURLToPath5(import.meta.url);
22626
- const backfillPath = path44.resolve(
22627
- path44.dirname(thisFile),
23099
+ const backfillPath = path43.resolve(
23100
+ path43.dirname(thisFile),
22628
23101
  "../bin/backfill-vectors.js"
22629
23102
  );
22630
23103
  if (existsSync33(backfillPath)) {
22631
23104
  const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
22632
- const logPath = path44.join(exeDir, "workers.log");
22633
- mkdirSync17(path44.dirname(logPath), { recursive: true });
23105
+ const logPath = path43.join(exeDir, "workers.log");
23106
+ mkdirSync17(path43.dirname(logPath), { recursive: true });
22634
23107
  let logFd = "ignore";
22635
23108
  try {
22636
23109
  logFd = openSync3(logPath, "a");