@askexenow/exe-os 0.9.35 → 0.9.37

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 (67) hide show
  1. package/dist/bin/backfill-conversations.js +5 -1
  2. package/dist/bin/backfill-responses.js +5 -1
  3. package/dist/bin/backfill-vectors.js +1 -1
  4. package/dist/bin/cleanup-stale-review-tasks.js +10 -2
  5. package/dist/bin/cli.js +48 -14
  6. package/dist/bin/exe-agent.js +1 -1
  7. package/dist/bin/exe-assign.js +10 -2
  8. package/dist/bin/exe-boot.js +1 -1
  9. package/dist/bin/exe-call.js +7 -5
  10. package/dist/bin/exe-dispatch.js +10 -2
  11. package/dist/bin/exe-doctor.js +1 -1
  12. package/dist/bin/exe-export-behaviors.js +87 -4
  13. package/dist/bin/exe-forget.js +31 -11
  14. package/dist/bin/exe-gateway.js +10 -2
  15. package/dist/bin/exe-heartbeat.js +10 -2
  16. package/dist/bin/exe-kill.js +10 -2
  17. package/dist/bin/exe-launch-agent.js +85 -7
  18. package/dist/bin/exe-new-employee.js +26 -2
  19. package/dist/bin/exe-pending-messages.js +10 -2
  20. package/dist/bin/exe-pending-notifications.js +10 -2
  21. package/dist/bin/exe-pending-reviews.js +10 -2
  22. package/dist/bin/exe-rename.js +1 -1
  23. package/dist/bin/exe-review.js +10 -2
  24. package/dist/bin/exe-search.js +38 -19
  25. package/dist/bin/exe-session-cleanup.js +14 -3
  26. package/dist/bin/exe-start-codex.js +69 -3
  27. package/dist/bin/exe-start-opencode.js +80 -3
  28. package/dist/bin/exe-status.js +10 -2
  29. package/dist/bin/exe-team.js +10 -2
  30. package/dist/bin/git-sweep.js +10 -2
  31. package/dist/bin/graph-backfill.js +2 -1
  32. package/dist/bin/graph-export.js +10 -2
  33. package/dist/bin/install.js +25 -1
  34. package/dist/bin/intercom-check.js +10 -2
  35. package/dist/bin/scan-tasks.js +10 -2
  36. package/dist/bin/setup.js +7 -5
  37. package/dist/bin/shard-migrate.js +2 -1
  38. package/dist/gateway/index.js +10 -2
  39. package/dist/hooks/bug-report-worker.js +10 -2
  40. package/dist/hooks/codex-stop-task-finalizer.js +10 -2
  41. package/dist/hooks/commit-complete.js +10 -2
  42. package/dist/hooks/error-recall.js +38 -19
  43. package/dist/hooks/ingest-worker.js +9 -2
  44. package/dist/hooks/ingest.js +10 -2
  45. package/dist/hooks/instructions-loaded.js +10 -2
  46. package/dist/hooks/notification.js +10 -2
  47. package/dist/hooks/post-compact.js +10 -2
  48. package/dist/hooks/post-tool-combined.js +47 -21
  49. package/dist/hooks/pre-compact.js +12 -3
  50. package/dist/hooks/pre-tool-use.js +20 -8
  51. package/dist/hooks/prompt-submit.js +133 -20
  52. package/dist/hooks/session-end.js +138 -5
  53. package/dist/hooks/session-start.js +216 -46
  54. package/dist/hooks/stop.js +14 -4
  55. package/dist/hooks/subagent-stop.js +10 -2
  56. package/dist/hooks/summary-worker.js +121 -19
  57. package/dist/index.js +32 -16
  58. package/dist/lib/employee-templates.js +7 -5
  59. package/dist/lib/exe-daemon.js +124 -34
  60. package/dist/lib/hybrid-search.js +38 -19
  61. package/dist/lib/schedules.js +1 -1
  62. package/dist/lib/store.js +10 -2
  63. package/dist/mcp/server.js +118 -34
  64. package/dist/runtime/index.js +32 -16
  65. package/dist/tui/App.js +10 -2
  66. package/package.json +1 -1
  67. package/src/commands/exe/save.md +52 -0
@@ -3054,6 +3054,9 @@ function classifyMemoryType(input) {
3054
3054
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3055
3055
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3056
3056
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3057
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3058
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3059
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3057
3060
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3058
3061
  if (tool === "store_memory" || tool === "manual") return "observation";
3059
3062
  return "raw";
@@ -3196,6 +3199,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3196
3199
  }
3197
3200
  }
3198
3201
  function schedulePostWriteMemoryHygiene(memoryIds) {
3202
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3199
3203
  if (memoryIds.length === 0) return;
3200
3204
  const run = () => {
3201
3205
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3590,7 +3594,7 @@ var init_platform_procedures = __esm({
3590
3594
  title: "Chain of command \u2014 who talks to whom",
3591
3595
  domain: "workflow",
3592
3596
  priority: "p0",
3593
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3597
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3594
3598
  },
3595
3599
  {
3596
3600
  title: "Single dispatch path \u2014 create_task only",
@@ -4262,7 +4266,11 @@ async function searchMemories(queryVector, agentId, options) {
4262
4266
  sql += ` AND timestamp >= ?`;
4263
4267
  args.push(options.since);
4264
4268
  }
4265
- if (options?.memoryType) {
4269
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4270
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4271
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4272
+ args.push(...uniqueTypes);
4273
+ } else if (options?.memoryType) {
4266
4274
  sql += ` AND memory_type = ?`;
4267
4275
  args.push(options.memoryType);
4268
4276
  }
@@ -4484,6 +4492,17 @@ init_database();
4484
4492
  // src/lib/hybrid-search.ts
4485
4493
  init_store();
4486
4494
  init_database();
4495
+ function appendMemoryTypeFilter(sql, args, column, options) {
4496
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4497
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4498
+ sql += ` AND ${column} IN (${uniqueTypes.map(() => "?").join(",")})`;
4499
+ args.push(...uniqueTypes);
4500
+ } else if (options?.memoryType) {
4501
+ sql += ` AND ${column} = ?`;
4502
+ args.push(options.memoryType);
4503
+ }
4504
+ return sql;
4505
+ }
4487
4506
  async function lightweightSearch(queryText, agentId, options) {
4488
4507
  const client = getClient();
4489
4508
  const limit = options?.limit ?? 5;
@@ -4551,10 +4570,7 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
4551
4570
  sql += ` AND m.timestamp >= ?`;
4552
4571
  args.push(options.since);
4553
4572
  }
4554
- if (options?.memoryType) {
4555
- sql += ` AND m.memory_type = ?`;
4556
- args.push(options.memoryType);
4557
- }
4573
+ sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
4558
4574
  sql += ` ORDER BY rank LIMIT ?`;
4559
4575
  args.push(limit);
4560
4576
  const result = await client.execute({ sql, args });
@@ -4611,9 +4627,16 @@ async function recentRecords(agentId, options, limit, textFilter) {
4611
4627
  AND timestamp >= ? AND timestamp <= ?
4612
4628
  AND COALESCE(status, 'active') = 'active'
4613
4629
  AND ${options?.includeRaw === false ? "COALESCE(memory_type, 'raw') != 'raw'" : "1 = 1"}
4630
+ ${options?.memoryTypes?.length ? `AND memory_type IN (${options.memoryTypes.map(() => "?").join(",")})` : options?.memoryType ? "AND memory_type = ?" : ""}
4614
4631
  AND COALESCE(confidence, 0.7) >= 0.3
4615
4632
  ORDER BY timestamp DESC LIMIT ?`,
4616
- args: [agentId, windowStart, killedAt, boundarySlots]
4633
+ args: [
4634
+ agentId,
4635
+ windowStart,
4636
+ killedAt,
4637
+ ...options?.memoryTypes?.length ? [...new Set(options.memoryTypes)] : options?.memoryType ? [options.memoryType] : [],
4638
+ boundarySlots
4639
+ ]
4617
4640
  });
4618
4641
  for (const row of boundaryResult.rows) {
4619
4642
  sessionBoundaryMemories.push(rowToMemoryRecord(row));
@@ -4659,10 +4682,7 @@ async function recentRecords(agentId, options, limit, textFilter) {
4659
4682
  sql += ` AND timestamp >= ?`;
4660
4683
  args.push(options.since);
4661
4684
  }
4662
- if (options?.memoryType) {
4663
- sql += ` AND memory_type = ?`;
4664
- args.push(options.memoryType);
4665
- }
4685
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
4666
4686
  if (textFilter) {
4667
4687
  sql += ` AND raw_text LIKE '%' || ? || '%'`;
4668
4688
  args.push(textFilter);
@@ -3712,6 +3712,9 @@ function classifyMemoryType(input) {
3712
3712
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3713
3713
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3714
3714
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3715
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3716
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3717
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3715
3718
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3716
3719
  if (tool === "store_memory" || tool === "manual") return "observation";
3717
3720
  return "raw";
@@ -3854,6 +3857,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3854
3857
  }
3855
3858
  }
3856
3859
  function schedulePostWriteMemoryHygiene(memoryIds) {
3860
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3857
3861
  if (memoryIds.length === 0) return;
3858
3862
  const run = () => {
3859
3863
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4248,7 +4252,7 @@ var init_platform_procedures = __esm({
4248
4252
  title: "Chain of command \u2014 who talks to whom",
4249
4253
  domain: "workflow",
4250
4254
  priority: "p0",
4251
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4255
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4252
4256
  },
4253
4257
  {
4254
4258
  title: "Single dispatch path \u2014 create_task only",
@@ -4920,7 +4924,11 @@ async function searchMemories(queryVector, agentId, options) {
4920
4924
  sql += ` AND timestamp >= ?`;
4921
4925
  args.push(options.since);
4922
4926
  }
4923
- if (options?.memoryType) {
4927
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4928
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4929
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4930
+ args.push(...uniqueTypes);
4931
+ } else if (options?.memoryType) {
4924
4932
  sql += ` AND memory_type = ?`;
4925
4933
  args.push(options.memoryType);
4926
4934
  }
@@ -3084,6 +3084,9 @@ function classifyMemoryType(input) {
3084
3084
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3085
3085
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3086
3086
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3087
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3088
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3089
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3087
3090
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3088
3091
  if (tool === "store_memory" || tool === "manual") return "observation";
3089
3092
  return "raw";
@@ -3226,6 +3229,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3226
3229
  }
3227
3230
  }
3228
3231
  function schedulePostWriteMemoryHygiene(memoryIds) {
3232
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3229
3233
  if (memoryIds.length === 0) return;
3230
3234
  const run = () => {
3231
3235
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3620,7 +3624,7 @@ var init_platform_procedures = __esm({
3620
3624
  title: "Chain of command \u2014 who talks to whom",
3621
3625
  domain: "workflow",
3622
3626
  priority: "p0",
3623
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3627
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3624
3628
  },
3625
3629
  {
3626
3630
  title: "Single dispatch path \u2014 create_task only",
@@ -4292,7 +4296,11 @@ async function searchMemories(queryVector, agentId, options) {
4292
4296
  sql += ` AND timestamp >= ?`;
4293
4297
  args.push(options.since);
4294
4298
  }
4295
- if (options?.memoryType) {
4299
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4300
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4301
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4302
+ args.push(...uniqueTypes);
4303
+ } else if (options?.memoryType) {
4296
4304
  sql += ` AND memory_type = ?`;
4297
4305
  args.push(options.memoryType);
4298
4306
  }
@@ -3054,6 +3054,9 @@ function classifyMemoryType(input) {
3054
3054
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3055
3055
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3056
3056
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3057
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3058
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3059
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3057
3060
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3058
3061
  if (tool === "store_memory" || tool === "manual") return "observation";
3059
3062
  return "raw";
@@ -3196,6 +3199,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3196
3199
  }
3197
3200
  }
3198
3201
  function schedulePostWriteMemoryHygiene(memoryIds) {
3202
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3199
3203
  if (memoryIds.length === 0) return;
3200
3204
  const run = () => {
3201
3205
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3590,7 +3594,7 @@ var init_platform_procedures = __esm({
3590
3594
  title: "Chain of command \u2014 who talks to whom",
3591
3595
  domain: "workflow",
3592
3596
  priority: "p0",
3593
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3597
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3594
3598
  },
3595
3599
  {
3596
3600
  title: "Single dispatch path \u2014 create_task only",
@@ -4262,7 +4266,11 @@ async function searchMemories(queryVector, agentId, options) {
4262
4266
  sql += ` AND timestamp >= ?`;
4263
4267
  args.push(options.since);
4264
4268
  }
4265
- if (options?.memoryType) {
4269
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4270
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4271
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4272
+ args.push(...uniqueTypes);
4273
+ } else if (options?.memoryType) {
4266
4274
  sql += ` AND memory_type = ?`;
4267
4275
  args.push(options.memoryType);
4268
4276
  }
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
6
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
7
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
8
  }) : x)(function(x) {
@@ -14,6 +16,15 @@ var __export = (target, all) => {
14
16
  for (var name in all)
15
17
  __defProp(target, name, { get: all[name], enumerable: true });
16
18
  };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
+ }
25
+ return to;
26
+ };
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
17
28
 
18
29
  // src/types/memory.ts
19
30
  var EMBEDDING_DIM;
@@ -118,6 +129,21 @@ var init_secure_files = __esm({
118
129
  });
119
130
 
120
131
  // src/lib/config.ts
132
+ var config_exports = {};
133
+ __export(config_exports, {
134
+ CONFIG_MIGRATIONS: () => CONFIG_MIGRATIONS,
135
+ CONFIG_PATH: () => CONFIG_PATH,
136
+ CURRENT_CONFIG_VERSION: () => CURRENT_CONFIG_VERSION,
137
+ DB_PATH: () => DB_PATH,
138
+ EXE_AI_DIR: () => EXE_AI_DIR,
139
+ LEGACY_LANCE_PATH: () => LEGACY_LANCE_PATH,
140
+ MODELS_DIR: () => MODELS_DIR,
141
+ loadConfig: () => loadConfig,
142
+ loadConfigFrom: () => loadConfigFrom,
143
+ loadConfigSync: () => loadConfigSync,
144
+ migrateConfig: () => migrateConfig,
145
+ saveConfig: () => saveConfig
146
+ });
121
147
  import { readFile, writeFile } from "fs/promises";
122
148
  import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
123
149
  import path from "path";
@@ -221,6 +247,46 @@ async function loadConfig() {
221
247
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
222
248
  }
223
249
  }
250
+ function loadConfigSync() {
251
+ const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
252
+ const configPath = path.join(dir, "config.json");
253
+ if (!existsSync2(configPath)) {
254
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
255
+ }
256
+ try {
257
+ const raw = readFileSync(configPath, "utf-8");
258
+ let parsed = JSON.parse(raw);
259
+ parsed = migrateLegacyConfig(parsed);
260
+ const { config: migratedCfg } = migrateConfig(parsed);
261
+ normalizeScalingRoadmap(migratedCfg);
262
+ normalizeSessionLifecycle(migratedCfg);
263
+ normalizeAutoUpdate(migratedCfg);
264
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
265
+ } catch {
266
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
267
+ }
268
+ }
269
+ async function saveConfig(config) {
270
+ const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
271
+ await ensurePrivateDir(dir);
272
+ const configPath = path.join(dir, "config.json");
273
+ await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
274
+ await enforcePrivateFile(configPath);
275
+ }
276
+ async function loadConfigFrom(configPath) {
277
+ const raw = await readFile(configPath, "utf-8");
278
+ try {
279
+ let parsed = JSON.parse(raw);
280
+ parsed = migrateLegacyConfig(parsed);
281
+ const { config: migratedCfg } = migrateConfig(parsed);
282
+ normalizeScalingRoadmap(migratedCfg);
283
+ normalizeSessionLifecycle(migratedCfg);
284
+ normalizeAutoUpdate(migratedCfg);
285
+ return { ...DEFAULT_CONFIG, ...migratedCfg };
286
+ } catch {
287
+ return { ...DEFAULT_CONFIG };
288
+ }
289
+ }
224
290
  var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
225
291
  var init_config = __esm({
226
292
  "src/lib/config.ts"() {
@@ -3279,7 +3345,7 @@ var init_platform_procedures = __esm({
3279
3345
  title: "Chain of command \u2014 who talks to whom",
3280
3346
  domain: "workflow",
3281
3347
  priority: "p0",
3282
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3348
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3283
3349
  },
3284
3350
  {
3285
3351
  title: "Single dispatch path \u2014 create_task only",
@@ -3530,8 +3596,9 @@ function personalizePrompt(prompt, templateName, actualName) {
3530
3596
  return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
3531
3597
  }
3532
3598
  function renderClientCOOTemplate(vars) {
3599
+ const resolved = { ...vars, title: vars.title || "Chief Operating Officer" };
3533
3600
  for (const key of CLIENT_COO_PLACEHOLDERS) {
3534
- const value = vars[key];
3601
+ const value = resolved[key];
3535
3602
  if (typeof value !== "string" || value.length === 0) {
3536
3603
  throw new Error(
3537
3604
  `renderClientCOOTemplate: missing required variable "${key}"`
@@ -3540,7 +3607,7 @@ function renderClientCOOTemplate(vars) {
3540
3607
  }
3541
3608
  let out = CLIENT_COO_TEMPLATE;
3542
3609
  for (const key of CLIENT_COO_PLACEHOLDERS) {
3543
- out = out.split(`{{${key}}}`).join(vars[key]);
3610
+ out = out.split(`{{${key}}}`).join(resolved[key]);
3544
3611
  }
3545
3612
  if (vars.industry_context) {
3546
3613
  out += "\n" + vars.industry_context;
@@ -4017,7 +4084,7 @@ created_by: system
4017
4084
  ---
4018
4085
  ## Identity
4019
4086
 
4020
- You are {{agent_name}}, the Chief Operating Officer at {{company_name}}.
4087
+ You are {{agent_name}}, the {{title}} at {{company_name}}.
4021
4088
 
4022
4089
  You are {{founder_name}}'s most reliable teammate in business \u2014 the knowledgeable older sibling who has been through it all. You have seen projects succeed and fail. You know what matters and what is noise. You do not get anxious about problems; you see them coming, stay calm, and handle them.
4023
4090
 
@@ -4104,7 +4171,8 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
4104
4171
  CLIENT_COO_PLACEHOLDERS = [
4105
4172
  "agent_name",
4106
4173
  "company_name",
4107
- "founder_name"
4174
+ "founder_name",
4175
+ "title"
4108
4176
  ];
4109
4177
  }
4110
4178
  });
@@ -4682,6 +4750,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
4682
4750
  }
4683
4751
  }
4684
4752
  function schedulePostWriteMemoryHygiene(memoryIds) {
4753
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
4685
4754
  if (memoryIds.length === 0) return;
4686
4755
  const run = () => {
4687
4756
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -5001,7 +5070,16 @@ var BEHAVIORS_EXPORT_DIR = path9.join(
5001
5070
  "behaviors-export"
5002
5071
  );
5003
5072
  var STALE_EXPORT_AGE_MS = 60 * 60 * 1e3;
5004
- var EXPORT_BEHAVIOR_LIMIT = 30;
5073
+ var DEFAULT_BEHAVIOR_LIMIT = 30;
5074
+ function getBehaviorLimit() {
5075
+ try {
5076
+ const { loadConfigSync: loadConfigSync2 } = (init_config(), __toCommonJS(config_exports));
5077
+ const cfg = loadConfigSync2();
5078
+ return cfg.behaviorExportLimit ?? DEFAULT_BEHAVIOR_LIMIT;
5079
+ } catch {
5080
+ return DEFAULT_BEHAVIOR_LIMIT;
5081
+ }
5082
+ }
5005
5083
  function sweepStaleBehaviorExports(now = Date.now()) {
5006
5084
  if (!existsSync9(BEHAVIORS_EXPORT_DIR)) return;
5007
5085
  let entries;
@@ -5055,7 +5133,7 @@ function exportFilePath(agentId, projectName, sessionKey) {
5055
5133
  async function exportBehaviorsForAgent(agentId, projectName, sessionKey) {
5056
5134
  mkdirSync3(BEHAVIORS_EXPORT_DIR, { recursive: true });
5057
5135
  sweepStaleBehaviorExports();
5058
- const behaviors = await listBehaviors(agentId, projectName, EXPORT_BEHAVIOR_LIMIT);
5136
+ const behaviors = await listBehaviors(agentId, projectName, getBehaviorLimit());
5059
5137
  if (behaviors.length === 0) return null;
5060
5138
  const body = renderBehaviorExport(behaviors);
5061
5139
  const target = exportFilePath(agentId, projectName, sessionKey);
@@ -1266,6 +1266,7 @@ __export(installer_exports, {
1266
1266
  });
1267
1267
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
1268
1268
  import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync7, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
1269
+ import { createHash as createHash2 } from "crypto";
1269
1270
  import path11 from "path";
1270
1271
  import os7 from "os";
1271
1272
  import { execSync as execSync2 } from "child_process";
@@ -1950,7 +1951,30 @@ function setupTmux(home) {
1950
1951
  return;
1951
1952
  }
1952
1953
  mkdirSync6(exeDir, { recursive: true });
1953
- copyFileSync(assetPath, exeTmuxConf);
1954
+ if (existsSync11(exeTmuxConf)) {
1955
+ const currentContent = readFileSync9(exeTmuxConf, "utf8");
1956
+ const newContent = readFileSync9(assetPath, "utf8");
1957
+ const currentHash = createHash2("sha256").update(currentContent).digest("hex");
1958
+ const newHash = createHash2("sha256").update(newContent).digest("hex");
1959
+ if (currentHash !== newHash) {
1960
+ const shippedPath = path11.join(exeDir, ".tmux.conf.shipped-hash");
1961
+ const lastShippedHash = existsSync11(shippedPath) ? readFileSync9(shippedPath, "utf8").trim() : "";
1962
+ if (lastShippedHash && currentHash !== lastShippedHash) {
1963
+ process.stderr.write("exe-os: tmux config has user customizations \u2014 skipping overwrite\n");
1964
+ } else {
1965
+ copyFileSync(assetPath, exeTmuxConf);
1966
+ process.stderr.write("exe-os: tmux config updated\n");
1967
+ }
1968
+ writeFileSync7(shippedPath, newHash, "utf8");
1969
+ } else {
1970
+ process.stderr.write("exe-os: tmux config already up to date\n");
1971
+ }
1972
+ } else {
1973
+ copyFileSync(assetPath, exeTmuxConf);
1974
+ const newContent = readFileSync9(assetPath, "utf8");
1975
+ const newHash = createHash2("sha256").update(newContent).digest("hex");
1976
+ writeFileSync7(path11.join(exeDir, ".tmux.conf.shipped-hash"), newHash, "utf8");
1977
+ }
1954
1978
  if (existsSync11(userTmuxConf)) {
1955
1979
  const existing = readFileSync9(userTmuxConf, "utf8");
1956
1980
  if (!existing.includes(sourceLine)) {
@@ -2243,7 +2267,7 @@ var PLATFORM_PROCEDURES = [
2243
2267
  title: "Chain of command \u2014 who talks to whom",
2244
2268
  domain: "workflow",
2245
2269
  priority: "p0",
2246
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
2270
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
2247
2271
  },
2248
2272
  {
2249
2273
  title: "Single dispatch path \u2014 create_task only",
@@ -3473,6 +3473,9 @@ function classifyMemoryType(input) {
3473
3473
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3474
3474
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3475
3475
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3476
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3477
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3478
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3476
3479
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3477
3480
  if (tool === "store_memory" || tool === "manual") return "observation";
3478
3481
  return "raw";
@@ -3615,6 +3618,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3615
3618
  }
3616
3619
  }
3617
3620
  function schedulePostWriteMemoryHygiene(memoryIds) {
3621
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3618
3622
  if (memoryIds.length === 0) return;
3619
3623
  const run = () => {
3620
3624
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4009,7 +4013,7 @@ var init_platform_procedures = __esm({
4009
4013
  title: "Chain of command \u2014 who talks to whom",
4010
4014
  domain: "workflow",
4011
4015
  priority: "p0",
4012
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4016
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4013
4017
  },
4014
4018
  {
4015
4019
  title: "Single dispatch path \u2014 create_task only",
@@ -4681,7 +4685,11 @@ async function searchMemories(queryVector, agentId, options) {
4681
4685
  sql += ` AND timestamp >= ?`;
4682
4686
  args.push(options.since);
4683
4687
  }
4684
- if (options?.memoryType) {
4688
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4689
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4690
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4691
+ args.push(...uniqueTypes);
4692
+ } else if (options?.memoryType) {
4685
4693
  sql += ` AND memory_type = ?`;
4686
4694
  args.push(options.memoryType);
4687
4695
  }
@@ -3539,6 +3539,9 @@ function classifyMemoryType(input) {
3539
3539
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3540
3540
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3541
3541
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3542
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3543
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3544
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3542
3545
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3543
3546
  if (tool === "store_memory" || tool === "manual") return "observation";
3544
3547
  return "raw";
@@ -3681,6 +3684,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3681
3684
  }
3682
3685
  }
3683
3686
  function schedulePostWriteMemoryHygiene(memoryIds) {
3687
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3684
3688
  if (memoryIds.length === 0) return;
3685
3689
  const run = () => {
3686
3690
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4075,7 +4079,7 @@ var init_platform_procedures = __esm({
4075
4079
  title: "Chain of command \u2014 who talks to whom",
4076
4080
  domain: "workflow",
4077
4081
  priority: "p0",
4078
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4082
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4079
4083
  },
4080
4084
  {
4081
4085
  title: "Single dispatch path \u2014 create_task only",
@@ -4747,7 +4751,11 @@ async function searchMemories(queryVector, agentId, options) {
4747
4751
  sql += ` AND timestamp >= ?`;
4748
4752
  args.push(options.since);
4749
4753
  }
4750
- if (options?.memoryType) {
4754
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4755
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4756
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4757
+ args.push(...uniqueTypes);
4758
+ } else if (options?.memoryType) {
4751
4759
  sql += ` AND memory_type = ?`;
4752
4760
  args.push(options.memoryType);
4753
4761
  }
@@ -3578,6 +3578,9 @@ function classifyMemoryType(input) {
3578
3578
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3579
3579
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3580
3580
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3581
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3582
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3583
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3581
3584
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3582
3585
  if (tool === "store_memory" || tool === "manual") return "observation";
3583
3586
  return "raw";
@@ -3720,6 +3723,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3720
3723
  }
3721
3724
  }
3722
3725
  function schedulePostWriteMemoryHygiene(memoryIds) {
3726
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3723
3727
  if (memoryIds.length === 0) return;
3724
3728
  const run = () => {
3725
3729
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4114,7 +4118,7 @@ var init_platform_procedures = __esm({
4114
4118
  title: "Chain of command \u2014 who talks to whom",
4115
4119
  domain: "workflow",
4116
4120
  priority: "p0",
4117
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4121
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4118
4122
  },
4119
4123
  {
4120
4124
  title: "Single dispatch path \u2014 create_task only",
@@ -4786,7 +4790,11 @@ async function searchMemories(queryVector, agentId, options) {
4786
4790
  sql += ` AND timestamp >= ?`;
4787
4791
  args.push(options.since);
4788
4792
  }
4789
- if (options?.memoryType) {
4793
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4794
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4795
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4796
+ args.push(...uniqueTypes);
4797
+ } else if (options?.memoryType) {
4790
4798
  sql += ` AND memory_type = ?`;
4791
4799
  args.push(options.memoryType);
4792
4800
  }
@@ -2593,7 +2593,7 @@ var PLATFORM_PROCEDURES = [
2593
2593
  title: "Chain of command \u2014 who talks to whom",
2594
2594
  domain: "workflow",
2595
2595
  priority: "p0",
2596
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
2596
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
2597
2597
  },
2598
2598
  {
2599
2599
  title: "Single dispatch path \u2014 create_task only",
@@ -3068,6 +3068,9 @@ function classifyMemoryType(input) {
3068
3068
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3069
3069
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3070
3070
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3071
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3072
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3073
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3071
3074
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3072
3075
  if (tool === "store_memory" || tool === "manual") return "observation";
3073
3076
  return "raw";
@@ -3210,6 +3213,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3210
3213
  }
3211
3214
  }
3212
3215
  function schedulePostWriteMemoryHygiene(memoryIds) {
3216
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3213
3217
  if (memoryIds.length === 0) return;
3214
3218
  const run = () => {
3215
3219
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3604,7 +3608,7 @@ var init_platform_procedures = __esm({
3604
3608
  title: "Chain of command \u2014 who talks to whom",
3605
3609
  domain: "workflow",
3606
3610
  priority: "p0",
3607
- content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3611
+ content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3608
3612
  },
3609
3613
  {
3610
3614
  title: "Single dispatch path \u2014 create_task only",
@@ -4276,7 +4280,11 @@ async function searchMemories(queryVector, agentId, options) {
4276
4280
  sql += ` AND timestamp >= ?`;
4277
4281
  args.push(options.since);
4278
4282
  }
4279
- if (options?.memoryType) {
4283
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4284
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4285
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4286
+ args.push(...uniqueTypes);
4287
+ } else if (options?.memoryType) {
4280
4288
  sql += ` AND memory_type = ?`;
4281
4289
  args.push(options.memoryType);
4282
4290
  }