@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
@@ -3743,6 +3743,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3743
3743
  }
3744
3744
  }
3745
3745
  function schedulePostWriteMemoryHygiene(memoryIds) {
3746
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3746
3747
  if (memoryIds.length === 0) return;
3747
3748
  const run = () => {
3748
3749
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4137,7 +4138,7 @@ var init_platform_procedures = __esm({
4137
4138
  title: "Chain of command \u2014 who talks to whom",
4138
4139
  domain: "workflow",
4139
4140
  priority: "p0",
4140
- 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."
4141
+ 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."
4141
4142
  },
4142
4143
  {
4143
4144
  title: "Single dispatch path \u2014 create_task only",
@@ -4809,7 +4810,11 @@ async function searchMemories(queryVector, agentId, options) {
4809
4810
  sql += ` AND timestamp >= ?`;
4810
4811
  args.push(options.since);
4811
4812
  }
4812
- if (options?.memoryType) {
4813
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4814
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4815
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4816
+ args.push(...uniqueTypes);
4817
+ } else if (options?.memoryType) {
4813
4818
  sql += ` AND memory_type = ?`;
4814
4819
  args.push(options.memoryType);
4815
4820
  }
@@ -6039,6 +6044,17 @@ __export(hybrid_search_exports, {
6039
6044
  rrfMerge: () => rrfMerge,
6040
6045
  rrfMergeMulti: () => rrfMergeMulti
6041
6046
  });
6047
+ function appendMemoryTypeFilter(sql, args, column, options) {
6048
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
6049
+ const uniqueTypes = [...new Set(options.memoryTypes)];
6050
+ sql += ` AND ${column} IN (${uniqueTypes.map(() => "?").join(",")})`;
6051
+ args.push(...uniqueTypes);
6052
+ } else if (options?.memoryType) {
6053
+ sql += ` AND ${column} = ?`;
6054
+ args.push(options.memoryType);
6055
+ }
6056
+ return sql;
6057
+ }
6042
6058
  async function hybridSearch(queryText, agentId, options) {
6043
6059
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6044
6060
  const config2 = await loadConfig2();
@@ -6267,6 +6283,7 @@ async function estimateCardinality(agentId, options) {
6267
6283
  sql += ` AND timestamp >= ?`;
6268
6284
  args.push(options.since);
6269
6285
  }
6286
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
6270
6287
  try {
6271
6288
  const result = await client.execute({ sql, args });
6272
6289
  return Number(result.rows[0]?.cnt) || 0;
@@ -6388,10 +6405,7 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
6388
6405
  sql += ` AND m.timestamp >= ?`;
6389
6406
  args.push(options.since);
6390
6407
  }
6391
- if (options?.memoryType) {
6392
- sql += ` AND m.memory_type = ?`;
6393
- args.push(options.memoryType);
6394
- }
6408
+ sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
6395
6409
  sql += ` ORDER BY rank LIMIT ?`;
6396
6410
  args.push(limit);
6397
6411
  const result = await client.execute({ sql, args });
@@ -6448,9 +6462,16 @@ async function recentRecords(agentId, options, limit, textFilter) {
6448
6462
  AND timestamp >= ? AND timestamp <= ?
6449
6463
  AND COALESCE(status, 'active') = 'active'
6450
6464
  AND ${options?.includeRaw === false ? "COALESCE(memory_type, 'raw') != 'raw'" : "1 = 1"}
6465
+ ${options?.memoryTypes?.length ? `AND memory_type IN (${options.memoryTypes.map(() => "?").join(",")})` : options?.memoryType ? "AND memory_type = ?" : ""}
6451
6466
  AND COALESCE(confidence, 0.7) >= 0.3
6452
6467
  ORDER BY timestamp DESC LIMIT ?`,
6453
- args: [agentId, windowStart, killedAt, boundarySlots]
6468
+ args: [
6469
+ agentId,
6470
+ windowStart,
6471
+ killedAt,
6472
+ ...options?.memoryTypes?.length ? [...new Set(options.memoryTypes)] : options?.memoryType ? [options.memoryType] : [],
6473
+ boundarySlots
6474
+ ]
6454
6475
  });
6455
6476
  for (const row of boundaryResult.rows) {
6456
6477
  sessionBoundaryMemories.push(rowToMemoryRecord(row));
@@ -6496,10 +6517,7 @@ async function recentRecords(agentId, options, limit, textFilter) {
6496
6517
  sql += ` AND timestamp >= ?`;
6497
6518
  args.push(options.since);
6498
6519
  }
6499
- if (options?.memoryType) {
6500
- sql += ` AND memory_type = ?`;
6501
- args.push(options.memoryType);
6502
- }
6520
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
6503
6521
  if (textFilter) {
6504
6522
  sql += ` AND raw_text LIKE '%' || ? || '%'`;
6505
6523
  args.push(textFilter);
@@ -12685,6 +12703,63 @@ init_hybrid_search();
12685
12703
  init_store();
12686
12704
  init_active_agent();
12687
12705
  import { z } from "zod";
12706
+
12707
+ // src/lib/memory-retrieval-modes.ts
12708
+ var RETRIEVAL_MODES = [
12709
+ "all",
12710
+ "decisions_only",
12711
+ "behaviors_only",
12712
+ "procedures_only",
12713
+ "operational",
12714
+ "no_raw",
12715
+ "recent_high_value"
12716
+ ];
12717
+ var RETRIEVAL_MODE_DESCRIPTIONS = {
12718
+ all: "All visible memory types.",
12719
+ decisions_only: "Only decisions and ADRs.",
12720
+ behaviors_only: "Only durable behavior/correction memories.",
12721
+ procedures_only: "Only procedures/runbooks.",
12722
+ operational: "Raw operational/debug/tool output.",
12723
+ no_raw: "All non-raw memory types.",
12724
+ recent_high_value: "High-value durable memory types, intended for recency recovery."
12725
+ };
12726
+ function applyRetrievalMode(base, mode) {
12727
+ if (!mode || mode === "all") return base;
12728
+ const next = { ...base };
12729
+ switch (mode) {
12730
+ case "decisions_only":
12731
+ next.memoryTypes = ["decision", "adr"];
12732
+ next.includeRaw = false;
12733
+ break;
12734
+ case "behaviors_only":
12735
+ next.memoryTypes = ["behavior"];
12736
+ next.includeRaw = false;
12737
+ break;
12738
+ case "procedures_only":
12739
+ next.memoryTypes = ["procedure"];
12740
+ next.includeRaw = false;
12741
+ break;
12742
+ case "operational":
12743
+ next.memoryTypes = ["raw", "observation"];
12744
+ next.includeRaw = true;
12745
+ break;
12746
+ case "no_raw":
12747
+ next.includeRaw = false;
12748
+ break;
12749
+ case "recent_high_value":
12750
+ next.memoryTypes = ["decision", "adr", "behavior", "procedure"];
12751
+ next.includeRaw = false;
12752
+ break;
12753
+ default:
12754
+ return next;
12755
+ }
12756
+ return next;
12757
+ }
12758
+ function formatRetrievalModes() {
12759
+ return RETRIEVAL_MODES.map((mode) => `${mode}: ${RETRIEVAL_MODE_DESCRIPTIONS[mode]}`).join("; ");
12760
+ }
12761
+
12762
+ // src/mcp/tools/recall-my-memory.ts
12688
12763
  function formatSourceLine(record) {
12689
12764
  const doc2 = record.document_metadata;
12690
12765
  if (!doc2) return "";
@@ -12720,7 +12795,8 @@ function registerRecallMyMemory(server2) {
12720
12795
  ),
12721
12796
  include_source: z.boolean().optional().default(false).describe(
12722
12797
  "When true, attach parent document metadata (filename, mime, source_type) to each result. Default false."
12723
- )
12798
+ ),
12799
+ retrieval_mode: z.enum(RETRIEVAL_MODES).optional().default("all").describe(`Typed retrieval mode. ${formatRetrievalModes()}`)
12724
12800
  }
12725
12801
  },
12726
12802
  async ({
@@ -12734,7 +12810,8 @@ function registerRecallMyMemory(server2) {
12734
12810
  include_archived,
12735
12811
  workspace_id,
12736
12812
  user_id,
12737
- include_source
12813
+ include_source,
12814
+ retrieval_mode
12738
12815
  }) => {
12739
12816
  try {
12740
12817
  if (!recent && !query) {
@@ -12744,7 +12821,7 @@ function registerRecallMyMemory(server2) {
12744
12821
  };
12745
12822
  }
12746
12823
  const { agentId } = getActiveAgent();
12747
- const searchOptions = {
12824
+ const searchOptions = applyRetrievalMode({
12748
12825
  projectName: project_name,
12749
12826
  hasError: has_error,
12750
12827
  toolName: tool_name,
@@ -12755,7 +12832,7 @@ function registerRecallMyMemory(server2) {
12755
12832
  includeSource: include_source,
12756
12833
  includeDrafts: true,
12757
12834
  ...user_id !== void 0 ? { userId: user_id } : {}
12758
- };
12835
+ }, retrieval_mode);
12759
12836
  let results;
12760
12837
  if (recent) {
12761
12838
  results = await recentRecords(agentId, searchOptions, limit, query);
@@ -12843,10 +12920,11 @@ function registerAskTeamMemory(server2) {
12843
12920
  ),
12844
12921
  include_raw: z2.boolean().optional().default(false).describe(
12845
12922
  "Include raw technical memories when ACL allows it (default: non-raw memories only for cross-agent reads)"
12846
- )
12923
+ ),
12924
+ retrieval_mode: z2.enum(RETRIEVAL_MODES).optional().default("all").describe(`Typed retrieval mode. Raw visibility is still ACL-gated. ${formatRetrievalModes()}`)
12847
12925
  }
12848
12926
  },
12849
- async ({ team_member, query, project_name, limit, since, include_archived, include_raw: _include_raw }) => {
12927
+ async ({ team_member, query, project_name, limit, since, include_archived, include_raw: _include_raw, retrieval_mode }) => {
12850
12928
  try {
12851
12929
  const { agentId: queryingAgentId, agentRole: queryingAgentRole } = getActiveAgent();
12852
12930
  const employees = loadEmployeesSync();
@@ -12855,16 +12933,18 @@ function registerAskTeamMemory(server2) {
12855
12933
  const targetRole = targetEmployee?.role ?? "";
12856
12934
  const hasRawAccess = canSeeRaw(queryingRole, targetRole);
12857
12935
  const effectiveIncludeRaw = _include_raw && hasRawAccess;
12858
- const results = await hybridSearch(query, team_member, {
12936
+ const requestedMode = retrieval_mode ?? "all";
12937
+ const safeMode = !effectiveIncludeRaw && ["all", "operational"].includes(requestedMode) ? "no_raw" : requestedMode;
12938
+ const searchOptions = applyRetrievalMode({
12859
12939
  projectName: project_name,
12860
12940
  limit,
12861
12941
  since,
12862
12942
  includeArchived: include_archived,
12863
12943
  includeDrafts: false,
12864
- includeRaw: effectiveIncludeRaw,
12865
- memoryType: void 0
12866
- // Show all memory types — privacy enforced by draft filter + ACL, not type filter
12867
- });
12944
+ includeRaw: effectiveIncludeRaw
12945
+ }, safeMode);
12946
+ if (!effectiveIncludeRaw) searchOptions.includeRaw = false;
12947
+ const results = await hybridSearch(query, team_member, searchOptions);
12868
12948
  if (results.length === 0) {
12869
12949
  return {
12870
12950
  content: [
@@ -15695,7 +15775,7 @@ created_by: system
15695
15775
  ---
15696
15776
  ## Identity
15697
15777
 
15698
- You are {{agent_name}}, the Chief Operating Officer at {{company_name}}.
15778
+ You are {{agent_name}}, the {{title}} at {{company_name}}.
15699
15779
 
15700
15780
  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.
15701
15781
 
@@ -15782,11 +15862,13 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
15782
15862
  var CLIENT_COO_PLACEHOLDERS = [
15783
15863
  "agent_name",
15784
15864
  "company_name",
15785
- "founder_name"
15865
+ "founder_name",
15866
+ "title"
15786
15867
  ];
15787
15868
  function renderClientCOOTemplate(vars) {
15869
+ const resolved = { ...vars, title: vars.title || "Chief Operating Officer" };
15788
15870
  for (const key of CLIENT_COO_PLACEHOLDERS) {
15789
- const value = vars[key];
15871
+ const value = resolved[key];
15790
15872
  if (typeof value !== "string" || value.length === 0) {
15791
15873
  throw new Error(
15792
15874
  `renderClientCOOTemplate: missing required variable "${key}"`
@@ -15795,7 +15877,7 @@ function renderClientCOOTemplate(vars) {
15795
15877
  }
15796
15878
  let out = CLIENT_COO_TEMPLATE;
15797
15879
  for (const key of CLIENT_COO_PLACEHOLDERS) {
15798
- out = out.split(`{{${key}}}`).join(vars[key]);
15880
+ out = out.split(`{{${key}}}`).join(resolved[key]);
15799
15881
  }
15800
15882
  if (vars.industry_context) {
15801
15883
  out += "\n" + vars.industry_context;
@@ -15961,6 +16043,7 @@ ${vars}`);
15961
16043
  agent_name,
15962
16044
  company_name,
15963
16045
  founder_name,
16046
+ title: "Chief Operating Officer",
15964
16047
  industry_context: pack.identityContext ?? void 0
15965
16048
  });
15966
16049
  cooSummaryLines = [
@@ -6930,6 +6930,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
6930
6930
  }
6931
6931
  }
6932
6932
  function schedulePostWriteMemoryHygiene(memoryIds) {
6933
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
6933
6934
  if (memoryIds.length === 0) return;
6934
6935
  const run = () => {
6935
6936
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -7324,7 +7325,7 @@ var init_platform_procedures = __esm({
7324
7325
  title: "Chain of command \u2014 who talks to whom",
7325
7326
  domain: "workflow",
7326
7327
  priority: "p0",
7327
- 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."
7328
+ 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."
7328
7329
  },
7329
7330
  {
7330
7331
  title: "Single dispatch path \u2014 create_task only",
@@ -7996,7 +7997,11 @@ async function searchMemories(queryVector, agentId, options) {
7996
7997
  sql += ` AND timestamp >= ?`;
7997
7998
  args.push(options.since);
7998
7999
  }
7999
- if (options?.memoryType) {
8000
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
8001
+ const uniqueTypes = [...new Set(options.memoryTypes)];
8002
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
8003
+ args.push(...uniqueTypes);
8004
+ } else if (options?.memoryType) {
8000
8005
  sql += ` AND memory_type = ?`;
8001
8006
  args.push(options.memoryType);
8002
8007
  }
package/dist/tui/App.js CHANGED
@@ -8520,7 +8520,7 @@ var init_platform_procedures = __esm({
8520
8520
  title: "Chain of command \u2014 who talks to whom",
8521
8521
  domain: "workflow",
8522
8522
  priority: "p0",
8523
- 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."
8523
+ 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."
8524
8524
  },
8525
8525
  {
8526
8526
  title: "Single dispatch path \u2014 create_task only",
@@ -11239,6 +11239,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
11239
11239
  }
11240
11240
  }
11241
11241
  function schedulePostWriteMemoryHygiene(memoryIds) {
11242
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
11242
11243
  if (memoryIds.length === 0) return;
11243
11244
  const run = () => {
11244
11245
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -12056,7 +12057,11 @@ async function searchMemories(queryVector, agentId, options) {
12056
12057
  sql += ` AND timestamp >= ?`;
12057
12058
  args.push(options.since);
12058
12059
  }
12059
- if (options?.memoryType) {
12060
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
12061
+ const uniqueTypes = [...new Set(options.memoryTypes)];
12062
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
12063
+ args.push(...uniqueTypes);
12064
+ } else if (options?.memoryType) {
12060
12065
  sql += ` AND memory_type = ?`;
12061
12066
  args.push(options.memoryType);
12062
12067
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.35",
3
+ "version": "0.9.36",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -0,0 +1,48 @@
1
+ # /exe-save
2
+
3
+ Save a context checkpoint — commit everything important from this session to long-term memory before context fills up or session ends.
4
+
5
+ ## What to save
6
+
7
+ Store a structured memory checkpoint with ALL of the following:
8
+
9
+ 1. **What you accomplished** — list every completed task, fix, or deliverable
10
+ 2. **Decisions made** — architectural choices, trade-offs, priorities decided
11
+ 3. **Open items** — anything unfinished, blocked, or deferred
12
+ 4. **Key file paths** — files you created, modified, or need to revisit
13
+ 5. **Risks or concerns** — anything that might break or needs follow-up
14
+
15
+ ## How to save
16
+
17
+ ```bash
18
+ # Use store_memory MCP tool with a structured checkpoint
19
+ ```
20
+
21
+ Call `store_memory` with this format:
22
+
23
+ ```
24
+ CONTEXT CHECKPOINT [session-date]:
25
+ ## Completed
26
+ - [list what was done]
27
+
28
+ ## Decisions
29
+ - [list decisions and why]
30
+
31
+ ## Open Items
32
+ - [list what's unfinished]
33
+
34
+ ## Key Files
35
+ - [list important file paths]
36
+
37
+ ## Risks
38
+ - [list concerns]
39
+ ```
40
+
41
+ Then call `store_memory` again for each major decision as a separate `decision` type memory — these survive consolidation and are always retrievable via `recall_my_memory(query, retrieval_mode="decisions_only")`.
42
+
43
+ ## When to use
44
+
45
+ - Before your context window fills up
46
+ - At the end of a long working session
47
+ - Before switching to a different project
48
+ - When the founder says "save everything"