@cortexkit/pi-magic-context 0.42.5 → 0.42.6

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.
@@ -6834,6 +6834,7 @@ var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65;
6834
6834
  var EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 90% for cache safety: output capacity is reserved from the usable context window, and the remaining 10% absorbs mid-turn growth before the absolute 95% emergency wall. Use a value between 20 and 90.";
6835
6835
  var DEFAULT_HISTORIAN_TIMEOUT_MS = 600000;
6836
6836
  var DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15;
6837
+ var PROTECTED_TOKENS_MIN = 4000;
6837
6838
  var DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
6838
6839
  var PiThinkingLevelSchema = _enum(["off", "minimal", "low", "medium", "high", "xhigh", "max"]).optional();
6839
6840
  var OmpThinkingLevelSchema = _enum(["off", "minimal", "low", "medium", "high", "xhigh", "max", "inherit", "auto"]).optional();
@@ -7203,8 +7204,8 @@ var MagicContextConfigSchema = object({
7203
7204
  smart_notes: object({
7204
7205
  retina_handoff: boolean2().default(false).describe("When true, dreamer skips smart notes whose surface conditions compiled to retina provider configs at authoring time. Default false keeps both paths active until the retina consumer is deployed.")
7205
7206
  }).default({ retina_handoff: false }).describe("Smart-note ownership transition controls."),
7206
- cache_ttl: union([string2(), object({ default: string2() }).catchall(string2())]).default("5m").describe(`How long Magic Context assumes the provider's cached prefix stays valid. This is MC's own deferral gate — it does not change the provider's actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "model-id": "10m" }). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).`),
7207
- prompt_surface: PromptSurfaceConfigSchema.default({ default: "full" }).describe("Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. On OpenCode and Pi, per-model routing applies to the guidance block only: tool descriptions are registered once per process, so they follow the default preset (a v1 plugin-surface limitation; per-model tool descriptions are planned for the OpenCode v2 plugin API once the SDK stabilizes)."),
7207
+ cache_ttl: union([string2(), object({ default: string2() }).catchall(string2())]).default("5m").describe(`How long Magic Context assumes the provider's cached prefix stays valid. This is MC's own deferral gate — it does not change the provider's actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "provider/model": "1h", "provider/*": "never" }); keys resolve most-specific first (exact provider/model, bare model ID, shorter dash-prefixes, then the provider/* wildcard, then default). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).`),
7208
+ prompt_surface: PromptSurfaceConfigSchema.default({ default: "full" }).describe("Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. OpenCode 1.x, Pi, and OMP register tool descriptions once per process (they follow the default preset). OpenCode 2 rewrites the five ctx_* descriptions per request from the draft model."),
7208
7209
  output_reserve: union([
7209
7210
  number2().min(0),
7210
7211
  object({ default: number2().min(0) }).catchall(number2().min(0))
@@ -7220,7 +7221,7 @@ var MagicContextConfigSchema = object({
7220
7221
  execute_threshold_tokens: object({
7221
7222
  default: number2().min(5000).max(2000000).optional()
7222
7223
  }).catchall(number2().min(5000).max(2000000)).optional().describe("Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above 90% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000."),
7223
- protected_tokens: number2().int().min(4000).max(1e6).optional().describe("Positive integer token floor to protect from automatic reclaim (min: 4_000, max: 1_000_000). When omitted, the derived default is clamp(round(0.05 × usableSoft), min(16_000, round(0.08 × usableSoft)), 64_000)."),
7224
+ protected_tokens: number2().int().min(PROTECTED_TOKENS_MIN).max(1e6).optional().describe("Positive integer token floor to protect from automatic reclaim (min: 4_000, max: 1_000_000). When omitted, the derived default is clamp(round(0.05 × usableSoft), min(16_000, round(0.08 × usableSoft)), 64_000)."),
7224
7225
  protected_tags: unknown().optional().describe("Deprecated: number of recent tags to protect. Ignored for behaviour; use protected_tokens instead.").meta({ deprecated: true }),
7225
7226
  clear_reasoning_age: number2().min(10).default(50).describe("Clear reasoning/thinking blocks older than N tags (default: 50)"),
7226
7227
  history_budget_percentage: number2().min(0.05).max(0.5).default(DEFAULT_HISTORY_BUDGET_PERCENTAGE).describe("Fraction of usable context (context_limit × execute_threshold) reserved for the session history block (default: 0.15)"),
@@ -8934,6 +8935,25 @@ function extractTexts(parts) {
8934
8935
  }
8935
8936
  return texts;
8936
8937
  }
8938
+ function extractToolResultBodyTokens(parts) {
8939
+ let tokens = 0;
8940
+ for (const part of parts) {
8941
+ if (part === null || typeof part !== "object")
8942
+ continue;
8943
+ const p = part;
8944
+ if (p.type !== "tool")
8945
+ continue;
8946
+ const state = p.state;
8947
+ if (!state || typeof state !== "object")
8948
+ continue;
8949
+ const body = state.output ?? state.error;
8950
+ if (body === undefined)
8951
+ continue;
8952
+ const text = typeof body === "string" ? body : JSON.stringify(body);
8953
+ tokens += Math.ceil(text.length / 4);
8954
+ }
8955
+ return tokens;
8956
+ }
8937
8957
  function extractToolCallSummaries(parts) {
8938
8958
  const summaries = [];
8939
8959
  for (const part of parts) {
@@ -10947,6 +10967,28 @@ async function pullAndApplyMirrorPageWithStatus(args) {
10947
10967
  limit
10948
10968
  });
10949
10969
  const nextCursor = applyMirrorPage({ db: args.db, page: response.page });
10970
+ if (args.domain === "memories" && args.module.memoryIdentityAck) {
10971
+ const rowsByProject = new Map;
10972
+ for (const feed of response.page.rows) {
10973
+ if (feed.domain !== "memories" || feed.op === "tombstone")
10974
+ continue;
10975
+ const project = rowString(feed.full_row_snapshot, "project_path");
10976
+ if (!project)
10977
+ continue;
10978
+ const identity = mirrorIdentity(args.db, "memories", project, feed.module_row_id);
10979
+ if (!identity)
10980
+ continue;
10981
+ const rows = rowsByProject.get(project) ?? [];
10982
+ rows.push({
10983
+ module_row_id: feed.module_row_id,
10984
+ context_row_id: identity.context_row_id
10985
+ });
10986
+ rowsByProject.set(project, rows);
10987
+ }
10988
+ for (const [project, rows] of rowsByProject) {
10989
+ await args.module.memoryIdentityAck({ project, rows });
10990
+ }
10991
+ }
10950
10992
  return {
10951
10993
  cursor: nextCursor,
10952
10994
  hasMore: response.page.has_more,
@@ -11717,6 +11759,114 @@ function isSqliteLockError(error) {
11717
11759
  function tableExists2(db, name) {
11718
11760
  return Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name));
11719
11761
  }
11762
+ function tableHasHarnessColumn(db, name) {
11763
+ if (!tableExists2(db, name))
11764
+ return false;
11765
+ return db.prepare(`PRAGMA table_info(${name})`).all().some((column) => column.name === "harness");
11766
+ }
11767
+ var V85_OPENCODE2_RELABEL_TABLES = [
11768
+ "tags",
11769
+ "pending_ops",
11770
+ "source_contents",
11771
+ "compartments",
11772
+ "compartment_chunk_embeddings",
11773
+ "session_projects",
11774
+ "compartment_events",
11775
+ "compression_depth",
11776
+ "session_facts",
11777
+ "primer_candidates",
11778
+ "notes",
11779
+ "message_history_index",
11780
+ "message_history_source",
11781
+ "pending_session_cleanup",
11782
+ "message_history_orphan_sweep",
11783
+ "session_meta",
11784
+ "subagent_invocations",
11785
+ "historian_runs",
11786
+ "transform_decisions",
11787
+ "recomp_compartments",
11788
+ "recomp_facts"
11789
+ ];
11790
+ var V85_OPTIONAL_OPENCODE2_RELABEL_TABLES = ["session_project_backfill_state"];
11791
+ function deleteLosingOpenCode2Twin(db, table, joinColumns, newerPredicate) {
11792
+ if (!tableHasHarnessColumn(db, table))
11793
+ return;
11794
+ const naturalJoin = joinColumns.map((column) => `oc.${column} = o2.${column}`).join(" AND ");
11795
+ const o2On = naturalJoin ? `${naturalJoin} AND oc.harness = 'opencode'` : `oc.harness = 'opencode'`;
11796
+ const ocOn = naturalJoin ? `${naturalJoin} AND o2.harness = 'opencode2'` : `o2.harness = 'opencode2'`;
11797
+ db.exec(`
11798
+ DELETE FROM ${table}
11799
+ WHERE rowid IN (
11800
+ SELECT o2.rowid
11801
+ FROM ${table} AS o2
11802
+ JOIN ${table} AS oc
11803
+ ON ${o2On}
11804
+ WHERE o2.harness = 'opencode2'
11805
+ AND NOT (${newerPredicate})
11806
+ );
11807
+ DELETE FROM ${table}
11808
+ WHERE rowid IN (
11809
+ SELECT oc.rowid
11810
+ FROM ${table} AS oc
11811
+ JOIN ${table} AS o2
11812
+ ON ${ocOn}
11813
+ WHERE oc.harness = 'opencode'
11814
+ AND (${newerPredicate})
11815
+ );
11816
+ `);
11817
+ }
11818
+ function relabelOpenCode2HarnessRows(db) {
11819
+ deleteLosingOpenCode2Twin(db, "session_projects", ["session_id"], "o2.updated_at > oc.updated_at");
11820
+ deleteLosingOpenCode2Twin(db, "primer_candidates", ["project_path", "session_id", "source_start_message_id", "source_end_message_id"], "o2.created_at > oc.created_at");
11821
+ deleteLosingOpenCode2Twin(db, "transform_decisions", ["session_id", "message_id"], "o2.ts_ms > oc.ts_ms");
11822
+ deleteLosingOpenCode2Twin(db, "message_history_orphan_sweep", [], "COALESCE(o2.last_swept_at, -1) > COALESCE(oc.last_swept_at, -1)");
11823
+ if (tableHasHarnessColumn(db, "session_project_backfill_state")) {
11824
+ db.exec(`
11825
+ DELETE FROM session_project_backfill_state
11826
+ WHERE harness = 'opencode2'
11827
+ AND EXISTS (
11828
+ SELECT 1 FROM session_project_backfill_state WHERE harness = 'opencode'
11829
+ )
11830
+ AND NOT (
11831
+ (status = 'completed'
11832
+ AND (SELECT status FROM session_project_backfill_state WHERE harness = 'opencode')
11833
+ != 'completed')
11834
+ OR (
11835
+ status = (SELECT status FROM session_project_backfill_state WHERE harness = 'opencode')
11836
+ AND COALESCE(started_at, -1) > COALESCE(
11837
+ (SELECT started_at FROM session_project_backfill_state WHERE harness = 'opencode'),
11838
+ -1
11839
+ )
11840
+ )
11841
+ );
11842
+ DELETE FROM session_project_backfill_state
11843
+ WHERE harness = 'opencode'
11844
+ AND EXISTS (
11845
+ SELECT 1 FROM session_project_backfill_state WHERE harness = 'opencode2'
11846
+ )
11847
+ AND (
11848
+ ((SELECT status FROM session_project_backfill_state WHERE harness = 'opencode2') = 'completed'
11849
+ AND status != 'completed')
11850
+ OR (
11851
+ status = (SELECT status FROM session_project_backfill_state WHERE harness = 'opencode2')
11852
+ AND COALESCE(
11853
+ (SELECT started_at FROM session_project_backfill_state WHERE harness = 'opencode2'),
11854
+ -1
11855
+ ) > COALESCE(started_at, -1)
11856
+ )
11857
+ );
11858
+ `);
11859
+ }
11860
+ const tables = new Set([
11861
+ ...V85_OPENCODE2_RELABEL_TABLES,
11862
+ ...V85_OPTIONAL_OPENCODE2_RELABEL_TABLES
11863
+ ]);
11864
+ for (const table of tables) {
11865
+ if (!tableHasHarnessColumn(db, table))
11866
+ continue;
11867
+ db.exec(`UPDATE ${table} SET harness = 'opencode' WHERE harness = 'opencode2'`);
11868
+ }
11869
+ }
11720
11870
  function healMismatchedTierClose(db, table, hasLegacy) {
11721
11871
  if (!tableExists2(db, table))
11722
11872
  return;
@@ -13879,6 +14029,13 @@ var MIGRATIONS = [
13879
14029
  ensureColumn(db, "session_meta", "protected_tokens_effective", "INTEGER");
13880
14030
  ensureColumn(db, "session_meta", "protected_tokens_pre_snapshot", "TEXT");
13881
14031
  }
14032
+ },
14033
+ {
14034
+ version: 85,
14035
+ description: "relabel OpenCode 1.x mis-tagged opencode2 session rows",
14036
+ up(db) {
14037
+ relabelOpenCode2HarnessRows(db);
14038
+ }
13882
14039
  }
13883
14040
  ];
13884
14041
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -14067,15 +14224,16 @@ import { isAbsolute as isAbsolute3, join as join4 } from "node:path";
14067
14224
  var cachedResolution = null;
14068
14225
  var lastReadFailure = null;
14069
14226
  var claimedDiagnostics = new Set;
14070
- function openCodeDataDir() {
14071
- return join4(process.env.XDG_DATA_HOME ?? join4(homedir7(), ".local", "share"), "opencode");
14227
+ function openCodeDataDir(env = process.env, dataHome) {
14228
+ return join4(dataHome ?? env.XDG_DATA_HOME ?? join4(homedir7(), ".local", "share"), "opencode");
14072
14229
  }
14073
- function environmentKey(dataDir) {
14230
+ function environmentKey(dataDir, hostGeneration, channel, env) {
14074
14231
  return [
14232
+ hostGeneration,
14075
14233
  dataDir,
14076
- process.env.OPENCODE_DB ?? "",
14077
- process.env.OPENCODE_DISABLE_CHANNEL_DB ?? "",
14078
- process.env.OPENCODE_CHANNEL ?? ""
14234
+ env.OPENCODE_DB ?? "",
14235
+ env.OPENCODE_DISABLE_CHANNEL_DB ?? "",
14236
+ channel ?? env.OPENCODE_CHANNEL ?? ""
14079
14237
  ].join("\x00");
14080
14238
  }
14081
14239
  function channelPath(dataDir, channel) {
@@ -14107,8 +14265,8 @@ function discoverOpenCodeDb(dataDir) {
14107
14265
  const channel = name === "opencode.db" ? null : name.slice("opencode-".length, -".db".length) || null;
14108
14266
  return { path: existing.path, source: "discovered", channel };
14109
14267
  }
14110
- function resolveFresh(dataDir) {
14111
- const explicit = process.env.OPENCODE_DB;
14268
+ function resolveV1Fresh(dataDir, env = process.env) {
14269
+ const explicit = env.OPENCODE_DB;
14112
14270
  if (explicit !== undefined && explicit.length > 0) {
14113
14271
  if (explicit === ":memory:") {
14114
14272
  return { path: explicit, source: "OPENCODE_DB", channel: null };
@@ -14119,24 +14277,47 @@ function resolveFresh(dataDir) {
14119
14277
  channel: null
14120
14278
  };
14121
14279
  }
14122
- const disableChannelDb = process.env.OPENCODE_DISABLE_CHANNEL_DB;
14280
+ const disableChannelDb = env.OPENCODE_DISABLE_CHANNEL_DB;
14123
14281
  if (disableChannelDb === "1" || disableChannelDb === "true") {
14124
14282
  return { path: join4(dataDir, "opencode.db"), source: "default", channel: null };
14125
14283
  }
14126
- const channel = process.env.OPENCODE_CHANNEL;
14284
+ const channel = env.OPENCODE_CHANNEL;
14127
14285
  if (channel !== undefined && channel.length > 0) {
14128
14286
  return { path: channelPath(dataDir, channel), source: "channel", channel };
14129
14287
  }
14130
14288
  return discoverOpenCodeDb(dataDir);
14131
14289
  }
14132
- function resolveOpenCodeDbPath() {
14133
- const dataDir = openCodeDataDir();
14134
- const key = environmentKey(dataDir);
14290
+ function sourceOpenCodeDatabaseFilename(hostGeneration, channel, env = process.env) {
14291
+ if (hostGeneration === "v1") {
14292
+ const explicit = env.OPENCODE_DB;
14293
+ if (explicit !== undefined && explicit.length > 0)
14294
+ return explicit;
14295
+ if (env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true") {
14296
+ return "opencode.db";
14297
+ }
14298
+ return ["latest", "beta", "prod"].includes(channel) ? "opencode.db" : `opencode-${channel}.db`;
14299
+ }
14300
+ return env.OPENCODE_DB ?? (["latest", "dev", "beta", "next", "prod"].includes(channel) || env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true" ? "opencode.db" : `opencode-${channel.replace(/[^a-zA-Z0-9._-]/g, "")}.db`);
14301
+ }
14302
+ function resolveV2Fresh(dataDir, channel, env) {
14303
+ const filename = sourceOpenCodeDatabaseFilename("v2", channel, env);
14304
+ const explicit = env.OPENCODE_DB !== undefined;
14305
+ return {
14306
+ path: filename === ":memory:" ? filename : join4(dataDir, filename),
14307
+ source: explicit ? "OPENCODE_DB" : env.OPENCODE_CHANNEL ? "channel" : "default",
14308
+ channel: explicit ? null : channel
14309
+ };
14310
+ }
14311
+ function resolveOpenCodeDbPath(hostGeneration = "v1", options = {}) {
14312
+ const env = options.env ?? process.env;
14313
+ const dataDir = openCodeDataDir(env, options.dataHome);
14314
+ const channel = options.channel ?? env.OPENCODE_CHANNEL;
14315
+ const key = environmentKey(dataDir, hostGeneration, channel, env);
14135
14316
  if (cachedResolution?.key === key && (!cachedResolution.existed || existsSync5(cachedResolution.resolution.path))) {
14136
14317
  if (cachedResolution.existed)
14137
14318
  return cachedResolution.resolution;
14138
14319
  }
14139
- const resolution = resolveFresh(dataDir);
14320
+ const resolution = hostGeneration === "v2" ? resolveV2Fresh(dataDir, channel ?? "latest", env) : resolveV1Fresh(dataDir, env);
14140
14321
  cachedResolution = {
14141
14322
  key,
14142
14323
  resolution,
@@ -14144,6 +14325,29 @@ function resolveOpenCodeDbPath() {
14144
14325
  };
14145
14326
  return resolution;
14146
14327
  }
14328
+ function schemaTableNames(db, schema = "main") {
14329
+ const rows = db.prepare(`SELECT name FROM ${schema}.sqlite_master WHERE type = 'table' AND name IN ('message', 'part', 'session', 'project', 'session_message')`).all();
14330
+ return new Set(rows.flatMap((row) => typeof row.name === "string" ? [row.name] : []));
14331
+ }
14332
+ function detectOpenCodeStoreGeneration(db, schema = "main") {
14333
+ const tables = schemaTableNames(db, schema);
14334
+ const hasV1Messages = tables.has("message") && tables.has("part");
14335
+ if (hasV1Messages)
14336
+ return "v1";
14337
+ if (tables.has("session_message"))
14338
+ return "v2";
14339
+ if (tables.has("session") || tables.has("project"))
14340
+ return "v1";
14341
+ return "unknown";
14342
+ }
14343
+ function assertOpenCodeStoreGeneration(db, expected, path, schema = "main") {
14344
+ const actual = detectOpenCodeStoreGeneration(db, schema);
14345
+ if (actual === expected)
14346
+ return;
14347
+ if (actual === "unknown")
14348
+ return;
14349
+ throw new Error(`OpenCode store generation mismatch at ${path}: expected ${expected}, found ${actual}; refusing generation-specific database access`);
14350
+ }
14147
14351
  function openCodeDbPathExists(resolution = resolveOpenCodeDbPath()) {
14148
14352
  return resolution.path !== ":memory:" && existsSync5(resolution.path);
14149
14353
  }
@@ -14213,6 +14417,7 @@ function runToolOwnerBackfill(db) {
14213
14417
  const escapedDbPath = opencodeDbPath.replaceAll("'", "''");
14214
14418
  db.exec(`ATTACH '${escapedDbPath}' AS oc_backfill`);
14215
14419
  try {
14420
+ assertOpenCodeStoreGeneration(db, "v1", opencodeDbPath, "oc_backfill");
14216
14421
  backfillToolOwnersInChunks(db, result);
14217
14422
  } finally {
14218
14423
  try {
@@ -14431,7 +14636,7 @@ function getSchemaFenceRejection() {
14431
14636
  function getMigrationOnOpenRefusal() {
14432
14637
  return lastMigrationOnOpenRefusal;
14433
14638
  }
14434
- var LATEST_SUPPORTED_VERSION = 84;
14639
+ var LATEST_SUPPORTED_VERSION = 85;
14435
14640
  var BOOT_SQLITE_BUSY_TIMEOUT_MS = 5000;
14436
14641
  var PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
14437
14642
  var defaultStoragePermissionFs = { chmodSync: chmodSync2, mkdirSync: mkdirSync4 };
@@ -14897,7 +15102,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
14897
15102
  tag_id INTEGER,
14898
15103
  session_id TEXT,
14899
15104
  content TEXT,
14900
- created_at INTEGER,
15105
+ created_at INTEGER, -- epoch ms; Date.now() on source writes, preserved on session clones
14901
15106
  harness TEXT NOT NULL DEFAULT 'opencode',
14902
15107
  PRIMARY KEY(session_id, tag_id)
14903
15108
  );
@@ -14921,7 +15126,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
14921
15126
  p1_embedding BLOB,
14922
15127
  p1_embedding_model_id TEXT,
14923
15128
  legacy INTEGER NOT NULL DEFAULT 0,
14924
- created_at INTEGER NOT NULL,
15129
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
14925
15130
  harness TEXT NOT NULL DEFAULT 'opencode',
14926
15131
  UNIQUE(session_id, sequence)
14927
15132
  );
@@ -14940,7 +15145,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
14940
15145
  model_id TEXT NOT NULL,
14941
15146
  dims INTEGER NOT NULL,
14942
15147
  vector BLOB NOT NULL,
14943
- created_at INTEGER NOT NULL,
15148
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
14944
15149
  UNIQUE(compartment_id, model_id, window_index)
14945
15150
  );
14946
15151
  CREATE INDEX IF NOT EXISTS idx_cce_session ON compartment_chunk_embeddings(session_id);
@@ -14963,7 +15168,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
14963
15168
  kind TEXT NOT NULL,
14964
15169
  at_compartment INTEGER,
14965
15170
  fields_json TEXT NOT NULL DEFAULT '{}',
14966
- created_at INTEGER NOT NULL,
15171
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
14967
15172
  harness TEXT NOT NULL DEFAULT 'opencode'
14968
15173
  );
14969
15174
  CREATE INDEX IF NOT EXISTS idx_compartment_events_session
@@ -14992,7 +15197,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
14992
15197
  session_id TEXT NOT NULL,
14993
15198
  category TEXT NOT NULL,
14994
15199
  content TEXT NOT NULL,
14995
- created_at INTEGER NOT NULL,
15200
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
14996
15201
  updated_at INTEGER NOT NULL,
14997
15202
  harness TEXT NOT NULL DEFAULT 'opencode'
14998
15203
  );
@@ -15011,7 +15216,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
15011
15216
  source_message_time INTEGER NOT NULL,
15012
15217
  question_embedding BLOB,
15013
15218
  question_embedding_model_id TEXT,
15014
- created_at INTEGER NOT NULL,
15219
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
15015
15220
  UNIQUE(project_path, harness, session_id, source_start_message_id, source_end_message_id)
15016
15221
  );
15017
15222
  CREATE INDEX IF NOT EXISTS idx_primer_candidates_project_time
@@ -15034,7 +15239,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
15034
15239
  answer_refreshed_at INTEGER,
15035
15240
  source_candidate_ids TEXT NOT NULL DEFAULT '[]',
15036
15241
  source_candidate_provenance TEXT,
15037
- created_at INTEGER NOT NULL,
15242
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
15038
15243
  updated_at INTEGER NOT NULL
15039
15244
  );
15040
15245
  CREATE INDEX IF NOT EXISTS idx_primers_project_status_observed
@@ -15147,7 +15352,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
15147
15352
  job_id TEXT,
15148
15353
  cursor TEXT,
15149
15354
  status TEXT NOT NULL DEFAULT 'pending',
15150
- created_at INTEGER NOT NULL DEFAULT 0,
15355
+ created_at INTEGER NOT NULL DEFAULT 0, -- epoch ms (Date.now())
15151
15356
  updated_at INTEGER NOT NULL DEFAULT 0,
15152
15357
  UNIQUE(session_id, request_key)
15153
15358
  );
@@ -15188,7 +15393,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
15188
15393
  shadow_epoch INTEGER NOT NULL DEFAULT 0,
15189
15394
  corpus_hash TEXT NOT NULL DEFAULT '',
15190
15395
  coverage_json TEXT NOT NULL DEFAULT '{}',
15191
- created_at INTEGER NOT NULL DEFAULT 0,
15396
+ created_at INTEGER NOT NULL DEFAULT 0, -- epoch ms (Date.now())
15192
15397
  UNIQUE(dedup_key, cohort_key)
15193
15398
  );
15194
15399
  CREATE INDEX IF NOT EXISTS idx_embedding_measurement_session
@@ -15611,7 +15816,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
15611
15816
  importance_avg REAL,
15612
15817
  discarded_last INTEGER NOT NULL DEFAULT 0,
15613
15818
  legacy INTEGER NOT NULL DEFAULT 0,
15614
- created_at INTEGER NOT NULL
15819
+ created_at INTEGER NOT NULL -- epoch ms (Date.now())
15615
15820
  );
15616
15821
  CREATE INDEX IF NOT EXISTS idx_historian_runs_session
15617
15822
  ON historian_runs(session_id, created_at DESC);
@@ -15664,7 +15869,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
15664
15869
  importance INTEGER NOT NULL DEFAULT 50,
15665
15870
  episode_type TEXT,
15666
15871
  pass_number INTEGER NOT NULL,
15667
- created_at INTEGER NOT NULL,
15872
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
15668
15873
  harness TEXT NOT NULL DEFAULT 'opencode',
15669
15874
  UNIQUE(session_id, sequence)
15670
15875
  );
@@ -15675,7 +15880,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
15675
15880
  category TEXT NOT NULL,
15676
15881
  content TEXT NOT NULL,
15677
15882
  pass_number INTEGER NOT NULL,
15678
- created_at INTEGER NOT NULL,
15883
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
15679
15884
  harness TEXT NOT NULL DEFAULT 'opencode'
15680
15885
  );
15681
15886
 
@@ -19655,6 +19860,12 @@ function getReadOnlySessionDb() {
19655
19860
  }
19656
19861
  closeCachedReadOnlyDb();
19657
19862
  const db = new Database(dbPath, { readonly: true });
19863
+ try {
19864
+ assertOpenCodeStoreGeneration(db, "v1", dbPath);
19865
+ } catch (error) {
19866
+ closeQuietly(db);
19867
+ throw error;
19868
+ }
19658
19869
  cachedReadOnlyDb = { path: dbPath, db };
19659
19870
  clearOpenCodeDbReadFailure();
19660
19871
  return db;
@@ -21273,6 +21484,14 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
21273
21484
  const totalMessageCount = getCachedAbsoluteMessageCount(sessionId) ?? messages.length;
21274
21485
  const startOrdinal = Math.max(1, offset);
21275
21486
  const completedToolArcs = buildToolArcs(messages).flatMap((arc) => arc.resOrdinal === null ? [] : [{ start: arc.invOrdinal, end: arc.resOrdinal }]);
21487
+ const completedToolComponents = [];
21488
+ for (const arc of completedToolArcs) {
21489
+ const component = completedToolComponents[completedToolComponents.length - 1];
21490
+ if (component && arc.start <= component.end)
21491
+ component.end = Math.max(component.end, arc.end);
21492
+ else
21493
+ completedToolComponents.push({ ...arc });
21494
+ }
21276
21495
  const lines = [];
21277
21496
  const lineMeta = [];
21278
21497
  const flushedToolOnlyBlocks = [];
@@ -21286,6 +21505,25 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
21286
21505
  let pendingNoiseMeta = [];
21287
21506
  let commitClusters = 0;
21288
21507
  let lastFlushedRole = "";
21508
+ let admittedOversizeComponentEnd = null;
21509
+ let currentBlockApproxTokens = 0;
21510
+ let formattedBudgetCrossed = false;
21511
+ let sourceCharacters = 0;
21512
+ const toolResultBoundaries = [];
21513
+ function pinComponentWhenFormattedBudgetCrosses(ordinal, appendedText) {
21514
+ if (admittedOversizeComponentEnd !== null || formattedBudgetCrossed || !currentBlock)
21515
+ return;
21516
+ currentBlockApproxTokens += estimateTokens(appendedText) + (currentBlock.parts.length > 1 ? 1 : 0);
21517
+ if (totalTokens + currentBlockApproxTokens + 64 <= tokenBudget)
21518
+ return;
21519
+ const previewTokens = totalTokens + estimateTokens(formatBlock(currentBlock));
21520
+ if (previewTokens <= tokenBudget)
21521
+ return;
21522
+ formattedBudgetCrossed = true;
21523
+ const component = completedToolComponents.find((candidate) => candidate.start <= ordinal && candidate.end >= ordinal);
21524
+ if (component)
21525
+ admittedOversizeComponentEnd = component.end;
21526
+ }
21289
21527
  function recordFilteredNoise(meta) {
21290
21528
  pendingNoiseMeta.push(meta);
21291
21529
  if (!currentBlock) {
@@ -21312,7 +21550,23 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
21312
21550
  highestScannedOrdinal = Math.max(highestScannedOrdinal, lastOrdinal);
21313
21551
  lastMessageId = currentBlock.meta[currentBlock.meta.length - 1]?.messageId ?? "";
21314
21552
  messagesProcessed += currentBlock.meta.length;
21553
+ const lineStart = sourceCharacters + (lines.length > 0 ? 1 : 0);
21554
+ const renderedParts = currentBlock.parts.join(" / ");
21555
+ let partOffset = lineStart + (blockText.length - renderedParts.length);
21556
+ for (let index = 0;index < currentBlock.parts.length; index++) {
21557
+ const part = currentBlock.parts[index] ?? "";
21558
+ const partMeta = currentBlock.partMeta[index];
21559
+ if (partMeta && partMeta.toolResultBodyTokens > 0) {
21560
+ toolResultBoundaries.push({
21561
+ ordinal: partMeta.ordinal,
21562
+ sourceOffset: partOffset,
21563
+ bodyTokens: partMeta.toolResultBodyTokens
21564
+ });
21565
+ }
21566
+ partOffset += part.length + (index + 1 < currentBlock.parts.length ? 3 : 0);
21567
+ }
21315
21568
  lines.push(blockText);
21569
+ sourceCharacters = lineStart + blockText.length;
21316
21570
  lineMeta.push(...currentBlock.meta);
21317
21571
  totalTokens += blockTokens;
21318
21572
  if (currentBlock.isToolOnly) {
@@ -21322,11 +21576,15 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
21322
21576
  });
21323
21577
  }
21324
21578
  currentBlock = null;
21579
+ currentBlockApproxTokens = 0;
21325
21580
  return true;
21326
21581
  }
21327
21582
  for (const msg of messages) {
21328
21583
  if (eligibleEndOrdinal !== undefined && msg.ordinal >= eligibleEndOrdinal)
21329
21584
  break;
21585
+ if (admittedOversizeComponentEnd !== null && msg.ordinal > admittedOversizeComponentEnd) {
21586
+ break;
21587
+ }
21330
21588
  if (msg.ordinal < startOrdinal)
21331
21589
  continue;
21332
21590
  const meta = { ordinal: msg.ordinal, messageId: msg.id };
@@ -21340,6 +21598,10 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
21340
21598
  if (currentBlock && currentBlock.role === "A") {
21341
21599
  currentBlock.endOrdinal = msg.ordinal;
21342
21600
  currentBlock.parts.push(tcText);
21601
+ currentBlock.partMeta.push({
21602
+ ordinal: msg.ordinal,
21603
+ toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
21604
+ });
21343
21605
  currentBlock.meta.push(...pendingNoiseMeta, meta);
21344
21606
  pendingNoiseMeta = [];
21345
21607
  } else {
@@ -21350,12 +21612,19 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
21350
21612
  startOrdinal: pendingNoiseMeta[0]?.ordinal ?? msg.ordinal,
21351
21613
  endOrdinal: msg.ordinal,
21352
21614
  parts: [tcText],
21615
+ partMeta: [
21616
+ {
21617
+ ordinal: msg.ordinal,
21618
+ toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
21619
+ }
21620
+ ],
21353
21621
  meta: [...pendingNoiseMeta, meta],
21354
21622
  commitHashes: [],
21355
21623
  isToolOnly: true
21356
21624
  };
21357
21625
  pendingNoiseMeta = [];
21358
21626
  }
21627
+ pinComponentWhenFormattedBudgetCrosses(msg.ordinal, tcText);
21359
21628
  continue;
21360
21629
  }
21361
21630
  const role = compactRole(msg.role);
@@ -21372,11 +21641,16 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
21372
21641
  if (currentBlock && currentBlock.role === role) {
21373
21642
  currentBlock.endOrdinal = msg.ordinal;
21374
21643
  currentBlock.parts.push(text);
21644
+ currentBlock.partMeta.push({
21645
+ ordinal: msg.ordinal,
21646
+ toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
21647
+ });
21375
21648
  currentBlock.meta.push(...pendingNoiseMeta, meta);
21376
21649
  currentBlock.commitHashes = mergeCommitHashes(currentBlock.commitHashes, compacted.commitHashes);
21377
21650
  if (msgHasNarrative)
21378
21651
  currentBlock.isToolOnly = false;
21379
21652
  pendingNoiseMeta = [];
21653
+ pinComponentWhenFormattedBudgetCrosses(msg.ordinal, text);
21380
21654
  continue;
21381
21655
  }
21382
21656
  if (!flushCurrentBlock())
@@ -21386,11 +21660,18 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
21386
21660
  startOrdinal: pendingNoiseMeta[0]?.ordinal ?? msg.ordinal,
21387
21661
  endOrdinal: msg.ordinal,
21388
21662
  parts: [text],
21663
+ partMeta: [
21664
+ {
21665
+ ordinal: msg.ordinal,
21666
+ toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
21667
+ }
21668
+ ],
21389
21669
  meta: [...pendingNoiseMeta, meta],
21390
21670
  commitHashes: [...compacted.commitHashes],
21391
21671
  isToolOnly: !msgHasNarrative
21392
21672
  };
21393
21673
  pendingNoiseMeta = [];
21674
+ pinComponentWhenFormattedBudgetCrosses(msg.ordinal, text);
21394
21675
  }
21395
21676
  if (flushCurrentBlock() && pendingNoiseMeta.length > 0) {
21396
21677
  highestScannedOrdinal = Math.max(highestScannedOrdinal, pendingNoiseMeta[pendingNoiseMeta.length - 1]?.ordinal ?? highestScannedOrdinal);
@@ -21421,7 +21702,8 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
21421
21702
  ...messagesProcessed === 0 && text.length === 0 ? { filteredNoiseLines: pendingNoiseMeta } : {},
21422
21703
  commitClusterCount: commitClusters,
21423
21704
  toolOnlyRanges,
21424
- completedToolArcs
21705
+ completedToolArcs,
21706
+ toolResultBoundaries
21425
21707
  };
21426
21708
  }
21427
21709
 
@@ -21771,19 +22053,25 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, _lastIndexedOrdinal,
21771
22053
  }
21772
22054
  return inserted;
21773
22055
  }
21774
- function getMessageHistoryOrphanSweepState(db) {
21775
- return db.prepare("SELECT cursor_session_id, last_swept_at FROM message_history_orphan_sweep WHERE harness = 'opencode'").get() ?? {};
22056
+ function openCodeSweepHarness() {
22057
+ const harness = getHarness();
22058
+ if (harness === "opencode" || harness === "opencode2")
22059
+ return harness;
22060
+ throw new Error(`OpenCode orphan sweep cannot read a ${harness} host store`);
22061
+ }
22062
+ function getMessageHistoryOrphanSweepState(db, harness) {
22063
+ return db.prepare("SELECT cursor_session_id, last_swept_at FROM message_history_orphan_sweep WHERE harness = ?").get(harness) ?? {};
21776
22064
  }
21777
- function persistMessageHistoryOrphanSweepState(db, cursor, lastSweptAt) {
22065
+ function persistMessageHistoryOrphanSweepState(db, cursor, lastSweptAt, harness) {
21778
22066
  db.prepare(`INSERT INTO message_history_orphan_sweep (harness, cursor_session_id, last_swept_at)
21779
- VALUES ('opencode', ?, ?)
22067
+ VALUES (?, ?, ?)
21780
22068
  ON CONFLICT(harness) DO UPDATE SET
21781
22069
  cursor_session_id = excluded.cursor_session_id,
21782
- last_swept_at = excluded.last_swept_at`).run(cursor, lastSweptAt);
22070
+ last_swept_at = excluded.last_swept_at`).run(harness, cursor, lastSweptAt);
21783
22071
  }
21784
- function getOpenCodeSessionScopedCandidateSourceSql() {
22072
+ function getOpenCodeSessionScopedCandidateSourceSql(harness) {
21785
22073
  return SESSION_SCOPED_TABLES.filter((definition) => definition.harnessScoped === true).map((definition) => {
21786
- const predicates = ["session_id IS NOT NULL", "harness = 'opencode'"];
22074
+ const predicates = ["session_id IS NOT NULL", `harness = '${harness}'`];
21787
22075
  if (definition.extraPredicate)
21788
22076
  predicates.push(definition.extraPredicate);
21789
22077
  return `SELECT session_id FROM ${definition.table} WHERE ${predicates.join(" AND ")}`;
@@ -21797,7 +22085,8 @@ function sweepOrphanedOpenCodeMessageIndexes(db, openReadableOpenCodeDb, options
21797
22085
  const safetyAgeMs = Math.max(0, options.safetyAgeMs ?? MESSAGE_HISTORY_ORPHAN_SAFETY_AGE_MS);
21798
22086
  const cooldownMs = Math.max(0, options.cooldownMs ?? MESSAGE_HISTORY_ORPHAN_SWEEP_COOLDOWN_MS);
21799
22087
  const unavailableReprobeMs = Math.max(cooldownMs, options.unavailableReprobeMs ?? MESSAGE_HISTORY_ORPHAN_UNAVAILABLE_REPROBE_MS);
21800
- const state = getMessageHistoryOrphanSweepState(db);
22088
+ const harness = openCodeSweepHarness();
22089
+ const state = getMessageHistoryOrphanSweepState(db, harness);
21801
22090
  const cursor = typeof state.cursor_session_id === "string" ? state.cursor_session_id : "";
21802
22091
  if (typeof state.last_swept_at === "number" && state.last_swept_at + cooldownMs > now) {
21803
22092
  return { status: "cooldown", scanned: 0, deleted: 0, cursor };
@@ -21809,12 +22098,12 @@ function sweepOrphanedOpenCodeMessageIndexes(db, openReadableOpenCodeDb, options
21809
22098
  openCodeDb = null;
21810
22099
  }
21811
22100
  if (!openCodeDb) {
21812
- persistMessageHistoryOrphanSweepState(db, cursor, now + unavailableReprobeMs - cooldownMs);
22101
+ persistMessageHistoryOrphanSweepState(db, cursor, now + unavailableReprobeMs - cooldownMs, harness);
21813
22102
  return { status: "source_unavailable", scanned: 0, deleted: 0, cursor };
21814
22103
  }
21815
22104
  try {
21816
22105
  const cutoff = now - safetyAgeMs;
21817
- const candidateSourceSql = getOpenCodeSessionScopedCandidateSourceSql();
22106
+ const candidateSourceSql = getOpenCodeSessionScopedCandidateSourceSql(harness);
21818
22107
  const candidates = db.prepare(`SELECT session_id
21819
22108
  FROM (${candidateSourceSql}) AS session_candidates
21820
22109
  WHERE session_id > ?
@@ -21822,7 +22111,7 @@ function sweepOrphanedOpenCodeMessageIndexes(db, openReadableOpenCodeDb, options
21822
22111
  SELECT 1
21823
22112
  FROM message_history_index
21824
22113
  WHERE message_history_index.session_id = session_candidates.session_id
21825
- AND message_history_index.harness = 'opencode'
22114
+ AND message_history_index.harness = '${harness}'
21826
22115
  AND message_history_index.updated_at > ?
21827
22116
  )
21828
22117
  ORDER BY session_id ASC
@@ -21843,13 +22132,13 @@ function sweepOrphanedOpenCodeMessageIndexes(db, openReadableOpenCodeDb, options
21843
22132
  SELECT 1
21844
22133
  FROM message_history_index
21845
22134
  WHERE message_history_index.session_id = session_candidates.session_id
21846
- AND message_history_index.harness = 'opencode'
22135
+ AND message_history_index.harness = '${harness}'
21847
22136
  AND message_history_index.updated_at > ?
21848
22137
  )
21849
22138
  LIMIT 1`);
21850
22139
  const eligibleSessionIds = missingSessionIds.filter((sessionId) => stillEligible.get(sessionId, cutoff));
21851
- deleted = deleteSessionScopedRows(db, eligibleSessionIds, "opencode");
21852
- persistMessageHistoryOrphanSweepState(db, nextCursor, completedAt);
22140
+ deleted = deleteSessionScopedRows(db, eligibleSessionIds, harness);
22141
+ persistMessageHistoryOrphanSweepState(db, nextCursor, completedAt, harness);
21853
22142
  db.exec("COMMIT");
21854
22143
  committed = true;
21855
22144
  logSlowWriteTransaction("message_index_orphan_sweep", transactionStartedAt);
@@ -23888,9 +24177,9 @@ import { existsSync as existsSync9, readFileSync as readFileSync9, statSync as s
23888
24177
  import { dirname as dirname5, isAbsolute as isAbsolute4, resolve as resolve4 } from "node:path";
23889
24178
 
23890
24179
  // ../plugin/src/tools/light-descriptions.ts
23891
- var CTX_REDUCE_LIGHT_DESCRIPTION = `For ctx_reduce users, mark spent §N§ outputs discardable; release is QUEUED, not immediate, so content stays visible until space is needed. Newest tags stay protected until they age out. Released content becomes a placeholder; recover it only by rerunning the source or recovery tool, so mark only genuinely finished material. Mark analyzed, redundant, persisted, or merely confirmatory outputs; keep user messages, unresolved errors, unextracted evidence, and exact wording. NEVER blanket-mark a large range: review every tag first.`;
24180
+ var CTX_REDUCE_LIGHT_DESCRIPTION = `Marking QUEUES content for release. It stays fully visible to you until it is actually released, which may be the next turn or many turns later. Newest tags stay protected until they age out. Release leaves a placeholder; recover only by rerunning the source or recovery tool. Mark only finished material. Mark analyzed, redundant, saved, or confirmatory outputs; keep user messages, unresolved errors, unextracted evidence, and exact wording. NEVER blanket-mark a large range: review every tag first.`;
23892
24181
  var CTX_EXPAND_LIGHT_DESCRIPTION = `For ctx_expand users, recover compacted conversation by passing a session-history heading's inclusive start/end ordinals. Results are raw [N] U:/A: transcript capped near 15K tokens; oversized ranges return the head and a continuation. Use verbose=true to list each message ordinal, part previews, and tool-output sizes; use message=N for one complete stored message and its tool exchanges. NEVER expand ranges after the last compartment because that live tail is already visible.`;
23893
- var CTX_NOTE_LIGHT_DESCRIPTION = `For ctx_note: write saves, read lists, update changes, dismiss retires one note_id or 1–50 note_ids (choose one); surface_condition makes a smart note. Smart-note conditions must be externally verifiable via GitHub, disk, git, or web—not this conversation or future actions.`;
24182
+ var CTX_NOTE_LIGHT_DESCRIPTION = `For ctx_note: write saves, read lists, update changes one note (note_ids=[N]), dismiss retires 1–50 (note_ids); surface_condition makes a smart note. Smart-note conditions must be externally verifiable via GitHub, disk, git, or web—not this conversation or future actions.`;
23894
24183
  var CTX_MEMORY_LIGHT_DESCRIPTION = `For ctx_memory users, write one standalone durable fact with category and content; update one ID, archive one or more IDs, merge two or more IDs, or get one to twenty numeric IDs. get reads memories in every status; list remains dreamer-only, so primary agents must NEVER assume bulk-list access.`;
23895
24184
  var CTX_SEARCH_LIGHT_DESCRIPTION = `For ctx_search users, retrieve only hidden recall: memories not in <project-memory>, compacted messages outside the live tail, commits, and notes; phrase query as a question carrying exact terms. Omit sources for broad search; select memory, message, git_commit, or note, or pass memory IDs directly. Hits expand through ctx_expand.`;
23896
24185
 
@@ -24157,8 +24446,8 @@ function createPromptSurfaceRuntime(options) {
24157
24446
  return content;
24158
24447
  };
24159
24448
  return {
24160
- resolveRegistration(config) {
24161
- const { preset } = resolvePromptSurface(config, undefined);
24449
+ resolveRegistration(config, modelKey) {
24450
+ const { preset } = resolvePromptSurface(config, modelKey);
24162
24451
  const overrides = config?.tool_descriptions ?? {};
24163
24452
  for (const [toolId, description] of Object.entries(overrides)) {
24164
24453
  if (!PROMPT_SURFACE_TOOL_ID_SET.has(toolId)) {
@@ -25762,6 +26051,11 @@ function parsePiConfig(rawConfig, recoveredTopLevelKeys = []) {
25762
26051
  }
25763
26052
  delete patched[key];
25764
26053
  const defaultValue = defaults[key];
26054
+ const invalidRawValue = rawConfig[key];
26055
+ if (key === "protected_tokens" && typeof invalidRawValue === "number" && invalidRawValue < PROTECTED_TOKENS_MIN) {
26056
+ warnings.push(`protected_tokens is a token floor (minimum ${PROTECTED_TOKENS_MIN}, default derived from the context window); ${invalidRawValue} looks like the old protected_tags count. Remove the key to use the default, or set a token count such as 16000.`);
26057
+ continue;
26058
+ }
25765
26059
  warnings.push(`"${key}": invalid value (${redactConfigValue(rawConfig[key])}), using default ${JSON.stringify(defaultValue)}.`);
25766
26060
  }
25767
26061
  const retryParsed = MagicContextConfigSchema.safeParse(patched);
@@ -27558,6 +27852,27 @@ var embeddingRowMetadata = new WeakMap;
27558
27852
  function isSynapseEmbeddingTruncated(vector) {
27559
27853
  return embeddingRowMetadata.get(vector)?.truncated === true;
27560
27854
  }
27855
+ function toSynapseLaneDescriptor(metadata) {
27856
+ const tokenBudget = metadata.recommended_token_budget;
27857
+ return {
27858
+ lane: metadata.model,
27859
+ ...metadata.device_class ? { device_class: metadata.device_class } : {},
27860
+ max_tokens: metadata.max_tokens,
27861
+ max_tokens_source: metadata.max_tokens_source,
27862
+ ...metadata.bucket_ladder ? { bucket_ladder: [...metadata.bucket_ladder] } : {},
27863
+ ...metadata.dims ? { dims: metadata.dims } : {},
27864
+ ...metadata.dtype ? { dtype: metadata.dtype } : {},
27865
+ ...typeof metadata.certified === "boolean" ? { certified: metadata.certified } : {},
27866
+ ...metadata.warm_load_cost_hint_ms !== undefined ? { warm_load_cost_hint_ms: metadata.warm_load_cost_hint_ms } : {},
27867
+ ...metadata.recommended_batch ? {
27868
+ recommended_batch: {
27869
+ rows: metadata.recommended_batch,
27870
+ ...tokenBudget !== undefined ? { token_budget: tokenBudget } : {}
27871
+ }
27872
+ } : {},
27873
+ warm: metadata.max_tokens_source === "runtime_bucket" || metadata.max_tokens_source === "worker_bucket"
27874
+ };
27875
+ }
27561
27876
  function formatSynapseLaneDescriptor(descriptor) {
27562
27877
  const certified = descriptor.certified === undefined ? "unknown" : String(descriptor.certified);
27563
27878
  return `lane=${descriptor.lane}; device_class=${descriptor.device_class ?? "unknown"}; ` + `max_tokens=${descriptor.max_tokens} (${descriptor.max_tokens_source}); ` + `certified=${certified}; warm=${descriptor.warm ? "yes" : "no"}; ` + `warm_load_cost_hint_ms=${descriptor.warm_load_cost_hint_ms ?? "unknown"}`;
@@ -29362,6 +29677,7 @@ async function injectWasmOrt() {
29362
29677
  try {
29363
29678
  const { module: ortWeb, entryPath } = await importWasmOrtForRuntime();
29364
29679
  if (ortWeb.env?.wasm) {
29680
+ ortWeb.env.wasm.numThreads = 1;
29365
29681
  ortWeb.env.wasm.wasmPaths = `${pathToFileURL2(dirname8(entryPath)).href}/`;
29366
29682
  }
29367
29683
  globalThis[Symbol.for("onnxruntime")] = ortWeb;
@@ -30873,6 +31189,13 @@ function updatePersistedShadowBackfillState(db, projectIdentity, scope, modelId,
30873
31189
  SET provenance_json = ?
30874
31190
  WHERE project_path = ? AND scope = ? AND model_id = ?`).run(JSON.stringify(provenance), projectIdentity, scope, modelId);
30875
31191
  }
31192
+ function shadowDescriptorProvenanceJson(db, projectIdentity, scope, modelId, synapseProvenance) {
31193
+ const provenance = typeof synapseProvenance === "object" && synapseProvenance !== null && !Array.isArray(synapseProvenance) ? { ...synapseProvenance } : synapseProvenance === undefined ? {} : { synapse_provenance: synapseProvenance };
31194
+ const existing = getPersistedShadowBackfillState(db, projectIdentity, scope, modelId);
31195
+ if (existing)
31196
+ provenance[SHADOW_BACKFILL_PROVENANCE_KEY2] = existing;
31197
+ return JSON.stringify(provenance);
31198
+ }
30876
31199
  function persistPrimaryDescriptor(db, registration) {
30877
31200
  const descriptorTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'embedding_registrations'").get();
30878
31201
  if (!descriptorTable)
@@ -30892,6 +31215,43 @@ function persistPrimaryDescriptor(db, registration) {
30892
31215
  generation = excluded.generation,
30893
31216
  updated_at = excluded.updated_at`).run(registration.projectIdentity, registration.providerIdentity, registration.modelId, registration.chunkModelId, fields.fingerprint ?? "", fields.tableEpoch ?? 0, fields.dims ?? 0, JSON.stringify(fields.provenance ?? {}), registration.generation, Date.now());
30894
31217
  }
31218
+ function persistShadowDescriptor(db, registration) {
31219
+ const descriptorTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'shadow_embedding_registrations'").get();
31220
+ if (!descriptorTable)
31221
+ return;
31222
+ const fields = synapseConfigFields(registration.config);
31223
+ const now = Date.now();
31224
+ db.prepare(`INSERT INTO shadow_embedding_registrations
31225
+ (project_path, scope, model_id, generation, fingerprint, table_epoch, dims, provenance_json, updated_at)
31226
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
31227
+ ON CONFLICT(project_path, scope, model_id) DO UPDATE SET
31228
+ generation = excluded.generation,
31229
+ fingerprint = excluded.fingerprint,
31230
+ table_epoch = excluded.table_epoch,
31231
+ dims = excluded.dims,
31232
+ provenance_json = excluded.provenance_json,
31233
+ updated_at = excluded.updated_at`).run(registration.projectIdentity, "memory", registration.modelId, registration.generation, fields.fingerprint ?? "", fields.tableEpoch ?? 0, fields.dims ?? 0, shadowDescriptorProvenanceJson(db, registration.projectIdentity, "memory", registration.modelId, fields.provenance), now);
31234
+ db.prepare(`INSERT INTO shadow_embedding_registrations
31235
+ (project_path, scope, model_id, generation, fingerprint, table_epoch, dims, provenance_json, updated_at)
31236
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
31237
+ ON CONFLICT(project_path, scope, model_id) DO UPDATE SET
31238
+ generation = excluded.generation,
31239
+ fingerprint = excluded.fingerprint,
31240
+ table_epoch = excluded.table_epoch,
31241
+ dims = excluded.dims,
31242
+ provenance_json = excluded.provenance_json,
31243
+ updated_at = excluded.updated_at`).run(registration.projectIdentity, "commit", registration.modelId, registration.generation, fields.fingerprint ?? "", fields.tableEpoch ?? 0, fields.dims ?? 0, shadowDescriptorProvenanceJson(db, registration.projectIdentity, "commit", registration.modelId, fields.provenance), now);
31244
+ db.prepare(`INSERT INTO shadow_embedding_registrations
31245
+ (project_path, scope, model_id, generation, fingerprint, table_epoch, dims, provenance_json, updated_at)
31246
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
31247
+ ON CONFLICT(project_path, scope, model_id) DO UPDATE SET
31248
+ generation = excluded.generation,
31249
+ fingerprint = excluded.fingerprint,
31250
+ table_epoch = excluded.table_epoch,
31251
+ dims = excluded.dims,
31252
+ provenance_json = excluded.provenance_json,
31253
+ updated_at = excluded.updated_at`).run(registration.projectIdentity, "chunk", registration.chunkModelId, registration.generation, fields.fingerprint ?? "", fields.tableEpoch ?? 0, fields.dims ?? 0, shadowDescriptorProvenanceJson(db, registration.projectIdentity, "chunk", registration.chunkModelId, fields.provenance), now);
31254
+ }
30895
31255
  function resolveEmbeddingConfig(config) {
30896
31256
  if (!config || config.provider === "local") {
30897
31257
  return {
@@ -31315,6 +31675,91 @@ function registerProjectEmbedding(db, projectIdentity, config, features, sourceD
31315
31675
  }
31316
31676
  return snapshotFor(registration);
31317
31677
  }
31678
+ function registerProjectShadowEmbedding(db, projectIdentity, config, sourceDirectory, options = {}) {
31679
+ const resolvedConfig = resolveEmbeddingConfig(config);
31680
+ if (resolvedConfig.provider !== "synapse") {
31681
+ throw new Error("Shadow embedding registration requires the synapse provider");
31682
+ }
31683
+ const providerIdentity = getEmbeddingProviderIdentity(resolvedConfig);
31684
+ const chunkModelId = getChunkEmbeddingModelId(resolvedConfig, providerIdentity);
31685
+ const provider = createProvider(resolvedConfig, {
31686
+ projectRoot: sourceDirectory,
31687
+ session: `shadow:${projectIdentity}`
31688
+ });
31689
+ if (!provider)
31690
+ return null;
31691
+ const prior = shadowRegistrations.get(projectIdentity);
31692
+ if (prior && prior.providerIdentity === providerIdentity) {
31693
+ provider.dispose();
31694
+ dbForShadowQueue.set(projectIdentity, db);
31695
+ persistShadowDescriptor(db, prior);
31696
+ const backfillAlreadyArmed = hasPendingShadowBackfill(projectIdentity) || shadowQueue.some((item) => item.projectIdentity === projectIdentity);
31697
+ if (!backfillAlreadyArmed || options.manualBackfill === true) {
31698
+ maybeArmShadowBackfill(db, projectIdentity, prior, options.manualBackfill === true);
31699
+ }
31700
+ return {
31701
+ ...snapshotFor({
31702
+ projectIdentity,
31703
+ sourceDirectory,
31704
+ config: prior.config,
31705
+ providerIdentity: prior.providerIdentity,
31706
+ runtimeFingerprint: `shadow:${prior.providerIdentity}`,
31707
+ provider: prior.provider,
31708
+ generation: prior.generation,
31709
+ features: { memoryEnabled: true, gitCommitEnabled: true },
31710
+ modelId: prior.modelId,
31711
+ chunkModelId: prior.chunkModelId,
31712
+ observationMode: false
31713
+ }),
31714
+ provider: "synapse"
31715
+ };
31716
+ }
31717
+ const generation = ++globalRegistrationGeneration;
31718
+ const registration = {
31719
+ projectIdentity,
31720
+ sourceDirectory,
31721
+ config: resolvedConfig,
31722
+ provider,
31723
+ providerIdentity,
31724
+ modelId: providerIdentity,
31725
+ chunkModelId,
31726
+ generation
31727
+ };
31728
+ shadowRegistrations.set(projectIdentity, registration);
31729
+ dbForShadowQueue.set(projectIdentity, db);
31730
+ if (prior) {
31731
+ disposeProvider(prior.provider);
31732
+ for (const scope of ["memory", "commit", "chunk"]) {
31733
+ const scopeKey = `${projectIdentity}:${scope}`;
31734
+ shadowBackfillLastIds.delete(scopeKey);
31735
+ shadowBackfillStopReasons.delete(scopeKey);
31736
+ shadowBackfillLastWriteOutcomes.delete(scopeKey);
31737
+ }
31738
+ }
31739
+ db.transaction(() => {
31740
+ const now = Date.now();
31741
+ recordScopeActiveIdentity(db, projectIdentity, "memory", registration.modelId, now);
31742
+ recordScopeActiveIdentity(db, projectIdentity, "commit", registration.modelId, now);
31743
+ recordScopeActiveIdentity(db, projectIdentity, "chunk", registration.chunkModelId, now);
31744
+ persistShadowDescriptor(db, registration);
31745
+ })();
31746
+ maybeArmShadowBackfill(db, projectIdentity, registration, options.manualBackfill === true);
31747
+ return {
31748
+ projectIdentity,
31749
+ sourceDirectory,
31750
+ providerIdentity,
31751
+ runtimeFingerprint: `shadow:${providerIdentity}`,
31752
+ generation,
31753
+ features: { memoryEnabled: true, gitCommitEnabled: true },
31754
+ enabled: true,
31755
+ gitCommitEnabled: true,
31756
+ modelId: registration.modelId,
31757
+ chunkModelId: registration.chunkModelId,
31758
+ model: "model" in resolvedConfig && typeof resolvedConfig.model === "string" ? resolvedConfig.model : registration.modelId,
31759
+ provider: "synapse",
31760
+ ...synapseDescriptorFromConfig(resolvedConfig) ? { synapseDescriptor: synapseDescriptorFromConfig(resolvedConfig) } : {}
31761
+ };
31762
+ }
31318
31763
  function startShadowWorker() {
31319
31764
  if (shadowWorker)
31320
31765
  return;
@@ -31502,6 +31947,56 @@ function pumpShadowBackfill() {
31502
31947
  pendingShadowBackfills.delete(projectIdentity);
31503
31948
  }
31504
31949
  }
31950
+ function maybeArmShadowBackfill(db, projectIdentity, shadow, manualBackfill = false) {
31951
+ if (untrustedLoadProjects.has(projectIdentity))
31952
+ return;
31953
+ const primary = projectRegistrations.get(projectIdentity);
31954
+ if (!primary)
31955
+ return;
31956
+ const pending = new Set;
31957
+ for (const scope of ["memory", "commit", "chunk"]) {
31958
+ const primaryModelId = shadowModelIdForScope(primary, scope);
31959
+ const shadowModelId = shadowModelIdForScope(shadow, scope);
31960
+ const stallKey = `${projectIdentity}:${scope}`;
31961
+ if (primaryModelId === "off" || shadowModelId === "off")
31962
+ continue;
31963
+ const batch = shadowBackfillCandidateBatch(db, projectIdentity, scope, primaryModelId, shadow, SHADOW_MAX_ITEMS_PER_TICK);
31964
+ const persisted = getPersistedShadowBackfillState(db, projectIdentity, scope, shadowModelId);
31965
+ if (batch.ids.length === 0) {
31966
+ if (persisted?.stopReason === "stalled_no_progress") {
31967
+ shadowBackfillStopReasons.set(stallKey, "drained");
31968
+ updatePersistedShadowBackfillState(db, projectIdentity, scope, shadowModelId, (state) => ({
31969
+ ...state,
31970
+ stopReason: "drained",
31971
+ candidateSignature: undefined,
31972
+ writeRefusalReason: undefined,
31973
+ stoppedAt: shadowBackfillNow()
31974
+ }));
31975
+ }
31976
+ continue;
31977
+ }
31978
+ if (!manualBackfill && persisted?.stopReason === "stalled_no_progress" && persisted.candidateSignature === batch.signature) {
31979
+ shadowBackfillStopReasons.set(stallKey, "stalled_no_progress");
31980
+ continue;
31981
+ }
31982
+ shadowBackfillStopReasons.delete(stallKey);
31983
+ shadowBackfillLastIds.delete(stallKey);
31984
+ shadowBackfillLastWriteOutcomes.delete(stallKey);
31985
+ updatePersistedShadowBackfillState(db, projectIdentity, scope, shadowModelId, (state) => ({
31986
+ ...state,
31987
+ stopReason: undefined,
31988
+ candidateSignature: undefined,
31989
+ writeRefusalReason: undefined,
31990
+ stoppedAt: undefined
31991
+ }));
31992
+ pending.add(scope);
31993
+ }
31994
+ if (pending.size === 0)
31995
+ return;
31996
+ pendingShadowBackfills.set(projectIdentity, pending);
31997
+ pumpShadowBackfill();
31998
+ startShadowWorker();
31999
+ }
31505
32000
  async function embedShadowItems(registration, items, db, scope) {
31506
32001
  const raw = registration.config;
31507
32002
  const fingerprint = typeof raw.synapse_fingerprint === "string" ? raw.synapse_fingerprint : "";
@@ -31759,6 +32254,26 @@ function registerProjectInObservationMode(db, projectIdentity, sourceDirectory,
31759
32254
  disposeProvider(prior?.provider ?? null);
31760
32255
  return snapshotFor(registration);
31761
32256
  }
32257
+ function unregisterProjectShadowEmbedding(projectIdentity) {
32258
+ const shadow = shadowRegistrations.get(projectIdentity);
32259
+ shadowRegistrations.delete(projectIdentity);
32260
+ dbForShadowQueue.delete(projectIdentity);
32261
+ pendingShadowBackfills.delete(projectIdentity);
32262
+ for (let index = shadowQueue.length - 1;index >= 0; index -= 1) {
32263
+ if (shadowQueue[index].projectIdentity === projectIdentity)
32264
+ shadowQueue.splice(index, 1);
32265
+ }
32266
+ for (const scope of ["memory", "commit", "chunk"]) {
32267
+ const key = `${projectIdentity}:${scope}`;
32268
+ shadowBackfillLastIds.delete(key);
32269
+ shadowBackfillStopReasons.delete(key);
32270
+ shadowBackfillLastWriteOutcomes.delete(key);
32271
+ }
32272
+ const primaryProvider = projectRegistrations.get(projectIdentity)?.provider ?? null;
32273
+ if (shadow?.provider && shadow.provider !== primaryProvider) {
32274
+ disposeProvider(shadow.provider);
32275
+ }
32276
+ }
31762
32277
  function getProjectEmbeddingSnapshot(projectIdentity) {
31763
32278
  const registration = projectRegistrations.get(projectIdentity);
31764
32279
  return registration ? snapshotFor(registration) : null;
@@ -32446,6 +32961,133 @@ function handleUntrustedLoad(db, projectIdentity, directory, detailed) {
32446
32961
  return true;
32447
32962
  }
32448
32963
 
32964
+ // ../plugin/src/plugin/embedding-routing.ts
32965
+ var SYNAPSE_PROBE_TTL_MS = 60000;
32966
+ var synapseProbeCache = new Map;
32967
+ function fallbackConfig(config, provider) {
32968
+ const raw = config;
32969
+ const model = typeof raw.model === "string" ? raw.model.trim() : "";
32970
+ const endpoint = typeof raw.endpoint === "string" ? raw.endpoint.trim() : "";
32971
+ const apiKey = typeof raw.api_key === "string" ? raw.api_key.trim() : "";
32972
+ const inputType = typeof raw.input_type === "string" ? raw.input_type.trim() : "";
32973
+ const queryInputType = typeof raw.query_input_type === "string" ? raw.query_input_type.trim() : "";
32974
+ const queryInstruction = typeof raw.query_instruction === "string" || raw.query_instruction === false ? raw.query_instruction : undefined;
32975
+ const documentPrefix = typeof raw.document_prefix === "string" ? raw.document_prefix : undefined;
32976
+ const truncate = typeof raw.truncate === "string" ? raw.truncate.trim() : "";
32977
+ const maxInputTokens = typeof raw.max_input_tokens === "number" ? raw.max_input_tokens : undefined;
32978
+ if (provider === "off")
32979
+ return { provider: "off" };
32980
+ if (provider === "openai-compatible") {
32981
+ return {
32982
+ provider: "openai-compatible",
32983
+ model,
32984
+ endpoint,
32985
+ ...apiKey ? { api_key: apiKey } : {},
32986
+ ...inputType ? { input_type: inputType } : {},
32987
+ ...queryInputType ? { query_input_type: queryInputType } : {},
32988
+ ...queryInstruction !== undefined ? { query_instruction: queryInstruction } : {},
32989
+ ...documentPrefix !== undefined ? { document_prefix: documentPrefix } : {},
32990
+ ...truncate ? { truncate } : {},
32991
+ ...maxInputTokens !== undefined ? { max_input_tokens: maxInputTokens } : {}
32992
+ };
32993
+ }
32994
+ return {
32995
+ provider: "local",
32996
+ model: model || DEFAULT_LOCAL_EMBEDDING_MODEL,
32997
+ local_runtime: raw.local_runtime === "native" || raw.local_runtime === "wasm" ? raw.local_runtime : "auto",
32998
+ ...maxInputTokens !== undefined ? { max_input_tokens: maxInputTokens } : {}
32999
+ };
33000
+ }
33001
+ function synapseOptions(config, subc, projectRoot, session, metadata) {
33002
+ return {
33003
+ connectionFile: subc.connection_file,
33004
+ projectRoot,
33005
+ session,
33006
+ model: metadata?.model ?? (config.provider === "synapse" && "model" in config ? config.model : undefined) ?? SYNAPSE_DEFAULT_MODEL,
33007
+ ...metadata ? {
33008
+ metadata
33009
+ } : {}
33010
+ };
33011
+ }
33012
+ function probeKey(subc, config) {
33013
+ const model = config.provider === "synapse" && "model" in config ? config.model : SYNAPSE_DEFAULT_MODEL;
33014
+ return `${subc.connection_file}\x00${model ?? SYNAPSE_DEFAULT_MODEL}`;
33015
+ }
33016
+ function discoverSynapseLane(config, subc, projectRoot, session) {
33017
+ const key = probeKey(subc, config);
33018
+ const cached = synapseProbeCache.get(key);
33019
+ if (cached && cached.expiresAt > Date.now())
33020
+ return cached.promise;
33021
+ const promise = SynapseEmbeddingProvider.discover(synapseOptions(config, subc, projectRoot, session));
33022
+ synapseProbeCache.set(key, { expiresAt: Date.now() + SYNAPSE_PROBE_TTL_MS, promise });
33023
+ promise.catch(() => {
33024
+ return;
33025
+ });
33026
+ return promise;
33027
+ }
33028
+ function resolvedSynapseConfig(subc, metadata, projectRoot, session) {
33029
+ return {
33030
+ provider: "synapse",
33031
+ model: metadata.model,
33032
+ max_input_tokens: metadata.max_tokens,
33033
+ synapse_connection_file: subc.connection_file,
33034
+ synapse_fingerprint: metadata.fingerprint,
33035
+ synapse_table_epoch: metadata.table_epoch,
33036
+ ...typeof metadata.dims === "number" ? { synapse_dims: metadata.dims } : {},
33037
+ ...metadata.recommended_batch ? { synapse_recommended_batch: metadata.recommended_batch } : {},
33038
+ ...metadata.recommended_token_budget ? { synapse_recommended_token_budget: metadata.recommended_token_budget } : {},
33039
+ synapse_descriptor: toSynapseLaneDescriptor(metadata),
33040
+ ...metadata.provenance !== undefined ? { synapse_provenance: metadata.provenance } : {}
33041
+ };
33042
+ }
33043
+ async function resolveEmbeddingRouting(args) {
33044
+ const config = args.config.embedding;
33045
+ const subc = args.config.subc;
33046
+ const shadowEnabled = args.config.shadow_embedding?.enabled === true;
33047
+ const warnings = [];
33048
+ if (config.provider !== "synapse") {
33049
+ let shadow = null;
33050
+ if (shadowEnabled && config.provider === "off") {
33051
+ warnings.push("shadow_embedding is ignored when embedding.provider is off");
33052
+ } else if (shadowEnabled && !subc) {
33053
+ warnings.push("shadow_embedding requires a subc block; shadow lane is disabled");
33054
+ } else if (shadowEnabled && subc) {
33055
+ try {
33056
+ const metadata = await discoverSynapseLane(config, subc, args.projectRoot, args.session ?? "routing");
33057
+ shadow = resolvedSynapseConfig(subc, metadata, args.projectRoot, args.session ?? "routing");
33058
+ } catch (error) {
33059
+ warnings.push(`shadow_embedding is unavailable; using the primary ${config.provider} lane: ${error instanceof Error ? error.message : String(error)}`);
33060
+ }
33061
+ }
33062
+ return { primary: config, shadow, warnings };
33063
+ }
33064
+ if (shadowEnabled) {
33065
+ warnings.push("shadow_embedding is ignored when the primary provider is synapse");
33066
+ }
33067
+ const fallbackProvider = config.fallback_provider;
33068
+ const fallback = fallbackConfig(config, fallbackProvider);
33069
+ if (!subc) {
33070
+ warnings.push("embedding.provider synapse requires a subc block; using fallback provider");
33071
+ return { primary: fallback, shadow: null, warnings };
33072
+ }
33073
+ if (!fallbackProvider) {
33074
+ warnings.push("embedding.provider synapse requires embedding.fallback_provider; using local fallback");
33075
+ return { primary: fallbackConfig(config, "local"), shadow: null, warnings };
33076
+ }
33077
+ try {
33078
+ const metadata = await discoverSynapseLane(config, subc, args.projectRoot, args.session ?? "routing");
33079
+ return {
33080
+ primary: resolvedSynapseConfig(subc, metadata, args.projectRoot, args.session ?? "routing"),
33081
+ shadow: null,
33082
+ warnings
33083
+ };
33084
+ } catch (error) {
33085
+ warnings.push(`Synapse is not ready; using embedding.fallback_provider=${fallbackProvider}: ${error instanceof Error ? error.message : String(error)}`);
33086
+ log(`[magic-context] Synapse routing fell back: ${warnings.at(-1)}`);
33087
+ return { primary: fallback, shadow: null, warnings };
33088
+ }
33089
+ }
33090
+
32449
33091
  // src/embedding-bootstrap.ts
32450
33092
  var registrationFingerprintsByDatabase = new WeakMap;
32451
33093
  function configCandidatePaths(directory, loadedPaths) {
@@ -32486,16 +33128,36 @@ async function ensureProjectRegisteredFromPiDirectory(directory, db) {
32486
33128
  handleUntrustedLoad(db, projectIdentity, directory, detailed);
32487
33129
  return;
32488
33130
  }
33131
+ const routing = await resolveEmbeddingRouting({
33132
+ config: detailed.config,
33133
+ projectRoot: directory,
33134
+ session: `bootstrap:${projectIdentity}`
33135
+ });
33136
+ for (const warning of routing.warnings) {
33137
+ log(`[magic-context] ${warning}`);
33138
+ }
32489
33139
  const features = {
32490
33140
  memoryEnabled: detailed.config.memory.enabled,
32491
33141
  gitCommitEnabled: detailed.config.memory.git_commit_indexing.enabled
32492
33142
  };
32493
- registerProjectEmbedding(db, projectIdentity, detailed.config.embedding, features, directory);
32494
- const fingerprintPaths = configCandidatePaths(directory, detailed.loadedFromPaths);
32495
- registrationFingerprints.set(projectIdentity, {
32496
- paths: fingerprintPaths,
32497
- fingerprint: configFingerprint(fingerprintPaths)
32498
- });
33143
+ registerProjectEmbedding(db, projectIdentity, routing.primary, features, directory);
33144
+ if (routing.shadow) {
33145
+ registerProjectShadowEmbedding(db, projectIdentity, routing.shadow, directory);
33146
+ } else {
33147
+ unregisterProjectShadowEmbedding(projectIdentity);
33148
+ }
33149
+ const configuredProvider = detailed.config.embedding.provider;
33150
+ const canDiscover = Boolean(detailed.config.subc) && (configuredProvider === "synapse" ? Boolean(detailed.config.embedding.fallback_provider) : configuredProvider !== "off" && detailed.config.shadow_embedding?.enabled === true);
33151
+ const discoveryFailed = canDiscover && (configuredProvider === "synapse" ? routing.primary.provider !== "synapse" : routing.shadow === null);
33152
+ if (!discoveryFailed) {
33153
+ const fingerprintPaths = configCandidatePaths(directory, detailed.loadedFromPaths);
33154
+ registrationFingerprints.set(projectIdentity, {
33155
+ paths: fingerprintPaths,
33156
+ fingerprint: configFingerprint(fingerprintPaths)
33157
+ });
33158
+ } else {
33159
+ registrationFingerprints.delete(projectIdentity);
33160
+ }
32499
33161
  }
32500
33162
 
32501
33163
  // src/pi-harness-kind.ts
@@ -33124,6 +33786,46 @@ Two recovery modes for finer detail:
33124
33786
  - ctx_expand(message=138) — returns the FULL untruncated content of the message at that ordinal: every text part, and every tool call's complete input + output, read from stored history. This is the cheap way to get back a tool output you dropped with ctx_reduce — the original is still in storage even though the wire shows [dropped §N§]. If the message was deleted from history (session prune/revert), it says so.`;
33125
33787
  var CTX_EXPAND_TOKEN_BUDGET = 15000;
33126
33788
 
33789
+ // ../plugin/src/tools/ctx-expand/mode.ts
33790
+ function isInt(value) {
33791
+ return typeof value === "number" && Number.isInteger(value);
33792
+ }
33793
+ function minOrdinal(domain) {
33794
+ return domain === "non-negative" ? 0 : 1;
33795
+ }
33796
+ function messageError(domain) {
33797
+ return domain === "non-negative" ? "Error: message must be a non-negative integer." : "Error: message must be a positive integer.";
33798
+ }
33799
+ function rangeError(domain) {
33800
+ return domain === "non-negative" ? "Error: provide either message=<ordinal>, or start and end (non-negative integers, start <= end)." : "Error: provide either message=<ordinal>, or start and end (positive integers, start <= end).";
33801
+ }
33802
+ function resolveCtxExpandMode(args, domain) {
33803
+ const min = minOrdinal(domain);
33804
+ const messagePresent = args.message !== undefined && args.message !== null;
33805
+ const message = isInt(args.message) ? args.message : undefined;
33806
+ const start = isInt(args.start) ? args.start : undefined;
33807
+ const end = isInt(args.end) ? args.end : undefined;
33808
+ const messageValid = message !== undefined && message >= min;
33809
+ const rangeValid = start !== undefined && end !== undefined && start >= min && end >= start;
33810
+ const fillerPair = start === 0 && end === 0;
33811
+ const rangeNamed = rangeValid && !fillerPair;
33812
+ if (messageValid && !rangeNamed) {
33813
+ return { kind: "message", message };
33814
+ }
33815
+ if (messagePresent && !messageValid && !rangeNamed) {
33816
+ return { kind: "error", message: messageError(domain) };
33817
+ }
33818
+ if (rangeValid) {
33819
+ return {
33820
+ kind: "range",
33821
+ start,
33822
+ end,
33823
+ verbose: args.verbose === true
33824
+ };
33825
+ }
33826
+ return { kind: "error", message: rangeError(domain) };
33827
+ }
33828
+
33127
33829
  // ../plugin/src/tools/ctx-expand/render.ts
33128
33830
  function isRecord4(value) {
33129
33831
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -33720,27 +34422,26 @@ function createCtxExpandTool(deps) {
33720
34422
  readMessages: () => readPiSessionMessages(ctx)
33721
34423
  });
33722
34424
  try {
33723
- if (params.message !== undefined) {
33724
- if (typeof params.message !== "number" || !Number.isInteger(params.message) || params.message < 1) {
33725
- return err("Error: message must be a positive integer.");
33726
- }
33727
- return ok(renderMessageByOrdinal(sessionId, params.message));
34425
+ const mode = resolveCtxExpandMode(params, "positive");
34426
+ if (mode.kind === "error") {
34427
+ return err(mode.message);
33728
34428
  }
33729
- if (typeof params.start !== "number" || typeof params.end !== "number" || !Number.isInteger(params.start) || !Number.isInteger(params.end) || params.start < 1 || params.end < params.start) {
33730
- return err("Error: provide either message=<ordinal>, or start and end (positive integers, start <= end).");
34429
+ if (mode.kind === "message") {
34430
+ return ok(renderMessageByOrdinal(sessionId, mode.message));
33731
34431
  }
34432
+ const { start, end, verbose } = mode;
33732
34433
  const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
33733
- if (lastCompartmentEnd >= 0 && params.start > lastCompartmentEnd) {
33734
- return ok(`Range ${params.start}-${params.end} is entirely within the live tail (after the last compacted message ${lastCompartmentEnd}); those messages are already visible in context.`);
34434
+ if (lastCompartmentEnd >= 0 && start > lastCompartmentEnd) {
34435
+ return ok(`Range ${start}-${end} is entirely within the live tail (after the last compacted message ${lastCompartmentEnd}); those messages are already visible in context.`);
33735
34436
  }
33736
- const effectiveEnd = lastCompartmentEnd >= 0 ? Math.min(params.end, lastCompartmentEnd) : params.end;
33737
- if (params.verbose === true) {
33738
- const v = renderVerboseRange(sessionId, params.start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET);
34437
+ const effectiveEnd = lastCompartmentEnd >= 0 ? Math.min(end, lastCompartmentEnd) : end;
34438
+ if (verbose) {
34439
+ const v = renderVerboseRange(sessionId, start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET);
33739
34440
  if (!v.text) {
33740
- return ok(`No messages found in range ${params.start}-${effectiveEnd}. The range may be outside this session's history.`);
34441
+ return ok(`No messages found in range ${start}-${effectiveEnd}. The range may be outside this session's history.`);
33741
34442
  }
33742
34443
  const out = [
33743
- `Messages ${params.start}-${v.lastOrdinal} (verbose). Recover any one in full with ctx_expand(message=<ordinal>):`,
34444
+ `Messages ${start}-${v.lastOrdinal} (verbose). Recover any one in full with ctx_expand(message=<ordinal>):`,
33744
34445
  "",
33745
34446
  v.text
33746
34447
  ];
@@ -33750,9 +34451,9 @@ function createCtxExpandTool(deps) {
33750
34451
  return ok(out.join(`
33751
34452
  `));
33752
34453
  }
33753
- const chunk = readSessionChunk(sessionId, CTX_EXPAND_TOKEN_BUDGET, params.start, effectiveEnd + 1);
34454
+ const chunk = readSessionChunk(sessionId, CTX_EXPAND_TOKEN_BUDGET, start, effectiveEnd + 1);
33754
34455
  if (!chunk.text || chunk.messageCount === 0) {
33755
- return ok(`No messages found in range ${params.start}-${params.end}. The range may be outside this session's history.`);
34456
+ return ok(`No messages found in range ${start}-${end}. The range may be outside this session's history.`);
33756
34457
  }
33757
34458
  const lines = [];
33758
34459
  lines.push(`Messages ${chunk.startIndex}-${chunk.endIndex} (${chunk.messageCount} messages, ~${chunk.tokenEstimate} tokens):`);
@@ -35376,7 +36077,7 @@ function err2(text) {
35376
36077
  };
35377
36078
  }
35378
36079
  function normalizeLimit(limit) {
35379
- if (typeof limit !== "number" || !Number.isFinite(limit))
36080
+ if (typeof limit !== "number" || !Number.isFinite(limit) || limit === 0)
35380
36081
  return DEFAULT_LIST_LIMIT;
35381
36082
  return Math.max(1, Math.floor(limit));
35382
36083
  }
@@ -35451,8 +36152,8 @@ function formatGetOutput(args) {
35451
36152
 
35452
36153
  `);
35453
36154
  }
35454
- function updateMemoryContentInCurrentTransaction(db, memory, content, normalizedHash) {
35455
- db.prepare("UPDATE memories SET content = ?, normalized_hash = ?, updated_at = ? WHERE id = ?").run(content, normalizedHash, Date.now(), memory.id);
36155
+ function updateMemoryContentInCurrentTransaction(db, memory, content, normalizedHash, category) {
36156
+ db.prepare("UPDATE memories SET content = ?, normalized_hash = ?, category = ?, updated_at = ? WHERE id = ?").run(content, normalizedHash, category, Date.now(), memory.id);
35456
36157
  if (hasMemoryShareableColumn(db)) {
35457
36158
  db.prepare("UPDATE memories SET shareable = 0 WHERE id = ?").run(memory.id);
35458
36159
  }
@@ -35513,14 +36214,17 @@ function createCtxMemoryTool(deps) {
35513
36214
  await deps.ensureProjectRegistered?.(ctx.cwd, deps.db);
35514
36215
  const activeCurateCategory = dreamerAllowed ? getActiveCurateCategory(deps.db, projectIdentity) : null;
35515
36216
  if (activeCurateCategory) {
36217
+ const usesCategory = ["write", "update", "merge", "list"].includes(params.action);
36218
+ const usesIds = ["update", "archive", "merge", "get"].includes(params.action);
36219
+ const usesSuccessor = params.action === "update" || params.action === "archive";
35516
36220
  const scopeRefusal = getCurateCategoryScopeRefusal({
35517
36221
  scope: activeCurateCategory,
35518
36222
  action: params.action,
35519
- requestedCategory: params.category,
35520
- ids: [
36223
+ requestedCategory: usesCategory ? params.category : undefined,
36224
+ ids: usesIds ? [
35521
36225
  ...params.ids ?? [],
35522
- ...Number.isInteger(params.superseded_by) ? [params.superseded_by] : []
35523
- ],
36226
+ ...usesSuccessor && Number.isInteger(params.superseded_by) ? [params.superseded_by] : []
36227
+ ] : [],
35524
36228
  categoryForId: (id) => {
35525
36229
  const category = getMemoryById(deps.db, id)?.category;
35526
36230
  return category ? curateCategoryForMemoryCategory(category) : null;
@@ -35655,18 +36359,19 @@ function createCtxMemoryTool(deps) {
35655
36359
  return err2(inactiveMemoryError(updateId, "updating"));
35656
36360
  }
35657
36361
  const normalizedHash = computeNormalizedHash(content);
36362
+ const targetCategory = params.category ?? memory.category;
35658
36363
  const targetIdentity = targetIdentityForStoredPath(memory.projectPath);
35659
- const duplicate = getMemoryByHash(deps.db, targetIdentity, memory.category, normalizedHash);
36364
+ const duplicate = getMemoryByHash(deps.db, targetIdentity, targetCategory, normalizedHash);
35660
36365
  if (duplicate && duplicate.id !== memory.id) {
35661
36366
  return err2(`Error: Memory content already exists as ID ${duplicate.id}; merge or archive duplicates instead.`);
35662
36367
  }
35663
36368
  runImmediateTransaction(deps.db, () => {
35664
- updateMemoryContentInCurrentTransaction(deps.db, memory, content, normalizedHash);
36369
+ updateMemoryContentInCurrentTransaction(deps.db, memory, content, normalizedHash, targetCategory);
35665
36370
  queueMemoryMutation(deps.db, {
35666
36371
  projectPath: targetIdentity,
35667
36372
  mutationType: "update",
35668
36373
  targetMemoryId: memory.id,
35669
- category: memory.category,
36374
+ category: targetCategory,
35670
36375
  newContent: content
35671
36376
  });
35672
36377
  });
@@ -35676,7 +36381,7 @@ function createCtxMemoryTool(deps) {
35676
36381
  memoryId: memory.id,
35677
36382
  content
35678
36383
  });
35679
- return ok2(`Updated memory [ID: ${memory.id}] in ${memory.category}.`);
36384
+ return ok2(`Updated memory [ID: ${memory.id}] in ${targetCategory}.`);
35680
36385
  }
35681
36386
  if (params.action === "merge") {
35682
36387
  const ids = params.ids;
@@ -36398,7 +37103,7 @@ Use a note when something matters LATER but not in the next few steps: "revisit
36398
37103
  Actions:
36399
37104
  - write: save a note (content). Add surface_condition to make it a smart note (below).
36400
37105
  - read: list notes, newest first. Default: latest active session notes + ready smart notes; page older ones with limit/offset, or inspect other states with filter.
36401
- - update: change a note by note_id. dismiss: retire one by note_id or 1–50 by note_ids; provide exactly one.
37106
+ - update: change one note (note_ids=[N]). dismiss: retire 1–50 notes (note_ids=[...]).
36402
37107
 
36403
37108
  Smart notes: pass surface_condition and the note stays hidden until a background checker confirms the condition — using ONLY externally verifiable signals (GitHub state via gh, files on disk, git history, web pages). It cannot see this conversation, so the condition must be checkable from outside:
36404
37109
  ✓ "When PR #42 in cortexkit/magic-context is merged"
@@ -36431,13 +37136,10 @@ var ParamsSchema2 = _Object_({
36431
37136
  surface_condition: Optional(String2({
36432
37137
  description: "Externally verifiable condition for smart notes. A background checker verifies it using ONLY outside signals (GitHub state via gh, files on disk, git history, web) — it cannot see this conversation. Use for PR/issue state, release tags, file contents, workflow runs. NOT for 'when the user mentions X' / 'when we revisit Y' — write a regular note instead."
36433
37138
  })),
36434
- note_id: Optional(Number2({
36435
- description: "Note ID (required for 'dismiss' and 'update' actions)."
36436
- })),
36437
37139
  note_ids: Optional(_Array_(Integer({ minimum: 1, maximum: Number.MAX_SAFE_INTEGER }), {
36438
37140
  minItems: 1,
36439
37141
  maxItems: 50,
36440
- description: "One to fifty note ids for 'dismiss' only; do not combine with note_id."
37142
+ description: "Note ids: exactly one for 'update', one to fifty for 'dismiss'. Ignored by 'write' and 'read'."
36441
37143
  })),
36442
37144
  filter: Optional(Union(FILTER_VALUES.map((value) => Literal(value)), {
36443
37145
  description: "Optional read filter. Defaults to active session notes + ready smart notes. Use 'all' to inspect every status or 'pending' to inspect unsurfaced smart notes."
@@ -36482,16 +37184,17 @@ function formatNoteLine(note) {
36482
37184
  }
36483
37185
  var DISMISS_FOOTER = `
36484
37186
 
36485
- To dismiss a stale note: ctx_note(action="dismiss", note_id=N) or note_ids=[N,...]`;
37187
+ To dismiss a stale note: ctx_note(action="dismiss", note_ids=[N])`;
36486
37188
  function formatDismissResults(results) {
36487
37189
  const dismissedCount = results.filter((result) => result.outcome === "dismissed").length;
36488
37190
  return `Dismissed ${dismissedCount} of ${results.length} notes.
36489
37191
  ${results.map((result) => `- Note #${result.noteId}: ${result.outcome}`).join(`
36490
37192
  `)}`;
36491
37193
  }
36492
- function parseDismissNoteIds(value) {
36493
- if (!Array.isArray(value) || value.length < 1 || value.length > 50 || value.some((id) => typeof id !== "number" || !Number.isInteger(id) || id <= 0)) {
36494
- return "Error: 'note_ids' must contain 1 to 50 positive integer ids when action is 'dismiss'.";
37194
+ function parseNoteIds(action, value) {
37195
+ const max = action === "update" ? 1 : 50;
37196
+ if (!Array.isArray(value) || value.length < 1 || value.length > max || value.some((id) => typeof id !== "number" || !Number.isInteger(id) || id <= 0)) {
37197
+ return action === "update" ? "Error: 'note_ids' must contain exactly one positive integer id when action is 'update'." : "Error: 'note_ids' must contain 1 to 50 positive integer ids when action is 'dismiss'.";
36495
37198
  }
36496
37199
  return value;
36497
37200
  }
@@ -36519,7 +37222,6 @@ function createCtxNoteTool(deps) {
36519
37222
  },
36520
37223
  content: "string",
36521
37224
  surface_condition: "string",
36522
- note_id: "number",
36523
37225
  note_ids: { type: "array", items: "number", maxItems: 50 },
36524
37226
  filter: { type: "enum", values: FILTER_VALUES },
36525
37227
  limit: "number",
@@ -36528,17 +37230,9 @@ function createCtxNoteTool(deps) {
36528
37230
  const sessionId = ctx.sessionManager.getSessionId();
36529
37231
  const dreamerEnabled = deps.resolveDreamerEnabled?.(ctx) ?? deps.dreamerEnabled;
36530
37232
  const action = params.action ?? (params.content?.trim() ? "write" : "read");
36531
- const hasNoteId = params.note_id !== undefined;
36532
- const hasNoteIds = params.note_ids !== undefined;
36533
- if (hasNoteId && hasNoteIds) {
36534
- return err3("Error: 'note_id' and 'note_ids' cannot be used together; provide one or the other.");
36535
- }
36536
- if (hasNoteIds && action !== "dismiss") {
36537
- return err3("Error: 'note_ids' is only valid when action is 'dismiss'.");
36538
- }
36539
- const dismissNoteIds = action === "dismiss" && hasNoteIds ? parseDismissNoteIds(params.note_ids) : undefined;
36540
- if (typeof dismissNoteIds === "string")
36541
- return err3(dismissNoteIds);
37233
+ const noteIds = action === "dismiss" || action === "update" ? parseNoteIds(action, params.note_ids) : undefined;
37234
+ if (typeof noteIds === "string")
37235
+ return err3(noteIds);
36542
37236
  if (action === "write") {
36543
37237
  const content = params.content?.trim();
36544
37238
  if (!content)
@@ -36589,25 +37283,21 @@ wake plane active — create a scheduled wake instead; stored as a plain note.`)
36589
37283
  if (!projectIdentity) {
36590
37284
  return err3("Error: Could not resolve project identity for note dismiss.");
36591
37285
  }
36592
- if (dismissNoteIds) {
36593
- return ok3(formatDismissResults(dismissNotes(deps.db, dismissNoteIds, {
37286
+ const ids = noteIds;
37287
+ if (ids.length > 1) {
37288
+ return ok3(formatDismissResults(dismissNotes(deps.db, ids, {
36594
37289
  projectPath: projectIdentity,
36595
37290
  sessionId
36596
37291
  })));
36597
37292
  }
36598
- if (typeof params.note_id !== "number") {
36599
- return err3("Error: 'note_id' is required when action is 'dismiss'.");
36600
- }
36601
- const dismissed = dismissNote(deps.db, params.note_id, {
37293
+ const dismissed = dismissNote(deps.db, ids[0], {
36602
37294
  projectPath: projectIdentity,
36603
37295
  sessionId
36604
37296
  });
36605
- return dismissed ? ok3(`Note #${params.note_id} dismissed.`) : err3(`Error: Note #${params.note_id} not found in your session/project or already dismissed.`);
37297
+ return dismissed ? ok3(`Note #${ids[0]} dismissed.`) : err3(`Error: Note #${ids[0]} not found in your session/project or already dismissed.`);
36606
37298
  }
36607
37299
  if (action === "update") {
36608
- if (typeof params.note_id !== "number") {
36609
- return err3("Error: 'note_id' is required when action is 'update'.");
36610
- }
37300
+ const noteId = noteIds[0];
36611
37301
  const updates = {};
36612
37302
  if (params.content?.trim())
36613
37303
  updates.content = params.content.trim();
@@ -36627,19 +37317,19 @@ wake plane active — create a scheduled wake instead; stored as a plain note.`)
36627
37317
  if (!projectIdentity) {
36628
37318
  return err3("Error: Could not resolve project identity for note update.");
36629
37319
  }
36630
- const updated = updateNote(deps.db, params.note_id, updates, {
37320
+ const updated = updateNote(deps.db, noteId, updates, {
36631
37321
  projectPath: projectIdentity,
36632
37322
  sessionId
36633
37323
  });
36634
37324
  if (!updated) {
36635
- return err3(`Error: Note #${params.note_id} not found in your session/project.`);
37325
+ return err3(`Error: Note #${noteId} not found in your session/project.`);
36636
37326
  }
36637
37327
  const parts = [];
36638
37328
  if (updates.content)
36639
37329
  parts.push(`content: ${updates.content}`);
36640
37330
  if (updates.surfaceCondition)
36641
37331
  parts.push(`condition: ${updates.surfaceCondition}`);
36642
- return ok3(`Updated note #${params.note_id}
37332
+ return ok3(`Updated note #${noteId}
36643
37333
  - ${parts.join(`
36644
37334
  - `)}${compilation ? conditionCompileReplySuffix(compilation) : ""}`);
36645
37335
  }
@@ -36799,7 +37489,7 @@ function parseInteger(str) {
36799
37489
  var CTX_REDUCE_DESCRIPTION = `Mark spent tagged content as discardable to reclaim context space. This is NOT an immediate delete. Use §N§ identifiers visible in the conversation. The \`drop\` param accepts ranges: "3-5", "1,2,9", "1-5,8".
36800
37490
 
36801
37491
  How it works:
36802
- - Marking QUEUES content for release. It stays fully visible to you until context space is actually needed — which may be as soon as the next turn if you are already under pressure, or many turns later if not. So mark spent outputs as soon as you finish with them; don't hoard the call for the end of the turn.
37492
+ - Marking QUEUES content for release. It stays fully visible to you until it is actually released, which may be the next turn or many turns later. Mark spent outputs as soon as you finish with them; don't hoard the call for the end of the turn.
36803
37493
  - The newest tags are protected: marking one just queues it until it ages out of the recent window, so marking recent output is harmless.
36804
37494
  - When content is finally released it becomes a short placeholder, and re-running the tool is the only way to get it back. So mark only what you are genuinely DONE with — the test is "have I extracted what I need from this?", not "is it safe / do I have time before it drops?".
36805
37495
 
@@ -39588,6 +40278,12 @@ function getWritableOpenCodeDb() {
39588
40278
  throw new Error(`OpenCode database not found at ${dbPath} (source=${resolution.source}; is OpenCode installed?)`);
39589
40279
  }
39590
40280
  const db = new Database(dbPath);
40281
+ try {
40282
+ assertOpenCodeStoreGeneration(db, "v1", dbPath);
40283
+ } catch (error) {
40284
+ closeQuietly(db);
40285
+ throw error;
40286
+ }
39591
40287
  db.exec("PRAGMA busy_timeout=5000");
39592
40288
  db.exec("PRAGMA journal_mode=WAL");
39593
40289
  cachedWriteDb = { path: dbPath, db };
@@ -40440,10 +41136,15 @@ var ParamsSchema4 = _Object_({
40440
41136
  }))
40441
41137
  }, { additionalProperties: true });
40442
41138
  function normalizeLimit3(limit) {
40443
- if (typeof limit !== "number" || !Number.isFinite(limit))
41139
+ if (typeof limit !== "number" || !Number.isFinite(limit) || limit === 0)
40444
41140
  return DEFAULT_LIMIT;
40445
41141
  return Math.max(1, Math.floor(limit));
40446
41142
  }
41143
+ function normalizeSources(sources) {
41144
+ if (sources === undefined || sources.length === 0)
41145
+ return;
41146
+ return sources;
41147
+ }
40447
41148
  function createCtxSearchTool(deps) {
40448
41149
  const resolveProject = deps.resolveProjectIdentity ?? resolveProjectIdentityForSession;
40449
41150
  return {
@@ -40526,7 +41227,7 @@ function createCtxSearchTool(deps) {
40526
41227
  isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
40527
41228
  maxMessageOrdinal: messageOrdinalCutoff,
40528
41229
  gitCommitsEnabled,
40529
- sources: params.sources,
41230
+ sources: normalizeSources(params.sources),
40530
41231
  visibleMemoryIds,
40531
41232
  diagnostics,
40532
41233
  gitRepositoryAvailable: directoryHasGitMetadata(ctx.cwd),
@@ -40660,4 +41361,4 @@ function registerMagicContextTools(pi, opts) {
40660
41361
  }
40661
41362
  }
40662
41363
 
40663
- export { COMPACTION_ENABLED_PATH, isDreamerRunnable, isCompactionEnabled, migrateMagicContextConfigLocations, withContentLanguageDirective, withMigrationLanguageDirective, buildPrimaryLanguageDirective, parseCron, nextOccurrence, nextDueAtMs, canonicalModelIdentity, piModelRefToCanonical, resolveModelRefForPi, modelRefLookupOrder, ompModelRefToCanonical, resolveModelRefForOmp, resolveModelConfigValue, resolveModelConfigOrDefault, DEFAULT_HISTORIAN_TIMEOUT_MS, getProtectedTokensTierOverrides, sanitizeDiagnosticText, hasShareabilitySensitiveText, FAIL_CLOSED_DOCTOR_COMMAND, formatFailClosedBlockingMessage, createFailClosedBlockingError, isFailClosedBlockingError, shouldBypassFailClosedBlock, createFailClosedController, setHarness, getHarness, ensureCortexKitArtifactGitignore, getProjectMagicContextHistorianDir, getMagicContextStorageResolution, getMagicContextStorageDir, log, sessionLog, flushLogger, ProjectIdentityError, resolveProjectIdentityStrict, resolveProjectIdentity, resolveProjectIdentityForSession, beginBootQuietPeriod, scheduleAfterBootQuiet, CTX_REDUCE_KEEP, newestCtxReduceTagNumbers, textMentionsRecentCommit, hasMeaningfulUserText, extractTexts, extractToolCallSummaries, preloadTokenizer, estimateTokens, normalizeText, stripWellFormedLeadingTagPrefix, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isRecord, estimateImageTokensFromDataUrl, normalizeTodoStateJson, buildSyntheticTodoPart, stripChannel1ReminderSpans, effectiveTailHygiene, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, decideChannel1, evaluateChannel2, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, planEmergencyDrop, updateTagByteSize, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, updateTagInputByteSize, updateTagTokenCount, getPersistedToolTagAccounting, getAllStatusTagTokenTotalsFlat, updateTagInputTokenCount, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, updateTagDropMode, updateCavemanDepth, hasPiFallbackMessageTags, findAdoptableFallbackTags, hasPiFallbackToolOwnerTags, findPiFallbackToolOwnerTags, adoptPiFallbackToolOwnerTag, adoptPiFallbackMessageTag, getMaxTagNumberBySession, getAssignableTagNumberByMessageId, deriveTagLoadFloor, getTagsBySession, getActiveTagsBySession, getTagsForPendingOperations, getTagsByNumbers, getDroppedTagsByNumbers, getMaxDroppedTagNumber, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, resolveOpenCodeDbPath, openCodeDbPathExists, recordOpenCodeDbReadFailure, clearOpenCodeDbReadFailure, claimOpenCodeDbDiagnosticOnce, Database, closeQuietly, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForCompletedToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, invalidateTrueRawTokenCache, DROPPED_INPUT_MESSAGE, droppedInputMarker, containsDroppedInputPlaceholder, isEditTool, applyEditMarkerToInput, setRawMessageProvider, withRawMessageProvider, cleanUserText, withRawSessionMessageCache, readRawSessionMessages, primeTailRawMessageCache, getCachedAbsoluteMessageCount, primeInMemoryTailRawMessageCache, getRawSessionMessageCount, getRawSessionTagKeysThrough, getLegacyProtectedTailStartOrdinal, readSessionChunk, logSlowWriteTransaction, clearCompressionDepth, clearCompressionDepthRange, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, recordSessionProjectIdentity, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, isNoContentCompartment, HAS_COMPARTMENT_CONTENT_SQL, persistCachedM0, clearCachedM0M1, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getCompartmentsByEndMessageId, appendCompartments, saveRecompStagingPass, getRecompStaging, clearRecompStaging, getRecompPartialRange, setRecompPartialRange, escapeXmlAttr, escapeXmlContent, getModuleNoteEvaluationBridge, getContextStoreUuid, drainMirrorPages, parseCompartmentOutput, resolveWorkspaceShareCategories, resolveWorkspaceIdentitySet, expandWorkspaceIdentitySetWithAliases, sourceNameForMemory, computeWorkspaceEpochFingerprint, bumpEpochsForWorkspaceMembers, readProjectDocsCanonical, encodePiContentDecision, getPiContentDecisions, freezePiContentDecision, getNativeReplayState, saveNativeToolInputs, addNativeReasoningIds, copySessionStateForClone, getErrorMessage, describeError, piHarnessKindFromExecutable, setStoragePrivatePermissionEnforcement, getSchemaFenceRejection, getMigrationOnOpenRefusal, LATEST_SUPPORTED_VERSION, getDatabasePath, getPersistedSchemaVersion, setSqlitePragmaConfig, applySqliteTuningPragmas, runSqliteOptimize, openDatabase, openDatabaseAsync, queueM0Mutation, getMaxM0MutationId, queueMemoryMutation, getMemoryMutationsForRender, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationId, getMaxMemoryMutationIdForProjects, MAX_EXECUTE_THRESHOLD, escalationBands, computeProtectionWindow, readEpochFloorSnapshot, getProtectionWindowForSession, isProviderOverflowFailClosedProven, describeProtectedTailDrainBudgetSkip, loadProtectedTailMeta, markProtectedTailPolicyV3Seeded, recordProtectedTailPublicationFloor, recordProtectedTailNoEligibleHead, getWrapupInProgressState, isWrapupInProgress, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, reserveProtectedTailDrainTokens, clearEmergencyDrainLatch, recordHistorianDrainFailure, clearHistorianDrainFailure, rollbackProtectedTailDrainReservation, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getChannel1NudgeState, setChannel1NudgeState, markChannel1PostReduceGracePending, captureChannel1PostReduceGraceBaseline, getChannel2NudgeState, getChannel2NudgeClaim, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getPersistedNoteNudge, setPersistedNoteNudgeTrigger, setPersistedNoteNudgeTriggerMessageId, getNoteNudgeAnchors, getAutoSearchHintDecisions, deliverNoteNudgeAtomic, appendAutoSearchHintDecision, pruneNoteNudgeAnchors, pruneAutoSearchHintDecisions, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, getNoteLastReadAt, incrementHistorianFailure, clearHistorianFailureState, getOverflowState, recordOverflowDetected, clearEmergencyRecovery, clearDetectedContextLimit, getStrippedPlaceholderIds, applyStrippedPlaceholderDelta, NEWEST_REASONING_BEARING_ASSISTANT, THINKING_BINDING_RECOVERY_FROZEN_PREFIX, thinkingBindingRecoveryFrozenId, getThinkingBindingRecoveryTarget, armThinkingBindingRecovery, clearThinkingBindingRecoveryIf, getMergedReasoningStrippedIds, addMergedReasoningStrippedIds, getProcessedImageStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, clearPendingCompactionMarkerStateIf, getPendingPiCompactionMarkerState, setPendingPiCompactionMarkerState, clearPendingPiCompactionMarkerStateIf, getSessionsWithPendingPiMarker, setSessionWorkMetrics, getSessionWorkMetrics, resolveEpochFloorForPass, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, getNotes, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, markNoteReady, markNoteChecked, queuePendingOp, getPendingOps, getPendingOpsCount, clearPendingOps, removePendingOp, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, insertPrimerCandidates, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectUserProfileVersion, saveSourceContent, getSourceContents, recordSubagentInvocation, getLatestHistorianInvocationId, BoundedSessionMap, MIN_PLAUSIBLE_CONTEXT_LIMIT, reloadWindowOverlay, getWindowOverlay, resolveWindowOverlayFacts, deriveWindowGeometry, hasTrustedAbsoluteWall, applyProvenInputFloor, formatWindowDerivationLine, isSaneLimit, resolveOutputReserve, getSdkContextLimit, formatConfigParseStatusLine, formatConfigParseNotice, claimConfigParseFailuresOnce, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, SYNTH_USER_ID_PREFIX, resolvePiStableId, readPiSessionSnapshot, readPiSessionMessages, readPiSessionMessagePage, findLastModelKeyFromBranch, convertEntriesToRawMessages, convertEntriesToRawMessagePage, computeCueContentHash, hasMuralCueColumns, getMuralCueState, memoryNeedsCue, setMuralCue, recordMuralCueRejection, invalidateMemory, computeNormalizedHash, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, getUnclassifiedMemoryIds, insertMemory, getMemoryByHash, getMemoriesByProject, getMemoriesByProjects, getMaxMemoryIdForProjects, getAllActiveMemoriesForMigration, getMemoryById, setMemoryClassification, archiveMemory, deleteMemory, getMemoryCount, getMemoryCountsByStatus, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, getTaskScheduleState, getMostRecentTaskRunAt, pruneNonCanonicalTaskRows, deleteTaskScheduleRowsForProject, seedTaskScheduleState, writeTaskScheduleState, isRetrospectiveWindowProcessed, recordRetrospectiveWindowProcessed, curateCategoryForMemoryCategory, peekCurateCategoryScope, beginCurateCategoryRun, curateTaskStateAfterSuccess, formatSynapseLaneDescriptor, buildCanonicalChunkTextFromFts, buildCompartmentSummaryFallbackText, canonicalizeInMemoryChunkTextForEmbedding, chunkCanonicalText, chunkEmbeddingWindowsAreCurrent, replaceCompartmentChunkEmbeddings, cosineSimilarity, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, describeShadowBackfillWriteRefusal, contentSha256, sweepStaleEmbeddingIdentitiesForProject, enqueueShadowEmbeddingItems, getProjectEmbeddingSnapshot, getProjectChunkEmbeddingModelId, getProjectEmbeddingMaxInputTokens, embedTextForProject, embedBatchForProject, embedItemsForProject, embedUnembeddedMemoriesForProject, drainCommitBacklogForProject, embedSessionCompartmentChunks, getEmbeddingCoverageStatus, promoteSessionFactsDurable, embedPromotedFacts, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, isDirectiveShapedProjectRule, takeCurateSafetyRefusalCount, wakePlaneStatus, indexCommitsForProject, embedUnembeddedCommits, loadPiConfig, ensureProjectRegisteredFromPiDirectory, resolvePiHarnessDetection, resolvePiHarnessKind, resolveMuralWire, updateCompactionMarkerAfterPublication, COMPARTMENT_RENDER_EPOCH, encodeCachedM0UpgradeIdentity, decodeCachedM0UpgradeIdentity, DEFAULT_HISTORY_BUDGET_TOKENS, renderCompartmentAtTier, renderDecayedCompartments, extractM0Block, TEMPORAL_MARKER_PATTERN, temporalMarkerPrefix, clearInjectionCache, getVisibleMemoryIds, renderMemoryBlock, DEFAULT_MEMORY_BUDGET_TOKENS, DEFAULT_USER_PROFILE_BUDGET_TOKENS, trimMemoriesToBudgetV2, trimWorkspaceMemoriesToBudgetV2, trimUserMemoriesToBudget, renderMemoryBlockV2, stripMemoryMuralBlock, unifiedSearch, rememberTodowriteToolCallTodos, parseTodos, setTodoSnapshot, registerTodoOverlay, registerTodoStateLifecycle, syncCtxMemoryToolEnabled, registerMagicContextTools };
41364
+ export { COMPACTION_ENABLED_PATH, isDreamerRunnable, isCompactionEnabled, migrateMagicContextConfigLocations, withContentLanguageDirective, withMigrationLanguageDirective, buildPrimaryLanguageDirective, parseCron, nextOccurrence, nextDueAtMs, canonicalModelIdentity, piModelRefToCanonical, resolveModelRefForPi, modelRefLookupOrder, ompModelRefToCanonical, resolveModelRefForOmp, resolveModelConfigValue, resolveModelConfigOrDefault, DEFAULT_HISTORIAN_TIMEOUT_MS, getProtectedTokensTierOverrides, sanitizeDiagnosticText, hasShareabilitySensitiveText, FAIL_CLOSED_DOCTOR_COMMAND, formatFailClosedBlockingMessage, createFailClosedBlockingError, isFailClosedBlockingError, shouldBypassFailClosedBlock, createFailClosedController, setHarness, getHarness, ensureCortexKitArtifactGitignore, getProjectMagicContextHistorianDir, getMagicContextStorageResolution, getMagicContextStorageDir, log, sessionLog, flushLogger, ProjectIdentityError, resolveProjectIdentityStrict, resolveProjectIdentity, resolveProjectIdentityForSession, beginBootQuietPeriod, scheduleAfterBootQuiet, CTX_REDUCE_KEEP, newestCtxReduceTagNumbers, textMentionsRecentCommit, hasMeaningfulUserText, extractTexts, extractToolCallSummaries, preloadTokenizer, estimateTokens, normalizeText, stripWellFormedLeadingTagPrefix, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isRecord, estimateImageTokensFromDataUrl, normalizeTodoStateJson, buildSyntheticTodoPart, stripChannel1ReminderSpans, effectiveTailHygiene, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, decideChannel1, evaluateChannel2, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, planEmergencyDrop, updateTagByteSize, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, updateTagInputByteSize, updateTagTokenCount, getPersistedToolTagAccounting, getAllStatusTagTokenTotalsFlat, updateTagInputTokenCount, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, updateTagDropMode, updateCavemanDepth, hasPiFallbackMessageTags, findAdoptableFallbackTags, hasPiFallbackToolOwnerTags, findPiFallbackToolOwnerTags, adoptPiFallbackToolOwnerTag, adoptPiFallbackMessageTag, getMaxTagNumberBySession, getAssignableTagNumberByMessageId, deriveTagLoadFloor, getTagsBySession, getActiveTagsBySession, getTagsForPendingOperations, getTagsByNumbers, getDroppedTagsByNumbers, getMaxDroppedTagNumber, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, resolveOpenCodeDbPath, assertOpenCodeStoreGeneration, openCodeDbPathExists, recordOpenCodeDbReadFailure, clearOpenCodeDbReadFailure, claimOpenCodeDbDiagnosticOnce, Database, closeQuietly, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForCompletedToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, invalidateTrueRawTokenCache, DROPPED_INPUT_MESSAGE, droppedInputMarker, containsDroppedInputPlaceholder, isEditTool, applyEditMarkerToInput, setRawMessageProvider, withRawMessageProvider, cleanUserText, withRawSessionMessageCache, readRawSessionMessages, primeTailRawMessageCache, getCachedAbsoluteMessageCount, primeInMemoryTailRawMessageCache, getRawSessionMessageCount, getRawSessionTagKeysThrough, getLegacyProtectedTailStartOrdinal, readSessionChunk, logSlowWriteTransaction, clearCompressionDepth, clearCompressionDepthRange, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, recordSessionProjectIdentity, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, isNoContentCompartment, HAS_COMPARTMENT_CONTENT_SQL, persistCachedM0, clearCachedM0M1, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getCompartmentsByEndMessageId, appendCompartments, saveRecompStagingPass, getRecompStaging, clearRecompStaging, getRecompPartialRange, setRecompPartialRange, escapeXmlAttr, escapeXmlContent, getModuleNoteEvaluationBridge, getContextStoreUuid, drainMirrorPages, parseCompartmentOutput, resolveWorkspaceShareCategories, resolveWorkspaceIdentitySet, expandWorkspaceIdentitySetWithAliases, sourceNameForMemory, computeWorkspaceEpochFingerprint, bumpEpochsForWorkspaceMembers, readProjectDocsCanonical, encodePiContentDecision, getPiContentDecisions, freezePiContentDecision, getNativeReplayState, saveNativeToolInputs, addNativeReasoningIds, copySessionStateForClone, getErrorMessage, describeError, piHarnessKindFromExecutable, setStoragePrivatePermissionEnforcement, getSchemaFenceRejection, getMigrationOnOpenRefusal, LATEST_SUPPORTED_VERSION, getDatabasePath, getPersistedSchemaVersion, setSqlitePragmaConfig, applySqliteTuningPragmas, runSqliteOptimize, openDatabase, openDatabaseAsync, queueM0Mutation, getMaxM0MutationId, queueMemoryMutation, getMemoryMutationsForRender, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationId, getMaxMemoryMutationIdForProjects, MAX_EXECUTE_THRESHOLD, escalationBands, computeProtectionWindow, readEpochFloorSnapshot, getProtectionWindowForSession, isProviderOverflowFailClosedProven, describeProtectedTailDrainBudgetSkip, loadProtectedTailMeta, markProtectedTailPolicyV3Seeded, recordProtectedTailPublicationFloor, recordProtectedTailNoEligibleHead, getWrapupInProgressState, isWrapupInProgress, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, reserveProtectedTailDrainTokens, clearEmergencyDrainLatch, recordHistorianDrainFailure, clearHistorianDrainFailure, rollbackProtectedTailDrainReservation, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getChannel1NudgeState, setChannel1NudgeState, markChannel1PostReduceGracePending, captureChannel1PostReduceGraceBaseline, getChannel2NudgeState, getChannel2NudgeClaim, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getPersistedNoteNudge, setPersistedNoteNudgeTrigger, setPersistedNoteNudgeTriggerMessageId, getNoteNudgeAnchors, getAutoSearchHintDecisions, deliverNoteNudgeAtomic, appendAutoSearchHintDecision, pruneNoteNudgeAnchors, pruneAutoSearchHintDecisions, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, getNoteLastReadAt, incrementHistorianFailure, clearHistorianFailureState, getOverflowState, recordOverflowDetected, clearEmergencyRecovery, clearDetectedContextLimit, getStrippedPlaceholderIds, applyStrippedPlaceholderDelta, NEWEST_REASONING_BEARING_ASSISTANT, THINKING_BINDING_RECOVERY_FROZEN_PREFIX, thinkingBindingRecoveryFrozenId, getThinkingBindingRecoveryTarget, armThinkingBindingRecovery, clearThinkingBindingRecoveryIf, getMergedReasoningStrippedIds, addMergedReasoningStrippedIds, getProcessedImageStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, clearPendingCompactionMarkerStateIf, getPendingPiCompactionMarkerState, setPendingPiCompactionMarkerState, clearPendingPiCompactionMarkerStateIf, getSessionsWithPendingPiMarker, setSessionWorkMetrics, getSessionWorkMetrics, resolveEpochFloorForPass, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, getNotes, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, markNoteReady, markNoteChecked, queuePendingOp, getPendingOps, getPendingOpsCount, clearPendingOps, removePendingOp, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, insertPrimerCandidates, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectUserProfileVersion, saveSourceContent, getSourceContents, recordSubagentInvocation, getLatestHistorianInvocationId, BoundedSessionMap, MIN_PLAUSIBLE_CONTEXT_LIMIT, reloadWindowOverlay, getWindowOverlay, resolveWindowOverlayFacts, deriveWindowGeometry, hasTrustedAbsoluteWall, applyProvenInputFloor, formatWindowDerivationLine, isSaneLimit, resolveOutputReserve, getSdkContextLimit, formatConfigParseStatusLine, formatConfigParseNotice, claimConfigParseFailuresOnce, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, SYNTH_USER_ID_PREFIX, resolvePiStableId, readPiSessionSnapshot, readPiSessionMessages, readPiSessionMessagePage, findLastModelKeyFromBranch, convertEntriesToRawMessages, convertEntriesToRawMessagePage, computeCueContentHash, hasMuralCueColumns, getMuralCueState, memoryNeedsCue, setMuralCue, recordMuralCueRejection, invalidateMemory, computeNormalizedHash, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, getUnclassifiedMemoryIds, insertMemory, getMemoryByHash, getMemoriesByProject, getMemoriesByProjects, getMaxMemoryIdForProjects, getAllActiveMemoriesForMigration, getMemoryById, setMemoryClassification, archiveMemory, deleteMemory, getMemoryCount, getMemoryCountsByStatus, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, getTaskScheduleState, getMostRecentTaskRunAt, pruneNonCanonicalTaskRows, deleteTaskScheduleRowsForProject, seedTaskScheduleState, writeTaskScheduleState, isRetrospectiveWindowProcessed, recordRetrospectiveWindowProcessed, curateCategoryForMemoryCategory, peekCurateCategoryScope, beginCurateCategoryRun, curateTaskStateAfterSuccess, formatSynapseLaneDescriptor, buildCanonicalChunkTextFromFts, buildCompartmentSummaryFallbackText, canonicalizeInMemoryChunkTextForEmbedding, chunkCanonicalText, chunkEmbeddingWindowsAreCurrent, replaceCompartmentChunkEmbeddings, cosineSimilarity, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, describeShadowBackfillWriteRefusal, contentSha256, sweepStaleEmbeddingIdentitiesForProject, enqueueShadowEmbeddingItems, getProjectEmbeddingSnapshot, getProjectChunkEmbeddingModelId, getProjectEmbeddingMaxInputTokens, embedTextForProject, embedBatchForProject, embedItemsForProject, embedUnembeddedMemoriesForProject, drainCommitBacklogForProject, embedSessionCompartmentChunks, getEmbeddingCoverageStatus, promoteSessionFactsDurable, embedPromotedFacts, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, isDirectiveShapedProjectRule, takeCurateSafetyRefusalCount, wakePlaneStatus, indexCommitsForProject, embedUnembeddedCommits, loadPiConfig, ensureProjectRegisteredFromPiDirectory, resolvePiHarnessDetection, resolvePiHarnessKind, resolveMuralWire, updateCompactionMarkerAfterPublication, COMPARTMENT_RENDER_EPOCH, encodeCachedM0UpgradeIdentity, decodeCachedM0UpgradeIdentity, DEFAULT_HISTORY_BUDGET_TOKENS, renderCompartmentAtTier, renderDecayedCompartments, extractM0Block, TEMPORAL_MARKER_PATTERN, temporalMarkerPrefix, clearInjectionCache, getVisibleMemoryIds, renderMemoryBlock, DEFAULT_MEMORY_BUDGET_TOKENS, DEFAULT_USER_PROFILE_BUDGET_TOKENS, trimMemoriesToBudgetV2, trimWorkspaceMemoriesToBudgetV2, trimUserMemoriesToBudget, renderMemoryBlockV2, stripMemoryMuralBlock, unifiedSearch, rememberTodowriteToolCallTodos, parseTodos, setTodoSnapshot, registerTodoOverlay, registerTodoStateLifecycle, syncCtxMemoryToolEnabled, registerMagicContextTools };