@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
@@ -3808,6 +3808,20 @@ async function ensureSchema() {
3808
3808
  });
3809
3809
  } catch {
3810
3810
  }
3811
+ try {
3812
+ await client.execute({
3813
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
3814
+ args: []
3815
+ });
3816
+ } catch {
3817
+ }
3818
+ try {
3819
+ await client.execute({
3820
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
3821
+ args: []
3822
+ });
3823
+ } catch {
3824
+ }
3811
3825
  await client.executeMultiple(`
3812
3826
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
3813
3827
  content_text,
@@ -4059,6 +4073,22 @@ async function ensureSchema() {
4059
4073
  );
4060
4074
  } catch {
4061
4075
  }
4076
+ for (const col of [
4077
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
4078
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
4079
+ ]) {
4080
+ try {
4081
+ await client.execute(col);
4082
+ } catch {
4083
+ }
4084
+ }
4085
+ try {
4086
+ await client.execute({
4087
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
4088
+ args: []
4089
+ });
4090
+ } catch {
4091
+ }
4062
4092
  try {
4063
4093
  await client.execute({
4064
4094
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -4101,6 +4131,13 @@ async function ensureSchema() {
4101
4131
  } catch {
4102
4132
  }
4103
4133
  }
4134
+ try {
4135
+ await client.execute({
4136
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
4137
+ args: []
4138
+ });
4139
+ } catch {
4140
+ }
4104
4141
  try {
4105
4142
  await client.execute({
4106
4143
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -4516,6 +4553,20 @@ var init_platform_procedures = __esm({
4516
4553
  priority: "p1",
4517
4554
  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."
4518
4555
  },
4556
+ // --- Tool guidance ---
4557
+ {
4558
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
4559
+ domain: "tools",
4560
+ priority: "p2",
4561
+ 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."
4562
+ },
4563
+ // --- Release awareness ---
4564
+ {
4565
+ title: "What's New check \u2014 surface new features after update",
4566
+ domain: "support",
4567
+ priority: "p1",
4568
+ 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."
4569
+ },
4519
4570
  // --- Platform vs Customer ownership ---
4520
4571
  {
4521
4572
  title: "What the platform provides vs what you customize",
@@ -4604,13 +4655,13 @@ var init_platform_procedures = __esm({
4604
4655
  title: "MCP tools \u2014 memory, decision, and search",
4605
4656
  domain: "tool-use",
4606
4657
  priority: "p1",
4607
- 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.`
4658
+ 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.`
4608
4659
  },
4609
4660
  {
4610
4661
  title: "MCP tools \u2014 task orchestration",
4611
4662
  domain: "tool-use",
4612
4663
  priority: "p1",
4613
- 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.'
4664
+ 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.'
4614
4665
  },
4615
4666
  {
4616
4667
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -4640,7 +4691,7 @@ var init_platform_procedures = __esm({
4640
4691
  title: "MCP tools \u2014 admin, config, and operations",
4641
4692
  domain: "tool-use",
4642
4693
  priority: "p1",
4643
- 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.'
4694
+ 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.'
4644
4695
  }
4645
4696
  ];
4646
4697
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5324,6 +5375,8 @@ async function writeMemory(record) {
5324
5375
  source_type: record.source_type ?? null,
5325
5376
  tier: record.tier ?? classifyTier(record),
5326
5377
  supersedes_id: record.supersedes_id ?? null,
5378
+ valid_from: record.valid_from ?? record.timestamp,
5379
+ invalid_at: record.invalid_at ?? null,
5327
5380
  draft: record.draft ? 1 : 0,
5328
5381
  memory_type: memoryType,
5329
5382
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -5342,7 +5395,8 @@ async function writeMemory(record) {
5342
5395
  token_cost: record.token_cost ?? null,
5343
5396
  audience: record.audience ?? null,
5344
5397
  language_type: record.language_type ?? inferLanguageType(record),
5345
- parent_memory_id: record.parent_memory_id ?? null
5398
+ parent_memory_id: record.parent_memory_id ?? null,
5399
+ procedure_for: record.procedure_for ?? null
5346
5400
  };
5347
5401
  _pendingRecords.push(dbRow);
5348
5402
  orgBus.emit({
@@ -5397,6 +5451,8 @@ async function flushBatch() {
5397
5451
  const sourceType = row.source_type ?? null;
5398
5452
  const tier = row.tier ?? 3;
5399
5453
  const supersedesId = row.supersedes_id ?? null;
5454
+ const validFrom = row.valid_from ?? row.timestamp;
5455
+ const invalidAt = row.invalid_at ?? null;
5400
5456
  const draft = row.draft ? 1 : 0;
5401
5457
  const memoryType = row.memory_type ?? "raw";
5402
5458
  const trajectory = row.trajectory ?? null;
@@ -5416,15 +5472,16 @@ async function flushBatch() {
5416
5472
  const audience = row.audience ?? null;
5417
5473
  const languageType = row.language_type ?? null;
5418
5474
  const parentMemoryId = row.parent_memory_id ?? null;
5475
+ const procedureFor = row.procedure_for ?? null;
5419
5476
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5420
5477
  tool_name, project_name,
5421
5478
  has_error, raw_text, vector, version, task_id, importance, status,
5422
5479
  confidence, last_accessed,
5423
5480
  workspace_id, document_id, user_id, char_offset, page_number,
5424
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5481
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5425
5482
  intent, outcome, domain, referenced_entities, retrieval_count,
5426
5483
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5427
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5484
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5428
5485
  const metaArgs = [
5429
5486
  intent,
5430
5487
  outcome,
@@ -5440,7 +5497,8 @@ async function flushBatch() {
5440
5497
  tokenCost,
5441
5498
  audience,
5442
5499
  languageType,
5443
- parentMemoryId
5500
+ parentMemoryId,
5501
+ procedureFor
5444
5502
  ];
5445
5503
  const baseArgs = [
5446
5504
  row.id,
@@ -5469,6 +5527,8 @@ async function flushBatch() {
5469
5527
  sourceType,
5470
5528
  tier,
5471
5529
  supersedesId,
5530
+ validFrom,
5531
+ invalidAt,
5472
5532
  draft,
5473
5533
  memoryType,
5474
5534
  trajectory,
@@ -5476,8 +5536,8 @@ async function flushBatch() {
5476
5536
  ];
5477
5537
  return {
5478
5538
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5479
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5480
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5539
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5540
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5481
5541
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5482
5542
  };
5483
5543
  };
@@ -5593,6 +5653,12 @@ async function searchMemories(queryVector, agentId, options) {
5593
5653
  AND vector IS NOT NULL${statusFilter}${draftFilter}
5594
5654
  AND COALESCE(confidence, 0.7) >= 0.3`;
5595
5655
  const args = [agentId];
5656
+ if (options?.asOf) {
5657
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
5658
+ args.push(options.asOf, options.asOf);
5659
+ } else {
5660
+ sql += ` AND invalid_at IS NULL`;
5661
+ }
5596
5662
  const scope = buildWikiScopeFilter(options, "");
5597
5663
  sql += scope.clause;
5598
5664
  args.push(...scope.args);
@@ -2841,6 +2841,20 @@ async function ensureSchema() {
2841
2841
  });
2842
2842
  } catch {
2843
2843
  }
2844
+ try {
2845
+ await client.execute({
2846
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2847
+ args: []
2848
+ });
2849
+ } catch {
2850
+ }
2851
+ try {
2852
+ await client.execute({
2853
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2854
+ args: []
2855
+ });
2856
+ } catch {
2857
+ }
2844
2858
  await client.executeMultiple(`
2845
2859
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2846
2860
  content_text,
@@ -3092,6 +3106,22 @@ async function ensureSchema() {
3092
3106
  );
3093
3107
  } catch {
3094
3108
  }
3109
+ for (const col of [
3110
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
3111
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
3112
+ ]) {
3113
+ try {
3114
+ await client.execute(col);
3115
+ } catch {
3116
+ }
3117
+ }
3118
+ try {
3119
+ await client.execute({
3120
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3121
+ args: []
3122
+ });
3123
+ } catch {
3124
+ }
3095
3125
  try {
3096
3126
  await client.execute({
3097
3127
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -3134,6 +3164,13 @@ async function ensureSchema() {
3134
3164
  } catch {
3135
3165
  }
3136
3166
  }
3167
+ try {
3168
+ await client.execute({
3169
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3170
+ args: []
3171
+ });
3172
+ } catch {
3173
+ }
3137
3174
  try {
3138
3175
  await client.execute({
3139
3176
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -4272,6 +4309,20 @@ var init_platform_procedures = __esm({
4272
4309
  priority: "p1",
4273
4310
  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."
4274
4311
  },
4312
+ // --- Tool guidance ---
4313
+ {
4314
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
4315
+ domain: "tools",
4316
+ priority: "p2",
4317
+ 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."
4318
+ },
4319
+ // --- Release awareness ---
4320
+ {
4321
+ title: "What's New check \u2014 surface new features after update",
4322
+ domain: "support",
4323
+ priority: "p1",
4324
+ 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."
4325
+ },
4275
4326
  // --- Platform vs Customer ownership ---
4276
4327
  {
4277
4328
  title: "What the platform provides vs what you customize",
@@ -4360,13 +4411,13 @@ var init_platform_procedures = __esm({
4360
4411
  title: "MCP tools \u2014 memory, decision, and search",
4361
4412
  domain: "tool-use",
4362
4413
  priority: "p1",
4363
- 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.`
4414
+ 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.`
4364
4415
  },
4365
4416
  {
4366
4417
  title: "MCP tools \u2014 task orchestration",
4367
4418
  domain: "tool-use",
4368
4419
  priority: "p1",
4369
- 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.'
4420
+ 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.'
4370
4421
  },
4371
4422
  {
4372
4423
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -4396,7 +4447,7 @@ var init_platform_procedures = __esm({
4396
4447
  title: "MCP tools \u2014 admin, config, and operations",
4397
4448
  domain: "tool-use",
4398
4449
  priority: "p1",
4399
- 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.'
4450
+ 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.'
4400
4451
  }
4401
4452
  ];
4402
4453
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5080,6 +5131,8 @@ async function writeMemory(record) {
5080
5131
  source_type: record.source_type ?? null,
5081
5132
  tier: record.tier ?? classifyTier(record),
5082
5133
  supersedes_id: record.supersedes_id ?? null,
5134
+ valid_from: record.valid_from ?? record.timestamp,
5135
+ invalid_at: record.invalid_at ?? null,
5083
5136
  draft: record.draft ? 1 : 0,
5084
5137
  memory_type: memoryType,
5085
5138
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -5098,7 +5151,8 @@ async function writeMemory(record) {
5098
5151
  token_cost: record.token_cost ?? null,
5099
5152
  audience: record.audience ?? null,
5100
5153
  language_type: record.language_type ?? inferLanguageType(record),
5101
- parent_memory_id: record.parent_memory_id ?? null
5154
+ parent_memory_id: record.parent_memory_id ?? null,
5155
+ procedure_for: record.procedure_for ?? null
5102
5156
  };
5103
5157
  _pendingRecords.push(dbRow);
5104
5158
  orgBus.emit({
@@ -5153,6 +5207,8 @@ async function flushBatch() {
5153
5207
  const sourceType = row.source_type ?? null;
5154
5208
  const tier = row.tier ?? 3;
5155
5209
  const supersedesId = row.supersedes_id ?? null;
5210
+ const validFrom = row.valid_from ?? row.timestamp;
5211
+ const invalidAt = row.invalid_at ?? null;
5156
5212
  const draft = row.draft ? 1 : 0;
5157
5213
  const memoryType = row.memory_type ?? "raw";
5158
5214
  const trajectory = row.trajectory ?? null;
@@ -5172,15 +5228,16 @@ async function flushBatch() {
5172
5228
  const audience = row.audience ?? null;
5173
5229
  const languageType = row.language_type ?? null;
5174
5230
  const parentMemoryId = row.parent_memory_id ?? null;
5231
+ const procedureFor = row.procedure_for ?? null;
5175
5232
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5176
5233
  tool_name, project_name,
5177
5234
  has_error, raw_text, vector, version, task_id, importance, status,
5178
5235
  confidence, last_accessed,
5179
5236
  workspace_id, document_id, user_id, char_offset, page_number,
5180
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5237
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5181
5238
  intent, outcome, domain, referenced_entities, retrieval_count,
5182
5239
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5183
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5240
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5184
5241
  const metaArgs = [
5185
5242
  intent,
5186
5243
  outcome,
@@ -5196,7 +5253,8 @@ async function flushBatch() {
5196
5253
  tokenCost,
5197
5254
  audience,
5198
5255
  languageType,
5199
- parentMemoryId
5256
+ parentMemoryId,
5257
+ procedureFor
5200
5258
  ];
5201
5259
  const baseArgs = [
5202
5260
  row.id,
@@ -5225,6 +5283,8 @@ async function flushBatch() {
5225
5283
  sourceType,
5226
5284
  tier,
5227
5285
  supersedesId,
5286
+ validFrom,
5287
+ invalidAt,
5228
5288
  draft,
5229
5289
  memoryType,
5230
5290
  trajectory,
@@ -5232,8 +5292,8 @@ async function flushBatch() {
5232
5292
  ];
5233
5293
  return {
5234
5294
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5235
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5236
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5295
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5296
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5237
5297
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5238
5298
  };
5239
5299
  };
@@ -5349,6 +5409,12 @@ async function searchMemories(queryVector, agentId2, options) {
5349
5409
  AND vector IS NOT NULL${statusFilter}${draftFilter}
5350
5410
  AND COALESCE(confidence, 0.7) >= 0.3`;
5351
5411
  const args = [agentId2];
5412
+ if (options?.asOf) {
5413
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
5414
+ args.push(options.asOf, options.asOf);
5415
+ } else {
5416
+ sql += ` AND invalid_at IS NULL`;
5417
+ }
5352
5418
  const scope = buildWikiScopeFilter(options, "");
5353
5419
  sql += scope.clause;
5354
5420
  args.push(...scope.args);
@@ -2765,6 +2765,20 @@ async function ensureSchema() {
2765
2765
  });
2766
2766
  } catch {
2767
2767
  }
2768
+ try {
2769
+ await client.execute({
2770
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2771
+ args: []
2772
+ });
2773
+ } catch {
2774
+ }
2775
+ try {
2776
+ await client.execute({
2777
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2778
+ args: []
2779
+ });
2780
+ } catch {
2781
+ }
2768
2782
  await client.executeMultiple(`
2769
2783
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2770
2784
  content_text,
@@ -3016,6 +3030,22 @@ async function ensureSchema() {
3016
3030
  );
3017
3031
  } catch {
3018
3032
  }
3033
+ for (const col of [
3034
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
3035
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
3036
+ ]) {
3037
+ try {
3038
+ await client.execute(col);
3039
+ } catch {
3040
+ }
3041
+ }
3042
+ try {
3043
+ await client.execute({
3044
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3045
+ args: []
3046
+ });
3047
+ } catch {
3048
+ }
3019
3049
  try {
3020
3050
  await client.execute({
3021
3051
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -3058,6 +3088,13 @@ async function ensureSchema() {
3058
3088
  } catch {
3059
3089
  }
3060
3090
  }
3091
+ try {
3092
+ await client.execute({
3093
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3094
+ args: []
3095
+ });
3096
+ } catch {
3097
+ }
3061
3098
  try {
3062
3099
  await client.execute({
3063
3100
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -4196,6 +4233,20 @@ var init_platform_procedures = __esm({
4196
4233
  priority: "p1",
4197
4234
  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."
4198
4235
  },
4236
+ // --- Tool guidance ---
4237
+ {
4238
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
4239
+ domain: "tools",
4240
+ priority: "p2",
4241
+ 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."
4242
+ },
4243
+ // --- Release awareness ---
4244
+ {
4245
+ title: "What's New check \u2014 surface new features after update",
4246
+ domain: "support",
4247
+ priority: "p1",
4248
+ 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."
4249
+ },
4199
4250
  // --- Platform vs Customer ownership ---
4200
4251
  {
4201
4252
  title: "What the platform provides vs what you customize",
@@ -4284,13 +4335,13 @@ var init_platform_procedures = __esm({
4284
4335
  title: "MCP tools \u2014 memory, decision, and search",
4285
4336
  domain: "tool-use",
4286
4337
  priority: "p1",
4287
- 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.`
4338
+ 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.`
4288
4339
  },
4289
4340
  {
4290
4341
  title: "MCP tools \u2014 task orchestration",
4291
4342
  domain: "tool-use",
4292
4343
  priority: "p1",
4293
- 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.'
4344
+ 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.'
4294
4345
  },
4295
4346
  {
4296
4347
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -4320,7 +4371,7 @@ var init_platform_procedures = __esm({
4320
4371
  title: "MCP tools \u2014 admin, config, and operations",
4321
4372
  domain: "tool-use",
4322
4373
  priority: "p1",
4323
- 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.'
4374
+ 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.'
4324
4375
  }
4325
4376
  ];
4326
4377
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5004,6 +5055,8 @@ async function writeMemory(record) {
5004
5055
  source_type: record.source_type ?? null,
5005
5056
  tier: record.tier ?? classifyTier(record),
5006
5057
  supersedes_id: record.supersedes_id ?? null,
5058
+ valid_from: record.valid_from ?? record.timestamp,
5059
+ invalid_at: record.invalid_at ?? null,
5007
5060
  draft: record.draft ? 1 : 0,
5008
5061
  memory_type: memoryType,
5009
5062
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -5022,7 +5075,8 @@ async function writeMemory(record) {
5022
5075
  token_cost: record.token_cost ?? null,
5023
5076
  audience: record.audience ?? null,
5024
5077
  language_type: record.language_type ?? inferLanguageType(record),
5025
- parent_memory_id: record.parent_memory_id ?? null
5078
+ parent_memory_id: record.parent_memory_id ?? null,
5079
+ procedure_for: record.procedure_for ?? null
5026
5080
  };
5027
5081
  _pendingRecords.push(dbRow);
5028
5082
  orgBus.emit({
@@ -5077,6 +5131,8 @@ async function flushBatch() {
5077
5131
  const sourceType = row.source_type ?? null;
5078
5132
  const tier = row.tier ?? 3;
5079
5133
  const supersedesId = row.supersedes_id ?? null;
5134
+ const validFrom = row.valid_from ?? row.timestamp;
5135
+ const invalidAt = row.invalid_at ?? null;
5080
5136
  const draft = row.draft ? 1 : 0;
5081
5137
  const memoryType = row.memory_type ?? "raw";
5082
5138
  const trajectory = row.trajectory ?? null;
@@ -5096,15 +5152,16 @@ async function flushBatch() {
5096
5152
  const audience = row.audience ?? null;
5097
5153
  const languageType = row.language_type ?? null;
5098
5154
  const parentMemoryId = row.parent_memory_id ?? null;
5155
+ const procedureFor = row.procedure_for ?? null;
5099
5156
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5100
5157
  tool_name, project_name,
5101
5158
  has_error, raw_text, vector, version, task_id, importance, status,
5102
5159
  confidence, last_accessed,
5103
5160
  workspace_id, document_id, user_id, char_offset, page_number,
5104
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5161
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5105
5162
  intent, outcome, domain, referenced_entities, retrieval_count,
5106
5163
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5107
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5164
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5108
5165
  const metaArgs = [
5109
5166
  intent,
5110
5167
  outcome,
@@ -5120,7 +5177,8 @@ async function flushBatch() {
5120
5177
  tokenCost,
5121
5178
  audience,
5122
5179
  languageType,
5123
- parentMemoryId
5180
+ parentMemoryId,
5181
+ procedureFor
5124
5182
  ];
5125
5183
  const baseArgs = [
5126
5184
  row.id,
@@ -5149,6 +5207,8 @@ async function flushBatch() {
5149
5207
  sourceType,
5150
5208
  tier,
5151
5209
  supersedesId,
5210
+ validFrom,
5211
+ invalidAt,
5152
5212
  draft,
5153
5213
  memoryType,
5154
5214
  trajectory,
@@ -5156,8 +5216,8 @@ async function flushBatch() {
5156
5216
  ];
5157
5217
  return {
5158
5218
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5159
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5160
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5219
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5220
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5161
5221
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5162
5222
  };
5163
5223
  };
@@ -5273,6 +5333,12 @@ async function searchMemories(queryVector, agentId, options) {
5273
5333
  AND vector IS NOT NULL${statusFilter}${draftFilter}
5274
5334
  AND COALESCE(confidence, 0.7) >= 0.3`;
5275
5335
  const args = [agentId];
5336
+ if (options?.asOf) {
5337
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
5338
+ args.push(options.asOf, options.asOf);
5339
+ } else {
5340
+ sql += ` AND invalid_at IS NULL`;
5341
+ }
5276
5342
  const scope = buildWikiScopeFilter(options, "");
5277
5343
  sql += scope.clause;
5278
5344
  args.push(...scope.args);
@@ -5522,6 +5588,19 @@ init_database();
5522
5588
  init_store();
5523
5589
  init_database();
5524
5590
  var RRF_K = 60;
5591
+ function buildTemporalFilter(options, columnPrefix) {
5592
+ const asOf = options?.asOf;
5593
+ if (asOf) {
5594
+ return {
5595
+ clause: ` AND (${columnPrefix}valid_from IS NULL OR ${columnPrefix}valid_from <= ?) AND (${columnPrefix}invalid_at IS NULL OR ${columnPrefix}invalid_at > ?)`,
5596
+ args: [asOf, asOf]
5597
+ };
5598
+ }
5599
+ return {
5600
+ clause: ` AND ${columnPrefix}invalid_at IS NULL`,
5601
+ args: []
5602
+ };
5603
+ }
5525
5604
  function appendMemoryTypeFilter(sql, args, column, options) {
5526
5605
  if (options?.memoryTypes && options.memoryTypes.length > 0) {
5527
5606
  const uniqueTypes = [...new Set(options.memoryTypes)];
@@ -5631,6 +5710,9 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
5631
5710
  AND m.agent_id = ?${statusFilter}${draftFilter}
5632
5711
  AND COALESCE(m.confidence, 0.7) >= 0.3`;
5633
5712
  const args = [matchExpr, agentId];
5713
+ const temporal = buildTemporalFilter(options, "m.");
5714
+ sql += temporal.clause;
5715
+ args.push(...temporal.args);
5634
5716
  const scope = buildWikiScopeFilter(options, "m.");
5635
5717
  sql += scope.clause;
5636
5718
  args.push(...scope.args);
@@ -5743,6 +5825,9 @@ async function recentRecords(agentId, options, limit, textFilter) {
5743
5825
  WHERE agent_id = ?${statusFilter}${draftFilter}
5744
5826
  AND COALESCE(confidence, 0.7) >= 0.3`;
5745
5827
  const args = [agentId];
5828
+ const temporal = buildTemporalFilter(options, "");
5829
+ sql += temporal.clause;
5830
+ args.push(...temporal.args);
5746
5831
  const scope = buildWikiScopeFilter(options, "");
5747
5832
  sql += scope.clause;
5748
5833
  args.push(...scope.args);