@askexenow/exe-os 0.9.93 → 0.9.95

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 (88) hide show
  1. package/deploy/compose/docker-compose.yml +1 -0
  2. package/dist/bin/agentic-ontology-backfill.js +65 -8
  3. package/dist/bin/agentic-reflection-backfill.js +54 -3
  4. package/dist/bin/agentic-semantic-label.js +54 -3
  5. package/dist/bin/backfill-conversations.js +69 -9
  6. package/dist/bin/backfill-responses.js +69 -9
  7. package/dist/bin/backfill-vectors.js +54 -3
  8. package/dist/bin/bulk-sync-postgres.js +66 -8
  9. package/dist/bin/cleanup-stale-review-tasks.js +121 -13
  10. package/dist/bin/cli.js +1561 -466
  11. package/dist/bin/customer-readiness.js +61 -0
  12. package/dist/bin/exe-agent.js +17 -3
  13. package/dist/bin/exe-assign.js +75 -9
  14. package/dist/bin/exe-boot.js +114 -12
  15. package/dist/bin/exe-call.js +17 -3
  16. package/dist/bin/exe-cloud.js +76 -10
  17. package/dist/bin/exe-dispatch.js +136 -18
  18. package/dist/bin/exe-doctor.js +75 -9
  19. package/dist/bin/exe-export-behaviors.js +75 -9
  20. package/dist/bin/exe-forget.js +94 -9
  21. package/dist/bin/exe-gateway.js +135 -18
  22. package/dist/bin/exe-heartbeat.js +121 -13
  23. package/dist/bin/exe-kill.js +75 -9
  24. package/dist/bin/exe-launch-agent.js +75 -9
  25. package/dist/bin/exe-new-employee.js +18 -4
  26. package/dist/bin/exe-pending-messages.js +121 -13
  27. package/dist/bin/exe-pending-notifications.js +121 -13
  28. package/dist/bin/exe-pending-reviews.js +121 -13
  29. package/dist/bin/exe-rename.js +75 -9
  30. package/dist/bin/exe-review.js +75 -9
  31. package/dist/bin/exe-search.js +100 -9
  32. package/dist/bin/exe-session-cleanup.js +136 -18
  33. package/dist/bin/exe-settings.js +1 -0
  34. package/dist/bin/exe-start-codex.js +65 -8
  35. package/dist/bin/exe-start-opencode.js +65 -8
  36. package/dist/bin/exe-status.js +121 -13
  37. package/dist/bin/exe-support.js +1 -0
  38. package/dist/bin/exe-team.js +75 -9
  39. package/dist/bin/git-sweep.js +136 -18
  40. package/dist/bin/graph-backfill.js +65 -8
  41. package/dist/bin/graph-export.js +75 -9
  42. package/dist/bin/intercom-check.js +136 -18
  43. package/dist/bin/scan-tasks.js +136 -18
  44. package/dist/bin/setup.js +55 -4
  45. package/dist/bin/shard-migrate.js +65 -8
  46. package/dist/bin/stack-update.js +5 -6
  47. package/dist/bin/update.js +1 -1
  48. package/dist/gateway/index.js +136 -18
  49. package/dist/hooks/bug-report-worker.js +136 -18
  50. package/dist/hooks/codex-stop-task-finalizer.js +126 -14
  51. package/dist/hooks/commit-complete.js +136 -18
  52. package/dist/hooks/error-recall.js +100 -9
  53. package/dist/hooks/ingest.js +75 -9
  54. package/dist/hooks/instructions-loaded.js +75 -9
  55. package/dist/hooks/notification.js +75 -9
  56. package/dist/hooks/post-compact.js +313 -50
  57. package/dist/hooks/post-tool-combined.js +436 -13
  58. package/dist/hooks/pre-compact.js +136 -18
  59. package/dist/hooks/pre-tool-use.js +121 -13
  60. package/dist/hooks/prompt-submit.js +194 -19
  61. package/dist/hooks/session-end.js +136 -18
  62. package/dist/hooks/session-start.js +146 -13
  63. package/dist/hooks/stop.js +121 -13
  64. package/dist/hooks/subagent-stop.js +121 -13
  65. package/dist/hooks/summary-worker.js +99 -7
  66. package/dist/index.js +136 -18
  67. package/dist/lib/cloud-sync.js +38 -0
  68. package/dist/lib/consolidation.js +3 -1
  69. package/dist/lib/database.js +37 -0
  70. package/dist/lib/db.js +37 -0
  71. package/dist/lib/device-registry.js +37 -0
  72. package/dist/lib/employee-templates.js +17 -3
  73. package/dist/lib/exe-daemon.js +916 -42
  74. package/dist/lib/hybrid-search.js +100 -9
  75. package/dist/lib/license.js +1 -1
  76. package/dist/lib/messaging.js +43 -4
  77. package/dist/lib/schedules.js +54 -3
  78. package/dist/lib/store.js +75 -9
  79. package/dist/lib/tasks.js +61 -9
  80. package/dist/lib/tmux-routing.js +61 -9
  81. package/dist/mcp/server.js +878 -42
  82. package/dist/mcp/tools/create-task.js +70 -12
  83. package/dist/mcp/tools/list-tasks.js +49 -5
  84. package/dist/mcp/tools/send-message.js +43 -4
  85. package/dist/mcp/tools/update-task.js +61 -9
  86. package/dist/runtime/index.js +136 -18
  87. package/dist/tui/App.js +135 -18
  88. package/package.json +1 -1
@@ -3366,6 +3366,20 @@ async function ensureSchema() {
3366
3366
  });
3367
3367
  } catch {
3368
3368
  }
3369
+ try {
3370
+ await client.execute({
3371
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
3372
+ args: []
3373
+ });
3374
+ } catch {
3375
+ }
3376
+ try {
3377
+ await client.execute({
3378
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
3379
+ args: []
3380
+ });
3381
+ } catch {
3382
+ }
3369
3383
  await client.executeMultiple(`
3370
3384
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
3371
3385
  content_text,
@@ -3617,6 +3631,22 @@ async function ensureSchema() {
3617
3631
  );
3618
3632
  } catch {
3619
3633
  }
3634
+ for (const col of [
3635
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
3636
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
3637
+ ]) {
3638
+ try {
3639
+ await client.execute(col);
3640
+ } catch {
3641
+ }
3642
+ }
3643
+ try {
3644
+ await client.execute({
3645
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3646
+ args: []
3647
+ });
3648
+ } catch {
3649
+ }
3620
3650
  try {
3621
3651
  await client.execute({
3622
3652
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -3659,6 +3689,13 @@ async function ensureSchema() {
3659
3689
  } catch {
3660
3690
  }
3661
3691
  }
3692
+ try {
3693
+ await client.execute({
3694
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3695
+ args: []
3696
+ });
3697
+ } catch {
3698
+ }
3662
3699
  try {
3663
3700
  await client.execute({
3664
3701
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -3719,7 +3756,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
3719
3756
  import os7 from "os";
3720
3757
  import path9 from "path";
3721
3758
  import { jwtVerify, importSPKI } from "jose";
3722
- var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, PLAN_LIMITS;
3759
+ var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, PLAN_LIMITS;
3723
3760
  var init_license = __esm({
3724
3761
  "src/lib/license.ts"() {
3725
3762
  "use strict";
@@ -3727,6 +3764,7 @@ var init_license = __esm({
3727
3764
  LICENSE_PATH = path9.join(EXE_AI_DIR, "license.key");
3728
3765
  CACHE_PATH = path9.join(EXE_AI_DIR, "license-cache.json");
3729
3766
  DEVICE_ID_PATH = path9.join(EXE_AI_DIR, "device-id");
3767
+ API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
3730
3768
  PLAN_LIMITS = {
3731
3769
  free: { devices: 1, employees: 1, memories: 5e3 },
3732
3770
  pro: { devices: 3, employees: 5, memories: 1e5 },
@@ -4353,8 +4391,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
4353
4391
  const complexity = input.complexity ?? "standard";
4354
4392
  const sessionScope = earlySessionScope;
4355
4393
  await client.execute({
4356
- sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, session_scope, created_at, updated_at)
4357
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
4394
+ sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, session_scope, spawn_runtime, spawn_model, created_at, updated_at)
4395
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
4358
4396
  args: [
4359
4397
  id,
4360
4398
  input.title,
@@ -4374,6 +4412,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
4374
4412
  0,
4375
4413
  null,
4376
4414
  sessionScope,
4415
+ input.spawnRuntime ?? null,
4416
+ input.spawnModel ?? null,
4377
4417
  now,
4378
4418
  now
4379
4419
  ]
@@ -4430,7 +4470,9 @@ ${input.context}
4430
4470
  budgetTokens: input.budgetTokens ?? null,
4431
4471
  budgetFallbackModel: input.budgetFallbackModel ?? null,
4432
4472
  tokensUsed: 0,
4433
- tokensWarnedAt: null
4473
+ tokensWarnedAt: null,
4474
+ spawnRuntime: input.spawnRuntime ?? null,
4475
+ spawnModel: input.spawnModel ?? null
4434
4476
  };
4435
4477
  }
4436
4478
  async function listTasks(input) {
@@ -4480,7 +4522,9 @@ async function listTasks(input) {
4480
4522
  budgetTokens: r.budget_tokens !== null ? Number(r.budget_tokens) : null,
4481
4523
  budgetFallbackModel: r.budget_fallback_model !== null ? String(r.budget_fallback_model) : null,
4482
4524
  tokensUsed: Number(r.tokens_used ?? 0),
4483
- tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null
4525
+ tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null,
4526
+ spawnRuntime: r.spawn_runtime !== null && r.spawn_runtime !== void 0 ? String(r.spawn_runtime) : null,
4527
+ spawnModel: r.spawn_model !== null && r.spawn_model !== void 0 ? String(r.spawn_model) : null
4484
4528
  }));
4485
4529
  }
4486
4530
  function isTmuxSessionAlive(identifier) {
@@ -5777,6 +5821,8 @@ async function updateTask(input) {
5777
5821
  budgetFallbackModel: row.budget_fallback_model !== void 0 && row.budget_fallback_model !== null ? String(row.budget_fallback_model) : null,
5778
5822
  tokensUsed: Number(row.tokens_used ?? 0),
5779
5823
  tokensWarnedAt: row.tokens_warned_at !== void 0 && row.tokens_warned_at !== null ? Number(row.tokens_warned_at) : null,
5824
+ spawnRuntime: row.spawn_runtime !== void 0 && row.spawn_runtime !== null ? String(row.spawn_runtime) : null,
5825
+ spawnModel: row.spawn_model !== void 0 && row.spawn_model !== null ? String(row.spawn_model) : null,
5780
5826
  nextTask
5781
5827
  };
5782
5828
  }
@@ -6269,9 +6315,13 @@ function getDispatchedBy(sessionKey) {
6269
6315
  }
6270
6316
  }
6271
6317
  function resolveExeSession() {
6318
+ if (process.env.EXE_SESSION_NAME) {
6319
+ return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
6320
+ }
6272
6321
  const mySession = getMySession();
6273
6322
  if (!mySession) return null;
6274
6323
  const fromSessionName = extractRootExe(mySession);
6324
+ let candidate = null;
6275
6325
  try {
6276
6326
  const key = getSessionKey();
6277
6327
  const parentExe = getParentExe(key);
@@ -6282,13 +6332,47 @@ function resolveExeSession() {
6282
6332
  `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
6283
6333
  `
6284
6334
  );
6285
- return fromSessionName;
6335
+ candidate = fromSessionName;
6336
+ } else {
6337
+ candidate = fromCache;
6286
6338
  }
6287
- return fromCache;
6288
6339
  }
6289
6340
  } catch {
6290
6341
  }
6291
- return fromSessionName ?? mySession;
6342
+ if (!candidate) {
6343
+ candidate = fromSessionName ?? mySession;
6344
+ }
6345
+ if (candidate && isRootSession(candidate)) {
6346
+ try {
6347
+ const transport = getTransport();
6348
+ const liveSessions = transport.listSessions();
6349
+ if (!liveSessions.includes(candidate)) {
6350
+ const liveRoots = liveSessions.filter((s) => isRootSession(s));
6351
+ if (liveRoots.length === 1) {
6352
+ process.stderr.write(
6353
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
6354
+ `
6355
+ );
6356
+ return liveRoots[0];
6357
+ } else if (liveRoots.length > 1) {
6358
+ const base = candidate.replace(/\d+$/, "");
6359
+ const match = liveRoots.find((s) => s.startsWith(base));
6360
+ const chosen = match ?? liveRoots[0];
6361
+ process.stderr.write(
6362
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
6363
+ `
6364
+ );
6365
+ return chosen;
6366
+ }
6367
+ process.stderr.write(
6368
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
6369
+ `
6370
+ );
6371
+ }
6372
+ } catch {
6373
+ }
6374
+ }
6375
+ return candidate;
6292
6376
  }
6293
6377
  function isEmployeeAlive(sessionName) {
6294
6378
  return getTransport().isAlive(sessionName);
@@ -6690,7 +6774,12 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6690
6774
  }
6691
6775
  const spawnCwd = opts?.cwd ?? projectDir;
6692
6776
  const useExeAgent = !!(opts?.model && opts?.provider);
6693
- const agentRtConfig = getAgentRuntime(employeeName);
6777
+ const baseRtConfig = getAgentRuntime(employeeName);
6778
+ const agentRtConfig = {
6779
+ ...baseRtConfig,
6780
+ ...opts?.runtimeOverride ? { runtime: opts.runtimeOverride } : {},
6781
+ ...opts?.modelOverride ? { model: opts.modelOverride } : {}
6782
+ };
6694
6783
  const useCodex = !useExeAgent && agentRtConfig.runtime === "codex";
6695
6784
  const useOpencode = !useExeAgent && !useCodex && agentRtConfig.runtime === "opencode";
6696
6785
  const ccProvider = useExeAgent || useCodex || useOpencode ? DEFAULT_PROVIDER : detectActiveProvider();
@@ -7983,6 +8072,20 @@ var init_platform_procedures = __esm({
7983
8072
  priority: "p1",
7984
8073
  content: "Once per session (COO boot only, never repeat), call list_my_feature_requests to check if any previously filed feature requests have been shipped by AskExe. If any request has status 'shipped' with a shipped_version, surface it to the founder immediately: '\u{1F680} N feature(s) shipped \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no requests exist or none are shipped, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
7985
8074
  },
8075
+ // --- Tool guidance ---
8076
+ {
8077
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
8078
+ domain: "tools",
8079
+ priority: "p2",
8080
+ content: "The company_actions tool executes business actions through gateway connectors (e.g. send WhatsApp, trigger workflows, update CRM). It routes through the exe-gateway on the VPS. Actions are defined by the customer's gateway configuration \u2014 each connector (WhatsApp, Shopify, email, etc.) exposes specific actions. Use query_company_brain to find available data first, then company_actions to act on it. Requires gateway auth token. Read-only founders should NOT use this \u2014 it mutates external state."
8081
+ },
8082
+ // --- Release awareness ---
8083
+ {
8084
+ title: "What's New check \u2014 surface new features after update",
8085
+ domain: "support",
8086
+ priority: "p1",
8087
+ content: "Once per session (COO boot only, never repeat), check if the installed exe-os version is newer than the last session. If it is, read the bundled release-notes.json (at the package root) and surface a brief summary to the founder: 'Updated to exe-os vX.Y.Z \u2014 N new features, M fixes.' List the top 3 features by name. This helps the founder know what they got from the update. If release-notes.json doesn't exist or the version hasn't changed, skip silently. Never repeat this check in the same session."
8088
+ },
7986
8089
  // --- Platform vs Customer ownership ---
7987
8090
  {
7988
8091
  title: "What the platform provides vs what you customize",
@@ -8071,13 +8174,13 @@ var init_platform_procedures = __esm({
8071
8174
  title: "MCP tools \u2014 memory, decision, and search",
8072
8175
  domain: "tool-use",
8073
8176
  priority: "p1",
8074
- content: `memory(action="recall") / recall_my_memory: search your own memories (semantic + FTS). memory(action="ask_team") / ask_team_memory: search a colleague's memories by agent name. memory(action="store") / store_memory: persist a memory. memory(action="commit") / commit_memory: high-importance memory that survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal memory window. Requires session_id + target_timestamp. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. decision(action="store") / store_decision: record an architectural decision (domain, decision, rationale). decision(action="get") / get_decision: retrieve a past decision by domain or query.`
8177
+ content: `memory(action="recall") / recall_my_memory: search memories (semantic + FTS). Params: as_of (bi-temporal \u2014 what did I know at time X?), kind (decision|procedure|observation|raw|conversation|behavior), retrieval_mode (all|decisions_only|procedures_only|operational|recent_high_value). memory(action="ask_team") / ask_team_memory: search a colleague's memories. memory(action="store") / store_memory: persist a memory. Params: kind, procedure_for (domain tag for procedures). memory(action="commit") / commit_memory: high-importance, survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal window. Requires session_id + target_timestamp. memory(action="get_by_id"): fetch one memory by UUID with full untruncated text. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. memory(action="supersede"): replace an old memory with a new version (old_id + new text). decision(action="store") / store_decision: record an architectural decision (domain, decision, rationale). decision(action="get") / get_decision: retrieve a past decision by domain or query.`
8075
8178
  },
8076
8179
  {
8077
8180
  title: "MCP tools \u2014 task orchestration",
8078
8181
  domain: "tool-use",
8079
8182
  priority: "p1",
8080
- content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
8183
+ content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. Params: blocked_by (task ID for dependency), parent_task_id (subtask hierarchy), reviewer, complexity (routine|standard|complex|critical), budget_tokens (max token cap), budget_fallback_model, spawn_runtime (override runtime: claude|codex|opencode), spawn_model (override model). task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
8081
8184
  },
8082
8185
  {
8083
8186
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -8107,7 +8210,7 @@ var init_platform_procedures = __esm({
8107
8210
  title: "MCP tools \u2014 admin, config, and operations",
8108
8211
  domain: "tool-use",
8109
8212
  priority: "p1",
8110
- content: 'config(action="list_employees"): view roster. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. mcp_ping(): daemon health + license status + tool usage stats.'
8213
+ content: 'config(action="list_employees"): view roster. config(action="set_agent_config"): view or change per-agent runtime + model. Call with no args to show all agents. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. Supports cloud_action param: status|sync|reupload. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="worker_gate"): check spawn slot availability \u2014 alive/stale/reserved counts vs max. Use before dispatching. config(action="auto_wake_status"): orphaned tasks, blocked tasks, auto-wake retry status. config(action="orchestration_phase"): view/change org phase (phase_1_coo|phase_2_executives|phase_3_parallel_org). config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. diagnostics(action="pending_work_summary"): pending reviews + messages + notifications in one call. diagnostics(action="rename_employee"): rename an agent across all systems (roster, identity, DB, symlinks). diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role. mcp_ping(): daemon health + license status + tool usage stats.'
8111
8214
  }
8112
8215
  ];
8113
8216
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -8791,6 +8894,8 @@ async function writeMemory(record) {
8791
8894
  source_type: record.source_type ?? null,
8792
8895
  tier: record.tier ?? classifyTier(record),
8793
8896
  supersedes_id: record.supersedes_id ?? null,
8897
+ valid_from: record.valid_from ?? record.timestamp,
8898
+ invalid_at: record.invalid_at ?? null,
8794
8899
  draft: record.draft ? 1 : 0,
8795
8900
  memory_type: memoryType,
8796
8901
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -8809,7 +8914,8 @@ async function writeMemory(record) {
8809
8914
  token_cost: record.token_cost ?? null,
8810
8915
  audience: record.audience ?? null,
8811
8916
  language_type: record.language_type ?? inferLanguageType(record),
8812
- parent_memory_id: record.parent_memory_id ?? null
8917
+ parent_memory_id: record.parent_memory_id ?? null,
8918
+ procedure_for: record.procedure_for ?? null
8813
8919
  };
8814
8920
  _pendingRecords.push(dbRow);
8815
8921
  orgBus.emit({
@@ -8864,6 +8970,8 @@ async function flushBatch() {
8864
8970
  const sourceType = row.source_type ?? null;
8865
8971
  const tier = row.tier ?? 3;
8866
8972
  const supersedesId = row.supersedes_id ?? null;
8973
+ const validFrom = row.valid_from ?? row.timestamp;
8974
+ const invalidAt = row.invalid_at ?? null;
8867
8975
  const draft = row.draft ? 1 : 0;
8868
8976
  const memoryType = row.memory_type ?? "raw";
8869
8977
  const trajectory = row.trajectory ?? null;
@@ -8883,15 +8991,16 @@ async function flushBatch() {
8883
8991
  const audience = row.audience ?? null;
8884
8992
  const languageType = row.language_type ?? null;
8885
8993
  const parentMemoryId = row.parent_memory_id ?? null;
8994
+ const procedureFor = row.procedure_for ?? null;
8886
8995
  const cols = `id, agent_id, agent_role, session_id, timestamp,
8887
8996
  tool_name, project_name,
8888
8997
  has_error, raw_text, vector, version, task_id, importance, status,
8889
8998
  confidence, last_accessed,
8890
8999
  workspace_id, document_id, user_id, char_offset, page_number,
8891
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
9000
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
8892
9001
  intent, outcome, domain, referenced_entities, retrieval_count,
8893
9002
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
8894
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
9003
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
8895
9004
  const metaArgs = [
8896
9005
  intent,
8897
9006
  outcome,
@@ -8907,7 +9016,8 @@ async function flushBatch() {
8907
9016
  tokenCost,
8908
9017
  audience,
8909
9018
  languageType,
8910
- parentMemoryId
9019
+ parentMemoryId,
9020
+ procedureFor
8911
9021
  ];
8912
9022
  const baseArgs = [
8913
9023
  row.id,
@@ -8936,6 +9046,8 @@ async function flushBatch() {
8936
9046
  sourceType,
8937
9047
  tier,
8938
9048
  supersedesId,
9049
+ validFrom,
9050
+ invalidAt,
8939
9051
  draft,
8940
9052
  memoryType,
8941
9053
  trajectory,
@@ -8943,8 +9055,8 @@ async function flushBatch() {
8943
9055
  ];
8944
9056
  return {
8945
9057
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
8946
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
8947
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
9058
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
9059
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
8948
9060
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
8949
9061
  };
8950
9062
  };
@@ -9060,6 +9172,12 @@ async function searchMemories(queryVector, agentId, options) {
9060
9172
  AND vector IS NOT NULL${statusFilter}${draftFilter}
9061
9173
  AND COALESCE(confidence, 0.7) >= 0.3`;
9062
9174
  const args = [agentId];
9175
+ if (options?.asOf) {
9176
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
9177
+ args.push(options.asOf, options.asOf);
9178
+ } else {
9179
+ sql += ` AND invalid_at IS NULL`;
9180
+ }
9063
9181
  const scope = buildWikiScopeFilter(options, "");
9064
9182
  sql += scope.clause;
9065
9183
  args.push(...scope.args);
package/dist/bin/setup.js CHANGED
@@ -1792,7 +1792,7 @@ var init_license = __esm({
1792
1792
  LICENSE_PATH = path6.join(EXE_AI_DIR, "license.key");
1793
1793
  CACHE_PATH = path6.join(EXE_AI_DIR, "license-cache.json");
1794
1794
  DEVICE_ID_PATH = path6.join(EXE_AI_DIR, "device-id");
1795
- API_BASE = "https://askexe.com/cloud";
1795
+ API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
1796
1796
  RETRY_DELAY_MS = 500;
1797
1797
  LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
1798
1798
  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
@@ -4170,6 +4170,20 @@ async function ensureSchema() {
4170
4170
  });
4171
4171
  } catch {
4172
4172
  }
4173
+ try {
4174
+ await client.execute({
4175
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
4176
+ args: []
4177
+ });
4178
+ } catch {
4179
+ }
4180
+ try {
4181
+ await client.execute({
4182
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
4183
+ args: []
4184
+ });
4185
+ } catch {
4186
+ }
4173
4187
  await client.executeMultiple(`
4174
4188
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
4175
4189
  content_text,
@@ -4421,6 +4435,22 @@ async function ensureSchema() {
4421
4435
  );
4422
4436
  } catch {
4423
4437
  }
4438
+ for (const col of [
4439
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
4440
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
4441
+ ]) {
4442
+ try {
4443
+ await client.execute(col);
4444
+ } catch {
4445
+ }
4446
+ }
4447
+ try {
4448
+ await client.execute({
4449
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
4450
+ args: []
4451
+ });
4452
+ } catch {
4453
+ }
4424
4454
  try {
4425
4455
  await client.execute({
4426
4456
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -4463,6 +4493,13 @@ async function ensureSchema() {
4463
4493
  } catch {
4464
4494
  }
4465
4495
  }
4496
+ try {
4497
+ await client.execute({
4498
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
4499
+ args: []
4500
+ });
4501
+ } catch {
4502
+ }
4466
4503
  try {
4467
4504
  await client.execute({
4468
4505
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -6606,6 +6643,20 @@ var init_platform_procedures = __esm({
6606
6643
  priority: "p1",
6607
6644
  content: "Once per session (COO boot only, never repeat), call list_my_feature_requests to check if any previously filed feature requests have been shipped by AskExe. If any request has status 'shipped' with a shipped_version, surface it to the founder immediately: '\u{1F680} N feature(s) shipped \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no requests exist or none are shipped, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
6608
6645
  },
6646
+ // --- Tool guidance ---
6647
+ {
6648
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
6649
+ domain: "tools",
6650
+ priority: "p2",
6651
+ content: "The company_actions tool executes business actions through gateway connectors (e.g. send WhatsApp, trigger workflows, update CRM). It routes through the exe-gateway on the VPS. Actions are defined by the customer's gateway configuration \u2014 each connector (WhatsApp, Shopify, email, etc.) exposes specific actions. Use query_company_brain to find available data first, then company_actions to act on it. Requires gateway auth token. Read-only founders should NOT use this \u2014 it mutates external state."
6652
+ },
6653
+ // --- Release awareness ---
6654
+ {
6655
+ title: "What's New check \u2014 surface new features after update",
6656
+ domain: "support",
6657
+ priority: "p1",
6658
+ content: "Once per session (COO boot only, never repeat), check if the installed exe-os version is newer than the last session. If it is, read the bundled release-notes.json (at the package root) and surface a brief summary to the founder: 'Updated to exe-os vX.Y.Z \u2014 N new features, M fixes.' List the top 3 features by name. This helps the founder know what they got from the update. If release-notes.json doesn't exist or the version hasn't changed, skip silently. Never repeat this check in the same session."
6659
+ },
6609
6660
  // --- Platform vs Customer ownership ---
6610
6661
  {
6611
6662
  title: "What the platform provides vs what you customize",
@@ -6694,13 +6745,13 @@ var init_platform_procedures = __esm({
6694
6745
  title: "MCP tools \u2014 memory, decision, and search",
6695
6746
  domain: "tool-use",
6696
6747
  priority: "p1",
6697
- content: `memory(action="recall") / recall_my_memory: search your own memories (semantic + FTS). memory(action="ask_team") / ask_team_memory: search a colleague's memories by agent name. memory(action="store") / store_memory: persist a memory. memory(action="commit") / commit_memory: high-importance memory that survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal memory window. Requires session_id + target_timestamp. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. decision(action="store") / store_decision: record an architectural decision (domain, decision, rationale). decision(action="get") / get_decision: retrieve a past decision by domain or query.`
6748
+ content: `memory(action="recall") / recall_my_memory: search memories (semantic + FTS). Params: as_of (bi-temporal \u2014 what did I know at time X?), kind (decision|procedure|observation|raw|conversation|behavior), retrieval_mode (all|decisions_only|procedures_only|operational|recent_high_value). memory(action="ask_team") / ask_team_memory: search a colleague's memories. memory(action="store") / store_memory: persist a memory. Params: kind, procedure_for (domain tag for procedures). memory(action="commit") / commit_memory: high-importance, survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal window. Requires session_id + target_timestamp. memory(action="get_by_id"): fetch one memory by UUID with full untruncated text. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. memory(action="supersede"): replace an old memory with a new version (old_id + new text). decision(action="store") / store_decision: record an architectural decision (domain, decision, rationale). decision(action="get") / get_decision: retrieve a past decision by domain or query.`
6698
6749
  },
6699
6750
  {
6700
6751
  title: "MCP tools \u2014 task orchestration",
6701
6752
  domain: "tool-use",
6702
6753
  priority: "p1",
6703
- content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
6754
+ content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. Params: blocked_by (task ID for dependency), parent_task_id (subtask hierarchy), reviewer, complexity (routine|standard|complex|critical), budget_tokens (max token cap), budget_fallback_model, spawn_runtime (override runtime: claude|codex|opencode), spawn_model (override model). task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
6704
6755
  },
6705
6756
  {
6706
6757
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -6730,7 +6781,7 @@ var init_platform_procedures = __esm({
6730
6781
  title: "MCP tools \u2014 admin, config, and operations",
6731
6782
  domain: "tool-use",
6732
6783
  priority: "p1",
6733
- content: 'config(action="list_employees"): view roster. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. mcp_ping(): daemon health + license status + tool usage stats.'
6784
+ content: 'config(action="list_employees"): view roster. config(action="set_agent_config"): view or change per-agent runtime + model. Call with no args to show all agents. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. Supports cloud_action param: status|sync|reupload. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="worker_gate"): check spawn slot availability \u2014 alive/stale/reserved counts vs max. Use before dispatching. config(action="auto_wake_status"): orphaned tasks, blocked tasks, auto-wake retry status. config(action="orchestration_phase"): view/change org phase (phase_1_coo|phase_2_executives|phase_3_parallel_org). config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. diagnostics(action="pending_work_summary"): pending reviews + messages + notifications in one call. diagnostics(action="rename_employee"): rename an agent across all systems (roster, identity, DB, symlinks). diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role. mcp_ping(): daemon health + license status + tool usage stats.'
6734
6785
  }
6735
6786
  ];
6736
6787
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -2550,6 +2550,20 @@ async function ensureSchema() {
2550
2550
  });
2551
2551
  } catch {
2552
2552
  }
2553
+ try {
2554
+ await client.execute({
2555
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2556
+ args: []
2557
+ });
2558
+ } catch {
2559
+ }
2560
+ try {
2561
+ await client.execute({
2562
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2563
+ args: []
2564
+ });
2565
+ } catch {
2566
+ }
2553
2567
  await client.executeMultiple(`
2554
2568
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2555
2569
  content_text,
@@ -2801,6 +2815,22 @@ async function ensureSchema() {
2801
2815
  );
2802
2816
  } catch {
2803
2817
  }
2818
+ for (const col of [
2819
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
2820
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
2821
+ ]) {
2822
+ try {
2823
+ await client.execute(col);
2824
+ } catch {
2825
+ }
2826
+ }
2827
+ try {
2828
+ await client.execute({
2829
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
2830
+ args: []
2831
+ });
2832
+ } catch {
2833
+ }
2804
2834
  try {
2805
2835
  await client.execute({
2806
2836
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -2843,6 +2873,13 @@ async function ensureSchema() {
2843
2873
  } catch {
2844
2874
  }
2845
2875
  }
2876
+ try {
2877
+ await client.execute({
2878
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
2879
+ args: []
2880
+ });
2881
+ } catch {
2882
+ }
2846
2883
  try {
2847
2884
  await client.execute({
2848
2885
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -3424,6 +3461,20 @@ var init_platform_procedures = __esm({
3424
3461
  priority: "p1",
3425
3462
  content: "Once per session (COO boot only, never repeat), call list_my_feature_requests to check if any previously filed feature requests have been shipped by AskExe. If any request has status 'shipped' with a shipped_version, surface it to the founder immediately: '\u{1F680} N feature(s) shipped \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no requests exist or none are shipped, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
3426
3463
  },
3464
+ // --- Tool guidance ---
3465
+ {
3466
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
3467
+ domain: "tools",
3468
+ priority: "p2",
3469
+ content: "The company_actions tool executes business actions through gateway connectors (e.g. send WhatsApp, trigger workflows, update CRM). It routes through the exe-gateway on the VPS. Actions are defined by the customer's gateway configuration \u2014 each connector (WhatsApp, Shopify, email, etc.) exposes specific actions. Use query_company_brain to find available data first, then company_actions to act on it. Requires gateway auth token. Read-only founders should NOT use this \u2014 it mutates external state."
3470
+ },
3471
+ // --- Release awareness ---
3472
+ {
3473
+ title: "What's New check \u2014 surface new features after update",
3474
+ domain: "support",
3475
+ priority: "p1",
3476
+ content: "Once per session (COO boot only, never repeat), check if the installed exe-os version is newer than the last session. If it is, read the bundled release-notes.json (at the package root) and surface a brief summary to the founder: 'Updated to exe-os vX.Y.Z \u2014 N new features, M fixes.' List the top 3 features by name. This helps the founder know what they got from the update. If release-notes.json doesn't exist or the version hasn't changed, skip silently. Never repeat this check in the same session."
3477
+ },
3427
3478
  // --- Platform vs Customer ownership ---
3428
3479
  {
3429
3480
  title: "What the platform provides vs what you customize",
@@ -3512,13 +3563,13 @@ var init_platform_procedures = __esm({
3512
3563
  title: "MCP tools \u2014 memory, decision, and search",
3513
3564
  domain: "tool-use",
3514
3565
  priority: "p1",
3515
- content: `memory(action="recall") / recall_my_memory: search your own memories (semantic + FTS). memory(action="ask_team") / ask_team_memory: search a colleague's memories by agent name. memory(action="store") / store_memory: persist a memory. memory(action="commit") / commit_memory: high-importance memory that survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal memory window. Requires session_id + target_timestamp. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. decision(action="store") / store_decision: record an architectural decision (domain, decision, rationale). decision(action="get") / get_decision: retrieve a past decision by domain or query.`
3566
+ content: `memory(action="recall") / recall_my_memory: search memories (semantic + FTS). Params: as_of (bi-temporal \u2014 what did I know at time X?), kind (decision|procedure|observation|raw|conversation|behavior), retrieval_mode (all|decisions_only|procedures_only|operational|recent_high_value). memory(action="ask_team") / ask_team_memory: search a colleague's memories. memory(action="store") / store_memory: persist a memory. Params: kind, procedure_for (domain tag for procedures). memory(action="commit") / commit_memory: high-importance, survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal window. Requires session_id + target_timestamp. memory(action="get_by_id"): fetch one memory by UUID with full untruncated text. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. memory(action="supersede"): replace an old memory with a new version (old_id + new text). decision(action="store") / store_decision: record an architectural decision (domain, decision, rationale). decision(action="get") / get_decision: retrieve a past decision by domain or query.`
3516
3567
  },
3517
3568
  {
3518
3569
  title: "MCP tools \u2014 task orchestration",
3519
3570
  domain: "tool-use",
3520
3571
  priority: "p1",
3521
- content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
3572
+ content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. Params: blocked_by (task ID for dependency), parent_task_id (subtask hierarchy), reviewer, complexity (routine|standard|complex|critical), budget_tokens (max token cap), budget_fallback_model, spawn_runtime (override runtime: claude|codex|opencode), spawn_model (override model). task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
3522
3573
  },
3523
3574
  {
3524
3575
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -3548,7 +3599,7 @@ var init_platform_procedures = __esm({
3548
3599
  title: "MCP tools \u2014 admin, config, and operations",
3549
3600
  domain: "tool-use",
3550
3601
  priority: "p1",
3551
- content: 'config(action="list_employees"): view roster. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. mcp_ping(): daemon health + license status + tool usage stats.'
3602
+ content: 'config(action="list_employees"): view roster. config(action="set_agent_config"): view or change per-agent runtime + model. Call with no args to show all agents. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. Supports cloud_action param: status|sync|reupload. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="worker_gate"): check spawn slot availability \u2014 alive/stale/reserved counts vs max. Use before dispatching. config(action="auto_wake_status"): orphaned tasks, blocked tasks, auto-wake retry status. config(action="orchestration_phase"): view/change org phase (phase_1_coo|phase_2_executives|phase_3_parallel_org). config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. diagnostics(action="pending_work_summary"): pending reviews + messages + notifications in one call. diagnostics(action="rename_employee"): rename an agent across all systems (roster, identity, DB, symlinks). diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role. mcp_ping(): daemon health + license status + tool usage stats.'
3552
3603
  }
3553
3604
  ];
3554
3605
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -4606,6 +4657,8 @@ async function flushBatch() {
4606
4657
  const sourceType = row.source_type ?? null;
4607
4658
  const tier = row.tier ?? 3;
4608
4659
  const supersedesId = row.supersedes_id ?? null;
4660
+ const validFrom = row.valid_from ?? row.timestamp;
4661
+ const invalidAt = row.invalid_at ?? null;
4609
4662
  const draft = row.draft ? 1 : 0;
4610
4663
  const memoryType = row.memory_type ?? "raw";
4611
4664
  const trajectory = row.trajectory ?? null;
@@ -4625,15 +4678,16 @@ async function flushBatch() {
4625
4678
  const audience = row.audience ?? null;
4626
4679
  const languageType = row.language_type ?? null;
4627
4680
  const parentMemoryId = row.parent_memory_id ?? null;
4681
+ const procedureFor = row.procedure_for ?? null;
4628
4682
  const cols = `id, agent_id, agent_role, session_id, timestamp,
4629
4683
  tool_name, project_name,
4630
4684
  has_error, raw_text, vector, version, task_id, importance, status,
4631
4685
  confidence, last_accessed,
4632
4686
  workspace_id, document_id, user_id, char_offset, page_number,
4633
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
4687
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
4634
4688
  intent, outcome, domain, referenced_entities, retrieval_count,
4635
4689
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
4636
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
4690
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
4637
4691
  const metaArgs = [
4638
4692
  intent,
4639
4693
  outcome,
@@ -4649,7 +4703,8 @@ async function flushBatch() {
4649
4703
  tokenCost,
4650
4704
  audience,
4651
4705
  languageType,
4652
- parentMemoryId
4706
+ parentMemoryId,
4707
+ procedureFor
4653
4708
  ];
4654
4709
  const baseArgs = [
4655
4710
  row.id,
@@ -4678,6 +4733,8 @@ async function flushBatch() {
4678
4733
  sourceType,
4679
4734
  tier,
4680
4735
  supersedesId,
4736
+ validFrom,
4737
+ invalidAt,
4681
4738
  draft,
4682
4739
  memoryType,
4683
4740
  trajectory,
@@ -4685,8 +4742,8 @@ async function flushBatch() {
4685
4742
  ];
4686
4743
  return {
4687
4744
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
4688
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
4689
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
4745
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
4746
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
4690
4747
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
4691
4748
  };
4692
4749
  };