@retaw106/mmc-pi 2.0.0 → 2.1.0

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;
@@ -34431,7 +34637,7 @@ function currentReclaimHints(db, sessionId, hints) {
34431
34637
 
34432
34638
  // src/debug-assertions-pi.ts
34433
34639
  function runPiDebugAssertion(assert) {
34434
- if (process.env.MAGIC_CONTEXT_DEBUG_ASSERTIONS === "1")
34640
+ if (process.env.MMC_DEBUG_ASSERTIONS === "1")
34435
34641
  assert?.();
34436
34642
  }
34437
34643
 
@@ -34580,9 +34786,6 @@ function probe(db, sessionId, kind) {
34580
34786
  function hasPiFallbackMessageTags2(db, sessionId) {
34581
34787
  return probe(db, sessionId, "message");
34582
34788
  }
34583
- function hasPiFallbackToolOwnerTags2(db, sessionId) {
34584
- return probe(db, sessionId, "tool");
34585
- }
34586
34789
 
34587
34790
  // src/historian-tail-pi.ts
34588
34791
  function readPiHistorianTail(db, sessionId, provider) {
@@ -34938,7 +35141,7 @@ function readCurrentMarkersFromCompartments(db, state, compartments) {
34938
35141
  };
34939
35142
  }
34940
35143
  function mustMaterializePi(state, db, currentCompartmentsOverride, passSnapshot) {
34941
- const meta = passSnapshot?.sessionMeta ?? getOrCreateSessionMeta(db, state.sessionId);
35144
+ const meta = passSnapshot?.sessionMeta ?? readSessionMeta(db, state.sessionId);
34942
35145
  if (!meta.cachedM0Bytes)
34943
35146
  return { value: true, reason: "first_render" };
34944
35147
  if (!meta.cachedM1Bytes)
@@ -35090,7 +35293,7 @@ function readFrozenM0InputsPi(state, db, memoryCutoff, compartmentsOverride) {
35090
35293
  return read.deferred();
35091
35294
  }
35092
35295
  function renderFreshM0PiNonPersisted(state, db) {
35093
- const cachedMaterializedAt = getOrCreateSessionMeta(db, state.sessionId).cachedM0MaterializedAt ?? 0;
35296
+ const cachedMaterializedAt = readSessionMeta(db, state.sessionId).cachedM0MaterializedAt ?? 0;
35094
35297
  const frozen = readFrozenM0InputsPi(state, db, cachedMaterializedAt);
35095
35298
  frozen.markers.materializedAt = cachedMaterializedAt;
35096
35299
  const historyBudget = historyLocalBudget(state.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS, piModelRefToCanonical(state.hardSignals?.modelKey ?? ""));
@@ -35359,7 +35562,7 @@ function readCachedPiM0M1Row(db, sessionId) {
35359
35562
  function createPiM0M1PassSnapshot(args) {
35360
35563
  const compartments = args.compactionOff ? [] : args.compartments ? [...args.compartments] : getCompartments(args.db, args.sessionId);
35361
35564
  return {
35362
- sessionMeta: args.sessionMeta ?? getOrCreateSessionMeta(args.db, args.sessionId),
35565
+ sessionMeta: args.sessionMeta ?? readSessionMeta(args.db, args.sessionId),
35363
35566
  compartments,
35364
35567
  cachedRow: readCachedPiM0M1Row(args.db, args.sessionId),
35365
35568
  compartmentSequence: compartments.at(-1)?.sequence ?? EMPTY_MAX_COMPARTMENT_SEQ
@@ -36060,6 +36263,83 @@ function authorizePiToolRemoval(args) {
36060
36263
  }
36061
36264
  }
36062
36265
 
36266
+ // src/pi-context-budget.ts
36267
+ var PI_CONTEXT_BUDGET = {
36268
+ hostDeadlineMs: 30000,
36269
+ hostMarginMs: 5000,
36270
+ outcomeMs: 25000,
36271
+ fallbackObservedMs: 4,
36272
+ workMs: 21000,
36273
+ writerMs: 16500,
36274
+ completionReserveMs: 2000,
36275
+ searchMs: 3000
36276
+ };
36277
+
36278
+ class PiContextDeadlineError extends Error {
36279
+ }
36280
+
36281
+ class PiContextBudget {
36282
+ startedAt;
36283
+ now;
36284
+ sideTurn = false;
36285
+ stage = "entry";
36286
+ recovery = "not attempted";
36287
+ abandoned = false;
36288
+ completed = false;
36289
+ failureReason;
36290
+ assertOwner = () => {};
36291
+ constructor(startedAt = performance.now(), now = () => performance.now()) {
36292
+ this.startedAt = startedAt;
36293
+ this.now = now;
36294
+ }
36295
+ elapsed() {
36296
+ return this.now() - this.startedAt;
36297
+ }
36298
+ remainingWork() {
36299
+ return Math.max(0, PI_CONTEXT_BUDGET.workMs - this.elapsed());
36300
+ }
36301
+ remainingOutcome = () => Math.max(0, PI_CONTEXT_BUDGET.outcomeMs - this.elapsed());
36302
+ writerAllowance() {
36303
+ return Math.max(0, Math.min(PI_CONTEXT_BUDGET.writerMs, this.remainingWork() - PI_CONTEXT_BUDGET.completionReserveMs));
36304
+ }
36305
+ assertOutcome = () => {
36306
+ this.assertOwner();
36307
+ if (this.abandoned || this.elapsed() >= PI_CONTEXT_BUDGET.outcomeMs)
36308
+ throw new PiContextDeadlineError(this.diagnostic());
36309
+ };
36310
+ assert = () => {
36311
+ this.assertOutcome();
36312
+ if (this.elapsed() >= PI_CONTEXT_BUDGET.workMs)
36313
+ throw new PiContextDeadlineError(this.diagnostic());
36314
+ };
36315
+ assertDecisionPublication = () => {
36316
+ if (!this.completed)
36317
+ this.assertOwner();
36318
+ if (this.abandoned || this.elapsed() >= PI_CONTEXT_BUDGET.outcomeMs)
36319
+ throw new PiContextDeadlineError(this.diagnostic());
36320
+ };
36321
+ diagnostic() {
36322
+ return `stage=${this.stage} elapsed=${Math.round(this.elapsed())}ms recovery=${this.recovery}`;
36323
+ }
36324
+ waitUntil = async (pending, assert, remaining) => {
36325
+ assert();
36326
+ let timer;
36327
+ try {
36328
+ return await Promise.race([
36329
+ pending,
36330
+ new Promise((_, reject) => {
36331
+ timer = setTimeout(() => reject(new PiContextDeadlineError(this.diagnostic())), remaining());
36332
+ })
36333
+ ]);
36334
+ } finally {
36335
+ clearTimeout(timer);
36336
+ assert();
36337
+ }
36338
+ };
36339
+ wait = (pending) => this.waitUntil(pending, this.assert, () => this.remainingWork());
36340
+ waitMandatory = (pending) => this.waitUntil(pending, this.assertOutcome, this.remainingOutcome);
36341
+ }
36342
+
36063
36343
  // src/pi-context-limit.ts
36064
36344
  var MIN_SANE_LIMIT2 = 16000;
36065
36345
  var MAX_SANE_LIMIT2 = 1e7;
@@ -36111,31 +36391,187 @@ function resolvePiUsableContextLimit(args) {
36111
36391
 
36112
36392
  // src/pi-context-refusal.ts
36113
36393
  import { Text as Text2 } from "@earendil-works/pi-tui";
36394
+
36395
+ // src/omp-request-kind.ts
36396
+ var SIDE_REMINDER = `<system-reminder>
36397
+ Ephemeral side-channel turn; reuses current conversation context.
36398
+ Tool catalog attached only to keep prompt cache warm; tools NOT available this turn.
36399
+ Do NOT emit tool calls; reply plain text only. Tool calls discarded without execution.
36400
+ </system-reminder>`;
36401
+ function textContainsReminder(value) {
36402
+ if (typeof value === "string")
36403
+ return value.trim() === SIDE_REMINDER;
36404
+ if (!Array.isArray(value))
36405
+ return false;
36406
+ return value.some((block) => {
36407
+ if (!block || typeof block !== "object")
36408
+ return false;
36409
+ const part = block;
36410
+ return typeof part.text === "string" && part.text.trim() === SIDE_REMINDER;
36411
+ });
36412
+ }
36413
+ function isOmpSideContext(event) {
36414
+ const tail = event.messages.at(-1);
36415
+ if (tail?.role !== "user" || tail.attribution !== "agent")
36416
+ return false;
36417
+ return event.messages.some((message) => {
36418
+ const row = message;
36419
+ return row.role === "developer" && row.attribution === "agent" && textContainsReminder(row.content);
36420
+ });
36421
+ }
36422
+
36423
+ // src/pi-context-refusal.ts
36114
36424
  var ENTRY_TYPE = "magic-context-turn-refused";
36115
36425
  var RETRY_MESSAGE = "Magic Context could not safely prepare this turn; send your message again.";
36116
- function registerPiGuardedContext(pi, handler) {
36426
+
36427
+ class PiContextSupersededError extends Error {
36428
+ }
36429
+ var receiptMaps = new Set;
36430
+ function clearPiContextReceipt(sessionId) {
36431
+ for (const receipts of receiptMaps)
36432
+ receipts.delete(sessionId);
36433
+ }
36434
+ function operationKey(ctx) {
36435
+ return ctx.sessionManager?.getSessionId?.() ?? ctx.sessionManager ?? "no-session";
36436
+ }
36437
+ function registerPiGuardedContext(pi, handler, options = {}) {
36438
+ const operations = new Map;
36439
+ const sideSessions = new Map;
36440
+ receiptMaps.add(operations);
36441
+ const newOperation = () => ({
36442
+ ready: false,
36443
+ refused: false,
36444
+ ended: false
36445
+ });
36446
+ const fenceEnabled = resolvePiHarnessKind() === "omp";
36447
+ const refuse = (ctx, budget, reason, isCurrent) => {
36448
+ if (!isCurrent()) {
36449
+ log(`[magic-context][pi] DISCARDED CONTEXT RESULT ${budget.diagnostic()}`, reason);
36450
+ return;
36451
+ }
36452
+ budget.abandoned = true;
36453
+ budget.recovery = budget.recovery === "not attempted" ? "no managed result; refused" : budget.recovery;
36454
+ const message = `${RETRY_MESSAGE} ${budget.diagnostic()} (${reason instanceof Error ? reason.message : String(reason)})`;
36455
+ try {
36456
+ ctx.ui?.notify(message, "error");
36457
+ } catch (error) {
36458
+ log("[magic-context][pi] refusal notice failed", error);
36459
+ }
36460
+ try {
36461
+ pi.appendEntry(ENTRY_TYPE, { message });
36462
+ } catch (error) {
36463
+ log("[magic-context][pi] refusal entry failed", error);
36464
+ } finally {
36465
+ if (!budget.sideTurn)
36466
+ ctx.abort();
36467
+ }
36468
+ try {
36469
+ options.onRefusal?.(ctx, budget, message, isCurrent);
36470
+ } catch (error) {
36471
+ log("[magic-context][pi] refusal diagnostic failed", error);
36472
+ }
36473
+ };
36474
+ if (fenceEnabled) {
36475
+ pi.on("agent_start", (_event, ctx) => {
36476
+ operations.set(operationKey(ctx), newOperation());
36477
+ });
36478
+ pi.on("agent_end", (_event, ctx) => {
36479
+ const key = operationKey(ctx);
36480
+ const counts = sideSessions.get(key);
36481
+ if (counts)
36482
+ 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"}`);
36483
+ const operation = operations.get(key);
36484
+ if (operation) {
36485
+ operation.ended = true;
36486
+ operation.ready = false;
36487
+ }
36488
+ });
36489
+ pi.on("before_provider_request", (_event, ctx) => {
36490
+ if (options.compactionOff?.(ctx))
36491
+ return;
36492
+ const key = operationKey(ctx);
36493
+ if (sideSessions.get(key)?.sides)
36494
+ return;
36495
+ let operation = operations.get(key);
36496
+ if (!operation) {
36497
+ operation = newOperation();
36498
+ operations.set(key, operation);
36499
+ }
36500
+ const active = operation;
36501
+ const isCurrent = () => operations.get(key) === active;
36502
+ const budget = active.pass ?? new PiContextBudget;
36503
+ try {
36504
+ budget.assertOwner();
36505
+ if (!budget.completed)
36506
+ budget.assertOutcome();
36507
+ if (!active.ready || active.refused || active.ended || budget.abandoned)
36508
+ throw new Error("missing managed context receipt");
36509
+ } catch (error) {
36510
+ active.refused = true;
36511
+ budget.stage = "provider dispatch";
36512
+ refuse(ctx, budget, error, isCurrent);
36513
+ }
36514
+ });
36515
+ }
36117
36516
  pi.registerEntryRenderer?.(ENTRY_TYPE, (entry) => new Text2(entry.data?.message ?? RETRY_MESSAGE, 0, 0));
36118
36517
  pi.on("context", async (event, ctx) => {
36518
+ const budget = new PiContextBudget;
36519
+ budget.sideTurn = fenceEnabled && isOmpSideContext(event);
36520
+ const key = operationKey(ctx);
36521
+ if (fenceEnabled) {
36522
+ let counts = sideSessions.get(key);
36523
+ if (!counts) {
36524
+ counts = { contexts: 0, sides: 0 };
36525
+ sideSessions.set(key, counts);
36526
+ }
36527
+ counts.contexts++;
36528
+ if (budget.sideTurn && ++counts.sides === 1)
36529
+ 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})`);
36530
+ }
36531
+ const owner = operations.get(key);
36532
+ let operation = operations.get(key);
36533
+ if (budget.sideTurn || !operation || !fenceEnabled) {
36534
+ operation = newOperation();
36535
+ if (!budget.sideTurn)
36536
+ operations.set(key, operation);
36537
+ }
36538
+ const active = operation;
36539
+ active.pass = budget;
36540
+ active.ready = false;
36541
+ const isOwned = () => budget.sideTurn ? operations.get(key) === owner : operations.get(key) === active && active.pass === budget;
36542
+ const isCurrent = () => isOwned() && (budget.sideTurn || !active.ended);
36543
+ budget.assertOwner = () => {
36544
+ if (!isCurrent())
36545
+ throw new PiContextSupersededError("Pi context pass superseded before writer admission");
36546
+ };
36119
36547
  try {
36120
- return await withSqliteTransformPass(() => handler(event, ctx));
36548
+ const result = await withSqliteTransformPass(() => handler(event, ctx, budget));
36549
+ budget.assertOutcome();
36550
+ if (result?.messages) {
36551
+ budget.completed = true;
36552
+ active.ready = true;
36553
+ }
36554
+ return result;
36121
36555
  } catch (error) {
36556
+ if (error instanceof PiContextSupersededError || !isCurrent()) {
36557
+ log(`[magic-context][pi] DISCARDED CONTEXT RESULT ${budget.diagnostic()}`, error);
36558
+ throw error;
36559
+ }
36122
36560
  log("[magic-context][pi] turn refused", error);
36123
- if (typeof ctx.abort !== "function")
36561
+ if (typeof ctx.abort !== "function") {
36562
+ budget.abandoned = true;
36563
+ options.onRefusal?.(ctx, budget, error instanceof Error ? error.message : String(error), isOwned);
36124
36564
  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
36565
  }
36566
+ active.refused = true;
36567
+ refuse(ctx, budget, error, isOwned);
36132
36568
  return { messages: event.messages };
36133
36569
  }
36134
36570
  });
36135
36571
  }
36136
36572
 
36137
36573
  // 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";
36574
+ import { closeSync as closeSync2, existsSync as existsSync11, openSync as openSync2, readSync as readSync2, statSync as statSync6 } from "node:fs";
36139
36575
  import { join as join9 } from "node:path";
36140
36576
 
36141
36577
  // ../plugin/src/features/magic-context/memory-maintainer/lease.ts
@@ -36966,7 +37402,7 @@ function screenAgentsCitation(item, agentsSourceText) {
36966
37402
  }
36967
37403
 
36968
37404
  // ../plugin/src/features/magic-context/memory-maintainer/provider-output-failure.ts
36969
- import { createHash as createHash12 } from "node:crypto";
37405
+ import { createHash as createHash13 } from "node:crypto";
36970
37406
  var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
36971
37407
 
36972
37408
  class DreamerProviderOutputFailureError extends Error {
@@ -37023,7 +37459,7 @@ function providerOutputFailureFromInvalidManifest2(messages, responseText) {
37023
37459
  const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
37024
37460
  if (!normalized)
37025
37461
  return null;
37026
- const fingerprint = createHash12("sha256").update(normalized).digest("hex").slice(0, 16);
37462
+ const fingerprint = createHash13("sha256").update(normalized).digest("hex").slice(0, 16);
37027
37463
  return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
37028
37464
  }
37029
37465
 
@@ -37439,7 +37875,7 @@ function readProjectAgentsBlock(directory) {
37439
37875
  try {
37440
37876
  if (!existsSync11(path))
37441
37877
  return null;
37442
- const stat = statSync5(path);
37878
+ const stat = statSync6(path);
37443
37879
  if (!stat.isFile())
37444
37880
  return null;
37445
37881
  const cap = AGENTS_BLOCK_MAX_BYTES;
@@ -37713,7 +38149,7 @@ function runPiMaintenanceFactory(deps) {
37713
38149
  }
37714
38150
 
37715
38151
  // ../plugin/src/hooks/magic-context/lkg-persist.ts
37716
- import { createHash as createHash13 } from "node:crypto";
38152
+ import { createHash as createHash14 } from "node:crypto";
37717
38153
  function parseStringArray(value) {
37718
38154
  if (typeof value !== "string")
37719
38155
  return null;
@@ -37827,7 +38263,7 @@ function rememberFingerprint(db, sessionId, fingerprint) {
37827
38263
  saved.set(sessionId, fingerprint);
37828
38264
  }
37829
38265
  function slotFingerprint(slot) {
37830
- return createHash13("sha256").update(JSON.stringify([
38266
+ return createHash14("sha256").update(JSON.stringify([
37831
38267
  slot.jsonPrefix,
37832
38268
  slot.inputIdSeq,
37833
38269
  slot.inputContentDigests,
@@ -38004,6 +38440,11 @@ function readServedTemporalDecisions(db, sessionId, runtime, messageIds) {
38004
38440
  return result;
38005
38441
  }
38006
38442
 
38443
+ // ../plugin/src/hooks/magic-context/lkg-measured-request.ts
38444
+ var requests = new BoundedSessionMap(1000);
38445
+ var claimedRequests = new WeakSet;
38446
+ var captures = new BoundedSessionMap(1000);
38447
+
38007
38448
  // ../plugin/src/hooks/magic-context/openai-compat-adjacency.ts
38008
38449
  function assertOpenAiCompatAdjacency(messages) {
38009
38450
  const violations = [];
@@ -38533,7 +38974,7 @@ function plainOutputFields(messages) {
38533
38974
  }
38534
38975
  return outputs;
38535
38976
  }
38536
- function snapshotInputs(messages, entryIds) {
38977
+ function snapshotInputs(messages, entryIds, omitsBookkeeping) {
38537
38978
  if (!entryIds || entryIds.length !== messages.length) {
38538
38979
  return { inputs: [], failure: "lkg_entry_ids_unavailable" };
38539
38980
  }
@@ -38544,7 +38985,7 @@ function snapshotInputs(messages, entryIds) {
38544
38985
  const inputs = [];
38545
38986
  const seen = new Set;
38546
38987
  for (let index = 0;index < entryIds.length; index += 1) {
38547
- const fields = lkgContentFields(messages[index]);
38988
+ const fields = lkgContentFields(omitsBookkeeping ? piProviderInput(messages[index]) : messages[index]);
38548
38989
  if (!fields)
38549
38990
  return { inputs: [], failure: "lkg_content_snapshot_failed" };
38550
38991
  const id = entryIds[index] || `pi-lkg-unmapped:${lkgContentDigestFromFields(fields)}`;
@@ -38560,6 +39001,35 @@ function snapshotInputs(messages, entryIds) {
38560
39001
  }
38561
39002
  return { inputs, failure: null };
38562
39003
  }
39004
+ var bookkeepingOmittingApis = new Set([
39005
+ "anthropic-messages",
39006
+ "google-generative-ai",
39007
+ "openai-completions",
39008
+ "openai-responses",
39009
+ "openai-codex-responses"
39010
+ ]);
39011
+ function omitsRootBookkeeping(args) {
39012
+ if (args.transport != null)
39013
+ return false;
39014
+ let api = args.apiKey;
39015
+ if (api === undefined) {
39016
+ const apis = new Set(args.messages.flatMap((message) => {
39017
+ const value = message;
39018
+ return value?.role === "assistant" && typeof value.api === "string" ? [value.api] : [];
39019
+ }));
39020
+ if (apis.size === 1)
39021
+ api = [...apis][0];
39022
+ }
39023
+ return typeof api === "string" && bookkeepingOmittingApis.has(api);
39024
+ }
39025
+ function piProviderInput(message) {
39026
+ if (!message || typeof message !== "object" || Array.isArray(message))
39027
+ return message;
39028
+ const descriptors = Object.getOwnPropertyDescriptors(message);
39029
+ delete descriptors.completedAt;
39030
+ delete descriptors.contextSnapshot;
39031
+ return Object.create(Object.getPrototypeOf(message), descriptors);
39032
+ }
38563
39033
  function extendsMeasuredRequest(measuredJson, nextJson) {
38564
39034
  return measuredJson === nextJson || measuredJson.length > 2 && nextJson.startsWith(`${measuredJson.slice(0, -1)},`);
38565
39035
  }
@@ -38580,7 +39050,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38580
39050
  return state;
38581
39051
  };
38582
39052
  const beginPass = (args) => {
38583
- const snapped = snapshotInputs(args.messages, args.entryIds);
39053
+ const snapped = snapshotInputs(args.messages, args.entryIds, omitsRootBookkeeping(args));
38584
39054
  const slot = getSlot(args.sessionId);
38585
39055
  if (snapped.failure || !slot) {
38586
39056
  return {
@@ -38734,6 +39204,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38734
39204
  return result.ok && measuredPrefix ? { ...result, measuredPrefix } : result;
38735
39205
  };
38736
39206
  const captureAppliedPass = (args) => {
39207
+ args.assertCurrentPass?.();
38737
39208
  const { snapshot } = args;
38738
39209
  if (snapshot.preparationFailure || snapshot.inputs.length === 0)
38739
39210
  return;
@@ -38750,12 +39221,14 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38750
39221
  ...plainOutput ? args.outputMessages.slice(prefix).map((message) => JSON.stringify(message) ?? "null") : []
38751
39222
  ];
38752
39223
  jsonPrefix = !plainOutput ? JSON.stringify(args.outputMessages) : priorOutput && prefix === outputs.length && prefix === priorOutput.inputs.length ? priorOutput.json : `[${jsonMessages.join(",")}]`;
39224
+ args.assertCurrentPass?.();
38753
39225
  state.outputSnapshot = plainOutput ? {
38754
39226
  inputs: outputs,
38755
39227
  jsonMessages,
38756
39228
  json: jsonPrefix
38757
39229
  } : null;
38758
39230
  } catch (error) {
39231
+ args.assertCurrentPass?.();
38759
39232
  dropSlot(snapshot.sessionId, "lkg_snapshot_serialize_failed");
38760
39233
  const failedState = stateFor(snapshot.sessionId);
38761
39234
  failedState.syncCaptureRequired = true;
@@ -38779,6 +39252,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38779
39252
  const outputIds = args.outputEntryIds ?? inferredIds;
38780
39253
  const inputIds = new Set(snapshot.inputs.map((input) => input.id));
38781
39254
  const ownership = outputIds.length === args.outputMessages.length && outputIds.every((id) => id === null || typeof id === "string" && inputIds.has(id)) ? [...outputIds] : undefined;
39255
+ args.assertCurrentPass?.();
38782
39256
  state.captureSequence += 1;
38783
39257
  const plan = {
38784
39258
  sessionId: snapshot.sessionId,
@@ -38794,6 +39268,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38794
39268
  state.capturedRequest = args.hostEnvelopeSignature ? { ...plan, envelopeSignature: args.hostEnvelopeSignature } : undefined;
38795
39269
  const livePrior = getSlot(snapshot.sessionId);
38796
39270
  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);
39271
+ args.assertCurrentPass?.();
38797
39272
  if (unchanged && !state.syncCaptureRequired) {
38798
39273
  const kept = {
38799
39274
  ...livePrior,
@@ -38809,6 +39284,12 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38809
39284
  dropSlot(snapshot.sessionId, "lkg_cache_bust_pending_capture");
38810
39285
  }
38811
39286
  const commit = () => {
39287
+ try {
39288
+ args.assertCurrentPass?.();
39289
+ } catch (error) {
39290
+ sessionLog(plan.sessionId, "DISCARDED CONTEXT RESULT: queued LKG capture", error);
39291
+ return;
39292
+ }
38812
39293
  if (plan.captureSequence !== state.captureSequence)
38813
39294
  return;
38814
39295
  const startedAt = performance.now();
@@ -38837,6 +39318,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38837
39318
  } : undefined);
38838
39319
  reusedPrefix = incremental.reusedPrefix;
38839
39320
  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)) {
39321
+ args.assertCurrentPass?.();
38840
39322
  state.acceptedInputs = plan.inputs;
38841
39323
  return;
38842
39324
  }
@@ -38852,6 +39334,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38852
39334
  capturedAt: plan.capturedAt,
38853
39335
  captureSequence: plan.captureSequence
38854
39336
  };
39337
+ args.assertCurrentPass?.();
38855
39338
  if (!captureSlot(plan.sessionId, slot)) {
38856
39339
  throw new Error("LKG slot rejected the Pi snapshot");
38857
39340
  }
@@ -38860,6 +39343,12 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
38860
39343
  const persisted = saveLkgSlotToDb(db, plan.sessionId, slot);
38861
39344
  state.syncCaptureRequired = !persisted;
38862
39345
  } catch (error) {
39346
+ try {
39347
+ args.assertCurrentPass?.();
39348
+ } catch (discarded) {
39349
+ sessionLog(plan.sessionId, "DISCARDED CONTEXT RESULT: LKG publication", discarded);
39350
+ return;
39351
+ }
38863
39352
  if (plan.captureSequence !== state.captureSequence)
38864
39353
  return;
38865
39354
  dropSlot(plan.sessionId, "lkg_async_capture_failed");
@@ -38955,7 +39444,7 @@ function resolvePiLkgOutputEntryIds(messages, syntheticLeadingCount, entryId) {
38955
39444
  }
38956
39445
 
38957
39446
  // src/pi-lkg-fit-envelope.ts
38958
- import { createHash as createHash14 } from "node:crypto";
39447
+ import { createHash as createHash15 } from "node:crypto";
38959
39448
 
38960
39449
  // src/host-system-prompt.ts
38961
39450
  function readHostSystemPrompt(ctx) {
@@ -38973,7 +39462,7 @@ function readHostSystemPrompt(ctx) {
38973
39462
  }
38974
39463
 
38975
39464
  // src/pi-lkg-fit-envelope.ts
38976
- function readPiLkgFitEnvelope(ctx, pi, modelKey, frozen) {
39465
+ function readPiLkgFitEnvelope(ctx, pi, modelKey, frozen, wireSchema) {
38977
39466
  try {
38978
39467
  if (!modelKey || typeof pi.getAllTools !== "function")
38979
39468
  return;
@@ -38985,7 +39474,8 @@ function readPiLkgFitEnvelope(ctx, pi, modelKey, frozen) {
38985
39474
  for (const tool of allTools) {
38986
39475
  if (!tool || typeof tool !== "object")
38987
39476
  return;
38988
- const { name, description, parameters } = tool;
39477
+ const { name, description } = tool;
39478
+ const parameters = wireSchema ? wireSchema(tool) : tool.parameters;
38989
39479
  if (typeof name !== "string" || !name.length || typeof description !== "string" || !parameters || typeof parameters !== "object" || Array.isArray(parameters))
38990
39480
  return;
38991
39481
  tools.push({ name, description, parameters });
@@ -39033,7 +39523,7 @@ function readPiLkgFitEnvelope(ctx, pi, modelKey, frozen) {
39033
39523
  refusalToolDefinitionTokens,
39034
39524
  toolDefinitionsMeasured: refusalToolDefinitionTokens !== undefined,
39035
39525
  envelopeBytes: Buffer.byteLength(envelopeJson),
39036
- envelopeSignature: activeNames ? createHash14("sha256").update(envelopeJson).update(JSON.stringify(activeNames)).digest("hex") : undefined,
39526
+ envelopeSignature: activeNames ? createHash15("sha256").update(envelopeJson).update(JSON.stringify(activeNames)).digest("hex") : undefined,
39037
39527
  calibration
39038
39528
  };
39039
39529
  } catch {
@@ -39928,6 +40418,29 @@ function injectSyntheticTodowriteForPi(args) {
39928
40418
  return args.messages;
39929
40419
  }
39930
40420
 
40421
+ // src/pi-tool-wire-schema.ts
40422
+ import { isAbsolute as isAbsolute3 } from "node:path";
40423
+ import { pathToFileURL as pathToFileURL2 } from "node:url";
40424
+ var resolver;
40425
+ function loadPiToolWireSchema() {
40426
+ if (resolver)
40427
+ return resolver;
40428
+ resolver = (async () => {
40429
+ const specifier = "@oh-my-pi/pi-ai/utils/schema/wire";
40430
+ for (const base of [process.argv[1], import.meta.url]) {
40431
+ if (!base || !base.startsWith("file:") && !isAbsolute3(base))
40432
+ continue;
40433
+ try {
40434
+ const path = import.meta.resolve(specifier, base.startsWith("file:") ? base : pathToFileURL2(base).href);
40435
+ const host = await import(path);
40436
+ if (typeof host.toolWireSchema === "function")
40437
+ return host.toolWireSchema;
40438
+ } catch {}
40439
+ }
40440
+ })();
40441
+ return resolver;
40442
+ }
40443
+
39931
40444
  // src/provider-error-recovery-pi.ts
39932
40445
  function reportBindingRecovery(sessionId, report, message) {
39933
40446
  if (report)
@@ -40587,14 +41100,26 @@ function replayPiReminderStrips(args) {
40587
41100
  }
40588
41101
 
40589
41102
  // src/served-array-ledger.ts
40590
- import { createHash as createHash15 } from "node:crypto";
41103
+ import { createHash as createHash16 } from "node:crypto";
41104
+ import { readFileSync as readFileSync13 } from "node:fs";
40591
41105
  import * as path5 from "node:path";
40592
41106
  var PI_SERVED_ARRAY_TAIL_MESSAGES = 40;
40593
41107
  var PI_SERVED_ARRAY_BODY_CAPTURE_ENV = "MMC_PI_SERVED_BODY_CAPTURE";
40594
41108
  var LEDGER_DIRECTORY = "pi-served-array-digests";
40595
41109
  var BODY_DIRECTORY = "pi-served-array-bodies";
41110
+ var IDENTITY_DIRECTORY = "pi-served-tag-numbers";
40596
41111
  var FLUSH_DELAY_MS = 25;
41112
+
41113
+ class PiServedIdentityError extends Error {
41114
+ constructor(cause) {
41115
+ super("Pi served-number identity could not be persisted or restored", {
41116
+ cause
41117
+ });
41118
+ this.name = "PiServedIdentityError";
41119
+ }
41120
+ }
40597
41121
  var previousBySession = new Map;
41122
+ var servedTagNumbersBySession = new Map;
40598
41123
  var sequenceBySession = new Map;
40599
41124
  var pendingLinesByPath = new Map;
40600
41125
  var flushTimer = null;
@@ -40602,10 +41127,39 @@ var swallowedWriteCount = 0;
40602
41127
  var lastWriteError = null;
40603
41128
  function clearPiServedArraySession(sessionId) {
40604
41129
  previousBySession.delete(sessionId);
41130
+ servedTagNumbersBySession.delete(sessionId);
40605
41131
  sequenceBySession.delete(sessionId);
40606
41132
  }
41133
+ function getPiServedTagNumbers(sessionId, storageDir = getMagicContextStorageDir()) {
41134
+ const filePath = getPiServedTagNumbersPath(sessionId, storageDir);
41135
+ const cached = servedTagNumbersBySession.get(sessionId);
41136
+ if (cached?.path === filePath)
41137
+ return cached.numbers;
41138
+ let text;
41139
+ try {
41140
+ text = readFileSync13(filePath, "utf8");
41141
+ } catch (error) {
41142
+ if (error.code !== "ENOENT")
41143
+ throw error;
41144
+ text = "";
41145
+ }
41146
+ const numbers = new Set;
41147
+ for (const line of text.split(`
41148
+ `)) {
41149
+ if (!line.trim())
41150
+ continue;
41151
+ const row = JSON.parse(line);
41152
+ if (row.version !== 1 || row.session_id !== sessionId || !Array.isArray(row.tag_numbers) || !row.tag_numbers.every((number) => Number.isSafeInteger(number) && number > 0)) {
41153
+ throw new Error("Invalid durable Pi served-number record; refusing identity adoption");
41154
+ }
41155
+ for (const number of row.tag_numbers)
41156
+ numbers.add(number);
41157
+ }
41158
+ servedTagNumbersBySession.set(sessionId, { path: filePath, numbers });
41159
+ return numbers;
41160
+ }
40607
41161
  function sha256(value) {
40608
- return createHash15("sha256").update(value).digest("hex");
41162
+ return createHash16("sha256").update(value).digest("hex");
40609
41163
  }
40610
41164
  function safeSessionFileStem(sessionId) {
40611
41165
  const readable = sessionId.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 96);
@@ -40617,6 +41171,9 @@ function getPiServedArrayLedgerPath(sessionId, storageDir = getMagicContextStora
40617
41171
  function getPiServedArrayBodyPath(sessionId, storageDir = getMagicContextStorageDir()) {
40618
41172
  return path5.join(storageDir, BODY_DIRECTORY, `${safeSessionFileStem(sessionId)}.jsonl`);
40619
41173
  }
41174
+ function getPiServedTagNumbersPath(sessionId, storageDir = getMagicContextStorageDir()) {
41175
+ return path5.join(storageDir, IDENTITY_DIRECTORY, `${safeSessionFileStem(sessionId)}.jsonl`);
41176
+ }
40620
41177
  function fullBodyCaptureEnabled() {
40621
41178
  const value = process.env[PI_SERVED_ARRAY_BODY_CAPTURE_ENV]?.trim().toLowerCase();
40622
41179
  return value === "1" || value === "true" || value === "yes" || value === "on";
@@ -40682,8 +41239,19 @@ function flushPiServedArrayLedger() {
40682
41239
  return;
40683
41240
  const pending = [...pendingLinesByPath.entries()];
40684
41241
  pendingLinesByPath.clear();
40685
- for (const [filePath, lines] of pending)
40686
- appendPendingLines(filePath, lines);
41242
+ for (const [filePath, lines] of pending) {
41243
+ const admitted = lines.filter((item) => {
41244
+ try {
41245
+ item.assertCurrentPass?.();
41246
+ return true;
41247
+ } catch (error) {
41248
+ log("[magic-context][pi] DISCARDED CONTEXT RESULT: queued served capture", error);
41249
+ return false;
41250
+ }
41251
+ }).map((item) => item.line);
41252
+ if (admitted.length)
41253
+ appendPendingLines(filePath, admitted);
41254
+ }
40687
41255
  }
40688
41256
  function scheduleFlush() {
40689
41257
  if (flushTimer)
@@ -40691,19 +41259,30 @@ function scheduleFlush() {
40691
41259
  flushTimer = setTimeout(flushPiServedArrayLedger, FLUSH_DELAY_MS);
40692
41260
  flushTimer.unref?.();
40693
41261
  }
40694
- function enqueue(filePath, line) {
41262
+ function enqueue(filePath, line, assertCurrentPass) {
40695
41263
  const pending = pendingLinesByPath.get(filePath);
40696
41264
  if (pending)
40697
- pending.push(line);
41265
+ pending.push({ line, assertCurrentPass });
40698
41266
  else
40699
- pendingLinesByPath.set(filePath, [line]);
41267
+ pendingLinesByPath.set(filePath, [{ line, assertCurrentPass }]);
40700
41268
  scheduleFlush();
40701
41269
  }
40702
41270
  function capturePiServedArray(sessionId, messages, options = {}) {
41271
+ options.assertCurrentPass?.();
41272
+ let identityPersistenceFailed = false;
40703
41273
  try {
40704
41274
  const serializedMessages = options.serializedOutput?.jsonMessages ?? messages.map(serializeMessage);
40705
41275
  const serializedArray = options.serializedOutput?.json ?? `[${serializedMessages.join(",")}]`;
40706
41276
  const digest = sha256(serializedArray);
41277
+ const storageDir = options.storageDir ?? getMagicContextStorageDir();
41278
+ identityPersistenceFailed = true;
41279
+ const previousNumbers = getPiServedTagNumbers(sessionId, storageDir);
41280
+ identityPersistenceFailed = false;
41281
+ const served = new Set(previousNumbers);
41282
+ for (const number of options.servedTagNumbers ?? []) {
41283
+ if (Number.isSafeInteger(number) && number > 0)
41284
+ served.add(number);
41285
+ }
40707
41286
  const previous = previousBySession.get(sessionId);
40708
41287
  const divergence = previous ? firstDivergence(previous.serializedMessages, serializedMessages) : null;
40709
41288
  const sequence = (sequenceBySession.get(sessionId) ?? 0) + 1;
@@ -40720,9 +41299,27 @@ function capturePiServedArray(sessionId, messages, options = {}) {
40720
41299
  block_vector_start: tailStart,
40721
41300
  block_vectors: messages.slice(tailStart).map(blockVector)
40722
41301
  };
40723
- const storageDir = options.storageDir ?? getMagicContextStorageDir();
41302
+ options.assertCurrentPass?.();
41303
+ const newNumbers = [...served].filter((number) => !previousNumbers.has(number));
41304
+ const identityPath = getPiServedTagNumbersPath(sessionId, storageDir);
41305
+ if (newNumbers.length) {
41306
+ identityPersistenceFailed = true;
41307
+ ensureStorageDirectorySync(path5.dirname(identityPath));
41308
+ options.assertCurrentPass?.();
41309
+ writeStorageFileSync(identityPath, `${JSON.stringify({ version: 1, session_id: sessionId, tag_numbers: newNumbers })}
41310
+ `, {
41311
+ encoding: "utf8",
41312
+ flag: "a"
41313
+ });
41314
+ identityPersistenceFailed = false;
41315
+ }
41316
+ options.assertCurrentPass?.();
41317
+ servedTagNumbersBySession.set(sessionId, {
41318
+ path: identityPath,
41319
+ numbers: served
41320
+ });
40724
41321
  enqueue(getPiServedArrayLedgerPath(sessionId, storageDir), `${JSON.stringify(record)}
40725
- `);
41322
+ `, options.assertCurrentPass);
40726
41323
  if (options.fullBodyCapture ?? fullBodyCaptureEnabled()) {
40727
41324
  const bodyHeader = JSON.stringify({
40728
41325
  version: 1,
@@ -40732,12 +41329,15 @@ function capturePiServedArray(sessionId, messages, options = {}) {
40732
41329
  sha256: digest
40733
41330
  });
40734
41331
  enqueue(getPiServedArrayBodyPath(sessionId, storageDir), `${bodyHeader.slice(0, -1)},"messages":${serializedArray}}
40735
- `);
41332
+ `, options.assertCurrentPass);
40736
41333
  }
40737
41334
  previousBySession.set(sessionId, { digest, serializedMessages });
40738
41335
  sequenceBySession.set(sessionId, sequence);
40739
41336
  return record;
40740
41337
  } catch (error) {
41338
+ options.assertCurrentPass?.();
41339
+ if (identityPersistenceFailed)
41340
+ throw new PiServedIdentityError(error);
40741
41341
  recordWriteFailure(error);
40742
41342
  return;
40743
41343
  }
@@ -40932,7 +41532,7 @@ function stripPiProcessedImages(args) {
40932
41532
  }
40933
41533
 
40934
41534
  // src/system-prompt.ts
40935
- import { createHash as createHash16 } from "node:crypto";
41535
+ import { createHash as createHash17 } from "node:crypto";
40936
41536
 
40937
41537
  // ../plugin/src/agents/magic-context-prompt.ts
40938
41538
  var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
@@ -41106,7 +41706,7 @@ function processSystemPromptForCache(args) {
41106
41706
  const liveDate = dateMatch ? dateMatch[0] : null;
41107
41707
  const stickyDate = stickyDateBySession.get(sessionId);
41108
41708
  const stableCandidate = liveDate && stickyDate && liveDate !== stickyDate ? systemPrompt.replace(DATE_PATTERN, stickyDate) : systemPrompt;
41109
- const stableCandidateHash = createHash16("md5").update(promptSurfaceHashMaterial(stableCandidate, args.promptSurfacePreset)).digest("hex");
41709
+ const stableCandidateHash = createHash17("md5").update(promptSurfaceHashMaterial(stableCandidate, args.promptSurfacePreset)).digest("hex");
41110
41710
  const contentOrPresetChanged = !isFirstHash && stableCandidateHash !== previousHash;
41111
41711
  const idleCacheExpired = sessionMeta !== undefined && computeHardCacheExpired(sessionMeta.cacheTtl, sessionMeta.lastResponseTime, Date.now());
41112
41712
  const dateMayAdvance = isCacheBusting || idleCacheExpired || contentOrPresetChanged;
@@ -41121,7 +41721,7 @@ function processSystemPromptForCache(args) {
41121
41721
  sessionLog(sessionId, `system prompt date frozen: real=${liveDate}, using=${stickyDate} (cache-stable pass)`);
41122
41722
  }
41123
41723
  }
41124
- const currentHash = createHash16("md5").update(promptSurfaceHashMaterial(frozenPrompt, args.promptSurfacePreset)).digest("hex");
41724
+ const currentHash = createHash17("md5").update(promptSurfaceHashMaterial(frozenPrompt, args.promptSurfacePreset)).digest("hex");
41125
41725
  const hashChanged = !isFirstHash && currentHash !== previousHash;
41126
41726
  if (hashChanged) {
41127
41727
  sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${frozenPrompt.length})`);
@@ -41149,19 +41749,6 @@ function clearPiSystemPromptSession(sessionId) {
41149
41749
  stickyDateBySession.delete(sessionId);
41150
41750
  }
41151
41751
 
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
41752
  // src/transcript-pi.ts
41166
41753
  function createPiTranscript(source, sessionId, entryIds, options = {}) {
41167
41754
  const working = source.slice();
@@ -41730,6 +42317,7 @@ var pendingDecisionLogObserverForTests;
41730
42317
  var mutationGateObserverForTests;
41731
42318
  var lkgRecoveryLogObserverForTests;
41732
42319
  var variantChangeLogObserverForTests;
42320
+ var beforePipelineForTests;
41733
42321
  function logPiLkgRecovery(sessionId, message) {
41734
42322
  lkgRecoveryLogObserverForTests?.(message);
41735
42323
  sessionLog(sessionId, message);
@@ -41745,11 +42333,22 @@ var deferredMaterializationSessions = new Set;
41745
42333
  var sessionsByProject = new Map;
41746
42334
  var lastSeenProjectIdentityBySession = new Map;
41747
42335
  var persistedProjectIdentityBySession = new Map;
42336
+ var sessionProjectBindingFailureLogAtBySession = new Map;
42337
+ var SESSION_PROJECT_BINDING_FAILURE_LOG_INTERVAL_MS = 10 * 60 * 1000;
41748
42338
  var rawMessageProviderUnregistersBySession = new Map;
41749
42339
  var activeContextHandlerSessions = new Set;
41750
42340
  var lastHeuristicsTurnIdBySession = new Map;
41751
42341
  var routinePressureAppliedBySession = new Map;
41752
42342
  var firstContextPassSeenBySession = new Set;
42343
+ var contextPassGeneration = new Map;
42344
+
42345
+ class PiLkgAdmissionReplay extends Error {
42346
+ messages;
42347
+ constructor(messages) {
42348
+ super("Saved request served before writer wait");
42349
+ this.messages = messages;
42350
+ }
42351
+ }
41753
42352
  var liveModelBySession = new Map;
41754
42353
  var latestAssistantModelTimestampBySession = new Map;
41755
42354
  var taggedStableMessageIdsBySession = new Map;
@@ -41974,7 +42573,7 @@ function trackSessionForProject(projectIdentity, sessionId) {
41974
42573
  function isContextHandlerSessionActive(sessionId) {
41975
42574
  return activeContextHandlerSessions.has(sessionId);
41976
42575
  }
41977
- function updateSessionProjectTracking(sessionId, projectIdentity, db) {
42576
+ function updateSessionProjectTracking(sessionId, projectIdentity, db, observedCwd) {
41978
42577
  if (!projectIdentity)
41979
42578
  return;
41980
42579
  const prev = lastSeenProjectIdentityBySession.get(sessionId);
@@ -41987,9 +42586,22 @@ function updateSessionProjectTracking(sessionId, projectIdentity, db) {
41987
42586
  }
41988
42587
  if (db && persistedProjectIdentityBySession.get(sessionId) !== projectIdentity) {
41989
42588
  try {
41990
- recordSessionProjectIdentity(db, sessionId, projectIdentity);
42589
+ const change = recordSessionProjectIdentity(db, sessionId, projectIdentity);
41991
42590
  persistedProjectIdentityBySession.set(sessionId, projectIdentity);
41992
- } catch {}
42591
+ if (change) {
42592
+ sessionLog(sessionId, `project binding changed harness=${getHarness()} cwd=${observedCwd ?? "unknown"} old=${change.previousProjectPath ?? "none"} new=${change.projectPath}`);
42593
+ }
42594
+ } catch (error) {
42595
+ const now = Date.now();
42596
+ const lastLoggedAt = sessionProjectBindingFailureLogAtBySession.get(sessionId);
42597
+ if (lastLoggedAt === undefined || now - lastLoggedAt >= SESSION_PROJECT_BINDING_FAILURE_LOG_INTERVAL_MS) {
42598
+ sessionProjectBindingFailureLogAtBySession.set(sessionId, now);
42599
+ sessionLog(sessionId, `project binding write failed harness=${getHarness()} cwd=${observedCwd ?? "unknown"} attempted=${projectIdentity}: ${error instanceof Error ? error.message : String(error)}`);
42600
+ }
42601
+ }
42602
+ }
42603
+ if (db && persistedProjectIdentityBySession.get(sessionId) === projectIdentity && sessionProjectBindingFailureLogAtBySession.delete(sessionId)) {
42604
+ sessionLog(sessionId, `project binding write recovered harness=${getHarness()} cwd=${observedCwd ?? "unknown"} identity=${projectIdentity}`);
41993
42605
  }
41994
42606
  trackSessionForProject(projectIdentity, sessionId);
41995
42607
  lastSeenProjectIdentityBySession.set(sessionId, projectIdentity);
@@ -42004,11 +42616,6 @@ function recordPiLiveModel(sessionId, modelKey, assistantTimestamp) {
42004
42616
  liveModelBySession.set(sessionId, modelKey);
42005
42617
  return true;
42006
42618
  }
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
42619
  function persistLastTransformErrorIfChanged(db, sessionId, summary, knownCurrent) {
42013
42620
  try {
42014
42621
  const current = knownCurrent === undefined ? getOrCreateSessionMeta(db, sessionId).lastTransformError : knownCurrent;
@@ -42113,15 +42720,195 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId, preloadedBranchEn
42113
42720
  }
42114
42721
  return result;
42115
42722
  }
42723
+ function piContextHeaderFields(message) {
42724
+ if (!message || typeof message !== "object")
42725
+ return null;
42726
+ const record = message;
42727
+ if (typeof record.role !== "string")
42728
+ return null;
42729
+ return {
42730
+ responseId: typeof record.responseId === "string" ? record.responseId : null,
42731
+ timestamp: typeof record.timestamp === "number" || typeof record.timestamp === "string" ? record.timestamp : null,
42732
+ role: record.role,
42733
+ toolCallId: typeof record.toolCallId === "string" ? record.toolCallId : null
42734
+ };
42735
+ }
42736
+ function piAlignmentCheckForEntry(entry) {
42737
+ if (!isPiContextEmitEligible(entry))
42738
+ return null;
42739
+ const row = entry;
42740
+ const header = row.type === "message" ? piContextHeaderFields(row.message) : {
42741
+ responseId: null,
42742
+ timestamp: new Date(row.timestamp).getTime(),
42743
+ role: row.type === "custom_message" ? "custom" : "branchSummary",
42744
+ toolCallId: null
42745
+ };
42746
+ if (!header)
42747
+ return null;
42748
+ return {
42749
+ ...header,
42750
+ headerKey: JSON.stringify([
42751
+ header.responseId,
42752
+ header.timestamp,
42753
+ header.role,
42754
+ header.toolCallId
42755
+ ]),
42756
+ entry: row
42757
+ };
42758
+ }
42759
+ function piAlignedContentMatches(check, message) {
42760
+ const entry = check.entry;
42761
+ if (entry.type === "branch_summary") {
42762
+ const summary = message;
42763
+ return summary.summary === entry.summary && summary.fromId === entry.fromId;
42764
+ }
42765
+ if (entry.type === "custom_message") {
42766
+ const custom = message;
42767
+ if (custom.customType !== entry.customType)
42768
+ return false;
42769
+ }
42770
+ if (check.fingerprint === undefined) {
42771
+ check.fingerprint = entry.type === "message" ? piMessageEntryFingerprint(entry.message) : piMessageEntryFingerprint({
42772
+ role: check.role,
42773
+ timestamp: check.timestamp,
42774
+ content: entry.content ?? []
42775
+ });
42776
+ }
42777
+ return check.fingerprint !== null && piMessageEntryFingerprint(message) === check.fingerprint;
42778
+ }
42779
+ function findPiAlignmentMismatch(lookup, entryIds, messages) {
42780
+ for (let index = 0;index < entryIds.length; index += 1) {
42781
+ const id = entryIds[index];
42782
+ if (id === undefined)
42783
+ continue;
42784
+ if (!piAlignedPositionMatches(lookup, id, messages[index]))
42785
+ return index;
42786
+ }
42787
+ return -1;
42788
+ }
42789
+ function piAlignedPositionMatches(lookup, id, message) {
42790
+ const check = lookup.alignmentChecks.get(id);
42791
+ const header = piContextHeaderFields(message);
42792
+ if (!check || !header || header.role !== check.role || !Object.is(header.timestamp, check.timestamp) || header.responseId !== check.responseId || header.toolCallId !== check.toolCallId)
42793
+ return false;
42794
+ return (lookup.alignmentHeaderCounts.get(check.headerKey) ?? 0) <= 1 || piAlignedContentMatches(check, message);
42795
+ }
42796
+ function anchorPiEventEntryIds(lookup, aligned, messages) {
42797
+ const projectionIndex = new Map;
42798
+ for (let index = 0;index < aligned.length; index += 1) {
42799
+ const id = aligned[index];
42800
+ if (id !== undefined)
42801
+ projectionIndex.set(id, index);
42802
+ }
42803
+ const result = new Array(messages.length).fill(undefined);
42804
+ const used = new Set;
42805
+ const anchors = [];
42806
+ for (let index = 0;index < messages.length; index += 1) {
42807
+ const header = piContextHeaderFields(messages[index]);
42808
+ if (!header)
42809
+ continue;
42810
+ const key = JSON.stringify([
42811
+ header.responseId,
42812
+ header.timestamp,
42813
+ header.role,
42814
+ header.toolCallId
42815
+ ]);
42816
+ if (lookup.alignmentHeaderCounts.get(key) !== 1)
42817
+ continue;
42818
+ const id = lookup.alignmentEntryIdByHeader.get(key);
42819
+ const position = id === undefined ? undefined : projectionIndex.get(id);
42820
+ if (id === undefined || position === undefined)
42821
+ continue;
42822
+ const previous = anchors.at(-1);
42823
+ if (used.has(id) || previous && position <= previous.projection)
42824
+ return null;
42825
+ anchors.push({ message: index, projection: position });
42826
+ used.add(id);
42827
+ result[index] = id;
42828
+ }
42829
+ const fillRun = (messageStart, messageEnd, projectionStart, projectionEnd) => {
42830
+ if (messageEnd - messageStart !== projectionEnd - projectionStart)
42831
+ return;
42832
+ for (let offset = 0;offset < messageEnd - messageStart; offset += 1) {
42833
+ const id = aligned[projectionStart + offset];
42834
+ const message = messages[messageStart + offset];
42835
+ if (id !== undefined && !used.has(id) && piAlignedPositionMatches(lookup, id, message)) {
42836
+ result[messageStart + offset] = id;
42837
+ used.add(id);
42838
+ }
42839
+ }
42840
+ };
42841
+ let previousMessage = -1;
42842
+ let previousProjection = -1;
42843
+ for (const anchor of anchors) {
42844
+ fillRun(previousMessage + 1, anchor.message, previousProjection + 1, anchor.projection);
42845
+ previousMessage = anchor.message;
42846
+ previousProjection = anchor.projection;
42847
+ }
42848
+ fillRun(previousMessage + 1, messages.length, previousProjection + 1, aligned.length);
42849
+ for (let index = 0;index < messages.length; index += 1) {
42850
+ if (result[index] !== undefined)
42851
+ continue;
42852
+ const message = messages[index];
42853
+ if (!message || typeof message !== "object")
42854
+ continue;
42855
+ const byRef = lookup.entryIdByMessageRef.get(message);
42856
+ if (byRef !== undefined && !used.has(byRef)) {
42857
+ result[index] = byRef;
42858
+ used.add(byRef);
42859
+ continue;
42860
+ }
42861
+ const fingerprint = piMessageEntryFingerprint(message);
42862
+ const bucket = fingerprint ? lookup.entryIdsByFingerprint.get(fingerprint) : undefined;
42863
+ const id = bucket?.length === 1 ? bucket[0] : undefined;
42864
+ if (id !== undefined && !used.has(id)) {
42865
+ result[index] = id;
42866
+ used.add(id);
42867
+ }
42868
+ }
42869
+ return result;
42870
+ }
42871
+ var piAlignmentMismatchLoggedSessions = new Set;
42872
+ var piEntryAlignmentLaneCounts = { anchored: 0, fingerprint: 0 };
42873
+ function resolvePiEventEntryIds(ctx, messages, sessionId, branchEntries) {
42874
+ if (branchEntries === null)
42875
+ return null;
42876
+ const lookup = getPiBranchEntryLookup(branchEntries);
42877
+ const aligned = messages.some(isPiSystemEntry) ? lookup.alignedEntryIds : lookup.alignedVisibleEntryIds;
42878
+ if (aligned.length === messages.length) {
42879
+ const mismatch = findPiAlignmentMismatch(lookup, aligned, messages);
42880
+ if (mismatch < 0)
42881
+ return aligned;
42882
+ if (!piAlignmentMismatchLoggedSessions.has(sessionId)) {
42883
+ piAlignmentMismatchLoggedSessions.add(sessionId);
42884
+ 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)`);
42885
+ }
42886
+ }
42887
+ const anchored = anchorPiEventEntryIds(lookup, aligned, messages);
42888
+ if (anchored) {
42889
+ piEntryAlignmentLaneCounts.anchored += 1;
42890
+ return anchored;
42891
+ }
42892
+ piEntryAlignmentLaneCounts.fingerprint += 1;
42893
+ return collectMessageEntryIdsByRef(ctx, messages, sessionId, branchEntries);
42894
+ }
42116
42895
  function addPiBranchEntryToLookup(lookup, entry) {
42117
42896
  if (!entry || typeof entry !== "object")
42118
42897
  return;
42898
+ const check = piAlignmentCheckForEntry(entry);
42899
+ if (check) {
42900
+ lookup.alignmentChecks.set(entry.id, check);
42901
+ lookup.alignmentEntryIdByHeader.set(check.headerKey, entry.id);
42902
+ lookup.alignmentHeaderCounts.set(check.headerKey, (lookup.alignmentHeaderCounts.get(check.headerKey) ?? 0) + 1);
42903
+ }
42119
42904
  const row = entry;
42120
42905
  if (row.type !== "message" || typeof row.id !== "string" || !row.message || typeof row.message !== "object") {
42121
42906
  return;
42122
42907
  }
42123
42908
  lookup.entryIdByMessageRef.set(row.message, row.id);
42124
42909
  const fingerprint = piMessageEntryFingerprint(row.message);
42910
+ if (check)
42911
+ check.fingerprint = fingerprint;
42125
42912
  if (!fingerprint)
42126
42913
  return;
42127
42914
  const bucket = lookup.entryIdsByFingerprint.get(fingerprint);
@@ -42139,6 +42926,56 @@ function isPiContextEmitEligible(entry) {
42139
42926
  return row.type === "message" || row.type === "custom_message" || row.type === "branch_summary" && typeof row.summary === "string" && row.summary.length > 0;
42140
42927
  }
42141
42928
  function buildPiAlignedEntryIds(entries) {
42929
+ const all = buildPiAlignedEntryIdsIncludingSystem(entries);
42930
+ return { all, visible: buildPiAlignedVisibleEntryIds(entries) };
42931
+ }
42932
+ function buildPiAlignedVisibleEntryIds(entries) {
42933
+ let compactionIndex = -1;
42934
+ for (let index = entries.length - 1;index >= 0; index -= 1) {
42935
+ if (entries[index]?.type === "compaction") {
42936
+ compactionIndex = index;
42937
+ break;
42938
+ }
42939
+ }
42940
+ const context = [];
42941
+ if (compactionIndex >= 0) {
42942
+ const compaction = entries[compactionIndex];
42943
+ context.push(compaction);
42944
+ const firstKeptEntryId = compaction.firstKeptEntryId;
42945
+ let foundFirstKept = false;
42946
+ for (let index = 0;index < compactionIndex; index += 1) {
42947
+ const entry = entries[index];
42948
+ if (typeof firstKeptEntryId === "string" && entry?.id === firstKeptEntryId) {
42949
+ foundFirstKept = true;
42950
+ }
42951
+ if (foundFirstKept)
42952
+ context.push(entry);
42953
+ }
42954
+ }
42955
+ for (let index = compactionIndex + 1;index < entries.length; index += 1) {
42956
+ context.push(entries[index]);
42957
+ }
42958
+ const omitted = new Map;
42959
+ for (const entry of context) {
42960
+ const edit = entry;
42961
+ if (edit?.type !== "context_edit" || typeof edit.targetId !== "string")
42962
+ continue;
42963
+ omitted.set(edit.targetId, edit.replacement === null);
42964
+ }
42965
+ const ids = [];
42966
+ if (compactionIndex >= 0) {
42967
+ const compactionId = entries[compactionIndex].id;
42968
+ if (typeof compactionId !== "string" || omitted.get(compactionId) !== true)
42969
+ ids.push(undefined);
42970
+ }
42971
+ for (let index = compactionIndex >= 0 ? 1 : 0;index < context.length; index += 1) {
42972
+ const entry = context[index];
42973
+ if (isPiContextEmitEligible(entry) && !isPiSystemMessageEntry(entry) && omitted.get(entry.id) !== true)
42974
+ ids.push(entry.id);
42975
+ }
42976
+ return ids;
42977
+ }
42978
+ function buildPiAlignedEntryIdsIncludingSystem(entries) {
42142
42979
  let compactionIndex = -1;
42143
42980
  let firstKeptEntryId;
42144
42981
  for (let index = entries.length - 1;index >= 0; index -= 1) {
@@ -42202,10 +43039,15 @@ function getPiBranchEntryLookup(entries) {
42202
43039
  const cached = piBranchLookupByProjection.get(entries);
42203
43040
  if (cached)
42204
43041
  return cached;
43042
+ const aligned = buildPiAlignedEntryIds(entries);
42205
43043
  const lookup = {
42206
43044
  entryIdByMessageRef: new Map,
42207
43045
  entryIdsByFingerprint: new Map,
42208
- alignedEntryIds: buildPiAlignedEntryIds(entries)
43046
+ alignedEntryIds: aligned.all,
43047
+ alignedVisibleEntryIds: aligned.visible,
43048
+ alignmentChecks: new Map,
43049
+ alignmentHeaderCounts: new Map,
43050
+ alignmentEntryIdByHeader: new Map
42209
43051
  };
42210
43052
  for (const entry of entries)
42211
43053
  addPiBranchEntryToLookup(lookup, entry);
@@ -42281,7 +43123,10 @@ function readPiBranchEntriesForContext(ctx, sessionId) {
42281
43123
  suffix.reverse();
42282
43124
  if (cached && cachedAncestorIndex === cached.entries.length - 1) {
42283
43125
  const entries = [...cached.entries, ...suffix];
42284
- if (suffix.some((entry) => entry?.type === "compaction")) {
43126
+ if (suffix.some((entry) => {
43127
+ const type = entry?.type;
43128
+ return type === "compaction" || type === "context_edit";
43129
+ })) {
42285
43130
  return installProjection(leafId, entries);
42286
43131
  }
42287
43132
  for (let index = 0;index < suffix.length; index += 1) {
@@ -42291,6 +43136,9 @@ function readPiBranchEntriesForContext(ctx, sessionId) {
42291
43136
  addPiBranchEntryToLookup(cached.lookup, entry);
42292
43137
  if (isPiContextEmitEligible(entry)) {
42293
43138
  cached.lookup.alignedEntryIds.push(entry.id);
43139
+ if (!isPiSystemMessageEntry(entry)) {
43140
+ cached.lookup.alignedVisibleEntryIds.push(entry.id);
43141
+ }
42294
43142
  }
42295
43143
  }
42296
43144
  const projection = {
@@ -42315,46 +43163,69 @@ function readPiBranchEntriesForContext(ctx, sessionId) {
42315
43163
  }
42316
43164
  }
42317
43165
  }
42318
- function piMessageEntryFingerprint(message) {
43166
+ function piMessageEntryFingerprintHeader(message) {
42319
43167
  if (!message || typeof message !== "object")
42320
43168
  return null;
42321
43169
  const record = message;
42322
43170
  if (typeof record.role !== "string")
42323
43171
  return null;
42324
- const firstText = firstPiTextContent(record.content);
42325
- const firstTextHash = crypto3.createHash("sha256").update(firstText ?? "").digest("hex").slice(0, 16);
42326
43172
  return JSON.stringify([
42327
43173
  typeof record.responseId === "string" ? record.responseId : null,
42328
43174
  typeof record.timestamp === "number" || typeof record.timestamp === "string" ? record.timestamp : null,
42329
43175
  record.role,
42330
- typeof record.toolCallId === "string" ? record.toolCallId : null,
42331
- firstTextHash
43176
+ typeof record.toolCallId === "string" ? record.toolCallId : null
42332
43177
  ]);
42333
43178
  }
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;
43179
+ function readPiFallbackFingerprintHeaders(db, sessionId) {
43180
+ const rows = db.prepare(`SELECT DISTINCT entry_fingerprint FROM tags WHERE session_id = ? AND type = 'message'
43181
+ AND entry_fingerprint IS NOT NULL AND message_id LIKE 'pi-msg-%'`).all(sessionId);
43182
+ const headers = new Set;
43183
+ for (const row of rows) {
43184
+ let parsed;
43185
+ try {
43186
+ parsed = JSON.parse(row.entry_fingerprint);
43187
+ } catch {
43188
+ return null;
42345
43189
  }
43190
+ if (!Array.isArray(parsed) || parsed.length !== 5)
43191
+ return null;
43192
+ headers.add(JSON.stringify(parsed.slice(0, 4)));
42346
43193
  }
42347
- return null;
43194
+ return headers;
42348
43195
  }
42349
- function buildEntryFingerprintMap(messages, resolveStableId, reusableMessageIds, includeReusable = true) {
43196
+ var piEntryFingerprintCount = 0;
43197
+ function piMessageEntryFingerprint(message) {
43198
+ piEntryFingerprintCount += 1;
43199
+ if (!message || typeof message !== "object")
43200
+ return null;
43201
+ const record = message;
43202
+ if (typeof record.role !== "string")
43203
+ return null;
43204
+ const contentHash = crypto3.createHash("sha256").update(stableStringify(record.content)).digest("hex");
43205
+ return JSON.stringify([
43206
+ typeof record.responseId === "string" ? record.responseId : null,
43207
+ typeof record.timestamp === "number" || typeof record.timestamp === "string" ? record.timestamp : null,
43208
+ record.role,
43209
+ typeof record.toolCallId === "string" ? record.toolCallId : null,
43210
+ contentHash
43211
+ ]);
43212
+ }
43213
+ function buildEntryFingerprintMap(messages, resolveStableId, reusableMessageIds, includeReusable = true, reusableHeaders) {
42350
43214
  const map = new Map;
42351
43215
  for (let i = 0;i < messages.length; i++) {
42352
43216
  const msg = messages[i];
42353
43217
  const id = resolveStableId(msg, i);
42354
43218
  if (!id)
42355
43219
  continue;
42356
- if (!includeReusable && reusableMessageIds?.has(id))
42357
- continue;
43220
+ if (reusableMessageIds?.has(id)) {
43221
+ if (!includeReusable)
43222
+ continue;
43223
+ if (reusableHeaders) {
43224
+ const header = piMessageEntryFingerprintHeader(msg);
43225
+ if (header === null || !reusableHeaders.has(header))
43226
+ continue;
43227
+ }
43228
+ }
42358
43229
  const fp = piMessageEntryFingerprint(msg);
42359
43230
  if (fp)
42360
43231
  map.set(id, fp);
@@ -42422,54 +43293,116 @@ function runImmediateTransaction(db, fn) {
42422
43293
  try {
42423
43294
  const result = fn();
42424
43295
  db.exec("COMMIT");
42425
- logSlowWriteTransaction("pi_compaction_queue", transactionStartedAt);
43296
+ logSlowWriteTransaction("pi_fallback_adoption", transactionStartedAt);
42426
43297
  return result;
42427
43298
  } catch (error) {
42428
43299
  db.exec("ROLLBACK");
42429
43300
  throw error;
42430
43301
  }
42431
43302
  }
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;
43303
+ function readPiAdoptionRevision(db) {
43304
+ return {
43305
+ external: db.prepare("PRAGMA data_version").get(),
43306
+ local: db.prepare("SELECT total_changes() AS changes").get()
43307
+ };
43308
+ }
43309
+ function preparePiAdoptionFingerprints(fingerprintById) {
43310
+ const realIdsByFingerprint = new Map;
43311
+ for (const [id, fingerprint] of fingerprintById) {
43312
+ if (id.startsWith("pi-msg-"))
43313
+ continue;
43314
+ const ids = realIdsByFingerprint.get(fingerprint) ?? [];
43315
+ ids.push(id);
43316
+ realIdsByFingerprint.set(fingerprint, ids);
42444
43317
  }
42445
- return false;
43318
+ const fingerprints = [...realIdsByFingerprint.keys()];
43319
+ const batches = [];
43320
+ for (let i = 0;i < fingerprints.length; i += 900) {
43321
+ const values = fingerprints.slice(i, i + 900);
43322
+ batches.push({ values, placeholders: values.map(() => "?").join(",") });
43323
+ }
43324
+ return { realIdsByFingerprint, batches };
42446
43325
  }
42447
- function readAdoptablePiFallbackFingerprints(db, sessionId, fingerprintById) {
42448
- const fingerprints = [
42449
- ...new Set([...fingerprintById].filter(([id]) => !id.startsWith("pi-msg-")).map(([, fingerprint]) => fingerprint))
42450
- ];
43326
+ function readAdoptablePiFallbackFingerprints(db, sessionId, batches) {
42451
43327
  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(",");
43328
+ for (const { values, placeholders } of batches) {
42455
43329
  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);
43330
+ AND entry_fingerprint IN (${placeholders}) AND message_id LIKE 'pi-msg-%'`).all(sessionId, ...values);
42457
43331
  for (const row of rows)
42458
43332
  found.add(row.entry_fingerprint);
42459
43333
  }
42460
43334
  return found;
42461
43335
  }
43336
+ function piFallbackBaseId(messageId) {
43337
+ return /^(.*):p\d+$/.exec(messageId)?.[1] ?? messageId;
43338
+ }
43339
+ function pairPiFallbackBases(realIds, candidates, realIdPositions) {
43340
+ const pairs = new Map(realIds.map((id) => [id, null]));
43341
+ if (realIds.length < 2)
43342
+ return pairs;
43343
+ const positions = realIdPositions();
43344
+ if (!positions || realIds.some((id) => !positions.has(id)))
43345
+ return pairs;
43346
+ const newestTag = new Map;
43347
+ for (const c of candidates) {
43348
+ const base = piFallbackBaseId(c.messageId);
43349
+ newestTag.set(base, Math.max(newestTag.get(base) ?? 0, c.tagNumber));
43350
+ }
43351
+ if (newestTag.size < realIds.length)
43352
+ return pairs;
43353
+ 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] }));
43354
+ if (chosen.some((entry) => entry.index === undefined))
43355
+ return pairs;
43356
+ chosen.sort((left, right) => Number(left.index) - Number(right.index));
43357
+ if (new Set(chosen.map((entry) => entry.index)).size !== chosen.length)
43358
+ return pairs;
43359
+ const ordered = [...realIds].sort((left, right) => (positions.get(left) ?? 0) - (positions.get(right) ?? 0));
43360
+ for (let index = 0;index < ordered.length; index += 1) {
43361
+ pairs.set(ordered[index], chosen[index]?.base ?? null);
43362
+ }
43363
+ return pairs;
43364
+ }
42462
43365
  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)
43366
+ let { realIdsByFingerprint, batches } = preparePiAdoptionFingerprints(fingerprintById);
43367
+ const ownerMap = options.messages && options.resolveStableId ? buildPiToolOwnerMap(options.messages, options.resolveStableId) : null;
43368
+ if (!batches.length && !ownerMap?.size && !options.rebuildFingerprints)
42468
43369
  return;
43370
+ const revision = () => readPiAdoptionRevision(db);
43371
+ const beforeDiscovery = revision();
43372
+ const discovered = hasPiFallbackMessageTags(db, sessionId) ? readAdoptablePiFallbackFingerprints(db, sessionId, batches) : new Set;
43373
+ const targetsFor = (fingerprints) => [...fingerprints].flatMap((fingerprint) => (realIdsByFingerprint.get(fingerprint) ?? []).map((id) => [id, fingerprint]));
43374
+ const discoveredTargets = targetsFor(discovered);
42469
43375
  runImmediateTransaction(db, () => {
42470
- if (shouldRunMessageMigration) {
42471
- const adoptable = readAdoptablePiFallbackFingerprints(db, sessionId, fingerprintById);
42472
- for (const [realMessageId, fingerprint] of fingerprintById) {
43376
+ const admitted = revision();
43377
+ const preflight = options.preflightRevision;
43378
+ const rebuild = options.rebuildFingerprints;
43379
+ const expanded = Boolean(preflight && rebuild && (preflight.external.data_version !== admitted.external.data_version || preflight.local.changes !== admitted.local.changes));
43380
+ if (expanded && rebuild) {
43381
+ ({ realIdsByFingerprint, batches } = preparePiAdoptionFingerprints(rebuild()));
43382
+ }
43383
+ if (batches.length && hasPiFallbackMessageTags(db, sessionId)) {
43384
+ const unchanged = !expanded && beforeDiscovery.external.data_version === admitted.external.data_version && beforeDiscovery.local.changes === admitted.local.changes;
43385
+ const adoptable = unchanged ? discovered : readAdoptablePiFallbackFingerprints(db, sessionId, batches);
43386
+ const targets = expanded ? targetsFor(adoptable) : discoveredTargets.filter(([, fp]) => adoptable.has(fp));
43387
+ if (!expanded)
43388
+ targets.push(...targetsFor([...adoptable].filter((fp) => !discovered.has(fp))));
43389
+ const pairedBaseByRealId = new Map;
43390
+ let positions;
43391
+ const realIdPositions = () => {
43392
+ if (positions)
43393
+ return positions;
43394
+ const { messages, resolveStableId } = options;
43395
+ if (!messages || !resolveStableId)
43396
+ return;
43397
+ positions = new Map;
43398
+ for (let index = 0;index < messages.length; index += 1) {
43399
+ const id = resolveStableId(messages[index], index);
43400
+ if (id !== undefined && !positions.has(id))
43401
+ positions.set(id, index);
43402
+ }
43403
+ return positions;
43404
+ };
43405
+ for (const [realMessageId, fingerprint] of targets) {
42473
43406
  if (realMessageId.startsWith("pi-msg-"))
42474
43407
  continue;
42475
43408
  if (!adoptable.has(fingerprint))
@@ -42477,19 +43410,27 @@ function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {
42477
43410
  const candidates = findAdoptableFallbackTags(db, sessionId, fingerprint);
42478
43411
  if (candidates.length === 0)
42479
43412
  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);
43413
+ const baseIds = new Set(candidates.map((c) => piFallbackBaseId(c.messageId)));
43414
+ let base;
43415
+ if (baseIds.size === 1)
43416
+ base = [...baseIds][0];
43417
+ else {
43418
+ if (!pairedBaseByRealId.has(realMessageId)) {
43419
+ for (const [id, paired] of pairPiFallbackBases((realIdsByFingerprint.get(fingerprint) ?? []).filter((id) => !id.startsWith("pi-msg-")), candidates, realIdPositions))
43420
+ pairedBaseByRealId.set(id, paired);
43421
+ }
43422
+ base = pairedBaseByRealId.get(realMessageId) ?? undefined;
42484
43423
  }
42485
- if (baseIds.size !== 1)
43424
+ if (base === undefined)
42486
43425
  continue;
42487
43426
  for (const c of candidates) {
43427
+ if (piFallbackBaseId(c.messageId) !== base)
43428
+ continue;
42488
43429
  const ordinalMatch = /:p(\d+)$/.exec(c.messageId);
42489
43430
  if (!ordinalMatch)
42490
43431
  continue;
42491
43432
  const realContentId = `${realMessageId}:p${ordinalMatch[1]}`;
42492
- const adoption = adoptPiFallbackMessageTag(db, sessionId, c.tagNumber, c.messageId, realContentId);
43433
+ const adoption = adoptPiFallbackMessageTag(db, sessionId, c.tagNumber, c.messageId, realContentId, getPiServedTagNumbers(sessionId));
42493
43434
  if (adoption.action !== "skipped") {
42494
43435
  tagger.unbindTag(sessionId, c.messageId);
42495
43436
  if (adoption.action === "folded") {
@@ -42500,8 +43441,7 @@ function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {
42500
43441
  }
42501
43442
  }
42502
43443
  }
42503
- if (shouldRunToolOwnerMigration && options.messages && options.resolveStableId) {
42504
- const ownerMap = buildPiToolOwnerMap(options.messages, options.resolveStableId);
43444
+ if (ownerMap && hasPiFallbackToolOwnerTags(db, sessionId)) {
42505
43445
  for (const row of findPiFallbackToolOwnerTags(db, sessionId)) {
42506
43446
  const parsed = parsePiFallbackToolOwnerId(row.toolOwnerMessageId);
42507
43447
  if (parsed?.role !== "assistant")
@@ -42512,7 +43452,7 @@ function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {
42512
43452
  const [realOwnerId] = owners;
42513
43453
  if (!realOwnerId || realOwnerId.startsWith("pi-msg-"))
42514
43454
  continue;
42515
- const adoption = adoptPiFallbackToolOwnerTag(db, sessionId, row.tagNumber, row.callId, row.toolOwnerMessageId, realOwnerId);
43455
+ const adoption = adoptPiFallbackToolOwnerTag(db, sessionId, row.tagNumber, row.callId, row.toolOwnerMessageId, realOwnerId, getPiServedTagNumbers(sessionId));
42516
43456
  if (adoption.action !== "skipped") {
42517
43457
  tagger.unbindToolTag(sessionId, row.toolOwnerMessageId, row.callId);
42518
43458
  if (adoption.action === "folded") {
@@ -42583,12 +43523,32 @@ function registerPiContextHandler(pi, baseOptions) {
42583
43523
  variantChangeLogObserverForTests?.(message);
42584
43524
  sessionLog(sessionId, message);
42585
43525
  });
42586
- registerPiGuardedContext(pi, async (event, ctx) => {
42587
- const transformStartTime = performance.now();
43526
+ const contextHandler = async (event, ctx, budget) => {
43527
+ const passSessionId = ctx.sessionManager ? resolveSessionId2(ctx) : undefined;
43528
+ const generation = Symbol();
43529
+ if (passSessionId && !budget.sideTurn)
43530
+ contextPassGeneration.set(passSessionId, generation);
43531
+ const signal = event.signal ?? ctx.signal;
43532
+ const assertOperation = budget.assertOwner;
43533
+ budget.assertOwner = () => {
43534
+ assertOperation();
43535
+ if (!budget.sideTurn && passSessionId && contextPassGeneration.get(passSessionId) !== generation)
43536
+ throw new PiContextSupersededError("Pi context pass superseded before writer admission");
43537
+ signal?.throwIfAborted();
43538
+ };
43539
+ let assertCurrentPass = budget.assert;
43540
+ const guardAwait = budget.wait;
43541
+ const passGuard = { assert: assertCurrentPass, wait: guardAwait };
43542
+ guardSqliteTransformPass({
43543
+ assert: assertCurrentPass,
43544
+ remainingMs: () => budget.remainingWork()
43545
+ });
43546
+ budget.stage = "schema/claim";
43547
+ const toolWireSchema = await guardAwait(loadPiToolWireSchema());
43548
+ const transformStartTime = budget.startedAt;
42588
43549
  let rawMessageCount = 0;
42589
43550
  let rawFallbackLimit;
42590
43551
  let sessionIdForError;
42591
- let sessionMetaForPass;
42592
43552
  let lkgPassSnapshot;
42593
43553
  let lkgCompactionOff = baseOptions.compactionOff === true;
42594
43554
  let lkgEmergencyRecoveryArmed = false;
@@ -42616,17 +43576,21 @@ function registerPiContextHandler(pi, baseOptions) {
42616
43576
  const scheduler = schedulerFor(options);
42617
43577
  lkgCompactionOff = options.compactionOff === true;
42618
43578
  const projectIdentity = resolveProjectIdentityForSession(projectDirectory, options.allowHomeProject) ?? "";
42619
- updateSessionProjectTracking(sessionId, projectIdentity, options.db);
42620
43579
  logTransformTiming(sessionId, "findSessionId", tFindSession, `messages=${event.messages.length}`);
43580
+ budget.stage = "branch projection";
42621
43581
  const tEntryBranch = performance.now();
42622
43582
  const branchEntries = readPiBranchEntriesForContext(ctx, sessionId);
43583
+ assertCurrentPass();
42623
43584
  const piLiveUsageIsRawBranchEstimate = isPiLiveUsageRawBranchEstimate(branchEntries);
42624
43585
  recordPiLiveUsageClassification(sessionId, piLiveUsageIsRawBranchEstimate);
42625
- schedulePiTransformDecisionResolve({
42626
- db: options.db,
42627
- sessionId,
42628
- branchEntries
42629
- });
43586
+ assertCurrentPass();
43587
+ if (!budget.sideTurn)
43588
+ schedulePiTransformDecisionResolve({
43589
+ db: options.db,
43590
+ sessionId,
43591
+ branchEntries,
43592
+ assertCurrentPass
43593
+ });
42630
43594
  let rawOrdinalCount;
42631
43595
  const rawMessageProvider = {
42632
43596
  getMessageCount: () => rawOrdinalCount ??= branchEntries !== null ? countPiRawMessages(branchEntries) : readPiSessionMessages(ctx).length,
@@ -42638,21 +43602,63 @@ function registerPiContextHandler(pi, baseOptions) {
42638
43602
  const unregisterRaw = setRawMessageProvider2(sessionId, rawMessageProvider);
42639
43603
  rawMessageProviderUnregistersBySession.set(sessionId, unregisterRaw);
42640
43604
  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);
43605
+ const alignedEntryIds = branchEntries === null ? null : getPiBranchEntryLookup(branchEntries).alignedEntryIds;
43606
+ const resolvedEntryIds = resolvePiEventEntryIds(ctx, event.messages, sessionId, branchEntries);
42644
43607
  const strictEntryIds = resolvedEntryIds ? [...resolvedEntryIds] : null;
42645
43608
  const lkgEntryIds = reconcilePiLkgEntryIds(strictEntryIds, alignedEntryIds);
42646
43609
  const lkgModelKey = resolvePiContextModelKey(ctx) ?? null;
42647
43610
  const lkgContextModel = ctx.model;
42648
43611
  const lkgProviderKey = typeof lkgContextModel?.provider === "string" ? lkgContextModel.provider : null;
42649
- lkgPassSnapshot = lkgCoordinator.beginPass({
43612
+ const snapshot = lkgCoordinator.beginPass({
42650
43613
  sessionId,
42651
43614
  messages: event.messages,
42652
43615
  entryIds: lkgEntryIds,
42653
43616
  modelKey: lkgModelKey,
42654
- providerKey: lkgProviderKey
43617
+ providerKey: lkgProviderKey,
43618
+ apiKey: ctx.model?.api ?? null,
43619
+ transport: ctx.model?.transport
42655
43620
  });
43621
+ lkgPassSnapshot = snapshot;
43622
+ let checkedReplay = false;
43623
+ budget.stage = "writer admission";
43624
+ assertCurrentPass();
43625
+ const sessionMetaForUsage = await guardAwait(withAsyncPrivilegedWriter(options.db, () => {
43626
+ assertCurrentPass();
43627
+ return getOrCreateSessionMeta(options.db, sessionId);
43628
+ }, {
43629
+ signal,
43630
+ budgetMs: budget.writerAllowance(),
43631
+ assertCurrentPass,
43632
+ jitter: true,
43633
+ beforeRetry: (error) => {
43634
+ assertCurrentPass();
43635
+ if (checkedReplay)
43636
+ return;
43637
+ checkedReplay = true;
43638
+ const state = loadPiHistorianStateSnapshot(options.db, sessionId);
43639
+ lkgEmergencyRecoveryArmed = state.needsEmergencyRecovery;
43640
+ if (state.detectedContextLimit > 0)
43641
+ rawFallbackLimit = resolvePiWindowGeometry({
43642
+ model: ctx.model,
43643
+ rawContextWindow: piUsage?.contextWindow,
43644
+ detectedContextLimit: state.detectedContextLimit
43645
+ })?.usableHard;
43646
+ if (lkgCompactionOff || lkgEmergencyRecoveryArmed || isProviderOverflowFailClosedProven(sessionId))
43647
+ return;
43648
+ const replay = lkgCoordinator.replay(snapshot, (id) => ctx.sessionManager.getEntry?.(id)?.parentId);
43649
+ if (!replay.ok)
43650
+ return;
43651
+ try {
43652
+ assertPiRawFallbackFits(replay.messages, rawFallbackLimit, (line) => logPiLkgRecovery(sessionId, line), error, readPiLkgFitEnvelope(ctx, pi, lkgModelKey, sessionDecisionCalibration(options.db, sessionId), toolWireSchema), replay.measuredPrefix);
43653
+ } catch {
43654
+ return;
43655
+ }
43656
+ logPiLkgRecovery(sessionId, `TRANSIENT STORAGE FAILURE ${piStorageErrorReason(error)}: LKG replay served ${replay.messages.length} messages instead of raw ${rawMessageCount}`);
43657
+ throw new PiLkgAdmissionReplay(replay.messages);
43658
+ }
43659
+ }));
43660
+ assertCurrentPass();
43661
+ updateSessionProjectTracking(sessionId, projectIdentity, options.db, projectDirectory);
42656
43662
  const lkgInputIdByRef = new Map;
42657
43663
  for (const input of lkgPassSnapshot.inputs)
42658
43664
  lkgInputIdByRef.set(event.messages[input.messageIndex], input.id);
@@ -42680,8 +43686,6 @@ function registerPiContextHandler(pi, baseOptions) {
42680
43686
  }
42681
43687
  }
42682
43688
  const tMeta = performance.now();
42683
- const sessionMetaForUsage = getOrCreateSessionMeta(options.db, sessionId);
42684
- sessionMetaForPass = sessionMetaForUsage;
42685
43689
  const historianStateForPass = options.compactionOff ? EMPTY_PI_HISTORIAN_STATE_SNAPSHOT : (() => {
42686
43690
  try {
42687
43691
  return loadPiHistorianStateSnapshot(options.db, sessionId);
@@ -42841,7 +43845,7 @@ function registerPiContextHandler(pi, baseOptions) {
42841
43845
  } catch (err) {
42842
43846
  sessionLog(sessionId, `transform: overflow state read failed: ${err instanceof Error ? err.message : String(err)}`);
42843
43847
  }
42844
- const sessionMeta = sessionMetaForUsage;
43848
+ let sessionMeta = sessionMetaForUsage;
42845
43849
  const modelKey = liveModelBySession.get(sessionId);
42846
43850
  const providerId = typeof ctx.model?.provider === "string" ? ctx.model.provider : undefined;
42847
43851
  const canUseEmptySentinels = modelAcceptsEmptyContent(providerId);
@@ -42953,14 +43957,25 @@ function registerPiContextHandler(pi, baseOptions) {
42953
43957
  if (now - lastNotifiedAt >= EMERGENCY_NOTIFICATION_COOLDOWN_MS) {
42954
43958
  lastEmergencyNotificationAtMs.set(sessionId, now);
42955
43959
  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 {}
43960
+ sessionLog(sessionId, `EMERGENCY: usage=${usagePercentage.toFixed(1)}% — notified user, evaluating available emergency reclaim`);
43961
+ }
43962
+ const historian = inFlightHistorian.get(sessionId);
43963
+ const visibleToolResults = new Set(event.messages.flatMap((message) => message.role === "toolResult" ? [message.toolCallId] : []));
43964
+ const toolTags = getTagsBySession(options.db, sessionId).filter((tag) => tag.type === "tool");
43965
+ const knownTools = new Set(toolTags.map((tag) => tag.messageId));
43966
+ const activeTools = new Set(toolTags.filter((tag) => tag.status === "active").map((tag) => tag.messageId));
43967
+ 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))));
43968
+ if (historian && !hasToolReclaim && getPendingOps(options.db, sessionId).length === 0 && !historyRefreshSessions.has(sessionId) && !deferredHistoryRefreshSessions.has(sessionId)) {
43969
+ budget.stage = "emergency historian";
43970
+ await budget.wait(historian);
43971
+ assertCurrentPass();
43972
+ sessionMeta = getOrCreateSessionMeta(options.db, sessionId);
43973
+ piM0M1PassSnapshot = options.injection ? createPiM0M1PassSnapshot({
43974
+ db: options.db,
43975
+ sessionId,
43976
+ compactionOff: false,
43977
+ sessionMeta
43978
+ }) : undefined;
42964
43979
  }
42965
43980
  if (emergencyRecoveryArmed && realUsagePercentageBeforeEmergencyBump < forceMaterializationPercentage && !inFlightHistorian.has(sessionId) && !hasEligiblePiCompartmentHistory(options.db, sessionId)) {
42966
43981
  try {
@@ -42983,7 +43998,17 @@ function registerPiContextHandler(pi, baseOptions) {
42983
43998
  }) / 100)) : undefined;
42984
43999
  logTransformTiming(sessionId, "prePipelineTotal", transformStartTime);
42985
44000
  const tRunPipeline = performance.now();
42986
- const result = await runPipeline({
44001
+ budget.stage = "pipeline";
44002
+ assertCurrentPass = budget.assertOutcome;
44003
+ guardSqliteTransformPass({
44004
+ assert: assertCurrentPass,
44005
+ remainingMs: budget.remainingOutcome
44006
+ });
44007
+ if (beforePipelineForTests)
44008
+ await budget.waitMandatory(beforePipelineForTests());
44009
+ assertCurrentPass();
44010
+ const result = await budget.waitMandatory(runPipeline({
44011
+ assertCurrentPass,
42987
44012
  db: options.db,
42988
44013
  tagger,
42989
44014
  sessionId,
@@ -43036,20 +44061,21 @@ function registerPiContextHandler(pi, baseOptions) {
43036
44061
  resolvedModelID: ctx.model?.id,
43037
44062
  canUseEmptySentinels,
43038
44063
  temporalAwareness: options.injection?.temporalAwareness === true,
43039
- appendCompaction: resolvePiAppendCompaction(ctx),
44064
+ appendCompaction: guardedPiAppendCompaction(ctx, assertCurrentPass),
43040
44065
  readBranchEntries: resolvePiReadBranchEntries(ctx),
43041
44066
  isSubagent: sessionMeta.isSubagent,
43042
44067
  compactionOff: options.compactionOff === true,
43043
44068
  injectionPassSnapshot: piM0M1PassSnapshot
43044
- });
44069
+ }));
43045
44070
  logTransformTiming(sessionId, "runPipeline", tRunPipeline);
43046
44071
  const postPipelineStart = performance.now();
43047
44072
  const tTransformDecision = performance.now();
43048
44073
  if (strictEntryIds) {
44074
+ assertCurrentPass();
43049
44075
  recordSuccessfulTaggedMessageIds(sessionId, strictEntryIds);
43050
44076
  }
43051
44077
  const piDecisionSnapshotNewestAssistant = result.bustedThisPass ? findNewestPiAssistantEntryId(branchEntries) : undefined;
43052
- if (piDecisionSnapshotNewestAssistant !== undefined) {
44078
+ const publishTransformDecision = !budget.sideTurn && piDecisionSnapshotNewestAssistant !== undefined ? () => {
43053
44079
  recordPendingPiTransformDecision(sessionId, {
43054
44080
  tsMs: Date.now(),
43055
44081
  decision: schedulerDecision,
@@ -43064,28 +44090,51 @@ function registerPiContextHandler(pi, baseOptions) {
43064
44090
  droppedCount: result.droppedCount,
43065
44091
  inputTokens: usageInputTokens,
43066
44092
  bustedThisPass: true
43067
- }, piDecisionSnapshotNewestAssistant);
43068
- }
44093
+ }, piDecisionSnapshotNewestAssistant, budget.assertDecisionPublication);
44094
+ } : undefined;
43069
44095
  logTransformTiming(sessionId, "transformDecisionAndReuseState", tTransformDecision);
43070
44096
  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
44097
+ const historian = options.historian;
44098
+ budget.stage = "historian scheduling";
44099
+ if (historian && !options.compactionOff && budget.remainingWork() > 0) {
44100
+ guardSqliteTransformPass({
44101
+ assert: budget.assert,
44102
+ remainingMs: () => budget.remainingWork()
43088
44103
  });
44104
+ try {
44105
+ budget.assert();
44106
+ maybeFireHistorian({
44107
+ startGuard: () => {
44108
+ if (!budget.completed)
44109
+ budget.assertOwner();
44110
+ if (budget.abandoned || budget.remainingWork() === 0)
44111
+ throw new PiContextDeadlineError(budget.diagnostic());
44112
+ },
44113
+ pi,
44114
+ ctx,
44115
+ sessionId,
44116
+ db: options.db,
44117
+ historian,
44118
+ isFirstContextPassForSession,
44119
+ activeTags: result.activeTags,
44120
+ rawMessageProvider,
44121
+ taggerFloor,
44122
+ sessionMeta,
44123
+ liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
44124
+ piUsage,
44125
+ minimumPercentage: usagePercentage,
44126
+ historianStateSnapshot: historianStateForPass,
44127
+ publishedHistoryRide: isCacheBusting
44128
+ });
44129
+ } catch (error) {
44130
+ budget.assertOutcome();
44131
+ sessionLog(sessionId, `historian scheduling skipped: ${String(error)}`);
44132
+ } finally {
44133
+ guardSqliteTransformPass({
44134
+ assert: budget.assertOutcome,
44135
+ remainingMs: budget.remainingOutcome
44136
+ });
44137
+ }
43089
44138
  }
43090
44139
  logTransformTiming(sessionId, "historianScheduling", tHistorianScheduling);
43091
44140
  const tPostTransform = performance.now();
@@ -43120,9 +44169,15 @@ function registerPiContextHandler(pi, baseOptions) {
43120
44169
  }
43121
44170
  logTransformTiming(sessionId, "storedHintReplay", tStoredHintReplay);
43122
44171
  const tAutoSearch = performance.now();
43123
- if (options.autoSearch?.enabled && !options.compactionOff) {
44172
+ budget.stage = "auto-search";
44173
+ if (options.autoSearch?.enabled && !options.compactionOff && budget.remainingWork() > PI_CONTEXT_BUDGET.searchMs) {
44174
+ guardSqliteTransformPass({
44175
+ assert: budget.assert,
44176
+ remainingMs: () => budget.remainingWork()
44177
+ });
43124
44178
  try {
43125
- outputMessages = await runAutoSearchHintForPi({
44179
+ outputMessages = await guardAwait(runAutoSearchHintForPi({
44180
+ passGuard,
43126
44181
  sessionId,
43127
44182
  db: options.db,
43128
44183
  messages: outputMessages,
@@ -43137,9 +44192,15 @@ function registerPiContextHandler(pi, baseOptions) {
43137
44192
  visibleMemoryIds: getVisibleMemoryIds(options.db, sessionId) ?? null,
43138
44193
  wordRules: cavemanWordRulesForLanguage(options.language)
43139
44194
  }
43140
- });
44195
+ }));
43141
44196
  } catch (err) {
44197
+ assertCurrentPass();
43142
44198
  sessionLog(sessionId, `auto-search failed: ${err instanceof Error ? err.message : String(err)}`);
44199
+ } finally {
44200
+ guardSqliteTransformPass({
44201
+ assert: budget.assertOutcome,
44202
+ remainingMs: budget.remainingOutcome
44203
+ });
43143
44204
  }
43144
44205
  }
43145
44206
  logTransformTiming(sessionId, "autoSearch", tAutoSearch);
@@ -43287,6 +44348,7 @@ function registerPiContextHandler(pi, baseOptions) {
43287
44348
  }
43288
44349
  logTransformTiming(sessionId, "channelNudgeAccounting", tChannelAccounting);
43289
44350
  const tWorkMetrics = performance.now();
44351
+ budget.stage = "bookkeeping";
43290
44352
  try {
43291
44353
  const metrics = computePiWorkMetrics(outputMessages);
43292
44354
  setSessionWorkMetrics(options.db, sessionId, metrics.newWorkTokens, metrics.totalInputTokens);
@@ -43336,19 +44398,27 @@ function registerPiContextHandler(pi, baseOptions) {
43336
44398
  sessionLog(sessionId, `transform completed in ${transformElapsedMs.toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
43337
44399
  runPiDebugAssertion(assertTailHygieneLastWriter);
43338
44400
  if (!options.compactionOff && (result.executedWorkThisPass || isCacheBusting || schedulerDecision === "execute")) {
43339
- const envelope = readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(options.db, sessionId));
44401
+ const envelope = readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(options.db, sessionId), toolWireSchema);
43340
44402
  const estimate = estimatePiOutgoingInputTokens(outputMessages, envelope, lkgPassSnapshot ? lkgCoordinator.measureOutgoingPrefix(lkgPassSnapshot, outputMessages, (id) => ctx.sessionManager.getEntry?.(id)?.parentId) : undefined, rawFallbackLimit);
43341
44403
  const refusal = outgoingContextRefusal(estimate, rawFallbackLimit, protectedToolTokenCount(getActiveTagsBySession(options.db, sessionId), options.protectedTools, envelope ? calibrationForModelKey(envelope.modelKey) : undefined));
43342
44404
  if (refusal)
43343
44405
  throw contextRefusalError(refusal);
43344
44406
  }
43345
44407
  let serializedOutput;
43346
- if (!lkgCompactionOff && lkgPassSnapshot) {
44408
+ budget.stage = "LKG/served publication";
44409
+ budget.assertOutcome();
44410
+ guardSqliteTransformPass({
44411
+ assert: budget.assertOutcome,
44412
+ remainingMs: () => Math.max(0, PI_CONTEXT_BUDGET.outcomeMs - budget.elapsed())
44413
+ });
44414
+ if (!budget.sideTurn && !lkgCompactionOff && lkgPassSnapshot) {
43347
44415
  let hostEnvelopeSignature;
43348
44416
  try {
43349
- hostEnvelopeSignature = readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionId))?.envelopeSignature;
44417
+ hostEnvelopeSignature = readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionId), toolWireSchema)?.envelopeSignature;
43350
44418
  } catch {}
44419
+ budget.assertOutcome();
43351
44420
  serializedOutput = lkgCoordinator.captureAppliedPass({
44421
+ assertCurrentPass: budget.assertOutcome,
43352
44422
  hostEnvelopeSignature,
43353
44423
  snapshot: lkgPassSnapshot,
43354
44424
  outputMessages,
@@ -43356,8 +44426,15 @@ function registerPiContextHandler(pi, baseOptions) {
43356
44426
  cacheBusting: result.bustedThisPass
43357
44427
  });
43358
44428
  }
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);
44429
+ budget.assertOutcome();
44430
+ if (!budget.sideTurn)
44431
+ capturePiServedArray(sessionId, outputMessages, {
44432
+ servedTagNumbers: result.servedTagNumbers,
44433
+ serializedOutput,
44434
+ assertCurrentPass: budget.assertOutcome
44435
+ });
44436
+ if (!budget.sideTurn)
44437
+ captureOpencodeReasoningBudgetStatus(sessionId, piReasoningStatusMessages(outputMessages), resolveKeepReasoningTokens(options.heuristics?.keepReasoningTokens, resolvePiContextModelKey(ctx)), isPrefixBoundThinkingModel(ctx.model?.provider, ctx.model?.id), sessionDecisionCalibration(options.db, sessionId).proseRatio);
43361
44438
  if (thinkingBindingRecoveryApplied) {
43362
44439
  try {
43363
44440
  clearThinkingBindingRecoveryIf(options.db, sessionId, thinkingBindingRecoveryApplied.flagTarget);
@@ -43365,14 +44442,34 @@ function registerPiContextHandler(pi, baseOptions) {
43365
44442
  sessionLog(sessionId, `thinking binding recovery cleanup deferred: ${error instanceof Error ? error.message : String(error)}`);
43366
44443
  }
43367
44444
  }
44445
+ budget.assertOutcome();
44446
+ publishTransformDecision?.();
43368
44447
  return { messages: outputMessages };
43369
44448
  } catch (err) {
44449
+ budget.assertOutcome();
44450
+ budget.stage = "recovery";
44451
+ if (err instanceof PiServedIdentityError) {
44452
+ if (sessionIdForError)
44453
+ clearPiLkgSessionState(sessionIdForError);
44454
+ throw new PiStorageBusyError({ cause: err });
44455
+ }
44456
+ if (err instanceof PiLkgAdmissionReplay && sessionIdForError) {
44457
+ budget.assertOutcome();
44458
+ if (!budget.sideTurn)
44459
+ capturePiServedArray(sessionIdForError, err.messages, {
44460
+ assertCurrentPass: budget.assertOutcome
44461
+ });
44462
+ budget.assertOutcome();
44463
+ budget.recovery = "fitting LKG before writer retries";
44464
+ return { messages: err.messages };
44465
+ }
43370
44466
  if ((isFailClosedBlockingError(err) || err instanceof EmergencyFailClosedError) && !baseOptions.compactionOff)
43371
44467
  throw err;
43372
44468
  if (!lkgCompactionOff && sessionIdForError && isProviderOverflowFailClosedProven(sessionIdForError)) {
43373
44469
  throw new EmergencyFailClosedError("Emergency recovery transform failed; refusing an unbounded raw fallback", { cause: err });
43374
44470
  }
43375
44471
  const message = err instanceof Error ? err.message : String(err);
44472
+ budget.failureReason = message;
43376
44473
  const stack = err instanceof Error ? err.stack : undefined;
43377
44474
  const transientStorageFailure = isTransientPiStorageError(err);
43378
44475
  const degradedPass = !lkgCompactionOff;
@@ -43385,14 +44482,21 @@ function registerPiContextHandler(pi, baseOptions) {
43385
44482
  assertPiRawFallbackFits(replay.messages, rawFallbackLimit, (line) => {
43386
44483
  if (sessionIdForError)
43387
44484
  logPiLkgRecovery(sessionIdForError, line);
43388
- }, err, readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionIdForError)), replay.measuredPrefix);
44485
+ }, err, readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionIdForError), toolWireSchema), replay.measuredPrefix);
43389
44486
  const reason = piStorageErrorReason(err);
43390
44487
  logPiLkgRecovery(sessionIdForError, `${failureLabel} ${reason}: LKG replay served ${replay.messages.length} messages instead of raw ${rawMessageCount}`);
43391
- capturePiServedArray(sessionIdForError, replay.messages);
44488
+ budget.assertOutcome();
44489
+ if (!budget.sideTurn)
44490
+ capturePiServedArray(sessionIdForError, replay.messages, {
44491
+ assertCurrentPass: budget.assertOutcome
44492
+ });
44493
+ budget.assertOutcome();
44494
+ budget.recovery = "fitting LKG replay";
43392
44495
  return { messages: replay.messages };
43393
44496
  }
43394
44497
  logPiLkgRecovery(sessionIdForError, `${failureLabel} ${piStorageErrorReason(err)}: LKG unavailable (${replay.reason}); refusing unreduced ${rawMessageCount}-message input`);
43395
44498
  } catch (replayError) {
44499
+ budget.assertOutcome();
43396
44500
  if (replayError instanceof PiStorageBusyError)
43397
44501
  throw replayError;
43398
44502
  logPiLkgRecovery(sessionIdForError, `${failureLabel} ${piStorageErrorReason(err)}: LKG replay unavailable (${replayError instanceof Error ? replayError.message : String(replayError)}); refusing unreduced ${rawMessageCount}-message input`);
@@ -43403,9 +44507,6 @@ function registerPiContextHandler(pi, baseOptions) {
43403
44507
  }
43404
44508
  if (transientStorageFailure)
43405
44509
  throw new PiStorageBusyError({ cause: err });
43406
- if (sessionIdForError && !transientStorageFailure) {
43407
- persistLastTransformErrorIfChanged(baseOptions.db, sessionIdForError, summarizeTransformError(err), sessionMetaForPass?.lastTransformError);
43408
- }
43409
44510
  if (!lkgCompactionOff && sessionIdForError) {
43410
44511
  throw new PiStorageBusyError({
43411
44512
  cause: err instanceof PiDegradedPassError ? err : new PiDegradedPassError("context-handler-failed", {
@@ -43416,6 +44517,23 @@ function registerPiContextHandler(pi, baseOptions) {
43416
44517
  log(`[magic-context][pi] context handler failed (continuing without mutation): ${message}`, stack);
43417
44518
  return;
43418
44519
  }
44520
+ };
44521
+ registerPiGuardedContext(pi, contextHandler, {
44522
+ compactionOff: (ctx) => (baseOptions.resolveForProject?.(ctx.cwd) ?? baseOptions).compactionOff === true,
44523
+ onRefusal: (ctx, budget, message, isCurrent) => {
44524
+ const sessionId = resolveSessionId2(ctx);
44525
+ if (!sessionId)
44526
+ return;
44527
+ withoutSqliteTransformPass(() => setImmediate(() => {
44528
+ if (!isCurrent())
44529
+ return;
44530
+ try {
44531
+ withSqliteBackgroundWriter(() => persistLastTransformErrorIfChanged(baseOptions.db, sessionId, budget.failureReason ?? message));
44532
+ } catch (error) {
44533
+ log(`[magic-context][pi] refused-turn diagnostic not persisted ${budget.diagnostic()}`, error);
44534
+ }
44535
+ }));
44536
+ }
43419
44537
  });
43420
44538
  log("[magic-context][pi] registered context handler (tagging + drops + nudges)");
43421
44539
  }
@@ -43609,12 +44727,15 @@ function spawnPiHistorianRun(args) {
43609
44727
  currentContextLimit,
43610
44728
  fallbackModelId
43611
44729
  } = args;
44730
+ args.startGuard?.();
43612
44731
  const holderId = crypto3.randomUUID();
43613
44732
  const controller = new AbortController;
43614
44733
  historianAbortControllers.set(sessionId, controller);
43615
- const runPromise = (async () => {
44734
+ const runPromise = withoutSqliteTransformPass(() => (async () => {
44735
+ await new Promise((resolve) => setTimeout(resolve, 0));
43616
44736
  if (controller.signal.aborted)
43617
44737
  return;
44738
+ args.startGuard?.();
43618
44739
  const lease = acquireCompartmentLease(db, sessionId, holderId);
43619
44740
  if (!lease) {
43620
44741
  sessionLog(sessionId, "historian skipped: compartment lease held by another process");
@@ -43627,6 +44748,9 @@ function spawnPiHistorianRun(args) {
43627
44748
  }
43628
44749
  const renewal = startPiCompartmentLeaseRenewal(db, sessionId, holderId);
43629
44750
  try {
44751
+ const runBoundary = typeof boundarySnapshot === "function" ? boundarySnapshot() : boundarySnapshot;
44752
+ if (!runBoundary)
44753
+ return;
43630
44754
  await runPiHistorian({
43631
44755
  db,
43632
44756
  sessionId,
@@ -43654,7 +44778,7 @@ function spawnPiHistorianRun(args) {
43654
44778
  const window = ctx.modelRegistry?.find(model.slice(0, slash), model.slice(slash + 1))?.contextWindow;
43655
44779
  return isSaneLimit(window) ? window : undefined;
43656
44780
  },
43657
- boundarySnapshot,
44781
+ boundarySnapshot: runBoundary,
43658
44782
  refreshBoundarySnapshot,
43659
44783
  currentContextLimit,
43660
44784
  historianTimeoutMs: historian.timeoutMs,
@@ -43713,7 +44837,7 @@ function spawnPiHistorianRun(args) {
43713
44837
  } catch (error) {
43714
44838
  sessionLog(sessionId, `pi historian finalizer failed: ${error instanceof Error ? error.message : String(error)}`);
43715
44839
  }
43716
- });
44840
+ }));
43717
44841
  inFlightHistorian.set(sessionId, runPromise);
43718
44842
  historian.onStatusChange?.(ctx, sessionId);
43719
44843
  }
@@ -43723,6 +44847,13 @@ function resolvePiAppendCompaction(ctx) {
43723
44847
  return;
43724
44848
  return sm.appendCompaction.bind(sm);
43725
44849
  }
44850
+ function guardedPiAppendCompaction(ctx, assertCurrentPass) {
44851
+ const append = resolvePiAppendCompaction(ctx);
44852
+ return append ? (...args) => {
44853
+ assertCurrentPass();
44854
+ return append(...args);
44855
+ } : undefined;
44856
+ }
43726
44857
  function resolvePiReadBranchEntries(ctx) {
43727
44858
  const sm = ctx.sessionManager;
43728
44859
  if (typeof sm?.getBranch !== "function")
@@ -43821,7 +44952,6 @@ function maybeFireHistorian(args) {
43821
44952
  readMessages: () => readPiSessionMessages(ctx),
43822
44953
  readMessagePage: (afterOrdinal, limit, finalWatermark) => readPiSessionMessagePage(ctx, afterOrdinal, limit, finalWatermark)
43823
44954
  };
43824
- const unregister = setRawMessageProvider2(sessionId, provider);
43825
44955
  const modelKey = liveModelBySession.get(sessionId);
43826
44956
  const triggerInputs = resolvePiHistorianTriggerInputs({
43827
44957
  db,
@@ -43832,6 +44962,20 @@ function maybeFireHistorian(args) {
43832
44962
  });
43833
44963
  const historianForceMaterializationPercentage = escalationBands(triggerInputs.executeThresholdPercentage).forceMaterializationPercentage;
43834
44964
  const boundaryContextLimit = triggerInputs.contextLimit;
44965
+ if (isHistorianDrainBudgetSpent({
44966
+ db,
44967
+ sessionId,
44968
+ contextLimit: boundaryContextLimit,
44969
+ executeThresholdPercentage: triggerInputs.executeThresholdPercentage,
44970
+ usagePercentage: usage.percentage
44971
+ })) {
44972
+ if (sessionMeta.compartmentInProgress) {
44973
+ updateSessionMeta(db, sessionId, { compartmentInProgress: false });
44974
+ sessionMeta.compartmentInProgress = false;
44975
+ }
44976
+ return;
44977
+ }
44978
+ const unregister = setRawMessageProvider2(sessionId, provider);
43835
44979
  const resolvePiBoundarySnapshot = (emergencyTailScale) => resolveProtectedTailBoundary(resolveBoundaryContext({
43836
44980
  db,
43837
44981
  sessionId,
@@ -43863,16 +45007,19 @@ function maybeFireHistorian(args) {
43863
45007
  }
43864
45008
  const failureCount = historianStateSnapshot.historianFailureCount;
43865
45009
  if (failureCount > 0) {
43866
- boundarySnapshot = resolveRunnablePiBoundarySnapshot();
43867
- }
43868
- const shouldRecoverOnFirstPass = failureCount > 0 && boundarySnapshot !== undefined && hasEligiblePiCompartmentHistory(db, sessionId, boundarySnapshot);
43869
- if (shouldRecoverOnFirstPass) {
43870
45010
  triggered = true;
43871
- sessionLog(sessionId, `historian recovery triggered on session load after ${failureCount} failure(s)`);
43872
- sendPiIgnoredNotification(ctx, `## Historian recovery
45011
+ const prepareRecoveryBoundary = () => {
45012
+ const snapshot = resolveRunnablePiBoundarySnapshot();
45013
+ if (!hasEligiblePiCompartmentHistory(db, sessionId, snapshot))
45014
+ return;
45015
+ sessionLog(sessionId, `historian recovery triggered on session load after ${failureCount} failure(s)`);
45016
+ sendPiIgnoredNotification(ctx, `## Historian recovery
43873
45017
 
43874
45018
  Historian previously failed ${failureCount} time(s), so Magic Context is retrying history comparting immediately after restart.`);
45019
+ return snapshot;
45020
+ };
43875
45021
  spawnPiHistorianRun({
45022
+ startGuard: args.startGuard,
43876
45023
  pi: args.pi,
43877
45024
  ctx,
43878
45025
  sessionId,
@@ -43880,7 +45027,7 @@ Historian previously failed ${failureCount} time(s), so Magic Context is retryin
43880
45027
  historian,
43881
45028
  provider,
43882
45029
  unregister,
43883
- boundarySnapshot,
45030
+ boundarySnapshot: prepareRecoveryBoundary,
43884
45031
  refreshBoundarySnapshot: resolveRunnablePiBoundarySnapshot,
43885
45032
  currentContextLimit: boundaryContextLimit,
43886
45033
  fallbackModelId: modelKey
@@ -43915,6 +45062,7 @@ Historian previously failed ${failureCount} time(s), so Magic Context is retryin
43915
45062
  triggered = true;
43916
45063
  sessionLog(sessionId, `historian trigger fired (reason=${trigger.reason ?? "unknown"}) usage=${usage.percentage.toFixed(1)}% — spawning subagent`);
43917
45064
  spawnPiHistorianRun({
45065
+ startGuard: args.startGuard,
43918
45066
  pi: args.pi,
43919
45067
  ctx,
43920
45068
  sessionId,
@@ -44034,6 +45182,7 @@ async function runCompactionOffPipeline(args) {
44034
45182
  };
44035
45183
  }
44036
45184
  async function runPipeline(args) {
45185
+ args.assertCurrentPass?.();
44037
45186
  if (args.compactionOff)
44038
45187
  return runCompactionOffPipeline(args);
44039
45188
  const activeThinkingTurn = hasActiveAnthropicThinkingTurn(args.messages, args.resolvedProviderID, args.resolvedModelID);
@@ -44273,12 +45422,22 @@ async function runPipeline(args) {
44273
45422
  let protectionFloorResolution = resolveProtectionFloor();
44274
45423
  const shouldRunHeuristics = args.heuristics !== undefined && isCacheBustingPass && (rideSignals.publishedHistory || args.forceMaterialization === true || hasPendingMaterializeSignal || deferredMaterializeEligible || foldBustsServedPrefixThisPass || firstRenderBust || rideSignals.subagentExecute || args.schedulerDecision === "execute" && !alreadyRanHeuristicsThisTurn);
44275
45424
  const tFallbackIdentity = performance.now();
45425
+ const preflightRevision = readPiAdoptionRevision(args.db);
44276
45426
  const hasFallbackMessageTags = hasPiFallbackMessageTags2(args.db, args.sessionId);
44277
- const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, hasFallbackMessageTags);
45427
+ const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, hasFallbackMessageTags, hasFallbackMessageTags ? readPiFallbackFingerprintHeaders(args.db, args.sessionId) : undefined);
45428
+ args.assertCurrentPass?.();
44278
45429
  adoptPiFallbackTags(args.db, args.sessionId, args.tagger, entryFingerprintByMessageId, {
44279
45430
  messages: args.messages,
44280
45431
  resolveStableId: stableIdResolver,
44281
- hasFallbackMessageTags
45432
+ hasFallbackMessageTags,
45433
+ preflightRevision,
45434
+ rebuildFingerprints: args.reusableMessageIds?.size ? () => {
45435
+ args.assertCurrentPass?.();
45436
+ const full = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, true, readPiFallbackFingerprintHeaders(args.db, args.sessionId));
45437
+ for (const [id, fingerprint] of full)
45438
+ entryFingerprintByMessageId.set(id, fingerprint);
45439
+ return entryFingerprintByMessageId;
45440
+ } : undefined
44282
45441
  });
44283
45442
  logTransformTiming(args.sessionId, "fallbackIdentityAndAdoption", tFallbackIdentity);
44284
45443
  afterFallbackAdoptionForTests?.(args.stableIdSchemeCutover === true);
@@ -44294,22 +45453,25 @@ async function runPipeline(args) {
44294
45453
  tagToolTokenCache = new Map;
44295
45454
  piTagToolTokenCacheBySession.set(args.sessionId, tagToolTokenCache);
44296
45455
  }
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
- }));
45456
+ const { targets } = runPersistedReplayStage("tagging-persistence-failure", () => args.tagger.cleanup(args.sessionId), () => {
45457
+ args.assertCurrentPass?.();
45458
+ return tagTranscript(args.sessionId, transcript, args.tagger, args.db, {
45459
+ skipPrefixInjection: !ctxReduceCallable,
45460
+ entryFingerprintByMessageId,
45461
+ reuseMessageIds: textIdentityPlan.reusableMessageIds,
45462
+ textIdentityDriftMessageIds: textIdentityPlan.driftedMessageIds,
45463
+ textIdentitySourceCache: textIdentityPlan.sourceCache,
45464
+ textTokenCache: tagTextTokenCache,
45465
+ toolTokenCache: tagToolTokenCache,
45466
+ onTiming: hasPiTransformTimingObserver() ? (phase, elapsedMs) => {
45467
+ recordPiTransformTiming({
45468
+ sessionId: args.sessionId,
45469
+ stage: `tag:${phase}`,
45470
+ elapsedMs
45471
+ });
45472
+ } : undefined
45473
+ });
45474
+ });
44313
45475
  logTransformTiming(args.sessionId, "tagMessages", tTag);
44314
45476
  if (foldBustsServedPrefixThisPass) {
44315
45477
  try {
@@ -44815,6 +45977,7 @@ async function runPipeline(args) {
44815
45977
  let preserveDeferredMaterializationForMarkerDrain = false;
44816
45978
  if (deferredHistoryDrainEligible) {
44817
45979
  try {
45980
+ args.assertCurrentPass?.();
44818
45981
  const pending = getPendingPiCompactionMarkerState(args.db, args.sessionId);
44819
45982
  if (!pending) {
44820
45983
  if (injectionResult?.contentionExhausted === true) {
@@ -44835,6 +45998,7 @@ async function runPipeline(args) {
44835
45998
  preserveDeferredMaterializationForMarkerDrain = true;
44836
45999
  sessionLog(args.sessionId, "Pi compaction-marker drain skipped: sessionManager appendCompaction/getBranch or folding system state unavailable; preserving deferred signals");
44837
46000
  } else {
46001
+ args.assertCurrentPass?.();
44838
46002
  const outcome = applyDeferredPiCompactionMarker({
44839
46003
  db: args.db,
44840
46004
  appendCompaction: args.appendCompaction,
@@ -44877,6 +46041,7 @@ async function runPipeline(args) {
44877
46041
  }
44878
46042
  }
44879
46043
  } catch (err) {
46044
+ args.assertCurrentPass?.();
44880
46045
  sessionLog(args.sessionId, `Pi compaction-marker drain failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
44881
46046
  }
44882
46047
  }
@@ -44959,8 +46124,21 @@ async function runPipeline(args) {
44959
46124
  if (bustedThisPass || isCacheBustingPass) {
44960
46125
  droppedTokens = estimateDroppedTokensFromTagReductions(args.db, args.sessionId, droppedTokenReductions);
44961
46126
  }
46127
+ const visibleCallIds = new Set;
46128
+ for (const message of outputMessages) {
46129
+ if (message.role === "toolResult")
46130
+ visibleCallIds.add(message.toolCallId);
46131
+ if (message.role === "assistant" && Array.isArray(message.content)) {
46132
+ for (const part of message.content) {
46133
+ if (part.type === "toolCall")
46134
+ visibleCallIds.add(part.id);
46135
+ }
46136
+ }
46137
+ }
46138
+ 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
46139
  return {
44963
46140
  messages: outputMessages,
46141
+ servedTagNumbers,
44964
46142
  heuristicsExecuted,
44965
46143
  executedWorkThisPass,
44966
46144
  historyInjected: injectionResult?.injected ?? false,
@@ -45170,6 +46348,8 @@ function clearContextHandlerSession(sessionId) {
45170
46348
  deferredHistoryRefreshSessions.delete(sessionId);
45171
46349
  deferredMaterializationSessions.delete(sessionId);
45172
46350
  firstContextPassSeenBySession.delete(sessionId);
46351
+ contextPassGeneration.delete(sessionId);
46352
+ clearPiContextReceipt(sessionId);
45173
46353
  liveModelBySession.delete(sessionId);
45174
46354
  latestAssistantModelTimestampBySession.delete(sessionId);
45175
46355
  taggedStableMessageIdsBySession.delete(sessionId);
@@ -45183,6 +46363,7 @@ function clearContextHandlerSession(sessionId) {
45183
46363
  piTagToolTokenCacheBySession.delete(sessionId);
45184
46364
  piTextIdentitySourceCacheBySession.delete(sessionId);
45185
46365
  piBranchProjectionBySession.delete(sessionId);
46366
+ piAlignmentMismatchLoggedSessions.delete(sessionId);
45186
46367
  clearPiInjectionTokenCountCache(sessionId);
45187
46368
  clearPiTailHygieneContentMemo();
45188
46369
  clearPiChannel1State(sessionId);
@@ -45190,6 +46371,7 @@ function clearContextHandlerSession(sessionId) {
45190
46371
  routinePressureAppliedBySession.delete(sessionId);
45191
46372
  lastSeenProjectIdentityBySession.delete(sessionId);
45192
46373
  persistedProjectIdentityBySession.delete(sessionId);
46374
+ sessionProjectBindingFailureLogAtBySession.delete(sessionId);
45193
46375
  for (const [projectIdentity, sessions] of sessionsByProject) {
45194
46376
  sessions.delete(sessionId);
45195
46377
  if (sessions.size === 0)
@@ -48692,7 +49874,7 @@ function buildStatusViewFor(check, options) {
48692
49874
  // package.json
48693
49875
  var package_default = {
48694
49876
  name: "@retaw106/mmc-pi",
48695
- version: "2.0.0",
49877
+ version: "2.1.0",
48696
49878
  type: "module",
48697
49879
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
48698
49880
  main: "dist/index.js",
@@ -50525,17 +51707,17 @@ async function bootPiRuntimeWithDeadline(args) {
50525
51707
  }
50526
51708
 
50527
51709
  // src/pi-session-api.ts
50528
- import { existsSync as existsSync13, readFileSync as readFileSync13, realpathSync as realpathSync3, statSync as statSync6 } from "node:fs";
51710
+ import { existsSync as existsSync13, readFileSync as readFileSync14, realpathSync as realpathSync3, statSync as statSync7 } from "node:fs";
50529
51711
  import {
50530
51712
  basename as basename2,
50531
51713
  dirname as dirname7,
50532
51714
  extname,
50533
51715
  join as join12,
50534
51716
  relative,
50535
- resolve as resolve6,
51717
+ resolve as resolve7,
50536
51718
  sep
50537
51719
  } from "node:path";
50538
- import { pathToFileURL } from "node:url";
51720
+ import { pathToFileURL as pathToFileURL3 } from "node:url";
50539
51721
  var PI_CODING_AGENT_MODULE = "@earendil-works/pi-coding-agent";
50540
51722
  var CODING_AGENT_MODULES = [PI_CODING_AGENT_MODULE];
50541
51723
  var CODING_AGENT_MODULE_LABEL = CODING_AGENT_MODULES.join(" or ");
@@ -50550,7 +51732,7 @@ function isScriptEntry(filePath) {
50550
51732
  }
50551
51733
  function readManifest(pkgJsonPath) {
50552
51734
  try {
50553
- const pkg = JSON.parse(readFileSync13(pkgJsonPath, "utf8"));
51735
+ const pkg = JSON.parse(readFileSync14(pkgJsonPath, "utf8"));
50554
51736
  return pkg && typeof pkg === "object" ? pkg : null;
50555
51737
  } catch {
50556
51738
  return null;
@@ -50565,7 +51747,7 @@ function isCompiledBunBinary() {
50565
51747
  }
50566
51748
  function resolveRunningEntry() {
50567
51749
  const argv1 = process.argv[1];
50568
- if (argv1 && existsSync13(argv1) && statSync6(argv1).isFile()) {
51750
+ if (argv1 && existsSync13(argv1) && statSync7(argv1).isFile()) {
50569
51751
  const real = realpathSync3(argv1);
50570
51752
  if (isScriptEntry(real)) {
50571
51753
  return real;
@@ -50626,8 +51808,8 @@ function resolveManifestEntry(found) {
50626
51808
  if (!entryRel.startsWith("./")) {
50627
51809
  throw new Error(`Invalid entry "${entryRel}" in ${found.dir}/package.json: targets must start with "./"`);
50628
51810
  }
50629
- const root = resolve6(found.dir);
50630
- const resolved = resolve6(root, entryRel);
51811
+ const root = resolve7(found.dir);
51812
+ const resolved = resolve7(root, entryRel);
50631
51813
  if (resolved !== root && !resolved.startsWith(root + sep)) {
50632
51814
  throw new Error(`Invalid entry "${entryRel}" in ${found.dir}/package.json: target escapes the package root`);
50633
51815
  }
@@ -50660,14 +51842,14 @@ var defaultLoaders = [
50660
51842
  if (TS_ENTRY_PATTERN.test(entry)) {
50661
51843
  const srcEntry = toSourceEntry(entryPath, found.dir);
50662
51844
  if (!srcEntry && TS_ENTRY_PATTERN.test(entryPath) && existsSync13(entryPath)) {
50663
- return await import(pathToFileURL(entryPath).href);
51845
+ return await import(pathToFileURL3(entryPath).href);
50664
51846
  }
50665
51847
  if (srcEntry && existsSync13(srcEntry)) {
50666
- return await import(pathToFileURL(srcEntry).href);
51848
+ return await import(pathToFileURL3(srcEntry).href);
50667
51849
  }
50668
51850
  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
51851
  }
50670
- return await import(pathToFileURL(entryPath).href);
51852
+ return await import(pathToFileURL3(entryPath).href);
50671
51853
  }
50672
51854
  },
50673
51855
  {
@@ -50710,7 +51892,7 @@ async function loadDefaultPiSessionApi(loaders) {
50710
51892
  throw new Error("Pi session APIs unavailable: expected SessionManager.listAll on pi-coding-agent");
50711
51893
  }
50712
51894
  const loadEntriesFromFile = mod.loadEntriesFromFile ?? ((filePath) => {
50713
- const content = readFileSync13(filePath, "utf8");
51895
+ const content = readFileSync14(filePath, "utf8");
50714
51896
  return mod.parseSessionEntries?.(content) ?? [];
50715
51897
  });
50716
51898
  return {
@@ -50747,10 +51929,10 @@ import * as childProcess from "node:child_process";
50747
51929
  import {
50748
51930
  existsSync as existsSync14,
50749
51931
  mkdtempSync,
50750
- readFileSync as readFileSync14,
51932
+ readFileSync as readFileSync15,
50751
51933
  realpathSync as realpathSync4,
50752
51934
  rmSync as rmSync2,
50753
- statSync as statSync7,
51935
+ statSync as statSync8,
50754
51936
  writeFileSync as writeFileSync4
50755
51937
  } from "node:fs";
50756
51938
  import { createRequire } from "node:module";
@@ -50758,7 +51940,7 @@ import { homedir as homedir5, tmpdir } from "node:os";
50758
51940
  import {
50759
51941
  basename as basename3,
50760
51942
  dirname as dirname8,
50761
- isAbsolute as isAbsolute3,
51943
+ isAbsolute as isAbsolute4,
50762
51944
  join as join13,
50763
51945
  resolve as resolvePath,
50764
51946
  sep as sep2
@@ -50772,9 +51954,9 @@ var BUN_VIRTUAL_SCRIPT_PREFIX = "/$bunfs/root/";
50772
51954
  var WINDOWS_PI_EXTENSIONS = [".EXE", ".COM", ".CMD", ".BAT", ".PS1"];
50773
51955
  var DEFAULT_PI_RESOLUTION_FS = {
50774
51956
  existsSync: existsSync14,
50775
- statSync: statSync7,
51957
+ statSync: statSync8,
50776
51958
  realpathSync: realpathSync4,
50777
- readFileSync: readFileSync14
51959
+ readFileSync: readFileSync15
50778
51960
  };
50779
51961
  function packageHarnessKind(packageName) {
50780
51962
  return typeof packageName === "string" && PI_CODING_AGENT_PACKAGE_NAMES.has(packageName) ? "pi" : undefined;
@@ -50827,7 +52009,7 @@ function resolvePiBin(found, fs, checkedPaths) {
50827
52009
  const packageRoot = resolvePath(found.dir);
50828
52010
  const candidate = resolvePath(packageRoot, binEntry);
50829
52011
  checkedPaths.push(candidate);
50830
- if (isAbsolute3(binEntry) || !pathIsInside(packageRoot, candidate)) {
52012
+ if (isAbsolute4(binEntry) || !pathIsInside(packageRoot, candidate)) {
50831
52013
  return null;
50832
52014
  }
50833
52015
  try {
@@ -51046,7 +52228,7 @@ function configurePiSubagentExtensions(extensions) {
51046
52228
  function resolveSubagentExtensionEntry(entry, targetHarness) {
51047
52229
  const trimmed = entry.trim();
51048
52230
  const isNpmSource = trimmed.startsWith("npm:");
51049
- return !isNpmSource && !isAbsolute3(trimmed) ? resolvePath(getHostAgentSettingsDir(targetHarness), trimmed) : trimmed;
52231
+ return !isNpmSource && !isAbsolute4(trimmed) ? resolvePath(getHostAgentSettingsDir(targetHarness), trimmed) : trimmed;
51050
52232
  }
51051
52233
  var HISTORIAN_AGENTS = new Set([
51052
52234
  "magic-context-historian",
@@ -51857,6 +53039,19 @@ function terminateChild(child) {
51857
53039
  }
51858
53040
  }
51859
53041
 
53042
+ // src/timeout.ts
53043
+ function withTimeout(p, ms) {
53044
+ let handle;
53045
+ const timeout = new Promise((resolve) => {
53046
+ handle = setTimeout(() => resolve(undefined), ms);
53047
+ handle.unref?.();
53048
+ });
53049
+ return Promise.race([p, timeout]).finally(() => {
53050
+ if (handle)
53051
+ clearTimeout(handle);
53052
+ });
53053
+ }
53054
+
51860
53055
  // ../plugin/src/tools/parameter-descriptions.ts
51861
53056
  var FULL_PARAMETER_DESCRIPTIONS = {
51862
53057
  mmc_reduce: {
@@ -52031,7 +53226,7 @@ function resolveCtxExpandMode(args, domain) {
52031
53226
  }
52032
53227
 
52033
53228
  // ../plugin/src/tools/ctx-expand/render.ts
52034
- import { createHash as createHash18 } from "node:crypto";
53229
+ import { createHash as createHash19 } from "node:crypto";
52035
53230
  function isRecord7(value) {
52036
53231
  return value !== null && typeof value === "object" && !Array.isArray(value);
52037
53232
  }
@@ -52120,7 +53315,7 @@ function reasoningOf(part) {
52120
53315
  function renderPartPreview(part, expandTools) {
52121
53316
  if (!isRecord7(part))
52122
53317
  return null;
52123
- const expansion = expandToolPart(part, expandTools);
53318
+ const expansion = expandToolPart(part, expandTools, true);
52124
53319
  if (expansion !== null)
52125
53320
  return ` • tool ${part.tool}: ${expansion}`;
52126
53321
  const text = textOf(part);
@@ -52255,7 +53450,7 @@ function renderItemByTag(db, sessionId, number, textIndexDomain = "part") {
52255
53450
  const index = scoped ? Number(scoped[2]) : 0;
52256
53451
  const piText = message.parts.filter((part) => isRecord7(part) && part.type === "text");
52257
53452
  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]) : [];
53453
+ const matching = derived ? piText.filter((part) => isRecord7(part) && typeof part.text === "string" && createHash19("sha256").update(part.text).digest("hex") === derived[3]) : [];
52259
53454
  const selected = derived ? matching[Number(derived[4])] : textIndexDomain === "text" ? piText[index] : part;
52260
53455
  return selected ? renderPartFull(selected) ?? "" : `Tag ${number}'s original text part is no longer in stored history.`;
52261
53456
  }
@@ -54573,7 +55768,7 @@ function logNoProjectIdentityOnce(directory) {
54573
55768
  }
54574
55769
  var loggedPiConfigDirs = new Set;
54575
55770
  function logPiConfigLoad(args) {
54576
- const key = resolve7(args.dir);
55771
+ const key = resolve8(args.dir);
54577
55772
  if (args.dedupe && loggedPiConfigDirs.has(key))
54578
55773
  return;
54579
55774
  if (args.dedupe) {
@@ -55435,8 +56630,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
55435
56630
  existingSystemPrompt: event.systemPrompt
55436
56631
  });
55437
56632
  const composedPrompt = composeMagicContextSystemPrompt(event.systemPrompt, block);
56633
+ const promptOptions = event.systemPromptOptions;
56634
+ const hostSections = promptOptions?.sections;
56635
+ if (block && hostSections) {
56636
+ hostSections.magic_context = block;
56637
+ }
55438
56638
  if (!sessionId) {
55439
- if (block)
56639
+ if (block && !hostSections)
55440
56640
  return { systemPrompt: composedPrompt };
55441
56641
  return;
55442
56642
  }
@@ -55455,6 +56655,9 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
55455
56655
  if (isCacheBusting) {
55456
56656
  clearSystemPromptRefresh(sessionId);
55457
56657
  }
56658
+ if (hostSections) {
56659
+ return;
56660
+ }
55458
56661
  return { systemPrompt: result.systemPrompt };
55459
56662
  } catch (error) {
55460
56663
  warn("failed to build magic-context block:", error);