@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
@@ -2637,6 +2637,20 @@ async function ensureSchema() {
2637
2637
  });
2638
2638
  } catch {
2639
2639
  }
2640
+ try {
2641
+ await client.execute({
2642
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2643
+ args: []
2644
+ });
2645
+ } catch {
2646
+ }
2647
+ try {
2648
+ await client.execute({
2649
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2650
+ args: []
2651
+ });
2652
+ } catch {
2653
+ }
2640
2654
  await client.executeMultiple(`
2641
2655
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2642
2656
  content_text,
@@ -2888,6 +2902,22 @@ async function ensureSchema() {
2888
2902
  );
2889
2903
  } catch {
2890
2904
  }
2905
+ for (const col of [
2906
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
2907
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
2908
+ ]) {
2909
+ try {
2910
+ await client.execute(col);
2911
+ } catch {
2912
+ }
2913
+ }
2914
+ try {
2915
+ await client.execute({
2916
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
2917
+ args: []
2918
+ });
2919
+ } catch {
2920
+ }
2891
2921
  try {
2892
2922
  await client.execute({
2893
2923
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -2930,6 +2960,13 @@ async function ensureSchema() {
2930
2960
  } catch {
2931
2961
  }
2932
2962
  }
2963
+ try {
2964
+ await client.execute({
2965
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
2966
+ args: []
2967
+ });
2968
+ } catch {
2969
+ }
2933
2970
  try {
2934
2971
  await client.execute({
2935
2972
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -3511,6 +3548,20 @@ var init_platform_procedures = __esm({
3511
3548
  priority: "p1",
3512
3549
  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."
3513
3550
  },
3551
+ // --- Tool guidance ---
3552
+ {
3553
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
3554
+ domain: "tools",
3555
+ priority: "p2",
3556
+ 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."
3557
+ },
3558
+ // --- Release awareness ---
3559
+ {
3560
+ title: "What's New check \u2014 surface new features after update",
3561
+ domain: "support",
3562
+ priority: "p1",
3563
+ 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."
3564
+ },
3514
3565
  // --- Platform vs Customer ownership ---
3515
3566
  {
3516
3567
  title: "What the platform provides vs what you customize",
@@ -3599,13 +3650,13 @@ var init_platform_procedures = __esm({
3599
3650
  title: "MCP tools \u2014 memory, decision, and search",
3600
3651
  domain: "tool-use",
3601
3652
  priority: "p1",
3602
- 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.`
3653
+ 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.`
3603
3654
  },
3604
3655
  {
3605
3656
  title: "MCP tools \u2014 task orchestration",
3606
3657
  domain: "tool-use",
3607
3658
  priority: "p1",
3608
- 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.'
3659
+ 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.'
3609
3660
  },
3610
3661
  {
3611
3662
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -3635,7 +3686,7 @@ var init_platform_procedures = __esm({
3635
3686
  title: "MCP tools \u2014 admin, config, and operations",
3636
3687
  domain: "tool-use",
3637
3688
  priority: "p1",
3638
- 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.'
3689
+ 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.'
3639
3690
  }
3640
3691
  ];
3641
3692
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5562,6 +5613,8 @@ async function flushBatch() {
5562
5613
  const sourceType = row.source_type ?? null;
5563
5614
  const tier = row.tier ?? 3;
5564
5615
  const supersedesId = row.supersedes_id ?? null;
5616
+ const validFrom = row.valid_from ?? row.timestamp;
5617
+ const invalidAt = row.invalid_at ?? null;
5565
5618
  const draft = row.draft ? 1 : 0;
5566
5619
  const memoryType = row.memory_type ?? "raw";
5567
5620
  const trajectory = row.trajectory ?? null;
@@ -5581,15 +5634,16 @@ async function flushBatch() {
5581
5634
  const audience = row.audience ?? null;
5582
5635
  const languageType = row.language_type ?? null;
5583
5636
  const parentMemoryId = row.parent_memory_id ?? null;
5637
+ const procedureFor = row.procedure_for ?? null;
5584
5638
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5585
5639
  tool_name, project_name,
5586
5640
  has_error, raw_text, vector, version, task_id, importance, status,
5587
5641
  confidence, last_accessed,
5588
5642
  workspace_id, document_id, user_id, char_offset, page_number,
5589
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5643
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5590
5644
  intent, outcome, domain, referenced_entities, retrieval_count,
5591
5645
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5592
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5646
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5593
5647
  const metaArgs = [
5594
5648
  intent,
5595
5649
  outcome,
@@ -5605,7 +5659,8 @@ async function flushBatch() {
5605
5659
  tokenCost,
5606
5660
  audience,
5607
5661
  languageType,
5608
- parentMemoryId
5662
+ parentMemoryId,
5663
+ procedureFor
5609
5664
  ];
5610
5665
  const baseArgs = [
5611
5666
  row.id,
@@ -5634,6 +5689,8 @@ async function flushBatch() {
5634
5689
  sourceType,
5635
5690
  tier,
5636
5691
  supersedesId,
5692
+ validFrom,
5693
+ invalidAt,
5637
5694
  draft,
5638
5695
  memoryType,
5639
5696
  trajectory,
@@ -5641,8 +5698,8 @@ async function flushBatch() {
5641
5698
  ];
5642
5699
  return {
5643
5700
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5644
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5645
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5701
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5702
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5646
5703
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5647
5704
  };
5648
5705
  };
@@ -2787,6 +2787,20 @@ async function ensureSchema() {
2787
2787
  });
2788
2788
  } catch {
2789
2789
  }
2790
+ try {
2791
+ await client.execute({
2792
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2793
+ args: []
2794
+ });
2795
+ } catch {
2796
+ }
2797
+ try {
2798
+ await client.execute({
2799
+ sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2800
+ args: []
2801
+ });
2802
+ } catch {
2803
+ }
2790
2804
  await client.executeMultiple(`
2791
2805
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
2792
2806
  content_text,
@@ -3038,6 +3052,22 @@ async function ensureSchema() {
3038
3052
  );
3039
3053
  } catch {
3040
3054
  }
3055
+ for (const col of [
3056
+ "ALTER TABLE memories ADD COLUMN valid_from TEXT",
3057
+ "ALTER TABLE memories ADD COLUMN invalid_at TEXT"
3058
+ ]) {
3059
+ try {
3060
+ await client.execute(col);
3061
+ } catch {
3062
+ }
3063
+ }
3064
+ try {
3065
+ await client.execute({
3066
+ sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
3067
+ args: []
3068
+ });
3069
+ } catch {
3070
+ }
3041
3071
  try {
3042
3072
  await client.execute({
3043
3073
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
@@ -3080,6 +3110,13 @@ async function ensureSchema() {
3080
3110
  } catch {
3081
3111
  }
3082
3112
  }
3113
+ try {
3114
+ await client.execute({
3115
+ sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
3116
+ args: []
3117
+ });
3118
+ } catch {
3119
+ }
3083
3120
  try {
3084
3121
  await client.execute({
3085
3122
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
@@ -4218,6 +4255,20 @@ var init_platform_procedures = __esm({
4218
4255
  priority: "p1",
4219
4256
  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."
4220
4257
  },
4258
+ // --- Tool guidance ---
4259
+ {
4260
+ title: "How to use company_actions \u2014 execute business actions through gateway connectors",
4261
+ domain: "tools",
4262
+ priority: "p2",
4263
+ 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."
4264
+ },
4265
+ // --- Release awareness ---
4266
+ {
4267
+ title: "What's New check \u2014 surface new features after update",
4268
+ domain: "support",
4269
+ priority: "p1",
4270
+ 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."
4271
+ },
4221
4272
  // --- Platform vs Customer ownership ---
4222
4273
  {
4223
4274
  title: "What the platform provides vs what you customize",
@@ -4306,13 +4357,13 @@ var init_platform_procedures = __esm({
4306
4357
  title: "MCP tools \u2014 memory, decision, and search",
4307
4358
  domain: "tool-use",
4308
4359
  priority: "p1",
4309
- 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.`
4360
+ 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.`
4310
4361
  },
4311
4362
  {
4312
4363
  title: "MCP tools \u2014 task orchestration",
4313
4364
  domain: "tool-use",
4314
4365
  priority: "p1",
4315
- 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.'
4366
+ 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.'
4316
4367
  },
4317
4368
  {
4318
4369
  title: "MCP tools \u2014 knowledge graph (GraphRAG)",
@@ -4342,7 +4393,7 @@ var init_platform_procedures = __esm({
4342
4393
  title: "MCP tools \u2014 admin, config, and operations",
4343
4394
  domain: "tool-use",
4344
4395
  priority: "p1",
4345
- 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.'
4396
+ 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.'
4346
4397
  }
4347
4398
  ];
4348
4399
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -5026,6 +5077,8 @@ async function writeMemory(record) {
5026
5077
  source_type: record.source_type ?? null,
5027
5078
  tier: record.tier ?? classifyTier(record),
5028
5079
  supersedes_id: record.supersedes_id ?? null,
5080
+ valid_from: record.valid_from ?? record.timestamp,
5081
+ invalid_at: record.invalid_at ?? null,
5029
5082
  draft: record.draft ? 1 : 0,
5030
5083
  memory_type: memoryType,
5031
5084
  trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
@@ -5044,7 +5097,8 @@ async function writeMemory(record) {
5044
5097
  token_cost: record.token_cost ?? null,
5045
5098
  audience: record.audience ?? null,
5046
5099
  language_type: record.language_type ?? inferLanguageType(record),
5047
- parent_memory_id: record.parent_memory_id ?? null
5100
+ parent_memory_id: record.parent_memory_id ?? null,
5101
+ procedure_for: record.procedure_for ?? null
5048
5102
  };
5049
5103
  _pendingRecords.push(dbRow);
5050
5104
  orgBus.emit({
@@ -5099,6 +5153,8 @@ async function flushBatch() {
5099
5153
  const sourceType = row.source_type ?? null;
5100
5154
  const tier = row.tier ?? 3;
5101
5155
  const supersedesId = row.supersedes_id ?? null;
5156
+ const validFrom = row.valid_from ?? row.timestamp;
5157
+ const invalidAt = row.invalid_at ?? null;
5102
5158
  const draft = row.draft ? 1 : 0;
5103
5159
  const memoryType = row.memory_type ?? "raw";
5104
5160
  const trajectory = row.trajectory ?? null;
@@ -5118,15 +5174,16 @@ async function flushBatch() {
5118
5174
  const audience = row.audience ?? null;
5119
5175
  const languageType = row.language_type ?? null;
5120
5176
  const parentMemoryId = row.parent_memory_id ?? null;
5177
+ const procedureFor = row.procedure_for ?? null;
5121
5178
  const cols = `id, agent_id, agent_role, session_id, timestamp,
5122
5179
  tool_name, project_name,
5123
5180
  has_error, raw_text, vector, version, task_id, importance, status,
5124
5181
  confidence, last_accessed,
5125
5182
  workspace_id, document_id, user_id, char_offset, page_number,
5126
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
5183
+ source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
5127
5184
  intent, outcome, domain, referenced_entities, retrieval_count,
5128
5185
  chain_position, review_status, context_window_pct, file_paths, commit_hash,
5129
- duration_ms, token_cost, audience, language_type, parent_memory_id`;
5186
+ duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
5130
5187
  const metaArgs = [
5131
5188
  intent,
5132
5189
  outcome,
@@ -5142,7 +5199,8 @@ async function flushBatch() {
5142
5199
  tokenCost,
5143
5200
  audience,
5144
5201
  languageType,
5145
- parentMemoryId
5202
+ parentMemoryId,
5203
+ procedureFor
5146
5204
  ];
5147
5205
  const baseArgs = [
5148
5206
  row.id,
@@ -5171,6 +5229,8 @@ async function flushBatch() {
5171
5229
  sourceType,
5172
5230
  tier,
5173
5231
  supersedesId,
5232
+ validFrom,
5233
+ invalidAt,
5174
5234
  draft,
5175
5235
  memoryType,
5176
5236
  trajectory,
@@ -5178,8 +5238,8 @@ async function flushBatch() {
5178
5238
  ];
5179
5239
  return {
5180
5240
  sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
5181
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5182
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5241
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
5242
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
5183
5243
  args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
5184
5244
  };
5185
5245
  };
@@ -5295,6 +5355,12 @@ async function searchMemories(queryVector, agentId, options) {
5295
5355
  AND vector IS NOT NULL${statusFilter}${draftFilter}
5296
5356
  AND COALESCE(confidence, 0.7) >= 0.3`;
5297
5357
  const args = [agentId];
5358
+ if (options?.asOf) {
5359
+ sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
5360
+ args.push(options.asOf, options.asOf);
5361
+ } else {
5362
+ sql += ` AND invalid_at IS NULL`;
5363
+ }
5298
5364
  const scope = buildWikiScopeFilter(options, "");
5299
5365
  sql += scope.clause;
5300
5366
  args.push(...scope.args);
@@ -5763,7 +5829,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
5763
5829
  import os8 from "os";
5764
5830
  import path11 from "path";
5765
5831
  import { jwtVerify, importSPKI } from "jose";
5766
- var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
5832
+ var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE;
5767
5833
  var init_license = __esm({
5768
5834
  "src/lib/license.ts"() {
5769
5835
  "use strict";
@@ -5771,6 +5837,7 @@ var init_license = __esm({
5771
5837
  LICENSE_PATH = path11.join(EXE_AI_DIR, "license.key");
5772
5838
  CACHE_PATH = path11.join(EXE_AI_DIR, "license-cache.json");
5773
5839
  DEVICE_ID_PATH = path11.join(EXE_AI_DIR, "device-id");
5840
+ API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
5774
5841
  }
5775
5842
  });
5776
5843
 
@@ -5814,6 +5881,9 @@ import { fileURLToPath as fileURLToPath3 } from "url";
5814
5881
  function getMySession() {
5815
5882
  return getTransport().getMySession();
5816
5883
  }
5884
+ function isRootSession(name) {
5885
+ return name.length > 0 && !name.includes("-");
5886
+ }
5817
5887
  function extractRootExe(name) {
5818
5888
  if (!name) return null;
5819
5889
  if (!name.includes("-")) return name;
@@ -5829,9 +5899,13 @@ function getParentExe(sessionKey) {
5829
5899
  }
5830
5900
  }
5831
5901
  function resolveExeSession() {
5902
+ if (process.env.EXE_SESSION_NAME) {
5903
+ return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
5904
+ }
5832
5905
  const mySession = getMySession();
5833
5906
  if (!mySession) return null;
5834
5907
  const fromSessionName = extractRootExe(mySession);
5908
+ let candidate = null;
5835
5909
  try {
5836
5910
  const key = getSessionKey();
5837
5911
  const parentExe = getParentExe(key);
@@ -5842,13 +5916,47 @@ function resolveExeSession() {
5842
5916
  `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
5843
5917
  `
5844
5918
  );
5845
- return fromSessionName;
5919
+ candidate = fromSessionName;
5920
+ } else {
5921
+ candidate = fromCache;
5846
5922
  }
5847
- return fromCache;
5848
5923
  }
5849
5924
  } catch {
5850
5925
  }
5851
- return fromSessionName ?? mySession;
5926
+ if (!candidate) {
5927
+ candidate = fromSessionName ?? mySession;
5928
+ }
5929
+ if (candidate && isRootSession(candidate)) {
5930
+ try {
5931
+ const transport = getTransport();
5932
+ const liveSessions = transport.listSessions();
5933
+ if (!liveSessions.includes(candidate)) {
5934
+ const liveRoots = liveSessions.filter((s) => isRootSession(s));
5935
+ if (liveRoots.length === 1) {
5936
+ process.stderr.write(
5937
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
5938
+ `
5939
+ );
5940
+ return liveRoots[0];
5941
+ } else if (liveRoots.length > 1) {
5942
+ const base = candidate.replace(/\d+$/, "");
5943
+ const match = liveRoots.find((s) => s.startsWith(base));
5944
+ const chosen = match ?? liveRoots[0];
5945
+ process.stderr.write(
5946
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
5947
+ `
5948
+ );
5949
+ return chosen;
5950
+ }
5951
+ process.stderr.write(
5952
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
5953
+ `
5954
+ );
5955
+ }
5956
+ } catch {
5957
+ }
5958
+ }
5959
+ return candidate;
5852
5960
  }
5853
5961
  var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
5854
5962
  var init_tmux_routing = __esm({
@@ -232,6 +232,7 @@ import { jwtVerify, importSPKI } from "jose";
232
232
  var LICENSE_PATH = path2.join(EXE_AI_DIR, "license.key");
233
233
  var CACHE_PATH = path2.join(EXE_AI_DIR, "license-cache.json");
234
234
  var DEVICE_ID_PATH = path2.join(EXE_AI_DIR, "device-id");
235
+ var API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
235
236
  function loadLicense() {
236
237
  try {
237
238
  if (!existsSync3(LICENSE_PATH)) return null;