@cortexkit/pi-magic-context 0.22.2 → 0.22.4

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.
package/dist/index.js CHANGED
@@ -46,214 +46,6 @@ var __export = (target, all) => {
46
46
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
47
47
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
48
48
 
49
- // ../plugin/src/shared/harness.ts
50
- function setHarness(value) {
51
- if (harnessLocked && currentHarness !== value) {
52
- throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
53
- }
54
- currentHarness = value;
55
- harnessLocked = true;
56
- }
57
- function getHarness() {
58
- return currentHarness;
59
- }
60
- var currentHarness = "opencode", harnessLocked = false;
61
-
62
- // ../plugin/src/shared/data-path.ts
63
- import * as os from "node:os";
64
- import * as path2 from "node:path";
65
- function getDataDir() {
66
- return process.env.XDG_DATA_HOME ?? path2.join(os.homedir(), ".local", "share");
67
- }
68
- function getMagicContextTempDir(harness = getHarness()) {
69
- return path2.join(os.tmpdir(), harness, "magic-context");
70
- }
71
- function getMagicContextLogPath(harness = getHarness()) {
72
- return path2.join(getMagicContextTempDir(harness), "magic-context.log");
73
- }
74
- function getProjectMagicContextDir(directory) {
75
- return path2.join(directory, ".opencode", "magic-context");
76
- }
77
- function getProjectMagicContextHistorianDir(directory) {
78
- return path2.join(getProjectMagicContextDir(directory), "historian");
79
- }
80
- function getOpenCodeStorageDir() {
81
- return path2.join(getDataDir(), "opencode", "storage");
82
- }
83
- function getMagicContextStorageDir() {
84
- return path2.join(getDataDir(), "cortexkit", "magic-context");
85
- }
86
- function getLegacyOpenCodeMagicContextStorageDir() {
87
- return path2.join(getOpenCodeStorageDir(), "plugin", "magic-context");
88
- }
89
- var init_data_path = () => {};
90
-
91
- // ../plugin/src/shared/logger.ts
92
- import * as fs from "node:fs";
93
- import * as path3 from "node:path";
94
- function ensureDir(filePath) {
95
- const dir = path3.dirname(filePath);
96
- if (dir === lastEnsuredDir)
97
- return;
98
- try {
99
- fs.mkdirSync(dir, { recursive: true });
100
- lastEnsuredDir = dir;
101
- } catch {}
102
- }
103
- function flush() {
104
- if (flushTimer) {
105
- clearTimeout(flushTimer);
106
- flushTimer = null;
107
- }
108
- if (buffer.length === 0)
109
- return;
110
- const data = buffer.join("");
111
- buffer = [];
112
- try {
113
- const logFile = getMagicContextLogPath();
114
- ensureDir(logFile);
115
- fs.appendFileSync(logFile, data);
116
- } catch {}
117
- }
118
- function scheduleFlush() {
119
- if (flushTimer)
120
- return;
121
- flushTimer = setTimeout(() => {
122
- flushTimer = null;
123
- flush();
124
- }, FLUSH_INTERVAL_MS);
125
- }
126
- function log(message, data) {
127
- if (isTestEnv)
128
- return;
129
- try {
130
- const timestamp = new Date().toISOString();
131
- const serialized = data === undefined ? "" : data instanceof Error ? ` ${data.message}${data.stack ? `
132
- ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
133
- buffer.push(`[${timestamp}] ${message}${serialized}
134
- `);
135
- if (buffer.length >= BUFFER_SIZE_LIMIT) {
136
- flush();
137
- } else {
138
- scheduleFlush();
139
- }
140
- } catch {}
141
- }
142
- function sessionLog(sessionId, message, data) {
143
- log(`[magic-context][${sessionId}] ${message}`, data);
144
- }
145
- var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, lastEnsuredDir = null;
146
- var init_logger = __esm(() => {
147
- init_data_path();
148
- buffer = [];
149
- if (!isTestEnv) {
150
- process.on("exit", flush);
151
- }
152
- });
153
-
154
- // ../plugin/src/shared/sqlite.ts
155
- function buildNodeSqliteDatabaseClass(DatabaseSync) {
156
- const SAVEPOINT = "mc_tx_sp";
157
-
158
- class NodeSqliteDatabase extends DatabaseSync {
159
- constructor(filename, options) {
160
- const translated = { ...options };
161
- if (options && "readonly" in options) {
162
- translated.readOnly = options.readonly;
163
- delete translated.readonly;
164
- }
165
- super(typeof filename === "string" ? filename : ":memory:", translated);
166
- }
167
- transaction(fn) {
168
- const self = this;
169
- const wrapped = function(...args) {
170
- const nested = self.isTransaction === true;
171
- self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
172
- try {
173
- const result = fn.apply(this, args);
174
- self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
175
- return result;
176
- } catch (error) {
177
- if (nested) {
178
- self.exec(`ROLLBACK TO ${SAVEPOINT}`);
179
- self.exec(`RELEASE ${SAVEPOINT}`);
180
- } else {
181
- self.exec("ROLLBACK");
182
- }
183
- throw error;
184
- }
185
- };
186
- return wrapped;
187
- }
188
- }
189
- return NodeSqliteDatabase;
190
- }
191
- var isBun, bunSpec, nodeSpec, sqliteModule, DatabaseImpl, Database;
192
- var init_sqlite = __esm(async () => {
193
- isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
194
- bunSpec = "bun:" + "sqlite";
195
- nodeSpec = "node:" + "sqlite";
196
- sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
197
- DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
198
- Database = DatabaseImpl;
199
- });
200
-
201
- // ../plugin/src/shared/sqlite-helpers.ts
202
- function closeQuietly(db) {
203
- if (!db)
204
- return;
205
- try {
206
- db.close();
207
- } catch {}
208
- }
209
-
210
- // ../plugin/src/hooks/magic-context/read-session-db.ts
211
- import { existsSync } from "node:fs";
212
- import { join as join2 } from "node:path";
213
- function getOpenCodeDbPath() {
214
- return join2(getDataDir(), "opencode", "opencode.db");
215
- }
216
- function openCodeDbExists() {
217
- return existsSync(getOpenCodeDbPath());
218
- }
219
- function closeCachedReadOnlyDb() {
220
- if (!cachedReadOnlyDb) {
221
- return;
222
- }
223
- try {
224
- closeQuietly(cachedReadOnlyDb.db);
225
- } catch (error) {
226
- log("[magic-context] failed to close cached OpenCode read-only DB:", error);
227
- } finally {
228
- cachedReadOnlyDb = null;
229
- }
230
- }
231
- function getReadOnlySessionDb() {
232
- const dbPath = getOpenCodeDbPath();
233
- if (cachedReadOnlyDb?.path === dbPath) {
234
- return cachedReadOnlyDb.db;
235
- }
236
- closeCachedReadOnlyDb();
237
- const db = new Database(dbPath, { readonly: true });
238
- cachedReadOnlyDb = { path: dbPath, db };
239
- return db;
240
- }
241
- function withReadOnlySessionDb(fn) {
242
- return fn(getReadOnlySessionDb());
243
- }
244
- function getRawSessionMessageCountFromDb(db, sessionId) {
245
- const row = db.prepare(`SELECT COUNT(*) as count FROM message WHERE session_id = ?
246
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
247
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')`).get(sessionId);
248
- return typeof row?.count === "number" ? row.count : 0;
249
- }
250
- var cachedReadOnlyDb = null;
251
- var init_read_session_db = __esm(async () => {
252
- init_data_path();
253
- init_logger();
254
- await init_sqlite();
255
- });
256
-
257
49
  // ../../node_modules/.bun/esprima@4.0.1/node_modules/esprima/dist/esprima.js
258
50
  var require_esprima = __commonJS((exports, module) => {
259
51
  (function webpackUniversalModuleDefinition(root, factory) {
@@ -8282,8 +8074,115 @@ function hasGitDir(canonical) {
8282
8074
  }
8283
8075
  }
8284
8076
 
8285
- // ../plugin/src/features/magic-context/message-index-async.ts
8286
- init_logger();
8077
+ // ../plugin/src/shared/logger.ts
8078
+ import * as fs from "node:fs";
8079
+ import * as path3 from "node:path";
8080
+
8081
+ // ../plugin/src/shared/data-path.ts
8082
+ import * as os from "node:os";
8083
+ import * as path2 from "node:path";
8084
+
8085
+ // ../plugin/src/shared/harness.ts
8086
+ var currentHarness = "opencode";
8087
+ var harnessLocked = false;
8088
+ function setHarness(value) {
8089
+ if (harnessLocked && currentHarness !== value) {
8090
+ throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
8091
+ }
8092
+ currentHarness = value;
8093
+ harnessLocked = true;
8094
+ }
8095
+ function getHarness() {
8096
+ return currentHarness;
8097
+ }
8098
+
8099
+ // ../plugin/src/shared/data-path.ts
8100
+ function getDataDir() {
8101
+ return process.env.XDG_DATA_HOME ?? path2.join(os.homedir(), ".local", "share");
8102
+ }
8103
+ function getMagicContextTempDir(harness = getHarness()) {
8104
+ return path2.join(os.tmpdir(), harness, "magic-context");
8105
+ }
8106
+ function getMagicContextLogPath(harness = getHarness()) {
8107
+ return path2.join(getMagicContextTempDir(harness), "magic-context.log");
8108
+ }
8109
+ function getProjectMagicContextDir(directory) {
8110
+ return path2.join(directory, ".opencode", "magic-context");
8111
+ }
8112
+ function getProjectMagicContextHistorianDir(directory) {
8113
+ return path2.join(getProjectMagicContextDir(directory), "historian");
8114
+ }
8115
+ function getOpenCodeStorageDir() {
8116
+ return path2.join(getDataDir(), "opencode", "storage");
8117
+ }
8118
+ function getMagicContextStorageDir() {
8119
+ return path2.join(getDataDir(), "cortexkit", "magic-context");
8120
+ }
8121
+ function getLegacyOpenCodeMagicContextStorageDir() {
8122
+ return path2.join(getOpenCodeStorageDir(), "plugin", "magic-context");
8123
+ }
8124
+
8125
+ // ../plugin/src/shared/logger.ts
8126
+ var isTestEnv = false;
8127
+ var buffer = [];
8128
+ var flushTimer = null;
8129
+ var FLUSH_INTERVAL_MS = 500;
8130
+ var BUFFER_SIZE_LIMIT = 50;
8131
+ var lastEnsuredDir = null;
8132
+ function ensureDir(filePath) {
8133
+ const dir = path3.dirname(filePath);
8134
+ if (dir === lastEnsuredDir)
8135
+ return;
8136
+ try {
8137
+ fs.mkdirSync(dir, { recursive: true });
8138
+ lastEnsuredDir = dir;
8139
+ } catch {}
8140
+ }
8141
+ function flush() {
8142
+ if (flushTimer) {
8143
+ clearTimeout(flushTimer);
8144
+ flushTimer = null;
8145
+ }
8146
+ if (buffer.length === 0)
8147
+ return;
8148
+ const data = buffer.join("");
8149
+ buffer = [];
8150
+ try {
8151
+ const logFile = getMagicContextLogPath();
8152
+ ensureDir(logFile);
8153
+ fs.appendFileSync(logFile, data);
8154
+ } catch {}
8155
+ }
8156
+ function scheduleFlush() {
8157
+ if (flushTimer)
8158
+ return;
8159
+ flushTimer = setTimeout(() => {
8160
+ flushTimer = null;
8161
+ flush();
8162
+ }, FLUSH_INTERVAL_MS);
8163
+ }
8164
+ function log(message, data) {
8165
+ if (isTestEnv)
8166
+ return;
8167
+ try {
8168
+ const timestamp = new Date().toISOString();
8169
+ const serialized = data === undefined ? "" : data instanceof Error ? ` ${data.message}${data.stack ? `
8170
+ ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
8171
+ buffer.push(`[${timestamp}] ${message}${serialized}
8172
+ `);
8173
+ if (buffer.length >= BUFFER_SIZE_LIMIT) {
8174
+ flush();
8175
+ } else {
8176
+ scheduleFlush();
8177
+ }
8178
+ } catch {}
8179
+ }
8180
+ function sessionLog(sessionId, message, data) {
8181
+ log(`[magic-context][${sessionId}] ${message}`, data);
8182
+ }
8183
+ if (!isTestEnv) {
8184
+ process.on("exit", flush);
8185
+ }
8287
8186
 
8288
8187
  // ../plugin/src/shared/internal-initiator-marker.ts
8289
8188
  var OMO_INTERNAL_INITIATOR_MARKER = "<!-- OMO_INTERNAL_INITIATOR -->";
@@ -8297,8 +8196,102 @@ function removeSystemReminders(text) {
8297
8196
  return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, "").trim();
8298
8197
  }
8299
8198
 
8300
- // ../plugin/src/hooks/magic-context/read-session-chunk.ts
8301
- await init_read_session_db();
8199
+ // ../plugin/src/hooks/magic-context/read-session-db.ts
8200
+ import { existsSync } from "node:fs";
8201
+ import { join as join2 } from "node:path";
8202
+
8203
+ // ../plugin/src/shared/sqlite.ts
8204
+ var isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
8205
+ var bunSpec = "bun:" + "sqlite";
8206
+ var nodeSpec = "node:" + "sqlite";
8207
+ var sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
8208
+ var DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
8209
+ function buildNodeSqliteDatabaseClass(DatabaseSync) {
8210
+ const SAVEPOINT = "mc_tx_sp";
8211
+
8212
+ class NodeSqliteDatabase extends DatabaseSync {
8213
+ constructor(filename, options) {
8214
+ const translated = { ...options };
8215
+ if (options && "readonly" in options) {
8216
+ translated.readOnly = options.readonly;
8217
+ delete translated.readonly;
8218
+ }
8219
+ super(typeof filename === "string" ? filename : ":memory:", translated);
8220
+ }
8221
+ transaction(fn) {
8222
+ const self = this;
8223
+ const wrapped = function(...args) {
8224
+ const nested = self.isTransaction === true;
8225
+ self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
8226
+ try {
8227
+ const result = fn.apply(this, args);
8228
+ self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
8229
+ return result;
8230
+ } catch (error) {
8231
+ if (nested) {
8232
+ self.exec(`ROLLBACK TO ${SAVEPOINT}`);
8233
+ self.exec(`RELEASE ${SAVEPOINT}`);
8234
+ } else {
8235
+ self.exec("ROLLBACK");
8236
+ }
8237
+ throw error;
8238
+ }
8239
+ };
8240
+ return wrapped;
8241
+ }
8242
+ }
8243
+ return NodeSqliteDatabase;
8244
+ }
8245
+ var Database = DatabaseImpl;
8246
+
8247
+ // ../plugin/src/shared/sqlite-helpers.ts
8248
+ function closeQuietly(db) {
8249
+ if (!db)
8250
+ return;
8251
+ try {
8252
+ db.close();
8253
+ } catch {}
8254
+ }
8255
+
8256
+ // ../plugin/src/hooks/magic-context/read-session-db.ts
8257
+ function getOpenCodeDbPath() {
8258
+ return join2(getDataDir(), "opencode", "opencode.db");
8259
+ }
8260
+ function openCodeDbExists() {
8261
+ return existsSync(getOpenCodeDbPath());
8262
+ }
8263
+ var cachedReadOnlyDb = null;
8264
+ function closeCachedReadOnlyDb() {
8265
+ if (!cachedReadOnlyDb) {
8266
+ return;
8267
+ }
8268
+ try {
8269
+ closeQuietly(cachedReadOnlyDb.db);
8270
+ } catch (error) {
8271
+ log("[magic-context] failed to close cached OpenCode read-only DB:", error);
8272
+ } finally {
8273
+ cachedReadOnlyDb = null;
8274
+ }
8275
+ }
8276
+ function getReadOnlySessionDb() {
8277
+ const dbPath = getOpenCodeDbPath();
8278
+ if (cachedReadOnlyDb?.path === dbPath) {
8279
+ return cachedReadOnlyDb.db;
8280
+ }
8281
+ closeCachedReadOnlyDb();
8282
+ const db = new Database(dbPath, { readonly: true });
8283
+ cachedReadOnlyDb = { path: dbPath, db };
8284
+ return db;
8285
+ }
8286
+ function withReadOnlySessionDb(fn) {
8287
+ return fn(getReadOnlySessionDb());
8288
+ }
8289
+ function getRawSessionMessageCountFromDb(db, sessionId) {
8290
+ const row = db.prepare(`SELECT COUNT(*) as count FROM message WHERE session_id = ?
8291
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
8292
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')`).get(sessionId);
8293
+ return typeof row?.count === "number" ? row.count : 0;
8294
+ }
8302
8295
 
8303
8296
  // ../../node_modules/.bun/ai-tokenizer@1.0.6/node_modules/ai-tokenizer/dist/index.js
8304
8297
  function _typeof(o) {
@@ -140942,14 +140935,48 @@ function readRawSessionMessagesFromDb(db, sessionId) {
140942
140935
  var encoder = new TextEncoder;
140943
140936
  var TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
140944
140937
  var MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
140938
+ var COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
140939
+ var MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
140940
+ var STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
140941
+ function stripWellFormedLeadingTagPrefix(value) {
140942
+ return value.replace(/^(\u00a7\d+\u00a7\s*)+/, "");
140943
+ }
140944
+ function stripCompleteTagPairsGlobally(value) {
140945
+ return value.replace(COMPLETE_TAG_PAIR_GLOBAL_REGEX, "");
140946
+ }
140947
+ function stripMalformedTagNotationGlobally(value) {
140948
+ return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
140949
+ }
140950
+ function stripTagSectionCharacters(value) {
140951
+ return value.replace(STRAY_SECTION_CHAR_REGEX, "");
140952
+ }
140953
+ function stripPersistedAssistantText(value) {
140954
+ let text = stripWellFormedLeadingTagPrefix(value);
140955
+ text = stripCompleteTagPairsGlobally(text);
140956
+ text = stripMalformedTagNotationGlobally(text);
140957
+ text = stripTagSectionCharacters(text);
140958
+ return text.trim();
140959
+ }
140945
140960
  function byteSize(value) {
140946
140961
  return encoder.encode(value).length;
140947
140962
  }
140948
140963
  function stripTagPrefix(value) {
140949
- let stripped = value.replace(MALFORMED_TAG_PREFIX_REGEX, "");
140950
- stripped = stripped.replace(TAG_PREFIX_REGEX, "");
140964
+ let stripped = value;
140965
+ for (let pass = 0;pass < 8; pass++) {
140966
+ const prev = stripped;
140967
+ stripped = stripped.replace(MALFORMED_TAG_PREFIX_REGEX, "");
140968
+ stripped = stripped.replace(TAG_PREFIX_REGEX, "");
140969
+ if (stripped === prev)
140970
+ break;
140971
+ }
140951
140972
  return stripped;
140952
140973
  }
140974
+ function peelLeadingMcTagNotation(value) {
140975
+ const body = stripTagPrefix(value);
140976
+ if (body === value)
140977
+ return { tagPrefix: "", body };
140978
+ return { tagPrefix: value.slice(0, value.length - body.length), body };
140979
+ }
140953
140980
  function prependTag(tagId, value) {
140954
140981
  const stripped = stripTagPrefix(value);
140955
140982
  return `§${tagId}§ ${stripped}`;
@@ -140991,7 +141018,9 @@ function hasMeaningfulPart(part) {
140991
141018
  return false;
140992
141019
  const type = part.type;
140993
141020
  if (type === "text") {
140994
- return typeof part.text === "string" && part.text.trim().length > 0;
141021
+ if (typeof part.text !== "string")
141022
+ return false;
141023
+ return stripTagPrefix(part.text).trim().length > 0;
140995
141024
  }
140996
141025
  if (typeof type !== "string")
140997
141026
  return false;
@@ -141306,6 +141335,7 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
141306
141335
  toolOnlyRanges
141307
141336
  };
141308
141337
  }
141338
+
141309
141339
  // ../plugin/src/features/magic-context/compression-depth-storage.ts
141310
141340
  var incrementDepthStatements = new WeakMap;
141311
141341
  var totalDepthStatements = new WeakMap;
@@ -141709,6 +141739,7 @@ function parseReportedLimit(message) {
141709
141739
  }
141710
141740
  return;
141711
141741
  }
141742
+
141712
141743
  // ../plugin/src/features/magic-context/compartment-lease.ts
141713
141744
  var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
141714
141745
  var COMPARTMENT_LEASE_RENEWAL_MS = 60 * 1000;
@@ -141779,6 +141810,9 @@ var SESSION_META_SELECT_COLUMNS = [
141779
141810
  "cached_m0_materialized_at",
141780
141811
  "cached_m0_session_facts_version",
141781
141812
  "cached_m0_upgrade_state",
141813
+ "cached_m0_system_hash",
141814
+ "cached_m0_tool_set_hash",
141815
+ "cached_m0_model_key",
141782
141816
  "last_observed_model_key",
141783
141817
  "upgrade_reminded_at",
141784
141818
  "pi_stable_id_scheme"
@@ -141815,6 +141849,9 @@ var META_COLUMNS = {
141815
141849
  cachedM0MaterializedAt: "cached_m0_materialized_at",
141816
141850
  cachedM0SessionFactsVersion: "cached_m0_session_facts_version",
141817
141851
  cachedM0UpgradeState: "cached_m0_upgrade_state",
141852
+ cachedM0SystemHash: "cached_m0_system_hash",
141853
+ cachedM0ToolSetHash: "cached_m0_tool_set_hash",
141854
+ cachedM0ModelKey: "cached_m0_model_key",
141818
141855
  lastObservedModelKey: "last_observed_model_key",
141819
141856
  upgradeRemindedAt: "upgrade_reminded_at",
141820
141857
  piStableIdScheme: "pi_stable_id_scheme"
@@ -141857,7 +141894,7 @@ function isSessionMetaRow(row) {
141857
141894
  if (row === null || typeof row !== "object")
141858
141895
  return false;
141859
141896
  const r = row;
141860
- return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
141897
+ return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.cached_m0_system_hash) && isStringOrNull(r.cached_m0_tool_set_hash) && isStringOrNull(r.cached_m0_model_key) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
141861
141898
  }
141862
141899
  function getDefaultSessionMeta(sessionId) {
141863
141900
  return {
@@ -141893,6 +141930,9 @@ function getDefaultSessionMeta(sessionId) {
141893
141930
  cachedM0MaterializedAt: null,
141894
141931
  cachedM0SessionFactsVersion: null,
141895
141932
  cachedM0UpgradeState: null,
141933
+ cachedM0SystemHash: null,
141934
+ cachedM0ToolSetHash: null,
141935
+ cachedM0ModelKey: null,
141896
141936
  lastObservedModelKey: null,
141897
141937
  upgradeRemindedAt: null,
141898
141938
  piStableIdScheme: null
@@ -141944,6 +141984,9 @@ function toSessionMeta(row) {
141944
141984
  cachedM0MaterializedAt: numOrNull(row.cached_m0_materialized_at),
141945
141985
  cachedM0SessionFactsVersion: numOrNull(row.cached_m0_session_facts_version),
141946
141986
  cachedM0UpgradeState: stringOrNull(row.cached_m0_upgrade_state),
141987
+ cachedM0SystemHash: stringOrNull(row.cached_m0_system_hash),
141988
+ cachedM0ToolSetHash: stringOrNull(row.cached_m0_tool_set_hash),
141989
+ cachedM0ModelKey: stringOrNull(row.cached_m0_model_key),
141947
141990
  lastObservedModelKey: stringOrNull(row.last_observed_model_key),
141948
141991
  upgradeRemindedAt: numOrNull(row.upgrade_reminded_at),
141949
141992
  piStableIdScheme: numOrNull(row.pi_stable_id_scheme)
@@ -141963,8 +142006,11 @@ function persistCachedM0(db, sessionId, payload) {
141963
142006
  cached_m0_project_docs_hash = ?,
141964
142007
  cached_m0_materialized_at = ?,
141965
142008
  cached_m0_session_facts_version = ?,
141966
- cached_m0_upgrade_state = ?
141967
- WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, sessionId);
142009
+ cached_m0_upgrade_state = ?,
142010
+ cached_m0_system_hash = ?,
142011
+ cached_m0_tool_set_hash = ?,
142012
+ cached_m0_model_key = ?
142013
+ WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, payload.systemHash ?? "", payload.toolSetHash ?? "", payload.modelKey ?? "", sessionId);
141968
142014
  }
141969
142015
  function clearCachedM0M1(db, sessionId) {
141970
142016
  ensureSessionMetaRow(db, sessionId);
@@ -141982,6 +142028,9 @@ function clearCachedM0M1(db, sessionId) {
141982
142028
  ["cached_m0_materialized_at", null],
141983
142029
  ["cached_m0_session_facts_version", null],
141984
142030
  ["cached_m0_upgrade_state", null],
142031
+ ["cached_m0_system_hash", null],
142032
+ ["cached_m0_tool_set_hash", null],
142033
+ ["cached_m0_model_key", null],
141985
142034
  ["cached_m0_last_baseline_end_message_id", null],
141986
142035
  ["memory_block_cache", ""],
141987
142036
  ["memory_block_count", 0],
@@ -142187,11 +142236,7 @@ function escapeXmlAttr(s) {
142187
142236
  function escapeXmlContent(s) {
142188
142237
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
142189
142238
  }
142190
- // ../plugin/src/features/magic-context/migrations.ts
142191
- init_logger();
142192
-
142193
142239
  // ../plugin/src/features/magic-context/storage-db.ts
142194
- init_data_path();
142195
142240
  import { copyFileSync, cpSync, existsSync as existsSync4, mkdirSync as mkdirSync2 } from "node:fs";
142196
142241
  import { dirname as dirname2, join as join5 } from "node:path";
142197
142242
 
@@ -142271,12 +142316,7 @@ function safeString(value) {
142271
142316
  }
142272
142317
  }
142273
142318
 
142274
- // ../plugin/src/features/magic-context/storage-db.ts
142275
- init_logger();
142276
- await init_sqlite();
142277
-
142278
142319
  // ../plugin/src/features/magic-context/key-files/project-key-files.ts
142279
- init_logger();
142280
142320
  import { createHash as createHash2 } from "node:crypto";
142281
142321
  import { existsSync as existsSync2, readFileSync, realpathSync } from "node:fs";
142282
142322
  import { join as join3, resolve, sep } from "node:path";
@@ -142446,8 +142486,6 @@ function loadToolDefinitionMeasurements(db) {
142446
142486
  }
142447
142487
 
142448
142488
  // ../plugin/src/features/magic-context/tool-owner-backfill.ts
142449
- init_data_path();
142450
- init_logger();
142451
142489
  import { existsSync as existsSync3 } from "node:fs";
142452
142490
  import { join as join4 } from "node:path";
142453
142491
  var LEASE_DURATION_MS = 5 * 60 * 1000;
@@ -142695,7 +142733,7 @@ var databases = new Map;
142695
142733
  var persistenceByDatabase = new WeakMap;
142696
142734
  var persistenceErrorByDatabase = new WeakMap;
142697
142735
  var lastSchemaFenceRejection = null;
142698
- var LATEST_SUPPORTED_VERSION = 29;
142736
+ var LATEST_SUPPORTED_VERSION = 30;
142699
142737
  function resolveDatabasePath(dbPathOverride) {
142700
142738
  if (dbPathOverride) {
142701
142739
  return { dbDir: dirname2(dbPathOverride), dbPath: dbPathOverride };
@@ -143160,6 +143198,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
143160
143198
  cached_m0_materialized_at INTEGER,
143161
143199
  cached_m0_session_facts_version INTEGER,
143162
143200
  cached_m0_upgrade_state TEXT,
143201
+ cached_m0_system_hash TEXT,
143202
+ cached_m0_tool_set_hash TEXT,
143203
+ cached_m0_model_key TEXT,
143163
143204
  cached_m0_last_baseline_end_message_id TEXT,
143164
143205
  upgrade_reminded_at INTEGER,
143165
143206
  pi_stable_id_scheme INTEGER
@@ -143351,6 +143392,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
143351
143392
  ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
143352
143393
  ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
143353
143394
  ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
143395
+ ensureColumn(db, "session_meta", "cached_m0_system_hash", "TEXT");
143396
+ ensureColumn(db, "session_meta", "cached_m0_tool_set_hash", "TEXT");
143397
+ ensureColumn(db, "session_meta", "cached_m0_model_key", "TEXT");
143354
143398
  ensureColumn(db, "session_meta", "cached_m0_last_baseline_end_message_id", "TEXT");
143355
143399
  ensureColumn(db, "session_meta", "upgrade_reminded_at", "INTEGER");
143356
143400
  db.exec(`
@@ -144280,6 +144324,28 @@ var MIGRATIONS = [
144280
144324
  db.exec("ALTER TABLE notes ADD COLUMN anchor_ordinal INTEGER");
144281
144325
  }
144282
144326
  }
144327
+ },
144328
+ {
144329
+ version: 30,
144330
+ description: "HARD-bust m[0] markers: cached system/tool-set/model identity",
144331
+ up: (db) => {
144332
+ const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta' LIMIT 1").get();
144333
+ if (!hasSessionMeta)
144334
+ return;
144335
+ ensureColumn(db, "session_meta", "cached_m0_system_hash", "TEXT");
144336
+ ensureColumn(db, "session_meta", "cached_m0_tool_set_hash", "TEXT");
144337
+ ensureColumn(db, "session_meta", "cached_m0_model_key", "TEXT");
144338
+ const columns = new Set(db.prepare("PRAGMA table_info(session_meta)").all().map((column) => column.name));
144339
+ if (columns.has("cached_m0_bytes")) {
144340
+ db.prepare(`UPDATE session_meta SET
144341
+ cached_m0_bytes = NULL,
144342
+ cached_m1_bytes = NULL,
144343
+ cached_m0_materialized_at = NULL,
144344
+ cached_m0_system_hash = NULL,
144345
+ cached_m0_tool_set_hash = NULL,
144346
+ cached_m0_model_key = NULL`).run();
144347
+ }
144348
+ }
144283
144349
  }
144284
144350
  ];
144285
144351
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -144578,7 +144644,6 @@ function getMaxMemoryMutationId(db, projectPath) {
144578
144644
  return row?.max_id ?? null;
144579
144645
  }
144580
144646
  // ../plugin/src/features/magic-context/storage-meta-persisted.ts
144581
- init_logger();
144582
144647
  var CAS_RETRY_LIMIT = 5;
144583
144648
  var AUTO_SEARCH_NO_HINT_REASONS = new Set([
144584
144649
  "below-threshold",
@@ -145041,8 +145106,6 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
145041
145106
  import { Buffer as Buffer3 } from "node:buffer";
145042
145107
 
145043
145108
  // ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
145044
- init_logger();
145045
- await init_read_session_db();
145046
145109
  function resolveIsSubagentFromOpenCodeDb(sessionId) {
145047
145110
  try {
145048
145111
  return withReadOnlySessionDb((openCodeDb) => {
@@ -145076,6 +145139,9 @@ var SESSION_META_FALLBACK_SELECTS = {
145076
145139
  cached_m0_materialized_at: "NULL AS cached_m0_materialized_at",
145077
145140
  cached_m0_session_facts_version: "NULL AS cached_m0_session_facts_version",
145078
145141
  cached_m0_upgrade_state: "NULL AS cached_m0_upgrade_state",
145142
+ cached_m0_system_hash: "NULL AS cached_m0_system_hash",
145143
+ cached_m0_tool_set_hash: "NULL AS cached_m0_tool_set_hash",
145144
+ cached_m0_model_key: "NULL AS cached_m0_model_key",
145079
145145
  last_observed_model_key: "NULL AS last_observed_model_key",
145080
145146
  upgrade_reminded_at: "NULL AS upgrade_reminded_at"
145081
145147
  };
@@ -145308,7 +145374,6 @@ function markNoteChecked(db, noteId) {
145308
145374
  db.prepare("UPDATE notes SET last_checked_at = ?, updated_at = ? WHERE id = ? AND type = 'smart'").run(now, now, noteId);
145309
145375
  }
145310
145376
  // ../plugin/src/features/magic-context/storage-ops.ts
145311
- init_logger();
145312
145377
  var queuePendingOpStatements = new WeakMap;
145313
145378
  var getPendingOpsStatements = new WeakMap;
145314
145379
  var clearPendingOpsStatements = new WeakMap;
@@ -145710,7 +145775,6 @@ var ERROR_CLASSES = new Set([
145710
145775
  "unknown"
145711
145776
  ]);
145712
145777
  // ../plugin/src/features/magic-context/v22-deferred-backfill.ts
145713
- init_logger();
145714
145778
  import { createHash as createHash4 } from "node:crypto";
145715
145779
  import { realpathSync as realpathSync2 } from "node:fs";
145716
145780
  import path5 from "node:path";
@@ -145989,8 +146053,6 @@ function getAgentFallbackModels(agent) {
145989
146053
  }
145990
146054
 
145991
146055
  // ../plugin/src/shared/models-dev-cache.ts
145992
- init_data_path();
145993
- init_logger();
145994
146056
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, writeFileSync } from "node:fs";
145995
146057
  import { join as join6 } from "node:path";
145996
146058
  var MIN_SANE_LIMIT = 20000;
@@ -146100,7 +146162,6 @@ function resolveHistorianContextLimit(historianModelOverride) {
146100
146162
  }
146101
146163
 
146102
146164
  // ../plugin/src/hooks/magic-context/event-resolvers.ts
146103
- init_logger();
146104
146165
  var DEFAULT_CONTEXT_LIMIT = 128000;
146105
146166
  var MAX_EXECUTE_THRESHOLD = 80;
146106
146167
  function resolveCacheTtl(cacheTtl, modelKey) {
@@ -146233,7 +146294,6 @@ function resolveTokensMatchWithKey(tokensConfig, modelKey) {
146233
146294
  }
146234
146295
 
146235
146296
  // ../plugin/src/hooks/magic-context/note-nudger.ts
146236
- init_logger();
146237
146297
  var NOTE_NUDGE_COOLDOWN_MS = 15 * 60 * 1000;
146238
146298
  var lastDeliveredAt = new Map;
146239
146299
  function getPersistedNoteNudgeDeliveredAt(_db, sessionId) {
@@ -146401,7 +146461,6 @@ function isTodoItem(value) {
146401
146461
  }
146402
146462
 
146403
146463
  // ../plugin/src/hooks/magic-context/upgrade-reminder.ts
146404
- init_logger();
146405
146464
  var remindedThisProcess = new Set;
146406
146465
  var UPGRADE_REMINDER_TEXT = [
146407
146466
  "\uD83C\uDF86 Historian V2 is released!",
@@ -146502,7 +146561,6 @@ async function maybeSendUpgradeReminder(deps, sessionId) {
146502
146561
  }
146503
146562
 
146504
146563
  // ../plugin/src/shared/announcement.ts
146505
- init_data_path();
146506
146564
  import * as fs2 from "node:fs";
146507
146565
  import * as path6 from "node:path";
146508
146566
  var ANNOUNCEMENT_VERSION = "0.22.0";
@@ -146548,9 +146606,14 @@ function shouldShowAnnouncement() {
146548
146606
  return lastVersion !== ANNOUNCEMENT_VERSION;
146549
146607
  }
146550
146608
 
146551
- // src/index.ts
146552
- init_data_path();
146553
- init_logger();
146609
+ // ../plugin/src/shared/keep-subagents.ts
146610
+ var keepSubagents = false;
146611
+ function setKeepSubagents(value) {
146612
+ keepSubagents = value === true;
146613
+ }
146614
+ function shouldKeepSubagents() {
146615
+ return keepSubagents;
146616
+ }
146554
146617
 
146555
146618
  // ../plugin/src/shared/resolve-fallbacks.ts
146556
146619
  function resolveFallbackChain(agentName, userFallbacks) {
@@ -146617,9 +146680,6 @@ function isEmptySidekickResult(text) {
146617
146680
  return trimmed.length === 0 || trimmed === "no relevant memories found";
146618
146681
  }
146619
146682
 
146620
- // src/commands/ctx-aug.ts
146621
- init_logger();
146622
-
146623
146683
  // src/subagent-runner.ts
146624
146684
  import * as childProcess from "node:child_process";
146625
146685
  import { existsSync as existsSync6 } from "node:fs";
@@ -146629,7 +146689,6 @@ import { createInterface } from "node:readline";
146629
146689
  import { fileURLToPath } from "node:url";
146630
146690
 
146631
146691
  // ../plugin/src/features/magic-context/subagent-token-capture.ts
146632
- init_logger();
146633
146692
  function asNumber(value) {
146634
146693
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
146635
146694
  }
@@ -146720,7 +146779,6 @@ function recordChildInvocation(input) {
146720
146779
  }
146721
146780
 
146722
146781
  // src/subagent-runner.ts
146723
- init_logger();
146724
146782
  function resolveBundledPiCli() {
146725
146783
  try {
146726
146784
  const require_ = createRequire2(import.meta.url);
@@ -147493,18 +147551,10 @@ function clearStaleEntries(db, maxAgeMs, projectIdentity) {
147493
147551
  const result = projectIdentity ? db.prepare("DELETE FROM dream_queue WHERE project_path = ? AND started_at IS NOT NULL AND started_at < ?").run(projectIdentity, cutoff) : db.prepare("DELETE FROM dream_queue WHERE started_at IS NOT NULL AND started_at < ?").run(cutoff);
147494
147552
  return result.changes;
147495
147553
  }
147496
-
147497
- // src/commands/ctx-dream.ts
147498
- init_logger();
147499
147554
  // ../plugin/src/features/magic-context/dreamer/runner.ts
147500
147555
  import { existsSync as existsSync8 } from "node:fs";
147501
147556
  import { join as join11 } from "node:path";
147502
-
147503
- // ../plugin/src/shared/index.ts
147504
- init_logger();
147505
-
147506
147557
  // ../plugin/src/shared/model-suggestion-retry.ts
147507
- init_logger();
147508
147558
  function extractMessage(error) {
147509
147559
  if (typeof error === "string")
147510
147560
  return error;
@@ -147739,40 +147789,66 @@ function extractLatestAssistantText(messages) {
147739
147789
  `) || null;
147740
147790
  }
147741
147791
 
147742
- // ../plugin/src/features/magic-context/dreamer/runner.ts
147743
- init_data_path();
147744
- init_logger();
147745
- await init_sqlite();
147746
-
147747
147792
  // ../plugin/src/features/magic-context/key-files/identify-key-files.ts
147748
147793
  import { readFileSync as readFileSync6 } from "node:fs";
147749
- import { isAbsolute, join as join10, relative as relative2 } from "node:path";
147750
- init_logger();
147794
+ import { isAbsolute as isAbsolute2, join as join10, relative as relative2 } from "node:path";
147751
147795
 
147752
147796
  // ../plugin/src/features/magic-context/key-files/aft-availability.ts
147753
147797
  var import_comment_json = __toESM(require_src2(), 1);
147754
147798
  import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
147755
147799
  import { homedir as homedir2 } from "node:os";
147756
- import { join as join9 } from "node:path";
147800
+ import { isAbsolute, join as join9, resolve as resolve2 } from "node:path";
147801
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
147757
147802
  var overrideAvailability = null;
147758
147803
  function parseConfig(path7) {
147759
147804
  if (!existsSync7(path7))
147760
147805
  return null;
147761
147806
  return import_comment_json.parse(readFileSync5(path7, "utf-8"));
147762
147807
  }
147763
- function entryMatchesAft(entry) {
147808
+ var AFT_NAME_NEEDLES = ["@cortexkit/aft", "aft-opencode", "aft-pi"];
147809
+ function stringMentionsAft(value) {
147810
+ return AFT_NAME_NEEDLES.some((needle) => value.includes(needle));
147811
+ }
147812
+ function resolveLocalEntryPackageName(value, configDir) {
147813
+ let dir = null;
147814
+ if (value.startsWith("file://")) {
147815
+ try {
147816
+ dir = fileURLToPath2(value);
147817
+ } catch {
147818
+ return null;
147819
+ }
147820
+ } else if (value.startsWith("~/")) {
147821
+ dir = join9(homedir2(), value.slice(2));
147822
+ } else if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
147823
+ dir = isAbsolute(value) ? value : resolve2(configDir, value);
147824
+ } else {
147825
+ return null;
147826
+ }
147827
+ try {
147828
+ const pkg = JSON.parse(readFileSync5(join9(dir, "package.json"), "utf-8"));
147829
+ return typeof pkg.name === "string" ? pkg.name : null;
147830
+ } catch {
147831
+ return null;
147832
+ }
147833
+ }
147834
+ function entryMatchesAft(entry, configDir) {
147764
147835
  const value = Array.isArray(entry) ? entry[0] : entry;
147765
- return typeof value === "string" && (value.includes("@cortexkit/aft") || value.includes("aft-opencode") || value.includes("aft-pi"));
147836
+ if (typeof value !== "string")
147837
+ return false;
147838
+ if (stringMentionsAft(value))
147839
+ return true;
147840
+ const name2 = resolveLocalEntryPackageName(value, configDir);
147841
+ return name2 != null && stringMentionsAft(name2);
147766
147842
  }
147767
- function hasAftInArray(value) {
147768
- return Array.isArray(value) && value.some(entryMatchesAft);
147843
+ function hasAftInArray(value, configDir) {
147844
+ return Array.isArray(value) && value.some((entry) => entryMatchesAft(entry, configDir));
147769
147845
  }
147770
- function hasAftAtKeys(value, keys) {
147846
+ function hasAftAtKeys(value, keys, configDir) {
147771
147847
  if (!value || typeof value !== "object")
147772
147848
  return false;
147773
147849
  const record = value;
147774
147850
  for (const key of keys) {
147775
- if (hasAftInArray(record[key]))
147851
+ if (hasAftInArray(record[key], configDir))
147776
147852
  return true;
147777
147853
  }
147778
147854
  return false;
@@ -147789,7 +147865,8 @@ function getAftAvailability() {
147789
147865
  for (const path7 of opencodePaths) {
147790
147866
  try {
147791
147867
  const config = parseConfig(path7);
147792
- if (hasAftAtKeys(config, ["plugin", "plugins", "mcp", "mcp_servers"])) {
147868
+ const configDir = join9(path7, "..");
147869
+ if (hasAftAtKeys(config, ["plugin", "plugins", "mcp", "mcp_servers"], configDir)) {
147793
147870
  opencode = true;
147794
147871
  break;
147795
147872
  }
@@ -147799,12 +147876,13 @@ function getAftAvailability() {
147799
147876
  for (const path7 of piPaths) {
147800
147877
  try {
147801
147878
  const config = parseConfig(path7);
147802
- if (hasAftAtKeys(config, ["packages", "extensions"])) {
147879
+ const configDir = join9(path7, "..");
147880
+ if (hasAftAtKeys(config, ["packages", "extensions"], configDir)) {
147803
147881
  pi = true;
147804
147882
  break;
147805
147883
  }
147806
147884
  const agent = config?.agent;
147807
- if (hasAftAtKeys(agent, ["packages", "extensions"])) {
147885
+ if (hasAftAtKeys(agent, ["packages", "extensions"], configDir)) {
147808
147886
  pi = true;
147809
147887
  break;
147810
147888
  }
@@ -147824,7 +147902,7 @@ function isAftAvailable() {
147824
147902
 
147825
147903
  // ../plugin/src/features/magic-context/key-files/read-history.ts
147826
147904
  import { realpathSync as realpathSync3 } from "node:fs";
147827
- import { relative, resolve as resolve2 } from "node:path";
147905
+ import { relative, resolve as resolve3 } from "node:path";
147828
147906
  function toMs(value) {
147829
147907
  if (typeof value === "number" && Number.isFinite(value))
147830
147908
  return value;
@@ -147861,7 +147939,7 @@ function coalesceRanges(ranges) {
147861
147939
  }
147862
147940
  function normalizeProjectRelativePath(projectPath, filePath) {
147863
147941
  const root = realpathSync3(projectPath);
147864
- const abs = filePath.startsWith("/") ? resolve2(filePath) : resolve2(root, filePath);
147942
+ const abs = filePath.startsWith("/") ? resolve3(filePath) : resolve3(root, filePath);
147865
147943
  let real = abs;
147866
147944
  try {
147867
147945
  real = realpathSync3(abs);
@@ -148004,9 +148082,6 @@ function collectKeyFileCandidates(args) {
148004
148082
  })).sort((a, b) => b.totalReads - a.totalReads || b.lastReadAt - a.lastReadAt).slice(0, 200);
148005
148083
  }
148006
148084
 
148007
- // ../plugin/src/features/magic-context/key-files/storage-key-files.ts
148008
- init_logger();
148009
-
148010
148085
  // ../plugin/src/features/magic-context/key-files/identify-key-files.ts
148011
148086
  var KEY_FILES_SYSTEM_PROMPT = "You are a file importance evaluator. Given read statistics about files in a coding session, identify which are core orientation files worth pinning in context. Return a JSON array.";
148012
148087
  class KeyFilesValidationError extends Error {
@@ -148226,11 +148301,13 @@ async function runKeyFilesLlm(args) {
148226
148301
  const text = extractLatestAssistantText(messages);
148227
148302
  if (!text)
148228
148303
  throw new Error("Dreamer returned no key-files output.");
148229
- return text;
148304
+ return { text, messages };
148230
148305
  } finally {
148231
- await args.client.session.delete({ path: { id: agentSessionId } }).catch(() => {
148232
- return;
148233
- });
148306
+ if (!shouldKeepSubagents()) {
148307
+ await args.client.session.delete({ path: { id: agentSessionId } }).catch(() => {
148308
+ return;
148309
+ });
148310
+ }
148234
148311
  }
148235
148312
  }
148236
148313
  async function runKeyFilesTask(args) {
@@ -148276,9 +148353,27 @@ async function runKeyFilesTask(args) {
148276
148353
  log(`[key-files] lease renewal threw: ${getErrorMessage(error)}`);
148277
148354
  }
148278
148355
  }, 60000);
148356
+ let invocationRecorded = false;
148357
+ const llmStartedAt = Date.now();
148358
+ const recordKeyFilesInvocation = (params) => {
148359
+ if (!args.parentSessionId || invocationRecorded)
148360
+ return;
148361
+ invocationRecorded = true;
148362
+ recordChildInvocation({
148363
+ db: args.db,
148364
+ parentSessionId: args.parentSessionId,
148365
+ harness: getHarness(),
148366
+ subagent: "dreamer",
148367
+ task: "key files",
148368
+ startedAt: llmStartedAt,
148369
+ status: params.status,
148370
+ messages: params.messages,
148371
+ error: params.error
148372
+ });
148373
+ };
148279
148374
  try {
148280
148375
  try {
148281
- const raw = await runKeyFilesLlm({
148376
+ const { text: raw, messages: llmMessages } = await runKeyFilesLlm({
148282
148377
  client: args.client,
148283
148378
  parentSessionId: args.parentSessionId,
148284
148379
  projectPath,
@@ -148286,8 +148381,10 @@ async function runKeyFilesTask(args) {
148286
148381
  deadline: args.deadline,
148287
148382
  fallbackModels: args.fallbackModels
148288
148383
  });
148384
+ recordKeyFilesInvocation({ status: "completed", messages: llmMessages });
148289
148385
  validated = validateLlmOutput(raw, args.config, projectPath, new Set(candidates.map((candidate) => candidate.path)));
148290
148386
  } catch (error) {
148387
+ recordKeyFilesInvocation({ status: "failed", error });
148291
148388
  log(`[key-files] LLM validation failed: ${getErrorMessage(error)}`);
148292
148389
  throw error;
148293
148390
  }
@@ -148881,9 +148978,6 @@ function getMemoryCountsByStatus(db, projectPath) {
148881
148978
  return counts;
148882
148979
  }
148883
148980
 
148884
- // ../plugin/src/features/magic-context/user-memory/review-user-memories.ts
148885
- init_logger();
148886
-
148887
148981
  // ../plugin/src/features/magic-context/dreamer/task-prompts.ts
148888
148982
  var DREAMER_SYSTEM_PROMPT = `You are a memory maintenance agent for the magic-context system.
148889
148983
  You run during scheduled dream windows to maintain a project's cross-session memory store and codebase documentation.
@@ -149386,7 +149480,8 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
149386
149480
  db: args.db,
149387
149481
  parentSessionId: args.parentSessionId,
149388
149482
  harness: "opencode",
149389
- subagent: "user_memory_review",
149483
+ subagent: "dreamer",
149484
+ task: "user memories",
149390
149485
  startedAt,
149391
149486
  status: params.status,
149392
149487
  messages: params.messages,
@@ -149510,7 +149605,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
149510
149605
  return result;
149511
149606
  } finally {
149512
149607
  clearInterval(leaseInterval);
149513
- if (agentSessionId) {
149608
+ if (agentSessionId && !shouldKeepSubagents()) {
149514
149609
  await args.client.session.delete({
149515
149610
  path: { id: agentSessionId },
149516
149611
  query: { directory: args.sessionDirectory }
@@ -149834,14 +149929,14 @@ async function runDream(args) {
149834
149929
  }
149835
149930
  } finally {
149836
149931
  clearInterval(leaseRenewalInterval);
149837
- if (agentSessionId && !taskFailed) {
149932
+ if (agentSessionId && !taskFailed && !shouldKeepSubagents()) {
149838
149933
  await args.client.session.delete({
149839
149934
  path: { id: agentSessionId }
149840
149935
  }).catch((error) => {
149841
149936
  log("[dreamer] failed to delete child session:", error);
149842
149937
  });
149843
- } else if (agentSessionId && taskFailed) {
149844
- log(`[dreamer] KEEPING failed child session ${agentSessionId} for task ${taskName} (debugging)`);
149938
+ } else if (agentSessionId && (taskFailed || shouldKeepSubagents())) {
149939
+ log(`[dreamer] KEEPING child session ${agentSessionId} for task ${taskName} (${taskFailed ? "failed" : "keep_subagents"})`);
149845
149940
  }
149846
149941
  }
149847
149942
  if (lostLease) {
@@ -150126,7 +150221,7 @@ Only include notes whose conditions you could definitively evaluate against exte
150126
150221
  parts: [{ type: "text", text: evaluationPrompt, synthetic: true }]
150127
150222
  }
150128
150223
  }, {
150129
- timeoutMs: Math.min(remainingMs, 300000),
150224
+ timeoutMs: Math.min(remainingMs, 5 * 60 * 1000),
150130
150225
  signal: abortController.signal,
150131
150226
  fallbackModels: args.fallbackModels,
150132
150227
  callContext: "dreamer:smart-notes"
@@ -150202,7 +150297,7 @@ Only include notes whose conditions you could definitively evaluate against exte
150202
150297
  });
150203
150298
  } finally {
150204
150299
  clearInterval(leaseInterval);
150205
- if (agentSessionId) {
150300
+ if (agentSessionId && !shouldKeepSubagents()) {
150206
150301
  await args.client.session.delete({
150207
150302
  path: { id: agentSessionId }
150208
150303
  }).catch(() => {});
@@ -150213,14 +150308,14 @@ var MAX_LEASE_RETRIES = 3;
150213
150308
  async function processDreamQueue(args) {
150214
150309
  const maxRuntimeMs = args.maxRuntimeMinutes * 60 * 1000;
150215
150310
  if (!hasActiveDreamLease(args.db)) {
150216
- clearStaleEntries(args.db, maxRuntimeMs + 1800000, args.projectIdentity);
150311
+ clearStaleEntries(args.db, maxRuntimeMs + 30 * 60 * 1000, args.projectIdentity);
150217
150312
  }
150218
150313
  const entry = dequeueNext(args.db, args.projectIdentity);
150219
150314
  if (!entry) {
150220
150315
  return null;
150221
150316
  }
150222
150317
  const projectDirectory = args.sessionDirectoryOverride ?? resolveDreamSessionDirectory(entry.projectIdentity);
150223
- log(`[dreamer] dequeued project ${entry.projectIdentity} (dir=${projectDirectory}), starting dream run`);
150318
+ log(`[dreamer] dequeued project ${entry.projectIdentity}, starting dream run`);
150224
150319
  let result;
150225
150320
  try {
150226
150321
  result = await runDream({
@@ -150256,7 +150351,6 @@ async function processDreamQueue(args) {
150256
150351
  return result;
150257
150352
  }
150258
150353
  // ../plugin/src/features/magic-context/dreamer/scheduler.ts
150259
- init_logger();
150260
150354
  function parseScheduleWindow(schedule) {
150261
150355
  const match = /^(\d{1,2}):(\d{2})-(\d{1,2}):(\d{2})$/.exec(schedule.trim());
150262
150356
  if (!match)
@@ -150331,7 +150425,6 @@ function checkScheduleAndEnqueue(db, schedule, ownProjectIdentity) {
150331
150425
  return enqueued;
150332
150426
  }
150333
150427
  // ../plugin/src/features/magic-context/git-commits/git-log-reader.ts
150334
- init_logger();
150335
150428
  import { execFile } from "node:child_process";
150336
150429
  import { promisify } from "node:util";
150337
150430
  var execFileAsync = promisify(execFile);
@@ -150344,6 +150437,7 @@ async function readGitCommits(directory, options = {}) {
150344
150437
  if (revision.startsWith("-")) {
150345
150438
  throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
150346
150439
  }
150440
+ const projectLabel = options.projectIdentity ?? "<project>";
150347
150441
  const args = [
150348
150442
  "log",
150349
150443
  revision,
@@ -150366,11 +150460,11 @@ async function readGitCommits(directory, options = {}) {
150366
150460
  stdout = result.stdout;
150367
150461
  } catch (error) {
150368
150462
  const message = error instanceof Error ? error.message : String(error);
150369
- log(`[git-commits] readGitCommits failed at cwd=${directory}: ${message.slice(0, 500)}`);
150463
+ log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
150370
150464
  return [];
150371
150465
  }
150372
150466
  if (stdout.trim().length === 0) {
150373
- log(`[git-commits] readGitCommits returned empty stdout at cwd=${directory} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
150467
+ log(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
150374
150468
  }
150375
150469
  return parseGitLogOutput(stdout);
150376
150470
  }
@@ -150414,9 +150508,6 @@ ${body}` : subject;
150414
150508
  }
150415
150509
  return commits;
150416
150510
  }
150417
- // ../plugin/src/features/magic-context/git-commits/indexer.ts
150418
- init_logger();
150419
-
150420
150511
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
150421
150512
  var exports_external = {};
150422
150513
  __export(exports_external, {
@@ -164857,6 +164948,7 @@ var MagicContextConfigSchema = exports_external.object({
164857
164948
  model: DEFAULT_LOCAL_EMBEDDING_MODEL
164858
164949
  }).describe("Embedding provider configuration"),
164859
164950
  temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add start/end date attributes on compartments. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
164951
+ keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
164860
164952
  caveman_text_compression: exports_external.object({
164861
164953
  enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Only active when ctx_reduce_enabled=false. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
164862
164954
  min_chars: exports_external.number().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
@@ -164892,9 +164984,6 @@ var MagicContextConfigSchema = exports_external.object({
164892
164984
  };
164893
164985
  });
164894
164986
 
164895
- // ../plugin/src/features/magic-context/memory/embedding.ts
164896
- init_logger();
164897
-
164898
164987
  // ../plugin/src/features/magic-context/memory/cosine-similarity.ts
164899
164988
  function cosineSimilarity(a, b) {
164900
164989
  if (a.length !== b.length) {
@@ -164940,8 +165029,6 @@ import { mkdirSync as mkdirSync5 } from "node:fs";
164940
165029
  import { open, stat, unlink, writeFile } from "node:fs/promises";
164941
165030
  import { dirname as dirname4, join as join12 } from "node:path";
164942
165031
  import { pathToFileURL } from "node:url";
164943
- init_data_path();
164944
- init_logger();
164945
165032
  var LOCK_POLL_MS = 150;
164946
165033
  var STALE_LOCK_MS = 3 * 60000;
164947
165034
  var MAX_LOCK_WAIT_MS = 5 * 60000;
@@ -164980,7 +165067,7 @@ async function acquireModelLoadLock(lockPath) {
164980
165067
  if (Date.now() - waitStart > MAX_LOCK_WAIT_MS) {
164981
165068
  throw new Error(`[magic-context] embedding-load lock wait exceeded ${MAX_LOCK_WAIT_MS}ms; another process is still loading the model. Skipping this init attempt to avoid an unsynchronized native load.`);
164982
165069
  }
164983
- await new Promise((resolve3) => setTimeout(resolve3, LOCK_POLL_MS));
165070
+ await new Promise((resolve4) => setTimeout(resolve4, LOCK_POLL_MS));
164984
165071
  }
164985
165072
  }
164986
165073
  }
@@ -165149,7 +165236,7 @@ class LocalEmbeddingProvider {
165149
165236
  }
165150
165237
  const delayMs = 300 * attempt + Math.floor(Math.random() * 200);
165151
165238
  log(`[magic-context] embedding model load attempt ${attempt}/${MAX_ATTEMPTS} failed transiently, retrying in ${delayMs}ms`);
165152
- await new Promise((resolve3) => setTimeout(resolve3, delayMs));
165239
+ await new Promise((resolve4) => setTimeout(resolve4, delayMs));
165153
165240
  }
165154
165241
  }
165155
165242
  if (this.pipeline) {
@@ -165177,8 +165264,8 @@ class LocalEmbeddingProvider {
165177
165264
  if (this.inFlight === 0) {
165178
165265
  return Promise.resolve();
165179
165266
  }
165180
- return new Promise((resolve3) => {
165181
- this.inFlightWaiters.push(resolve3);
165267
+ return new Promise((resolve4) => {
165268
+ this.inFlightWaiters.push(resolve4);
165182
165269
  });
165183
165270
  }
165184
165271
  finishInFlight() {
@@ -165277,7 +165364,6 @@ class LocalEmbeddingProvider {
165277
165364
  }
165278
165365
 
165279
165366
  // ../plugin/src/features/magic-context/memory/embedding-openai.ts
165280
- init_logger();
165281
165367
  function normalizeEndpoint2(endpoint) {
165282
165368
  return endpoint?.trim().replace(/\/+$/, "") ?? "";
165283
165369
  }
@@ -165493,7 +165579,6 @@ class OpenAICompatibleEmbeddingProvider {
165493
165579
 
165494
165580
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
165495
165581
  import { createHash as createHash7, randomUUID } from "node:crypto";
165496
- init_logger();
165497
165582
 
165498
165583
  // ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
165499
165584
  var saveStatements = new WeakMap;
@@ -166027,7 +166112,6 @@ async function embedText(text, signal) {
166027
166112
  var SWEEP_MAX_WALL_CLOCK_MS2 = 10 * 60 * 1000;
166028
166113
 
166029
166114
  // ../plugin/src/features/magic-context/git-commits/storage-git-commits.ts
166030
- init_logger();
166031
166115
  var insertStatements = new WeakMap;
166032
166116
  var existingShasStatements = new WeakMap;
166033
166117
  var projectCountStatements = new WeakMap;
@@ -166163,7 +166247,8 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
166163
166247
  const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
166164
166248
  const commits = await readGitCommits(directory, {
166165
166249
  sinceMs,
166166
- maxCommits: options.maxCommits
166250
+ maxCommits: options.maxCommits,
166251
+ projectIdentity: projectPath
166167
166252
  });
166168
166253
  result.scanned = commits.length;
166169
166254
  if (commits.length === 0) {
@@ -166238,9 +166323,6 @@ async function embedUnembeddedCommits(db, projectPath) {
166238
166323
  embedInProgress.delete(projectPath);
166239
166324
  }
166240
166325
  }
166241
- // ../plugin/src/features/magic-context/git-commits/search-git-commits.ts
166242
- init_logger();
166243
-
166244
166326
  // ../plugin/src/features/magic-context/memory/storage-memory-fts.ts
166245
166327
  var DEFAULT_SEARCH_LIMIT = 10;
166246
166328
  var searchStatements = new WeakMap;
@@ -166403,7 +166485,6 @@ function searchGitCommitsSync(db, projectPath, query, options) {
166403
166485
  return results.slice(0, options.limit);
166404
166486
  }
166405
166487
  // ../plugin/src/plugin/dream-timer.ts
166406
- init_logger();
166407
166488
  var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
166408
166489
  var activeTimer = null;
166409
166490
  function openTimerDatabaseOrNull(context) {
@@ -166430,7 +166511,7 @@ async function startDreamScheduleTimer(args) {
166430
166511
  const isNewRegistration = !registeredProjects.has(args.directory);
166431
166512
  registeredProjects.set(args.directory, args);
166432
166513
  if (isNewRegistration) {
166433
- log(`[dreamer] registered project ${args.directory} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
166514
+ log(`[dreamer] registered project ${args.projectIdentity} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
166434
166515
  }
166435
166516
  if (!activeTimer) {
166436
166517
  log(`[dreamer] started independent schedule timer (every ${DREAM_TIMER_INTERVAL_MS / 60000}m)`);
@@ -166445,7 +166526,7 @@ async function startDreamScheduleTimer(args) {
166445
166526
  }
166446
166527
  return () => {
166447
166528
  registeredProjects.delete(args.directory);
166448
- log(`[dreamer] unregistered project ${args.directory} (remaining=${registeredProjects.size})`);
166529
+ log(`[dreamer] unregistered project ${args.projectIdentity} (remaining=${registeredProjects.size})`);
166449
166530
  if (registeredProjects.size === 0 && activeTimer) {
166450
166531
  clearInterval(activeTimer);
166451
166532
  activeTimer = null;
@@ -166493,7 +166574,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled = getProjectEmbedd
166493
166574
  return;
166494
166575
  }
166495
166576
  try {
166496
- log(`[dreamer] timer tick (${origin}) ${reg.directory} — checking schedule window "${reg.dreamerConfig.schedule}"`);
166577
+ log(`[dreamer] timer tick (${origin}) ${reg.projectIdentity} — checking schedule window "${reg.dreamerConfig.schedule}"`);
166497
166578
  checkScheduleAndEnqueue(db, reg.dreamerConfig.schedule, reg.projectIdentity);
166498
166579
  await processDreamQueue({
166499
166580
  db,
@@ -166508,7 +166589,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled = getProjectEmbedd
166508
166589
  fallbackModels: resolveFallbackChain(DREAMER_AGENT, reg.dreamerConfig.fallback_models)
166509
166590
  });
166510
166591
  } catch (error51) {
166511
- log(`[dreamer] timer-triggered queue processing failed for ${reg.directory}:`, error51);
166592
+ log(`[dreamer] timer-triggered queue processing failed for ${reg.projectIdentity}:`, error51);
166512
166593
  }
166513
166594
  }
166514
166595
  function startGitSweepLeaseRenewal(db, projectIdentity, holderId) {
@@ -166530,12 +166611,12 @@ async function sweepGitCommits(args) {
166530
166611
  const lease2 = acquireGitSweepLease(db, projectIdentity, holderId);
166531
166612
  if (!lease2.acquired) {
166532
166613
  const reason = lease2.reason === "cooldown_active" ? `cooldown active until ${lease2.nextAllowedAt}` : `lease held by ${lease2.leaseHolder ?? "another holder"} until ${lease2.leaseExpiresAt ?? "unknown"}`;
166533
- log(`[git-commits] sweep skipped for ${projectIdentity} (${directory}): ${reason}`);
166614
+ log(`[git-commits] sweep skipped for ${projectIdentity}: ${reason}`);
166534
166615
  return;
166535
166616
  }
166536
166617
  const startedAt = Date.now();
166537
166618
  const stopRenewal = startGitSweepLeaseRenewal(db, projectIdentity, holderId);
166538
- log(`[git-commits] sweep starting for ${directory} (project=${projectIdentity} sinceDays=${gitCommitIndexing.since_days} maxCommits=${gitCommitIndexing.max_commits})`);
166619
+ log(`[git-commits] sweep starting for ${projectIdentity} (sinceDays=${gitCommitIndexing.since_days} maxCommits=${gitCommitIndexing.max_commits})`);
166539
166620
  try {
166540
166621
  const result = await indexCommitsForProject(db, projectIdentity, directory, {
166541
166622
  sinceDays: gitCommitIndexing.since_days,
@@ -166555,7 +166636,7 @@ async function sweepGitCommits(args) {
166555
166636
  } catch (error51) {
166556
166637
  releaseGitSweepLease(db, projectIdentity, holderId);
166557
166638
  const elapsedMs = Date.now() - startedAt;
166558
- log(`[git-commits] sweep failed for ${directory} after ${elapsedMs}ms: ${error51 instanceof Error ? error51.message : String(error51)}`);
166639
+ log(`[git-commits] sweep failed for ${projectIdentity} after ${elapsedMs}ms: ${error51 instanceof Error ? error51.message : String(error51)}`);
166559
166640
  } finally {
166560
166641
  stopRenewal();
166561
166642
  }
@@ -166563,7 +166644,6 @@ async function sweepGitCommits(args) {
166563
166644
 
166564
166645
  // ../plugin/src/plugin/embedding-bootstrap-helpers.ts
166565
166646
  import { createHash as createHash8 } from "node:crypto";
166566
- init_logger();
166567
166647
  var EMBEDDING_AFFECTING_KEYS = new Set([
166568
166648
  "embedding.api_key",
166569
166649
  "embedding.endpoint",
@@ -166731,7 +166811,7 @@ function migrateLegacyExperimental(rawConfig, warnings) {
166731
166811
  // ../plugin/src/config/variable.ts
166732
166812
  import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
166733
166813
  import { homedir as homedir3 } from "node:os";
166734
- import { dirname as dirname5, isAbsolute as isAbsolute2, resolve as resolve3 } from "node:path";
166814
+ import { dirname as dirname5, isAbsolute as isAbsolute3, resolve as resolve4 } from "node:path";
166735
166815
 
166736
166816
  // ../plugin/src/shared/jsonc-parser.ts
166737
166817
  function stripJsonComments(content) {
@@ -166841,9 +166921,9 @@ function substituteConfigVariables(input) {
166841
166921
  }
166842
166922
  let filePath = rawPath.trim();
166843
166923
  if (filePath.startsWith("~/")) {
166844
- filePath = resolve3(homedir3(), filePath.slice(2));
166845
- } else if (!isAbsolute2(filePath)) {
166846
- filePath = resolve3(configDir, filePath);
166924
+ filePath = resolve4(homedir3(), filePath.slice(2));
166925
+ } else if (!isAbsolute3(filePath)) {
166926
+ filePath = resolve4(configDir, filePath);
166847
166927
  }
166848
166928
  if (!existsSync9(filePath)) {
166849
166929
  warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
@@ -167458,7 +167538,6 @@ function registerCtxDreamCommand(pi, deps) {
167458
167538
  }
167459
167539
 
167460
167540
  // ../plugin/src/hooks/magic-context/execute-flush.ts
167461
- init_logger();
167462
167541
  function executeFlush(db, sessionId) {
167463
167542
  try {
167464
167543
  const pendingOps = getPendingOps(db, sessionId);
@@ -167490,7 +167569,6 @@ function executeFlush(db, sessionId) {
167490
167569
  import * as crypto2 from "node:crypto";
167491
167570
 
167492
167571
  // ../plugin/src/features/magic-context/scheduler.ts
167493
- init_logger();
167494
167572
  var TTL_PATTERN = /^(\d+)([smh])$/;
167495
167573
  var NUMERIC_PATTERN = /^\d+$/;
167496
167574
  var UNIT_TO_MS = {
@@ -167545,6 +167623,7 @@ function createScheduler(config2) {
167545
167623
  }
167546
167624
  };
167547
167625
  }
167626
+
167548
167627
  // ../plugin/src/features/magic-context/tagger.ts
167549
167628
  var TOOL_COMPOSITE_KEY_SEP = "\x00";
167550
167629
  function makeToolCompositeKey(ownerMsgId, callId) {
@@ -168304,7 +168383,6 @@ function replayCavemanCompression(sessionId, db, targets, tags) {
168304
168383
  }
168305
168384
 
168306
168385
  // ../plugin/src/hooks/magic-context/compartment-trigger.ts
168307
- init_logger();
168308
168386
  var PROACTIVE_TRIGGER_OFFSET_PERCENTAGE = 2;
168309
168387
  var POST_DROP_TARGET_RATIO = 0.75;
168310
168388
  var MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE = 6000;
@@ -168541,9 +168619,6 @@ class BoundedSessionMap {
168541
168619
  }
168542
168620
  }
168543
168621
 
168544
- // ../plugin/src/hooks/magic-context/inject-compartments.ts
168545
- init_logger();
168546
-
168547
168622
  // ../plugin/src/hooks/magic-context/decay-curve.ts
168548
168623
  var H50 = 24;
168549
168624
  var D = 25;
@@ -168713,7 +168788,6 @@ function extractM0Block(m0Text, tag) {
168713
168788
  // ../plugin/src/hooks/magic-context/key-files-block.ts
168714
168789
  import { readFileSync as readFileSync9, realpathSync as realpathSync4 } from "node:fs";
168715
168790
  import { join as join14, sep as sep2 } from "node:path";
168716
- init_logger();
168717
168791
  var cachedKeyFilesBySession = new Map;
168718
168792
  var staleUpdates = new Map;
168719
168793
  function staleKey(update) {
@@ -168811,9 +168885,6 @@ ${blocks.join(`
168811
168885
  return rendered;
168812
168886
  }
168813
168887
 
168814
- // ../plugin/src/hooks/magic-context/inject-compartments.ts
168815
- await init_read_session_db();
168816
-
168817
168888
  // ../plugin/src/hooks/magic-context/temporal-awareness.ts
168818
168889
  var TEMPORAL_AWARENESS_THRESHOLD_SECONDS = 300;
168819
168890
  var SECONDS_PER_MINUTE = 60;
@@ -168970,9 +169041,6 @@ function renderMemoryBlockV2(memories, wrapper = "project-memory") {
168970
169041
  `);
168971
169042
  }
168972
169043
 
168973
- // ../plugin/src/hooks/magic-context/nudger.ts
168974
- init_logger();
168975
-
168976
169044
  // ../plugin/src/shared/format-bytes.ts
168977
169045
  function formatBytes(bytes) {
168978
169046
  if (bytes < 1024)
@@ -169174,9 +169242,6 @@ function estimateProjectedPercentage(db, sessionId, contextUsage, preloadedTags)
169174
169242
  return contextUsage.percentage * (1 - dropRatio);
169175
169243
  }
169176
169244
 
169177
- // src/context-handler.ts
169178
- init_logger();
169179
-
169180
169245
  // ../plugin/src/shared/tag-transcript.ts
169181
169246
  function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
169182
169247
  const skipPrefixInjection = options.skipPrefixInjection === true;
@@ -169478,9 +169543,6 @@ function buildToolTarget(part, message) {
169478
169543
  };
169479
169544
  }
169480
169545
 
169481
- // ../plugin/src/features/magic-context/search.ts
169482
- init_logger();
169483
-
169484
169546
  // ../plugin/src/features/magic-context/literal-probes.ts
169485
169547
  var MAX_PROBES = 5;
169486
169548
  var MIN_PROBE_LENGTH = 3;
@@ -169537,7 +169599,6 @@ function containsProbeVerbatim(text, probes) {
169537
169599
  return probes.some((probe) => haystack.includes(probe.toLowerCase()));
169538
169600
  }
169539
169601
  // ../plugin/src/features/magic-context/memory/embedding-backfill.ts
169540
- init_logger();
169541
169602
  async function ensureMemoryEmbeddings(args) {
169542
169603
  const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
169543
169604
  if (!snapshot?.enabled) {
@@ -169576,7 +169637,6 @@ async function ensureMemoryEmbeddings(args) {
169576
169637
  return args.existingEmbeddings;
169577
169638
  }
169578
169639
  // ../plugin/src/features/magic-context/memory/promotion.ts
169579
- init_logger();
169580
169640
  function isPromotableCategory(category) {
169581
169641
  return PROMOTABLE_CATEGORIES.some((promotableCategory) => promotableCategory === category);
169582
169642
  }
@@ -170078,17 +170138,16 @@ ${trimmedBody}…
170078
170138
  }
170079
170139
 
170080
170140
  // src/auto-search-pi.ts
170081
- init_logger();
170082
170141
  var AUTO_SEARCH_TIMEOUT_MS = 3000;
170083
170142
  var DEFAULT_SCORE_THRESHOLD = 0.55;
170084
170143
  var DEFAULT_MIN_PROMPT_CHARS = 20;
170085
170144
  async function unifiedSearchWithTimeout(db, sessionId, projectPath, prompt, options, timeoutMs) {
170086
170145
  const controller = new AbortController;
170087
170146
  let timer;
170088
- const timeoutPromise = new Promise((resolve4) => {
170147
+ const timeoutPromise = new Promise((resolve5) => {
170089
170148
  timer = setTimeout(() => {
170090
170149
  controller.abort();
170091
- resolve4(null);
170150
+ resolve5(null);
170092
170151
  }, timeoutMs);
170093
170152
  });
170094
170153
  try {
@@ -170308,7 +170367,6 @@ ${hintText}`;
170308
170367
  function clearAutoSearchForPiSession(_sessionId) {}
170309
170368
 
170310
170369
  // src/compaction-marker-manager-pi.ts
170311
- init_logger();
170312
170370
  function applyDeferredPiCompactionMarker(deps, sessionId, pending) {
170313
170371
  try {
170314
170372
  const matches = getCompartmentsByEndMessageId(deps.db, sessionId, pending.endMessageId);
@@ -170450,7 +170508,6 @@ function stripSystemInjection(text) {
170450
170508
  }
170451
170509
 
170452
170510
  // src/heuristic-cleanup-pi.ts
170453
- init_logger();
170454
170511
  var DEDUP_SAFE_TOOLS = new Set([
170455
170512
  "mcp_grep",
170456
170513
  "mcp_read",
@@ -170700,9 +170757,6 @@ function buildMessageIdToMaxTagFromTargets(targets) {
170700
170757
  return byMessage;
170701
170758
  }
170702
170759
 
170703
- // src/inject-compartments-pi.ts
170704
- init_logger();
170705
-
170706
170760
  // src/read-session-pi.ts
170707
170761
  var SYNTH_USER_ID_PREFIX = "synth-user-";
170708
170762
  function resolvePiStableId(msg, index, entryIds, entryIdByRef) {
@@ -171085,6 +171139,13 @@ function safeGetActiveUserMemoriesPi(db) {
171085
171139
  throw error51;
171086
171140
  }
171087
171141
  }
171142
+ var EMPTY_PI_HARD_SIGNALS = {
171143
+ systemHash: "",
171144
+ toolSetHash: "",
171145
+ modelKey: "",
171146
+ cacheExpired: false,
171147
+ lastResponseTime: 0
171148
+ };
171088
171149
  function decodeCachedM0(value) {
171089
171150
  if (!value)
171090
171151
  return null;
@@ -171131,7 +171192,10 @@ function getCachedMarkers(db, state, compartmentsForNormalization) {
171131
171192
  sessionFactsVersion: meta3.cachedM0SessionFactsVersion,
171132
171193
  materializedAt: meta3.cachedM0MaterializedAt,
171133
171194
  upgradeState: meta3.cachedM0UpgradeState,
171134
- lastBaselineEndMessageId: cachedBoundary
171195
+ lastBaselineEndMessageId: cachedBoundary,
171196
+ systemHash: meta3.cachedM0SystemHash ?? "",
171197
+ toolSetHash: meta3.cachedM0ToolSetHash ?? "",
171198
+ modelKey: meta3.cachedM0ModelKey ?? ""
171135
171199
  };
171136
171200
  }
171137
171201
  function lastBaselineEndMessageId(compartments) {
@@ -171159,7 +171223,10 @@ function readCurrentMarkersFromCompartments(db, state, compartments, projectDocs
171159
171223
  sessionFactsVersion: getSessionFactsVersion(db, state.sessionId),
171160
171224
  materializedAt: Date.now(),
171161
171225
  upgradeState: `${PI_M0_UPGRADE_STATE}:${compartments.some((c) => c.legacy === 1) ? "legacy" : "ready"}`,
171162
- lastBaselineEndMessageId: lastBaselineEndMessageId(compartments)
171226
+ lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
171227
+ systemHash: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
171228
+ toolSetHash: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).toolSetHash,
171229
+ modelKey: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey
171163
171230
  };
171164
171231
  }
171165
171232
  function mustMaterializePi(state, db, currentCompartmentsOverride) {
@@ -171176,7 +171243,19 @@ function mustMaterializePi(state, db, currentCompartmentsOverride) {
171176
171243
  if (getCachedMarkers(db, state, currentCompartments) === null) {
171177
171244
  return { value: true, reason: "cache_invalid" };
171178
171245
  }
171179
- const cachedMaxCompartmentSeq = normalizeCachedMaxCompartmentSeq(meta3.cachedM0MaxCompartmentSeq ?? EMPTY_MAX_COMPARTMENT_SEQ, currentCompartments);
171246
+ const hard = state.hardSignals ?? EMPTY_PI_HARD_SIGNALS;
171247
+ if (hard.modelKey !== "" && hard.modelKey !== (meta3.cachedM0ModelKey ?? "")) {
171248
+ return { value: true, reason: "model_change" };
171249
+ }
171250
+ if (hard.systemHash !== "" && hard.systemHash !== (meta3.cachedM0SystemHash ?? "")) {
171251
+ return { value: true, reason: "system_hash" };
171252
+ }
171253
+ if (hard.toolSetHash !== "" && hard.toolSetHash !== (meta3.cachedM0ToolSetHash ?? "")) {
171254
+ return { value: true, reason: "tool_set_hash" };
171255
+ }
171256
+ if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (meta3.cachedM0MaterializedAt ?? 0)) {
171257
+ return { value: true, reason: "ttl_idle" };
171258
+ }
171180
171259
  if (meta3.cachedM0UpgradeState !== current.upgradeState) {
171181
171260
  return { value: true, reason: "renderer_upgrade" };
171182
171261
  }
@@ -171186,15 +171265,9 @@ function mustMaterializePi(state, db, currentCompartmentsOverride) {
171186
171265
  if (current.projectMemoryEpoch !== (meta3.cachedM0ProjectMemoryEpoch ?? 0)) {
171187
171266
  return { value: true, reason: "project_memory_change" };
171188
171267
  }
171189
- if (current.projectUserProfileVersion !== (meta3.cachedM0ProjectUserProfileVersion ?? 0)) {
171190
- return { value: true, reason: "user_profile_change" };
171191
- }
171192
171268
  if (current.maxMutationId !== (meta3.cachedM0MaxMutationId ?? 0)) {
171193
171269
  return { value: true, reason: "pending_mutations" };
171194
171270
  }
171195
- if (current.maxCompartmentSeq !== cachedMaxCompartmentSeq) {
171196
- return { value: true, reason: "new_compartment" };
171197
- }
171198
171271
  return { value: false, reason: null };
171199
171272
  }
171200
171273
  function renderUserProfileBlock(db, wrapper = "user-profile", memoriesOverride) {
@@ -171274,7 +171347,10 @@ function readFrozenM0InputsPi(state, db, docs = readProjectDocsCanonical(state.p
171274
171347
  sessionFactsVersion: getSessionFactsVersion(db, state.sessionId),
171275
171348
  materializedAt: Date.now(),
171276
171349
  upgradeState: `${PI_M0_UPGRADE_STATE}:${compartments.some((c) => c.legacy === 1) ? "legacy" : "ready"}`,
171277
- lastBaselineEndMessageId: lastBaselineEndMessageId(compartments)
171350
+ lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
171351
+ systemHash: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
171352
+ toolSetHash: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).toolSetHash,
171353
+ modelKey: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey
171278
171354
  };
171279
171355
  return { docs, markers, compartments, memories, userProfile };
171280
171356
  });
@@ -171350,7 +171426,10 @@ function materializeM0Pi(state, db) {
171350
171426
  projectDocsHash: snapshotMarkers.projectDocsHash,
171351
171427
  materializedAt: snapshotMarkers.materializedAt,
171352
171428
  sessionFactsVersion: snapshotMarkers.sessionFactsVersion,
171353
- upgradeState: snapshotMarkers.upgradeState
171429
+ upgradeState: snapshotMarkers.upgradeState,
171430
+ systemHash: snapshotMarkers.systemHash,
171431
+ toolSetHash: snapshotMarkers.toolSetHash,
171432
+ modelKey: snapshotMarkers.modelKey
171354
171433
  });
171355
171434
  db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ? WHERE session_id = ?").run(renderedMemoryIds.length, JSON.stringify(renderedMemoryIds), state.sessionId);
171356
171435
  setCachedBoundary(db, state.sessionId, snapshotMarkers.lastBaselineEndMessageId);
@@ -171516,6 +171595,9 @@ function readCachedPiM0M1Row(db, sessionId) {
171516
171595
  cached_m0_materialized_at,
171517
171596
  cached_m0_session_facts_version,
171518
171597
  cached_m0_upgrade_state,
171598
+ cached_m0_system_hash,
171599
+ cached_m0_tool_set_hash,
171600
+ cached_m0_model_key,
171519
171601
  cached_m0_last_baseline_end_message_id,
171520
171602
  memory_block_ids
171521
171603
  FROM session_meta
@@ -171553,14 +171635,17 @@ function markersFromCachedPiRow(row, compartmentsForNormalization) {
171553
171635
  materializedAt: row.cached_m0_materialized_at,
171554
171636
  sessionFactsVersion: row.cached_m0_session_facts_version,
171555
171637
  upgradeState: row.cached_m0_upgrade_state,
171556
- lastBaselineEndMessageId: typeof row.cached_m0_last_baseline_end_message_id === "string" && row.cached_m0_last_baseline_end_message_id.length > 0 ? row.cached_m0_last_baseline_end_message_id : null
171638
+ lastBaselineEndMessageId: typeof row.cached_m0_last_baseline_end_message_id === "string" && row.cached_m0_last_baseline_end_message_id.length > 0 ? row.cached_m0_last_baseline_end_message_id : null,
171639
+ systemHash: row.cached_m0_system_hash ?? "",
171640
+ toolSetHash: row.cached_m0_tool_set_hash ?? "",
171641
+ modelKey: row.cached_m0_model_key ?? ""
171557
171642
  };
171558
171643
  }
171559
171644
  function cachedPiRowMatchesSnapshot(args) {
171560
171645
  const rowMarkers = markersFromCachedPiRow(args.row, args.compartmentsForNormalization);
171561
171646
  if (!rowMarkers)
171562
171647
  return false;
171563
- return bufferEqualsNullable(args.row.cached_m0_bytes, args.m0Bytes) && rowMarkers.projectMemoryEpoch === args.markers.projectMemoryEpoch && rowMarkers.projectUserProfileVersion === args.markers.projectUserProfileVersion && rowMarkers.maxCompartmentSeq === args.markers.maxCompartmentSeq && rowMarkers.maxMemoryId === args.markers.maxMemoryId && rowMarkers.maxMutationId === args.markers.maxMutationId && rowMarkers.maxMemoryMutationId === args.markers.maxMemoryMutationId && (rowMarkers.projectDocsHash ?? "") === (args.markers.projectDocsHash ?? "") && rowMarkers.materializedAt === args.markers.materializedAt && rowMarkers.sessionFactsVersion === args.markers.sessionFactsVersion && (rowMarkers.upgradeState ?? null) === (args.markers.upgradeState ?? null);
171648
+ return bufferEqualsNullable(args.row.cached_m0_bytes, args.m0Bytes) && rowMarkers.projectMemoryEpoch === args.markers.projectMemoryEpoch && rowMarkers.projectUserProfileVersion === args.markers.projectUserProfileVersion && rowMarkers.maxCompartmentSeq === args.markers.maxCompartmentSeq && rowMarkers.maxMemoryId === args.markers.maxMemoryId && rowMarkers.maxMutationId === args.markers.maxMutationId && rowMarkers.maxMemoryMutationId === args.markers.maxMemoryMutationId && (rowMarkers.projectDocsHash ?? "") === (args.markers.projectDocsHash ?? "") && rowMarkers.materializedAt === args.markers.materializedAt && rowMarkers.sessionFactsVersion === args.markers.sessionFactsVersion && (rowMarkers.upgradeState ?? null) === (args.markers.upgradeState ?? null) && (rowMarkers.systemHash ?? "") === (args.markers.systemHash ?? "") && (rowMarkers.toolSetHash ?? "") === (args.markers.toolSetHash ?? "") && (rowMarkers.modelKey ?? "") === (args.markers.modelKey ?? "");
171564
171649
  }
171565
171650
  function decodeCachedM1(row, sessionId) {
171566
171651
  if (!row.cached_m1_bytes) {
@@ -171620,12 +171705,14 @@ function softRefreshCachedM1Pi(args) {
171620
171705
  }
171621
171706
  const rendered = renderM1PiWithMetadata(args.state, args.db, markers, parseMemoryBlockIds(row.memory_block_ids), preRenderedKeyFilesBlock);
171622
171707
  const m1Bytes = Buffer.from(rendered.text, "utf8");
171623
- args.db.prepare("UPDATE session_meta SET cached_m1_bytes = ? WHERE session_id = ?").run(m1Bytes, args.state.sessionId);
171708
+ const latestCompartment = args.compartmentsForNormalization.at(-1);
171709
+ const advancedBoundary = latestCompartment?.endMessageId && latestCompartment.endMessageId.length > 0 ? latestCompartment.endMessageId : markers.lastBaselineEndMessageId;
171710
+ args.db.prepare("UPDATE session_meta SET cached_m1_bytes = ?, cached_m0_last_baseline_end_message_id = ? WHERE session_id = ?").run(m1Bytes, advancedBoundary, args.state.sessionId);
171624
171711
  args.db.exec("COMMIT");
171625
171712
  return {
171626
171713
  m0: decodeCachedM0(row.cached_m0_bytes) ?? "",
171627
171714
  m1: rendered.text,
171628
- markers,
171715
+ markers: { ...markers, lastBaselineEndMessageId: advancedBoundary },
171629
171716
  memoryUpdateCount: rendered.memoryUpdateCount,
171630
171717
  recomputed: true
171631
171718
  };
@@ -171745,7 +171832,10 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
171745
171832
  markers = replayed.markers;
171746
171833
  }
171747
171834
  const M0_DRIFT_RATIO_FLOOR = 2000;
171748
- if (!materialized && !contentionExhausted && m1Recomputed && recomputeM1ThisPass && (memoryUpdateCount > 40 || m1 !== PI_M1_PLACEHOLDER && m0.length >= M0_DRIFT_RATIO_FLOOR && m1.length > m0.length * 0.15)) {
171835
+ const M1_ABSOLUTE_CAP_RATIO = 0.2;
171836
+ const m1AbsoluteBudget = (state.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS) * M1_ABSOLUTE_CAP_RATIO;
171837
+ const m1OverAbsoluteCap = m1 !== PI_M1_PLACEHOLDER && estimateTokens(m1) > m1AbsoluteBudget;
171838
+ if (!materialized && !contentionExhausted && m1Recomputed && recomputeM1ThisPass && (memoryUpdateCount > 40 || m1OverAbsoluteCap || m1 !== PI_M1_PLACEHOLDER && m0.length >= M0_DRIFT_RATIO_FLOOR && m1.length > m0.length * 0.15)) {
171749
171839
  decision = { value: true, reason: "drift" };
171750
171840
  try {
171751
171841
  const result = materializeM0PiWithRetry(state, db);
@@ -171928,7 +172018,6 @@ function isRecord3(value) {
171928
172018
  }
171929
172019
 
171930
172020
  // ../plugin/src/features/magic-context/compartment-embedding.ts
171931
- init_logger();
171932
172021
  async function embedAndStoreCompartments(db, sessionId, projectPath, compartments) {
171933
172022
  if (compartments.length === 0)
171934
172023
  return;
@@ -172825,7 +172914,6 @@ Memory is disabled for this project: do NOT emit a <facts> block. Produce compar
172825
172914
  }
172826
172915
 
172827
172916
  // ../plugin/src/hooks/magic-context/compartment-runner-drop-queue.ts
172828
- init_logger();
172829
172917
  function queueDropsForCompartmentalizedMessages(db, sessionId, upToMessageIndex) {
172830
172918
  const tags = getTagsBySession(db, sessionId);
172831
172919
  const { messageFileKeys, toolObservations } = getRawSessionTagKeysThrough(sessionId, upToMessageIndex);
@@ -174949,7 +175037,6 @@ function buildReferenceBlocks(args) {
174949
175037
  }
174950
175038
 
174951
175039
  // src/pi-historian-runner.ts
174952
- init_logger();
174953
175040
  var HISTORIAN_AGENT_NAME = "magic-context-historian";
174954
175041
  var DEFAULT_HISTORIAN_TIMEOUT_MS2 = 120000;
174955
175042
  var HISTORIAN_ALERT_COOLDOWN_MS = 60 * 1000;
@@ -175732,7 +175819,6 @@ function replayStrippedInlineThinkingPi(args) {
175732
175819
  }
175733
175820
 
175734
175821
  // src/strip-placeholders-pi.ts
175735
- init_logger();
175736
175822
  var DROPPED_SEGMENT_PATTERN = /^\[dropped(?: §[^§]+§)?\]$/;
175737
175823
  function isDroppedOnlyText(text) {
175738
175824
  const trimmed = text.trim();
@@ -175936,7 +176022,6 @@ Prefer many small targeted operations over one large blanket operation, and keep
175936
176022
  }
175937
176023
 
175938
176024
  // src/system-prompt.ts
175939
- init_logger();
175940
176025
  var MAGIC_CONTEXT_MARKER = "## Magic Context";
175941
176026
  var stickyDateBySession = new Map;
175942
176027
  function buildMagicContextBlock(opts) {
@@ -176017,10 +176102,8 @@ function injectPiTemporalMarkers(messages) {
176017
176102
  if (prefix !== null) {
176018
176103
  const userMsg = msg;
176019
176104
  if (typeof userMsg.content === "string") {
176020
- if (!TEMPORAL_MARKER_PATTERN.test(stripTagPrefix2(userMsg.content))) {
176021
- const tagMatch = userMsg.content.match(/^(?:§\d+§\s*)+/);
176022
- const tagPrefix = tagMatch ? tagMatch[0] : "";
176023
- const body = userMsg.content.slice(tagPrefix.length);
176105
+ if (!TEMPORAL_MARKER_PATTERN.test(stripTagPrefix(userMsg.content))) {
176106
+ const { tagPrefix, body } = peelLeadingMcTagNotation(userMsg.content);
176024
176107
  messages[i] = {
176025
176108
  ...userMsg,
176026
176109
  content: tagPrefix + prefix + body
@@ -176031,9 +176114,7 @@ function injectPiTemporalMarkers(messages) {
176031
176114
  const firstTextIndex = userMsg.content.findIndex((p) => p && typeof p === "object" && p.type === "text");
176032
176115
  if (firstTextIndex >= 0) {
176033
176116
  const existing = userMsg.content[firstTextIndex];
176034
- const tagMatch = existing.text.match(/^(?:§\d+§\s*)+/);
176035
- const tagPrefix = tagMatch ? tagMatch[0] : "";
176036
- const body = existing.text.slice(tagPrefix.length);
176117
+ const { tagPrefix, body } = peelLeadingMcTagNotation(existing.text);
176037
176118
  if (!TEMPORAL_MARKER_PATTERN.test(body)) {
176038
176119
  const newContent = userMsg.content.slice();
176039
176120
  newContent[firstTextIndex] = {
@@ -176056,18 +176137,12 @@ function injectPiTemporalMarkers(messages) {
176056
176137
  }
176057
176138
  return injected;
176058
176139
  }
176059
- function stripTagPrefix2(text) {
176060
- const match = text.match(/^(?:§\d+§\s*)+/);
176061
- if (!match)
176062
- return text;
176063
- return text.slice(match[0].length);
176064
- }
176065
176140
 
176066
176141
  // src/timeout.ts
176067
176142
  function withTimeout(p, ms) {
176068
176143
  let handle;
176069
- const timeout = new Promise((resolve4) => {
176070
- handle = setTimeout(() => resolve4(undefined), ms);
176144
+ const timeout = new Promise((resolve5) => {
176145
+ handle = setTimeout(() => resolve5(undefined), ms);
176071
176146
  handle.unref?.();
176072
176147
  });
176073
176148
  return Promise.race([p, timeout]).finally(() => {
@@ -177799,9 +177874,18 @@ async function runPipeline(args) {
177799
177874
  if (args.injection) {
177800
177875
  try {
177801
177876
  const tInjection = performance.now();
177802
- if (args.isCacheBusting || deferredHistoryRefresh) {
177803
- clearM0M1PiCache(args.db, args.sessionId, args.isCacheBusting ? "history refresh" : "deferred history refresh");
177804
- }
177877
+ const hardMeta = getOrCreateSessionMeta(args.db, args.sessionId);
177878
+ let piTtlMs = 5 * 60 * 1000;
177879
+ try {
177880
+ piTtlMs = parseCacheTtl(hardMeta.cacheTtl);
177881
+ } catch {}
177882
+ const piHardSignals = {
177883
+ systemHash: typeof hardMeta.systemPromptHash === "string" ? hardMeta.systemPromptHash : "",
177884
+ toolSetHash: "",
177885
+ modelKey: liveModelBySession.get(args.sessionId) ?? "",
177886
+ cacheExpired: hardMeta.lastResponseTime > 0 && Date.now() - hardMeta.lastResponseTime >= piTtlMs,
177887
+ lastResponseTime: hardMeta.lastResponseTime
177888
+ };
177805
177889
  injectionResult = injectM0M1Pi({
177806
177890
  sessionId: args.sessionId,
177807
177891
  projectIdentity: args.projectIdentity,
@@ -177809,8 +177893,9 @@ async function runPipeline(args) {
177809
177893
  injectionBudgetTokens: args.injection.injectionBudgetTokens,
177810
177894
  historyBudgetTokens: args.injection.historyBudgetTokens,
177811
177895
  keyFilesEnabled: args.injection.keyFilesEnabled,
177812
- keyFilesTokenBudget: args.injection.keyFilesTokenBudget
177813
- }, args.db, args.messages, args.entryIds, executedWorkThisPass);
177896
+ keyFilesTokenBudget: args.injection.keyFilesTokenBudget,
177897
+ hardSignals: piHardSignals
177898
+ }, args.db, args.messages, args.entryIds, args.isCacheBusting || deferredHistoryRefresh || executedWorkThisPass);
177814
177899
  if (args.isCacheBusting) {
177815
177900
  historyRefreshSessions.delete(args.sessionId);
177816
177901
  historyWasConsumedThisPass = true;
@@ -178163,12 +178248,8 @@ ${result}`;
178163
178248
  });
178164
178249
  }
178165
178250
 
178166
- // ../plugin/src/hooks/magic-context/compartment-runner.ts
178167
- init_logger();
178168
-
178169
178251
  // ../plugin/src/hooks/magic-context/historian-state-file.ts
178170
178252
  import { mkdirSync as mkdirSync6, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
178171
- init_data_path();
178172
178253
  function cleanupHistorianStateFile(path7) {
178173
178254
  if (!path7)
178174
178255
  return;
@@ -178176,13 +178257,7 @@ function cleanupHistorianStateFile(path7) {
178176
178257
  unlinkSync(path7);
178177
178258
  } catch {}
178178
178259
  }
178179
- // ../plugin/src/hooks/magic-context/compartment-runner-incremental.ts
178180
- init_logger();
178181
-
178182
178260
  // ../plugin/src/features/magic-context/compaction-marker.ts
178183
- init_data_path();
178184
- init_logger();
178185
- await init_sqlite();
178186
178261
  import { join as join15 } from "node:path";
178187
178262
  var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
178188
178263
  function randomBase62(length) {
@@ -178337,9 +178412,6 @@ function removeCompactionMarker(state) {
178337
178412
  }
178338
178413
 
178339
178414
  // ../plugin/src/hooks/magic-context/compaction-marker-manager.ts
178340
- init_data_path();
178341
- init_logger();
178342
- await init_sqlite();
178343
178415
  var MARKER_SUMMARY_TEXT = "[Compacted by magic-context — session history is managed by the plugin]";
178344
178416
  function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, directory) {
178345
178417
  const existing = getPersistedCompactionMarkerState(db, sessionId);
@@ -178373,7 +178445,6 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
178373
178445
  // ../plugin/src/hooks/magic-context/compartment-runner-historian.ts
178374
178446
  import { mkdirSync as mkdirSync7, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
178375
178447
  import { join as join16 } from "node:path";
178376
- init_data_path();
178377
178448
  function historianResponseDumpDir(directory) {
178378
178449
  return getProjectMagicContextHistorianDir(directory);
178379
178450
  }
@@ -178573,12 +178644,12 @@ async function runHistorianPrompt(args) {
178573
178644
  error: `Historian failed while processing this session: ${desc.brief}`
178574
178645
  };
178575
178646
  } finally {
178576
- if (agentSessionId && outcomeOk) {
178647
+ if (agentSessionId && outcomeOk && !shouldKeepSubagents()) {
178577
178648
  await client.session.delete({ path: { id: agentSessionId } }).catch((e) => {
178578
178649
  sessionLog(parentSessionId, "compartment agent: session cleanup failed", getErrorMessage(e));
178579
178650
  });
178580
- } else if (agentSessionId && !outcomeOk) {
178581
- sessionLog(parentSessionId, `historian: KEEPING failed child session ${agentSessionId} for debugging (not deleted)`);
178651
+ } else if (agentSessionId && (!outcomeOk || shouldKeepSubagents())) {
178652
+ sessionLog(parentSessionId, `historian: KEEPING child session ${agentSessionId} (${outcomeOk ? "keep_subagents" : "failed"}) — not deleted`);
178582
178653
  }
178583
178654
  }
178584
178655
  }
@@ -178657,8 +178728,8 @@ function isTransientHistorianPromptError(message) {
178657
178728
  ].some((token) => normalized.includes(token));
178658
178729
  }
178659
178730
  function sleep(ms) {
178660
- return new Promise((resolve4) => {
178661
- setTimeout(resolve4, ms);
178731
+ return new Promise((resolve5) => {
178732
+ setTimeout(resolve5, ms);
178662
178733
  });
178663
178734
  }
178664
178735
  function cleanupHistorianDump(sessionId, dumpPath) {
@@ -178699,7 +178770,6 @@ function sanitizeDumpName(value) {
178699
178770
  }
178700
178771
 
178701
178772
  // ../plugin/src/hooks/magic-context/send-session-notification.ts
178702
- init_logger();
178703
178773
  function hasNotificationSessionClient(client) {
178704
178774
  if (client === null || typeof client !== "object")
178705
178775
  return false;
@@ -178798,11 +178868,7 @@ async function sendIgnoredMessage(client, sessionId, text, params, forcePersist
178798
178868
  var HISTORIAN_ALERT_COOLDOWN_MS2 = 60 * 1000;
178799
178869
  var lastHistorianAlertBySession2 = new Map;
178800
178870
 
178801
- // ../plugin/src/hooks/magic-context/compartment-runner-partial-recomp.ts
178802
- init_logger();
178803
-
178804
178871
  // ../plugin/src/hooks/magic-context/compartment-runner-recomp.ts
178805
- init_logger();
178806
178872
  function insertRecompCompartmentRows(db, sessionId, compartments, now) {
178807
178873
  const stmt = db.prepare("INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, p1, p2, p3, p4, importance, episode_type, legacy, created_at, harness) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
178808
178874
  for (const c of compartments) {
@@ -179571,9 +179637,6 @@ async function executeContextRecompWithResult(deps, options = {}) {
179571
179637
  }
179572
179638
  }
179573
179639
 
179574
- // src/commands/ctx-recomp.ts
179575
- init_logger();
179576
-
179577
179640
  // src/pi-recomp-client-shared.ts
179578
179641
  function createPiHistorianClient(args) {
179579
179642
  const sessions = new Map;
@@ -179705,9 +179768,6 @@ function resolvePiReadBranchEntries2(ctx) {
179705
179768
  };
179706
179769
  }
179707
179770
 
179708
- // src/pi-recomp-runner.ts
179709
- init_logger();
179710
-
179711
179771
  // src/status-line.ts
179712
179772
  var STATUS_KEY = "magic-context";
179713
179773
  var RECENT_FAILURE_MS = 60000;
@@ -180036,7 +180096,6 @@ function inferLevel(text) {
180036
180096
  }
180037
180097
 
180038
180098
  // ../plugin/src/features/magic-context/memory/memory-migration.ts
180039
- init_logger();
180040
180099
  function memoryMigrationGuardKey(projectPath) {
180041
180100
  return `memory_migration_5cat:${projectPath}`;
180042
180101
  }
@@ -180146,11 +180205,7 @@ function contextualizeUpgradeReason(reason) {
180146
180205
  return rewritten;
180147
180206
  }
180148
180207
 
180149
- // src/commands/ctx-session-upgrade.ts
180150
- init_logger();
180151
-
180152
180208
  // src/pi-memory-migration.ts
180153
- init_logger();
180154
180209
  var MIGRATION_SYSTEM_PROMPT2 = "You re-organize a software project's long-term memory into a stricter taxonomy. " + "Follow the user instructions exactly. Output ONLY the requested XML blocks, nothing else.";
180155
180210
  async function runPiMemoryMigration(deps) {
180156
180211
  const projectPath = resolveProjectIdentity(deps.directory);
@@ -180425,7 +180480,6 @@ ${migrationSummary}` : "",
180425
180480
  }
180426
180481
 
180427
180482
  // ../plugin/src/hooks/magic-context/execute-status.ts
180428
- init_logger();
180429
180483
  function formatExecuteThreshold(thresholdPercentage, mode, contextLimit) {
180430
180484
  if (mode === "tokens" && contextLimit > 0) {
180431
180485
  const tokens = Math.floor(thresholdPercentage / 100 * contextLimit);
@@ -180592,7 +180646,7 @@ function formatThresholdPercent(value) {
180592
180646
  // package.json
180593
180647
  var package_default = {
180594
180648
  name: "@cortexkit/pi-magic-context",
180595
- version: "0.22.2",
180649
+ version: "0.22.4",
180596
180650
  type: "module",
180597
180651
  description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
180598
180652
  main: "dist/index.js",
@@ -181177,8 +181231,6 @@ function computePiPressure(usage, contextLimit) {
181177
181231
  }
181178
181232
 
181179
181233
  // src/strip-tag-prefix.ts
181180
- var LEADING_TAG_PREFIX_REGEX = /^(\u00a7\d+\u00a7\s*)+/;
181181
- var SECTION_CHAR_REGEX = /\u00a7/g;
181182
181234
  function stripTagPrefixFromAssistantMessage(message) {
181183
181235
  if (message.role !== "assistant")
181184
181236
  return false;
@@ -181192,7 +181244,7 @@ function stripTagPrefixFromAssistantMessage(message) {
181192
181244
  const textPart = part;
181193
181245
  if (typeof textPart.text !== "string")
181194
181246
  continue;
181195
- const stripped = textPart.text.replace(LEADING_TAG_PREFIX_REGEX, "").replace(SECTION_CHAR_REGEX, "");
181247
+ const stripped = stripPersistedAssistantText(textPart.text);
181196
181248
  if (stripped !== textPart.text) {
181197
181249
  textPart.text = stripped;
181198
181250
  mutated = true;
@@ -185332,7 +185384,6 @@ function createCtxExpandTool(deps) {
185332
185384
  }
185333
185385
 
185334
185386
  // src/tools/ctx-memory.ts
185335
- init_logger();
185336
185387
  var DEFAULT_LIST_LIMIT = 10;
185337
185388
  var VALID_CATEGORIES = new Set(CATEGORY_PRIORITY);
185338
185389
  function isMemoryCategory2(value) {
@@ -186357,7 +186408,7 @@ async function persistPiPressureFromMessageEnd(args) {
186357
186408
  updates.cacheAlertSent = true;
186358
186409
  const safeTokens = Math.max(observedSafeInputTokens, pressure.inputTokens);
186359
186410
  const modelLabel = provider2 && model ? `${provider2}/${model}` : "the active model";
186360
- await args.notifyIssue?.(`⚠️ Magic Context: Pi reports a context limit of ${formatTokens(contextLimit)} tokens for ${modelLabel} but you've successfully sent ${formatTokens(safeTokens)} tokens in this session — the cached limit looks wrong. Restart Pi if you suspect this is incorrect.`);
186411
+ await args.notifyIssue?.(`⚠️ Magic Context: Pi reports a context limit of ${formatTokens(contextLimit)} tokens for ${modelLabel} but you've successfully sent ${formatTokens(safeTokens)} tokens in this session — the reported limit looks wrong. Restart Pi if you suspect this is incorrect.`);
186361
186412
  }
186362
186413
  }
186363
186414
  updates.lastContextPercentage = percentage;
@@ -186500,6 +186551,7 @@ async function src_default2(pi) {
186500
186551
  mmapSizeMb: config2.sqlite.mmap_size_mb
186501
186552
  });
186502
186553
  applySqliteTuningPragmas(db);
186554
+ setKeepSubagents(config2.keep_subagents === true);
186503
186555
  if (!config2.enabled) {
186504
186556
  info("plugin DISABLED via config (enabled: false) — skipping registration");
186505
186557
  return;