@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
@@ -3056,6 +3056,9 @@ function classifyMemoryType(input2) {
3056
3056
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3057
3057
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3058
3058
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3059
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3060
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3061
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3059
3062
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3060
3063
  if (tool === "store_memory" || tool === "manual") return "observation";
3061
3064
  return "raw";
@@ -3198,6 +3201,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3198
3201
  }
3199
3202
  }
3200
3203
  function schedulePostWriteMemoryHygiene(memoryIds) {
3204
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3201
3205
  if (memoryIds.length === 0) return;
3202
3206
  const run = () => {
3203
3207
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3592,7 +3596,7 @@ var init_platform_procedures = __esm({
3592
3596
  title: "Chain of command \u2014 who talks to whom",
3593
3597
  domain: "workflow",
3594
3598
  priority: "p0",
3595
- 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."
3599
+ 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."
3596
3600
  },
3597
3601
  {
3598
3602
  title: "Single dispatch path \u2014 create_task only",
@@ -4264,7 +4268,11 @@ async function searchMemories(queryVector, agentId, options) {
4264
4268
  sql += ` AND timestamp >= ?`;
4265
4269
  args.push(options.since);
4266
4270
  }
4267
- if (options?.memoryType) {
4271
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4272
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4273
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4274
+ args.push(...uniqueTypes);
4275
+ } else if (options?.memoryType) {
4268
4276
  sql += ` AND memory_type = ?`;
4269
4277
  args.push(options.memoryType);
4270
4278
  }
@@ -3476,6 +3476,9 @@ function classifyMemoryType(input2) {
3476
3476
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3477
3477
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3478
3478
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3479
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3480
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3481
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3479
3482
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3480
3483
  if (tool === "store_memory" || tool === "manual") return "observation";
3481
3484
  return "raw";
@@ -3618,6 +3621,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3618
3621
  }
3619
3622
  }
3620
3623
  function schedulePostWriteMemoryHygiene(memoryIds) {
3624
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3621
3625
  if (memoryIds.length === 0) return;
3622
3626
  const run = () => {
3623
3627
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4012,7 +4016,7 @@ var init_platform_procedures = __esm({
4012
4016
  title: "Chain of command \u2014 who talks to whom",
4013
4017
  domain: "workflow",
4014
4018
  priority: "p0",
4015
- 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."
4019
+ 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."
4016
4020
  },
4017
4021
  {
4018
4022
  title: "Single dispatch path \u2014 create_task only",
@@ -4684,7 +4688,11 @@ async function searchMemories(queryVector, agentId, options) {
4684
4688
  sql += ` AND timestamp >= ?`;
4685
4689
  args.push(options.since);
4686
4690
  }
4687
- if (options?.memoryType) {
4691
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4692
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4693
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4694
+ args.push(...uniqueTypes);
4695
+ } else if (options?.memoryType) {
4688
4696
  sql += ` AND memory_type = ?`;
4689
4697
  args.push(options.memoryType);
4690
4698
  }
@@ -3220,6 +3220,9 @@ function classifyMemoryType(input2) {
3220
3220
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3221
3221
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3222
3222
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3223
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3224
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3225
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3223
3226
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3224
3227
  if (tool === "store_memory" || tool === "manual") return "observation";
3225
3228
  return "raw";
@@ -3362,6 +3365,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3362
3365
  }
3363
3366
  }
3364
3367
  function schedulePostWriteMemoryHygiene(memoryIds) {
3368
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3365
3369
  if (memoryIds.length === 0) return;
3366
3370
  const run = () => {
3367
3371
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3756,7 +3760,7 @@ var init_platform_procedures = __esm({
3756
3760
  title: "Chain of command \u2014 who talks to whom",
3757
3761
  domain: "workflow",
3758
3762
  priority: "p0",
3759
- 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."
3763
+ 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."
3760
3764
  },
3761
3765
  {
3762
3766
  title: "Single dispatch path \u2014 create_task only",
@@ -4428,7 +4432,11 @@ async function searchMemories(queryVector, agentId, options) {
4428
4432
  sql += ` AND timestamp >= ?`;
4429
4433
  args.push(options.since);
4430
4434
  }
4431
- if (options?.memoryType) {
4435
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4436
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4437
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4438
+ args.push(...uniqueTypes);
4439
+ } else if (options?.memoryType) {
4432
4440
  sql += ` AND memory_type = ?`;
4433
4441
  args.push(options.memoryType);
4434
4442
  }
@@ -5726,6 +5734,17 @@ __export(hybrid_search_exports, {
5726
5734
  rrfMerge: () => rrfMerge,
5727
5735
  rrfMergeMulti: () => rrfMergeMulti
5728
5736
  });
5737
+ function appendMemoryTypeFilter(sql, args, column, options) {
5738
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
5739
+ const uniqueTypes = [...new Set(options.memoryTypes)];
5740
+ sql += ` AND ${column} IN (${uniqueTypes.map(() => "?").join(",")})`;
5741
+ args.push(...uniqueTypes);
5742
+ } else if (options?.memoryType) {
5743
+ sql += ` AND ${column} = ?`;
5744
+ args.push(options.memoryType);
5745
+ }
5746
+ return sql;
5747
+ }
5729
5748
  async function hybridSearch(queryText, agentId, options) {
5730
5749
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
5731
5750
  const config = await loadConfig2();
@@ -5821,7 +5840,7 @@ async function hybridSearch(queryText, agentId, options) {
5821
5840
  }
5822
5841
  if (lists.length === 0) return [];
5823
5842
  if (lists.length === 1 && !effectiveIsBroad) return lists[0].slice(0, limit);
5824
- const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, 150) : limit;
5843
+ const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, broadFetchTopK) : limit;
5825
5844
  let merged = lists.length === 1 ? lists[0].slice(0, rrfLimit) : rrfMergeMulti(lists, rrfLimit, RRF_K, weights);
5826
5845
  let graphContextMap = /* @__PURE__ */ new Map();
5827
5846
  let entityBoostRan = false;
@@ -5842,6 +5861,7 @@ async function hybridSearch(queryText, agentId, options) {
5842
5861
  returnTopK: 5
5843
5862
  };
5844
5863
  let rerankedAndBlended = null;
5864
+ const rerankReturnLimit = Math.max(limit, auto.returnTopK ?? 5);
5845
5865
  if (effectiveIsBroad && auto.enabled && rerankerAvailable) {
5846
5866
  const cardinality2 = await estimateCardinality(agentId, effectiveOptions);
5847
5867
  if (cardinality2 > auto.broadQueryMinCardinality) {
@@ -5853,16 +5873,16 @@ async function hybridSearch(queryText, agentId, options) {
5853
5873
  text: m.raw_text,
5854
5874
  context: graphContextMap.get(m.id)
5855
5875
  }));
5856
- const scored = await rerankWithContext2(effectiveQuery, candidates, auto.returnTopK);
5876
+ const scored = await rerankWithContext2(effectiveQuery, candidates, rerankReturnLimit);
5857
5877
  rerankedRecords = scored.map((s) => merged[s.index]);
5858
5878
  } else {
5859
5879
  const { rerank: rerank2 } = await Promise.resolve().then(() => (init_reranker(), reranker_exports));
5860
- rerankedRecords = await rerank2(effectiveQuery, merged, auto.returnTopK);
5880
+ rerankedRecords = await rerank2(effectiveQuery, merged, rerankReturnLimit);
5861
5881
  }
5862
5882
  if (rerankedRecords.length > 0) {
5863
5883
  rerankedAndBlended = rrfMergeMulti(
5864
5884
  [rerankedRecords],
5865
- auto.returnTopK,
5885
+ rerankReturnLimit,
5866
5886
  RRF_K
5867
5887
  );
5868
5888
  }
@@ -5870,10 +5890,7 @@ async function hybridSearch(queryText, agentId, options) {
5870
5890
  }
5871
5891
  }
5872
5892
  }
5873
- const finalResults = (rerankedAndBlended ?? merged).slice(
5874
- 0,
5875
- rerankedAndBlended ? auto.returnTopK : limit
5876
- );
5893
+ const finalResults = (rerankedAndBlended ?? merged).slice(0, limit);
5877
5894
  if (options?.includeSource && finalResults.length > 0) {
5878
5895
  await attachDocumentMetadata(finalResults);
5879
5896
  }
@@ -5954,6 +5971,7 @@ async function estimateCardinality(agentId, options) {
5954
5971
  sql += ` AND timestamp >= ?`;
5955
5972
  args.push(options.since);
5956
5973
  }
5974
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
5957
5975
  try {
5958
5976
  const result = await client.execute({ sql, args });
5959
5977
  return Number(result.rows[0]?.cnt) || 0;
@@ -6075,10 +6093,7 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
6075
6093
  sql += ` AND m.timestamp >= ?`;
6076
6094
  args.push(options.since);
6077
6095
  }
6078
- if (options?.memoryType) {
6079
- sql += ` AND m.memory_type = ?`;
6080
- args.push(options.memoryType);
6081
- }
6096
+ sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
6082
6097
  sql += ` ORDER BY rank LIMIT ?`;
6083
6098
  args.push(limit);
6084
6099
  const result = await client.execute({ sql, args });
@@ -6135,9 +6150,16 @@ async function recentRecords(agentId, options, limit, textFilter) {
6135
6150
  AND timestamp >= ? AND timestamp <= ?
6136
6151
  AND COALESCE(status, 'active') = 'active'
6137
6152
  AND ${options?.includeRaw === false ? "COALESCE(memory_type, 'raw') != 'raw'" : "1 = 1"}
6153
+ ${options?.memoryTypes?.length ? `AND memory_type IN (${options.memoryTypes.map(() => "?").join(",")})` : options?.memoryType ? "AND memory_type = ?" : ""}
6138
6154
  AND COALESCE(confidence, 0.7) >= 0.3
6139
6155
  ORDER BY timestamp DESC LIMIT ?`,
6140
- args: [agentId, windowStart, killedAt, boundarySlots]
6156
+ args: [
6157
+ agentId,
6158
+ windowStart,
6159
+ killedAt,
6160
+ ...options?.memoryTypes?.length ? [...new Set(options.memoryTypes)] : options?.memoryType ? [options.memoryType] : [],
6161
+ boundarySlots
6162
+ ]
6141
6163
  });
6142
6164
  for (const row of boundaryResult.rows) {
6143
6165
  sessionBoundaryMemories.push(rowToMemoryRecord(row));
@@ -6183,10 +6205,7 @@ async function recentRecords(agentId, options, limit, textFilter) {
6183
6205
  sql += ` AND timestamp >= ?`;
6184
6206
  args.push(options.since);
6185
6207
  }
6186
- if (options?.memoryType) {
6187
- sql += ` AND memory_type = ?`;
6188
- args.push(options.memoryType);
6189
- }
6208
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
6190
6209
  if (textFilter) {
6191
6210
  sql += ` AND raw_text LIKE '%' || ? || '%'`;
6192
6211
  args.push(textFilter);
@@ -6906,8 +6925,15 @@ process.stdin.on("end", async () => {
6906
6925
  try {
6907
6926
  const data = JSON.parse(input);
6908
6927
  const { extractSemanticText: extractSemanticText2 } = await Promise.resolve().then(() => (init_content_extractor(), content_extractor_exports));
6909
- const rawText = extractSemanticText2(data.tool_name, data.tool_input, data.tool_response);
6910
- if (rawText.length >= 50) {
6928
+ let rawText = extractSemanticText2(data.tool_name, data.tool_input, data.tool_response);
6929
+ if (rawText.trim().length < 10) {
6930
+ const inputPreview = JSON.stringify(data.tool_input ?? "").slice(0, 500);
6931
+ const outputPreview = JSON.stringify(data.tool_response ?? "").slice(0, 500);
6932
+ rawText = `Tool call: ${data.tool_name}
6933
+ Input: ${inputPreview}
6934
+ Output: ${outputPreview}`;
6935
+ }
6936
+ if (rawText.trim().length >= 10) {
6911
6937
  const { writeMemoryViaDaemon: writeMemoryViaDaemon2 } = await Promise.resolve().then(() => (init_memory_queue_client(), memory_queue_client_exports));
6912
6938
  const { detectError: detectError2 } = await Promise.resolve().then(() => (init_error_detector(), error_detector_exports));
6913
6939
  const { getProjectName: getProjectName2 } = await Promise.resolve().then(() => (init_project_name(), project_name_exports));
@@ -6737,6 +6737,9 @@ function classifyMemoryType(input2) {
6737
6737
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
6738
6738
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
6739
6739
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
6740
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
6741
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
6742
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
6740
6743
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
6741
6744
  if (tool === "store_memory" || tool === "manual") return "observation";
6742
6745
  return "raw";
@@ -6879,6 +6882,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
6879
6882
  }
6880
6883
  }
6881
6884
  function schedulePostWriteMemoryHygiene(memoryIds) {
6885
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
6882
6886
  if (memoryIds.length === 0) return;
6883
6887
  const run = () => {
6884
6888
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -7273,7 +7277,7 @@ var init_platform_procedures = __esm({
7273
7277
  title: "Chain of command \u2014 who talks to whom",
7274
7278
  domain: "workflow",
7275
7279
  priority: "p0",
7276
- 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."
7280
+ 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."
7277
7281
  },
7278
7282
  {
7279
7283
  title: "Single dispatch path \u2014 create_task only",
@@ -7945,7 +7949,11 @@ async function searchMemories(queryVector, agentId, options) {
7945
7949
  sql += ` AND timestamp >= ?`;
7946
7950
  args.push(options.since);
7947
7951
  }
7948
- if (options?.memoryType) {
7952
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
7953
+ const uniqueTypes = [...new Set(options.memoryTypes)];
7954
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
7955
+ args.push(...uniqueTypes);
7956
+ } else if (options?.memoryType) {
7949
7957
  sql += ` AND memory_type = ?`;
7950
7958
  args.push(options.memoryType);
7951
7959
  }
@@ -8428,7 +8436,8 @@ ${taskLines}`);
8428
8436
  project_name: projectName,
8429
8437
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
8430
8438
  importance: 8,
8431
- task_id: taskId
8439
+ task_id: taskId,
8440
+ memory_type: "checkpoint"
8432
8441
  });
8433
8442
  } catch {
8434
8443
  }
@@ -3683,9 +3683,12 @@ var init_cto_delegation_gate = __esm({
3683
3683
  SCRATCHPAD_MAX_AGE_MS = 10 * 60 * 1e3;
3684
3684
  SCRATCHPAD_ESCAPE_PATTERN = /^(?:ENGINEER|TOM)-CAPABLE:\s*NO\s*—\s*reason:\s*\S+/m;
3685
3685
  GATE_BLOCK_MESSAGE = [
3686
- "DELEGATE CHECK: this edit looks implementable by an engineer.",
3687
- "Dispatch create_task now OR mark ENGINEER-CAPABLE: NO with reason.",
3688
- "No code until decided."
3686
+ "ACTION BLOCKED by CTO delegation gate. Your Write/Edit was DENIED \u2014 it did NOT execute.",
3687
+ "This edit looks implementable by an engineer. You MUST either:",
3688
+ " 1. Dispatch create_task to an engineer, OR",
3689
+ " 2. Add ENGINEER-CAPABLE: NO with explicit reason to proceed yourself.",
3690
+ "Do NOT report this action as successful. It was blocked. No file was changed.",
3691
+ "If you are a sub-agent, report this FAILURE to your parent agent."
3689
3692
  ].join("\n");
3690
3693
  }
3691
3694
  });
@@ -3943,6 +3946,9 @@ function classifyMemoryType(input2) {
3943
3946
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3944
3947
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3945
3948
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3949
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3950
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3951
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3946
3952
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3947
3953
  if (tool === "store_memory" || tool === "manual") return "observation";
3948
3954
  return "raw";
@@ -4085,6 +4091,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
4085
4091
  }
4086
4092
  }
4087
4093
  function schedulePostWriteMemoryHygiene(memoryIds) {
4094
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
4088
4095
  if (memoryIds.length === 0) return;
4089
4096
  const run = () => {
4090
4097
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4479,7 +4486,7 @@ var init_platform_procedures = __esm({
4479
4486
  title: "Chain of command \u2014 who talks to whom",
4480
4487
  domain: "workflow",
4481
4488
  priority: "p0",
4482
- 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."
4489
+ 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."
4483
4490
  },
4484
4491
  {
4485
4492
  title: "Single dispatch path \u2014 create_task only",
@@ -5151,7 +5158,11 @@ async function searchMemories(queryVector, agentId, options) {
5151
5158
  sql += ` AND timestamp >= ?`;
5152
5159
  args.push(options.since);
5153
5160
  }
5154
- if (options?.memoryType) {
5161
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
5162
+ const uniqueTypes = [...new Set(options.memoryTypes)];
5163
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
5164
+ args.push(...uniqueTypes);
5165
+ } else if (options?.memoryType) {
5155
5166
  sql += ` AND memory_type = ?`;
5156
5167
  args.push(options.memoryType);
5157
5168
  }
@@ -5690,9 +5701,10 @@ process.stdin.on("end", async () => {
5690
5701
  hookSpecificOutput: {
5691
5702
  permissionDecision: "deny"
5692
5703
  },
5693
- systemMessage: `BLOCKED: You attempted to write to exe/${target}/ \u2014 that is ${target}'s task folder.
5694
- Your tasks are in exe/${agent.agentId}/. Use ask_team_memory("${target}") for context.
5695
- This write was prevented. Do NOT retry.`
5704
+ systemMessage: `ACTION BLOCKED: Your Write/Edit to exe/${target}/ was DENIED \u2014 it did NOT execute.
5705
+ That is ${target}'s task folder, not yours. Your tasks are in exe/${agent.agentId}/.
5706
+ Use ask_team_memory("${target}") if you need context from ${target}.
5707
+ Do NOT report this as successful. No file was changed. If you are a sub-agent, report FAILURE.`
5696
5708
  });
5697
5709
  process.stdout.write(output);
5698
5710
  process.exit(0);
@@ -3387,6 +3387,9 @@ function classifyMemoryType(input2) {
3387
3387
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3388
3388
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3389
3389
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3390
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3391
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3392
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3390
3393
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3391
3394
  if (tool === "store_memory" || tool === "manual") return "observation";
3392
3395
  return "raw";
@@ -3529,6 +3532,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3529
3532
  }
3530
3533
  }
3531
3534
  function schedulePostWriteMemoryHygiene(memoryIds) {
3535
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3532
3536
  if (memoryIds.length === 0) return;
3533
3537
  const run = () => {
3534
3538
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3923,7 +3927,7 @@ var init_platform_procedures = __esm({
3923
3927
  title: "Chain of command \u2014 who talks to whom",
3924
3928
  domain: "workflow",
3925
3929
  priority: "p0",
3926
- 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."
3930
+ 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."
3927
3931
  },
3928
3932
  {
3929
3933
  title: "Single dispatch path \u2014 create_task only",
@@ -4595,7 +4599,11 @@ async function searchMemories(queryVector, agentId, options) {
4595
4599
  sql += ` AND timestamp >= ?`;
4596
4600
  args.push(options.since);
4597
4601
  }
4598
- if (options?.memoryType) {
4602
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4603
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4604
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4605
+ args.push(...uniqueTypes);
4606
+ } else if (options?.memoryType) {
4599
4607
  sql += ` AND memory_type = ?`;
4600
4608
  args.push(options.memoryType);
4601
4609
  }
@@ -7723,6 +7731,13 @@ var init_tasks_notify = __esm({
7723
7731
  });
7724
7732
 
7725
7733
  // src/lib/behaviors.ts
7734
+ var behaviors_exports = {};
7735
+ __export(behaviors_exports, {
7736
+ deactivateBehavior: () => deactivateBehavior,
7737
+ listBehaviors: () => listBehaviors,
7738
+ listBehaviorsByDomain: () => listBehaviorsByDomain,
7739
+ storeBehavior: () => storeBehavior
7740
+ });
7726
7741
  import crypto6 from "crypto";
7727
7742
  async function storeBehavior(opts) {
7728
7743
  const client = getClient();
@@ -7742,6 +7757,63 @@ async function storeBehavior(opts) {
7742
7757
  });
7743
7758
  return id;
7744
7759
  }
7760
+ async function listBehaviors(agentId, projectName, limit = 30) {
7761
+ const client = getClient();
7762
+ const result = await client.execute({
7763
+ sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector
7764
+ FROM behaviors
7765
+ WHERE agent_id = ? AND active = 1
7766
+ AND (project_name IS NULL OR project_name = ?)
7767
+ ORDER BY
7768
+ CASE WHEN priority = 'p0' THEN 0
7769
+ WHEN priority = 'p1' THEN 1
7770
+ ELSE 2 END,
7771
+ updated_at DESC
7772
+ LIMIT ?`,
7773
+ args: [agentId, projectName ?? "", limit]
7774
+ });
7775
+ return result.rows.map((r) => ({
7776
+ id: String(r.id),
7777
+ agent_id: String(r.agent_id),
7778
+ project_name: r.project_name ? String(r.project_name) : null,
7779
+ domain: r.domain ? String(r.domain) : null,
7780
+ priority: String(r.priority || "p1"),
7781
+ content: String(r.content),
7782
+ active: Number(r.active),
7783
+ created_at: String(r.created_at),
7784
+ updated_at: String(r.updated_at),
7785
+ vector: r.vector ? Array.from(new Float32Array(r.vector)) : null
7786
+ }));
7787
+ }
7788
+ async function listBehaviorsByDomain(agentId, domain) {
7789
+ const client = getClient();
7790
+ const result = await client.execute({
7791
+ sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector
7792
+ FROM behaviors
7793
+ WHERE agent_id = ? AND domain = ? AND active = 1`,
7794
+ args: [agentId, domain]
7795
+ });
7796
+ return result.rows.map((r) => ({
7797
+ id: String(r.id),
7798
+ agent_id: String(r.agent_id),
7799
+ project_name: r.project_name ? String(r.project_name) : null,
7800
+ domain: r.domain ? String(r.domain) : null,
7801
+ priority: String(r.priority || "p1"),
7802
+ content: String(r.content),
7803
+ active: Number(r.active),
7804
+ created_at: String(r.created_at),
7805
+ updated_at: String(r.updated_at),
7806
+ vector: r.vector ? Array.from(new Float32Array(r.vector)) : null
7807
+ }));
7808
+ }
7809
+ async function deactivateBehavior(id) {
7810
+ const client = getClient();
7811
+ const result = await client.execute({
7812
+ sql: `UPDATE behaviors SET active = 0, updated_at = ? WHERE id = ? AND active = 1`,
7813
+ args: [(/* @__PURE__ */ new Date()).toISOString(), id]
7814
+ });
7815
+ return (result.rowsAffected ?? 0) > 0;
7816
+ }
7745
7817
  var init_behaviors = __esm({
7746
7818
  "src/lib/behaviors.ts"() {
7747
7819
  "use strict";
@@ -9697,6 +9769,17 @@ import path25 from "path";
9697
9769
  init_store();
9698
9770
  init_database();
9699
9771
  var RRF_K = 60;
9772
+ function appendMemoryTypeFilter(sql, args, column, options) {
9773
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
9774
+ const uniqueTypes = [...new Set(options.memoryTypes)];
9775
+ sql += ` AND ${column} IN (${uniqueTypes.map(() => "?").join(",")})`;
9776
+ args.push(...uniqueTypes);
9777
+ } else if (options?.memoryType) {
9778
+ sql += ` AND ${column} = ?`;
9779
+ args.push(options.memoryType);
9780
+ }
9781
+ return sql;
9782
+ }
9700
9783
  async function hybridSearch(queryText, agentId, options) {
9701
9784
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
9702
9785
  const config = await loadConfig2();
@@ -9792,7 +9875,7 @@ async function hybridSearch(queryText, agentId, options) {
9792
9875
  }
9793
9876
  if (lists.length === 0) return [];
9794
9877
  if (lists.length === 1 && !effectiveIsBroad) return lists[0].slice(0, limit);
9795
- const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, 150) : limit;
9878
+ const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, broadFetchTopK) : limit;
9796
9879
  let merged = lists.length === 1 ? lists[0].slice(0, rrfLimit) : rrfMergeMulti(lists, rrfLimit, RRF_K, weights);
9797
9880
  let graphContextMap = /* @__PURE__ */ new Map();
9798
9881
  let entityBoostRan = false;
@@ -9813,6 +9896,7 @@ async function hybridSearch(queryText, agentId, options) {
9813
9896
  returnTopK: 5
9814
9897
  };
9815
9898
  let rerankedAndBlended = null;
9899
+ const rerankReturnLimit = Math.max(limit, auto.returnTopK ?? 5);
9816
9900
  if (effectiveIsBroad && auto.enabled && rerankerAvailable) {
9817
9901
  const cardinality2 = await estimateCardinality(agentId, effectiveOptions);
9818
9902
  if (cardinality2 > auto.broadQueryMinCardinality) {
@@ -9824,16 +9908,16 @@ async function hybridSearch(queryText, agentId, options) {
9824
9908
  text: m.raw_text,
9825
9909
  context: graphContextMap.get(m.id)
9826
9910
  }));
9827
- const scored = await rerankWithContext2(effectiveQuery, candidates, auto.returnTopK);
9911
+ const scored = await rerankWithContext2(effectiveQuery, candidates, rerankReturnLimit);
9828
9912
  rerankedRecords = scored.map((s) => merged[s.index]);
9829
9913
  } else {
9830
9914
  const { rerank: rerank2 } = await Promise.resolve().then(() => (init_reranker(), reranker_exports));
9831
- rerankedRecords = await rerank2(effectiveQuery, merged, auto.returnTopK);
9915
+ rerankedRecords = await rerank2(effectiveQuery, merged, rerankReturnLimit);
9832
9916
  }
9833
9917
  if (rerankedRecords.length > 0) {
9834
9918
  rerankedAndBlended = rrfMergeMulti(
9835
9919
  [rerankedRecords],
9836
- auto.returnTopK,
9920
+ rerankReturnLimit,
9837
9921
  RRF_K
9838
9922
  );
9839
9923
  }
@@ -9841,10 +9925,7 @@ async function hybridSearch(queryText, agentId, options) {
9841
9925
  }
9842
9926
  }
9843
9927
  }
9844
- const finalResults = (rerankedAndBlended ?? merged).slice(
9845
- 0,
9846
- rerankedAndBlended ? auto.returnTopK : limit
9847
- );
9928
+ const finalResults = (rerankedAndBlended ?? merged).slice(0, limit);
9848
9929
  if (options?.includeSource && finalResults.length > 0) {
9849
9930
  await attachDocumentMetadata(finalResults);
9850
9931
  }
@@ -9925,6 +10006,7 @@ async function estimateCardinality(agentId, options) {
9925
10006
  sql += ` AND timestamp >= ?`;
9926
10007
  args.push(options.since);
9927
10008
  }
10009
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
9928
10010
  try {
9929
10011
  const result = await client.execute({ sql, args });
9930
10012
  return Number(result.rows[0]?.cnt) || 0;
@@ -10043,10 +10125,7 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
10043
10125
  sql += ` AND m.timestamp >= ?`;
10044
10126
  args.push(options.since);
10045
10127
  }
10046
- if (options?.memoryType) {
10047
- sql += ` AND m.memory_type = ?`;
10048
- args.push(options.memoryType);
10049
- }
10128
+ sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
10050
10129
  sql += ` ORDER BY rank LIMIT ?`;
10051
10130
  args.push(limit);
10052
10131
  const result = await client.execute({ sql, args });
@@ -10103,9 +10182,16 @@ async function recentRecords(agentId, options, limit, textFilter) {
10103
10182
  AND timestamp >= ? AND timestamp <= ?
10104
10183
  AND COALESCE(status, 'active') = 'active'
10105
10184
  AND ${options?.includeRaw === false ? "COALESCE(memory_type, 'raw') != 'raw'" : "1 = 1"}
10185
+ ${options?.memoryTypes?.length ? `AND memory_type IN (${options.memoryTypes.map(() => "?").join(",")})` : options?.memoryType ? "AND memory_type = ?" : ""}
10106
10186
  AND COALESCE(confidence, 0.7) >= 0.3
10107
10187
  ORDER BY timestamp DESC LIMIT ?`,
10108
- args: [agentId, windowStart, killedAt, boundarySlots]
10188
+ args: [
10189
+ agentId,
10190
+ windowStart,
10191
+ killedAt,
10192
+ ...options?.memoryTypes?.length ? [...new Set(options.memoryTypes)] : options?.memoryType ? [options.memoryType] : [],
10193
+ boundarySlots
10194
+ ]
10109
10195
  });
10110
10196
  for (const row of boundaryResult.rows) {
10111
10197
  sessionBoundaryMemories.push(rowToMemoryRecord(row));
@@ -10151,10 +10237,7 @@ async function recentRecords(agentId, options, limit, textFilter) {
10151
10237
  sql += ` AND timestamp >= ?`;
10152
10238
  args.push(options.since);
10153
10239
  }
10154
- if (options?.memoryType) {
10155
- sql += ` AND memory_type = ?`;
10156
- args.push(options.memoryType);
10157
- }
10240
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
10158
10241
  if (textFilter) {
10159
10242
  sql += ` AND raw_text LIKE '%' || ? || '%'`;
10160
10243
  args.push(textFilter);
@@ -10600,6 +10683,36 @@ ${fresh.map(
10600
10683
  }
10601
10684
  }
10602
10685
  }
10686
+ let behaviorContext = "";
10687
+ if (!IS_CODEX_RUNTIME && agent.agentId !== "default") {
10688
+ try {
10689
+ const counterPath = path25.join(CACHE_DIR3, `prompt-count-${getSessionKey()}`);
10690
+ let count = 1;
10691
+ try {
10692
+ count = parseInt(readFileSync17(counterPath, "utf8").trim(), 10) + 1;
10693
+ } catch {
10694
+ }
10695
+ writeFileSync11(counterPath, String(count), "utf8");
10696
+ const BEHAVIOR_REINJECT_INTERVAL = 50;
10697
+ if (count === 1 || count % BEHAVIOR_REINJECT_INTERVAL === 0) {
10698
+ const { listBehaviors: listBehaviors2 } = await Promise.resolve().then(() => (init_behaviors(), behaviors_exports));
10699
+ const behaviors = await listBehaviors2(agent.agentId);
10700
+ const active = behaviors.filter((b) => b.active !== 0).sort((a, b) => (a.priority === "p0" ? -1 : 1) - (b.priority === "p0" ? -1 : 1)).slice(0, 15);
10701
+ if (active.length > 0) {
10702
+ const lines = active.map(
10703
+ (b) => `- [${b.domain ?? "workflow"}] ${b.content.slice(0, 200)}`
10704
+ );
10705
+ behaviorContext = `
10706
+ ## Your Behavioral Memory
10707
+ Validated patterns and corrections for this session. Follow them.
10708
+ Sourced from exe-os Layer 2 (Expertise). Changes apply on next spawn.
10709
+
10710
+ ${lines.join("\n")}`;
10711
+ }
10712
+ }
10713
+ } catch {
10714
+ }
10715
+ }
10603
10716
  let reviewContext = "";
10604
10717
  if (canCoordinate(agent.agentId, agent.agentRole)) {
10605
10718
  try {
@@ -10655,7 +10768,7 @@ IMPORTANT: After completing your current task, you MUST address the pending revi
10655
10768
  } catch {
10656
10769
  }
10657
10770
  }
10658
- const combined = [cacheContext, memoryContext, reviewContext].filter(Boolean).join("\n\n");
10771
+ const combined = [cacheContext, memoryContext, behaviorContext, reviewContext].filter(Boolean).join("\n\n");
10659
10772
  if (combined.length > 0) {
10660
10773
  const output = JSON.stringify({
10661
10774
  hookSpecificOutput: {