@askexenow/exe-os 0.9.35 → 0.9.36

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 (66) hide show
  1. package/dist/bin/backfill-conversations.js +2 -1
  2. package/dist/bin/backfill-responses.js +2 -1
  3. package/dist/bin/backfill-vectors.js +1 -1
  4. package/dist/bin/cleanup-stale-review-tasks.js +7 -2
  5. package/dist/bin/cli.js +45 -14
  6. package/dist/bin/exe-agent.js +1 -1
  7. package/dist/bin/exe-assign.js +7 -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 +7 -2
  11. package/dist/bin/exe-doctor.js +1 -1
  12. package/dist/bin/exe-export-behaviors.js +84 -4
  13. package/dist/bin/exe-forget.js +28 -11
  14. package/dist/bin/exe-gateway.js +7 -2
  15. package/dist/bin/exe-heartbeat.js +7 -2
  16. package/dist/bin/exe-kill.js +7 -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 +7 -2
  20. package/dist/bin/exe-pending-notifications.js +7 -2
  21. package/dist/bin/exe-pending-reviews.js +7 -2
  22. package/dist/bin/exe-rename.js +1 -1
  23. package/dist/bin/exe-review.js +7 -2
  24. package/dist/bin/exe-search.js +29 -11
  25. package/dist/bin/exe-session-cleanup.js +7 -2
  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 +7 -2
  29. package/dist/bin/exe-team.js +7 -2
  30. package/dist/bin/git-sweep.js +7 -2
  31. package/dist/bin/graph-backfill.js +2 -1
  32. package/dist/bin/graph-export.js +7 -2
  33. package/dist/bin/install.js +25 -1
  34. package/dist/bin/intercom-check.js +7 -2
  35. package/dist/bin/scan-tasks.js +7 -2
  36. package/dist/bin/setup.js +7 -5
  37. package/dist/bin/shard-migrate.js +2 -1
  38. package/dist/gateway/index.js +7 -2
  39. package/dist/hooks/bug-report-worker.js +7 -2
  40. package/dist/hooks/codex-stop-task-finalizer.js +7 -2
  41. package/dist/hooks/commit-complete.js +7 -2
  42. package/dist/hooks/error-recall.js +29 -11
  43. package/dist/hooks/ingest.js +7 -2
  44. package/dist/hooks/instructions-loaded.js +7 -2
  45. package/dist/hooks/notification.js +7 -2
  46. package/dist/hooks/post-compact.js +7 -2
  47. package/dist/hooks/post-tool-combined.js +29 -11
  48. package/dist/hooks/pre-compact.js +7 -2
  49. package/dist/hooks/pre-tool-use.js +17 -8
  50. package/dist/hooks/prompt-submit.js +124 -12
  51. package/dist/hooks/session-end.js +7 -2
  52. package/dist/hooks/session-start.js +207 -38
  53. package/dist/hooks/stop.js +7 -2
  54. package/dist/hooks/subagent-stop.js +7 -2
  55. package/dist/hooks/summary-worker.js +1 -1
  56. package/dist/index.js +7 -2
  57. package/dist/lib/employee-templates.js +7 -5
  58. package/dist/lib/exe-daemon.js +115 -26
  59. package/dist/lib/hybrid-search.js +29 -11
  60. package/dist/lib/schedules.js +1 -1
  61. package/dist/lib/store.js +7 -2
  62. package/dist/mcp/server.js +109 -26
  63. package/dist/runtime/index.js +7 -2
  64. package/dist/tui/App.js +7 -2
  65. package/package.json +1 -1
  66. package/src/commands/exe/save.md +48 -0
@@ -129,6 +129,21 @@ var init_secure_files = __esm({
129
129
  });
130
130
 
131
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
+ });
132
147
  import { readFile, writeFile } from "fs/promises";
133
148
  import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
134
149
  import path from "path";
@@ -232,6 +247,46 @@ async function loadConfig() {
232
247
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
233
248
  }
234
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
+ }
235
290
  var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
236
291
  var init_config = __esm({
237
292
  "src/lib/config.ts"() {
@@ -2967,7 +3022,7 @@ var init_platform_procedures = __esm({
2967
3022
  title: "Chain of command \u2014 who talks to whom",
2968
3023
  domain: "workflow",
2969
3024
  priority: "p0",
2970
- 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."
3025
+ 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."
2971
3026
  },
2972
3027
  {
2973
3028
  title: "Single dispatch path \u2014 create_task only",
@@ -3521,6 +3576,7 @@ var init_preferences = __esm({
3521
3576
  // src/adapters/claude/installer.ts
3522
3577
  import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdir } from "fs/promises";
3523
3578
  import { existsSync as existsSync11, readFileSync as readFileSync7, writeFileSync as writeFileSync6, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
3579
+ import { createHash as createHash2 } from "crypto";
3524
3580
  import path12 from "path";
3525
3581
  import os9 from "os";
3526
3582
  import { execSync as execSync5 } from "child_process";
@@ -4287,6 +4343,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
4287
4343
  }
4288
4344
  }
4289
4345
  function schedulePostWriteMemoryHygiene(memoryIds) {
4346
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
4290
4347
  if (memoryIds.length === 0) return;
4291
4348
  const run = () => {
4292
4349
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4606,7 +4663,16 @@ var BEHAVIORS_EXPORT_DIR = path8.join(
4606
4663
  "behaviors-export"
4607
4664
  );
4608
4665
  var STALE_EXPORT_AGE_MS = 60 * 60 * 1e3;
4609
- var EXPORT_BEHAVIOR_LIMIT = 30;
4666
+ var DEFAULT_BEHAVIOR_LIMIT = 30;
4667
+ function getBehaviorLimit() {
4668
+ try {
4669
+ const { loadConfigSync: loadConfigSync2 } = (init_config(), __toCommonJS(config_exports));
4670
+ const cfg = loadConfigSync2();
4671
+ return cfg.behaviorExportLimit ?? DEFAULT_BEHAVIOR_LIMIT;
4672
+ } catch {
4673
+ return DEFAULT_BEHAVIOR_LIMIT;
4674
+ }
4675
+ }
4610
4676
  function sweepStaleBehaviorExports(now = Date.now()) {
4611
4677
  if (!existsSync8(BEHAVIORS_EXPORT_DIR)) return;
4612
4678
  let entries;
@@ -4660,7 +4726,7 @@ function exportFilePath(agentId, projectName, sessionKey) {
4660
4726
  async function exportBehaviorsForAgent(agentId, projectName, sessionKey) {
4661
4727
  mkdirSync3(BEHAVIORS_EXPORT_DIR, { recursive: true });
4662
4728
  sweepStaleBehaviorExports();
4663
- const behaviors = await listBehaviors(agentId, projectName, EXPORT_BEHAVIOR_LIMIT);
4729
+ const behaviors = await listBehaviors(agentId, projectName, getBehaviorLimit());
4664
4730
  if (behaviors.length === 0) return null;
4665
4731
  const body = renderBehaviorExport(behaviors);
4666
4732
  const target = exportFilePath(agentId, projectName, sessionKey);
@@ -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"() {
@@ -2956,7 +3022,7 @@ var init_platform_procedures = __esm({
2956
3022
  title: "Chain of command \u2014 who talks to whom",
2957
3023
  domain: "workflow",
2958
3024
  priority: "p0",
2959
- 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."
3025
+ 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."
2960
3026
  },
2961
3027
  {
2962
3028
  title: "Single dispatch path \u2014 create_task only",
@@ -3499,6 +3565,7 @@ var init_preferences = __esm({
3499
3565
  // src/adapters/claude/installer.ts
3500
3566
  import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdir } from "fs/promises";
3501
3567
  import { existsSync as existsSync11, readFileSync as readFileSync7, writeFileSync as writeFileSync6, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
3568
+ import { createHash as createHash2 } from "crypto";
3502
3569
  import path12 from "path";
3503
3570
  import os9 from "os";
3504
3571
  import { execSync as execSync5 } from "child_process";
@@ -4141,6 +4208,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
4141
4208
  }
4142
4209
  }
4143
4210
  function schedulePostWriteMemoryHygiene(memoryIds) {
4211
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
4144
4212
  if (memoryIds.length === 0) return;
4145
4213
  const run = () => {
4146
4214
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4460,7 +4528,16 @@ var BEHAVIORS_EXPORT_DIR = path8.join(
4460
4528
  "behaviors-export"
4461
4529
  );
4462
4530
  var STALE_EXPORT_AGE_MS = 60 * 60 * 1e3;
4463
- var EXPORT_BEHAVIOR_LIMIT = 30;
4531
+ var DEFAULT_BEHAVIOR_LIMIT = 30;
4532
+ function getBehaviorLimit() {
4533
+ try {
4534
+ const { loadConfigSync: loadConfigSync2 } = (init_config(), __toCommonJS(config_exports));
4535
+ const cfg = loadConfigSync2();
4536
+ return cfg.behaviorExportLimit ?? DEFAULT_BEHAVIOR_LIMIT;
4537
+ } catch {
4538
+ return DEFAULT_BEHAVIOR_LIMIT;
4539
+ }
4540
+ }
4464
4541
  function sweepStaleBehaviorExports(now = Date.now()) {
4465
4542
  if (!existsSync8(BEHAVIORS_EXPORT_DIR)) return;
4466
4543
  let entries;
@@ -4514,7 +4591,7 @@ function exportFilePath(agentId, projectName, sessionKey) {
4514
4591
  async function exportBehaviorsForAgent(agentId, projectName, sessionKey) {
4515
4592
  mkdirSync3(BEHAVIORS_EXPORT_DIR, { recursive: true });
4516
4593
  sweepStaleBehaviorExports();
4517
- const behaviors = await listBehaviors(agentId, projectName, EXPORT_BEHAVIOR_LIMIT);
4594
+ const behaviors = await listBehaviors(agentId, projectName, getBehaviorLimit());
4518
4595
  if (behaviors.length === 0) return null;
4519
4596
  const body = renderBehaviorExport(behaviors);
4520
4597
  const target = exportFilePath(agentId, projectName, sessionKey);
@@ -3218,6 +3218,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3218
3218
  }
3219
3219
  }
3220
3220
  function schedulePostWriteMemoryHygiene(memoryIds) {
3221
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3221
3222
  if (memoryIds.length === 0) return;
3222
3223
  const run = () => {
3223
3224
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3612,7 +3613,7 @@ var init_platform_procedures = __esm({
3612
3613
  title: "Chain of command \u2014 who talks to whom",
3613
3614
  domain: "workflow",
3614
3615
  priority: "p0",
3615
- 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."
3616
+ 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."
3616
3617
  },
3617
3618
  {
3618
3619
  title: "Single dispatch path \u2014 create_task only",
@@ -4284,7 +4285,11 @@ async function searchMemories(queryVector, agentId, options) {
4284
4285
  sql += ` AND timestamp >= ?`;
4285
4286
  args.push(options.since);
4286
4287
  }
4287
- if (options?.memoryType) {
4288
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4289
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4290
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4291
+ args.push(...uniqueTypes);
4292
+ } else if (options?.memoryType) {
4288
4293
  sql += ` AND memory_type = ?`;
4289
4294
  args.push(options.memoryType);
4290
4295
  }
@@ -3207,6 +3207,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3207
3207
  }
3208
3208
  }
3209
3209
  function schedulePostWriteMemoryHygiene(memoryIds) {
3210
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3210
3211
  if (memoryIds.length === 0) return;
3211
3212
  const run = () => {
3212
3213
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3601,7 +3602,7 @@ var init_platform_procedures = __esm({
3601
3602
  title: "Chain of command \u2014 who talks to whom",
3602
3603
  domain: "workflow",
3603
3604
  priority: "p0",
3604
- 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."
3605
+ 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."
3605
3606
  },
3606
3607
  {
3607
3608
  title: "Single dispatch path \u2014 create_task only",
@@ -4273,7 +4274,11 @@ async function searchMemories(queryVector, agentId, options) {
4273
4274
  sql += ` AND timestamp >= ?`;
4274
4275
  args.push(options.since);
4275
4276
  }
4276
- if (options?.memoryType) {
4277
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4278
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4279
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4280
+ args.push(...uniqueTypes);
4281
+ } else if (options?.memoryType) {
4277
4282
  sql += ` AND memory_type = ?`;
4278
4283
  args.push(options.memoryType);
4279
4284
  }
@@ -6830,6 +6830,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
6830
6830
  }
6831
6831
  }
6832
6832
  function schedulePostWriteMemoryHygiene(memoryIds) {
6833
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
6833
6834
  if (memoryIds.length === 0) return;
6834
6835
  const run = () => {
6835
6836
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -7224,7 +7225,7 @@ var init_platform_procedures = __esm({
7224
7225
  title: "Chain of command \u2014 who talks to whom",
7225
7226
  domain: "workflow",
7226
7227
  priority: "p0",
7227
- 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."
7228
+ 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."
7228
7229
  },
7229
7230
  {
7230
7231
  title: "Single dispatch path \u2014 create_task only",
@@ -7896,7 +7897,11 @@ async function searchMemories(queryVector, agentId, options) {
7896
7897
  sql += ` AND timestamp >= ?`;
7897
7898
  args2.push(options.since);
7898
7899
  }
7899
- if (options?.memoryType) {
7900
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
7901
+ const uniqueTypes = [...new Set(options.memoryTypes)];
7902
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
7903
+ args2.push(...uniqueTypes);
7904
+ } else if (options?.memoryType) {
7900
7905
  sql += ` AND memory_type = ?`;
7901
7906
  args2.push(options.memoryType);
7902
7907
  }
@@ -2945,7 +2945,7 @@ var init_platform_procedures = __esm({
2945
2945
  title: "Chain of command \u2014 who talks to whom",
2946
2946
  domain: "workflow",
2947
2947
  priority: "p0",
2948
- 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."
2948
+ 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."
2949
2949
  },
2950
2950
  {
2951
2951
  title: "Single dispatch path \u2014 create_task only",
@@ -3466,6 +3466,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3466
3466
  }
3467
3467
  }
3468
3468
  function schedulePostWriteMemoryHygiene(memoryIds) {
3469
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3469
3470
  if (memoryIds.length === 0) return;
3470
3471
  const run = () => {
3471
3472
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3196,6 +3196,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3196
3196
  }
3197
3197
  }
3198
3198
  function schedulePostWriteMemoryHygiene(memoryIds) {
3199
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3199
3200
  if (memoryIds.length === 0) return;
3200
3201
  const run = () => {
3201
3202
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3590,7 +3591,7 @@ var init_platform_procedures = __esm({
3590
3591
  title: "Chain of command \u2014 who talks to whom",
3591
3592
  domain: "workflow",
3592
3593
  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."
3594
+ 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
3595
  },
3595
3596
  {
3596
3597
  title: "Single dispatch path \u2014 create_task only",
@@ -4262,7 +4263,11 @@ async function searchMemories(queryVector, agentId, options) {
4262
4263
  sql += ` AND timestamp >= ?`;
4263
4264
  args.push(options.since);
4264
4265
  }
4265
- if (options?.memoryType) {
4266
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4267
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4268
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4269
+ args.push(...uniqueTypes);
4270
+ } else if (options?.memoryType) {
4266
4271
  sql += ` AND memory_type = ?`;
4267
4272
  args.push(options.memoryType);
4268
4273
  }
@@ -610,6 +610,7 @@ var init_preferences = __esm({
610
610
  // src/adapters/claude/installer.ts
611
611
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
612
612
  import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4, copyFileSync, mkdirSync as mkdirSync3 } from "fs";
613
+ import { createHash } from "crypto";
613
614
  import path6 from "path";
614
615
  import os5 from "os";
615
616
  import { execSync as execSync2 } from "child_process";
@@ -1294,7 +1295,30 @@ function setupTmux(home) {
1294
1295
  return;
1295
1296
  }
1296
1297
  mkdirSync3(exeDir, { recursive: true });
1297
- copyFileSync(assetPath, exeTmuxConf);
1298
+ if (existsSync7(exeTmuxConf)) {
1299
+ const currentContent = readFileSync5(exeTmuxConf, "utf8");
1300
+ const newContent = readFileSync5(assetPath, "utf8");
1301
+ const currentHash = createHash("sha256").update(currentContent).digest("hex");
1302
+ const newHash = createHash("sha256").update(newContent).digest("hex");
1303
+ if (currentHash !== newHash) {
1304
+ const shippedPath = path6.join(exeDir, ".tmux.conf.shipped-hash");
1305
+ const lastShippedHash = existsSync7(shippedPath) ? readFileSync5(shippedPath, "utf8").trim() : "";
1306
+ if (lastShippedHash && currentHash !== lastShippedHash) {
1307
+ process.stderr.write("exe-os: tmux config has user customizations \u2014 skipping overwrite\n");
1308
+ } else {
1309
+ copyFileSync(assetPath, exeTmuxConf);
1310
+ process.stderr.write("exe-os: tmux config updated\n");
1311
+ }
1312
+ writeFileSync4(shippedPath, newHash, "utf8");
1313
+ } else {
1314
+ process.stderr.write("exe-os: tmux config already up to date\n");
1315
+ }
1316
+ } else {
1317
+ copyFileSync(assetPath, exeTmuxConf);
1318
+ const newContent = readFileSync5(assetPath, "utf8");
1319
+ const newHash = createHash("sha256").update(newContent).digest("hex");
1320
+ writeFileSync4(path6.join(exeDir, ".tmux.conf.shipped-hash"), newHash, "utf8");
1321
+ }
1298
1322
  if (existsSync7(userTmuxConf)) {
1299
1323
  const existing = readFileSync5(userTmuxConf, "utf8");
1300
1324
  if (!existing.includes(sourceLine)) {
@@ -3295,6 +3295,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3295
3295
  }
3296
3296
  }
3297
3297
  function schedulePostWriteMemoryHygiene(memoryIds) {
3298
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3298
3299
  if (memoryIds.length === 0) return;
3299
3300
  const run = () => {
3300
3301
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3689,7 +3690,7 @@ var init_platform_procedures = __esm({
3689
3690
  title: "Chain of command \u2014 who talks to whom",
3690
3691
  domain: "workflow",
3691
3692
  priority: "p0",
3692
- 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."
3693
+ 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."
3693
3694
  },
3694
3695
  {
3695
3696
  title: "Single dispatch path \u2014 create_task only",
@@ -4361,7 +4362,11 @@ async function searchMemories(queryVector, agentId, options) {
4361
4362
  sql += ` AND timestamp >= ?`;
4362
4363
  args.push(options.since);
4363
4364
  }
4364
- if (options?.memoryType) {
4365
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4366
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4367
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4368
+ args.push(...uniqueTypes);
4369
+ } else if (options?.memoryType) {
4365
4370
  sql += ` AND memory_type = ?`;
4366
4371
  args.push(options.memoryType);
4367
4372
  }
@@ -6901,6 +6901,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
6901
6901
  }
6902
6902
  }
6903
6903
  function schedulePostWriteMemoryHygiene(memoryIds) {
6904
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
6904
6905
  if (memoryIds.length === 0) return;
6905
6906
  const run = () => {
6906
6907
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -7295,7 +7296,7 @@ var init_platform_procedures = __esm({
7295
7296
  title: "Chain of command \u2014 who talks to whom",
7296
7297
  domain: "workflow",
7297
7298
  priority: "p0",
7298
- 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."
7299
+ 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."
7299
7300
  },
7300
7301
  {
7301
7302
  title: "Single dispatch path \u2014 create_task only",
@@ -7967,7 +7968,11 @@ async function searchMemories(queryVector, agentId, options) {
7967
7968
  sql += ` AND timestamp >= ?`;
7968
7969
  args.push(options.since);
7969
7970
  }
7970
- if (options?.memoryType) {
7971
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
7972
+ const uniqueTypes = [...new Set(options.memoryTypes)];
7973
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
7974
+ args.push(...uniqueTypes);
7975
+ } else if (options?.memoryType) {
7971
7976
  sql += ` AND memory_type = ?`;
7972
7977
  args.push(options.memoryType);
7973
7978
  }
package/dist/bin/setup.js CHANGED
@@ -5659,7 +5659,7 @@ var init_platform_procedures = __esm({
5659
5659
  title: "Chain of command \u2014 who talks to whom",
5660
5660
  domain: "workflow",
5661
5661
  priority: "p0",
5662
- 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."
5662
+ 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."
5663
5663
  },
5664
5664
  {
5665
5665
  title: "Single dispatch path \u2014 create_task only",
@@ -5864,8 +5864,9 @@ function personalizePrompt(prompt, templateName, actualName) {
5864
5864
  return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
5865
5865
  }
5866
5866
  function renderClientCOOTemplate(vars) {
5867
+ const resolved = { ...vars, title: vars.title || "Chief Operating Officer" };
5867
5868
  for (const key of CLIENT_COO_PLACEHOLDERS) {
5868
- const value = vars[key];
5869
+ const value = resolved[key];
5869
5870
  if (typeof value !== "string" || value.length === 0) {
5870
5871
  throw new Error(
5871
5872
  `renderClientCOOTemplate: missing required variable "${key}"`
@@ -5874,7 +5875,7 @@ function renderClientCOOTemplate(vars) {
5874
5875
  }
5875
5876
  let out = CLIENT_COO_TEMPLATE;
5876
5877
  for (const key of CLIENT_COO_PLACEHOLDERS) {
5877
- out = out.split(`{{${key}}}`).join(vars[key]);
5878
+ out = out.split(`{{${key}}}`).join(resolved[key]);
5878
5879
  }
5879
5880
  if (vars.industry_context) {
5880
5881
  out += "\n" + vars.industry_context;
@@ -6351,7 +6352,7 @@ created_by: system
6351
6352
  ---
6352
6353
  ## Identity
6353
6354
 
6354
- You are {{agent_name}}, the Chief Operating Officer at {{company_name}}.
6355
+ You are {{agent_name}}, the {{title}} at {{company_name}}.
6355
6356
 
6356
6357
  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.
6357
6358
 
@@ -6438,7 +6439,8 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
6438
6439
  CLIENT_COO_PLACEHOLDERS = [
6439
6440
  "agent_name",
6440
6441
  "company_name",
6441
- "founder_name"
6442
+ "founder_name",
6443
+ "title"
6442
6444
  ];
6443
6445
  }
6444
6446
  });
@@ -2945,7 +2945,7 @@ var init_platform_procedures = __esm({
2945
2945
  title: "Chain of command \u2014 who talks to whom",
2946
2946
  domain: "workflow",
2947
2947
  priority: "p0",
2948
- 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."
2948
+ 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."
2949
2949
  },
2950
2950
  {
2951
2951
  title: "Single dispatch path \u2014 create_task only",
@@ -3466,6 +3466,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3466
3466
  }
3467
3467
  }
3468
3468
  function schedulePostWriteMemoryHygiene(memoryIds) {
3469
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3469
3470
  if (memoryIds.length === 0) return;
3470
3471
  const run = () => {
3471
3472
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3853,6 +3853,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3853
3853
  }
3854
3854
  }
3855
3855
  function schedulePostWriteMemoryHygiene(memoryIds) {
3856
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3856
3857
  if (memoryIds.length === 0) return;
3857
3858
  const run = () => {
3858
3859
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4247,7 +4248,7 @@ var init_platform_procedures = __esm({
4247
4248
  title: "Chain of command \u2014 who talks to whom",
4248
4249
  domain: "workflow",
4249
4250
  priority: "p0",
4250
- 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."
4251
+ 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."
4251
4252
  },
4252
4253
  {
4253
4254
  title: "Single dispatch path \u2014 create_task only",
@@ -4919,7 +4920,11 @@ async function searchMemories(queryVector, agentId, options) {
4919
4920
  sql += ` AND timestamp >= ?`;
4920
4921
  args.push(options.since);
4921
4922
  }
4922
- if (options?.memoryType) {
4923
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4924
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4925
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4926
+ args.push(...uniqueTypes);
4927
+ } else if (options?.memoryType) {
4923
4928
  sql += ` AND memory_type = ?`;
4924
4929
  args.push(options.memoryType);
4925
4930
  }
@@ -3595,6 +3595,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3595
3595
  }
3596
3596
  }
3597
3597
  function schedulePostWriteMemoryHygiene(memoryIds) {
3598
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3598
3599
  if (memoryIds.length === 0) return;
3599
3600
  const run = () => {
3600
3601
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3989,7 +3990,7 @@ var init_platform_procedures = __esm({
3989
3990
  title: "Chain of command \u2014 who talks to whom",
3990
3991
  domain: "workflow",
3991
3992
  priority: "p0",
3992
- 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."
3993
+ 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."
3993
3994
  },
3994
3995
  {
3995
3996
  title: "Single dispatch path \u2014 create_task only",
@@ -4661,7 +4662,11 @@ async function searchMemories(queryVector, agentId, options) {
4661
4662
  sql += ` AND timestamp >= ?`;
4662
4663
  args.push(options.since);
4663
4664
  }
4664
- if (options?.memoryType) {
4665
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4666
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4667
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4668
+ args.push(...uniqueTypes);
4669
+ } else if (options?.memoryType) {
4665
4670
  sql += ` AND memory_type = ?`;
4666
4671
  args.push(options.memoryType);
4667
4672
  }