@retaw106/mmc-pi 2.0.0 → 2.1.1

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
@@ -165,7 +165,7 @@ import {
165
165
  getRawSessionTagKeysThrough2,
166
166
  getLegacyProtectedTailStartOrdinal2,
167
167
  readSessionChunk2
168
- } from "./index-kxehmcmt.js";
168
+ } from "./index-4n1w7ehq.js";
169
169
  import {
170
170
  registerSlowWriteReporter,
171
171
  registerSqliteDiagnosticSink,
@@ -175,9 +175,11 @@ import {
175
175
  withSqliteBackgroundWriter,
176
176
  withSqliteTransformPass,
177
177
  withoutSqliteTransformPass,
178
+ guardSqliteTransformPass,
178
179
  isTransientSqliteError,
180
+ withAsyncPrivilegedWriter,
179
181
  withPrivilegedWriter
180
- } from "./index-wv28nczk.js";
182
+ } from "./index-ny303arh.js";
181
183
  import {
182
184
  pushNotification2
183
185
  } from "./index-b3eqj1g6.js";
@@ -189,7 +191,7 @@ import {
189
191
  // src/index.ts
190
192
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
191
193
  import { createRequire as createRequire2 } from "node:module";
192
- import { join as join14, resolve as resolve7 } from "node:path";
194
+ import { join as join14, resolve as resolve8 } from "node:path";
193
195
 
194
196
  // ../plugin/src/config/agent-disable.ts
195
197
  var COMPACTION_ENABLED_PATH = `compaction${"."}enabled`;
@@ -8084,6 +8086,10 @@ function sampleLiveConfig(boot, fresh) {
8084
8086
  let value = fresh;
8085
8087
  for (const part of parts)
8086
8088
  value = value?.[part];
8089
+ if (value === undefined) {
8090
+ removeLeaf(result, parts);
8091
+ continue;
8092
+ }
8087
8093
  let target = result;
8088
8094
  for (const part of parts.slice(0, -1)) {
8089
8095
  const child = target[part];
@@ -8097,6 +8103,26 @@ function sampleLiveConfig(boot, fresh) {
8097
8103
  }
8098
8104
  return result;
8099
8105
  }
8106
+ function removeLeaf(root, parts) {
8107
+ const parents = parts.slice(0, -1);
8108
+ let node = root;
8109
+ for (const part of parents) {
8110
+ const child = node[part];
8111
+ if (!child || typeof child !== "object" || Array.isArray(child))
8112
+ return;
8113
+ node = child;
8114
+ }
8115
+ const leaf = parts.at(-1);
8116
+ if (leaf === undefined || !Object.hasOwn(node, leaf))
8117
+ return;
8118
+ let target = root;
8119
+ for (const part of parents) {
8120
+ const copy = { ...target[part] };
8121
+ target[part] = copy;
8122
+ target = copy;
8123
+ }
8124
+ delete target[leaf];
8125
+ }
8100
8126
  function changedLiveKeys(previous, next) {
8101
8127
  const at = (config, path) => path.split(".").reduce((node, part) => node?.[part], config);
8102
8128
  return LIVE_RELOAD_CONFIG_PATHS.filter((path) => JSON.stringify(at(previous, path)) !== JSON.stringify(at(next, path)));
@@ -10152,6 +10178,41 @@ function emergencyDrainExitThreshold(executeThresholdPercentage) {
10152
10178
  }
10153
10179
  return Math.max(0, executeThresholdPercentage - EMERGENCY_DRAIN_EXIT_MARGIN);
10154
10180
  }
10181
+ function resolvedEmergencyDrainLatch(meta, usagePercentage, executeThresholdPercentage, now) {
10182
+ const { forceMaterializationPercentage } = escalationBands(executeThresholdPercentage);
10183
+ if (usagePercentage >= forceMaterializationPercentage)
10184
+ return meta.emergencyDrainActive > 0 ? meta.emergencyDrainActive : now;
10185
+ if (usagePercentage < emergencyDrainExitThreshold(executeThresholdPercentage) || now - meta.emergencyDrainActive > EMERGENCY_DRAIN_MAX_LATCH_MS)
10186
+ return 0;
10187
+ return meta.emergencyDrainActive;
10188
+ }
10189
+ function drainFailureBackoffActive(meta, now) {
10190
+ return meta.historianDrainFailureAt > 0 && meta.historianDrainFailureAt <= now && now - meta.historianDrainFailureAt < EMERGENCY_DRAIN_FAILURE_BACKOFF_MS;
10191
+ }
10192
+ function getProtectedTailDrainBudgetSkip(args) {
10193
+ const now = args.now ?? Date.now();
10194
+ const meta = loadProtectedTailMeta(args.db, args.sessionId);
10195
+ const latch = resolvedEmergencyDrainLatch(meta, args.usagePercentage, args.executeThresholdPercentage, now);
10196
+ if (latch !== meta.emergencyDrainActive) {
10197
+ args.db.prepare("UPDATE session_meta SET emergency_drain_active = ? WHERE session_id = ? AND emergency_drain_active = ?").run(latch, args.sessionId, meta.emergencyDrainActive);
10198
+ }
10199
+ const startedAt = meta.protectedTailDrainWindowStartedAt;
10200
+ if (startedAt <= 0 || startedAt > now || now - startedAt >= DRAIN_WINDOW_MS)
10201
+ return null;
10202
+ const limitTokens = protectedTailWindowBudget(args.usagePercentage, args.usable, args.perRunCap);
10203
+ if (meta.protectedTailDrainTokens < limitTokens)
10204
+ return null;
10205
+ if (latch > 0 && !drainFailureBackoffActive(meta, now))
10206
+ return null;
10207
+ return {
10208
+ windowStartedAt: startedAt,
10209
+ resetsAt: startedAt + DRAIN_WINDOW_MS,
10210
+ nextEligibleAt: latch > 0 ? Math.min(startedAt + DRAIN_WINDOW_MS, meta.historianDrainFailureAt + EMERGENCY_DRAIN_FAILURE_BACKOFF_MS) : startedAt + DRAIN_WINDOW_MS,
10211
+ resetInMs: startedAt + DRAIN_WINDOW_MS - now,
10212
+ spentTokens: meta.protectedTailDrainTokens,
10213
+ limitTokens
10214
+ };
10215
+ }
10155
10216
  function reserveProtectedTailDrainTokens(args) {
10156
10217
  const now = args.now ?? Date.now();
10157
10218
  const requested = Math.max(0, Math.floor(args.trueRawTokens));
@@ -10183,17 +10244,7 @@ function reserveProtectedTailDrainTokens(args) {
10183
10244
  WHERE session_id = ?`).run(now, args.sessionId);
10184
10245
  meta = loadProtectedTailMeta(args.db, args.sessionId);
10185
10246
  }
10186
- const exitThreshold = emergencyDrainExitThreshold(args.executeThresholdPercentage);
10187
- let latchActiveSince = meta.emergencyDrainActive;
10188
- const { forceMaterializationPercentage } = escalationBands(args.executeThresholdPercentage);
10189
- if (args.usagePercentage >= forceMaterializationPercentage) {
10190
- if (latchActiveSince <= 0)
10191
- latchActiveSince = now;
10192
- } else if (latchActiveSince > 0) {
10193
- const expired = now - latchActiveSince > EMERGENCY_DRAIN_MAX_LATCH_MS;
10194
- if (args.usagePercentage < exitThreshold || expired)
10195
- latchActiveSince = 0;
10196
- }
10247
+ const latchActiveSince = resolvedEmergencyDrainLatch(meta, args.usagePercentage, args.executeThresholdPercentage, now);
10197
10248
  if (latchActiveSince !== meta.emergencyDrainActive) {
10198
10249
  args.db.prepare("UPDATE session_meta SET emergency_drain_active = ? WHERE session_id = ?").run(latchActiveSince, args.sessionId);
10199
10250
  }
@@ -10202,7 +10253,7 @@ function reserveProtectedTailDrainTokens(args) {
10202
10253
  const remaining = Math.max(0, budget - meta.protectedTailDrainTokens);
10203
10254
  let reserved = Math.min(requested, args.perRunCap, remaining);
10204
10255
  let bypass = false;
10205
- const inFailureBackoff = meta.historianDrainFailureAt > 0 && meta.historianDrainFailureAt <= now && now - meta.historianDrainFailureAt < EMERGENCY_DRAIN_FAILURE_BACKOFF_MS;
10256
+ const inFailureBackoff = drainFailureBackoffActive(meta, now);
10206
10257
  if (reserved <= 0 && latchActive && !inFailureBackoff) {
10207
10258
  reserved = Math.min(requested, args.perRunCap);
10208
10259
  bypass = true;
@@ -11043,6 +11094,10 @@ function resolveEpochFloorForPass(db, sessionId, inputs) {
11043
11094
  import { Buffer as Buffer3 } from "node:buffer";
11044
11095
 
11045
11096
  // ../plugin/src/v2/store-reader.ts
11097
+ import { createHash as createHash4 } from "node:crypto";
11098
+ import { statSync as statSync3 } from "node:fs";
11099
+ import { hostname } from "node:os";
11100
+ import { resolve as resolve3 } from "node:path";
11046
11101
  function gaDatabasePath(dataHome, channel = "latest", env = process.env) {
11047
11102
  return resolveOpenCodeDbPath("v2", { dataHome, channel, env }).path;
11048
11103
  }
@@ -11155,6 +11210,8 @@ function decode2(row) {
11155
11210
  return { ...row, data };
11156
11211
  }
11157
11212
  function connect(path, identity = "") {
11213
+ const stat = statSync3(path);
11214
+ const acquiredIdentity = identity || `${stat.dev}:${stat.ino}:${stat.birthtimeMs}`;
11158
11215
  const db = new Database(path, { readonly: true, fileMustExist: true });
11159
11216
  try {
11160
11217
  assertOpenCodeStoreGeneration(db, "v2", path);
@@ -11166,7 +11223,7 @@ function connect(path, identity = "") {
11166
11223
  counters.openReaders += 1;
11167
11224
  counters.readersOpened += 1;
11168
11225
  counters.maxOpenReaders = Math.max(counters.maxOpenReaders, counters.openReaders);
11169
- return { db, statements: new Map, identity, leases: 0, retired: false };
11226
+ return { db, statements: new Map, identity: acquiredIdentity, leases: 0, retired: false };
11170
11227
  }
11171
11228
  function closeConnection(connection) {
11172
11229
  connection.statements.clear();
@@ -11179,15 +11236,20 @@ function closeConnection(connection) {
11179
11236
  }
11180
11237
  }
11181
11238
  class V2StoreReader {
11239
+ path;
11182
11240
  pool;
11183
11241
  db;
11184
11242
  connection;
11185
11243
  closed = false;
11186
11244
  constructor(path, pool) {
11245
+ this.path = path;
11187
11246
  this.pool = pool;
11188
11247
  this.connection = pool ? pool.acquire(path) : connect(path);
11189
11248
  this.db = this.connection.db;
11190
11249
  }
11250
+ hostIdentity() {
11251
+ return createHash4("sha256").update(JSON.stringify([hostname(), resolve3(this.path), this.connection.identity])).digest("hex");
11252
+ }
11191
11253
  prepare(sql) {
11192
11254
  if (this.closed)
11193
11255
  throw new Error("Store reader is closed");
@@ -11283,6 +11345,10 @@ class V2StoreReader {
11283
11345
  return null;
11284
11346
  return typeof row.parent_id === "string" && row.parent_id.length > 0;
11285
11347
  }
11348
+ storedRowsAfter(sessionID, after) {
11349
+ const row = this.prepare("SELECT COUNT(*) AS count FROM session_message WHERE session_id = ? AND seq > ?").get(sessionID, after);
11350
+ return row.count;
11351
+ }
11286
11352
  storedMessageCount(sessionID) {
11287
11353
  return trackDecodeOperation("storedMessageCount", () => {
11288
11354
  const row = this.prepare("SELECT COUNT(*) AS count FROM session_message WHERE session_id = ?").get(sessionID);
@@ -11526,10 +11592,10 @@ function resolveIsSubagentFromOpenCode2Db(sessionId) {
11526
11592
  }
11527
11593
 
11528
11594
  // ../plugin/src/features/magic-context/message-fts-rowid-map.ts
11529
- import { createHash as createHash4 } from "node:crypto";
11595
+ import { createHash as createHash5 } from "node:crypto";
11530
11596
  var MESSAGE_FTS_ROWID_MAP_BACKFILL_BATCH_SIZE = 100;
11531
11597
  var BACKFILL_STATE_ID = 1;
11532
- var EMPTY_INDEX_CONTENT_HASH = createHash4("sha256").update("").digest("hex");
11598
+ var EMPTY_INDEX_CONTENT_HASH = createHash5("sha256").update("").digest("hex");
11533
11599
  var upsertMapStatements = new WeakMap;
11534
11600
  var rangeReadyStatements = new WeakMap;
11535
11601
  var updateTimeStatements = new WeakMap;
@@ -11732,11 +11798,17 @@ function getSessionMetaSelectColumns(db) {
11732
11798
  sessionMetaSelectColumnsCache.set(db, projection);
11733
11799
  return projection;
11734
11800
  }
11735
- function getOrCreateSessionMeta(db, sessionId) {
11801
+ function findSessionMeta(db, sessionId) {
11736
11802
  const result = db.prepare(`SELECT ${getSessionMetaSelectColumns(db)} FROM session_meta WHERE session_id = ?`).get(sessionId);
11737
- if (isSessionMetaRow(result)) {
11738
- return toSessionMeta(result);
11739
- }
11803
+ return isSessionMetaRow(result) ? toSessionMeta(result) : undefined;
11804
+ }
11805
+ function readSessionMeta(db, sessionId) {
11806
+ return findSessionMeta(db, sessionId) ?? getDefaultSessionMeta(sessionId);
11807
+ }
11808
+ function getOrCreateSessionMeta(db, sessionId) {
11809
+ const existing = findSessionMeta(db, sessionId);
11810
+ if (existing)
11811
+ return existing;
11740
11812
  const harness = getHarness();
11741
11813
  const defaults = getDefaultSessionMeta(sessionId);
11742
11814
  const fallbackSubagent = harness === "opencode" ? resolveIsSubagentFromOpenCodeDb(sessionId) : harness === "opencode2" ? resolveIsSubagentFromOpenCode2Db(sessionId) : null;
@@ -11863,10 +11935,14 @@ function recordSessionProjectIdentity(db, sessionId, projectPath) {
11863
11935
  return;
11864
11936
  const harness = getHarness();
11865
11937
  const now = Date.now();
11938
+ let previousProjectPath;
11866
11939
  db.transaction(() => {
11940
+ const existing = db.prepare("SELECT project_path FROM session_projects WHERE session_id = ? AND harness = ?").get(sessionId, harness);
11941
+ previousProjectPath = existing?.project_path;
11867
11942
  getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
11868
11943
  getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath, SESSION_CHUNK_REPAIR_BATCH_SIZE);
11869
11944
  }).immediate();
11945
+ return previousProjectPath === projectPath ? undefined : { previousProjectPath, projectPath };
11870
11946
  }
11871
11947
 
11872
11948
  // ../plugin/src/features/magic-context/session-project-backfill.ts
@@ -13233,7 +13309,7 @@ function ensureContextStoreUuid(db) {
13233
13309
  return getContextStoreUuid(db) ?? minted;
13234
13310
  }
13235
13311
  // ../plugin/src/features/magic-context/message-index.ts
13236
- import { createHash as createHash5 } from "node:crypto";
13312
+ import { createHash as createHash6 } from "node:crypto";
13237
13313
  var MESSAGE_HISTORY_ORPHAN_SAFETY_AGE_MS = 24 * 60 * 60 * 1000;
13238
13314
  var MESSAGE_HISTORY_ORPHAN_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
13239
13315
  var MESSAGE_HISTORY_ORPHAN_UNAVAILABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
@@ -13440,7 +13516,7 @@ function toMessageIndexSource(message) {
13440
13516
  role: message.role,
13441
13517
  createdAt: message.createdAt,
13442
13518
  sourceVersion: normalizeSourceVersion(message.version),
13443
- contentHash: createHash5("sha256").update(content).digest("hex"),
13519
+ contentHash: createHash6("sha256").update(content).digest("hex"),
13444
13520
  content
13445
13521
  };
13446
13522
  }
@@ -13662,7 +13738,7 @@ function indexItemsAfterOrdinal(db, sessionId, items, finalWatermark, toSource)
13662
13738
  return inserted;
13663
13739
  }
13664
13740
  // ../plugin/src/features/magic-context/lkg-prefix-chunks.ts
13665
- import { createHash as createHash6 } from "node:crypto";
13741
+ import { createHash as createHash7 } from "node:crypto";
13666
13742
  var LKG_PREFIX_CHUNK_CHARS = 64 * 1024;
13667
13743
  function splitLkgPrefix(jsonPrefix) {
13668
13744
  const chunks = [];
@@ -13680,10 +13756,10 @@ function splitLkgPrefix(jsonPrefix) {
13680
13756
  return chunks;
13681
13757
  }
13682
13758
  function hashLkgChunk(body) {
13683
- return createHash6("sha256").update(body).digest("hex");
13759
+ return createHash7("sha256").update(body).digest("hex");
13684
13760
  }
13685
13761
  function hashLkgChunkList(chunkHashes) {
13686
- return createHash6("sha256").update(chunkHashes.join(`
13762
+ return createHash7("sha256").update(chunkHashes.join(`
13687
13763
  `)).digest("hex");
13688
13764
  }
13689
13765
  function layoutLkgPrefix(jsonPrefix) {
@@ -14153,7 +14229,7 @@ async function runMigrationsWithRetry(db, options = {}) {
14153
14229
  }
14154
14230
  }
14155
14231
  // ../plugin/src/hooks/magic-context/lkg-slot.ts
14156
- import { createHash as createHash7 } from "node:crypto";
14232
+ import { createHash as createHash8 } from "node:crypto";
14157
14233
 
14158
14234
  // ../plugin/src/shared/bounded-session-map.ts
14159
14235
  class BoundedSessionMap {
@@ -14308,7 +14384,7 @@ function lkgContentFields(value) {
14308
14384
  }
14309
14385
  }
14310
14386
  function lkgContentDigestFromFields(fields) {
14311
- const hash = createHash7("sha256");
14387
+ const hash = createHash8("sha256");
14312
14388
  for (const field of fields) {
14313
14389
  const value = typeof field === "symbol" ? field.description ?? "" : String(field);
14314
14390
  hash.update(`${typeof field}:${value.length}:`).update(value).update("\x00");
@@ -15135,8 +15211,8 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
15135
15211
  });
15136
15212
  }
15137
15213
  // ../plugin/src/features/magic-context/storage-db.ts
15138
- import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync9, statSync as statSync3, unlinkSync } from "node:fs";
15139
- import { basename, dirname as dirname3, join as join6, resolve as resolve3 } from "node:path";
15214
+ import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync9, statSync as statSync4, unlinkSync } from "node:fs";
15215
+ import { basename, dirname as dirname3, join as join6, resolve as resolve4 } from "node:path";
15140
15216
 
15141
15217
  // ../plugin/src/plugin/boot-quiet.ts
15142
15218
  var BOOT_QUIET_MS = 120000;
@@ -15626,7 +15702,7 @@ var RPC_DISCOVERY_PARSE_GRACE_MS = 10 * 60 * 1000;
15626
15702
  var defaultRpcDiscoveryFs = {
15627
15703
  readdirSync: (path, options) => options?.withFileTypes ? readdirSync2(path, { withFileTypes: true }) : readdirSync2(path),
15628
15704
  readFileSync: (path, encoding) => String(readFileSync9(path, encoding)),
15629
- statSync: (path) => ({ mtimeMs: statSync3(path).mtimeMs }),
15705
+ statSync: (path) => ({ mtimeMs: statSync4(path).mtimeMs }),
15630
15706
  unlinkSync: (path) => unlinkSync(path)
15631
15707
  };
15632
15708
  var rpcDiscoveryFs = defaultRpcDiscoveryFs;
@@ -15830,7 +15906,7 @@ function isDefaultSharedDatabasePath(dbPath) {
15830
15906
  if (!process.env.XDG_DATA_HOME && (process.env.MMC_TEST_DATA_DIR || false)) {
15831
15907
  return false;
15832
15908
  }
15833
- return resolve3(dbPath) === resolve3(join6(getMagicContextStorageDir(), "context.db"));
15909
+ return resolve4(dbPath) === resolve4(join6(getMagicContextStorageDir(), "context.db"));
15834
15910
  }
15835
15911
  function migrationBlockingPiPids(dbPath, discovery, discoveredPiPids) {
15836
15912
  if (isDefaultSharedDatabasePath(dbPath))
@@ -15915,8 +15991,8 @@ function finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion)
15915
15991
  startMessageFtsRowidMapBackfill(db).then(async () => {
15916
15992
  if (!readsOpenCodeStore)
15917
15993
  return;
15918
- const { readRawSessionMessagePage, readRawSessionMessages } = await import("./read-session-chunk-7m31yz4a.js");
15919
- const { startMessageTimeBackfill } = await import("./message-time-backfill-wnxmrd09.js");
15994
+ const { readRawSessionMessagePage, readRawSessionMessages } = await import("./read-session-chunk-7wcjah1z.js");
15995
+ const { startMessageTimeBackfill } = await import("./message-time-backfill-a3p9r5rh.js");
15920
15996
  await startMessageTimeBackfill(db, Object.assign(readRawSessionMessages, {
15921
15997
  readPage: readRawSessionMessagePage
15922
15998
  }));
@@ -18115,7 +18191,7 @@ var ERROR_CLASSES = new Set([
18115
18191
  "unknown"
18116
18192
  ]);
18117
18193
  // ../plugin/src/features/magic-context/workspaces.ts
18118
- import { createHash as createHash8 } from "node:crypto";
18194
+ import { createHash as createHash9 } from "node:crypto";
18119
18195
 
18120
18196
  // ../plugin/src/features/magic-context/memory/constants.ts
18121
18197
  var V2_MEMORY_CATEGORIES = [
@@ -18342,7 +18418,7 @@ function computeWorkspaceEpochFingerprint(db, identities) {
18342
18418
  const canonical = uniqueSorted(identities.filter((identity) => identity.length > 0));
18343
18419
  const epochs = getEpochMap(db, canonical);
18344
18420
  const shareCategories = selectWorkspaceShareCategories(db, canonical);
18345
- const hash = createHash8("sha256");
18421
+ const hash = createHash9("sha256");
18346
18422
  hash.update("share_categories", "utf8");
18347
18423
  hash.update("\x00");
18348
18424
  hash.update(shareCategories === null ? "NO_WORKSPACE" : JSON.stringify(shareCategories), "utf8");
@@ -19056,8 +19132,8 @@ function resolveHistorianModel(config, harness) {
19056
19132
  }
19057
19133
 
19058
19134
  // ../plugin/src/shared/prompt-surface-runtime.ts
19059
- import { readFileSync as readFileSync11, statSync as statSync4 } from "node:fs";
19060
- import { dirname as dirname4, isAbsolute as isAbsolute2, resolve as resolve4 } from "node:path";
19135
+ import { readFileSync as readFileSync11, statSync as statSync5 } from "node:fs";
19136
+ import { dirname as dirname4, isAbsolute as isAbsolute2, resolve as resolve5 } from "node:path";
19061
19137
 
19062
19138
  // ../plugin/src/tools/light-descriptions.ts
19063
19139
  var CTX_REDUCE_LIGHT_DESCRIPTION = `Stamp an item as no longer needed for the work ahead. Not a delete: stamping QUEUES it, the item stays readable until Magic Context clears stamped items in one sweep, newest tags are protected, and a cleared item goes to the archive (recent: a [dropped §N§] placeholder; older: removed) recoverable via mmc_expand(tag=N). The question is "does this need to stay on my desk for what comes next?" — a file you keep editing stays, the grep that found it goes. Stamp used reads/searches/outputs, acted-on build/test output, redundant dumps, extracted pasted payloads; keep user messages, your own text, unresolved errors, raw evidence, exact wording that may matter. Look at each tag; never blanket-stamp "1-50". Grammar: "3-5", "1,2,9", "1-5,8,12-15".`;
@@ -19090,7 +19166,7 @@ function promptSurfaceHashMaterial(systemContent, preset = "full") {
19090
19166
  var PROMPT_SURFACE_TOOL_ID_SET = new Set(ACTIVE_TOOL_IDS);
19091
19167
  function resolveUserConfigDirectory(options) {
19092
19168
  if (options.userConfigDirectory)
19093
- return resolve4(options.userConfigDirectory);
19169
+ return resolve5(options.userConfigDirectory);
19094
19170
  return dirname4(opencodeUserConfigBasePath());
19095
19171
  }
19096
19172
  function markerCount(content) {
@@ -19108,10 +19184,10 @@ function createPromptSurfaceRuntime(options) {
19108
19184
  const readGuidanceOverride = (configuredPath) => {
19109
19185
  if (!configuredPath)
19110
19186
  return;
19111
- const path = isAbsolute2(configuredPath) ? configuredPath : resolve4(userConfigDirectory, configuredPath);
19187
+ const path = isAbsolute2(configuredPath) ? configuredPath : resolve5(userConfigDirectory, configuredPath);
19112
19188
  let content;
19113
19189
  try {
19114
- if (!statSync4(path).isFile()) {
19190
+ if (!statSync5(path).isFile()) {
19115
19191
  warnOnce(`guidance-not-file:${path}`, `prompt_surface.guidance_override_path (${path}) is not a file; using built-in guidance.`);
19116
19192
  return;
19117
19193
  }
@@ -21092,12 +21168,14 @@ function normalizeMaterializeReason(harness, reason, rematerialized) {
21092
21168
  }
21093
21169
  return rematerialized ? "pressure_refold" : null;
21094
21170
  }
21095
- function recordPendingPiTransformDecision(sessionId, decision, snapshotNewestAssistantEntryId) {
21171
+ function recordPendingPiTransformDecision(sessionId, decision, snapshotNewestAssistantEntryId, publicationGuard) {
21172
+ publicationGuard?.();
21096
21173
  if (!decision.bustedThisPass)
21097
21174
  return;
21098
21175
  pendingPiDecisionBySession.set(sessionId, {
21099
21176
  ...decision,
21100
- snapshotNewestAssistantEntryId
21177
+ snapshotNewestAssistantEntryId,
21178
+ publicationGuard
21101
21179
  });
21102
21180
  }
21103
21181
  function findNewestPiAssistantEntryId(entries) {
@@ -21122,6 +21200,14 @@ function schedulePiTransformDecisionResolve(args) {
21122
21200
  const pending = pendingPiDecisionBySession.get(args.sessionId);
21123
21201
  if (!pending)
21124
21202
  return false;
21203
+ try {
21204
+ pending.publicationGuard?.();
21205
+ args.assertCurrentPass?.();
21206
+ } catch {
21207
+ pendingPiDecisionBySession.delete(args.sessionId);
21208
+ sessionLog(args.sessionId, "DISCARDED CONTEXT RESULT: pending Pi transform decision");
21209
+ return false;
21210
+ }
21125
21211
  const targetMessageId = findNewestPiAssistantEntryIdAfter(args.branchEntries, pending.snapshotNewestAssistantEntryId);
21126
21212
  if (!targetMessageId)
21127
21213
  return false;
@@ -21134,6 +21220,13 @@ function schedulePiTransformDecisionResolve(args) {
21134
21220
  try {
21135
21221
  if (!hasScheduledWriteToken(args.sessionId, token))
21136
21222
  return;
21223
+ try {
21224
+ pending.publicationGuard?.();
21225
+ args.assertCurrentPass?.();
21226
+ } catch {
21227
+ sessionLog(args.sessionId, "DISCARDED CONTEXT RESULT: queued Pi transform decision");
21228
+ return;
21229
+ }
21137
21230
  writeTransformDecisionBestEffort(dbPath, {
21138
21231
  ...pending,
21139
21232
  sessionId: args.sessionId,
@@ -22700,12 +22793,14 @@ function applyHeadCap(args) {
22700
22793
  diagnostics.completedRefence.tokenMass = index.rangeTokens(Math.min(...component.map((arc) => arc.invocation)), Math.max(...component.map((arc) => arc.result)) + 1);
22701
22794
  });
22702
22795
  diagnostics.completedRefence.to = end;
22703
- diagnostics.eligibleEnd = end <= offset ? offset : Math.min(end, protectedTailStart);
22796
+ if (end > protectedTailStart)
22797
+ end = offset;
22798
+ diagnostics.eligibleEnd = end <= offset ? offset : end;
22704
22799
  args.observeDiagnostics?.(diagnostics);
22705
22800
  if (end <= offset && offset < protectedTailStart) {
22706
22801
  return { eligibleEndOrdinal: offset, oversizeAtomicUnit };
22707
22802
  }
22708
- return { eligibleEndOrdinal: Math.min(end, protectedTailStart), oversizeAtomicUnit };
22803
+ return { eligibleEndOrdinal: end, oversizeAtomicUnit };
22709
22804
  }
22710
22805
  function resolveProtectedTailBoundary(ctx) {
22711
22806
  const createdAt = ctx.createdAt ?? Date.now();
@@ -22860,6 +22955,7 @@ function resolveProtectedTailBoundary(ctx) {
22860
22955
  }
22861
22956
  protectedTailStart = clampOrdinal(protectedTailStart, rawMessageCount);
22862
22957
  protectedTailStart = retreatPastHostUnservedRows(messages, protectedTailStart, offset);
22958
+ protectedTailStart = Math.max(offset, fenceBoundaryForCompletedToolArcs(protectedTailStart, arcs, 1));
22863
22959
  const perRunCap = selectPerRunCap({
22864
22960
  usagePercentage,
22865
22961
  N: scaledN,
@@ -22879,7 +22975,8 @@ function resolveProtectedTailBoundary(ctx) {
22879
22975
  capTokens: perRunCap,
22880
22976
  recentOpenArcCutoff
22881
22977
  });
22882
- const eligibleEndOrdinal = retreatPastHostUnservedRows(messages, head.eligibleEndOrdinal, offset);
22978
+ const servedEndOrdinal = retreatPastHostUnservedRows(messages, head.eligibleEndOrdinal, offset);
22979
+ const eligibleEndOrdinal = Math.max(offset, fenceBoundaryForCompletedToolArcs(servedEndOrdinal, arcs, 1));
22883
22980
  const rawRangeFingerprint = computeRawRangeFingerprint(messages, offset, eligibleEndOrdinal);
22884
22981
  return {
22885
22982
  sessionId: ctx.sessionId,
@@ -22907,7 +23004,7 @@ function resolveProtectedTailBoundary(ctx) {
22907
23004
  cacheNamespace: ctx.cacheNamespace,
22908
23005
  createdAt,
22909
23006
  rawRangeFingerprint,
22910
- trueRawEligibleTokens: index.rangeTokens(offset, protectedTailStart),
23007
+ trueRawEligibleTokens: index.rangeTokens(offset, eligibleEndOrdinal),
22911
23008
  oversizeAtomicUnit: head.oversizeAtomicUnit,
22912
23009
  boundaryReason,
22913
23010
  diagnostics: boundaryDiagnostics({
@@ -23138,6 +23235,8 @@ function getRawHistoryEligibility(db, sessionId) {
23138
23235
  function hasRunnableCompartmentWindow(snapshot) {
23139
23236
  if (snapshot.offset >= snapshot.protectedTailStart)
23140
23237
  return false;
23238
+ if (snapshot.eligibleEndOrdinal <= snapshot.offset)
23239
+ return false;
23141
23240
  const forceMaterializationPercentage = escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage;
23142
23241
  if (snapshot.usagePercentage >= forceMaterializationPercentage || snapshot.emergencyTailScale) {
23143
23242
  return snapshot.trueRawEligibleTokens >= deriveMinForceEligibleTokens(snapshot.N) || snapshot.eligibleEndOrdinal > snapshot.offset;
@@ -23208,6 +23307,29 @@ function recordHighPressureNoEligibleHead(db, snapshot) {
23208
23307
  return recordProtectedTailNoEligibleHead(db, snapshot.sessionId);
23209
23308
  }
23210
23309
 
23310
+ // ../plugin/src/hooks/magic-context/historian-drain-gate.ts
23311
+ var loggedWindows = new WeakMap;
23312
+ function isHistorianDrainBudgetSpent(args) {
23313
+ const target = deriveProtectedTailTokenTarget(args);
23314
+ const state = getProtectedTailDrainBudgetSkip({
23315
+ ...args,
23316
+ usable: target.usable,
23317
+ perRunCap: selectPerRunCap({ ...args, N: target.N })
23318
+ });
23319
+ if (!state)
23320
+ return false;
23321
+ let windows = loggedWindows.get(args.db);
23322
+ if (!windows) {
23323
+ windows = new Map;
23324
+ loggedWindows.set(args.db, windows);
23325
+ }
23326
+ if (windows.get(args.sessionId) !== state.resetsAt) {
23327
+ windows.set(args.sessionId, state.resetsAt);
23328
+ sessionLog(args.sessionId, `historian skip: internal drain budget spent (${state.spentTokens}/${state.limitTokens} tokens); next eligible at ${new Date(state.nextEligibleAt).toISOString()}`);
23329
+ }
23330
+ return true;
23331
+ }
23332
+
23211
23333
  // ../plugin/src/hooks/magic-context/active-anthropic-turn.ts
23212
23334
  function isInActiveAnthropicTurn(messages, index, anthropic) {
23213
23335
  if (!anthropic)
@@ -23490,7 +23612,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
23490
23612
  taggerFloor,
23491
23613
  storedTotalsExcludeToolTags
23492
23614
  });
23493
- const hasProtectedEligibleHead = boundary.offset < boundary.protectedTailStart;
23615
+ const hasProtectedEligibleHead = boundary.offset < Math.min(boundary.protectedTailStart, boundary.eligibleEndOrdinal);
23494
23616
  if (!hasProtectedEligibleHead) {
23495
23617
  return {
23496
23618
  ...TAIL_INFO_DEFAULTS,
@@ -23502,7 +23624,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
23502
23624
  const seed = sessionDecisionCalibration(db, sessionId);
23503
23625
  const sourceRatio = Math.max(seed.proseRatio, seed.toolsRatio);
23504
23626
  const scanBudget = Math.floor(Math.max(MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE, triggerBudget * TAIL_SIZE_TRIGGER_MULTIPLIER) / sourceRatio);
23505
- const chunk = readSessionChunk2(sessionId, scanBudget, rawEligibility.offset, boundary.protectedTailStart);
23627
+ const chunk = readSessionChunk2(sessionId, scanBudget, rawEligibility.offset, boundary.eligibleEndOrdinal);
23506
23628
  const isMeaningful = chunk.hasMore || boundary.trueRawEligibleTokens >= MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE || Math.ceil(chunk.tokenEstimate * sourceRatio) >= MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE || chunk.messageCount >= MIN_PROACTIVE_TAIL_MESSAGE_COUNT;
23507
23629
  return {
23508
23630
  nextStartOrdinal: rawEligibility.offset,
@@ -23529,6 +23651,14 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
23529
23651
  sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
23530
23652
  return { shouldFire: false };
23531
23653
  }
23654
+ if (isHistorianDrainBudgetSpent({
23655
+ db,
23656
+ sessionId,
23657
+ usagePercentage: usage.percentage,
23658
+ contextLimit: resolveBoundaryContextLimit(usage, contextLimit),
23659
+ executeThresholdPercentage
23660
+ }))
23661
+ return { shouldFire: false };
23532
23662
  const lazyInMemoryTail = typeof inMemoryTail === "function" ? inMemoryTail : undefined;
23533
23663
  let resolvedInMemoryTail = typeof inMemoryTail === "function" ? undefined : inMemoryTail;
23534
23664
  if (resolvedInMemoryTail) {
@@ -23808,13 +23938,13 @@ function hasMuralCueRejectionCountColumn(db) {
23808
23938
  }
23809
23939
 
23810
23940
  // ../plugin/src/features/magic-context/memory/normalize-hash.ts
23811
- import { createHash as createHash9 } from "node:crypto";
23941
+ import { createHash as createHash10 } from "node:crypto";
23812
23942
  function normalizeMemoryContent(content) {
23813
23943
  return content.toLowerCase().replace(/\s+/g, " ").trim();
23814
23944
  }
23815
23945
  function computeNormalizedHash(content) {
23816
23946
  const normalized = normalizeMemoryContent(content);
23817
- return createHash9("md5").update(normalized).digest("hex");
23947
+ return createHash10("md5").update(normalized).digest("hex");
23818
23948
  }
23819
23949
 
23820
23950
  // ../plugin/src/features/magic-context/memory/visibility.ts
@@ -24400,14 +24530,14 @@ function archiveMemory(db, id, reason) {
24400
24530
  }
24401
24531
 
24402
24532
  // ../plugin/src/features/magic-context/compaction-marker.ts
24403
- import { createHash as createHash10 } from "node:crypto";
24533
+ import { createHash as createHash11 } from "node:crypto";
24404
24534
  import { existsSync as existsSync9 } from "node:fs";
24405
24535
  var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
24406
24536
  var ID_PREFIX_HEX_LENGTH = 12;
24407
24537
  var ID_SUFFIX_LENGTH = 14;
24408
24538
  var ID_PREFIX_MASK = (1n << BigInt(ID_PREFIX_HEX_LENGTH * 4)) - 1n;
24409
24539
  function deterministicBase62(seed, length) {
24410
- let value = BigInt(`0x${createHash10("sha256").update(seed).digest("hex")}`);
24540
+ let value = BigInt(`0x${createHash11("sha256").update(seed).digest("hex")}`);
24411
24541
  const chars = Array(length);
24412
24542
  for (let index = length - 1;index >= 0; index -= 1) {
24413
24543
  chars[index] = BASE62_CHARS[Number(value % 62n)];
@@ -25693,9 +25823,9 @@ function advanceToolReclaimWatermarkToCurrentMax(db, sessionId) {
25693
25823
  }
25694
25824
 
25695
25825
  // ../plugin/src/shared/tag-transcript.ts
25696
- import { createHash as createHash11 } from "node:crypto";
25826
+ import { createHash as createHash12 } from "node:crypto";
25697
25827
  function textIdentityDigest(value) {
25698
- return createHash11("sha256").update(value).digest("hex");
25828
+ return createHash12("sha256").update(value).digest("hex");
25699
25829
  }
25700
25830
  function buildContentDerivedTextIds(messageId, parts) {
25701
25831
  const sources = parts.filter((part) => part.kind === "text").map((part) => stripTagPrefix(part.getText() ?? ""));
@@ -26636,6 +26766,22 @@ function searchMemoriesFTSUnion(db, projectPaths, query, limit = DEFAULT_SEARCH_
26636
26766
  function clearMemoryVerifications(db, memoryId) {
26637
26767
  db.prepare("DELETE FROM memory_verifications WHERE memory_id = ?").run(memoryId);
26638
26768
  }
26769
+ // ../plugin/src/features/magic-context/memory/types.ts
26770
+ var MEMORY_CATEGORY_RECORD = {
26771
+ PROJECT_RULES: true,
26772
+ ARCHITECTURE: true,
26773
+ CONFIG_VALUES: true,
26774
+ ARCHITECTURE_DECISIONS: true,
26775
+ CONSTRAINTS: true,
26776
+ CONFIG_DEFAULTS: true,
26777
+ NAMING: true,
26778
+ USER_PREFERENCES: true,
26779
+ USER_DIRECTIVES: true,
26780
+ ENVIRONMENT: true,
26781
+ WORKFLOW_RULES: true,
26782
+ KNOWN_ISSUES: true
26783
+ };
26784
+ var MEMORY_CATEGORIES = Object.keys(MEMORY_CATEGORY_RECORD);
26639
26785
  // ../plugin/src/features/magic-context/memory/verification-paths.ts
26640
26786
  import { execFile as execFile2 } from "node:child_process";
26641
26787
  import { promisify } from "node:util";
@@ -28031,8 +28177,10 @@ function findLatestMeaningfulUserMessage(messages, entryIds, entryIdByRef) {
28031
28177
  const msg = messages[i];
28032
28178
  if (msg?.role !== "user")
28033
28179
  continue;
28034
- if (collectUserPromptParts(msg).trim().length === 0)
28180
+ const promptText = extractUserPromptText(msg);
28181
+ if (promptText.length === 0 || !hasMeaningfulUserText2([{ type: "text", text: promptText }])) {
28035
28182
  continue;
28183
+ }
28036
28184
  if (entryIdByRef) {
28037
28185
  const byRef = msg && typeof msg === "object" ? entryIdByRef.get(msg) : undefined;
28038
28186
  if (typeof byRef === "string") {
@@ -28072,6 +28220,8 @@ function appendHintToUserMessage(message, hint) {
28072
28220
  }
28073
28221
  async function runAutoSearchHintForPi(args) {
28074
28222
  const startedAt = performance.now();
28223
+ args.passGuard?.assert();
28224
+ const wait = args.passGuard?.wait ?? ((pending) => pending);
28075
28225
  const { sessionId, db, messages, options, entryIdByRef } = args;
28076
28226
  const entryIds = args.entryIds === undefined ? messages.map((message, index) => {
28077
28227
  const timestamp = message.timestamp;
@@ -28094,7 +28244,8 @@ async function runAutoSearchHintForPi(args) {
28094
28244
  appendHintToUserMessage(userMsg, decision.text);
28095
28245
  }
28096
28246
  };
28097
- return await coalesceAutoSearchTurn(db, sessionId, userMsgId, async (lifecycleSignal) => {
28247
+ return await wait(coalesceAutoSearchTurn(db, sessionId, userMsgId, async (lifecycleSignal) => {
28248
+ args.passGuard?.assert();
28098
28249
  if (lifecycleSignal.aborted)
28099
28250
  return messages;
28100
28251
  if (wasAutoSearchSkipped(db, sessionId, userMsgId))
@@ -28195,7 +28346,7 @@ ${hintText}`;
28195
28346
  }
28196
28347
  sessionLog(sessionId, `auto-search: attached hint to ${userMsgId} (${results.length} fragments, top score ${results[0].score.toFixed(3)})`);
28197
28348
  return messages;
28198
- }, replayServedDecision);
28349
+ }, replayServedDecision));
28199
28350
  }
28200
28351
  function clearAutoSearchForPiSession(sessionId) {
28201
28352
  clearAutoSearchTimeoutForSession(sessionId);
@@ -32053,7 +32204,10 @@ function isTransientHistorianPromptError(message) {
32053
32204
 
32054
32205
  // src/pi-harness-kind.ts
32055
32206
  import { existsSync as existsSync10, readFileSync as readFileSync12, realpathSync as realpathSync2 } from "node:fs";
32056
- import { dirname as dirname5, join as join8, parse as parse7, resolve as resolve5 } from "node:path";
32207
+ import { dirname as dirname5, join as join8, parse as parse7, resolve as resolve6 } from "node:path";
32208
+ import { pathToFileURL } from "node:url";
32209
+ var OMP_UTILS_MODULE = "@oh-my-pi/pi-utils";
32210
+ var OMP_HOST_PACKAGE = "@oh-my-pi/pi-coding-agent";
32057
32211
  var PI_HOST_PACKAGES = new Set([
32058
32212
  "@earendil-works/pi-coding-agent",
32059
32213
  "@mariozechner/pi-coding-agent"
@@ -32066,7 +32220,7 @@ function hostEntries() {
32066
32220
  for (const candidate of [process.argv[1], process.execPath]) {
32067
32221
  if (!candidate)
32068
32222
  continue;
32069
- const requestedPath = resolve5(candidate);
32223
+ const requestedPath = resolve6(candidate);
32070
32224
  let resolvedPath;
32071
32225
  try {
32072
32226
  resolvedPath = realpathSync2(requestedPath);
@@ -32104,12 +32258,64 @@ function nearestPackageName(entryPath) {
32104
32258
  function packageNameDetection(entries) {
32105
32259
  for (const entry of entries) {
32106
32260
  const packageName = nearestPackageName(entry.resolvedPath);
32261
+ if (packageName === OMP_HOST_PACKAGE) {
32262
+ return { kind: "omp", via: "package-name" };
32263
+ }
32107
32264
  if (packageName !== undefined && PI_HOST_PACKAGES.has(packageName)) {
32108
32265
  return { kind: "pi", via: "package-name" };
32109
32266
  }
32110
32267
  }
32111
32268
  return;
32112
32269
  }
32270
+ function dependencyPackageRoot(entryPath, moduleName) {
32271
+ const moduleParts = moduleName.split("/");
32272
+ let directory = dirname5(entryPath);
32273
+ const root = parse7(directory).root;
32274
+ while (true) {
32275
+ const packageRoot = join8(directory, "node_modules", ...moduleParts);
32276
+ if (existsSync10(join8(packageRoot, "package.json")))
32277
+ return packageRoot;
32278
+ if (directory === root)
32279
+ return;
32280
+ directory = dirname5(directory);
32281
+ }
32282
+ }
32283
+ function importTarget(exportsValue) {
32284
+ if (typeof exportsValue === "string")
32285
+ return exportsValue;
32286
+ if (!exportsValue || typeof exportsValue !== "object")
32287
+ return;
32288
+ const conditions = exportsValue;
32289
+ if (typeof conditions.import === "string")
32290
+ return conditions.import;
32291
+ if (typeof conditions.default === "string")
32292
+ return conditions.default;
32293
+ return importTarget(conditions["."]);
32294
+ }
32295
+ function hostModuleImportUrl(entryPath) {
32296
+ const packageRoot = dependencyPackageRoot(entryPath, OMP_UTILS_MODULE);
32297
+ if (!packageRoot)
32298
+ return;
32299
+ const packageJson = readPackageJson(join8(packageRoot, "package.json"));
32300
+ const target = importTarget(packageJson?.exports) ?? (typeof packageJson?.module === "string" ? packageJson.module : typeof packageJson?.main === "string" ? packageJson.main : undefined);
32301
+ if (!target?.startsWith("./"))
32302
+ return;
32303
+ return pathToFileURL(resolve6(packageRoot, target)).href;
32304
+ }
32305
+ async function appNameDetection(entries) {
32306
+ for (const entry of entries) {
32307
+ const moduleUrl = hostModuleImportUrl(entry.resolvedPath);
32308
+ if (!moduleUrl)
32309
+ continue;
32310
+ try {
32311
+ const hostUtils = await import(moduleUrl);
32312
+ if (hostUtils.APP_NAME === "omp") {
32313
+ return { kind: "omp", via: "app-name" };
32314
+ }
32315
+ } catch {}
32316
+ }
32317
+ return;
32318
+ }
32113
32319
  function executableDetection(entries) {
32114
32320
  for (const entry of entries) {
32115
32321
  const kind = piHarnessKindFromExecutable(entry.requestedPath);
@@ -32124,7 +32330,7 @@ async function detectPiHarnessKind() {
32124
32330
  return { kind: processTitleKind, via: "process-title" };
32125
32331
  }
32126
32332
  const entries = hostEntries();
32127
- return packageNameDetection(entries) ?? executableDetection(entries) ?? { kind: "pi", via: "default" };
32333
+ return packageNameDetection(entries) ?? await appNameDetection(entries) ?? executableDetection(entries) ?? { kind: "pi", via: "default" };
32128
32334
  }
32129
32335
  async function resolvePiHarnessDetection() {
32130
32336
  const processGlobal = globalThis;
@@ -33551,6 +33757,8 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
33551
33757
  continue;
33552
33758
  const strippedSource = stripTagPrefix(stripped);
33553
33759
  if (strippedSource.trim().length === 0) {
33760
+ if (target.thinkingDropProtected)
33761
+ continue;
33554
33762
  const dropResult = target.drop?.() ?? "absent";
33555
33763
  const didReplace = dropResult === "absent" ? target.setContent(`[dropped §${tag.tagNumber}§]`) : false;
33556
33764
  if (dropResult === "removed" || dropResult === "absent") {
@@ -34431,7 +34639,7 @@ function currentReclaimHints(db, sessionId, hints) {
34431
34639
 
34432
34640
  // src/debug-assertions-pi.ts
34433
34641
  function runPiDebugAssertion(assert) {
34434
- if (process.env.MAGIC_CONTEXT_DEBUG_ASSERTIONS === "1")
34642
+ if (process.env.MMC_DEBUG_ASSERTIONS === "1")
34435
34643
  assert?.();
34436
34644
  }
34437
34645
 
@@ -34580,9 +34788,6 @@ function probe(db, sessionId, kind) {
34580
34788
  function hasPiFallbackMessageTags2(db, sessionId) {
34581
34789
  return probe(db, sessionId, "message");
34582
34790
  }
34583
- function hasPiFallbackToolOwnerTags2(db, sessionId) {
34584
- return probe(db, sessionId, "tool");
34585
- }
34586
34791
 
34587
34792
  // src/historian-tail-pi.ts
34588
34793
  function readPiHistorianTail(db, sessionId, provider) {
@@ -34938,7 +35143,7 @@ function readCurrentMarkersFromCompartments(db, state, compartments) {
34938
35143
  };
34939
35144
  }
34940
35145
  function mustMaterializePi(state, db, currentCompartmentsOverride, passSnapshot) {
34941
- const meta = passSnapshot?.sessionMeta ?? getOrCreateSessionMeta(db, state.sessionId);
35146
+ const meta = passSnapshot?.sessionMeta ?? readSessionMeta(db, state.sessionId);
34942
35147
  if (!meta.cachedM0Bytes)
34943
35148
  return { value: true, reason: "first_render" };
34944
35149
  if (!meta.cachedM1Bytes)
@@ -35090,7 +35295,7 @@ function readFrozenM0InputsPi(state, db, memoryCutoff, compartmentsOverride) {
35090
35295
  return read.deferred();
35091
35296
  }
35092
35297
  function renderFreshM0PiNonPersisted(state, db) {
35093
- const cachedMaterializedAt = getOrCreateSessionMeta(db, state.sessionId).cachedM0MaterializedAt ?? 0;
35298
+ const cachedMaterializedAt = readSessionMeta(db, state.sessionId).cachedM0MaterializedAt ?? 0;
35094
35299
  const frozen = readFrozenM0InputsPi(state, db, cachedMaterializedAt);
35095
35300
  frozen.markers.materializedAt = cachedMaterializedAt;
35096
35301
  const historyBudget = historyLocalBudget(state.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS, piModelRefToCanonical(state.hardSignals?.modelKey ?? ""));
@@ -35359,7 +35564,7 @@ function readCachedPiM0M1Row(db, sessionId) {
35359
35564
  function createPiM0M1PassSnapshot(args) {
35360
35565
  const compartments = args.compactionOff ? [] : args.compartments ? [...args.compartments] : getCompartments(args.db, args.sessionId);
35361
35566
  return {
35362
- sessionMeta: args.sessionMeta ?? getOrCreateSessionMeta(args.db, args.sessionId),
35567
+ sessionMeta: args.sessionMeta ?? readSessionMeta(args.db, args.sessionId),
35363
35568
  compartments,
35364
35569
  cachedRow: readCachedPiM0M1Row(args.db, args.sessionId),
35365
35570
  compartmentSequence: compartments.at(-1)?.sequence ?? EMPTY_MAX_COMPARTMENT_SEQ
@@ -36060,6 +36265,83 @@ function authorizePiToolRemoval(args) {
36060
36265
  }
36061
36266
  }
36062
36267
 
36268
+ // src/pi-context-budget.ts
36269
+ var PI_CONTEXT_BUDGET = {
36270
+ hostDeadlineMs: 30000,
36271
+ hostMarginMs: 5000,
36272
+ outcomeMs: 25000,
36273
+ fallbackObservedMs: 4,
36274
+ workMs: 21000,
36275
+ writerMs: 16500,
36276
+ completionReserveMs: 2000,
36277
+ searchMs: 3000
36278
+ };
36279
+
36280
+ class PiContextDeadlineError extends Error {
36281
+ }
36282
+
36283
+ class PiContextBudget {
36284
+ startedAt;
36285
+ now;
36286
+ sideTurn = false;
36287
+ stage = "entry";
36288
+ recovery = "not attempted";
36289
+ abandoned = false;
36290
+ completed = false;
36291
+ failureReason;
36292
+ assertOwner = () => {};
36293
+ constructor(startedAt = performance.now(), now = () => performance.now()) {
36294
+ this.startedAt = startedAt;
36295
+ this.now = now;
36296
+ }
36297
+ elapsed() {
36298
+ return this.now() - this.startedAt;
36299
+ }
36300
+ remainingWork() {
36301
+ return Math.max(0, PI_CONTEXT_BUDGET.workMs - this.elapsed());
36302
+ }
36303
+ remainingOutcome = () => Math.max(0, PI_CONTEXT_BUDGET.outcomeMs - this.elapsed());
36304
+ writerAllowance() {
36305
+ return Math.max(0, Math.min(PI_CONTEXT_BUDGET.writerMs, this.remainingWork() - PI_CONTEXT_BUDGET.completionReserveMs));
36306
+ }
36307
+ assertOutcome = () => {
36308
+ this.assertOwner();
36309
+ if (this.abandoned || this.elapsed() >= PI_CONTEXT_BUDGET.outcomeMs)
36310
+ throw new PiContextDeadlineError(this.diagnostic());
36311
+ };
36312
+ assert = () => {
36313
+ this.assertOutcome();
36314
+ if (this.elapsed() >= PI_CONTEXT_BUDGET.workMs)
36315
+ throw new PiContextDeadlineError(this.diagnostic());
36316
+ };
36317
+ assertDecisionPublication = () => {
36318
+ if (!this.completed)
36319
+ this.assertOwner();
36320
+ if (this.abandoned || this.elapsed() >= PI_CONTEXT_BUDGET.outcomeMs)
36321
+ throw new PiContextDeadlineError(this.diagnostic());
36322
+ };
36323
+ diagnostic() {
36324
+ return `stage=${this.stage} elapsed=${Math.round(this.elapsed())}ms recovery=${this.recovery}`;
36325
+ }
36326
+ waitUntil = async (pending, assert, remaining) => {
36327
+ assert();
36328
+ let timer;
36329
+ try {
36330
+ return await Promise.race([
36331
+ pending,
36332
+ new Promise((_, reject) => {
36333
+ timer = setTimeout(() => reject(new PiContextDeadlineError(this.diagnostic())), remaining());
36334
+ })
36335
+ ]);
36336
+ } finally {
36337
+ clearTimeout(timer);
36338
+ assert();
36339
+ }
36340
+ };
36341
+ wait = (pending) => this.waitUntil(pending, this.assert, () => this.remainingWork());
36342
+ waitMandatory = (pending) => this.waitUntil(pending, this.assertOutcome, this.remainingOutcome);
36343
+ }
36344
+
36063
36345
  // src/pi-context-limit.ts
36064
36346
  var MIN_SANE_LIMIT2 = 16000;
36065
36347
  var MAX_SANE_LIMIT2 = 1e7;
@@ -36111,31 +36393,187 @@ function resolvePiUsableContextLimit(args) {
36111
36393
 
36112
36394
  // src/pi-context-refusal.ts
36113
36395
  import { Text as Text2 } from "@earendil-works/pi-tui";
36396
+
36397
+ // src/omp-request-kind.ts
36398
+ var SIDE_REMINDER = `<system-reminder>
36399
+ Ephemeral side-channel turn; reuses current conversation context.
36400
+ Tool catalog attached only to keep prompt cache warm; tools NOT available this turn.
36401
+ Do NOT emit tool calls; reply plain text only. Tool calls discarded without execution.
36402
+ </system-reminder>`;
36403
+ function textContainsReminder(value) {
36404
+ if (typeof value === "string")
36405
+ return value.trim() === SIDE_REMINDER;
36406
+ if (!Array.isArray(value))
36407
+ return false;
36408
+ return value.some((block) => {
36409
+ if (!block || typeof block !== "object")
36410
+ return false;
36411
+ const part = block;
36412
+ return typeof part.text === "string" && part.text.trim() === SIDE_REMINDER;
36413
+ });
36414
+ }
36415
+ function isOmpSideContext(event) {
36416
+ const tail = event.messages.at(-1);
36417
+ if (tail?.role !== "user" || tail.attribution !== "agent")
36418
+ return false;
36419
+ return event.messages.some((message) => {
36420
+ const row = message;
36421
+ return row.role === "developer" && row.attribution === "agent" && textContainsReminder(row.content);
36422
+ });
36423
+ }
36424
+
36425
+ // src/pi-context-refusal.ts
36114
36426
  var ENTRY_TYPE = "magic-context-turn-refused";
36115
36427
  var RETRY_MESSAGE = "Magic Context could not safely prepare this turn; send your message again.";
36116
- function registerPiGuardedContext(pi, handler) {
36428
+
36429
+ class PiContextSupersededError extends Error {
36430
+ }
36431
+ var receiptMaps = new Set;
36432
+ function clearPiContextReceipt(sessionId) {
36433
+ for (const receipts of receiptMaps)
36434
+ receipts.delete(sessionId);
36435
+ }
36436
+ function operationKey(ctx) {
36437
+ return ctx.sessionManager?.getSessionId?.() ?? ctx.sessionManager ?? "no-session";
36438
+ }
36439
+ function registerPiGuardedContext(pi, handler, options = {}) {
36440
+ const operations = new Map;
36441
+ const sideSessions = new Map;
36442
+ receiptMaps.add(operations);
36443
+ const newOperation = () => ({
36444
+ ready: false,
36445
+ refused: false,
36446
+ ended: false
36447
+ });
36448
+ const fenceEnabled = resolvePiHarnessKind() === "omp";
36449
+ const refuse = (ctx, budget, reason, isCurrent) => {
36450
+ if (!isCurrent()) {
36451
+ log(`[magic-context][pi] DISCARDED CONTEXT RESULT ${budget.diagnostic()}`, reason);
36452
+ return;
36453
+ }
36454
+ budget.abandoned = true;
36455
+ budget.recovery = budget.recovery === "not attempted" ? "no managed result; refused" : budget.recovery;
36456
+ const message = `${RETRY_MESSAGE} ${budget.diagnostic()} (${reason instanceof Error ? reason.message : String(reason)})`;
36457
+ try {
36458
+ ctx.ui?.notify(message, "error");
36459
+ } catch (error) {
36460
+ log("[magic-context][pi] refusal notice failed", error);
36461
+ }
36462
+ try {
36463
+ pi.appendEntry(ENTRY_TYPE, { message });
36464
+ } catch (error) {
36465
+ log("[magic-context][pi] refusal entry failed", error);
36466
+ } finally {
36467
+ if (!budget.sideTurn)
36468
+ ctx.abort();
36469
+ }
36470
+ try {
36471
+ options.onRefusal?.(ctx, budget, message, isCurrent);
36472
+ } catch (error) {
36473
+ log("[magic-context][pi] refusal diagnostic failed", error);
36474
+ }
36475
+ };
36476
+ if (fenceEnabled) {
36477
+ pi.on("agent_start", (_event, ctx) => {
36478
+ operations.set(operationKey(ctx), newOperation());
36479
+ });
36480
+ pi.on("agent_end", (_event, ctx) => {
36481
+ const key = operationKey(ctx);
36482
+ const counts = sideSessions.get(key);
36483
+ if (counts)
36484
+ log(`[magic-context][pi] OMP context counts session=${String(key)} side_contexts=${counts.sides} context_passes=${counts.contexts} dispatch_fence=${counts.sides ? "latched off" : "on"}`);
36485
+ const operation = operations.get(key);
36486
+ if (operation) {
36487
+ operation.ended = true;
36488
+ operation.ready = false;
36489
+ }
36490
+ });
36491
+ pi.on("before_provider_request", (_event, ctx) => {
36492
+ if (options.compactionOff?.(ctx))
36493
+ return;
36494
+ const key = operationKey(ctx);
36495
+ if (sideSessions.get(key)?.sides)
36496
+ return;
36497
+ let operation = operations.get(key);
36498
+ if (!operation) {
36499
+ operation = newOperation();
36500
+ operations.set(key, operation);
36501
+ }
36502
+ const active = operation;
36503
+ const isCurrent = () => operations.get(key) === active;
36504
+ const budget = active.pass ?? new PiContextBudget;
36505
+ try {
36506
+ budget.assertOwner();
36507
+ if (!budget.completed)
36508
+ budget.assertOutcome();
36509
+ if (!active.ready || active.refused || active.ended || budget.abandoned)
36510
+ throw new Error("missing managed context receipt");
36511
+ } catch (error) {
36512
+ active.refused = true;
36513
+ budget.stage = "provider dispatch";
36514
+ refuse(ctx, budget, error, isCurrent);
36515
+ }
36516
+ });
36517
+ }
36117
36518
  pi.registerEntryRenderer?.(ENTRY_TYPE, (entry) => new Text2(entry.data?.message ?? RETRY_MESSAGE, 0, 0));
36118
36519
  pi.on("context", async (event, ctx) => {
36520
+ const budget = new PiContextBudget;
36521
+ budget.sideTurn = fenceEnabled && isOmpSideContext(event);
36522
+ const key = operationKey(ctx);
36523
+ if (fenceEnabled) {
36524
+ let counts = sideSessions.get(key);
36525
+ if (!counts) {
36526
+ counts = { contexts: 0, sides: 0 };
36527
+ sideSessions.set(key, counts);
36528
+ }
36529
+ counts.contexts++;
36530
+ if (budget.sideTurn && ++counts.sides === 1)
36531
+ log(`[magic-context][pi] OMP dispatch fence disabled for session ${String(key)}: verified ephemeral context; session-wide abort cannot distinguish provider operations (side_contexts=${counts.sides} context_passes=${counts.contexts})`);
36532
+ }
36533
+ const owner = operations.get(key);
36534
+ let operation = operations.get(key);
36535
+ if (budget.sideTurn || !operation || !fenceEnabled) {
36536
+ operation = newOperation();
36537
+ if (!budget.sideTurn)
36538
+ operations.set(key, operation);
36539
+ }
36540
+ const active = operation;
36541
+ active.pass = budget;
36542
+ active.ready = false;
36543
+ const isOwned = () => budget.sideTurn ? operations.get(key) === owner : operations.get(key) === active && active.pass === budget;
36544
+ const isCurrent = () => isOwned() && (budget.sideTurn || !active.ended);
36545
+ budget.assertOwner = () => {
36546
+ if (!isCurrent())
36547
+ throw new PiContextSupersededError("Pi context pass superseded before writer admission");
36548
+ };
36119
36549
  try {
36120
- return await withSqliteTransformPass(() => handler(event, ctx));
36550
+ const result = await withSqliteTransformPass(() => handler(event, ctx, budget));
36551
+ budget.assertOutcome();
36552
+ if (result?.messages) {
36553
+ budget.completed = true;
36554
+ active.ready = true;
36555
+ }
36556
+ return result;
36121
36557
  } catch (error) {
36558
+ if (error instanceof PiContextSupersededError || !isCurrent()) {
36559
+ log(`[magic-context][pi] DISCARDED CONTEXT RESULT ${budget.diagnostic()}`, error);
36560
+ throw error;
36561
+ }
36122
36562
  log("[magic-context][pi] turn refused", error);
36123
- if (typeof ctx.abort !== "function")
36563
+ if (typeof ctx.abort !== "function") {
36564
+ budget.abandoned = true;
36565
+ options.onRefusal?.(ctx, budget, error instanceof Error ? error.message : String(error), isOwned);
36124
36566
  throw error;
36125
- try {
36126
- pi.appendEntry(ENTRY_TYPE, { message: RETRY_MESSAGE });
36127
- } catch (displayError) {
36128
- log("[magic-context][pi] refusal entry failed", displayError);
36129
- } finally {
36130
- ctx.abort();
36131
36567
  }
36568
+ active.refused = true;
36569
+ refuse(ctx, budget, error, isOwned);
36132
36570
  return { messages: event.messages };
36133
36571
  }
36134
36572
  });
36135
36573
  }
36136
36574
 
36137
36575
  // src/pi-maintenance-runner.ts
36138
- import { closeSync as closeSync2, existsSync as existsSync11, openSync as openSync2, readSync as readSync2, statSync as statSync5 } from "node:fs";
36576
+ import { closeSync as closeSync2, existsSync as existsSync11, openSync as openSync2, readSync as readSync2, statSync as statSync6 } from "node:fs";
36139
36577
  import { join as join9 } from "node:path";
36140
36578
 
36141
36579
  // ../plugin/src/features/magic-context/memory-maintainer/lease.ts
@@ -36966,7 +37404,7 @@ function screenAgentsCitation(item, agentsSourceText) {
36966
37404
  }
36967
37405
 
36968
37406
  // ../plugin/src/features/magic-context/memory-maintainer/provider-output-failure.ts
36969
- import { createHash as createHash12 } from "node:crypto";
37407
+ import { createHash as createHash13 } from "node:crypto";
36970
37408
  var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
36971
37409
 
36972
37410
  class DreamerProviderOutputFailureError extends Error {
@@ -37023,7 +37461,7 @@ function providerOutputFailureFromInvalidManifest2(messages, responseText) {
37023
37461
  const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
37024
37462
  if (!normalized)
37025
37463
  return null;
37026
- const fingerprint = createHash12("sha256").update(normalized).digest("hex").slice(0, 16);
37464
+ const fingerprint = createHash13("sha256").update(normalized).digest("hex").slice(0, 16);
37027
37465
  return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
37028
37466
  }
37029
37467
 
@@ -37439,7 +37877,7 @@ function readProjectAgentsBlock(directory) {
37439
37877
  try {
37440
37878
  if (!existsSync11(path))
37441
37879
  return null;
37442
- const stat = statSync5(path);
37880
+ const stat = statSync6(path);
37443
37881
  if (!stat.isFile())
37444
37882
  return null;
37445
37883
  const cap = AGENTS_BLOCK_MAX_BYTES;
@@ -37713,7 +38151,7 @@ function runPiMaintenanceFactory(deps) {
37713
38151
  }
37714
38152
 
37715
38153
  // ../plugin/src/hooks/magic-context/lkg-persist.ts
37716
- import { createHash as createHash13 } from "node:crypto";
38154
+ import { createHash as createHash14 } from "node:crypto";
37717
38155
  function parseStringArray(value) {
37718
38156
  if (typeof value !== "string")
37719
38157
  return null;
@@ -37827,7 +38265,7 @@ function rememberFingerprint(db, sessionId, fingerprint) {
37827
38265
  saved.set(sessionId, fingerprint);
37828
38266
  }
37829
38267
  function slotFingerprint(slot) {
37830
- return createHash13("sha256").update(JSON.stringify([
38268
+ return createHash14("sha256").update(JSON.stringify([
37831
38269
  slot.jsonPrefix,
37832
38270
  slot.inputIdSeq,
37833
38271
  slot.inputContentDigests,
@@ -38004,6 +38442,11 @@ function readServedTemporalDecisions(db, sessionId, runtime, messageIds) {
38004
38442
  return result;
38005
38443
  }
38006
38444
 
38445
+ // ../plugin/src/hooks/magic-context/lkg-measured-request.ts
38446
+ var requests = new BoundedSessionMap(1000);
38447
+ var claimedRequests = new WeakSet;
38448
+ var captures = new BoundedSessionMap(1000);
38449
+
38007
38450
  // ../plugin/src/hooks/magic-context/openai-compat-adjacency.ts
38008
38451
  function assertOpenAiCompatAdjacency(messages) {
38009
38452
  const violations = [];
@@ -38533,7 +38976,7 @@ function plainOutputFields(messages) {
38533
38976
  }
38534
38977
  return outputs;
38535
38978
  }
38536
- function snapshotInputs(messages, entryIds) {
38979
+ function snapshotInputs(messages, entryIds, omitsBookkeeping) {
38537
38980
  if (!entryIds || entryIds.length !== messages.length) {
38538
38981
  return { inputs: [], failure: "lkg_entry_ids_unavailable" };
38539
38982
  }
@@ -38544,7 +38987,7 @@ function snapshotInputs(messages, entryIds) {
38544
38987
  const inputs = [];
38545
38988
  const seen = new Set;
38546
38989
  for (let index = 0;index < entryIds.length; index += 1) {
38547
- const fields = lkgContentFields(messages[index]);
38990
+ const fields = lkgContentFields(omitsBookkeeping ? piProviderInput(messages[index]) : messages[index]);
38548
38991
  if (!fields)
38549
38992
  return { inputs: [], failure: "lkg_content_snapshot_failed" };
38550
38993
  const id = entryIds[index] || `pi-lkg-unmapped:${lkgContentDigestFromFields(fields)}`;
@@ -38560,6 +39003,35 @@ function snapshotInputs(messages, entryIds) {
38560
39003
  }
38561
39004
  return { inputs, failure: null };
38562
39005
  }
39006
+ var bookkeepingOmittingApis = new Set([
39007
+ "anthropic-messages",
39008
+ "google-generative-ai",
39009
+ "openai-completions",
39010
+ "openai-responses",
39011
+ "openai-codex-responses"
39012
+ ]);
39013
+ function omitsRootBookkeeping(args) {
39014
+ if (args.transport != null)
39015
+ return false;
39016
+ let api = args.apiKey;
39017
+ if (api === undefined) {
39018
+ const apis = new Set(args.messages.flatMap((message) => {
39019
+ const value = message;
39020
+ return value?.role === "assistant" && typeof value.api === "string" ? [value.api] : [];
39021
+ }));
39022
+ if (apis.size === 1)
39023
+ api = [...apis][0];
39024
+ }
39025
+ return typeof api === "string" && bookkeepingOmittingApis.has(api);
39026
+ }
39027
+ function piProviderInput(message) {
39028
+ if (!message || typeof message !== "object" || Array.isArray(message))
39029
+ return message;
39030
+ const descriptors = Object.getOwnPropertyDescriptors(message);
39031
+ delete descriptors.completedAt;
39032
+ delete descriptors.contextSnapshot;
39033
+ return Object.create(Object.getPrototypeOf(message), descriptors);
39034
+ }
38563
39035
  function extendsMeasuredRequest(measuredJson, nextJson) {
38564
39036
  return measuredJson === nextJson || measuredJson.length > 2 && nextJson.startsWith(`${measuredJson.slice(0, -1)},`);
38565
39037
  }
@@ -38580,7 +39052,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38580
39052
  return state;
38581
39053
  };
38582
39054
  const beginPass = (args) => {
38583
- const snapped = snapshotInputs(args.messages, args.entryIds);
39055
+ const snapped = snapshotInputs(args.messages, args.entryIds, omitsRootBookkeeping(args));
38584
39056
  const slot = getSlot(args.sessionId);
38585
39057
  if (snapped.failure || !slot) {
38586
39058
  return {
@@ -38734,6 +39206,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38734
39206
  return result.ok && measuredPrefix ? { ...result, measuredPrefix } : result;
38735
39207
  };
38736
39208
  const captureAppliedPass = (args) => {
39209
+ args.assertCurrentPass?.();
38737
39210
  const { snapshot } = args;
38738
39211
  if (snapshot.preparationFailure || snapshot.inputs.length === 0)
38739
39212
  return;
@@ -38750,12 +39223,14 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38750
39223
  ...plainOutput ? args.outputMessages.slice(prefix).map((message) => JSON.stringify(message) ?? "null") : []
38751
39224
  ];
38752
39225
  jsonPrefix = !plainOutput ? JSON.stringify(args.outputMessages) : priorOutput && prefix === outputs.length && prefix === priorOutput.inputs.length ? priorOutput.json : `[${jsonMessages.join(",")}]`;
39226
+ args.assertCurrentPass?.();
38753
39227
  state.outputSnapshot = plainOutput ? {
38754
39228
  inputs: outputs,
38755
39229
  jsonMessages,
38756
39230
  json: jsonPrefix
38757
39231
  } : null;
38758
39232
  } catch (error) {
39233
+ args.assertCurrentPass?.();
38759
39234
  dropSlot(snapshot.sessionId, "lkg_snapshot_serialize_failed");
38760
39235
  const failedState = stateFor(snapshot.sessionId);
38761
39236
  failedState.syncCaptureRequired = true;
@@ -38779,6 +39254,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38779
39254
  const outputIds = args.outputEntryIds ?? inferredIds;
38780
39255
  const inputIds = new Set(snapshot.inputs.map((input) => input.id));
38781
39256
  const ownership = outputIds.length === args.outputMessages.length && outputIds.every((id) => id === null || typeof id === "string" && inputIds.has(id)) ? [...outputIds] : undefined;
39257
+ args.assertCurrentPass?.();
38782
39258
  state.captureSequence += 1;
38783
39259
  const plan = {
38784
39260
  sessionId: snapshot.sessionId,
@@ -38794,6 +39270,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38794
39270
  state.capturedRequest = args.hostEnvelopeSignature ? { ...plan, envelopeSignature: args.hostEnvelopeSignature } : undefined;
38795
39271
  const livePrior = getSlot(snapshot.sessionId);
38796
39272
  const unchanged = livePrior && livePrior.modelKey === plan.modelKey && livePrior.providerKey === plan.providerKey && livePrior.jsonPrefix === plan.jsonPrefix && livePrior.inputIdSeq.length === plan.inputs.length && exactReusablePrefix(plan.inputs, state.acceptedInputs) === plan.inputs.length && JSON.stringify(livePrior.piOutputEntryIds) === JSON.stringify(ownership);
39273
+ args.assertCurrentPass?.();
38797
39274
  if (unchanged && !state.syncCaptureRequired) {
38798
39275
  const kept = {
38799
39276
  ...livePrior,
@@ -38809,6 +39286,12 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38809
39286
  dropSlot(snapshot.sessionId, "lkg_cache_bust_pending_capture");
38810
39287
  }
38811
39288
  const commit = () => {
39289
+ try {
39290
+ args.assertCurrentPass?.();
39291
+ } catch (error) {
39292
+ sessionLog(plan.sessionId, "DISCARDED CONTEXT RESULT: queued LKG capture", error);
39293
+ return;
39294
+ }
38812
39295
  if (plan.captureSequence !== state.captureSequence)
38813
39296
  return;
38814
39297
  const startedAt = performance.now();
@@ -38837,6 +39320,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38837
39320
  } : undefined);
38838
39321
  reusedPrefix = incremental.reusedPrefix;
38839
39322
  if (!state.syncCaptureRequired && prior && reusedPrefix === plan.inputs.length && prior.inputIdSeq.length === plan.inputs.length && prior.jsonPrefix === plan.jsonPrefix && JSON.stringify(prior.piOutputEntryIds) === JSON.stringify(ownership)) {
39323
+ args.assertCurrentPass?.();
38840
39324
  state.acceptedInputs = plan.inputs;
38841
39325
  return;
38842
39326
  }
@@ -38852,6 +39336,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38852
39336
  capturedAt: plan.capturedAt,
38853
39337
  captureSequence: plan.captureSequence
38854
39338
  };
39339
+ args.assertCurrentPass?.();
38855
39340
  if (!captureSlot(plan.sessionId, slot)) {
38856
39341
  throw new Error("LKG slot rejected the Pi snapshot");
38857
39342
  }
@@ -38860,6 +39345,12 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38860
39345
  const persisted = saveLkgSlotToDb(db, plan.sessionId, slot);
38861
39346
  state.syncCaptureRequired = !persisted;
38862
39347
  } catch (error) {
39348
+ try {
39349
+ args.assertCurrentPass?.();
39350
+ } catch (discarded) {
39351
+ sessionLog(plan.sessionId, "DISCARDED CONTEXT RESULT: LKG publication", discarded);
39352
+ return;
39353
+ }
38863
39354
  if (plan.captureSequence !== state.captureSequence)
38864
39355
  return;
38865
39356
  dropSlot(plan.sessionId, "lkg_async_capture_failed");
@@ -38955,7 +39446,7 @@ function resolvePiLkgOutputEntryIds(messages, syntheticLeadingCount, entryId) {
38955
39446
  }
38956
39447
 
38957
39448
  // src/pi-lkg-fit-envelope.ts
38958
- import { createHash as createHash14 } from "node:crypto";
39449
+ import { createHash as createHash15 } from "node:crypto";
38959
39450
 
38960
39451
  // src/host-system-prompt.ts
38961
39452
  function readHostSystemPrompt(ctx) {
@@ -38973,7 +39464,7 @@ function readHostSystemPrompt(ctx) {
38973
39464
  }
38974
39465
 
38975
39466
  // src/pi-lkg-fit-envelope.ts
38976
- function readPiLkgFitEnvelope(ctx, pi, modelKey, frozen) {
39467
+ function readPiLkgFitEnvelope(ctx, pi, modelKey, frozen, wireSchema) {
38977
39468
  try {
38978
39469
  if (!modelKey || typeof pi.getAllTools !== "function")
38979
39470
  return;
@@ -38985,7 +39476,8 @@ function readPiLkgFitEnvelope(ctx, pi, modelKey, frozen) {
38985
39476
  for (const tool of allTools) {
38986
39477
  if (!tool || typeof tool !== "object")
38987
39478
  return;
38988
- const { name, description, parameters } = tool;
39479
+ const { name, description } = tool;
39480
+ const parameters = wireSchema ? wireSchema(tool) : tool.parameters;
38989
39481
  if (typeof name !== "string" || !name.length || typeof description !== "string" || !parameters || typeof parameters !== "object" || Array.isArray(parameters))
38990
39482
  return;
38991
39483
  tools.push({ name, description, parameters });
@@ -39033,7 +39525,7 @@ function readPiLkgFitEnvelope(ctx, pi, modelKey, frozen) {
39033
39525
  refusalToolDefinitionTokens,
39034
39526
  toolDefinitionsMeasured: refusalToolDefinitionTokens !== undefined,
39035
39527
  envelopeBytes: Buffer.byteLength(envelopeJson),
39036
- envelopeSignature: activeNames ? createHash14("sha256").update(envelopeJson).update(JSON.stringify(activeNames)).digest("hex") : undefined,
39528
+ envelopeSignature: activeNames ? createHash15("sha256").update(envelopeJson).update(JSON.stringify(activeNames)).digest("hex") : undefined,
39037
39529
  calibration
39038
39530
  };
39039
39531
  } catch {
@@ -39928,6 +40420,29 @@ function injectSyntheticTodowriteForPi(args) {
39928
40420
  return args.messages;
39929
40421
  }
39930
40422
 
40423
+ // src/pi-tool-wire-schema.ts
40424
+ import { isAbsolute as isAbsolute3 } from "node:path";
40425
+ import { pathToFileURL as pathToFileURL2 } from "node:url";
40426
+ var resolver;
40427
+ function loadPiToolWireSchema() {
40428
+ if (resolver)
40429
+ return resolver;
40430
+ resolver = (async () => {
40431
+ const specifier = "@oh-my-pi/pi-ai/utils/schema/wire";
40432
+ for (const base of [process.argv[1], import.meta.url]) {
40433
+ if (!base || !base.startsWith("file:") && !isAbsolute3(base))
40434
+ continue;
40435
+ try {
40436
+ const path = import.meta.resolve(specifier, base.startsWith("file:") ? base : pathToFileURL2(base).href);
40437
+ const host = await import(path);
40438
+ if (typeof host.toolWireSchema === "function")
40439
+ return host.toolWireSchema;
40440
+ } catch {}
40441
+ }
40442
+ })();
40443
+ return resolver;
40444
+ }
40445
+
39931
40446
  // src/provider-error-recovery-pi.ts
39932
40447
  function reportBindingRecovery(sessionId, report, message) {
39933
40448
  if (report)
@@ -40587,14 +41102,26 @@ function replayPiReminderStrips(args) {
40587
41102
  }
40588
41103
 
40589
41104
  // src/served-array-ledger.ts
40590
- import { createHash as createHash15 } from "node:crypto";
41105
+ import { createHash as createHash16 } from "node:crypto";
41106
+ import { readFileSync as readFileSync13 } from "node:fs";
40591
41107
  import * as path5 from "node:path";
40592
41108
  var PI_SERVED_ARRAY_TAIL_MESSAGES = 40;
40593
41109
  var PI_SERVED_ARRAY_BODY_CAPTURE_ENV = "MMC_PI_SERVED_BODY_CAPTURE";
40594
41110
  var LEDGER_DIRECTORY = "pi-served-array-digests";
40595
41111
  var BODY_DIRECTORY = "pi-served-array-bodies";
41112
+ var IDENTITY_DIRECTORY = "pi-served-tag-numbers";
40596
41113
  var FLUSH_DELAY_MS = 25;
41114
+
41115
+ class PiServedIdentityError extends Error {
41116
+ constructor(cause) {
41117
+ super("Pi served-number identity could not be persisted or restored", {
41118
+ cause
41119
+ });
41120
+ this.name = "PiServedIdentityError";
41121
+ }
41122
+ }
40597
41123
  var previousBySession = new Map;
41124
+ var servedTagNumbersBySession = new Map;
40598
41125
  var sequenceBySession = new Map;
40599
41126
  var pendingLinesByPath = new Map;
40600
41127
  var flushTimer = null;
@@ -40602,10 +41129,39 @@ var swallowedWriteCount = 0;
40602
41129
  var lastWriteError = null;
40603
41130
  function clearPiServedArraySession(sessionId) {
40604
41131
  previousBySession.delete(sessionId);
41132
+ servedTagNumbersBySession.delete(sessionId);
40605
41133
  sequenceBySession.delete(sessionId);
40606
41134
  }
41135
+ function getPiServedTagNumbers(sessionId, storageDir = getMagicContextStorageDir()) {
41136
+ const filePath = getPiServedTagNumbersPath(sessionId, storageDir);
41137
+ const cached = servedTagNumbersBySession.get(sessionId);
41138
+ if (cached?.path === filePath)
41139
+ return cached.numbers;
41140
+ let text;
41141
+ try {
41142
+ text = readFileSync13(filePath, "utf8");
41143
+ } catch (error) {
41144
+ if (error.code !== "ENOENT")
41145
+ throw error;
41146
+ text = "";
41147
+ }
41148
+ const numbers = new Set;
41149
+ for (const line of text.split(`
41150
+ `)) {
41151
+ if (!line.trim())
41152
+ continue;
41153
+ const row = JSON.parse(line);
41154
+ if (row.version !== 1 || row.session_id !== sessionId || !Array.isArray(row.tag_numbers) || !row.tag_numbers.every((number) => Number.isSafeInteger(number) && number > 0)) {
41155
+ throw new Error("Invalid durable Pi served-number record; refusing identity adoption");
41156
+ }
41157
+ for (const number of row.tag_numbers)
41158
+ numbers.add(number);
41159
+ }
41160
+ servedTagNumbersBySession.set(sessionId, { path: filePath, numbers });
41161
+ return numbers;
41162
+ }
40607
41163
  function sha256(value) {
40608
- return createHash15("sha256").update(value).digest("hex");
41164
+ return createHash16("sha256").update(value).digest("hex");
40609
41165
  }
40610
41166
  function safeSessionFileStem(sessionId) {
40611
41167
  const readable = sessionId.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 96);
@@ -40617,6 +41173,9 @@ function getPiServedArrayLedgerPath(sessionId, storageDir = getMagicContextStora
40617
41173
  function getPiServedArrayBodyPath(sessionId, storageDir = getMagicContextStorageDir()) {
40618
41174
  return path5.join(storageDir, BODY_DIRECTORY, `${safeSessionFileStem(sessionId)}.jsonl`);
40619
41175
  }
41176
+ function getPiServedTagNumbersPath(sessionId, storageDir = getMagicContextStorageDir()) {
41177
+ return path5.join(storageDir, IDENTITY_DIRECTORY, `${safeSessionFileStem(sessionId)}.jsonl`);
41178
+ }
40620
41179
  function fullBodyCaptureEnabled() {
40621
41180
  const value = process.env[PI_SERVED_ARRAY_BODY_CAPTURE_ENV]?.trim().toLowerCase();
40622
41181
  return value === "1" || value === "true" || value === "yes" || value === "on";
@@ -40682,8 +41241,19 @@ function flushPiServedArrayLedger() {
40682
41241
  return;
40683
41242
  const pending = [...pendingLinesByPath.entries()];
40684
41243
  pendingLinesByPath.clear();
40685
- for (const [filePath, lines] of pending)
40686
- appendPendingLines(filePath, lines);
41244
+ for (const [filePath, lines] of pending) {
41245
+ const admitted = lines.filter((item) => {
41246
+ try {
41247
+ item.assertCurrentPass?.();
41248
+ return true;
41249
+ } catch (error) {
41250
+ log("[magic-context][pi] DISCARDED CONTEXT RESULT: queued served capture", error);
41251
+ return false;
41252
+ }
41253
+ }).map((item) => item.line);
41254
+ if (admitted.length)
41255
+ appendPendingLines(filePath, admitted);
41256
+ }
40687
41257
  }
40688
41258
  function scheduleFlush() {
40689
41259
  if (flushTimer)
@@ -40691,19 +41261,30 @@ function scheduleFlush() {
40691
41261
  flushTimer = setTimeout(flushPiServedArrayLedger, FLUSH_DELAY_MS);
40692
41262
  flushTimer.unref?.();
40693
41263
  }
40694
- function enqueue(filePath, line) {
41264
+ function enqueue(filePath, line, assertCurrentPass) {
40695
41265
  const pending = pendingLinesByPath.get(filePath);
40696
41266
  if (pending)
40697
- pending.push(line);
41267
+ pending.push({ line, assertCurrentPass });
40698
41268
  else
40699
- pendingLinesByPath.set(filePath, [line]);
41269
+ pendingLinesByPath.set(filePath, [{ line, assertCurrentPass }]);
40700
41270
  scheduleFlush();
40701
41271
  }
40702
41272
  function capturePiServedArray(sessionId, messages, options = {}) {
41273
+ options.assertCurrentPass?.();
41274
+ let identityPersistenceFailed = false;
40703
41275
  try {
40704
41276
  const serializedMessages = options.serializedOutput?.jsonMessages ?? messages.map(serializeMessage);
40705
41277
  const serializedArray = options.serializedOutput?.json ?? `[${serializedMessages.join(",")}]`;
40706
41278
  const digest = sha256(serializedArray);
41279
+ const storageDir = options.storageDir ?? getMagicContextStorageDir();
41280
+ identityPersistenceFailed = true;
41281
+ const previousNumbers = getPiServedTagNumbers(sessionId, storageDir);
41282
+ identityPersistenceFailed = false;
41283
+ const served = new Set(previousNumbers);
41284
+ for (const number of options.servedTagNumbers ?? []) {
41285
+ if (Number.isSafeInteger(number) && number > 0)
41286
+ served.add(number);
41287
+ }
40707
41288
  const previous = previousBySession.get(sessionId);
40708
41289
  const divergence = previous ? firstDivergence(previous.serializedMessages, serializedMessages) : null;
40709
41290
  const sequence = (sequenceBySession.get(sessionId) ?? 0) + 1;
@@ -40720,9 +41301,27 @@ function capturePiServedArray(sessionId, messages, options = {}) {
40720
41301
  block_vector_start: tailStart,
40721
41302
  block_vectors: messages.slice(tailStart).map(blockVector)
40722
41303
  };
40723
- const storageDir = options.storageDir ?? getMagicContextStorageDir();
41304
+ options.assertCurrentPass?.();
41305
+ const newNumbers = [...served].filter((number) => !previousNumbers.has(number));
41306
+ const identityPath = getPiServedTagNumbersPath(sessionId, storageDir);
41307
+ if (newNumbers.length) {
41308
+ identityPersistenceFailed = true;
41309
+ ensureStorageDirectorySync(path5.dirname(identityPath));
41310
+ options.assertCurrentPass?.();
41311
+ writeStorageFileSync(identityPath, `${JSON.stringify({ version: 1, session_id: sessionId, tag_numbers: newNumbers })}
41312
+ `, {
41313
+ encoding: "utf8",
41314
+ flag: "a"
41315
+ });
41316
+ identityPersistenceFailed = false;
41317
+ }
41318
+ options.assertCurrentPass?.();
41319
+ servedTagNumbersBySession.set(sessionId, {
41320
+ path: identityPath,
41321
+ numbers: served
41322
+ });
40724
41323
  enqueue(getPiServedArrayLedgerPath(sessionId, storageDir), `${JSON.stringify(record)}
40725
- `);
41324
+ `, options.assertCurrentPass);
40726
41325
  if (options.fullBodyCapture ?? fullBodyCaptureEnabled()) {
40727
41326
  const bodyHeader = JSON.stringify({
40728
41327
  version: 1,
@@ -40732,12 +41331,15 @@ function capturePiServedArray(sessionId, messages, options = {}) {
40732
41331
  sha256: digest
40733
41332
  });
40734
41333
  enqueue(getPiServedArrayBodyPath(sessionId, storageDir), `${bodyHeader.slice(0, -1)},"messages":${serializedArray}}
40735
- `);
41334
+ `, options.assertCurrentPass);
40736
41335
  }
40737
41336
  previousBySession.set(sessionId, { digest, serializedMessages });
40738
41337
  sequenceBySession.set(sessionId, sequence);
40739
41338
  return record;
40740
41339
  } catch (error) {
41340
+ options.assertCurrentPass?.();
41341
+ if (identityPersistenceFailed)
41342
+ throw new PiServedIdentityError(error);
40741
41343
  recordWriteFailure(error);
40742
41344
  return;
40743
41345
  }
@@ -40932,7 +41534,7 @@ function stripPiProcessedImages(args) {
40932
41534
  }
40933
41535
 
40934
41536
  // src/system-prompt.ts
40935
- import { createHash as createHash16 } from "node:crypto";
41537
+ import { createHash as createHash17 } from "node:crypto";
40936
41538
 
40937
41539
  // ../plugin/src/agents/magic-context-prompt.ts
40938
41540
  var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
@@ -41106,7 +41708,7 @@ function processSystemPromptForCache(args) {
41106
41708
  const liveDate = dateMatch ? dateMatch[0] : null;
41107
41709
  const stickyDate = stickyDateBySession.get(sessionId);
41108
41710
  const stableCandidate = liveDate && stickyDate && liveDate !== stickyDate ? systemPrompt.replace(DATE_PATTERN, stickyDate) : systemPrompt;
41109
- const stableCandidateHash = createHash16("md5").update(promptSurfaceHashMaterial(stableCandidate, args.promptSurfacePreset)).digest("hex");
41711
+ const stableCandidateHash = createHash17("md5").update(promptSurfaceHashMaterial(stableCandidate, args.promptSurfacePreset)).digest("hex");
41110
41712
  const contentOrPresetChanged = !isFirstHash && stableCandidateHash !== previousHash;
41111
41713
  const idleCacheExpired = sessionMeta !== undefined && computeHardCacheExpired(sessionMeta.cacheTtl, sessionMeta.lastResponseTime, Date.now());
41112
41714
  const dateMayAdvance = isCacheBusting || idleCacheExpired || contentOrPresetChanged;
@@ -41121,7 +41723,7 @@ function processSystemPromptForCache(args) {
41121
41723
  sessionLog(sessionId, `system prompt date frozen: real=${liveDate}, using=${stickyDate} (cache-stable pass)`);
41122
41724
  }
41123
41725
  }
41124
- const currentHash = createHash16("md5").update(promptSurfaceHashMaterial(frozenPrompt, args.promptSurfacePreset)).digest("hex");
41726
+ const currentHash = createHash17("md5").update(promptSurfaceHashMaterial(frozenPrompt, args.promptSurfacePreset)).digest("hex");
41125
41727
  const hashChanged = !isFirstHash && currentHash !== previousHash;
41126
41728
  if (hashChanged) {
41127
41729
  sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${frozenPrompt.length})`);
@@ -41149,19 +41751,6 @@ function clearPiSystemPromptSession(sessionId) {
41149
41751
  stickyDateBySession.delete(sessionId);
41150
41752
  }
41151
41753
 
41152
- // src/timeout.ts
41153
- function withTimeout(p, ms) {
41154
- let handle;
41155
- const timeout = new Promise((resolve) => {
41156
- handle = setTimeout(() => resolve(undefined), ms);
41157
- handle.unref?.();
41158
- });
41159
- return Promise.race([p, timeout]).finally(() => {
41160
- if (handle)
41161
- clearTimeout(handle);
41162
- });
41163
- }
41164
-
41165
41754
  // src/transcript-pi.ts
41166
41755
  function createPiTranscript(source, sessionId, entryIds, options = {}) {
41167
41756
  const working = source.slice();
@@ -41730,6 +42319,7 @@ var pendingDecisionLogObserverForTests;
41730
42319
  var mutationGateObserverForTests;
41731
42320
  var lkgRecoveryLogObserverForTests;
41732
42321
  var variantChangeLogObserverForTests;
42322
+ var beforePipelineForTests;
41733
42323
  function logPiLkgRecovery(sessionId, message) {
41734
42324
  lkgRecoveryLogObserverForTests?.(message);
41735
42325
  sessionLog(sessionId, message);
@@ -41745,11 +42335,22 @@ var deferredMaterializationSessions = new Set;
41745
42335
  var sessionsByProject = new Map;
41746
42336
  var lastSeenProjectIdentityBySession = new Map;
41747
42337
  var persistedProjectIdentityBySession = new Map;
42338
+ var sessionProjectBindingFailureLogAtBySession = new Map;
42339
+ var SESSION_PROJECT_BINDING_FAILURE_LOG_INTERVAL_MS = 10 * 60 * 1000;
41748
42340
  var rawMessageProviderUnregistersBySession = new Map;
41749
42341
  var activeContextHandlerSessions = new Set;
41750
42342
  var lastHeuristicsTurnIdBySession = new Map;
41751
42343
  var routinePressureAppliedBySession = new Map;
41752
42344
  var firstContextPassSeenBySession = new Set;
42345
+ var contextPassGeneration = new Map;
42346
+
42347
+ class PiLkgAdmissionReplay extends Error {
42348
+ messages;
42349
+ constructor(messages) {
42350
+ super("Saved request served before writer wait");
42351
+ this.messages = messages;
42352
+ }
42353
+ }
41753
42354
  var liveModelBySession = new Map;
41754
42355
  var latestAssistantModelTimestampBySession = new Map;
41755
42356
  var taggedStableMessageIdsBySession = new Map;
@@ -41974,7 +42575,7 @@ function trackSessionForProject(projectIdentity, sessionId) {
41974
42575
  function isContextHandlerSessionActive(sessionId) {
41975
42576
  return activeContextHandlerSessions.has(sessionId);
41976
42577
  }
41977
- function updateSessionProjectTracking(sessionId, projectIdentity, db) {
42578
+ function updateSessionProjectTracking(sessionId, projectIdentity, db, observedCwd) {
41978
42579
  if (!projectIdentity)
41979
42580
  return;
41980
42581
  const prev = lastSeenProjectIdentityBySession.get(sessionId);
@@ -41987,9 +42588,22 @@ function updateSessionProjectTracking(sessionId, projectIdentity, db) {
41987
42588
  }
41988
42589
  if (db && persistedProjectIdentityBySession.get(sessionId) !== projectIdentity) {
41989
42590
  try {
41990
- recordSessionProjectIdentity(db, sessionId, projectIdentity);
42591
+ const change = recordSessionProjectIdentity(db, sessionId, projectIdentity);
41991
42592
  persistedProjectIdentityBySession.set(sessionId, projectIdentity);
41992
- } catch {}
42593
+ if (change) {
42594
+ sessionLog(sessionId, `project binding changed harness=${getHarness()} cwd=${observedCwd ?? "unknown"} old=${change.previousProjectPath ?? "none"} new=${change.projectPath}`);
42595
+ }
42596
+ } catch (error) {
42597
+ const now = Date.now();
42598
+ const lastLoggedAt = sessionProjectBindingFailureLogAtBySession.get(sessionId);
42599
+ if (lastLoggedAt === undefined || now - lastLoggedAt >= SESSION_PROJECT_BINDING_FAILURE_LOG_INTERVAL_MS) {
42600
+ sessionProjectBindingFailureLogAtBySession.set(sessionId, now);
42601
+ sessionLog(sessionId, `project binding write failed harness=${getHarness()} cwd=${observedCwd ?? "unknown"} attempted=${projectIdentity}: ${error instanceof Error ? error.message : String(error)}`);
42602
+ }
42603
+ }
42604
+ }
42605
+ if (db && persistedProjectIdentityBySession.get(sessionId) === projectIdentity && sessionProjectBindingFailureLogAtBySession.delete(sessionId)) {
42606
+ sessionLog(sessionId, `project binding write recovered harness=${getHarness()} cwd=${observedCwd ?? "unknown"} identity=${projectIdentity}`);
41993
42607
  }
41994
42608
  trackSessionForProject(projectIdentity, sessionId);
41995
42609
  lastSeenProjectIdentityBySession.set(sessionId, projectIdentity);
@@ -42004,11 +42618,6 @@ function recordPiLiveModel(sessionId, modelKey, assistantTimestamp) {
42004
42618
  liveModelBySession.set(sessionId, modelKey);
42005
42619
  return true;
42006
42620
  }
42007
- function summarizeTransformError(error) {
42008
- const raw = error instanceof Error ? error.message : String(error);
42009
- const normalized = raw.replace(/\s+/g, " ").trim();
42010
- return normalized.length > 180 ? `${normalized.slice(0, 177).trimEnd()}...` : normalized || "Unknown transform error";
42011
- }
42012
42621
  function persistLastTransformErrorIfChanged(db, sessionId, summary, knownCurrent) {
42013
42622
  try {
42014
42623
  const current = knownCurrent === undefined ? getOrCreateSessionMeta(db, sessionId).lastTransformError : knownCurrent;
@@ -42113,15 +42722,195 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId, preloadedBranchEn
42113
42722
  }
42114
42723
  return result;
42115
42724
  }
42725
+ function piContextHeaderFields(message) {
42726
+ if (!message || typeof message !== "object")
42727
+ return null;
42728
+ const record = message;
42729
+ if (typeof record.role !== "string")
42730
+ return null;
42731
+ return {
42732
+ responseId: typeof record.responseId === "string" ? record.responseId : null,
42733
+ timestamp: typeof record.timestamp === "number" || typeof record.timestamp === "string" ? record.timestamp : null,
42734
+ role: record.role,
42735
+ toolCallId: typeof record.toolCallId === "string" ? record.toolCallId : null
42736
+ };
42737
+ }
42738
+ function piAlignmentCheckForEntry(entry) {
42739
+ if (!isPiContextEmitEligible(entry))
42740
+ return null;
42741
+ const row = entry;
42742
+ const header = row.type === "message" ? piContextHeaderFields(row.message) : {
42743
+ responseId: null,
42744
+ timestamp: new Date(row.timestamp).getTime(),
42745
+ role: row.type === "custom_message" ? "custom" : "branchSummary",
42746
+ toolCallId: null
42747
+ };
42748
+ if (!header)
42749
+ return null;
42750
+ return {
42751
+ ...header,
42752
+ headerKey: JSON.stringify([
42753
+ header.responseId,
42754
+ header.timestamp,
42755
+ header.role,
42756
+ header.toolCallId
42757
+ ]),
42758
+ entry: row
42759
+ };
42760
+ }
42761
+ function piAlignedContentMatches(check, message) {
42762
+ const entry = check.entry;
42763
+ if (entry.type === "branch_summary") {
42764
+ const summary = message;
42765
+ return summary.summary === entry.summary && summary.fromId === entry.fromId;
42766
+ }
42767
+ if (entry.type === "custom_message") {
42768
+ const custom = message;
42769
+ if (custom.customType !== entry.customType)
42770
+ return false;
42771
+ }
42772
+ if (check.fingerprint === undefined) {
42773
+ check.fingerprint = entry.type === "message" ? piMessageEntryFingerprint(entry.message) : piMessageEntryFingerprint({
42774
+ role: check.role,
42775
+ timestamp: check.timestamp,
42776
+ content: entry.content ?? []
42777
+ });
42778
+ }
42779
+ return check.fingerprint !== null && piMessageEntryFingerprint(message) === check.fingerprint;
42780
+ }
42781
+ function findPiAlignmentMismatch(lookup, entryIds, messages) {
42782
+ for (let index = 0;index < entryIds.length; index += 1) {
42783
+ const id = entryIds[index];
42784
+ if (id === undefined)
42785
+ continue;
42786
+ if (!piAlignedPositionMatches(lookup, id, messages[index]))
42787
+ return index;
42788
+ }
42789
+ return -1;
42790
+ }
42791
+ function piAlignedPositionMatches(lookup, id, message) {
42792
+ const check = lookup.alignmentChecks.get(id);
42793
+ const header = piContextHeaderFields(message);
42794
+ if (!check || !header || header.role !== check.role || !Object.is(header.timestamp, check.timestamp) || header.responseId !== check.responseId || header.toolCallId !== check.toolCallId)
42795
+ return false;
42796
+ return (lookup.alignmentHeaderCounts.get(check.headerKey) ?? 0) <= 1 || piAlignedContentMatches(check, message);
42797
+ }
42798
+ function anchorPiEventEntryIds(lookup, aligned, messages) {
42799
+ const projectionIndex = new Map;
42800
+ for (let index = 0;index < aligned.length; index += 1) {
42801
+ const id = aligned[index];
42802
+ if (id !== undefined)
42803
+ projectionIndex.set(id, index);
42804
+ }
42805
+ const result = new Array(messages.length).fill(undefined);
42806
+ const used = new Set;
42807
+ const anchors = [];
42808
+ for (let index = 0;index < messages.length; index += 1) {
42809
+ const header = piContextHeaderFields(messages[index]);
42810
+ if (!header)
42811
+ continue;
42812
+ const key = JSON.stringify([
42813
+ header.responseId,
42814
+ header.timestamp,
42815
+ header.role,
42816
+ header.toolCallId
42817
+ ]);
42818
+ if (lookup.alignmentHeaderCounts.get(key) !== 1)
42819
+ continue;
42820
+ const id = lookup.alignmentEntryIdByHeader.get(key);
42821
+ const position = id === undefined ? undefined : projectionIndex.get(id);
42822
+ if (id === undefined || position === undefined)
42823
+ continue;
42824
+ const previous = anchors.at(-1);
42825
+ if (used.has(id) || previous && position <= previous.projection)
42826
+ return null;
42827
+ anchors.push({ message: index, projection: position });
42828
+ used.add(id);
42829
+ result[index] = id;
42830
+ }
42831
+ const fillRun = (messageStart, messageEnd, projectionStart, projectionEnd) => {
42832
+ if (messageEnd - messageStart !== projectionEnd - projectionStart)
42833
+ return;
42834
+ for (let offset = 0;offset < messageEnd - messageStart; offset += 1) {
42835
+ const id = aligned[projectionStart + offset];
42836
+ const message = messages[messageStart + offset];
42837
+ if (id !== undefined && !used.has(id) && piAlignedPositionMatches(lookup, id, message)) {
42838
+ result[messageStart + offset] = id;
42839
+ used.add(id);
42840
+ }
42841
+ }
42842
+ };
42843
+ let previousMessage = -1;
42844
+ let previousProjection = -1;
42845
+ for (const anchor of anchors) {
42846
+ fillRun(previousMessage + 1, anchor.message, previousProjection + 1, anchor.projection);
42847
+ previousMessage = anchor.message;
42848
+ previousProjection = anchor.projection;
42849
+ }
42850
+ fillRun(previousMessage + 1, messages.length, previousProjection + 1, aligned.length);
42851
+ for (let index = 0;index < messages.length; index += 1) {
42852
+ if (result[index] !== undefined)
42853
+ continue;
42854
+ const message = messages[index];
42855
+ if (!message || typeof message !== "object")
42856
+ continue;
42857
+ const byRef = lookup.entryIdByMessageRef.get(message);
42858
+ if (byRef !== undefined && !used.has(byRef)) {
42859
+ result[index] = byRef;
42860
+ used.add(byRef);
42861
+ continue;
42862
+ }
42863
+ const fingerprint = piMessageEntryFingerprint(message);
42864
+ const bucket = fingerprint ? lookup.entryIdsByFingerprint.get(fingerprint) : undefined;
42865
+ const id = bucket?.length === 1 ? bucket[0] : undefined;
42866
+ if (id !== undefined && !used.has(id)) {
42867
+ result[index] = id;
42868
+ used.add(id);
42869
+ }
42870
+ }
42871
+ return result;
42872
+ }
42873
+ var piAlignmentMismatchLoggedSessions = new Set;
42874
+ var piEntryAlignmentLaneCounts = { anchored: 0, fingerprint: 0 };
42875
+ function resolvePiEventEntryIds(ctx, messages, sessionId, branchEntries) {
42876
+ if (branchEntries === null)
42877
+ return null;
42878
+ const lookup = getPiBranchEntryLookup(branchEntries);
42879
+ const aligned = messages.some(isPiSystemEntry) ? lookup.alignedEntryIds : lookup.alignedVisibleEntryIds;
42880
+ if (aligned.length === messages.length) {
42881
+ const mismatch = findPiAlignmentMismatch(lookup, aligned, messages);
42882
+ if (mismatch < 0)
42883
+ return aligned;
42884
+ if (!piAlignmentMismatchLoggedSessions.has(sessionId)) {
42885
+ piAlignmentMismatchLoggedSessions.add(sessionId);
42886
+ sessionLog(sessionId, `pi entry alignment: message ${mismatch} of ${messages.length} does not match its projected entry; resolving ids by content fingerprint (logged once per session)`);
42887
+ }
42888
+ }
42889
+ const anchored = anchorPiEventEntryIds(lookup, aligned, messages);
42890
+ if (anchored) {
42891
+ piEntryAlignmentLaneCounts.anchored += 1;
42892
+ return anchored;
42893
+ }
42894
+ piEntryAlignmentLaneCounts.fingerprint += 1;
42895
+ return collectMessageEntryIdsByRef(ctx, messages, sessionId, branchEntries);
42896
+ }
42116
42897
  function addPiBranchEntryToLookup(lookup, entry) {
42117
42898
  if (!entry || typeof entry !== "object")
42118
42899
  return;
42900
+ const check = piAlignmentCheckForEntry(entry);
42901
+ if (check) {
42902
+ lookup.alignmentChecks.set(entry.id, check);
42903
+ lookup.alignmentEntryIdByHeader.set(check.headerKey, entry.id);
42904
+ lookup.alignmentHeaderCounts.set(check.headerKey, (lookup.alignmentHeaderCounts.get(check.headerKey) ?? 0) + 1);
42905
+ }
42119
42906
  const row = entry;
42120
42907
  if (row.type !== "message" || typeof row.id !== "string" || !row.message || typeof row.message !== "object") {
42121
42908
  return;
42122
42909
  }
42123
42910
  lookup.entryIdByMessageRef.set(row.message, row.id);
42124
42911
  const fingerprint = piMessageEntryFingerprint(row.message);
42912
+ if (check)
42913
+ check.fingerprint = fingerprint;
42125
42914
  if (!fingerprint)
42126
42915
  return;
42127
42916
  const bucket = lookup.entryIdsByFingerprint.get(fingerprint);
@@ -42139,6 +42928,56 @@ function isPiContextEmitEligible(entry) {
42139
42928
  return row.type === "message" || row.type === "custom_message" || row.type === "branch_summary" && typeof row.summary === "string" && row.summary.length > 0;
42140
42929
  }
42141
42930
  function buildPiAlignedEntryIds(entries) {
42931
+ const all = buildPiAlignedEntryIdsIncludingSystem(entries);
42932
+ return { all, visible: buildPiAlignedVisibleEntryIds(entries) };
42933
+ }
42934
+ function buildPiAlignedVisibleEntryIds(entries) {
42935
+ let compactionIndex = -1;
42936
+ for (let index = entries.length - 1;index >= 0; index -= 1) {
42937
+ if (entries[index]?.type === "compaction") {
42938
+ compactionIndex = index;
42939
+ break;
42940
+ }
42941
+ }
42942
+ const context = [];
42943
+ if (compactionIndex >= 0) {
42944
+ const compaction = entries[compactionIndex];
42945
+ context.push(compaction);
42946
+ const firstKeptEntryId = compaction.firstKeptEntryId;
42947
+ let foundFirstKept = false;
42948
+ for (let index = 0;index < compactionIndex; index += 1) {
42949
+ const entry = entries[index];
42950
+ if (typeof firstKeptEntryId === "string" && entry?.id === firstKeptEntryId) {
42951
+ foundFirstKept = true;
42952
+ }
42953
+ if (foundFirstKept)
42954
+ context.push(entry);
42955
+ }
42956
+ }
42957
+ for (let index = compactionIndex + 1;index < entries.length; index += 1) {
42958
+ context.push(entries[index]);
42959
+ }
42960
+ const omitted = new Map;
42961
+ for (const entry of context) {
42962
+ const edit = entry;
42963
+ if (edit?.type !== "context_edit" || typeof edit.targetId !== "string")
42964
+ continue;
42965
+ omitted.set(edit.targetId, edit.replacement === null);
42966
+ }
42967
+ const ids = [];
42968
+ if (compactionIndex >= 0) {
42969
+ const compactionId = entries[compactionIndex].id;
42970
+ if (typeof compactionId !== "string" || omitted.get(compactionId) !== true)
42971
+ ids.push(undefined);
42972
+ }
42973
+ for (let index = compactionIndex >= 0 ? 1 : 0;index < context.length; index += 1) {
42974
+ const entry = context[index];
42975
+ if (isPiContextEmitEligible(entry) && !isPiSystemMessageEntry(entry) && omitted.get(entry.id) !== true)
42976
+ ids.push(entry.id);
42977
+ }
42978
+ return ids;
42979
+ }
42980
+ function buildPiAlignedEntryIdsIncludingSystem(entries) {
42142
42981
  let compactionIndex = -1;
42143
42982
  let firstKeptEntryId;
42144
42983
  for (let index = entries.length - 1;index >= 0; index -= 1) {
@@ -42202,10 +43041,15 @@ function getPiBranchEntryLookup(entries) {
42202
43041
  const cached = piBranchLookupByProjection.get(entries);
42203
43042
  if (cached)
42204
43043
  return cached;
43044
+ const aligned = buildPiAlignedEntryIds(entries);
42205
43045
  const lookup = {
42206
43046
  entryIdByMessageRef: new Map,
42207
43047
  entryIdsByFingerprint: new Map,
42208
- alignedEntryIds: buildPiAlignedEntryIds(entries)
43048
+ alignedEntryIds: aligned.all,
43049
+ alignedVisibleEntryIds: aligned.visible,
43050
+ alignmentChecks: new Map,
43051
+ alignmentHeaderCounts: new Map,
43052
+ alignmentEntryIdByHeader: new Map
42209
43053
  };
42210
43054
  for (const entry of entries)
42211
43055
  addPiBranchEntryToLookup(lookup, entry);
@@ -42281,7 +43125,10 @@ function readPiBranchEntriesForContext(ctx, sessionId) {
42281
43125
  suffix.reverse();
42282
43126
  if (cached && cachedAncestorIndex === cached.entries.length - 1) {
42283
43127
  const entries = [...cached.entries, ...suffix];
42284
- if (suffix.some((entry) => entry?.type === "compaction")) {
43128
+ if (suffix.some((entry) => {
43129
+ const type = entry?.type;
43130
+ return type === "compaction" || type === "context_edit";
43131
+ })) {
42285
43132
  return installProjection(leafId, entries);
42286
43133
  }
42287
43134
  for (let index = 0;index < suffix.length; index += 1) {
@@ -42291,6 +43138,9 @@ function readPiBranchEntriesForContext(ctx, sessionId) {
42291
43138
  addPiBranchEntryToLookup(cached.lookup, entry);
42292
43139
  if (isPiContextEmitEligible(entry)) {
42293
43140
  cached.lookup.alignedEntryIds.push(entry.id);
43141
+ if (!isPiSystemMessageEntry(entry)) {
43142
+ cached.lookup.alignedVisibleEntryIds.push(entry.id);
43143
+ }
42294
43144
  }
42295
43145
  }
42296
43146
  const projection = {
@@ -42315,46 +43165,69 @@ function readPiBranchEntriesForContext(ctx, sessionId) {
42315
43165
  }
42316
43166
  }
42317
43167
  }
42318
- function piMessageEntryFingerprint(message) {
43168
+ function piMessageEntryFingerprintHeader(message) {
42319
43169
  if (!message || typeof message !== "object")
42320
43170
  return null;
42321
43171
  const record = message;
42322
43172
  if (typeof record.role !== "string")
42323
43173
  return null;
42324
- const firstText = firstPiTextContent(record.content);
42325
- const firstTextHash = crypto3.createHash("sha256").update(firstText ?? "").digest("hex").slice(0, 16);
42326
43174
  return JSON.stringify([
42327
43175
  typeof record.responseId === "string" ? record.responseId : null,
42328
43176
  typeof record.timestamp === "number" || typeof record.timestamp === "string" ? record.timestamp : null,
42329
43177
  record.role,
42330
- typeof record.toolCallId === "string" ? record.toolCallId : null,
42331
- firstTextHash
43178
+ typeof record.toolCallId === "string" ? record.toolCallId : null
42332
43179
  ]);
42333
43180
  }
42334
- function firstPiTextContent(content) {
42335
- if (typeof content === "string")
42336
- return content;
42337
- if (!Array.isArray(content))
42338
- return null;
42339
- for (const part of content) {
42340
- if (!part || typeof part !== "object")
42341
- continue;
42342
- const record = part;
42343
- if (record.type === "text" && typeof record.text === "string") {
42344
- return record.text;
43181
+ function readPiFallbackFingerprintHeaders(db, sessionId) {
43182
+ const rows = db.prepare(`SELECT DISTINCT entry_fingerprint FROM tags WHERE session_id = ? AND type = 'message'
43183
+ AND entry_fingerprint IS NOT NULL AND message_id LIKE 'pi-msg-%'`).all(sessionId);
43184
+ const headers = new Set;
43185
+ for (const row of rows) {
43186
+ let parsed;
43187
+ try {
43188
+ parsed = JSON.parse(row.entry_fingerprint);
43189
+ } catch {
43190
+ return null;
42345
43191
  }
43192
+ if (!Array.isArray(parsed) || parsed.length !== 5)
43193
+ return null;
43194
+ headers.add(JSON.stringify(parsed.slice(0, 4)));
42346
43195
  }
42347
- return null;
43196
+ return headers;
42348
43197
  }
42349
- function buildEntryFingerprintMap(messages, resolveStableId, reusableMessageIds, includeReusable = true) {
43198
+ var piEntryFingerprintCount = 0;
43199
+ function piMessageEntryFingerprint(message) {
43200
+ piEntryFingerprintCount += 1;
43201
+ if (!message || typeof message !== "object")
43202
+ return null;
43203
+ const record = message;
43204
+ if (typeof record.role !== "string")
43205
+ return null;
43206
+ const contentHash = crypto3.createHash("sha256").update(stableStringify(record.content)).digest("hex");
43207
+ return JSON.stringify([
43208
+ typeof record.responseId === "string" ? record.responseId : null,
43209
+ typeof record.timestamp === "number" || typeof record.timestamp === "string" ? record.timestamp : null,
43210
+ record.role,
43211
+ typeof record.toolCallId === "string" ? record.toolCallId : null,
43212
+ contentHash
43213
+ ]);
43214
+ }
43215
+ function buildEntryFingerprintMap(messages, resolveStableId, reusableMessageIds, includeReusable = true, reusableHeaders) {
42350
43216
  const map = new Map;
42351
43217
  for (let i = 0;i < messages.length; i++) {
42352
43218
  const msg = messages[i];
42353
43219
  const id = resolveStableId(msg, i);
42354
43220
  if (!id)
42355
43221
  continue;
42356
- if (!includeReusable && reusableMessageIds?.has(id))
42357
- continue;
43222
+ if (reusableMessageIds?.has(id)) {
43223
+ if (!includeReusable)
43224
+ continue;
43225
+ if (reusableHeaders) {
43226
+ const header = piMessageEntryFingerprintHeader(msg);
43227
+ if (header === null || !reusableHeaders.has(header))
43228
+ continue;
43229
+ }
43230
+ }
42358
43231
  const fp = piMessageEntryFingerprint(msg);
42359
43232
  if (fp)
42360
43233
  map.set(id, fp);
@@ -42422,54 +43295,116 @@ function runImmediateTransaction(db, fn) {
42422
43295
  try {
42423
43296
  const result = fn();
42424
43297
  db.exec("COMMIT");
42425
- logSlowWriteTransaction("pi_compaction_queue", transactionStartedAt);
43298
+ logSlowWriteTransaction("pi_fallback_adoption", transactionStartedAt);
42426
43299
  return result;
42427
43300
  } catch (error) {
42428
43301
  db.exec("ROLLBACK");
42429
43302
  throw error;
42430
43303
  }
42431
43304
  }
42432
- function hasAdoptablePiFallbackMessageTags(db, sessionId, fingerprintById) {
42433
- const fingerprints = [
42434
- ...new Set([...fingerprintById].filter(([id]) => !id.startsWith("pi-msg-")).map(([, fingerprint]) => fingerprint))
42435
- ];
42436
- for (let index = 0;index < fingerprints.length; index += 900) {
42437
- const batch = fingerprints.slice(index, index + 900);
42438
- const placeholders = batch.map(() => "?").join(",");
42439
- const match = db.prepare(`SELECT 1 FROM tags WHERE session_id = ? AND type = 'message'
42440
- AND entry_fingerprint IN (${placeholders})
42441
- AND message_id LIKE 'pi-msg-%' LIMIT 1`).get(sessionId, ...batch);
42442
- if (match != null)
42443
- return true;
43305
+ function readPiAdoptionRevision(db) {
43306
+ return {
43307
+ external: db.prepare("PRAGMA data_version").get(),
43308
+ local: db.prepare("SELECT total_changes() AS changes").get()
43309
+ };
43310
+ }
43311
+ function preparePiAdoptionFingerprints(fingerprintById) {
43312
+ const realIdsByFingerprint = new Map;
43313
+ for (const [id, fingerprint] of fingerprintById) {
43314
+ if (id.startsWith("pi-msg-"))
43315
+ continue;
43316
+ const ids = realIdsByFingerprint.get(fingerprint) ?? [];
43317
+ ids.push(id);
43318
+ realIdsByFingerprint.set(fingerprint, ids);
42444
43319
  }
42445
- return false;
43320
+ const fingerprints = [...realIdsByFingerprint.keys()];
43321
+ const batches = [];
43322
+ for (let i = 0;i < fingerprints.length; i += 900) {
43323
+ const values = fingerprints.slice(i, i + 900);
43324
+ batches.push({ values, placeholders: values.map(() => "?").join(",") });
43325
+ }
43326
+ return { realIdsByFingerprint, batches };
42446
43327
  }
42447
- function readAdoptablePiFallbackFingerprints(db, sessionId, fingerprintById) {
42448
- const fingerprints = [
42449
- ...new Set([...fingerprintById].filter(([id]) => !id.startsWith("pi-msg-")).map(([, fingerprint]) => fingerprint))
42450
- ];
43328
+ function readAdoptablePiFallbackFingerprints(db, sessionId, batches) {
42451
43329
  const found = new Set;
42452
- for (let index = 0;index < fingerprints.length; index += 900) {
42453
- const batch = fingerprints.slice(index, index + 900);
42454
- const placeholders = batch.map(() => "?").join(",");
43330
+ for (const { values, placeholders } of batches) {
42455
43331
  const rows = db.prepare(`SELECT DISTINCT entry_fingerprint FROM tags WHERE session_id = ? AND type = 'message'
42456
- AND entry_fingerprint IN (${placeholders}) AND message_id LIKE 'pi-msg-%'`).all(sessionId, ...batch);
43332
+ AND entry_fingerprint IN (${placeholders}) AND message_id LIKE 'pi-msg-%'`).all(sessionId, ...values);
42457
43333
  for (const row of rows)
42458
43334
  found.add(row.entry_fingerprint);
42459
43335
  }
42460
43336
  return found;
42461
43337
  }
43338
+ function piFallbackBaseId(messageId) {
43339
+ return /^(.*):p\d+$/.exec(messageId)?.[1] ?? messageId;
43340
+ }
43341
+ function pairPiFallbackBases(realIds, candidates, realIdPositions) {
43342
+ const pairs = new Map(realIds.map((id) => [id, null]));
43343
+ if (realIds.length < 2)
43344
+ return pairs;
43345
+ const positions = realIdPositions();
43346
+ if (!positions || realIds.some((id) => !positions.has(id)))
43347
+ return pairs;
43348
+ const newestTag = new Map;
43349
+ for (const c of candidates) {
43350
+ const base = piFallbackBaseId(c.messageId);
43351
+ newestTag.set(base, Math.max(newestTag.get(base) ?? 0, c.tagNumber));
43352
+ }
43353
+ if (newestTag.size < realIds.length)
43354
+ return pairs;
43355
+ const chosen = [...newestTag.entries()].sort((left, right) => right[1] - left[1]).slice(0, realIds.length).map(([base]) => ({ base, index: /^pi-msg-(\d+)-/.exec(base)?.[1] }));
43356
+ if (chosen.some((entry) => entry.index === undefined))
43357
+ return pairs;
43358
+ chosen.sort((left, right) => Number(left.index) - Number(right.index));
43359
+ if (new Set(chosen.map((entry) => entry.index)).size !== chosen.length)
43360
+ return pairs;
43361
+ const ordered = [...realIds].sort((left, right) => (positions.get(left) ?? 0) - (positions.get(right) ?? 0));
43362
+ for (let index = 0;index < ordered.length; index += 1) {
43363
+ pairs.set(ordered[index], chosen[index]?.base ?? null);
43364
+ }
43365
+ return pairs;
43366
+ }
42462
43367
  function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {}) {
42463
- const hasFallbackMessageTags = options.hasFallbackMessageTags === true || hasPiFallbackMessageTags2(db, sessionId);
42464
- const hasFallbackToolOwnerTags = options.hasFallbackToolOwnerTags === true || hasPiFallbackToolOwnerTags2(db, sessionId);
42465
- const shouldRunMessageMigration = hasFallbackMessageTags && hasAdoptablePiFallbackMessageTags(db, sessionId, fingerprintById);
42466
- const shouldRunToolOwnerMigration = Boolean(options.messages && options.resolveStableId && hasFallbackToolOwnerTags);
42467
- if (!shouldRunMessageMigration && !shouldRunToolOwnerMigration)
43368
+ let { realIdsByFingerprint, batches } = preparePiAdoptionFingerprints(fingerprintById);
43369
+ const ownerMap = options.messages && options.resolveStableId ? buildPiToolOwnerMap(options.messages, options.resolveStableId) : null;
43370
+ if (!batches.length && !ownerMap?.size && !options.rebuildFingerprints)
42468
43371
  return;
43372
+ const revision = () => readPiAdoptionRevision(db);
43373
+ const beforeDiscovery = revision();
43374
+ const discovered = hasPiFallbackMessageTags(db, sessionId) ? readAdoptablePiFallbackFingerprints(db, sessionId, batches) : new Set;
43375
+ const targetsFor = (fingerprints) => [...fingerprints].flatMap((fingerprint) => (realIdsByFingerprint.get(fingerprint) ?? []).map((id) => [id, fingerprint]));
43376
+ const discoveredTargets = targetsFor(discovered);
42469
43377
  runImmediateTransaction(db, () => {
42470
- if (shouldRunMessageMigration) {
42471
- const adoptable = readAdoptablePiFallbackFingerprints(db, sessionId, fingerprintById);
42472
- for (const [realMessageId, fingerprint] of fingerprintById) {
43378
+ const admitted = revision();
43379
+ const preflight = options.preflightRevision;
43380
+ const rebuild = options.rebuildFingerprints;
43381
+ const expanded = Boolean(preflight && rebuild && (preflight.external.data_version !== admitted.external.data_version || preflight.local.changes !== admitted.local.changes));
43382
+ if (expanded && rebuild) {
43383
+ ({ realIdsByFingerprint, batches } = preparePiAdoptionFingerprints(rebuild()));
43384
+ }
43385
+ if (batches.length && hasPiFallbackMessageTags(db, sessionId)) {
43386
+ const unchanged = !expanded && beforeDiscovery.external.data_version === admitted.external.data_version && beforeDiscovery.local.changes === admitted.local.changes;
43387
+ const adoptable = unchanged ? discovered : readAdoptablePiFallbackFingerprints(db, sessionId, batches);
43388
+ const targets = expanded ? targetsFor(adoptable) : discoveredTargets.filter(([, fp]) => adoptable.has(fp));
43389
+ if (!expanded)
43390
+ targets.push(...targetsFor([...adoptable].filter((fp) => !discovered.has(fp))));
43391
+ const pairedBaseByRealId = new Map;
43392
+ let positions;
43393
+ const realIdPositions = () => {
43394
+ if (positions)
43395
+ return positions;
43396
+ const { messages, resolveStableId } = options;
43397
+ if (!messages || !resolveStableId)
43398
+ return;
43399
+ positions = new Map;
43400
+ for (let index = 0;index < messages.length; index += 1) {
43401
+ const id = resolveStableId(messages[index], index);
43402
+ if (id !== undefined && !positions.has(id))
43403
+ positions.set(id, index);
43404
+ }
43405
+ return positions;
43406
+ };
43407
+ for (const [realMessageId, fingerprint] of targets) {
42473
43408
  if (realMessageId.startsWith("pi-msg-"))
42474
43409
  continue;
42475
43410
  if (!adoptable.has(fingerprint))
@@ -42477,19 +43412,27 @@ function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {
42477
43412
  const candidates = findAdoptableFallbackTags(db, sessionId, fingerprint);
42478
43413
  if (candidates.length === 0)
42479
43414
  continue;
42480
- const baseIds = new Set;
42481
- for (const c of candidates) {
42482
- const m = /^(.*):p\d+$/.exec(c.messageId);
42483
- baseIds.add(m ? m[1] : c.messageId);
43415
+ const baseIds = new Set(candidates.map((c) => piFallbackBaseId(c.messageId)));
43416
+ let base;
43417
+ if (baseIds.size === 1)
43418
+ base = [...baseIds][0];
43419
+ else {
43420
+ if (!pairedBaseByRealId.has(realMessageId)) {
43421
+ for (const [id, paired] of pairPiFallbackBases((realIdsByFingerprint.get(fingerprint) ?? []).filter((id) => !id.startsWith("pi-msg-")), candidates, realIdPositions))
43422
+ pairedBaseByRealId.set(id, paired);
43423
+ }
43424
+ base = pairedBaseByRealId.get(realMessageId) ?? undefined;
42484
43425
  }
42485
- if (baseIds.size !== 1)
43426
+ if (base === undefined)
42486
43427
  continue;
42487
43428
  for (const c of candidates) {
43429
+ if (piFallbackBaseId(c.messageId) !== base)
43430
+ continue;
42488
43431
  const ordinalMatch = /:p(\d+)$/.exec(c.messageId);
42489
43432
  if (!ordinalMatch)
42490
43433
  continue;
42491
43434
  const realContentId = `${realMessageId}:p${ordinalMatch[1]}`;
42492
- const adoption = adoptPiFallbackMessageTag(db, sessionId, c.tagNumber, c.messageId, realContentId);
43435
+ const adoption = adoptPiFallbackMessageTag(db, sessionId, c.tagNumber, c.messageId, realContentId, getPiServedTagNumbers(sessionId));
42493
43436
  if (adoption.action !== "skipped") {
42494
43437
  tagger.unbindTag(sessionId, c.messageId);
42495
43438
  if (adoption.action === "folded") {
@@ -42500,8 +43443,7 @@ function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {
42500
43443
  }
42501
43444
  }
42502
43445
  }
42503
- if (shouldRunToolOwnerMigration && options.messages && options.resolveStableId) {
42504
- const ownerMap = buildPiToolOwnerMap(options.messages, options.resolveStableId);
43446
+ if (ownerMap && hasPiFallbackToolOwnerTags(db, sessionId)) {
42505
43447
  for (const row of findPiFallbackToolOwnerTags(db, sessionId)) {
42506
43448
  const parsed = parsePiFallbackToolOwnerId(row.toolOwnerMessageId);
42507
43449
  if (parsed?.role !== "assistant")
@@ -42512,7 +43454,7 @@ function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {
42512
43454
  const [realOwnerId] = owners;
42513
43455
  if (!realOwnerId || realOwnerId.startsWith("pi-msg-"))
42514
43456
  continue;
42515
- const adoption = adoptPiFallbackToolOwnerTag(db, sessionId, row.tagNumber, row.callId, row.toolOwnerMessageId, realOwnerId);
43457
+ const adoption = adoptPiFallbackToolOwnerTag(db, sessionId, row.tagNumber, row.callId, row.toolOwnerMessageId, realOwnerId, getPiServedTagNumbers(sessionId));
42516
43458
  if (adoption.action !== "skipped") {
42517
43459
  tagger.unbindToolTag(sessionId, row.toolOwnerMessageId, row.callId);
42518
43460
  if (adoption.action === "folded") {
@@ -42583,12 +43525,32 @@ function registerPiContextHandler(pi, baseOptions) {
42583
43525
  variantChangeLogObserverForTests?.(message);
42584
43526
  sessionLog(sessionId, message);
42585
43527
  });
42586
- registerPiGuardedContext(pi, async (event, ctx) => {
42587
- const transformStartTime = performance.now();
43528
+ const contextHandler = async (event, ctx, budget) => {
43529
+ const passSessionId = ctx.sessionManager ? resolveSessionId2(ctx) : undefined;
43530
+ const generation = Symbol();
43531
+ if (passSessionId && !budget.sideTurn)
43532
+ contextPassGeneration.set(passSessionId, generation);
43533
+ const signal = event.signal ?? ctx.signal;
43534
+ const assertOperation = budget.assertOwner;
43535
+ budget.assertOwner = () => {
43536
+ assertOperation();
43537
+ if (!budget.sideTurn && passSessionId && contextPassGeneration.get(passSessionId) !== generation)
43538
+ throw new PiContextSupersededError("Pi context pass superseded before writer admission");
43539
+ signal?.throwIfAborted();
43540
+ };
43541
+ let assertCurrentPass = budget.assert;
43542
+ const guardAwait = budget.wait;
43543
+ const passGuard = { assert: assertCurrentPass, wait: guardAwait };
43544
+ guardSqliteTransformPass({
43545
+ assert: assertCurrentPass,
43546
+ remainingMs: () => budget.remainingWork()
43547
+ });
43548
+ budget.stage = "schema/claim";
43549
+ const toolWireSchema = await guardAwait(loadPiToolWireSchema());
43550
+ const transformStartTime = budget.startedAt;
42588
43551
  let rawMessageCount = 0;
42589
43552
  let rawFallbackLimit;
42590
43553
  let sessionIdForError;
42591
- let sessionMetaForPass;
42592
43554
  let lkgPassSnapshot;
42593
43555
  let lkgCompactionOff = baseOptions.compactionOff === true;
42594
43556
  let lkgEmergencyRecoveryArmed = false;
@@ -42616,17 +43578,21 @@ function registerPiContextHandler(pi, baseOptions) {
42616
43578
  const scheduler = schedulerFor(options);
42617
43579
  lkgCompactionOff = options.compactionOff === true;
42618
43580
  const projectIdentity = resolveProjectIdentityForSession(projectDirectory, options.allowHomeProject) ?? "";
42619
- updateSessionProjectTracking(sessionId, projectIdentity, options.db);
42620
43581
  logTransformTiming(sessionId, "findSessionId", tFindSession, `messages=${event.messages.length}`);
43582
+ budget.stage = "branch projection";
42621
43583
  const tEntryBranch = performance.now();
42622
43584
  const branchEntries = readPiBranchEntriesForContext(ctx, sessionId);
43585
+ assertCurrentPass();
42623
43586
  const piLiveUsageIsRawBranchEstimate = isPiLiveUsageRawBranchEstimate(branchEntries);
42624
43587
  recordPiLiveUsageClassification(sessionId, piLiveUsageIsRawBranchEstimate);
42625
- schedulePiTransformDecisionResolve({
42626
- db: options.db,
42627
- sessionId,
42628
- branchEntries
42629
- });
43588
+ assertCurrentPass();
43589
+ if (!budget.sideTurn)
43590
+ schedulePiTransformDecisionResolve({
43591
+ db: options.db,
43592
+ sessionId,
43593
+ branchEntries,
43594
+ assertCurrentPass
43595
+ });
42630
43596
  let rawOrdinalCount;
42631
43597
  const rawMessageProvider = {
42632
43598
  getMessageCount: () => rawOrdinalCount ??= branchEntries !== null ? countPiRawMessages(branchEntries) : readPiSessionMessages(ctx).length,
@@ -42638,21 +43604,63 @@ function registerPiContextHandler(pi, baseOptions) {
42638
43604
  const unregisterRaw = setRawMessageProvider2(sessionId, rawMessageProvider);
42639
43605
  rawMessageProviderUnregistersBySession.set(sessionId, unregisterRaw);
42640
43606
  scheduleReconciliation(options.db, sessionId, readRawSessionMessages2);
42641
- const branchLookup = branchEntries === null ? null : getPiBranchEntryLookup(branchEntries);
42642
- const alignedEntryIds = branchLookup?.alignedEntryIds ?? null;
42643
- const resolvedEntryIds = alignedEntryIds?.length === event.messages.length ? alignedEntryIds : branchEntries === null ? null : collectMessageEntryIdsByRef(ctx, event.messages, sessionId, branchEntries);
43607
+ const alignedEntryIds = branchEntries === null ? null : getPiBranchEntryLookup(branchEntries).alignedEntryIds;
43608
+ const resolvedEntryIds = resolvePiEventEntryIds(ctx, event.messages, sessionId, branchEntries);
42644
43609
  const strictEntryIds = resolvedEntryIds ? [...resolvedEntryIds] : null;
42645
43610
  const lkgEntryIds = reconcilePiLkgEntryIds(strictEntryIds, alignedEntryIds);
42646
43611
  const lkgModelKey = resolvePiContextModelKey(ctx) ?? null;
42647
43612
  const lkgContextModel = ctx.model;
42648
43613
  const lkgProviderKey = typeof lkgContextModel?.provider === "string" ? lkgContextModel.provider : null;
42649
- lkgPassSnapshot = lkgCoordinator.beginPass({
43614
+ const snapshot = lkgCoordinator.beginPass({
42650
43615
  sessionId,
42651
43616
  messages: event.messages,
42652
43617
  entryIds: lkgEntryIds,
42653
43618
  modelKey: lkgModelKey,
42654
- providerKey: lkgProviderKey
43619
+ providerKey: lkgProviderKey,
43620
+ apiKey: ctx.model?.api ?? null,
43621
+ transport: ctx.model?.transport
42655
43622
  });
43623
+ lkgPassSnapshot = snapshot;
43624
+ let checkedReplay = false;
43625
+ budget.stage = "writer admission";
43626
+ assertCurrentPass();
43627
+ const sessionMetaForUsage = await guardAwait(withAsyncPrivilegedWriter(options.db, () => {
43628
+ assertCurrentPass();
43629
+ return getOrCreateSessionMeta(options.db, sessionId);
43630
+ }, {
43631
+ signal,
43632
+ budgetMs: budget.writerAllowance(),
43633
+ assertCurrentPass,
43634
+ jitter: true,
43635
+ beforeRetry: (error) => {
43636
+ assertCurrentPass();
43637
+ if (checkedReplay)
43638
+ return;
43639
+ checkedReplay = true;
43640
+ const state = loadPiHistorianStateSnapshot(options.db, sessionId);
43641
+ lkgEmergencyRecoveryArmed = state.needsEmergencyRecovery;
43642
+ if (state.detectedContextLimit > 0)
43643
+ rawFallbackLimit = resolvePiWindowGeometry({
43644
+ model: ctx.model,
43645
+ rawContextWindow: piUsage?.contextWindow,
43646
+ detectedContextLimit: state.detectedContextLimit
43647
+ })?.usableHard;
43648
+ if (lkgCompactionOff || lkgEmergencyRecoveryArmed || isProviderOverflowFailClosedProven(sessionId))
43649
+ return;
43650
+ const replay = lkgCoordinator.replay(snapshot, (id) => ctx.sessionManager.getEntry?.(id)?.parentId);
43651
+ if (!replay.ok)
43652
+ return;
43653
+ try {
43654
+ assertPiRawFallbackFits(replay.messages, rawFallbackLimit, (line) => logPiLkgRecovery(sessionId, line), error, readPiLkgFitEnvelope(ctx, pi, lkgModelKey, sessionDecisionCalibration(options.db, sessionId), toolWireSchema), replay.measuredPrefix);
43655
+ } catch {
43656
+ return;
43657
+ }
43658
+ logPiLkgRecovery(sessionId, `TRANSIENT STORAGE FAILURE ${piStorageErrorReason(error)}: LKG replay served ${replay.messages.length} messages instead of raw ${rawMessageCount}`);
43659
+ throw new PiLkgAdmissionReplay(replay.messages);
43660
+ }
43661
+ }));
43662
+ assertCurrentPass();
43663
+ updateSessionProjectTracking(sessionId, projectIdentity, options.db, projectDirectory);
42656
43664
  const lkgInputIdByRef = new Map;
42657
43665
  for (const input of lkgPassSnapshot.inputs)
42658
43666
  lkgInputIdByRef.set(event.messages[input.messageIndex], input.id);
@@ -42680,8 +43688,6 @@ function registerPiContextHandler(pi, baseOptions) {
42680
43688
  }
42681
43689
  }
42682
43690
  const tMeta = performance.now();
42683
- const sessionMetaForUsage = getOrCreateSessionMeta(options.db, sessionId);
42684
- sessionMetaForPass = sessionMetaForUsage;
42685
43691
  const historianStateForPass = options.compactionOff ? EMPTY_PI_HISTORIAN_STATE_SNAPSHOT : (() => {
42686
43692
  try {
42687
43693
  return loadPiHistorianStateSnapshot(options.db, sessionId);
@@ -42841,7 +43847,7 @@ function registerPiContextHandler(pi, baseOptions) {
42841
43847
  } catch (err) {
42842
43848
  sessionLog(sessionId, `transform: overflow state read failed: ${err instanceof Error ? err.message : String(err)}`);
42843
43849
  }
42844
- const sessionMeta = sessionMetaForUsage;
43850
+ let sessionMeta = sessionMetaForUsage;
42845
43851
  const modelKey = liveModelBySession.get(sessionId);
42846
43852
  const providerId = typeof ctx.model?.provider === "string" ? ctx.model.provider : undefined;
42847
43853
  const canUseEmptySentinels = modelAcceptsEmptyContent(providerId);
@@ -42953,14 +43959,25 @@ function registerPiContextHandler(pi, baseOptions) {
42953
43959
  if (now - lastNotifiedAt >= EMERGENCY_NOTIFICATION_COOLDOWN_MS) {
42954
43960
  lastEmergencyNotificationAtMs.set(sessionId, now);
42955
43961
  sendPiIgnoredNotification(ctx, "Context full — /mmc-flush or /clear to continue.");
42956
- sessionLog(sessionId, `EMERGENCY: usage=${usagePercentage.toFixed(1)}% — notified user, awaiting in-flight historian + evaluating tiered emergency reclaim`);
42957
- }
42958
- const histPromise = inFlightHistorian.get(sessionId);
42959
- if (histPromise) {
42960
- try {
42961
- await withTimeout(histPromise, 30000);
42962
- sessionLog(sessionId, "EMERGENCY: historian wait completed (or timed out)");
42963
- } catch {}
43962
+ sessionLog(sessionId, `EMERGENCY: usage=${usagePercentage.toFixed(1)}% — notified user, evaluating available emergency reclaim`);
43963
+ }
43964
+ const historian = inFlightHistorian.get(sessionId);
43965
+ const visibleToolResults = new Set(event.messages.flatMap((message) => message.role === "toolResult" ? [message.toolCallId] : []));
43966
+ const toolTags = getTagsBySession(options.db, sessionId).filter((tag) => tag.type === "tool");
43967
+ const knownTools = new Set(toolTags.map((tag) => tag.messageId));
43968
+ const activeTools = new Set(toolTags.filter((tag) => tag.status === "active").map((tag) => tag.messageId));
43969
+ const hasToolReclaim = event.messages.some((message) => message.role === "assistant" && message.content.some((part) => part.type === "toolCall" && visibleToolResults.has(part.id) && (!knownTools.has(part.id) || activeTools.has(part.id))));
43970
+ if (historian && !hasToolReclaim && getPendingOps(options.db, sessionId).length === 0 && !historyRefreshSessions.has(sessionId) && !deferredHistoryRefreshSessions.has(sessionId)) {
43971
+ budget.stage = "emergency historian";
43972
+ await budget.wait(historian);
43973
+ assertCurrentPass();
43974
+ sessionMeta = getOrCreateSessionMeta(options.db, sessionId);
43975
+ piM0M1PassSnapshot = options.injection ? createPiM0M1PassSnapshot({
43976
+ db: options.db,
43977
+ sessionId,
43978
+ compactionOff: false,
43979
+ sessionMeta
43980
+ }) : undefined;
42964
43981
  }
42965
43982
  if (emergencyRecoveryArmed && realUsagePercentageBeforeEmergencyBump < forceMaterializationPercentage && !inFlightHistorian.has(sessionId) && !hasEligiblePiCompartmentHistory(options.db, sessionId)) {
42966
43983
  try {
@@ -42983,7 +44000,17 @@ function registerPiContextHandler(pi, baseOptions) {
42983
44000
  }) / 100)) : undefined;
42984
44001
  logTransformTiming(sessionId, "prePipelineTotal", transformStartTime);
42985
44002
  const tRunPipeline = performance.now();
42986
- const result = await runPipeline({
44003
+ budget.stage = "pipeline";
44004
+ assertCurrentPass = budget.assertOutcome;
44005
+ guardSqliteTransformPass({
44006
+ assert: assertCurrentPass,
44007
+ remainingMs: budget.remainingOutcome
44008
+ });
44009
+ if (beforePipelineForTests)
44010
+ await budget.waitMandatory(beforePipelineForTests());
44011
+ assertCurrentPass();
44012
+ const result = await budget.waitMandatory(runPipeline({
44013
+ assertCurrentPass,
42987
44014
  db: options.db,
42988
44015
  tagger,
42989
44016
  sessionId,
@@ -43036,20 +44063,21 @@ function registerPiContextHandler(pi, baseOptions) {
43036
44063
  resolvedModelID: ctx.model?.id,
43037
44064
  canUseEmptySentinels,
43038
44065
  temporalAwareness: options.injection?.temporalAwareness === true,
43039
- appendCompaction: resolvePiAppendCompaction(ctx),
44066
+ appendCompaction: guardedPiAppendCompaction(ctx, assertCurrentPass),
43040
44067
  readBranchEntries: resolvePiReadBranchEntries(ctx),
43041
44068
  isSubagent: sessionMeta.isSubagent,
43042
44069
  compactionOff: options.compactionOff === true,
43043
44070
  injectionPassSnapshot: piM0M1PassSnapshot
43044
- });
44071
+ }));
43045
44072
  logTransformTiming(sessionId, "runPipeline", tRunPipeline);
43046
44073
  const postPipelineStart = performance.now();
43047
44074
  const tTransformDecision = performance.now();
43048
44075
  if (strictEntryIds) {
44076
+ assertCurrentPass();
43049
44077
  recordSuccessfulTaggedMessageIds(sessionId, strictEntryIds);
43050
44078
  }
43051
44079
  const piDecisionSnapshotNewestAssistant = result.bustedThisPass ? findNewestPiAssistantEntryId(branchEntries) : undefined;
43052
- if (piDecisionSnapshotNewestAssistant !== undefined) {
44080
+ const publishTransformDecision = !budget.sideTurn && piDecisionSnapshotNewestAssistant !== undefined ? () => {
43053
44081
  recordPendingPiTransformDecision(sessionId, {
43054
44082
  tsMs: Date.now(),
43055
44083
  decision: schedulerDecision,
@@ -43064,28 +44092,51 @@ function registerPiContextHandler(pi, baseOptions) {
43064
44092
  droppedCount: result.droppedCount,
43065
44093
  inputTokens: usageInputTokens,
43066
44094
  bustedThisPass: true
43067
- }, piDecisionSnapshotNewestAssistant);
43068
- }
44095
+ }, piDecisionSnapshotNewestAssistant, budget.assertDecisionPublication);
44096
+ } : undefined;
43069
44097
  logTransformTiming(sessionId, "transformDecisionAndReuseState", tTransformDecision);
43070
44098
  const tHistorianScheduling = performance.now();
43071
- if (options.historian && !options.compactionOff) {
43072
- maybeFireHistorian({
43073
- pi,
43074
- ctx,
43075
- sessionId,
43076
- db: options.db,
43077
- historian: options.historian,
43078
- isFirstContextPassForSession,
43079
- activeTags: result.activeTags,
43080
- rawMessageProvider,
43081
- taggerFloor,
43082
- sessionMeta,
43083
- liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
43084
- piUsage,
43085
- minimumPercentage: usagePercentage,
43086
- historianStateSnapshot: historianStateForPass,
43087
- publishedHistoryRide: isCacheBusting
44099
+ const historian = options.historian;
44100
+ budget.stage = "historian scheduling";
44101
+ if (historian && !options.compactionOff && budget.remainingWork() > 0) {
44102
+ guardSqliteTransformPass({
44103
+ assert: budget.assert,
44104
+ remainingMs: () => budget.remainingWork()
43088
44105
  });
44106
+ try {
44107
+ budget.assert();
44108
+ maybeFireHistorian({
44109
+ startGuard: () => {
44110
+ if (!budget.completed)
44111
+ budget.assertOwner();
44112
+ if (budget.abandoned || budget.remainingWork() === 0)
44113
+ throw new PiContextDeadlineError(budget.diagnostic());
44114
+ },
44115
+ pi,
44116
+ ctx,
44117
+ sessionId,
44118
+ db: options.db,
44119
+ historian,
44120
+ isFirstContextPassForSession,
44121
+ activeTags: result.activeTags,
44122
+ rawMessageProvider,
44123
+ taggerFloor,
44124
+ sessionMeta,
44125
+ liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
44126
+ piUsage,
44127
+ minimumPercentage: usagePercentage,
44128
+ historianStateSnapshot: historianStateForPass,
44129
+ publishedHistoryRide: isCacheBusting
44130
+ });
44131
+ } catch (error) {
44132
+ budget.assertOutcome();
44133
+ sessionLog(sessionId, `historian scheduling skipped: ${String(error)}`);
44134
+ } finally {
44135
+ guardSqliteTransformPass({
44136
+ assert: budget.assertOutcome,
44137
+ remainingMs: budget.remainingOutcome
44138
+ });
44139
+ }
43089
44140
  }
43090
44141
  logTransformTiming(sessionId, "historianScheduling", tHistorianScheduling);
43091
44142
  const tPostTransform = performance.now();
@@ -43120,9 +44171,15 @@ function registerPiContextHandler(pi, baseOptions) {
43120
44171
  }
43121
44172
  logTransformTiming(sessionId, "storedHintReplay", tStoredHintReplay);
43122
44173
  const tAutoSearch = performance.now();
43123
- if (options.autoSearch?.enabled && !options.compactionOff) {
44174
+ budget.stage = "auto-search";
44175
+ if (options.autoSearch?.enabled && !options.compactionOff && budget.remainingWork() > PI_CONTEXT_BUDGET.searchMs) {
44176
+ guardSqliteTransformPass({
44177
+ assert: budget.assert,
44178
+ remainingMs: () => budget.remainingWork()
44179
+ });
43124
44180
  try {
43125
- outputMessages = await runAutoSearchHintForPi({
44181
+ outputMessages = await guardAwait(runAutoSearchHintForPi({
44182
+ passGuard,
43126
44183
  sessionId,
43127
44184
  db: options.db,
43128
44185
  messages: outputMessages,
@@ -43137,9 +44194,15 @@ function registerPiContextHandler(pi, baseOptions) {
43137
44194
  visibleMemoryIds: getVisibleMemoryIds(options.db, sessionId) ?? null,
43138
44195
  wordRules: cavemanWordRulesForLanguage(options.language)
43139
44196
  }
43140
- });
44197
+ }));
43141
44198
  } catch (err) {
44199
+ assertCurrentPass();
43142
44200
  sessionLog(sessionId, `auto-search failed: ${err instanceof Error ? err.message : String(err)}`);
44201
+ } finally {
44202
+ guardSqliteTransformPass({
44203
+ assert: budget.assertOutcome,
44204
+ remainingMs: budget.remainingOutcome
44205
+ });
43143
44206
  }
43144
44207
  }
43145
44208
  logTransformTiming(sessionId, "autoSearch", tAutoSearch);
@@ -43287,6 +44350,7 @@ function registerPiContextHandler(pi, baseOptions) {
43287
44350
  }
43288
44351
  logTransformTiming(sessionId, "channelNudgeAccounting", tChannelAccounting);
43289
44352
  const tWorkMetrics = performance.now();
44353
+ budget.stage = "bookkeeping";
43290
44354
  try {
43291
44355
  const metrics = computePiWorkMetrics(outputMessages);
43292
44356
  setSessionWorkMetrics(options.db, sessionId, metrics.newWorkTokens, metrics.totalInputTokens);
@@ -43336,19 +44400,27 @@ function registerPiContextHandler(pi, baseOptions) {
43336
44400
  sessionLog(sessionId, `transform completed in ${transformElapsedMs.toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
43337
44401
  runPiDebugAssertion(assertTailHygieneLastWriter);
43338
44402
  if (!options.compactionOff && (result.executedWorkThisPass || isCacheBusting || schedulerDecision === "execute")) {
43339
- const envelope = readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(options.db, sessionId));
44403
+ const envelope = readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(options.db, sessionId), toolWireSchema);
43340
44404
  const estimate = estimatePiOutgoingInputTokens(outputMessages, envelope, lkgPassSnapshot ? lkgCoordinator.measureOutgoingPrefix(lkgPassSnapshot, outputMessages, (id) => ctx.sessionManager.getEntry?.(id)?.parentId) : undefined, rawFallbackLimit);
43341
44405
  const refusal = outgoingContextRefusal(estimate, rawFallbackLimit, protectedToolTokenCount(getActiveTagsBySession(options.db, sessionId), options.protectedTools, envelope ? calibrationForModelKey(envelope.modelKey) : undefined));
43342
44406
  if (refusal)
43343
44407
  throw contextRefusalError(refusal);
43344
44408
  }
43345
44409
  let serializedOutput;
43346
- if (!lkgCompactionOff && lkgPassSnapshot) {
44410
+ budget.stage = "LKG/served publication";
44411
+ budget.assertOutcome();
44412
+ guardSqliteTransformPass({
44413
+ assert: budget.assertOutcome,
44414
+ remainingMs: () => Math.max(0, PI_CONTEXT_BUDGET.outcomeMs - budget.elapsed())
44415
+ });
44416
+ if (!budget.sideTurn && !lkgCompactionOff && lkgPassSnapshot) {
43347
44417
  let hostEnvelopeSignature;
43348
44418
  try {
43349
- hostEnvelopeSignature = readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionId))?.envelopeSignature;
44419
+ hostEnvelopeSignature = readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionId), toolWireSchema)?.envelopeSignature;
43350
44420
  } catch {}
44421
+ budget.assertOutcome();
43351
44422
  serializedOutput = lkgCoordinator.captureAppliedPass({
44423
+ assertCurrentPass: budget.assertOutcome,
43352
44424
  hostEnvelopeSignature,
43353
44425
  snapshot: lkgPassSnapshot,
43354
44426
  outputMessages,
@@ -43356,8 +44428,15 @@ function registerPiContextHandler(pi, baseOptions) {
43356
44428
  cacheBusting: result.bustedThisPass
43357
44429
  });
43358
44430
  }
43359
- capturePiServedArray(sessionId, outputMessages, { serializedOutput });
43360
- captureOpencodeReasoningBudgetStatus(sessionId, piReasoningStatusMessages(outputMessages), resolveKeepReasoningTokens(options.heuristics?.keepReasoningTokens, resolvePiContextModelKey(ctx)), isPrefixBoundThinkingModel(ctx.model?.provider, ctx.model?.id), sessionDecisionCalibration(options.db, sessionId).proseRatio);
44431
+ budget.assertOutcome();
44432
+ if (!budget.sideTurn)
44433
+ capturePiServedArray(sessionId, outputMessages, {
44434
+ servedTagNumbers: result.servedTagNumbers,
44435
+ serializedOutput,
44436
+ assertCurrentPass: budget.assertOutcome
44437
+ });
44438
+ if (!budget.sideTurn)
44439
+ captureOpencodeReasoningBudgetStatus(sessionId, piReasoningStatusMessages(outputMessages), resolveKeepReasoningTokens(options.heuristics?.keepReasoningTokens, resolvePiContextModelKey(ctx)), isPrefixBoundThinkingModel(ctx.model?.provider, ctx.model?.id), sessionDecisionCalibration(options.db, sessionId).proseRatio);
43361
44440
  if (thinkingBindingRecoveryApplied) {
43362
44441
  try {
43363
44442
  clearThinkingBindingRecoveryIf(options.db, sessionId, thinkingBindingRecoveryApplied.flagTarget);
@@ -43365,14 +44444,34 @@ function registerPiContextHandler(pi, baseOptions) {
43365
44444
  sessionLog(sessionId, `thinking binding recovery cleanup deferred: ${error instanceof Error ? error.message : String(error)}`);
43366
44445
  }
43367
44446
  }
44447
+ budget.assertOutcome();
44448
+ publishTransformDecision?.();
43368
44449
  return { messages: outputMessages };
43369
44450
  } catch (err) {
44451
+ budget.assertOutcome();
44452
+ budget.stage = "recovery";
44453
+ if (err instanceof PiServedIdentityError) {
44454
+ if (sessionIdForError)
44455
+ clearPiLkgSessionState(sessionIdForError);
44456
+ throw new PiStorageBusyError({ cause: err });
44457
+ }
44458
+ if (err instanceof PiLkgAdmissionReplay && sessionIdForError) {
44459
+ budget.assertOutcome();
44460
+ if (!budget.sideTurn)
44461
+ capturePiServedArray(sessionIdForError, err.messages, {
44462
+ assertCurrentPass: budget.assertOutcome
44463
+ });
44464
+ budget.assertOutcome();
44465
+ budget.recovery = "fitting LKG before writer retries";
44466
+ return { messages: err.messages };
44467
+ }
43370
44468
  if ((isFailClosedBlockingError(err) || err instanceof EmergencyFailClosedError) && !baseOptions.compactionOff)
43371
44469
  throw err;
43372
44470
  if (!lkgCompactionOff && sessionIdForError && isProviderOverflowFailClosedProven(sessionIdForError)) {
43373
44471
  throw new EmergencyFailClosedError("Emergency recovery transform failed; refusing an unbounded raw fallback", { cause: err });
43374
44472
  }
43375
44473
  const message = err instanceof Error ? err.message : String(err);
44474
+ budget.failureReason = message;
43376
44475
  const stack = err instanceof Error ? err.stack : undefined;
43377
44476
  const transientStorageFailure = isTransientPiStorageError(err);
43378
44477
  const degradedPass = !lkgCompactionOff;
@@ -43385,14 +44484,21 @@ function registerPiContextHandler(pi, baseOptions) {
43385
44484
  assertPiRawFallbackFits(replay.messages, rawFallbackLimit, (line) => {
43386
44485
  if (sessionIdForError)
43387
44486
  logPiLkgRecovery(sessionIdForError, line);
43388
- }, err, readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionIdForError)), replay.measuredPrefix);
44487
+ }, err, readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionIdForError), toolWireSchema), replay.measuredPrefix);
43389
44488
  const reason = piStorageErrorReason(err);
43390
44489
  logPiLkgRecovery(sessionIdForError, `${failureLabel} ${reason}: LKG replay served ${replay.messages.length} messages instead of raw ${rawMessageCount}`);
43391
- capturePiServedArray(sessionIdForError, replay.messages);
44490
+ budget.assertOutcome();
44491
+ if (!budget.sideTurn)
44492
+ capturePiServedArray(sessionIdForError, replay.messages, {
44493
+ assertCurrentPass: budget.assertOutcome
44494
+ });
44495
+ budget.assertOutcome();
44496
+ budget.recovery = "fitting LKG replay";
43392
44497
  return { messages: replay.messages };
43393
44498
  }
43394
44499
  logPiLkgRecovery(sessionIdForError, `${failureLabel} ${piStorageErrorReason(err)}: LKG unavailable (${replay.reason}); refusing unreduced ${rawMessageCount}-message input`);
43395
44500
  } catch (replayError) {
44501
+ budget.assertOutcome();
43396
44502
  if (replayError instanceof PiStorageBusyError)
43397
44503
  throw replayError;
43398
44504
  logPiLkgRecovery(sessionIdForError, `${failureLabel} ${piStorageErrorReason(err)}: LKG replay unavailable (${replayError instanceof Error ? replayError.message : String(replayError)}); refusing unreduced ${rawMessageCount}-message input`);
@@ -43403,9 +44509,6 @@ function registerPiContextHandler(pi, baseOptions) {
43403
44509
  }
43404
44510
  if (transientStorageFailure)
43405
44511
  throw new PiStorageBusyError({ cause: err });
43406
- if (sessionIdForError && !transientStorageFailure) {
43407
- persistLastTransformErrorIfChanged(baseOptions.db, sessionIdForError, summarizeTransformError(err), sessionMetaForPass?.lastTransformError);
43408
- }
43409
44512
  if (!lkgCompactionOff && sessionIdForError) {
43410
44513
  throw new PiStorageBusyError({
43411
44514
  cause: err instanceof PiDegradedPassError ? err : new PiDegradedPassError("context-handler-failed", {
@@ -43416,6 +44519,23 @@ function registerPiContextHandler(pi, baseOptions) {
43416
44519
  log(`[magic-context][pi] context handler failed (continuing without mutation): ${message}`, stack);
43417
44520
  return;
43418
44521
  }
44522
+ };
44523
+ registerPiGuardedContext(pi, contextHandler, {
44524
+ compactionOff: (ctx) => (baseOptions.resolveForProject?.(ctx.cwd) ?? baseOptions).compactionOff === true,
44525
+ onRefusal: (ctx, budget, message, isCurrent) => {
44526
+ const sessionId = resolveSessionId2(ctx);
44527
+ if (!sessionId)
44528
+ return;
44529
+ withoutSqliteTransformPass(() => setImmediate(() => {
44530
+ if (!isCurrent())
44531
+ return;
44532
+ try {
44533
+ withSqliteBackgroundWriter(() => persistLastTransformErrorIfChanged(baseOptions.db, sessionId, budget.failureReason ?? message));
44534
+ } catch (error) {
44535
+ log(`[magic-context][pi] refused-turn diagnostic not persisted ${budget.diagnostic()}`, error);
44536
+ }
44537
+ }));
44538
+ }
43419
44539
  });
43420
44540
  log("[magic-context][pi] registered context handler (tagging + drops + nudges)");
43421
44541
  }
@@ -43609,12 +44729,15 @@ function spawnPiHistorianRun(args) {
43609
44729
  currentContextLimit,
43610
44730
  fallbackModelId
43611
44731
  } = args;
44732
+ args.startGuard?.();
43612
44733
  const holderId = crypto3.randomUUID();
43613
44734
  const controller = new AbortController;
43614
44735
  historianAbortControllers.set(sessionId, controller);
43615
- const runPromise = (async () => {
44736
+ const runPromise = withoutSqliteTransformPass(() => (async () => {
44737
+ await new Promise((resolve) => setTimeout(resolve, 0));
43616
44738
  if (controller.signal.aborted)
43617
44739
  return;
44740
+ args.startGuard?.();
43618
44741
  const lease = acquireCompartmentLease(db, sessionId, holderId);
43619
44742
  if (!lease) {
43620
44743
  sessionLog(sessionId, "historian skipped: compartment lease held by another process");
@@ -43627,6 +44750,9 @@ function spawnPiHistorianRun(args) {
43627
44750
  }
43628
44751
  const renewal = startPiCompartmentLeaseRenewal(db, sessionId, holderId);
43629
44752
  try {
44753
+ const runBoundary = typeof boundarySnapshot === "function" ? boundarySnapshot() : boundarySnapshot;
44754
+ if (!runBoundary)
44755
+ return;
43630
44756
  await runPiHistorian({
43631
44757
  db,
43632
44758
  sessionId,
@@ -43654,7 +44780,7 @@ function spawnPiHistorianRun(args) {
43654
44780
  const window = ctx.modelRegistry?.find(model.slice(0, slash), model.slice(slash + 1))?.contextWindow;
43655
44781
  return isSaneLimit(window) ? window : undefined;
43656
44782
  },
43657
- boundarySnapshot,
44783
+ boundarySnapshot: runBoundary,
43658
44784
  refreshBoundarySnapshot,
43659
44785
  currentContextLimit,
43660
44786
  historianTimeoutMs: historian.timeoutMs,
@@ -43713,7 +44839,7 @@ function spawnPiHistorianRun(args) {
43713
44839
  } catch (error) {
43714
44840
  sessionLog(sessionId, `pi historian finalizer failed: ${error instanceof Error ? error.message : String(error)}`);
43715
44841
  }
43716
- });
44842
+ }));
43717
44843
  inFlightHistorian.set(sessionId, runPromise);
43718
44844
  historian.onStatusChange?.(ctx, sessionId);
43719
44845
  }
@@ -43723,6 +44849,13 @@ function resolvePiAppendCompaction(ctx) {
43723
44849
  return;
43724
44850
  return sm.appendCompaction.bind(sm);
43725
44851
  }
44852
+ function guardedPiAppendCompaction(ctx, assertCurrentPass) {
44853
+ const append = resolvePiAppendCompaction(ctx);
44854
+ return append ? (...args) => {
44855
+ assertCurrentPass();
44856
+ return append(...args);
44857
+ } : undefined;
44858
+ }
43726
44859
  function resolvePiReadBranchEntries(ctx) {
43727
44860
  const sm = ctx.sessionManager;
43728
44861
  if (typeof sm?.getBranch !== "function")
@@ -43821,7 +44954,6 @@ function maybeFireHistorian(args) {
43821
44954
  readMessages: () => readPiSessionMessages(ctx),
43822
44955
  readMessagePage: (afterOrdinal, limit, finalWatermark) => readPiSessionMessagePage(ctx, afterOrdinal, limit, finalWatermark)
43823
44956
  };
43824
- const unregister = setRawMessageProvider2(sessionId, provider);
43825
44957
  const modelKey = liveModelBySession.get(sessionId);
43826
44958
  const triggerInputs = resolvePiHistorianTriggerInputs({
43827
44959
  db,
@@ -43832,6 +44964,20 @@ function maybeFireHistorian(args) {
43832
44964
  });
43833
44965
  const historianForceMaterializationPercentage = escalationBands(triggerInputs.executeThresholdPercentage).forceMaterializationPercentage;
43834
44966
  const boundaryContextLimit = triggerInputs.contextLimit;
44967
+ if (isHistorianDrainBudgetSpent({
44968
+ db,
44969
+ sessionId,
44970
+ contextLimit: boundaryContextLimit,
44971
+ executeThresholdPercentage: triggerInputs.executeThresholdPercentage,
44972
+ usagePercentage: usage.percentage
44973
+ })) {
44974
+ if (sessionMeta.compartmentInProgress) {
44975
+ updateSessionMeta(db, sessionId, { compartmentInProgress: false });
44976
+ sessionMeta.compartmentInProgress = false;
44977
+ }
44978
+ return;
44979
+ }
44980
+ const unregister = setRawMessageProvider2(sessionId, provider);
43835
44981
  const resolvePiBoundarySnapshot = (emergencyTailScale) => resolveProtectedTailBoundary(resolveBoundaryContext({
43836
44982
  db,
43837
44983
  sessionId,
@@ -43863,16 +45009,19 @@ function maybeFireHistorian(args) {
43863
45009
  }
43864
45010
  const failureCount = historianStateSnapshot.historianFailureCount;
43865
45011
  if (failureCount > 0) {
43866
- boundarySnapshot = resolveRunnablePiBoundarySnapshot();
43867
- }
43868
- const shouldRecoverOnFirstPass = failureCount > 0 && boundarySnapshot !== undefined && hasEligiblePiCompartmentHistory(db, sessionId, boundarySnapshot);
43869
- if (shouldRecoverOnFirstPass) {
43870
45012
  triggered = true;
43871
- sessionLog(sessionId, `historian recovery triggered on session load after ${failureCount} failure(s)`);
43872
- sendPiIgnoredNotification(ctx, `## Historian recovery
45013
+ const prepareRecoveryBoundary = () => {
45014
+ const snapshot = resolveRunnablePiBoundarySnapshot();
45015
+ if (!hasEligiblePiCompartmentHistory(db, sessionId, snapshot))
45016
+ return;
45017
+ sessionLog(sessionId, `historian recovery triggered on session load after ${failureCount} failure(s)`);
45018
+ sendPiIgnoredNotification(ctx, `## Historian recovery
43873
45019
 
43874
45020
  Historian previously failed ${failureCount} time(s), so Magic Context is retrying history comparting immediately after restart.`);
45021
+ return snapshot;
45022
+ };
43875
45023
  spawnPiHistorianRun({
45024
+ startGuard: args.startGuard,
43876
45025
  pi: args.pi,
43877
45026
  ctx,
43878
45027
  sessionId,
@@ -43880,7 +45029,7 @@ Historian previously failed ${failureCount} time(s), so Magic Context is retryin
43880
45029
  historian,
43881
45030
  provider,
43882
45031
  unregister,
43883
- boundarySnapshot,
45032
+ boundarySnapshot: prepareRecoveryBoundary,
43884
45033
  refreshBoundarySnapshot: resolveRunnablePiBoundarySnapshot,
43885
45034
  currentContextLimit: boundaryContextLimit,
43886
45035
  fallbackModelId: modelKey
@@ -43915,6 +45064,7 @@ Historian previously failed ${failureCount} time(s), so Magic Context is retryin
43915
45064
  triggered = true;
43916
45065
  sessionLog(sessionId, `historian trigger fired (reason=${trigger.reason ?? "unknown"}) usage=${usage.percentage.toFixed(1)}% — spawning subagent`);
43917
45066
  spawnPiHistorianRun({
45067
+ startGuard: args.startGuard,
43918
45068
  pi: args.pi,
43919
45069
  ctx,
43920
45070
  sessionId,
@@ -44034,6 +45184,7 @@ async function runCompactionOffPipeline(args) {
44034
45184
  };
44035
45185
  }
44036
45186
  async function runPipeline(args) {
45187
+ args.assertCurrentPass?.();
44037
45188
  if (args.compactionOff)
44038
45189
  return runCompactionOffPipeline(args);
44039
45190
  const activeThinkingTurn = hasActiveAnthropicThinkingTurn(args.messages, args.resolvedProviderID, args.resolvedModelID);
@@ -44273,12 +45424,22 @@ async function runPipeline(args) {
44273
45424
  let protectionFloorResolution = resolveProtectionFloor();
44274
45425
  const shouldRunHeuristics = args.heuristics !== undefined && isCacheBustingPass && (rideSignals.publishedHistory || args.forceMaterialization === true || hasPendingMaterializeSignal || deferredMaterializeEligible || foldBustsServedPrefixThisPass || firstRenderBust || rideSignals.subagentExecute || args.schedulerDecision === "execute" && !alreadyRanHeuristicsThisTurn);
44275
45426
  const tFallbackIdentity = performance.now();
45427
+ const preflightRevision = readPiAdoptionRevision(args.db);
44276
45428
  const hasFallbackMessageTags = hasPiFallbackMessageTags2(args.db, args.sessionId);
44277
- const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, hasFallbackMessageTags);
45429
+ const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, hasFallbackMessageTags, hasFallbackMessageTags ? readPiFallbackFingerprintHeaders(args.db, args.sessionId) : undefined);
45430
+ args.assertCurrentPass?.();
44278
45431
  adoptPiFallbackTags(args.db, args.sessionId, args.tagger, entryFingerprintByMessageId, {
44279
45432
  messages: args.messages,
44280
45433
  resolveStableId: stableIdResolver,
44281
- hasFallbackMessageTags
45434
+ hasFallbackMessageTags,
45435
+ preflightRevision,
45436
+ rebuildFingerprints: args.reusableMessageIds?.size ? () => {
45437
+ args.assertCurrentPass?.();
45438
+ const full = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, true, readPiFallbackFingerprintHeaders(args.db, args.sessionId));
45439
+ for (const [id, fingerprint] of full)
45440
+ entryFingerprintByMessageId.set(id, fingerprint);
45441
+ return entryFingerprintByMessageId;
45442
+ } : undefined
44282
45443
  });
44283
45444
  logTransformTiming(args.sessionId, "fallbackIdentityAndAdoption", tFallbackIdentity);
44284
45445
  afterFallbackAdoptionForTests?.(args.stableIdSchemeCutover === true);
@@ -44294,22 +45455,25 @@ async function runPipeline(args) {
44294
45455
  tagToolTokenCache = new Map;
44295
45456
  piTagToolTokenCacheBySession.set(args.sessionId, tagToolTokenCache);
44296
45457
  }
44297
- const { targets } = runPersistedReplayStage("tagging-persistence-failure", () => args.tagger.cleanup(args.sessionId), () => tagTranscript(args.sessionId, transcript, args.tagger, args.db, {
44298
- skipPrefixInjection: !ctxReduceCallable,
44299
- entryFingerprintByMessageId,
44300
- reuseMessageIds: textIdentityPlan.reusableMessageIds,
44301
- textIdentityDriftMessageIds: textIdentityPlan.driftedMessageIds,
44302
- textIdentitySourceCache: textIdentityPlan.sourceCache,
44303
- textTokenCache: tagTextTokenCache,
44304
- toolTokenCache: tagToolTokenCache,
44305
- onTiming: hasPiTransformTimingObserver() ? (phase, elapsedMs) => {
44306
- recordPiTransformTiming({
44307
- sessionId: args.sessionId,
44308
- stage: `tag:${phase}`,
44309
- elapsedMs
44310
- });
44311
- } : undefined
44312
- }));
45458
+ const { targets } = runPersistedReplayStage("tagging-persistence-failure", () => args.tagger.cleanup(args.sessionId), () => {
45459
+ args.assertCurrentPass?.();
45460
+ return tagTranscript(args.sessionId, transcript, args.tagger, args.db, {
45461
+ skipPrefixInjection: !ctxReduceCallable,
45462
+ entryFingerprintByMessageId,
45463
+ reuseMessageIds: textIdentityPlan.reusableMessageIds,
45464
+ textIdentityDriftMessageIds: textIdentityPlan.driftedMessageIds,
45465
+ textIdentitySourceCache: textIdentityPlan.sourceCache,
45466
+ textTokenCache: tagTextTokenCache,
45467
+ toolTokenCache: tagToolTokenCache,
45468
+ onTiming: hasPiTransformTimingObserver() ? (phase, elapsedMs) => {
45469
+ recordPiTransformTiming({
45470
+ sessionId: args.sessionId,
45471
+ stage: `tag:${phase}`,
45472
+ elapsedMs
45473
+ });
45474
+ } : undefined
45475
+ });
45476
+ });
44313
45477
  logTransformTiming(args.sessionId, "tagMessages", tTag);
44314
45478
  if (foldBustsServedPrefixThisPass) {
44315
45479
  try {
@@ -44815,6 +45979,7 @@ async function runPipeline(args) {
44815
45979
  let preserveDeferredMaterializationForMarkerDrain = false;
44816
45980
  if (deferredHistoryDrainEligible) {
44817
45981
  try {
45982
+ args.assertCurrentPass?.();
44818
45983
  const pending = getPendingPiCompactionMarkerState(args.db, args.sessionId);
44819
45984
  if (!pending) {
44820
45985
  if (injectionResult?.contentionExhausted === true) {
@@ -44835,6 +46000,7 @@ async function runPipeline(args) {
44835
46000
  preserveDeferredMaterializationForMarkerDrain = true;
44836
46001
  sessionLog(args.sessionId, "Pi compaction-marker drain skipped: sessionManager appendCompaction/getBranch or folding system state unavailable; preserving deferred signals");
44837
46002
  } else {
46003
+ args.assertCurrentPass?.();
44838
46004
  const outcome = applyDeferredPiCompactionMarker({
44839
46005
  db: args.db,
44840
46006
  appendCompaction: args.appendCompaction,
@@ -44877,6 +46043,7 @@ async function runPipeline(args) {
44877
46043
  }
44878
46044
  }
44879
46045
  } catch (err) {
46046
+ args.assertCurrentPass?.();
44880
46047
  sessionLog(args.sessionId, `Pi compaction-marker drain failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
44881
46048
  }
44882
46049
  }
@@ -44959,8 +46126,21 @@ async function runPipeline(args) {
44959
46126
  if (bustedThisPass || isCacheBustingPass) {
44960
46127
  droppedTokens = estimateDroppedTokensFromTagReductions(args.db, args.sessionId, droppedTokenReductions);
44961
46128
  }
46129
+ const visibleCallIds = new Set;
46130
+ for (const message of outputMessages) {
46131
+ if (message.role === "toolResult")
46132
+ visibleCallIds.add(message.toolCallId);
46133
+ if (message.role === "assistant" && Array.isArray(message.content)) {
46134
+ for (const part of message.content) {
46135
+ if (part.type === "toolCall")
46136
+ visibleCallIds.add(part.id);
46137
+ }
46138
+ }
46139
+ }
46140
+ const servedTagNumbers = new Set(allTagsForPass.filter((tag) => targets.has(tag.tagNumber) && (tag.type === "message" ? ctxReduceCallable || tag.status !== "active" : tag.type === "tool" && visibleCallIds.has(tag.messageId) && (ctxReduceCallable || tag.status !== "active"))).map((tag) => tag.tagNumber));
44962
46141
  return {
44963
46142
  messages: outputMessages,
46143
+ servedTagNumbers,
44964
46144
  heuristicsExecuted,
44965
46145
  executedWorkThisPass,
44966
46146
  historyInjected: injectionResult?.injected ?? false,
@@ -45170,6 +46350,8 @@ function clearContextHandlerSession(sessionId) {
45170
46350
  deferredHistoryRefreshSessions.delete(sessionId);
45171
46351
  deferredMaterializationSessions.delete(sessionId);
45172
46352
  firstContextPassSeenBySession.delete(sessionId);
46353
+ contextPassGeneration.delete(sessionId);
46354
+ clearPiContextReceipt(sessionId);
45173
46355
  liveModelBySession.delete(sessionId);
45174
46356
  latestAssistantModelTimestampBySession.delete(sessionId);
45175
46357
  taggedStableMessageIdsBySession.delete(sessionId);
@@ -45183,6 +46365,7 @@ function clearContextHandlerSession(sessionId) {
45183
46365
  piTagToolTokenCacheBySession.delete(sessionId);
45184
46366
  piTextIdentitySourceCacheBySession.delete(sessionId);
45185
46367
  piBranchProjectionBySession.delete(sessionId);
46368
+ piAlignmentMismatchLoggedSessions.delete(sessionId);
45186
46369
  clearPiInjectionTokenCountCache(sessionId);
45187
46370
  clearPiTailHygieneContentMemo();
45188
46371
  clearPiChannel1State(sessionId);
@@ -45190,6 +46373,7 @@ function clearContextHandlerSession(sessionId) {
45190
46373
  routinePressureAppliedBySession.delete(sessionId);
45191
46374
  lastSeenProjectIdentityBySession.delete(sessionId);
45192
46375
  persistedProjectIdentityBySession.delete(sessionId);
46376
+ sessionProjectBindingFailureLogAtBySession.delete(sessionId);
45193
46377
  for (const [projectIdentity, sessions] of sessionsByProject) {
45194
46378
  sessions.delete(sessionId);
45195
46379
  if (sessions.size === 0)
@@ -48692,7 +49876,7 @@ function buildStatusViewFor(check, options) {
48692
49876
  // package.json
48693
49877
  var package_default = {
48694
49878
  name: "@retaw106/mmc-pi",
48695
- version: "2.0.0",
49879
+ version: "2.1.1",
48696
49880
  type: "module",
48697
49881
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
48698
49882
  main: "dist/index.js",
@@ -50525,17 +51709,17 @@ async function bootPiRuntimeWithDeadline(args) {
50525
51709
  }
50526
51710
 
50527
51711
  // src/pi-session-api.ts
50528
- import { existsSync as existsSync13, readFileSync as readFileSync13, realpathSync as realpathSync3, statSync as statSync6 } from "node:fs";
51712
+ import { existsSync as existsSync13, readFileSync as readFileSync14, realpathSync as realpathSync3, statSync as statSync7 } from "node:fs";
50529
51713
  import {
50530
51714
  basename as basename2,
50531
51715
  dirname as dirname7,
50532
51716
  extname,
50533
51717
  join as join12,
50534
51718
  relative,
50535
- resolve as resolve6,
51719
+ resolve as resolve7,
50536
51720
  sep
50537
51721
  } from "node:path";
50538
- import { pathToFileURL } from "node:url";
51722
+ import { pathToFileURL as pathToFileURL3 } from "node:url";
50539
51723
  var PI_CODING_AGENT_MODULE = "@earendil-works/pi-coding-agent";
50540
51724
  var CODING_AGENT_MODULES = [PI_CODING_AGENT_MODULE];
50541
51725
  var CODING_AGENT_MODULE_LABEL = CODING_AGENT_MODULES.join(" or ");
@@ -50550,7 +51734,7 @@ function isScriptEntry(filePath) {
50550
51734
  }
50551
51735
  function readManifest(pkgJsonPath) {
50552
51736
  try {
50553
- const pkg = JSON.parse(readFileSync13(pkgJsonPath, "utf8"));
51737
+ const pkg = JSON.parse(readFileSync14(pkgJsonPath, "utf8"));
50554
51738
  return pkg && typeof pkg === "object" ? pkg : null;
50555
51739
  } catch {
50556
51740
  return null;
@@ -50565,7 +51749,7 @@ function isCompiledBunBinary() {
50565
51749
  }
50566
51750
  function resolveRunningEntry() {
50567
51751
  const argv1 = process.argv[1];
50568
- if (argv1 && existsSync13(argv1) && statSync6(argv1).isFile()) {
51752
+ if (argv1 && existsSync13(argv1) && statSync7(argv1).isFile()) {
50569
51753
  const real = realpathSync3(argv1);
50570
51754
  if (isScriptEntry(real)) {
50571
51755
  return real;
@@ -50626,8 +51810,8 @@ function resolveManifestEntry(found) {
50626
51810
  if (!entryRel.startsWith("./")) {
50627
51811
  throw new Error(`Invalid entry "${entryRel}" in ${found.dir}/package.json: targets must start with "./"`);
50628
51812
  }
50629
- const root = resolve6(found.dir);
50630
- const resolved = resolve6(root, entryRel);
51813
+ const root = resolve7(found.dir);
51814
+ const resolved = resolve7(root, entryRel);
50631
51815
  if (resolved !== root && !resolved.startsWith(root + sep)) {
50632
51816
  throw new Error(`Invalid entry "${entryRel}" in ${found.dir}/package.json: target escapes the package root`);
50633
51817
  }
@@ -50660,14 +51844,14 @@ var defaultLoaders = [
50660
51844
  if (TS_ENTRY_PATTERN.test(entry)) {
50661
51845
  const srcEntry = toSourceEntry(entryPath, found.dir);
50662
51846
  if (!srcEntry && TS_ENTRY_PATTERN.test(entryPath) && existsSync13(entryPath)) {
50663
- return await import(pathToFileURL(entryPath).href);
51847
+ return await import(pathToFileURL3(entryPath).href);
50664
51848
  }
50665
51849
  if (srcEntry && existsSync13(srcEntry)) {
50666
- return await import(pathToFileURL(srcEntry).href);
51850
+ return await import(pathToFileURL3(srcEntry).href);
50667
51851
  }
50668
51852
  throw new Error(`Pi is running from TypeScript source (${entry}) but no source counterpart of ${entryPath} exists; refusing to load possibly stale build output`);
50669
51853
  }
50670
- return await import(pathToFileURL(entryPath).href);
51854
+ return await import(pathToFileURL3(entryPath).href);
50671
51855
  }
50672
51856
  },
50673
51857
  {
@@ -50710,7 +51894,7 @@ async function loadDefaultPiSessionApi(loaders) {
50710
51894
  throw new Error("Pi session APIs unavailable: expected SessionManager.listAll on pi-coding-agent");
50711
51895
  }
50712
51896
  const loadEntriesFromFile = mod.loadEntriesFromFile ?? ((filePath) => {
50713
- const content = readFileSync13(filePath, "utf8");
51897
+ const content = readFileSync14(filePath, "utf8");
50714
51898
  return mod.parseSessionEntries?.(content) ?? [];
50715
51899
  });
50716
51900
  return {
@@ -50747,10 +51931,10 @@ import * as childProcess from "node:child_process";
50747
51931
  import {
50748
51932
  existsSync as existsSync14,
50749
51933
  mkdtempSync,
50750
- readFileSync as readFileSync14,
51934
+ readFileSync as readFileSync15,
50751
51935
  realpathSync as realpathSync4,
50752
51936
  rmSync as rmSync2,
50753
- statSync as statSync7,
51937
+ statSync as statSync8,
50754
51938
  writeFileSync as writeFileSync4
50755
51939
  } from "node:fs";
50756
51940
  import { createRequire } from "node:module";
@@ -50758,7 +51942,7 @@ import { homedir as homedir5, tmpdir } from "node:os";
50758
51942
  import {
50759
51943
  basename as basename3,
50760
51944
  dirname as dirname8,
50761
- isAbsolute as isAbsolute3,
51945
+ isAbsolute as isAbsolute4,
50762
51946
  join as join13,
50763
51947
  resolve as resolvePath,
50764
51948
  sep as sep2
@@ -50772,9 +51956,9 @@ var BUN_VIRTUAL_SCRIPT_PREFIX = "/$bunfs/root/";
50772
51956
  var WINDOWS_PI_EXTENSIONS = [".EXE", ".COM", ".CMD", ".BAT", ".PS1"];
50773
51957
  var DEFAULT_PI_RESOLUTION_FS = {
50774
51958
  existsSync: existsSync14,
50775
- statSync: statSync7,
51959
+ statSync: statSync8,
50776
51960
  realpathSync: realpathSync4,
50777
- readFileSync: readFileSync14
51961
+ readFileSync: readFileSync15
50778
51962
  };
50779
51963
  function packageHarnessKind(packageName) {
50780
51964
  return typeof packageName === "string" && PI_CODING_AGENT_PACKAGE_NAMES.has(packageName) ? "pi" : undefined;
@@ -50827,7 +52011,7 @@ function resolvePiBin(found, fs, checkedPaths) {
50827
52011
  const packageRoot = resolvePath(found.dir);
50828
52012
  const candidate = resolvePath(packageRoot, binEntry);
50829
52013
  checkedPaths.push(candidate);
50830
- if (isAbsolute3(binEntry) || !pathIsInside(packageRoot, candidate)) {
52014
+ if (isAbsolute4(binEntry) || !pathIsInside(packageRoot, candidate)) {
50831
52015
  return null;
50832
52016
  }
50833
52017
  try {
@@ -51046,7 +52230,7 @@ function configurePiSubagentExtensions(extensions) {
51046
52230
  function resolveSubagentExtensionEntry(entry, targetHarness) {
51047
52231
  const trimmed = entry.trim();
51048
52232
  const isNpmSource = trimmed.startsWith("npm:");
51049
- return !isNpmSource && !isAbsolute3(trimmed) ? resolvePath(getHostAgentSettingsDir(targetHarness), trimmed) : trimmed;
52233
+ return !isNpmSource && !isAbsolute4(trimmed) ? resolvePath(getHostAgentSettingsDir(targetHarness), trimmed) : trimmed;
51050
52234
  }
51051
52235
  var HISTORIAN_AGENTS = new Set([
51052
52236
  "magic-context-historian",
@@ -51857,6 +53041,19 @@ function terminateChild(child) {
51857
53041
  }
51858
53042
  }
51859
53043
 
53044
+ // src/timeout.ts
53045
+ function withTimeout(p, ms) {
53046
+ let handle;
53047
+ const timeout = new Promise((resolve) => {
53048
+ handle = setTimeout(() => resolve(undefined), ms);
53049
+ handle.unref?.();
53050
+ });
53051
+ return Promise.race([p, timeout]).finally(() => {
53052
+ if (handle)
53053
+ clearTimeout(handle);
53054
+ });
53055
+ }
53056
+
51860
53057
  // ../plugin/src/tools/parameter-descriptions.ts
51861
53058
  var FULL_PARAMETER_DESCRIPTIONS = {
51862
53059
  mmc_reduce: {
@@ -51958,7 +53155,7 @@ Returns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversiz
51958
53155
 
51959
53156
  Finer recovery:
51960
53157
  - verbose=true lists each message separately with its ordinal and a per-part preview (tool calls with output sizes) so you can pick one.
51961
- - message=N returns that one message in full — every text part and every tool call's complete input and output — from stored history. This is the way back to a tool output you released with mmc_reduce; if the message was deleted from history it says so.`;
53158
+ - message=N returns that one message in full — every text part and every tool call's complete input and output — from stored history. This is the way back to a tool output you released with mmc_reduce; if the message is no longer in stored history it says so.`;
51962
53159
  var CTX_EXPAND_TOKEN_BUDGET = 15000;
51963
53160
 
51964
53161
  // ../plugin/src/features/magic-context/tag-input.ts
@@ -52031,7 +53228,7 @@ function resolveCtxExpandMode(args, domain) {
52031
53228
  }
52032
53229
 
52033
53230
  // ../plugin/src/tools/ctx-expand/render.ts
52034
- import { createHash as createHash18 } from "node:crypto";
53231
+ import { createHash as createHash19 } from "node:crypto";
52035
53232
  function isRecord7(value) {
52036
53233
  return value !== null && typeof value === "object" && !Array.isArray(value);
52037
53234
  }
@@ -52120,7 +53317,7 @@ function reasoningOf(part) {
52120
53317
  function renderPartPreview(part, expandTools) {
52121
53318
  if (!isRecord7(part))
52122
53319
  return null;
52123
- const expansion = expandToolPart(part, expandTools);
53320
+ const expansion = expandToolPart(part, expandTools, true);
52124
53321
  if (expansion !== null)
52125
53322
  return ` • tool ${part.tool}: ${expansion}`;
52126
53323
  const text = textOf(part);
@@ -52184,7 +53381,7 @@ function renderMessageByOrdinal(sessionId, ordinal) {
52184
53381
  });
52185
53382
  const msg = found[0];
52186
53383
  if (!msg) {
52187
- return `No message at ordinal ${ordinal} in this session's stored history — it was deleted ` + `(session prune/revert) or the ordinal is wrong, so it can't be recovered. ` + `Re-run the tool if you still need the data.`;
53384
+ return `No message at ordinal ${ordinal} is currently in this session's stored history — ` + `it may have been removed by a session prune/revert, or the ordinal may be wrong. ` + `Re-run the tool if you still need the data.`;
52188
53385
  }
52189
53386
  const rendered = msg.parts.map(renderPartFull).filter((l) => l !== null);
52190
53387
  const lines = [`[${msg.ordinal}] ${roleLabel(msg.role)} — full recovery:`, ""];
@@ -52255,9 +53452,12 @@ function renderItemByTag(db, sessionId, number, textIndexDomain = "part") {
52255
53452
  const index = scoped ? Number(scoped[2]) : 0;
52256
53453
  const piText = message.parts.filter((part) => isRecord7(part) && part.type === "text");
52257
53454
  const part = message.parts[index];
52258
- const matching = derived ? piText.filter((part) => isRecord7(part) && typeof part.text === "string" && createHash18("sha256").update(part.text).digest("hex") === derived[3]) : [];
53455
+ const matching = derived ? piText.filter((part) => isRecord7(part) && typeof part.text === "string" && createHash19("sha256").update(part.text).digest("hex") === derived[3]) : [];
52259
53456
  const selected = derived ? matching[Number(derived[4])] : textIndexDomain === "text" ? piText[index] : part;
52260
- return selected ? renderPartFull(selected) ?? "" : `Tag ${number}'s original text part is no longer in stored history.`;
53457
+ if (!selected)
53458
+ return `Tag ${number}'s original text part is no longer in stored history.`;
53459
+ const renderedPart = renderPartFull(selected);
53460
+ return renderedPart !== null ? renderedPart : `Tag ${number}'s stored text part has no renderable content (empty or structural-only); the requested content was not recovered.`;
52261
53461
  }
52262
53462
 
52263
53463
  // ../plugin/src/tools/unwrap-imitated-reduced-args.ts
@@ -52741,6 +53941,9 @@ function createCtxExpandTool(deps) {
52741
53941
  }
52742
53942
  return ok(lines.join(`
52743
53943
  `));
53944
+ } catch (error) {
53945
+ const message = error instanceof Error ? error.message : String(error);
53946
+ return err(`Error: mmc_expand failed to read this session's stored history: ${message}`);
52744
53947
  } finally {
52745
53948
  unregister();
52746
53949
  }
@@ -54573,7 +55776,7 @@ function logNoProjectIdentityOnce(directory) {
54573
55776
  }
54574
55777
  var loggedPiConfigDirs = new Set;
54575
55778
  function logPiConfigLoad(args) {
54576
- const key = resolve7(args.dir);
55779
+ const key = resolve8(args.dir);
54577
55780
  if (args.dedupe && loggedPiConfigDirs.has(key))
54578
55781
  return;
54579
55782
  if (args.dedupe) {
@@ -55435,8 +56638,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
55435
56638
  existingSystemPrompt: event.systemPrompt
55436
56639
  });
55437
56640
  const composedPrompt = composeMagicContextSystemPrompt(event.systemPrompt, block);
56641
+ const promptOptions = event.systemPromptOptions;
56642
+ const hostSections = promptOptions?.sections;
56643
+ if (block && hostSections) {
56644
+ hostSections.magic_context = block;
56645
+ }
55438
56646
  if (!sessionId) {
55439
- if (block)
56647
+ if (block && !hostSections)
55440
56648
  return { systemPrompt: composedPrompt };
55441
56649
  return;
55442
56650
  }
@@ -55455,6 +56663,9 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
55455
56663
  if (isCacheBusting) {
55456
56664
  clearSystemPromptRefresh(sessionId);
55457
56665
  }
56666
+ if (hostSections) {
56667
+ return;
56668
+ }
55458
56669
  return { systemPrompt: result.systemPrompt };
55459
56670
  } catch (error) {
55460
56671
  warn("failed to build magic-context block:", error);