@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
@@ -2942,6 +2942,20 @@ async function ensureSchema() {
2942
2942
  });
2943
2943
  } catch {
2944
2944
  }
2945
+ try {
2946
+ await client.execute({
2947
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2948
+ args: []
2949
+ });
2950
+ } catch {
2951
+ }
2952
+ try {
2953
+ await client.execute({
2954
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2955
+ args: []
2956
+ });
2957
+ } catch {
2958
+ }
2945
2959
  await client.executeMultiple(`
2946
2960
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2947
2961
  content_text,
@@ -3193,6 +3207,22 @@ async function ensureSchema() {
3193
3207
  );
3194
3208
  } catch {
3195
3209
  }
3210
+ for (const col of [
3211
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
3212
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
3213
+ ]) {
3214
+ try {
3215
+ await client.execute(col);
3216
+ } catch {
3217
+ }
3218
+ }
3219
+ try {
3220
+ await client.execute({
3221
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3222
+ args: []
3223
+ });
3224
+ } catch {
3225
+ }
3196
3226
  try {
3197
3227
  await client.execute({
3198
3228
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -3235,6 +3265,13 @@ async function ensureSchema() {
3235
3265
  } catch {
3236
3266
  }
3237
3267
  }
3268
+ try {
3269
+ await client.execute({
3270
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3271
+ args: []
3272
+ });
3273
+ } catch {
3274
+ }
3238
3275
  try {
3239
3276
  await client.execute({
3240
3277
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -4373,6 +4410,20 @@ var init_platform_procedures = __esm({
4373
4410
  priority: "p1",
4374
4411
  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."
4375
4412
  },
4413
+ // --- Tool guidance ---
4414
+ {
4415
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
4416
+ domain: "tools",
4417
+ priority: "p2",
4418
+ 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."
4419
+ },
4420
+ // --- Release awareness ---
4421
+ {
4422
+ title: "What's New check \u2014 surface new features after update",
4423
+ domain: "support",
4424
+ priority: "p1",
4425
+ 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."
4426
+ },
4376
4427
  // --- Platform vs Customer ownership ---
4377
4428
  {
4378
4429
  title: "What the platform provides vs what you customize",
@@ -4461,13 +4512,13 @@ var init_platform_procedures = __esm({
4461
4512
  title: "MCP tools \u2014 memory, decision, and search",
4462
4513
  domain: "tool-use",
4463
4514
  priority: "p1",
4464
- 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.`
4515
+ 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.`
4465
4516
  },
4466
4517
  {
4467
4518
  title: "MCP tools \u2014 task orchestration",
4468
4519
  domain: "tool-use",
4469
4520
  priority: "p1",
4470
- 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.'
4521
+ 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.'
4471
4522
  },
4472
4523
  {
4473
4524
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -4497,7 +4548,7 @@ var init_platform_procedures = __esm({
4497
4548
  title: "MCP tools \u2014 admin, config, and operations",
4498
4549
  domain: "tool-use",
4499
4550
  priority: "p1",
4500
- 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.'
4551
+ 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.'
4501
4552
  }
4502
4553
  ];
4503
4554
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5181,6 +5232,8 @@ async function writeMemory(record) {
5181
5232
  source_type: record.source_type ?? null,
5182
5233
  tier: record.tier ?? classifyTier(record),
5183
5234
  supersedes_id: record.supersedes_id ?? null,
5235
+ valid_from: record.valid_from ?? record.timestamp,
5236
+ invalid_at: record.invalid_at ?? null,
5184
5237
  draft: record.draft ? 1 : 0,
5185
5238
  memory_type: memoryType,
5186
5239
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -5199,7 +5252,8 @@ async function writeMemory(record) {
5199
5252
  token_cost: record.token_cost ?? null,
5200
5253
  audience: record.audience ?? null,
5201
5254
  language_type: record.language_type ?? inferLanguageType(record),
5202
- parent_memory_id: record.parent_memory_id ?? null
5255
+ parent_memory_id: record.parent_memory_id ?? null,
5256
+ procedure_for: record.procedure_for ?? null
5203
5257
  };
5204
5258
  _pendingRecords.push(dbRow);
5205
5259
  orgBus.emit({
@@ -5254,6 +5308,8 @@ async function flushBatch() {
5254
5308
  const sourceType = row.source_type ?? null;
5255
5309
  const tier = row.tier ?? 3;
5256
5310
  const supersedesId = row.supersedes_id ?? null;
5311
+ const validFrom = row.valid_from ?? row.timestamp;
5312
+ const invalidAt = row.invalid_at ?? null;
5257
5313
  const draft = row.draft ? 1 : 0;
5258
5314
  const memoryType = row.memory_type ?? "raw";
5259
5315
  const trajectory = row.trajectory ?? null;
@@ -5273,15 +5329,16 @@ async function flushBatch() {
5273
5329
  const audience = row.audience ?? null;
5274
5330
  const languageType = row.language_type ?? null;
5275
5331
  const parentMemoryId = row.parent_memory_id ?? null;
5332
+ const procedureFor = row.procedure_for ?? null;
5276
5333
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5277
5334
  tool_name, project_name,
5278
5335
  has_error, raw_text, vector, version, task_id, importance, status,
5279
5336
  confidence, last_accessed,
5280
5337
  workspace_id, document_id, user_id, char_offset, page_number,
5281
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5338
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5282
5339
  intent, outcome, domain, referenced_entities, retrieval_count,
5283
5340
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5284
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5341
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5285
5342
  const metaArgs = [
5286
5343
  intent,
5287
5344
  outcome,
@@ -5297,7 +5354,8 @@ async function flushBatch() {
5297
5354
  tokenCost,
5298
5355
  audience,
5299
5356
  languageType,
5300
- parentMemoryId
5357
+ parentMemoryId,
5358
+ procedureFor
5301
5359
  ];
5302
5360
  const baseArgs = [
5303
5361
  row.id,
@@ -5326,6 +5384,8 @@ async function flushBatch() {
5326
5384
  sourceType,
5327
5385
  tier,
5328
5386
  supersedesId,
5387
+ validFrom,
5388
+ invalidAt,
5329
5389
  draft,
5330
5390
  memoryType,
5331
5391
  trajectory,
@@ -5333,8 +5393,8 @@ async function flushBatch() {
5333
5393
  ];
5334
5394
  return {
5335
5395
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5336
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5337
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5396
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5397
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5338
5398
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5339
5399
  };
5340
5400
  };
@@ -5450,6 +5510,12 @@ async function searchMemories(queryVector, agentId, options) {
5450
5510
  AND vector IS NOT NULL${statusFilter}${draftFilter}
5451
5511
  AND COALESCE(confidence, 0.7) >= 0.3`;
5452
5512
  const args = [agentId];
5513
+ if (options?.asOf) {
5514
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
5515
+ args.push(options.asOf, options.asOf);
5516
+ } else {
5517
+ sql += ` AND invalid_at IS NULL`;
5518
+ }
5453
5519
  const scope = buildWikiScopeFilter(options, "");
5454
5520
  sql += scope.clause;
5455
5521
  args.push(...scope.args);
@@ -2767,6 +2767,20 @@ async function ensureSchema() {
2767
2767
  });
2768
2768
  } catch {
2769
2769
  }
2770
+ try {
2771
+ await client.execute({
2772
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2773
+ args: []
2774
+ });
2775
+ } catch {
2776
+ }
2777
+ try {
2778
+ await client.execute({
2779
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2780
+ args: []
2781
+ });
2782
+ } catch {
2783
+ }
2770
2784
  await client.executeMultiple(`
2771
2785
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2772
2786
  content_text,
@@ -3018,6 +3032,22 @@ async function ensureSchema() {
3018
3032
  );
3019
3033
  } catch {
3020
3034
  }
3035
+ for (const col of [
3036
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
3037
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
3038
+ ]) {
3039
+ try {
3040
+ await client.execute(col);
3041
+ } catch {
3042
+ }
3043
+ }
3044
+ try {
3045
+ await client.execute({
3046
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3047
+ args: []
3048
+ });
3049
+ } catch {
3050
+ }
3021
3051
  try {
3022
3052
  await client.execute({
3023
3053
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -3060,6 +3090,13 @@ async function ensureSchema() {
3060
3090
  } catch {
3061
3091
  }
3062
3092
  }
3093
+ try {
3094
+ await client.execute({
3095
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3096
+ args: []
3097
+ });
3098
+ } catch {
3099
+ }
3063
3100
  try {
3064
3101
  await client.execute({
3065
3102
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -4198,6 +4235,20 @@ var init_platform_procedures = __esm({
4198
4235
  priority: "p1",
4199
4236
  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."
4200
4237
  },
4238
+ // --- Tool guidance ---
4239
+ {
4240
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
4241
+ domain: "tools",
4242
+ priority: "p2",
4243
+ 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."
4244
+ },
4245
+ // --- Release awareness ---
4246
+ {
4247
+ title: "What's New check \u2014 surface new features after update",
4248
+ domain: "support",
4249
+ priority: "p1",
4250
+ 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."
4251
+ },
4201
4252
  // --- Platform vs Customer ownership ---
4202
4253
  {
4203
4254
  title: "What the platform provides vs what you customize",
@@ -4286,13 +4337,13 @@ var init_platform_procedures = __esm({
4286
4337
  title: "MCP tools \u2014 memory, decision, and search",
4287
4338
  domain: "tool-use",
4288
4339
  priority: "p1",
4289
- 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.`
4340
+ 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.`
4290
4341
  },
4291
4342
  {
4292
4343
  title: "MCP tools \u2014 task orchestration",
4293
4344
  domain: "tool-use",
4294
4345
  priority: "p1",
4295
- 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.'
4346
+ 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.'
4296
4347
  },
4297
4348
  {
4298
4349
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -4322,7 +4373,7 @@ var init_platform_procedures = __esm({
4322
4373
  title: "MCP tools \u2014 admin, config, and operations",
4323
4374
  domain: "tool-use",
4324
4375
  priority: "p1",
4325
- 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.'
4376
+ 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.'
4326
4377
  }
4327
4378
  ];
4328
4379
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5006,6 +5057,8 @@ async function writeMemory(record) {
5006
5057
  source_type: record.source_type ?? null,
5007
5058
  tier: record.tier ?? classifyTier(record),
5008
5059
  supersedes_id: record.supersedes_id ?? null,
5060
+ valid_from: record.valid_from ?? record.timestamp,
5061
+ invalid_at: record.invalid_at ?? null,
5009
5062
  draft: record.draft ? 1 : 0,
5010
5063
  memory_type: memoryType,
5011
5064
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -5024,7 +5077,8 @@ async function writeMemory(record) {
5024
5077
  token_cost: record.token_cost ?? null,
5025
5078
  audience: record.audience ?? null,
5026
5079
  language_type: record.language_type ?? inferLanguageType(record),
5027
- parent_memory_id: record.parent_memory_id ?? null
5080
+ parent_memory_id: record.parent_memory_id ?? null,
5081
+ procedure_for: record.procedure_for ?? null
5028
5082
  };
5029
5083
  _pendingRecords.push(dbRow);
5030
5084
  orgBus.emit({
@@ -5079,6 +5133,8 @@ async function flushBatch() {
5079
5133
  const sourceType = row.source_type ?? null;
5080
5134
  const tier = row.tier ?? 3;
5081
5135
  const supersedesId = row.supersedes_id ?? null;
5136
+ const validFrom = row.valid_from ?? row.timestamp;
5137
+ const invalidAt = row.invalid_at ?? null;
5082
5138
  const draft = row.draft ? 1 : 0;
5083
5139
  const memoryType = row.memory_type ?? "raw";
5084
5140
  const trajectory = row.trajectory ?? null;
@@ -5098,15 +5154,16 @@ async function flushBatch() {
5098
5154
  const audience = row.audience ?? null;
5099
5155
  const languageType = row.language_type ?? null;
5100
5156
  const parentMemoryId = row.parent_memory_id ?? null;
5157
+ const procedureFor = row.procedure_for ?? null;
5101
5158
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5102
5159
  tool_name, project_name,
5103
5160
  has_error, raw_text, vector, version, task_id, importance, status,
5104
5161
  confidence, last_accessed,
5105
5162
  workspace_id, document_id, user_id, char_offset, page_number,
5106
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5163
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5107
5164
  intent, outcome, domain, referenced_entities, retrieval_count,
5108
5165
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5109
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5166
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5110
5167
  const metaArgs = [
5111
5168
  intent,
5112
5169
  outcome,
@@ -5122,7 +5179,8 @@ async function flushBatch() {
5122
5179
  tokenCost,
5123
5180
  audience,
5124
5181
  languageType,
5125
- parentMemoryId
5182
+ parentMemoryId,
5183
+ procedureFor
5126
5184
  ];
5127
5185
  const baseArgs = [
5128
5186
  row.id,
@@ -5151,6 +5209,8 @@ async function flushBatch() {
5151
5209
  sourceType,
5152
5210
  tier,
5153
5211
  supersedesId,
5212
+ validFrom,
5213
+ invalidAt,
5154
5214
  draft,
5155
5215
  memoryType,
5156
5216
  trajectory,
@@ -5158,8 +5218,8 @@ async function flushBatch() {
5158
5218
  ];
5159
5219
  return {
5160
5220
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5161
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5162
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5221
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5222
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5163
5223
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5164
5224
  };
5165
5225
  };
@@ -5275,6 +5335,12 @@ async function searchMemories(queryVector, agentId, options) {
5275
5335
  AND vector IS NOT NULL${statusFilter}${draftFilter}
5276
5336
  AND COALESCE(confidence, 0.7) >= 0.3`;
5277
5337
  const args = [agentId];
5338
+ if (options?.asOf) {
5339
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
5340
+ args.push(options.asOf, options.asOf);
5341
+ } else {
5342
+ sql += ` AND invalid_at IS NULL`;
5343
+ }
5278
5344
  const scope = buildWikiScopeFilter(options, "");
5279
5345
  sql += scope.clause;
5280
5346
  args.push(...scope.args);
@@ -2767,6 +2767,20 @@ async function ensureSchema() {
2767
2767
  });
2768
2768
  } catch {
2769
2769
  }
2770
+ try {
2771
+ await client.execute({
2772
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2773
+ args: []
2774
+ });
2775
+ } catch {
2776
+ }
2777
+ try {
2778
+ await client.execute({
2779
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2780
+ args: []
2781
+ });
2782
+ } catch {
2783
+ }
2770
2784
  await client.executeMultiple(`
2771
2785
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2772
2786
  content_text,
@@ -3018,6 +3032,22 @@ async function ensureSchema() {
3018
3032
  );
3019
3033
  } catch {
3020
3034
  }
3035
+ for (const col of [
3036
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
3037
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
3038
+ ]) {
3039
+ try {
3040
+ await client.execute(col);
3041
+ } catch {
3042
+ }
3043
+ }
3044
+ try {
3045
+ await client.execute({
3046
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3047
+ args: []
3048
+ });
3049
+ } catch {
3050
+ }
3021
3051
  try {
3022
3052
  await client.execute({
3023
3053
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -3060,6 +3090,13 @@ async function ensureSchema() {
3060
3090
  } catch {
3061
3091
  }
3062
3092
  }
3093
+ try {
3094
+ await client.execute({
3095
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3096
+ args: []
3097
+ });
3098
+ } catch {
3099
+ }
3063
3100
  try {
3064
3101
  await client.execute({
3065
3102
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -4198,6 +4235,20 @@ var init_platform_procedures = __esm({
4198
4235
  priority: "p1",
4199
4236
  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."
4200
4237
  },
4238
+ // --- Tool guidance ---
4239
+ {
4240
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
4241
+ domain: "tools",
4242
+ priority: "p2",
4243
+ 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."
4244
+ },
4245
+ // --- Release awareness ---
4246
+ {
4247
+ title: "What's New check \u2014 surface new features after update",
4248
+ domain: "support",
4249
+ priority: "p1",
4250
+ 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."
4251
+ },
4201
4252
  // --- Platform vs Customer ownership ---
4202
4253
  {
4203
4254
  title: "What the platform provides vs what you customize",
@@ -4286,13 +4337,13 @@ var init_platform_procedures = __esm({
4286
4337
  title: "MCP tools \u2014 memory, decision, and search",
4287
4338
  domain: "tool-use",
4288
4339
  priority: "p1",
4289
- 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.`
4340
+ 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.`
4290
4341
  },
4291
4342
  {
4292
4343
  title: "MCP tools \u2014 task orchestration",
4293
4344
  domain: "tool-use",
4294
4345
  priority: "p1",
4295
- 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.'
4346
+ 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.'
4296
4347
  },
4297
4348
  {
4298
4349
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -4322,7 +4373,7 @@ var init_platform_procedures = __esm({
4322
4373
  title: "MCP tools \u2014 admin, config, and operations",
4323
4374
  domain: "tool-use",
4324
4375
  priority: "p1",
4325
- 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.'
4376
+ 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.'
4326
4377
  }
4327
4378
  ];
4328
4379
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5006,6 +5057,8 @@ async function writeMemory(record) {
5006
5057
  source_type: record.source_type ?? null,
5007
5058
  tier: record.tier ?? classifyTier(record),
5008
5059
  supersedes_id: record.supersedes_id ?? null,
5060
+ valid_from: record.valid_from ?? record.timestamp,
5061
+ invalid_at: record.invalid_at ?? null,
5009
5062
  draft: record.draft ? 1 : 0,
5010
5063
  memory_type: memoryType,
5011
5064
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -5024,7 +5077,8 @@ async function writeMemory(record) {
5024
5077
  token_cost: record.token_cost ?? null,
5025
5078
  audience: record.audience ?? null,
5026
5079
  language_type: record.language_type ?? inferLanguageType(record),
5027
- parent_memory_id: record.parent_memory_id ?? null
5080
+ parent_memory_id: record.parent_memory_id ?? null,
5081
+ procedure_for: record.procedure_for ?? null
5028
5082
  };
5029
5083
  _pendingRecords.push(dbRow);
5030
5084
  orgBus.emit({
@@ -5079,6 +5133,8 @@ async function flushBatch() {
5079
5133
  const sourceType = row.source_type ?? null;
5080
5134
  const tier = row.tier ?? 3;
5081
5135
  const supersedesId = row.supersedes_id ?? null;
5136
+ const validFrom = row.valid_from ?? row.timestamp;
5137
+ const invalidAt = row.invalid_at ?? null;
5082
5138
  const draft = row.draft ? 1 : 0;
5083
5139
  const memoryType = row.memory_type ?? "raw";
5084
5140
  const trajectory = row.trajectory ?? null;
@@ -5098,15 +5154,16 @@ async function flushBatch() {
5098
5154
  const audience = row.audience ?? null;
5099
5155
  const languageType = row.language_type ?? null;
5100
5156
  const parentMemoryId = row.parent_memory_id ?? null;
5157
+ const procedureFor = row.procedure_for ?? null;
5101
5158
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5102
5159
  tool_name, project_name,
5103
5160
  has_error, raw_text, vector, version, task_id, importance, status,
5104
5161
  confidence, last_accessed,
5105
5162
  workspace_id, document_id, user_id, char_offset, page_number,
5106
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5163
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5107
5164
  intent, outcome, domain, referenced_entities, retrieval_count,
5108
5165
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5109
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5166
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5110
5167
  const metaArgs = [
5111
5168
  intent,
5112
5169
  outcome,
@@ -5122,7 +5179,8 @@ async function flushBatch() {
5122
5179
  tokenCost,
5123
5180
  audience,
5124
5181
  languageType,
5125
- parentMemoryId
5182
+ parentMemoryId,
5183
+ procedureFor
5126
5184
  ];
5127
5185
  const baseArgs = [
5128
5186
  row.id,
@@ -5151,6 +5209,8 @@ async function flushBatch() {
5151
5209
  sourceType,
5152
5210
  tier,
5153
5211
  supersedesId,
5212
+ validFrom,
5213
+ invalidAt,
5154
5214
  draft,
5155
5215
  memoryType,
5156
5216
  trajectory,
@@ -5158,8 +5218,8 @@ async function flushBatch() {
5158
5218
  ];
5159
5219
  return {
5160
5220
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5161
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5162
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5221
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5222
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5163
5223
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5164
5224
  };
5165
5225
  };
@@ -5275,6 +5335,12 @@ async function searchMemories(queryVector, agentId, options) {
5275
5335
  AND vector IS NOT NULL${statusFilter}${draftFilter}
5276
5336
  AND COALESCE(confidence, 0.7) >= 0.3`;
5277
5337
  const args = [agentId];
5338
+ if (options?.asOf) {
5339
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
5340
+ args.push(options.asOf, options.asOf);
5341
+ } else {
5342
+ sql += ` AND invalid_at IS NULL`;
5343
+ }
5278
5344
  const scope = buildWikiScopeFilter(options, "");
5279
5345
  sql += scope.clause;
5280
5346
  args.push(...scope.args);