@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
@@ -2763,6 +2763,20 @@ async function ensureSchema() {
2763
2763
  });
2764
2764
  } catch {
2765
2765
  }
2766
+ try {
2767
+ await client.execute({
2768
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2769
+ args: []
2770
+ });
2771
+ } catch {
2772
+ }
2773
+ try {
2774
+ await client.execute({
2775
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2776
+ args: []
2777
+ });
2778
+ } catch {
2779
+ }
2766
2780
  await client.executeMultiple(`
2767
2781
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2768
2782
  content_text,
@@ -3014,6 +3028,22 @@ async function ensureSchema() {
3014
3028
  );
3015
3029
  } catch {
3016
3030
  }
3031
+ for (const col of [
3032
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
3033
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
3034
+ ]) {
3035
+ try {
3036
+ await client.execute(col);
3037
+ } catch {
3038
+ }
3039
+ }
3040
+ try {
3041
+ await client.execute({
3042
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3043
+ args: []
3044
+ });
3045
+ } catch {
3046
+ }
3017
3047
  try {
3018
3048
  await client.execute({
3019
3049
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -3056,6 +3086,13 @@ async function ensureSchema() {
3056
3086
  } catch {
3057
3087
  }
3058
3088
  }
3089
+ try {
3090
+ await client.execute({
3091
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3092
+ args: []
3093
+ });
3094
+ } catch {
3095
+ }
3059
3096
  try {
3060
3097
  await client.execute({
3061
3098
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -4194,6 +4231,20 @@ var init_platform_procedures = __esm({
4194
4231
  priority: "p1",
4195
4232
  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."
4196
4233
  },
4234
+ // --- Tool guidance ---
4235
+ {
4236
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
4237
+ domain: "tools",
4238
+ priority: "p2",
4239
+ 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."
4240
+ },
4241
+ // --- Release awareness ---
4242
+ {
4243
+ title: "What's New check \u2014 surface new features after update",
4244
+ domain: "support",
4245
+ priority: "p1",
4246
+ 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."
4247
+ },
4197
4248
  // --- Platform vs Customer ownership ---
4198
4249
  {
4199
4250
  title: "What the platform provides vs what you customize",
@@ -4282,13 +4333,13 @@ var init_platform_procedures = __esm({
4282
4333
  title: "MCP tools \u2014 memory, decision, and search",
4283
4334
  domain: "tool-use",
4284
4335
  priority: "p1",
4285
- 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.`
4336
+ 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.`
4286
4337
  },
4287
4338
  {
4288
4339
  title: "MCP tools \u2014 task orchestration",
4289
4340
  domain: "tool-use",
4290
4341
  priority: "p1",
4291
- 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.'
4342
+ 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.'
4292
4343
  },
4293
4344
  {
4294
4345
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -4318,7 +4369,7 @@ var init_platform_procedures = __esm({
4318
4369
  title: "MCP tools \u2014 admin, config, and operations",
4319
4370
  domain: "tool-use",
4320
4371
  priority: "p1",
4321
- 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.'
4372
+ 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.'
4322
4373
  }
4323
4374
  ];
4324
4375
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5002,6 +5053,8 @@ async function writeMemory(record) {
5002
5053
  source_type: record.source_type ?? null,
5003
5054
  tier: record.tier ?? classifyTier(record),
5004
5055
  supersedes_id: record.supersedes_id ?? null,
5056
+ valid_from: record.valid_from ?? record.timestamp,
5057
+ invalid_at: record.invalid_at ?? null,
5005
5058
  draft: record.draft ? 1 : 0,
5006
5059
  memory_type: memoryType,
5007
5060
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -5020,7 +5073,8 @@ async function writeMemory(record) {
5020
5073
  token_cost: record.token_cost ?? null,
5021
5074
  audience: record.audience ?? null,
5022
5075
  language_type: record.language_type ?? inferLanguageType(record),
5023
- parent_memory_id: record.parent_memory_id ?? null
5076
+ parent_memory_id: record.parent_memory_id ?? null,
5077
+ procedure_for: record.procedure_for ?? null
5024
5078
  };
5025
5079
  _pendingRecords.push(dbRow);
5026
5080
  orgBus.emit({
@@ -5075,6 +5129,8 @@ async function flushBatch() {
5075
5129
  const sourceType = row.source_type ?? null;
5076
5130
  const tier = row.tier ?? 3;
5077
5131
  const supersedesId = row.supersedes_id ?? null;
5132
+ const validFrom = row.valid_from ?? row.timestamp;
5133
+ const invalidAt = row.invalid_at ?? null;
5078
5134
  const draft = row.draft ? 1 : 0;
5079
5135
  const memoryType = row.memory_type ?? "raw";
5080
5136
  const trajectory = row.trajectory ?? null;
@@ -5094,15 +5150,16 @@ async function flushBatch() {
5094
5150
  const audience = row.audience ?? null;
5095
5151
  const languageType = row.language_type ?? null;
5096
5152
  const parentMemoryId = row.parent_memory_id ?? null;
5153
+ const procedureFor = row.procedure_for ?? null;
5097
5154
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5098
5155
  tool_name, project_name,
5099
5156
  has_error, raw_text, vector, version, task_id, importance, status,
5100
5157
  confidence, last_accessed,
5101
5158
  workspace_id, document_id, user_id, char_offset, page_number,
5102
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5159
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5103
5160
  intent, outcome, domain, referenced_entities, retrieval_count,
5104
5161
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5105
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5162
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5106
5163
  const metaArgs = [
5107
5164
  intent,
5108
5165
  outcome,
@@ -5118,7 +5175,8 @@ async function flushBatch() {
5118
5175
  tokenCost,
5119
5176
  audience,
5120
5177
  languageType,
5121
- parentMemoryId
5178
+ parentMemoryId,
5179
+ procedureFor
5122
5180
  ];
5123
5181
  const baseArgs = [
5124
5182
  row.id,
@@ -5147,6 +5205,8 @@ async function flushBatch() {
5147
5205
  sourceType,
5148
5206
  tier,
5149
5207
  supersedesId,
5208
+ validFrom,
5209
+ invalidAt,
5150
5210
  draft,
5151
5211
  memoryType,
5152
5212
  trajectory,
@@ -5154,8 +5214,8 @@ async function flushBatch() {
5154
5214
  ];
5155
5215
  return {
5156
5216
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5157
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5158
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5217
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5218
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5159
5219
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5160
5220
  };
5161
5221
  };
@@ -5271,6 +5331,12 @@ async function searchMemories(queryVector, agentId, options) {
5271
5331
  AND vector IS NOT NULL${statusFilter}${draftFilter}
5272
5332
  AND COALESCE(confidence, 0.7) >= 0.3`;
5273
5333
  const args = [agentId];
5334
+ if (options?.asOf) {
5335
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
5336
+ args.push(options.asOf, options.asOf);
5337
+ } else {
5338
+ sql += ` AND invalid_at IS NULL`;
5339
+ }
5274
5340
  const scope = buildWikiScopeFilter(options, "");
5275
5341
  sql += scope.clause;
5276
5342
  args.push(...scope.args);
@@ -6589,6 +6655,19 @@ var init_entity_boost = __esm({
6589
6655
  init_store();
6590
6656
  init_database();
6591
6657
  var RRF_K = 60;
6658
+ function buildTemporalFilter(options, columnPrefix) {
6659
+ const asOf = options?.asOf;
6660
+ if (asOf) {
6661
+ return {
6662
+ clause: ` AND (${columnPrefix}valid_from IS NULL OR ${columnPrefix}valid_from <= ?) AND (${columnPrefix}invalid_at IS NULL OR ${columnPrefix}invalid_at > ?)`,
6663
+ args: [asOf, asOf]
6664
+ };
6665
+ }
6666
+ return {
6667
+ clause: ` AND ${columnPrefix}invalid_at IS NULL`,
6668
+ args: []
6669
+ };
6670
+ }
6592
6671
  function appendMemoryTypeFilter(sql, args, column, options) {
6593
6672
  if (options?.memoryTypes && options.memoryTypes.length > 0) {
6594
6673
  const uniqueTypes = [...new Set(options.memoryTypes)];
@@ -6821,6 +6900,9 @@ async function estimateCardinality(agentId, options) {
6821
6900
  AND COALESCE(status, 'active') = 'active'
6822
6901
  AND COALESCE(confidence, 0.7) >= 0.3`;
6823
6902
  const args = [agentId];
6903
+ const temporal = buildTemporalFilter(options, "");
6904
+ sql += temporal.clause;
6905
+ args.push(...temporal.args);
6824
6906
  const rawVisibility = buildRawVisibilityFilter(options, "");
6825
6907
  sql += rawVisibility.clause;
6826
6908
  args.push(...rawVisibility.args);
@@ -6949,6 +7031,9 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
6949
7031
  AND m.agent_id = ?${statusFilter}${draftFilter}
6950
7032
  AND COALESCE(m.confidence, 0.7) >= 0.3`;
6951
7033
  const args = [matchExpr, agentId];
7034
+ const temporal = buildTemporalFilter(options, "m.");
7035
+ sql += temporal.clause;
7036
+ args.push(...temporal.args);
6952
7037
  const scope = buildWikiScopeFilter(options, "m.");
6953
7038
  sql += scope.clause;
6954
7039
  args.push(...scope.args);
@@ -7061,6 +7146,9 @@ async function recentRecords(agentId, options, limit, textFilter) {
7061
7146
  WHERE agent_id = ?${statusFilter}${draftFilter}
7062
7147
  AND COALESCE(confidence, 0.7) >= 0.3`;
7063
7148
  const args = [agentId];
7149
+ const temporal = buildTemporalFilter(options, "");
7150
+ sql += temporal.clause;
7151
+ args.push(...temporal.args);
7064
7152
  const scope = buildWikiScopeFilter(options, "");
7065
7153
  sql += scope.clause;
7066
7154
  args.push(...scope.args);
@@ -7173,6 +7261,9 @@ async function trajectoryBypass(queryText, agentId, options, limit) {
7173
7261
  AND json_extract(trajectory, '$.tool') = ?
7174
7262
  AND agent_id = ?${statusFilter}${draftFilter}`;
7175
7263
  const args = [toolName, agentId];
7264
+ const temporal = buildTemporalFilter(options, "");
7265
+ sql += temporal.clause;
7266
+ args.push(...temporal.args);
7176
7267
  const rawVisibility = buildRawVisibilityFilter(options, "");
7177
7268
  sql += rawVisibility.clause;
7178
7269
  args.push(...rawVisibility.args);
@@ -116,7 +116,7 @@ var DEFAULT_CONFIG = {
116
116
  var LICENSE_PATH = path2.join(EXE_AI_DIR, "license.key");
117
117
  var CACHE_PATH = path2.join(EXE_AI_DIR, "license-cache.json");
118
118
  var DEVICE_ID_PATH = path2.join(EXE_AI_DIR, "device-id");
119
- var API_BASE = "https://askexe.com/cloud";
119
+ var API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
120
120
  var RETRY_DELAY_MS = 500;
121
121
  async function fetchRetry(url, init) {
122
122
  try {
@@ -590,7 +590,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
590
590
  import os6 from "os";
591
591
  import path7 from "path";
592
592
  import { jwtVerify, importSPKI } from "jose";
593
- var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
593
+ var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE;
594
594
  var init_license = __esm({
595
595
  "src/lib/license.ts"() {
596
596
  "use strict";
@@ -598,6 +598,7 @@ var init_license = __esm({
598
598
  LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
599
599
  CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
600
600
  DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
601
+ API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
601
602
  }
602
603
  });
603
604
 
@@ -683,9 +684,13 @@ function getParentExe(sessionKey) {
683
684
  }
684
685
  }
685
686
  function resolveExeSession() {
687
+ if (process.env.EXE_SESSION_NAME) {
688
+ return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
689
+ }
686
690
  const mySession = getMySession();
687
691
  if (!mySession) return null;
688
692
  const fromSessionName = extractRootExe(mySession);
693
+ let candidate = null;
689
694
  try {
690
695
  const key = getSessionKey();
691
696
  const parentExe = getParentExe(key);
@@ -696,13 +701,47 @@ function resolveExeSession() {
696
701
  `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
697
702
  `
698
703
  );
699
- return fromSessionName;
704
+ candidate = fromSessionName;
705
+ } else {
706
+ candidate = fromCache;
700
707
  }
701
- return fromCache;
702
708
  }
703
709
  } catch {
704
710
  }
705
- return fromSessionName ?? mySession;
711
+ if (!candidate) {
712
+ candidate = fromSessionName ?? mySession;
713
+ }
714
+ if (candidate && isRootSession(candidate)) {
715
+ try {
716
+ const transport = getTransport();
717
+ const liveSessions = transport.listSessions();
718
+ if (!liveSessions.includes(candidate)) {
719
+ const liveRoots = liveSessions.filter((s) => isRootSession(s));
720
+ if (liveRoots.length === 1) {
721
+ process.stderr.write(
722
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
723
+ `
724
+ );
725
+ return liveRoots[0];
726
+ } else if (liveRoots.length > 1) {
727
+ const base = candidate.replace(/\d+$/, "");
728
+ const match = liveRoots.find((s) => s.startsWith(base));
729
+ const chosen = match ?? liveRoots[0];
730
+ process.stderr.write(
731
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
732
+ `
733
+ );
734
+ return chosen;
735
+ }
736
+ process.stderr.write(
737
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
738
+ `
739
+ );
740
+ }
741
+ } catch {
742
+ }
743
+ }
744
+ return candidate;
706
745
  }
707
746
  function isEmployeeAlive(sessionName) {
708
747
  return getTransport().isAlive(sessionName);
@@ -2549,6 +2549,20 @@ async function ensureSchema() {
2549
2549
  });
2550
2550
  } catch {
2551
2551
  }
2552
+ try {
2553
+ await client.execute({
2554
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2555
+ args: []
2556
+ });
2557
+ } catch {
2558
+ }
2559
+ try {
2560
+ await client.execute({
2561
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2562
+ args: []
2563
+ });
2564
+ } catch {
2565
+ }
2552
2566
  await client.executeMultiple(`
2553
2567
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2554
2568
  content_text,
@@ -2800,6 +2814,22 @@ async function ensureSchema() {
2800
2814
  );
2801
2815
  } catch {
2802
2816
  }
2817
+ for (const col of [
2818
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
2819
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
2820
+ ]) {
2821
+ try {
2822
+ await client.execute(col);
2823
+ } catch {
2824
+ }
2825
+ }
2826
+ try {
2827
+ await client.execute({
2828
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
2829
+ args: []
2830
+ });
2831
+ } catch {
2832
+ }
2803
2833
  try {
2804
2834
  await client.execute({
2805
2835
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -2842,6 +2872,13 @@ async function ensureSchema() {
2842
2872
  } catch {
2843
2873
  }
2844
2874
  }
2875
+ try {
2876
+ await client.execute({
2877
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
2878
+ args: []
2879
+ });
2880
+ } catch {
2881
+ }
2845
2882
  try {
2846
2883
  await client.execute({
2847
2884
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -3423,6 +3460,20 @@ var init_platform_procedures = __esm({
3423
3460
  priority: "p1",
3424
3461
  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."
3425
3462
  },
3463
+ // --- Tool guidance ---
3464
+ {
3465
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
3466
+ domain: "tools",
3467
+ priority: "p2",
3468
+ 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."
3469
+ },
3470
+ // --- Release awareness ---
3471
+ {
3472
+ title: "What's New check \u2014 surface new features after update",
3473
+ domain: "support",
3474
+ priority: "p1",
3475
+ 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."
3476
+ },
3426
3477
  // --- Platform vs Customer ownership ---
3427
3478
  {
3428
3479
  title: "What the platform provides vs what you customize",
@@ -3511,13 +3562,13 @@ var init_platform_procedures = __esm({
3511
3562
  title: "MCP tools \u2014 memory, decision, and search",
3512
3563
  domain: "tool-use",
3513
3564
  priority: "p1",
3514
- 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.`
3565
+ 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.`
3515
3566
  },
3516
3567
  {
3517
3568
  title: "MCP tools \u2014 task orchestration",
3518
3569
  domain: "tool-use",
3519
3570
  priority: "p1",
3520
- 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.'
3571
+ 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.'
3521
3572
  },
3522
3573
  {
3523
3574
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -3547,7 +3598,7 @@ var init_platform_procedures = __esm({
3547
3598
  title: "MCP tools \u2014 admin, config, and operations",
3548
3599
  domain: "tool-use",
3549
3600
  priority: "p1",
3550
- 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.'
3601
+ 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.'
3551
3602
  }
3552
3603
  ];
3553
3604
  PLATFORM_PROCEDURE_TITLES = new Set(