@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
@@ -3085,7 +3085,7 @@ var init_platform_procedures = __esm({
3085
3085
  title: "Chain of command \u2014 who talks to whom",
3086
3086
  domain: "workflow",
3087
3087
  priority: "p0",
3088
- 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."
3088
+ 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."
3089
3089
  },
3090
3090
  {
3091
3091
  title: "Single dispatch path \u2014 create_task only",
@@ -3576,6 +3576,9 @@ function classifyMemoryType(input) {
3576
3576
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3577
3577
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3578
3578
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3579
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3580
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3581
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3579
3582
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3580
3583
  if (tool === "store_memory" || tool === "manual") return "observation";
3581
3584
  return "raw";
@@ -3718,6 +3721,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3718
3721
  }
3719
3722
  }
3720
3723
  function schedulePostWriteMemoryHygiene(memoryIds) {
3724
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3721
3725
  if (memoryIds.length === 0) return;
3722
3726
  const run = () => {
3723
3727
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3085,7 +3085,7 @@ var init_platform_procedures = __esm({
3085
3085
  title: "Chain of command \u2014 who talks to whom",
3086
3086
  domain: "workflow",
3087
3087
  priority: "p0",
3088
- 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."
3088
+ 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."
3089
3089
  },
3090
3090
  {
3091
3091
  title: "Single dispatch path \u2014 create_task only",
@@ -3575,6 +3575,9 @@ function classifyMemoryType(input) {
3575
3575
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3576
3576
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3577
3577
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3578
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3579
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3580
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3578
3581
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3579
3582
  if (tool === "store_memory" || tool === "manual") return "observation";
3580
3583
  return "raw";
@@ -3717,6 +3720,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3717
3720
  }
3718
3721
  }
3719
3722
  function schedulePostWriteMemoryHygiene(memoryIds) {
3723
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3720
3724
  if (memoryIds.length === 0) return;
3721
3725
  const run = () => {
3722
3726
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3081,7 +3081,7 @@ var init_platform_procedures = __esm({
3081
3081
  title: "Chain of command \u2014 who talks to whom",
3082
3082
  domain: "workflow",
3083
3083
  priority: "p0",
3084
- 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."
3084
+ 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."
3085
3085
  },
3086
3086
  {
3087
3087
  title: "Single dispatch path \u2014 create_task only",
@@ -3065,6 +3065,9 @@ function classifyMemoryType(input) {
3065
3065
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3066
3066
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3067
3067
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3068
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3069
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3070
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3068
3071
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3069
3072
  if (tool === "store_memory" || tool === "manual") return "observation";
3070
3073
  return "raw";
@@ -3207,6 +3210,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3207
3210
  }
3208
3211
  }
3209
3212
  function schedulePostWriteMemoryHygiene(memoryIds) {
3213
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3210
3214
  if (memoryIds.length === 0) return;
3211
3215
  const run = () => {
3212
3216
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3601,7 +3605,7 @@ var init_platform_procedures = __esm({
3601
3605
  title: "Chain of command \u2014 who talks to whom",
3602
3606
  domain: "workflow",
3603
3607
  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."
3608
+ 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
3609
  },
3606
3610
  {
3607
3611
  title: "Single dispatch path \u2014 create_task only",
@@ -4273,7 +4277,11 @@ async function searchMemories(queryVector, agentId, options) {
4273
4277
  sql += ` AND timestamp >= ?`;
4274
4278
  args.push(options.since);
4275
4279
  }
4276
- if (options?.memoryType) {
4280
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4281
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4282
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4283
+ args.push(...uniqueTypes);
4284
+ } else if (options?.memoryType) {
4277
4285
  sql += ` AND memory_type = ?`;
4278
4286
  args.push(options.memoryType);
4279
4287
  }
package/dist/bin/cli.js CHANGED
@@ -824,6 +824,7 @@ __export(installer_exports, {
824
824
  });
825
825
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
826
826
  import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4, copyFileSync, mkdirSync as mkdirSync3 } from "fs";
827
+ import { createHash } from "crypto";
827
828
  import path6 from "path";
828
829
  import os5 from "os";
829
830
  import { execSync as execSync2 } from "child_process";
@@ -1508,7 +1509,30 @@ function setupTmux(home) {
1508
1509
  return;
1509
1510
  }
1510
1511
  mkdirSync3(exeDir, { recursive: true });
1511
- copyFileSync(assetPath, exeTmuxConf);
1512
+ if (existsSync7(exeTmuxConf)) {
1513
+ const currentContent = readFileSync5(exeTmuxConf, "utf8");
1514
+ const newContent = readFileSync5(assetPath, "utf8");
1515
+ const currentHash = createHash("sha256").update(currentContent).digest("hex");
1516
+ const newHash = createHash("sha256").update(newContent).digest("hex");
1517
+ if (currentHash !== newHash) {
1518
+ const shippedPath = path6.join(exeDir, ".tmux.conf.shipped-hash");
1519
+ const lastShippedHash = existsSync7(shippedPath) ? readFileSync5(shippedPath, "utf8").trim() : "";
1520
+ if (lastShippedHash && currentHash !== lastShippedHash) {
1521
+ process.stderr.write("exe-os: tmux config has user customizations \u2014 skipping overwrite\n");
1522
+ } else {
1523
+ copyFileSync(assetPath, exeTmuxConf);
1524
+ process.stderr.write("exe-os: tmux config updated\n");
1525
+ }
1526
+ writeFileSync4(shippedPath, newHash, "utf8");
1527
+ } else {
1528
+ process.stderr.write("exe-os: tmux config already up to date\n");
1529
+ }
1530
+ } else {
1531
+ copyFileSync(assetPath, exeTmuxConf);
1532
+ const newContent = readFileSync5(assetPath, "utf8");
1533
+ const newHash = createHash("sha256").update(newContent).digest("hex");
1534
+ writeFileSync4(path6.join(exeDir, ".tmux.conf.shipped-hash"), newHash, "utf8");
1535
+ }
1512
1536
  if (existsSync7(userTmuxConf)) {
1513
1537
  const existing = readFileSync5(userTmuxConf, "utf8");
1514
1538
  if (!existing.includes(sourceLine)) {
@@ -6803,7 +6827,7 @@ var init_state_bus = __esm({
6803
6827
  });
6804
6828
 
6805
6829
  // src/lib/memory-write-governor.ts
6806
- import { createHash } from "crypto";
6830
+ import { createHash as createHash2 } from "crypto";
6807
6831
  function normalizeMemoryText(text) {
6808
6832
  return text.replace(/\r\n/g, "\n").replace(/[ \t]+$/gm, "").replace(/\n{4,}/g, "\n\n\n").trim();
6809
6833
  }
@@ -6815,6 +6839,9 @@ function classifyMemoryType(input) {
6815
6839
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
6816
6840
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
6817
6841
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
6842
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
6843
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
6844
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
6818
6845
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
6819
6846
  if (tool === "store_memory" || tool === "manual") return "observation";
6820
6847
  return "raw";
@@ -6835,7 +6862,7 @@ function shouldSkipEmbedding(input) {
6835
6862
  return false;
6836
6863
  }
6837
6864
  function hashMemoryContent(text) {
6838
- return createHash("sha256").update(normalizeMemoryText(text)).digest("hex");
6865
+ return createHash2("sha256").update(normalizeMemoryText(text)).digest("hex");
6839
6866
  }
6840
6867
  function scopedDedupArgs(input) {
6841
6868
  return [input.contentHash, input.agentId, input.projectName, input.memoryType];
@@ -6957,6 +6984,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
6957
6984
  }
6958
6985
  }
6959
6986
  function schedulePostWriteMemoryHygiene(memoryIds) {
6987
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
6960
6988
  if (memoryIds.length === 0) return;
6961
6989
  const run = () => {
6962
6990
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -7351,7 +7379,7 @@ var init_platform_procedures = __esm({
7351
7379
  title: "Chain of command \u2014 who talks to whom",
7352
7380
  domain: "workflow",
7353
7381
  priority: "p0",
7354
- 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."
7382
+ 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."
7355
7383
  },
7356
7384
  {
7357
7385
  title: "Single dispatch path \u2014 create_task only",
@@ -8023,7 +8051,11 @@ async function searchMemories(queryVector, agentId, options) {
8023
8051
  sql += ` AND timestamp >= ?`;
8024
8052
  args2.push(options.since);
8025
8053
  }
8026
- if (options?.memoryType) {
8054
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
8055
+ const uniqueTypes = [...new Set(options.memoryTypes)];
8056
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
8057
+ args2.push(...uniqueTypes);
8058
+ } else if (options?.memoryType) {
8027
8059
  sql += ` AND memory_type = ?`;
8028
8060
  args2.push(options.memoryType);
8029
8061
  }
@@ -9156,7 +9188,7 @@ __export(identity_exports, {
9156
9188
  import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
9157
9189
  import { readdirSync as readdirSync4 } from "fs";
9158
9190
  import path17 from "path";
9159
- import { createHash as createHash2 } from "crypto";
9191
+ import { createHash as createHash3 } from "crypto";
9160
9192
  function ensureDir() {
9161
9193
  if (!existsSync16(IDENTITY_DIR2)) {
9162
9194
  mkdirSync9(IDENTITY_DIR2, { recursive: true });
@@ -9200,7 +9232,7 @@ function parseFrontmatter(raw) {
9200
9232
  };
9201
9233
  }
9202
9234
  function contentHash(content) {
9203
- return createHash2("sha256").update(content).digest("hex").slice(0, 16);
9235
+ return createHash3("sha256").update(content).digest("hex").slice(0, 16);
9204
9236
  }
9205
9237
  function getIdentity(agentId) {
9206
9238
  const filePath = identityPath(agentId);
@@ -13797,8 +13829,9 @@ function personalizePrompt(prompt, templateName, actualName) {
13797
13829
  return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
13798
13830
  }
13799
13831
  function renderClientCOOTemplate(vars) {
13832
+ const resolved = { ...vars, title: vars.title || "Chief Operating Officer" };
13800
13833
  for (const key of CLIENT_COO_PLACEHOLDERS) {
13801
- const value = vars[key];
13834
+ const value = resolved[key];
13802
13835
  if (typeof value !== "string" || value.length === 0) {
13803
13836
  throw new Error(
13804
13837
  `renderClientCOOTemplate: missing required variable "${key}"`
@@ -13807,7 +13840,7 @@ function renderClientCOOTemplate(vars) {
13807
13840
  }
13808
13841
  let out = CLIENT_COO_TEMPLATE;
13809
13842
  for (const key of CLIENT_COO_PLACEHOLDERS) {
13810
- out = out.split(`{{${key}}}`).join(vars[key]);
13843
+ out = out.split(`{{${key}}}`).join(resolved[key]);
13811
13844
  }
13812
13845
  if (vars.industry_context) {
13813
13846
  out += "\n" + vars.industry_context;
@@ -14284,7 +14317,7 @@ created_by: system
14284
14317
  ---
14285
14318
  ## Identity
14286
14319
 
14287
- You are {{agent_name}}, the Chief Operating Officer at {{company_name}}.
14320
+ You are {{agent_name}}, the {{title}} at {{company_name}}.
14288
14321
 
14289
14322
  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.
14290
14323
 
@@ -14371,7 +14404,8 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
14371
14404
  CLIENT_COO_PLACEHOLDERS = [
14372
14405
  "agent_name",
14373
14406
  "company_name",
14374
- "founder_name"
14407
+ "founder_name",
14408
+ "title"
14375
14409
  ];
14376
14410
  }
14377
14411
  });
@@ -14579,7 +14613,7 @@ var init_exe_rename = __esm({
14579
14613
  // src/lib/model-downloader.ts
14580
14614
  import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync26, unlinkSync as unlinkSync12, renameSync as renameSync5 } from "fs";
14581
14615
  import { mkdir as mkdir6 } from "fs/promises";
14582
- import { createHash as createHash3 } from "crypto";
14616
+ import { createHash as createHash4 } from "crypto";
14583
14617
  import path32 from "path";
14584
14618
  async function downloadModel(opts) {
14585
14619
  const { destDir, onProgress, fetchFn = globalThis.fetch } = opts;
@@ -14607,7 +14641,7 @@ async function downloadModel(opts) {
14607
14641
  throw new Error(`Download failed: HTTP ${response.status}`);
14608
14642
  }
14609
14643
  const contentLength = Number(response.headers.get("content-length") ?? EXPECTED_SIZE);
14610
- const hash = createHash3("sha256");
14644
+ const hash = createHash4("sha256");
14611
14645
  const fileStream = createWriteStream(tmpPath);
14612
14646
  const reader = response.body.getReader();
14613
14647
  try {
@@ -14651,7 +14685,7 @@ Download attempt ${attempt} failed, retrying...
14651
14685
  }
14652
14686
  async function fileHash(filePath) {
14653
14687
  return new Promise((resolve, reject) => {
14654
- const hash = createHash3("sha256");
14688
+ const hash = createHash4("sha256");
14655
14689
  const stream = createReadStream2(filePath);
14656
14690
  stream.on("data", (chunk) => hash.update(chunk));
14657
14691
  stream.on("end", () => resolve(hash.digest("hex")));
@@ -1323,7 +1323,7 @@ var PLATFORM_PROCEDURES = [
1323
1323
  title: "Chain of command \u2014 who talks to whom",
1324
1324
  domain: "workflow",
1325
1325
  priority: "p0",
1326
- 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."
1326
+ 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."
1327
1327
  },
1328
1328
  {
1329
1329
  title: "Single dispatch path \u2014 create_task only",
@@ -3095,7 +3095,7 @@ var init_platform_procedures = __esm({
3095
3095
  title: "Chain of command \u2014 who talks to whom",
3096
3096
  domain: "workflow",
3097
3097
  priority: "p0",
3098
- 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."
3098
+ 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."
3099
3099
  },
3100
3100
  {
3101
3101
  title: "Single dispatch path \u2014 create_task only",
@@ -3723,6 +3723,9 @@ function classifyMemoryType(input) {
3723
3723
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3724
3724
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3725
3725
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3726
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3727
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3728
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3726
3729
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3727
3730
  if (tool === "store_memory" || tool === "manual") return "observation";
3728
3731
  return "raw";
@@ -3865,6 +3868,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3865
3868
  }
3866
3869
  }
3867
3870
  function schedulePostWriteMemoryHygiene(memoryIds) {
3871
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3868
3872
  if (memoryIds.length === 0) return;
3869
3873
  const run = () => {
3870
3874
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4323,7 +4327,11 @@ async function searchMemories(queryVector, agentId, options) {
4323
4327
  sql += ` AND timestamp >= ?`;
4324
4328
  args.push(options.since);
4325
4329
  }
4326
- if (options?.memoryType) {
4330
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4331
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4332
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4333
+ args.push(...uniqueTypes);
4334
+ } else if (options?.memoryType) {
4327
4335
  sql += ` AND memory_type = ?`;
4328
4336
  args.push(options.memoryType);
4329
4337
  }
@@ -2914,7 +2914,7 @@ var init_platform_procedures = __esm({
2914
2914
  title: "Chain of command \u2014 who talks to whom",
2915
2915
  domain: "workflow",
2916
2916
  priority: "p0",
2917
- 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."
2917
+ 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."
2918
2918
  },
2919
2919
  {
2920
2920
  title: "Single dispatch path \u2014 create_task only",
@@ -581,7 +581,7 @@ var init_platform_procedures = __esm({
581
581
  title: "Chain of command \u2014 who talks to whom",
582
582
  domain: "workflow",
583
583
  priority: "p0",
584
- 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."
584
+ 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."
585
585
  },
586
586
  {
587
587
  title: "Single dispatch path \u2014 create_task only",
@@ -786,8 +786,9 @@ function personalizePrompt(prompt, templateName, actualName) {
786
786
  return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
787
787
  }
788
788
  function renderClientCOOTemplate(vars) {
789
+ const resolved = { ...vars, title: vars.title || "Chief Operating Officer" };
789
790
  for (const key of CLIENT_COO_PLACEHOLDERS) {
790
- const value = vars[key];
791
+ const value = resolved[key];
791
792
  if (typeof value !== "string" || value.length === 0) {
792
793
  throw new Error(
793
794
  `renderClientCOOTemplate: missing required variable "${key}"`
@@ -796,7 +797,7 @@ function renderClientCOOTemplate(vars) {
796
797
  }
797
798
  let out = CLIENT_COO_TEMPLATE;
798
799
  for (const key of CLIENT_COO_PLACEHOLDERS) {
799
- out = out.split(`{{${key}}}`).join(vars[key]);
800
+ out = out.split(`{{${key}}}`).join(resolved[key]);
800
801
  }
801
802
  if (vars.industry_context) {
802
803
  out += "\n" + vars.industry_context;
@@ -1273,7 +1274,7 @@ created_by: system
1273
1274
  ---
1274
1275
  ## Identity
1275
1276
 
1276
- You are {{agent_name}}, the Chief Operating Officer at {{company_name}}.
1277
+ You are {{agent_name}}, the {{title}} at {{company_name}}.
1277
1278
 
1278
1279
  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.
1279
1280
 
@@ -1360,7 +1361,8 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
1360
1361
  CLIENT_COO_PLACEHOLDERS = [
1361
1362
  "agent_name",
1362
1363
  "company_name",
1363
- "founder_name"
1364
+ "founder_name",
1365
+ "title"
1364
1366
  ];
1365
1367
  }
1366
1368
  });
@@ -6738,6 +6738,9 @@ function classifyMemoryType(input) {
6738
6738
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
6739
6739
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
6740
6740
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
6741
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
6742
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
6743
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
6741
6744
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
6742
6745
  if (tool === "store_memory" || tool === "manual") return "observation";
6743
6746
  return "raw";
@@ -6880,6 +6883,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
6880
6883
  }
6881
6884
  }
6882
6885
  function schedulePostWriteMemoryHygiene(memoryIds) {
6886
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
6883
6887
  if (memoryIds.length === 0) return;
6884
6888
  const run = () => {
6885
6889
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -7274,7 +7278,7 @@ var init_platform_procedures = __esm({
7274
7278
  title: "Chain of command \u2014 who talks to whom",
7275
7279
  domain: "workflow",
7276
7280
  priority: "p0",
7277
- 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."
7281
+ 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."
7278
7282
  },
7279
7283
  {
7280
7284
  title: "Single dispatch path \u2014 create_task only",
@@ -7946,7 +7950,11 @@ async function searchMemories(queryVector, agentId, options) {
7946
7950
  sql += ` AND timestamp >= ?`;
7947
7951
  args.push(options.since);
7948
7952
  }
7949
- if (options?.memoryType) {
7953
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
7954
+ const uniqueTypes = [...new Set(options.memoryTypes)];
7955
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
7956
+ args.push(...uniqueTypes);
7957
+ } else if (options?.memoryType) {
7950
7958
  sql += ` AND memory_type = ?`;
7951
7959
  args.push(options.memoryType);
7952
7960
  }
@@ -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",
@@ -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"() {
@@ -3054,6 +3120,9 @@ function classifyMemoryType(input) {
3054
3120
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3055
3121
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3056
3122
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3123
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3124
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3125
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3057
3126
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3058
3127
  if (tool === "store_memory" || tool === "manual") return "observation";
3059
3128
  return "raw";
@@ -3196,6 +3265,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3196
3265
  }
3197
3266
  }
3198
3267
  function schedulePostWriteMemoryHygiene(memoryIds) {
3268
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3199
3269
  if (memoryIds.length === 0) return;
3200
3270
  const run = () => {
3201
3271
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3590,7 +3660,7 @@ var init_platform_procedures = __esm({
3590
3660
  title: "Chain of command \u2014 who talks to whom",
3591
3661
  domain: "workflow",
3592
3662
  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."
3663
+ 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
3664
  },
3595
3665
  {
3596
3666
  title: "Single dispatch path \u2014 create_task only",
@@ -4262,7 +4332,11 @@ async function searchMemories(queryVector, agentId2, options) {
4262
4332
  sql += ` AND timestamp >= ?`;
4263
4333
  args.push(options.since);
4264
4334
  }
4265
- if (options?.memoryType) {
4335
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4336
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4337
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4338
+ args.push(...uniqueTypes);
4339
+ } else if (options?.memoryType) {
4266
4340
  sql += ` AND memory_type = ?`;
4267
4341
  args.push(options.memoryType);
4268
4342
  }
@@ -4529,7 +4603,16 @@ var BEHAVIORS_EXPORT_DIR = path8.join(
4529
4603
  "behaviors-export"
4530
4604
  );
4531
4605
  var STALE_EXPORT_AGE_MS = 60 * 60 * 1e3;
4532
- var EXPORT_BEHAVIOR_LIMIT = 30;
4606
+ var DEFAULT_BEHAVIOR_LIMIT = 30;
4607
+ function getBehaviorLimit() {
4608
+ try {
4609
+ const { loadConfigSync: loadConfigSync2 } = (init_config(), __toCommonJS(config_exports));
4610
+ const cfg = loadConfigSync2();
4611
+ return cfg.behaviorExportLimit ?? DEFAULT_BEHAVIOR_LIMIT;
4612
+ } catch {
4613
+ return DEFAULT_BEHAVIOR_LIMIT;
4614
+ }
4615
+ }
4533
4616
  function sweepStaleBehaviorExports(now = Date.now()) {
4534
4617
  if (!existsSync8(BEHAVIORS_EXPORT_DIR)) return;
4535
4618
  let entries;
@@ -4583,7 +4666,7 @@ function exportFilePath(agentId2, projectName2, sessionKey2) {
4583
4666
  async function exportBehaviorsForAgent(agentId2, projectName2, sessionKey2) {
4584
4667
  mkdirSync3(BEHAVIORS_EXPORT_DIR, { recursive: true });
4585
4668
  sweepStaleBehaviorExports();
4586
- const behaviors = await listBehaviors(agentId2, projectName2, EXPORT_BEHAVIOR_LIMIT);
4669
+ const behaviors = await listBehaviors(agentId2, projectName2, getBehaviorLimit());
4587
4670
  if (behaviors.length === 0) return null;
4588
4671
  const body = renderBehaviorExport(behaviors);
4589
4672
  const target = exportFilePath(agentId2, projectName2, sessionKey2);