@askexenow/exe-os 0.9.92 → 0.9.94

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 +118 -13
  10. package/dist/bin/cli.js +1605 -456
  11. package/dist/bin/customer-readiness.js +51 -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 +111 -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 +133 -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 +132 -18
  22. package/dist/bin/exe-heartbeat.js +118 -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 +118 -13
  27. package/dist/bin/exe-pending-notifications.js +118 -13
  28. package/dist/bin/exe-pending-reviews.js +118 -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 +133 -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 +118 -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 +133 -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 +133 -18
  43. package/dist/bin/scan-tasks.js +133 -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 +57 -1
  47. package/dist/bin/update.js +1 -1
  48. package/dist/gateway/index.js +133 -18
  49. package/dist/hooks/bug-report-worker.js +133 -18
  50. package/dist/hooks/codex-stop-task-finalizer.js +123 -14
  51. package/dist/hooks/commit-complete.js +133 -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 +310 -50
  57. package/dist/hooks/post-tool-combined.js +433 -13
  58. package/dist/hooks/pre-compact.js +133 -18
  59. package/dist/hooks/pre-tool-use.js +118 -13
  60. package/dist/hooks/prompt-submit.js +191 -19
  61. package/dist/hooks/session-end.js +133 -18
  62. package/dist/hooks/session-start.js +143 -13
  63. package/dist/hooks/stop.js +118 -13
  64. package/dist/hooks/subagent-stop.js +118 -13
  65. package/dist/hooks/summary-worker.js +96 -7
  66. package/dist/index.js +133 -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 +913 -42
  74. package/dist/lib/hybrid-search.js +100 -9
  75. package/dist/lib/license.js +1 -1
  76. package/dist/lib/messaging.js +40 -4
  77. package/dist/lib/schedules.js +54 -3
  78. package/dist/lib/store.js +75 -9
  79. package/dist/lib/tasks.js +58 -9
  80. package/dist/lib/tmux-routing.js +58 -9
  81. package/dist/mcp/server.js +875 -42
  82. package/dist/mcp/tools/create-task.js +67 -12
  83. package/dist/mcp/tools/list-tasks.js +46 -5
  84. package/dist/mcp/tools/send-message.js +40 -4
  85. package/dist/mcp/tools/update-task.js +58 -9
  86. package/dist/runtime/index.js +133 -18
  87. package/dist/tui/App.js +132 -18
  88. package/package.json +1 -1
@@ -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 your own memories (semantic + FTS). Supports as_of param for bi-temporal queries (what did I know at time X?), kind param to filter by memory type (decision, procedure, observation, raw, conversation, behavior). memory(action="ask_team") / ask_team_memory: search a colleague's memories by agent name. memory(action="store") / store_memory: persist a memory. Supports kind param and procedure_for domain tag for procedure-type memories. 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. memory(action="supersede") / 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. Supports spawn_runtime and spawn_model params to override the agent's default runtime/model for a specific task. 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="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. diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. Returns top-K tools ranked by relevance. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role identity. Returns drift score + recommendations. 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);
@@ -2863,6 +2863,20 @@ async function ensureSchema() {
2863
2863
  });
2864
2864
  } catch {
2865
2865
  }
2866
+ try {
2867
+ await client.execute({
2868
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2869
+ args: []
2870
+ });
2871
+ } catch {
2872
+ }
2873
+ try {
2874
+ await client.execute({
2875
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2876
+ args: []
2877
+ });
2878
+ } catch {
2879
+ }
2866
2880
  await client.executeMultiple(`
2867
2881
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2868
2882
  content_text,
@@ -3114,6 +3128,22 @@ async function ensureSchema() {
3114
3128
  );
3115
3129
  } catch {
3116
3130
  }
3131
+ for (const col of [
3132
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
3133
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
3134
+ ]) {
3135
+ try {
3136
+ await client.execute(col);
3137
+ } catch {
3138
+ }
3139
+ }
3140
+ try {
3141
+ await client.execute({
3142
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3143
+ args: []
3144
+ });
3145
+ } catch {
3146
+ }
3117
3147
  try {
3118
3148
  await client.execute({
3119
3149
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -3156,6 +3186,13 @@ async function ensureSchema() {
3156
3186
  } catch {
3157
3187
  }
3158
3188
  }
3189
+ try {
3190
+ await client.execute({
3191
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3192
+ args: []
3193
+ });
3194
+ } catch {
3195
+ }
3159
3196
  try {
3160
3197
  await client.execute({
3161
3198
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -4294,6 +4331,20 @@ var init_platform_procedures = __esm({
4294
4331
  priority: "p1",
4295
4332
  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."
4296
4333
  },
4334
+ // --- Tool guidance ---
4335
+ {
4336
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
4337
+ domain: "tools",
4338
+ priority: "p2",
4339
+ 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."
4340
+ },
4341
+ // --- Release awareness ---
4342
+ {
4343
+ title: "What's New check \u2014 surface new features after update",
4344
+ domain: "support",
4345
+ priority: "p1",
4346
+ 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."
4347
+ },
4297
4348
  // --- Platform vs Customer ownership ---
4298
4349
  {
4299
4350
  title: "What the platform provides vs what you customize",
@@ -4382,13 +4433,13 @@ var init_platform_procedures = __esm({
4382
4433
  title: "MCP tools \u2014 memory, decision, and search",
4383
4434
  domain: "tool-use",
4384
4435
  priority: "p1",
4385
- 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.`
4436
+ content: `memory(action="recall") / recall_my_memory: search your own memories (semantic + FTS). Supports as_of param for bi-temporal queries (what did I know at time X?), kind param to filter by memory type (decision, procedure, observation, raw, conversation, behavior). memory(action="ask_team") / ask_team_memory: search a colleague's memories by agent name. memory(action="store") / store_memory: persist a memory. Supports kind param and procedure_for domain tag for procedure-type memories. 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. memory(action="supersede") / 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.`
4386
4437
  },
4387
4438
  {
4388
4439
  title: "MCP tools \u2014 task orchestration",
4389
4440
  domain: "tool-use",
4390
4441
  priority: "p1",
4391
- 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.'
4442
+ content: `task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. Supports spawn_runtime and spawn_model params to override the agent's default runtime/model for a specific task. 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.`
4392
4443
  },
4393
4444
  {
4394
4445
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -4418,7 +4469,7 @@ var init_platform_procedures = __esm({
4418
4469
  title: "MCP tools \u2014 admin, config, and operations",
4419
4470
  domain: "tool-use",
4420
4471
  priority: "p1",
4421
- 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.'
4472
+ 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. diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. Returns top-K tools ranked by relevance. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role identity. Returns drift score + recommendations. mcp_ping(): daemon health + license status + tool usage stats.'
4422
4473
  }
4423
4474
  ];
4424
4475
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5102,6 +5153,8 @@ async function writeMemory(record) {
5102
5153
  source_type: record.source_type ?? null,
5103
5154
  tier: record.tier ?? classifyTier(record),
5104
5155
  supersedes_id: record.supersedes_id ?? null,
5156
+ valid_from: record.valid_from ?? record.timestamp,
5157
+ invalid_at: record.invalid_at ?? null,
5105
5158
  draft: record.draft ? 1 : 0,
5106
5159
  memory_type: memoryType,
5107
5160
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -5120,7 +5173,8 @@ async function writeMemory(record) {
5120
5173
  token_cost: record.token_cost ?? null,
5121
5174
  audience: record.audience ?? null,
5122
5175
  language_type: record.language_type ?? inferLanguageType(record),
5123
- parent_memory_id: record.parent_memory_id ?? null
5176
+ parent_memory_id: record.parent_memory_id ?? null,
5177
+ procedure_for: record.procedure_for ?? null
5124
5178
  };
5125
5179
  _pendingRecords.push(dbRow);
5126
5180
  orgBus.emit({
@@ -5175,6 +5229,8 @@ async function flushBatch() {
5175
5229
  const sourceType = row.source_type ?? null;
5176
5230
  const tier = row.tier ?? 3;
5177
5231
  const supersedesId = row.supersedes_id ?? null;
5232
+ const validFrom = row.valid_from ?? row.timestamp;
5233
+ const invalidAt = row.invalid_at ?? null;
5178
5234
  const draft = row.draft ? 1 : 0;
5179
5235
  const memoryType = row.memory_type ?? "raw";
5180
5236
  const trajectory = row.trajectory ?? null;
@@ -5194,15 +5250,16 @@ async function flushBatch() {
5194
5250
  const audience = row.audience ?? null;
5195
5251
  const languageType = row.language_type ?? null;
5196
5252
  const parentMemoryId = row.parent_memory_id ?? null;
5253
+ const procedureFor = row.procedure_for ?? null;
5197
5254
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5198
5255
  tool_name, project_name,
5199
5256
  has_error, raw_text, vector, version, task_id, importance, status,
5200
5257
  confidence, last_accessed,
5201
5258
  workspace_id, document_id, user_id, char_offset, page_number,
5202
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5259
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5203
5260
  intent, outcome, domain, referenced_entities, retrieval_count,
5204
5261
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5205
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5262
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5206
5263
  const metaArgs = [
5207
5264
  intent,
5208
5265
  outcome,
@@ -5218,7 +5275,8 @@ async function flushBatch() {
5218
5275
  tokenCost,
5219
5276
  audience,
5220
5277
  languageType,
5221
- parentMemoryId
5278
+ parentMemoryId,
5279
+ procedureFor
5222
5280
  ];
5223
5281
  const baseArgs = [
5224
5282
  row.id,
@@ -5247,6 +5305,8 @@ async function flushBatch() {
5247
5305
  sourceType,
5248
5306
  tier,
5249
5307
  supersedesId,
5308
+ validFrom,
5309
+ invalidAt,
5250
5310
  draft,
5251
5311
  memoryType,
5252
5312
  trajectory,
@@ -5254,8 +5314,8 @@ async function flushBatch() {
5254
5314
  ];
5255
5315
  return {
5256
5316
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5257
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5258
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5317
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5318
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5259
5319
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5260
5320
  };
5261
5321
  };
@@ -5371,6 +5431,12 @@ async function searchMemories(queryVector, agentId, options) {
5371
5431
  AND vector IS NOT NULL${statusFilter}${draftFilter}
5372
5432
  AND COALESCE(confidence, 0.7) >= 0.3`;
5373
5433
  const args = [agentId];
5434
+ if (options?.asOf) {
5435
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
5436
+ args.push(options.asOf, options.asOf);
5437
+ } else {
5438
+ sql += ` AND invalid_at IS NULL`;
5439
+ }
5374
5440
  const scope = buildWikiScopeFilter(options, "");
5375
5441
  sql += scope.clause;
5376
5442
  args.push(...scope.args);
@@ -2724,6 +2724,20 @@ var PLATFORM_PROCEDURES = [
2724
2724
  priority: "p1",
2725
2725
  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."
2726
2726
  },
2727
+ // --- Tool guidance ---
2728
+ {
2729
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
2730
+ domain: "tools",
2731
+ priority: "p2",
2732
+ 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."
2733
+ },
2734
+ // --- Release awareness ---
2735
+ {
2736
+ title: "What's New check \u2014 surface new features after update",
2737
+ domain: "support",
2738
+ priority: "p1",
2739
+ 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."
2740
+ },
2727
2741
  // --- Platform vs Customer ownership ---
2728
2742
  {
2729
2743
  title: "What the platform provides vs what you customize",
@@ -2812,13 +2826,13 @@ var PLATFORM_PROCEDURES = [
2812
2826
  title: "MCP tools \u2014 memory, decision, and search",
2813
2827
  domain: "tool-use",
2814
2828
  priority: "p1",
2815
- 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.`
2829
+ content: `memory(action="recall") / recall_my_memory: search your own memories (semantic + FTS). Supports as_of param for bi-temporal queries (what did I know at time X?), kind param to filter by memory type (decision, procedure, observation, raw, conversation, behavior). memory(action="ask_team") / ask_team_memory: search a colleague's memories by agent name. memory(action="store") / store_memory: persist a memory. Supports kind param and procedure_for domain tag for procedure-type memories. 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. memory(action="supersede") / 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.`
2816
2830
  },
2817
2831
  {
2818
2832
  title: "MCP tools \u2014 task orchestration",
2819
2833
  domain: "tool-use",
2820
2834
  priority: "p1",
2821
- 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.'
2835
+ content: `task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. Supports spawn_runtime and spawn_model params to override the agent's default runtime/model for a specific task. 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.`
2822
2836
  },
2823
2837
  {
2824
2838
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -2848,7 +2862,7 @@ var PLATFORM_PROCEDURES = [
2848
2862
  title: "MCP tools \u2014 admin, config, and operations",
2849
2863
  domain: "tool-use",
2850
2864
  priority: "p1",
2851
- 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.'
2865
+ 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. diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. Returns top-K tools ranked by relevance. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role identity. Returns drift score + recommendations. mcp_ping(): daemon health + license status + tool usage stats.'
2852
2866
  }
2853
2867
  ];
2854
2868
  var PLATFORM_PROCEDURE_TITLES = new Set(
@@ -3242,7 +3256,7 @@ import { jwtVerify, importSPKI } from "jose";
3242
3256
  var LICENSE_PATH = path6.join(EXE_AI_DIR, "license.key");
3243
3257
  var CACHE_PATH = path6.join(EXE_AI_DIR, "license-cache.json");
3244
3258
  var DEVICE_ID_PATH = path6.join(EXE_AI_DIR, "device-id");
3245
- var API_BASE = "https://askexe.com/cloud";
3259
+ var API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
3246
3260
  var RETRY_DELAY_MS = 500;
3247
3261
  async function fetchRetry(url, init) {
3248
3262
  try {