@askexenow/exe-os 0.8.0 → 0.8.1

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 (90) hide show
  1. package/README.md +178 -79
  2. package/dist/bin/backfill-responses.js +160 -8
  3. package/dist/bin/backfill-vectors.js +130 -1
  4. package/dist/bin/cleanup-stale-review-tasks.js +130 -1
  5. package/dist/bin/cli.js +10111 -7540
  6. package/dist/bin/exe-agent.js +159 -1
  7. package/dist/bin/exe-assign.js +235 -16
  8. package/dist/bin/exe-boot.js +344 -472
  9. package/dist/bin/exe-call.js +145 -1
  10. package/dist/bin/exe-cloud.js +11 -0
  11. package/dist/bin/exe-dispatch.js +37 -24
  12. package/dist/bin/exe-doctor.js +130 -1
  13. package/dist/bin/exe-export-behaviors.js +150 -7
  14. package/dist/bin/exe-forget.js +822 -665
  15. package/dist/bin/exe-gateway.js +470 -62
  16. package/dist/bin/exe-heartbeat.js +133 -2
  17. package/dist/bin/exe-kill.js +150 -7
  18. package/dist/bin/exe-launch-agent.js +150 -7
  19. package/dist/bin/exe-new-employee.js +756 -224
  20. package/dist/bin/exe-pending-messages.js +132 -2
  21. package/dist/bin/exe-pending-notifications.js +130 -1
  22. package/dist/bin/exe-pending-reviews.js +132 -2
  23. package/dist/bin/exe-review.js +160 -8
  24. package/dist/bin/exe-search.js +2473 -2008
  25. package/dist/bin/exe-session-cleanup.js +238 -51
  26. package/dist/bin/exe-settings.js +11 -0
  27. package/dist/bin/exe-status.js +130 -1
  28. package/dist/bin/exe-team.js +130 -1
  29. package/dist/bin/git-sweep.js +272 -16
  30. package/dist/bin/graph-backfill.js +150 -7
  31. package/dist/bin/graph-export.js +150 -7
  32. package/dist/bin/install.js +5 -0
  33. package/dist/bin/scan-tasks.js +238 -19
  34. package/dist/bin/setup.js +1776 -10
  35. package/dist/bin/shard-migrate.js +150 -7
  36. package/dist/bin/update.js +9 -6
  37. package/dist/bin/wiki-sync.js +150 -7
  38. package/dist/gateway/index.js +470 -62
  39. package/dist/hooks/bug-report-worker.js +195 -35
  40. package/dist/hooks/commit-complete.js +272 -16
  41. package/dist/hooks/error-recall.js +2313 -1847
  42. package/dist/hooks/exe-heartbeat-hook.js +5 -0
  43. package/dist/hooks/ingest-worker.js +330 -58
  44. package/dist/hooks/ingest.js +11 -0
  45. package/dist/hooks/instructions-loaded.js +199 -10
  46. package/dist/hooks/notification.js +199 -10
  47. package/dist/hooks/post-compact.js +199 -10
  48. package/dist/hooks/pre-compact.js +199 -10
  49. package/dist/hooks/pre-tool-use.js +199 -10
  50. package/dist/hooks/prompt-ingest-worker.js +179 -14
  51. package/dist/hooks/prompt-submit.js +781 -285
  52. package/dist/hooks/response-ingest-worker.js +1900 -1405
  53. package/dist/hooks/session-end.js +456 -12
  54. package/dist/hooks/session-start.js +2188 -1724
  55. package/dist/hooks/stop.js +200 -10
  56. package/dist/hooks/subagent-stop.js +199 -10
  57. package/dist/hooks/summary-worker.js +604 -334
  58. package/dist/index.js +554 -61
  59. package/dist/lib/cloud-sync.js +5 -0
  60. package/dist/lib/config.js +13 -0
  61. package/dist/lib/consolidation.js +5 -0
  62. package/dist/lib/database.js +104 -0
  63. package/dist/lib/device-registry.js +109 -0
  64. package/dist/lib/embedder.js +13 -0
  65. package/dist/lib/employee-templates.js +53 -26
  66. package/dist/lib/employees.js +5 -0
  67. package/dist/lib/exe-daemon-client.js +5 -0
  68. package/dist/lib/exe-daemon.js +493 -79
  69. package/dist/lib/file-grep.js +20 -4
  70. package/dist/lib/hybrid-search.js +1435 -190
  71. package/dist/lib/identity-templates.js +126 -5
  72. package/dist/lib/identity.js +5 -0
  73. package/dist/lib/license.js +5 -0
  74. package/dist/lib/messaging.js +37 -24
  75. package/dist/lib/schedules.js +130 -1
  76. package/dist/lib/skill-learning.js +11 -0
  77. package/dist/lib/status-brief.js +5 -0
  78. package/dist/lib/store.js +199 -10
  79. package/dist/lib/task-router.js +72 -6
  80. package/dist/lib/tasks.js +179 -50
  81. package/dist/lib/tmux-routing.js +179 -46
  82. package/dist/mcp/server.js +2129 -1855
  83. package/dist/mcp/tools/create-task.js +86 -36
  84. package/dist/mcp/tools/deactivate-behavior.js +5 -0
  85. package/dist/mcp/tools/list-tasks.js +39 -11
  86. package/dist/mcp/tools/send-message.js +37 -24
  87. package/dist/mcp/tools/update-task.js +153 -38
  88. package/dist/runtime/index.js +451 -59
  89. package/dist/tui/App.js +454 -59
  90. package/package.json +1 -1
@@ -150,6 +150,11 @@ var DEFAULT_CONFIG = {
150
150
  idleKillTicksRequired: 3,
151
151
  idleKillIntercomAckWindowMs: 1e4,
152
152
  maxAutoInstances: 10
153
+ },
154
+ autoUpdate: {
155
+ checkOnBoot: true,
156
+ autoInstall: false,
157
+ checkIntervalMs: 24 * 60 * 60 * 1e3
153
158
  }
154
159
  };
155
160
 
@@ -81,6 +81,11 @@ var DEFAULT_CONFIG = {
81
81
  idleKillTicksRequired: 3,
82
82
  idleKillIntercomAckWindowMs: 1e4,
83
83
  maxAutoInstances: 10
84
+ },
85
+ autoUpdate: {
86
+ checkOnBoot: true,
87
+ autoInstall: false,
88
+ checkIntervalMs: 24 * 60 * 60 * 1e3
84
89
  }
85
90
  };
86
91
  function migrateLegacyConfig(raw) {
@@ -138,6 +143,11 @@ function normalizeSessionLifecycle(raw) {
138
143
  const userSL = raw.sessionLifecycle ?? {};
139
144
  raw.sessionLifecycle = { ...defaultSL, ...userSL };
140
145
  }
146
+ function normalizeAutoUpdate(raw) {
147
+ const defaultAU = DEFAULT_CONFIG.autoUpdate;
148
+ const userAU = raw.autoUpdate ?? {};
149
+ raw.autoUpdate = { ...defaultAU, ...userAU };
150
+ }
141
151
  async function loadConfig() {
142
152
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
143
153
  await mkdir(dir, { recursive: true });
@@ -160,6 +170,7 @@ async function loadConfig() {
160
170
  }
161
171
  normalizeScalingRoadmap(migratedCfg);
162
172
  normalizeSessionLifecycle(migratedCfg);
173
+ normalizeAutoUpdate(migratedCfg);
163
174
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
164
175
  if (config.dbPath.startsWith("~")) {
165
176
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -182,6 +193,7 @@ function loadConfigSync() {
182
193
  const { config: migratedCfg } = migrateConfig(parsed);
183
194
  normalizeScalingRoadmap(migratedCfg);
184
195
  normalizeSessionLifecycle(migratedCfg);
196
+ normalizeAutoUpdate(migratedCfg);
185
197
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
186
198
  } catch {
187
199
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
@@ -201,6 +213,7 @@ async function loadConfigFrom(configPath) {
201
213
  const { config: migratedCfg } = migrateConfig(parsed);
202
214
  normalizeScalingRoadmap(migratedCfg);
203
215
  normalizeSessionLifecycle(migratedCfg);
216
+ normalizeAutoUpdate(migratedCfg);
204
217
  return { ...DEFAULT_CONFIG, ...migratedCfg };
205
218
  } catch {
206
219
  return { ...DEFAULT_CONFIG };
@@ -90,6 +90,11 @@ var init_config = __esm({
90
90
  idleKillTicksRequired: 3,
91
91
  idleKillIntercomAckWindowMs: 1e4,
92
92
  maxAutoInstances: 10
93
+ },
94
+ autoUpdate: {
95
+ checkOnBoot: true,
96
+ autoInstall: false,
97
+ checkIntervalMs: 24 * 60 * 60 * 1e3
93
98
  }
94
99
  };
95
100
  }
@@ -211,6 +211,27 @@ async function ensureSchema() {
211
211
  });
212
212
  } catch {
213
213
  }
214
+ try {
215
+ await client.execute({
216
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
217
+ args: []
218
+ });
219
+ } catch {
220
+ }
221
+ try {
222
+ await client.execute({
223
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
224
+ args: []
225
+ });
226
+ } catch {
227
+ }
228
+ try {
229
+ await client.execute({
230
+ sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
231
+ args: []
232
+ });
233
+ } catch {
234
+ }
214
235
  try {
215
236
  await client.execute({
216
237
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -621,6 +642,15 @@ async function ensureSchema() {
621
642
  } catch {
622
643
  }
623
644
  }
645
+ for (const col of [
646
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
647
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'"
648
+ ]) {
649
+ try {
650
+ await client.execute(col);
651
+ } catch {
652
+ }
653
+ }
624
654
  await client.executeMultiple(`
625
655
  CREATE INDEX IF NOT EXISTS idx_memories_workspace
626
656
  ON memories(workspace_id);
@@ -685,6 +715,34 @@ async function ensureSchema() {
685
715
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
686
716
  ON conversations(channel_id);
687
717
  `);
718
+ try {
719
+ await client.execute({
720
+ sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
721
+ args: []
722
+ });
723
+ } catch {
724
+ }
725
+ try {
726
+ await client.execute({
727
+ sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
728
+ args: []
729
+ });
730
+ } catch {
731
+ }
732
+ try {
733
+ await client.execute({
734
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
735
+ args: []
736
+ });
737
+ } catch {
738
+ }
739
+ try {
740
+ await client.execute({
741
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
742
+ args: []
743
+ });
744
+ } catch {
745
+ }
688
746
  await client.executeMultiple(`
689
747
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
690
748
  content_text,
@@ -711,6 +769,52 @@ async function ensureSchema() {
711
769
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
712
770
  END;
713
771
  `);
772
+ try {
773
+ await client.execute({
774
+ sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
775
+ args: []
776
+ });
777
+ } catch {
778
+ }
779
+ try {
780
+ await client.execute(
781
+ `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
782
+ );
783
+ } catch {
784
+ }
785
+ try {
786
+ await client.execute({
787
+ sql: `UPDATE memories SET tier = 1 WHERE tool_name = 'commit_to_long_term_memory' AND importance >= 8 AND tier = 3`,
788
+ args: []
789
+ });
790
+ await client.execute({
791
+ sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
792
+ args: []
793
+ });
794
+ } catch {
795
+ }
796
+ try {
797
+ await client.execute({
798
+ sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
799
+ args: []
800
+ });
801
+ } catch {
802
+ }
803
+ try {
804
+ await client.execute(
805
+ `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
806
+ );
807
+ } catch {
808
+ }
809
+ for (const col of [
810
+ "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
811
+ "ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER DEFAULT 0"
812
+ ]) {
813
+ try {
814
+ await client.execute(col);
815
+ } catch {
816
+ }
817
+ }
714
818
  }
715
819
  var disposeTurso = disposeDatabase;
716
820
  async function disposeDatabase() {
@@ -229,6 +229,27 @@ async function ensureSchema() {
229
229
  });
230
230
  } catch {
231
231
  }
232
+ try {
233
+ await client.execute({
234
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
235
+ args: []
236
+ });
237
+ } catch {
238
+ }
239
+ try {
240
+ await client.execute({
241
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
242
+ args: []
243
+ });
244
+ } catch {
245
+ }
246
+ try {
247
+ await client.execute({
248
+ sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
249
+ args: []
250
+ });
251
+ } catch {
252
+ }
232
253
  try {
233
254
  await client.execute({
234
255
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -639,6 +660,15 @@ async function ensureSchema() {
639
660
  } catch {
640
661
  }
641
662
  }
663
+ for (const col of [
664
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
665
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'"
666
+ ]) {
667
+ try {
668
+ await client.execute(col);
669
+ } catch {
670
+ }
671
+ }
642
672
  await client.executeMultiple(`
643
673
  CREATE INDEX IF NOT EXISTS idx_memories_workspace
644
674
  ON memories(workspace_id);
@@ -703,6 +733,34 @@ async function ensureSchema() {
703
733
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
704
734
  ON conversations(channel_id);
705
735
  `);
736
+ try {
737
+ await client.execute({
738
+ sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
739
+ args: []
740
+ });
741
+ } catch {
742
+ }
743
+ try {
744
+ await client.execute({
745
+ sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
746
+ args: []
747
+ });
748
+ } catch {
749
+ }
750
+ try {
751
+ await client.execute({
752
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
753
+ args: []
754
+ });
755
+ } catch {
756
+ }
757
+ try {
758
+ await client.execute({
759
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
760
+ args: []
761
+ });
762
+ } catch {
763
+ }
706
764
  await client.executeMultiple(`
707
765
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
708
766
  content_text,
@@ -729,6 +787,52 @@ async function ensureSchema() {
729
787
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
730
788
  END;
731
789
  `);
790
+ try {
791
+ await client.execute({
792
+ sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
793
+ args: []
794
+ });
795
+ } catch {
796
+ }
797
+ try {
798
+ await client.execute(
799
+ `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
800
+ );
801
+ } catch {
802
+ }
803
+ try {
804
+ await client.execute({
805
+ sql: `UPDATE memories SET tier = 1 WHERE tool_name = 'commit_to_long_term_memory' AND importance >= 8 AND tier = 3`,
806
+ args: []
807
+ });
808
+ await client.execute({
809
+ sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
810
+ args: []
811
+ });
812
+ } catch {
813
+ }
814
+ try {
815
+ await client.execute({
816
+ sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
817
+ args: []
818
+ });
819
+ } catch {
820
+ }
821
+ try {
822
+ await client.execute(
823
+ `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
824
+ );
825
+ } catch {
826
+ }
827
+ for (const col of [
828
+ "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
829
+ "ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER DEFAULT 0"
830
+ ]) {
831
+ try {
832
+ await client.execute(col);
833
+ } catch {
834
+ }
835
+ }
732
836
  }
733
837
  async function disposeDatabase() {
734
838
  if (_client) {
@@ -835,6 +939,11 @@ var DEFAULT_CONFIG = {
835
939
  idleKillTicksRequired: 3,
836
940
  idleKillIntercomAckWindowMs: 1e4,
837
941
  maxAutoInstances: 10
942
+ },
943
+ autoUpdate: {
944
+ checkOnBoot: true,
945
+ autoInstall: false,
946
+ checkIntervalMs: 24 * 60 * 60 * 1e3
838
947
  }
839
948
  };
840
949
 
@@ -89,6 +89,11 @@ function normalizeSessionLifecycle(raw) {
89
89
  const userSL = raw.sessionLifecycle ?? {};
90
90
  raw.sessionLifecycle = { ...defaultSL, ...userSL };
91
91
  }
92
+ function normalizeAutoUpdate(raw) {
93
+ const defaultAU = DEFAULT_CONFIG.autoUpdate;
94
+ const userAU = raw.autoUpdate ?? {};
95
+ raw.autoUpdate = { ...defaultAU, ...userAU };
96
+ }
92
97
  async function loadConfig() {
93
98
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
94
99
  await mkdir(dir, { recursive: true });
@@ -111,6 +116,7 @@ async function loadConfig() {
111
116
  }
112
117
  normalizeScalingRoadmap(migratedCfg);
113
118
  normalizeSessionLifecycle(migratedCfg);
119
+ normalizeAutoUpdate(migratedCfg);
114
120
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
115
121
  if (config.dbPath.startsWith("~")) {
116
122
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -133,6 +139,7 @@ function loadConfigSync() {
133
139
  const { config: migratedCfg } = migrateConfig(parsed);
134
140
  normalizeScalingRoadmap(migratedCfg);
135
141
  normalizeSessionLifecycle(migratedCfg);
142
+ normalizeAutoUpdate(migratedCfg);
136
143
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
137
144
  } catch {
138
145
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
@@ -152,6 +159,7 @@ async function loadConfigFrom(configPath) {
152
159
  const { config: migratedCfg } = migrateConfig(parsed);
153
160
  normalizeScalingRoadmap(migratedCfg);
154
161
  normalizeSessionLifecycle(migratedCfg);
162
+ normalizeAutoUpdate(migratedCfg);
155
163
  return { ...DEFAULT_CONFIG, ...migratedCfg };
156
164
  } catch {
157
165
  return { ...DEFAULT_CONFIG };
@@ -223,6 +231,11 @@ var init_config = __esm({
223
231
  idleKillTicksRequired: 3,
224
232
  idleKillIntercomAckWindowMs: 1e4,
225
233
  maxAutoInstances: 10
234
+ },
235
+ autoUpdate: {
236
+ checkOnBoot: true,
237
+ autoInstall: false,
238
+ checkIntervalMs: 24 * 60 * 60 * 1e3
226
239
  }
227
240
  };
228
241
  CONFIG_MIGRATIONS = [
@@ -76,11 +76,14 @@ You report to exe (COO). All work flows through exe. These procedures are non-ne
76
76
  - Do NOT ask permission. Do NOT say "want me to rebuild?" \u2014 just do it.
77
77
  - If the build fails, fix the error and retry before moving on.
78
78
 
79
- 7. AFTER reporting \u2014 CHECK FOR NEXT TASK (mandatory):
80
- - Re-read your task folder: exe/<your-name>/
79
+ 7. AFTER reporting \u2014 CHECK FOR NEXT WORK (mandatory):
80
+ - First: run list_tasks(status='needs_review') \u2014 check if YOU are the reviewer on any pending reviews. Reviews are work. Process them before anything else.
81
+ - Second: run list_tasks(status='blocked') \u2014 check if any tasks are blocked. For each blocked task: can YOU unblock it? If yes, unblock it now. If not, escalate to exe immediately. Blocked tasks sitting >24h without action is a pipeline failure.
82
+ - Then: re-read your task folder: exe/<your-name>/
81
83
  - If there are more open tasks, start the next highest-priority one (go to step 1)
82
- - If no more open tasks, tell the user: "All tasks complete. Anything else?"
84
+ - If no more open tasks AND no pending reviews AND no blocked tasks you can fix, tell the user: "All tasks complete. Anything else?"
83
85
  - Do NOT wait for the user to tell you to check \u2014 auto-chain through your queue.
86
+ - NEVER say "monitoring" or "waiting" while reviews, blocked tasks, or open tasks exist. That is idle drift.
84
87
 
85
88
  CONTEXT PRESSURE PROTOCOL (mandatory \u2014 never ignore):
86
89
  If Claude Code injects a system notice about context compression, or if you notice you're
@@ -111,6 +114,13 @@ or a workflow that would help future sessions, use store_behavior with domain='s
111
114
  Format: "SKILL: [name] \u2014 Step 1: ... Step 2: ... Pitfalls: ..."
112
115
  Skip for simple one-offs. The goal is procedural memory \u2014 not just corrections, but proven approaches.
113
116
 
117
+ SPAWNING EMPLOYEES (mandatory \u2014 never bypass):
118
+ When you need another employee to do work, ALWAYS use create_task MCP tool.
119
+ create_task auto-spawns the employee session. The task IS the spawn trigger.
120
+ NEVER manually launch sessions with tmux send-keys or claude -p.
121
+ NEVER spawn sessions without a task assigned \u2014 idle sessions waste resources.
122
+ NEVER refuse a dispatched task claiming "not in scope" \u2014 if it's assigned to you, it's your work.
123
+
114
124
  CREATING TASKS FOR OTHER EMPLOYEES:
115
125
  When you need to assign work to another employee (e.g., yoshi assigns to tom):
116
126
  - ALWAYS use create_task MCP tool. NEVER write .md files directly to exe/{name}/.
@@ -133,6 +143,14 @@ After every specialist task: verify tests ran, behavior was checked, and a memor
133
143
  Use recall_my_memory and ask_team_memory constantly. Store your own summaries (decisions, priorities, assignments) after every session.`,
134
144
  createdAt: "2026-01-01T00:00:00.000Z"
135
145
  };
146
+ var TEMPLATE_VERSION = 1;
147
+ var PROCEDURES_MARKER = "EXE OS \u2014 VISION AND NON-NEGOTIABLE PRINCIPLES";
148
+ function getSessionPrompt(storedPrompt) {
149
+ const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
150
+ const rolePrompt = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
151
+ return `${rolePrompt}
152
+ ${BASE_OPERATING_PROCEDURES}`;
153
+ }
136
154
  var TEMPLATES = {
137
155
  yoshi: {
138
156
  name: "yoshi",
@@ -202,8 +220,7 @@ ROLE BOUNDARIES \u2014 stay in your lane:
202
220
  - You do NOT create marketing content, slide decks, social media copy, or brand materials. That is mari's (CMO) job.
203
221
  - When a task involves content creation for non-technical audiences, your job is to produce the TECHNICAL ANALYSIS only \u2014 what the project does, how it works, what's unique. Stop there.
204
222
  - If a task asks you to "write content for slides" or "create social posts," produce a technical summary and note that mari should handle the content/design work. Do NOT write the slides yourself.
205
- - Your output is the INPUT for other specialists, not the final deliverable for external audiences.
206
- ${BASE_OPERATING_PROCEDURES}`
223
+ - Your output is the INPUT for other specialists, not the final deliverable for external audiences.`
207
224
  },
208
225
  mari: {
209
226
  name: "mari",
@@ -275,8 +292,7 @@ DELEGATION:
275
292
  - For content production tasks (video rendering, image generation, asset creation with exe-create), delegate to sasha via create_task. Write a clear brief with: deliverable, format, platform specs, brand guidelines, and reference assets.
276
293
  - You write the script/brief. Sasha produces. You review the output.
277
294
  - For tasks within your own domain (copy, strategy, SEO, social posts), handle directly.
278
- - When sasha completes work, the review routes back to you automatically. Review it before marking done.
279
- ${BASE_OPERATING_PROCEDURES}`
295
+ - When sasha completes work, the review routes back to you automatically. Review it before marking done.`
280
296
  },
281
297
  tom: {
282
298
  name: "tom",
@@ -334,8 +350,7 @@ What you do NOT do:
334
350
  - Marketing, content, design \u2014 that's mari
335
351
  - Prioritization, coordination \u2014 that's exe
336
352
  - Spec writing, test writing \u2014 that's yoshi (unless explicitly asked)
337
- - You implement. That's it. Do it well.
338
- ${BASE_OPERATING_PROCEDURES}`
353
+ - You implement. That's it. Do it well.`
339
354
  },
340
355
  sasha: {
341
356
  name: "sasha",
@@ -390,31 +405,38 @@ WHAT YOU DO NOT DO:
390
405
  - Marketing strategy, brand decisions, copywriting \u2014 that's mari
391
406
  - Architecture, tool development, debugging \u2014 that's yoshi
392
407
  - Prioritization, coordination \u2014 that's exe
393
- - You produce. That's it. Do it well.
394
- ${BASE_OPERATING_PROCEDURES}`
408
+ - You produce. That's it. Do it well.`
395
409
  },
396
410
  gen: {
397
411
  name: "gen",
398
- role: "AI Coding Specialist",
399
- systemPrompt: `You are gen, the AI Coding Specialist. You track the latest AI tools, open source repositories, and the AI frontier to keep the team at the cutting edge. You report to exe (COO).
412
+ role: "AI Product Lead",
413
+ systemPrompt: `You are gen, the AI Product Lead. You are the competitive intelligence engine. You study open source repos, new AI tools, and competitor products \u2014 then compare them against our codebase to find features we should steal, patterns we should adopt, and threats we should watch. You report to exe (COO).
414
+
415
+ Your core job: someone hands you a repo or a tool. You clone it, read it cover to cover, and compare it against our products (exe-os, exe-wiki, exe-crm). You report what they do better, what we do better, and what's worth building.
400
416
 
401
417
  Your domain:
402
- - AI tools and frameworks: LLM APIs, embedding models, vector databases, agent frameworks
403
- - Open source landscape: trending repos, new releases, license compatibility
404
- - AI frontier: latest research papers, capability benchmarks, emerging techniques
405
- - Experimental vs production pipeline: which tools are ready for prod, which need evaluation
406
- - Prompt engineering: patterns, anti-patterns, model-specific optimizations
407
- - Fine-tuning and training: when to fine-tune vs prompt, data preparation, evaluation
408
- - Cost optimization: token usage, model selection for cost/quality tradeoff
409
- - Integration patterns: how to embed AI capabilities into existing systems safely
410
-
411
- Maintain a clear separation between experimental tools (for evaluation) and production-ready tools (for shipping). Always document evaluation criteria and results.
412
- ${BASE_OPERATING_PROCEDURES}`
418
+ - Competitive analysis: clone repos, read architecture, compare features against ours
419
+ - AI frontier: latest tools, models, frameworks, benchmarks \u2014 what's production-ready vs hype
420
+ - Feature scouting: find patterns in other projects that would make our products better
421
+ - Open source landscape: trending repos, new releases, license compatibility (AGPL boundary matters)
422
+ - Integration evaluation: build minimal PoC, measure quality/cost/latency, report tradeoffs
423
+ - Cost optimization: model selection, token budgets, provider comparisons
424
+ - Roadmap input: recommend features based on competitive gaps, not guesswork
425
+
426
+ When you analyze a repo:
427
+ 1. Clone it, read ARCHITECTURE.md / README / key source files
428
+ 2. Compare against our equivalent (exe-os vs their orchestration, exe-wiki vs their knowledge base, etc.)
429
+ 3. Report: what to steal (with file paths), what they do worse (our moat), patterns worth adopting
430
+ 4. Write to exe/output/competitive/{repo-name}.md
431
+ 5. If a feature is worth building, create a task for yoshi with the spec
432
+
433
+ Every analysis must answer: "Should we build this? If yes, how hard? If no, why not?"
434
+
435
+ Maintain a clear separation between experimental (for evaluation) and production-ready (for shipping). Never recommend something you haven't read the source code for.`
413
436
  }
414
437
  };
415
438
  function buildCustomEmployeePrompt(name, role) {
416
- return `You are ${name}, a ${role}. You report to exe (COO). Your memories are tracked and searchable by colleagues.
417
- ${BASE_OPERATING_PROCEDURES}`;
439
+ return `You are ${name}, a ${role}. You report to exe (COO). Your memories are tracked and searchable by colleagues.`;
418
440
  }
419
441
  function getTemplate(name) {
420
442
  return TEMPLATES[name];
@@ -530,6 +552,9 @@ function renderClientCOOTemplate(vars) {
530
552
  for (const key of CLIENT_COO_PLACEHOLDERS) {
531
553
  out = out.split(`{{${key}}}`).join(vars[key]);
532
554
  }
555
+ if (vars.industry_context) {
556
+ out += "\n" + vars.industry_context;
557
+ }
533
558
  return out;
534
559
  }
535
560
  export {
@@ -537,7 +562,9 @@ export {
537
562
  CLIENT_COO_TEMPLATE,
538
563
  DEFAULT_EXE,
539
564
  TEMPLATES,
565
+ TEMPLATE_VERSION,
540
566
  buildCustomEmployeePrompt,
567
+ getSessionPrompt,
541
568
  getTemplate,
542
569
  renderClientCOOTemplate
543
570
  };
@@ -87,6 +87,11 @@ var DEFAULT_CONFIG = {
87
87
  idleKillTicksRequired: 3,
88
88
  idleKillIntercomAckWindowMs: 1e4,
89
89
  maxAutoInstances: 10
90
+ },
91
+ autoUpdate: {
92
+ checkOnBoot: true,
93
+ autoInstall: false,
94
+ checkIntervalMs: 24 * 60 * 60 * 1e3
90
95
  }
91
96
  };
92
97
 
@@ -89,6 +89,11 @@ var DEFAULT_CONFIG = {
89
89
  idleKillTicksRequired: 3,
90
90
  idleKillIntercomAckWindowMs: 1e4,
91
91
  maxAutoInstances: 10
92
+ },
93
+ autoUpdate: {
94
+ checkOnBoot: true,
95
+ autoInstall: false,
96
+ checkIntervalMs: 24 * 60 * 60 * 1e3
92
97
  }
93
98
  };
94
99