@cortexkit/pi-magic-context 0.42.4 → 0.42.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -107,6 +107,7 @@ import {
107
107
  getNullOwnerToolTag,
108
108
  adoptNullOwnerToolTag,
109
109
  resolveOpenCodeDbPath,
110
+ assertOpenCodeStoreGeneration,
110
111
  openCodeDbPathExists,
111
112
  recordOpenCodeDbReadFailure,
112
113
  clearOpenCodeDbReadFailure,
@@ -385,6 +386,18 @@ import {
385
386
  getActiveUserMemories,
386
387
  updateUserMemoryContent,
387
388
  dismissUserMemory,
389
+ getTaskScheduleState,
390
+ getMostRecentTaskRunAt,
391
+ pruneNonCanonicalTaskRows,
392
+ deleteTaskScheduleRowsForProject,
393
+ seedTaskScheduleState,
394
+ writeTaskScheduleState,
395
+ isRetrospectiveWindowProcessed,
396
+ recordRetrospectiveWindowProcessed,
397
+ curateCategoryForMemoryCategory,
398
+ peekCurateCategoryScope,
399
+ beginCurateCategoryRun,
400
+ curateTaskStateAfterSuccess,
388
401
  formatSynapseLaneDescriptor,
389
402
  buildCanonicalChunkTextFromFts,
390
403
  buildCompartmentSummaryFallbackText,
@@ -464,7 +477,7 @@ import {
464
477
  registerTodoStateLifecycle,
465
478
  syncCtxMemoryToolEnabled,
466
479
  registerMagicContextTools
467
- } from "./index-pbkqtaac.js";
480
+ } from "./index-r918mh6w.js";
468
481
  import {
469
482
  pushNotification2
470
483
  } from "./index-b3eqj1g6.js";
@@ -613,6 +626,9 @@ var DREAM_TASK_CAPABILITIES = {
613
626
  function formatDreamTaskBacklogs(backlogs, tasks = CANONICAL_DREAM_TASKS) {
614
627
  return tasks.filter((task) => backlogs[task] !== undefined).map((task) => {
615
628
  const backlog = backlogs[task];
629
+ if (task === "curate" && backlog?.category) {
630
+ return `- curate: ${backlog.category} (${backlog.pending})`;
631
+ }
616
632
  return `- ${task}: ${backlog?.pending ?? 0} pending / ${backlog?.total ?? 0} total`;
617
633
  }).join(`
618
634
  `);
@@ -1232,7 +1248,19 @@ async function runSessionProjectBackfill(db, source, options = {}) {
1232
1248
  let identityResolutionsSinceYield = 0;
1233
1249
  let afterSessionId = null;
1234
1250
  for (;; ) {
1235
- const sourcePage = await readPage(afterSessionId, SESSION_PAGE_SIZE);
1251
+ let sourcePage;
1252
+ try {
1253
+ sourcePage = await readPage(afterSessionId, SESSION_PAGE_SIZE);
1254
+ } catch (error) {
1255
+ try {
1256
+ if (!markBackfillRetryPending(db, harness, holderId, now())) {
1257
+ log("[session-projects] backfill lease changed before failure cleanup");
1258
+ }
1259
+ } catch (releaseError) {
1260
+ log(`[session-projects] failed to make backfill lease retryable after discovery failed: ${releaseError}`);
1261
+ }
1262
+ throw error;
1263
+ }
1236
1264
  if (sourcePage.length === 0)
1237
1265
  break;
1238
1266
  afterSessionId = sourcePage.at(-1)?.sessionId ?? afterSessionId;
@@ -2360,70 +2388,6 @@ function backoffMs(failureCount) {
2360
2388
  return minutes * 60 * 1000;
2361
2389
  }
2362
2390
 
2363
- // ../plugin/src/features/magic-context/dreamer/storage-task-schedule.ts
2364
- function toRow(r) {
2365
- return {
2366
- projectPath: r.project_path,
2367
- task: r.task,
2368
- lastRunAt: r.last_run_at,
2369
- nextDueAt: r.next_due_at,
2370
- schedule: r.schedule ?? null,
2371
- lastStatus: r.last_status ?? null,
2372
- lastError: r.last_error,
2373
- retryCount: r.retry_count ?? 0,
2374
- lastCheckedCommit: r.last_checked_commit ?? null,
2375
- lastBroadRunAt: r.last_broad_run_at ?? null,
2376
- retrospectiveWatermarkMs: r.retrospective_watermark_ms ?? null
2377
- };
2378
- }
2379
- var SELECT_COLUMNS = "project_path, task, last_run_at, next_due_at, schedule, last_status, last_error, retry_count, last_checked_commit, last_broad_run_at, retrospective_watermark_ms";
2380
- function getTaskScheduleState(db, projectPath, task) {
2381
- const row = db.prepare(`SELECT ${SELECT_COLUMNS} FROM task_schedule_state WHERE project_path = ? AND task = ?`).get(projectPath, task);
2382
- return row ? toRow(row) : null;
2383
- }
2384
- function getMostRecentTaskRunAt(db, projectPath) {
2385
- const row = db.prepare("SELECT MAX(last_run_at) AS max_at FROM task_schedule_state WHERE project_path = ?").get(projectPath);
2386
- const value = row?.max_at ?? null;
2387
- return typeof value === "number" && value > 0 ? value : null;
2388
- }
2389
- function pruneNonCanonicalTaskRows(db, projectPath, canonicalTasks) {
2390
- if (canonicalTasks.length === 0)
2391
- return 0;
2392
- const placeholders = canonicalTasks.map(() => "?").join(", ");
2393
- const result = db.prepare(`DELETE FROM task_schedule_state WHERE project_path = ? AND task NOT IN (${placeholders})`).run(projectPath, ...canonicalTasks);
2394
- return Number(result.changes ?? 0);
2395
- }
2396
- function deleteTaskScheduleRowsForProject(db, projectPath) {
2397
- const result = db.prepare("DELETE FROM task_schedule_state WHERE project_path = ?").run(projectPath);
2398
- return Number(result.changes ?? 0);
2399
- }
2400
- function seedTaskScheduleState(db, projectPath, task, nextDueAt, lastRunAt, schedule) {
2401
- db.prepare("INSERT INTO task_schedule_state (project_path, task, last_run_at, next_due_at, schedule, last_status, last_error, retry_count) VALUES (?, ?, ?, ?, ?, NULL, NULL, 0) ON CONFLICT(project_path, task) DO NOTHING").run(projectPath, task, lastRunAt, nextDueAt, schedule);
2402
- }
2403
- function writeTaskScheduleState(db, row) {
2404
- const broadCycleUpdate = row.lastBroadRunAt === undefined ? "last_broad_run_at = task_schedule_state.last_broad_run_at" : "last_broad_run_at = excluded.last_broad_run_at";
2405
- db.prepare(`INSERT INTO task_schedule_state
2406
- (project_path, task, last_run_at, next_due_at, schedule, last_status, last_error, retry_count, last_checked_commit, last_broad_run_at, retrospective_watermark_ms)
2407
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2408
- ON CONFLICT(project_path, task) DO UPDATE SET
2409
- last_run_at = excluded.last_run_at,
2410
- next_due_at = excluded.next_due_at,
2411
- schedule = excluded.schedule,
2412
- last_status = excluded.last_status,
2413
- last_error = excluded.last_error,
2414
- retry_count = excluded.retry_count,
2415
- last_checked_commit = COALESCE(excluded.last_checked_commit, task_schedule_state.last_checked_commit),
2416
- ${broadCycleUpdate},
2417
- retrospective_watermark_ms = COALESCE(excluded.retrospective_watermark_ms, task_schedule_state.retrospective_watermark_ms)`).run(row.projectPath, row.task, row.lastRunAt, row.nextDueAt, row.schedule, row.lastStatus, row.lastError, row.retryCount, row.lastCheckedCommit ?? null, row.lastBroadRunAt ?? null, row.retrospectiveWatermarkMs ?? null);
2418
- }
2419
- function isRetrospectiveWindowProcessed(db, projectPath, windowKey) {
2420
- const row = db.prepare("SELECT 1 AS one FROM retrospective_processed_windows WHERE project_path = ? AND window_key = ?").get(projectPath, windowKey);
2421
- return row != null;
2422
- }
2423
- function recordRetrospectiveWindowProcessed(db, projectPath, windowKey) {
2424
- db.prepare("INSERT INTO retrospective_processed_windows (project_path, window_key, processed_at) VALUES (?, ?, ?) ON CONFLICT(project_path, window_key) DO NOTHING").run(projectPath, windowKey, Date.now());
2425
- }
2426
-
2427
2391
  // ../plugin/src/features/magic-context/dreamer/task-gates.ts
2428
2392
  function countActiveMemories(db, projectPath) {
2429
2393
  const row = db.prepare("SELECT COUNT(*) AS cnt FROM memories WHERE project_path = ? AND status IN ('active','permanent')").get(projectPath);
@@ -2431,12 +2395,13 @@ function countActiveMemories(db, projectPath) {
2431
2395
  }
2432
2396
  function countLiveMemories(db, projectPath, options = {}) {
2433
2397
  const unclassified = options.unclassifiedOnly && hasMemoryClassifiedAtColumn(db);
2434
- const row = db.prepare(`SELECT COUNT(*) AS cnt
2435
- FROM memories
2436
- WHERE project_path = ?
2437
- AND status IN ('active','permanent')
2438
- AND (expires_at IS NULL OR expires_at > ?)
2439
- ${unclassified ? "AND classified_at IS NULL" : ""}`).get(projectPath, Date.now());
2398
+ const sql = `SELECT COUNT(*) AS cnt
2399
+ FROM memories
2400
+ WHERE project_path = ?
2401
+ AND status IN ('active','permanent')
2402
+ AND (expires_at IS NULL OR expires_at > ?)
2403
+ ${unclassified ? "AND classified_at IS NULL" : ""}`;
2404
+ const row = options.category ? db.prepare(`${sql} AND category = ?`).get(projectPath, Date.now(), options.category) : db.prepare(sql).get(projectPath, Date.now());
2440
2405
  return row?.cnt ?? 0;
2441
2406
  }
2442
2407
  function countUnmappedActiveMemories(db, projectPath) {
@@ -2547,8 +2512,13 @@ function getDreamTaskBacklog(db, projectPath, task, options = {}) {
2547
2512
  return { pending, total };
2548
2513
  }
2549
2514
  case "curate": {
2550
- const total = countLiveMemories(db, projectPath);
2551
- return { pending: total, total };
2515
+ const categories = db.prepare(`SELECT category FROM memories
2516
+ WHERE project_path = ?
2517
+ AND status IN ('active','permanent')
2518
+ AND (expires_at IS NULL OR expires_at > ?)`).all(projectPath, Date.now());
2519
+ const scope = peekCurateCategoryScope(db, projectPath, categories);
2520
+ const total = scope?.memories.length ?? 0;
2521
+ return scope ? { pending: total, total, category: scope.category } : { pending: 0, total: 0 };
2552
2522
  }
2553
2523
  case "compress-cues": {
2554
2524
  const total = countLiveMemories(db, projectPath);
@@ -2887,6 +2857,12 @@ function openOpenCodeDb() {
2887
2857
  }
2888
2858
  try {
2889
2859
  const db = new Database(dbPath, { readonly: true });
2860
+ try {
2861
+ assertOpenCodeStoreGeneration(db, "v1", dbPath);
2862
+ } catch (error) {
2863
+ db.close();
2864
+ throw error;
2865
+ }
2890
2866
  db.exec("PRAGMA busy_timeout = 5000");
2891
2867
  clearOpenCodeDbReadFailure();
2892
2868
  return db;
@@ -6186,9 +6162,11 @@ function buildCuratePrompt(args) {
6186
6162
 
6187
6163
  **Project:** ${args.projectPath}
6188
6164
 
6165
+ This run covers the whole of the \`${args.category}\` category (the other categories run in later windows).
6166
+
6189
6167
  The memories below are assumed ACCURATE (a separate verify task keeps them true). Your job is pool QUALITY: remove duplicates, tighten wording, and consolidate redundant entries that waste the ~6000-token injection budget. Explain each action in one line first. Do NOT mint new facts (that is the historian's job).
6190
6168
 
6191
- Work ALL THREE phases below in order (A → B → C) over the whole pool. Do NOT stop after consolidating — a run that only merges and never improves or archives is incomplete.
6169
+ Work ALL THREE phases below in order (A → B → C) over this category. Do NOT stop after consolidating — a run that only merges and never improves or archives is incomplete.
6192
6170
 
6193
6171
  ### Phase A — Consolidate duplicates
6194
6172
  Group by category, then merge near-identical / superset-subset / same-fact-different-angle clusters into one canonical memory with \`ctx_memory(action="merge", ids=[...], content="...", category="...")\`. Preserve every unique detail; terse present tense; paths/keys verbatim. Every id in a merge MUST share the same category — the system rejects cross-category merges. If two similar memories sit in different categories they are NOT duplicates; do not archive either as a consolidation. One fact per memory.
@@ -6408,6 +6386,7 @@ function buildDreamTaskPrompt(task, args) {
6408
6386
  case "curate":
6409
6387
  return buildCuratePrompt({
6410
6388
  projectPath: args.projectPath,
6389
+ category: args.curate?.category ?? "PROJECT_RULES",
6411
6390
  memories: args.curate?.memories ?? []
6412
6391
  });
6413
6392
  case "maintain-docs":
@@ -11210,6 +11189,7 @@ function createDreamTaskExecutor(deps) {
11210
11189
  processed: Math.max(0, processed),
11211
11190
  total: backlogAtStart.pending,
11212
11191
  startedAt,
11192
+ ...backlogAtStart.category ? { category: backlogAtStart.category } : {},
11213
11193
  ...refused === undefined ? {} : { refused: Math.max(0, refused) }
11214
11194
  });
11215
11195
  };
@@ -11262,7 +11242,8 @@ function createDreamTaskExecutor(deps) {
11262
11242
  totalAtStart: backlogAtStart.total,
11263
11243
  pendingAtEnd: end.pending,
11264
11244
  totalAtEnd: end.total,
11265
- processed
11245
+ processed,
11246
+ ...backlogAtStart.category ? { category: backlogAtStart.category } : {}
11266
11247
  };
11267
11248
  return value;
11268
11249
  })()
@@ -11868,6 +11849,7 @@ async function runAgenticTask(config, ctx, helpers) {
11868
11849
  let expiredArchived = 0;
11869
11850
  try {
11870
11851
  let curateMemories;
11852
+ let curateCategory;
11871
11853
  if (task === "curate") {
11872
11854
  expiredArchived = await archiveExpiredMemories({
11873
11855
  db,
@@ -11879,10 +11861,12 @@ async function runAgenticTask(config, ctx, helpers) {
11879
11861
  });
11880
11862
  if (leaseLost)
11881
11863
  throw new Error("Dream lease lost during expired-memory archive");
11882
- curateMemories = loadActiveMemoryPromptMemories(db, projectIdentity);
11883
- log(`[dreamer] curate pool: in_scope=${curateMemories.length} expired_archived=${expiredArchived}`);
11884
- if (curateMemories.length === 0 && expiredArchived > 0) {
11885
- const progress = formatExpiredArchiveProgress(expiredArchived);
11864
+ const scope = beginCurateCategoryRun(db, projectIdentity, loadActiveMemoryPromptMemories(db, projectIdentity));
11865
+ curateMemories = scope?.memories ?? [];
11866
+ curateCategory = scope?.category;
11867
+ log(`[dreamer] curate pool: category=${curateCategory ?? "none"} in_scope=${curateMemories.length} expired_archived=${expiredArchived}`);
11868
+ if (curateMemories.length === 0) {
11869
+ const progress = expiredArchived > 0 ? formatExpiredArchiveProgress(expiredArchived) : "curate: no populated project-memory category";
11886
11870
  helpers.recordRun("completed", null, {
11887
11871
  memoryChanges: helpers.computeMemoryDelta(memoryBefore),
11888
11872
  progress
@@ -11894,7 +11878,7 @@ async function runAgenticTask(config, ctx, helpers) {
11894
11878
  projectPath: projectIdentity,
11895
11879
  lastDreamAt: lastRunAt ? String(lastRunAt) : null,
11896
11880
  existingDocs,
11897
- curate: curateMemories ? { memories: curateMemories } : undefined
11881
+ curate: curateMemories && curateCategory ? { category: curateCategory, memories: curateMemories } : undefined
11898
11882
  });
11899
11883
  const createResponse = await createChildSessionWithFence({
11900
11884
  client: requireDreamClient(deps.client),
@@ -11986,16 +11970,34 @@ async function runAgenticTask(config, ctx, helpers) {
11986
11970
  }
11987
11971
  }
11988
11972
  const curateOutput = task === "curate" ? run.validated : undefined;
11973
+ const curateScopeProgress = task === "curate" && curateCategory && curateMemories ? `curate: ${curateCategory} (${curateMemories.length})` : null;
11989
11974
  const progress = [
11975
+ curateScopeProgress,
11990
11976
  expiredArchived > 0 ? formatExpiredArchiveProgress(expiredArchived) : null,
11991
11977
  curateOutput && curateOutput.memoryOperations.completedActions.length > 0 ? formatCurateMemoryOperations(curateOutput.memoryOperations.completedActions) : null,
11992
11978
  curateRefused > 0 ? `curate: refused ${curateRefused} unsafe mutation(s)` : null
11993
11979
  ].filter((value) => Boolean(value)).join("; ");
11980
+ const curateCount = task === "curate" && curateCategory ? loadActiveMemoryPromptMemories(db, projectIdentity).filter((memory) => curateCategoryForMemoryCategory(memory.category) === curateCategory).length : undefined;
11981
+ const curateBacklog = curateCount !== undefined && curateCategory ? {
11982
+ pending: curateCount,
11983
+ total: curateCount,
11984
+ category: curateCategory
11985
+ } : undefined;
11994
11986
  helpers.recordRun("completed", null, {
11995
11987
  memoryChanges: helpers.computeMemoryDelta(memoryBefore),
11996
- progress: progress || null
11988
+ progress: progress || null,
11989
+ backlogAfter: curateBacklog
11997
11990
  });
11998
- return { status: "completed", ...progress ? { detail: progress } : {} };
11991
+ return {
11992
+ status: "completed",
11993
+ ...progress ? { detail: progress } : {},
11994
+ ...curateBacklog ? { backlog: curateBacklog } : {},
11995
+ ...curateCategory ? {
11996
+ schedulePatch: {
11997
+ taskStateJson: curateTaskStateAfterSuccess(db, projectIdentity, curateCategory)
11998
+ }
11999
+ } : {}
12000
+ };
11999
12001
  } finally {
12000
12002
  heartbeat.stop();
12001
12003
  if (childSessionId)
@@ -12060,16 +12062,17 @@ function planDueTasks(db, projectIdentity, tasks, now) {
12060
12062
  }
12061
12063
  return due;
12062
12064
  }
12063
- function advanceAfterRun(db, projectIdentity, due, finishedAt, status, error, schedulePatch) {
12065
+ function advanceAfterRun(db, projectIdentity, due, finishedAt, status, error, schedulePatch, startedAt) {
12064
12066
  writeTaskScheduleState(db, {
12065
12067
  projectPath: projectIdentity,
12066
12068
  task: due.config.task,
12067
- lastRunAt: status === "completed" ? finishedAt : readLastRunAt(db, projectIdentity, due.config.task),
12069
+ lastRunAt: status === "completed" ? startedAt ?? finishedAt : readLastRunAt(db, projectIdentity, due.config.task),
12068
12070
  nextDueAt: nextDueAtMs(due.config.schedule, finishedAt, due.scheduledAt),
12069
12071
  schedule: due.config.schedule,
12070
12072
  lastStatus: status,
12071
12073
  lastError: error,
12072
12074
  retryCount: 0,
12075
+ taskStateJson: schedulePatch?.taskStateJson,
12073
12076
  retrospectiveWatermarkMs: schedulePatch?.retrospectiveWatermarkMs
12074
12077
  });
12075
12078
  }
@@ -12148,6 +12151,7 @@ async function runDomainGroup(deps, group, cb) {
12148
12151
  }
12149
12152
  }
12150
12153
  let outcome;
12154
+ const startedAt = Date.now();
12151
12155
  try {
12152
12156
  outcome = await executor(due.config, {
12153
12157
  db,
@@ -12161,8 +12165,8 @@ async function runDomainGroup(deps, group, cb) {
12161
12165
  }
12162
12166
  const finishedAt = Date.now();
12163
12167
  if (outcome.status === "completed") {
12164
- advanceAfterRun(db, projectIdentity, due, finishedAt, "completed", null, outcome.schedulePatch);
12165
- cb?.onRan?.(due.config.task, outcome.detail);
12168
+ advanceAfterRun(db, projectIdentity, due, finishedAt, "completed", null, outcome.schedulePatch, startedAt);
12169
+ cb?.onRan?.(due.config.task, outcome.detail, outcome.backlog);
12166
12170
  } else if (outcome.transient) {
12167
12171
  recordTransientFailure(db, projectIdentity, due, finishedAt, outcome.error ?? null);
12168
12172
  cb?.onFailed?.(due.config.task, outcome.failureDetail ?? outcome.error);
@@ -12229,6 +12233,7 @@ async function runManualDream(deps) {
12229
12233
  return result;
12230
12234
  }
12231
12235
  const groups = new Map;
12236
+ const runLocalBacklogs = {};
12232
12237
  for (const d of gated) {
12233
12238
  const kind = leaseKindFor(d.config.task);
12234
12239
  const arr = groups.get(kind) ?? [];
@@ -12238,10 +12243,12 @@ async function runManualDream(deps) {
12238
12243
  await Promise.all([...groups.values()].map((group) => runDomainGroup({ ...deps, executor: deps.executor }, group, {
12239
12244
  forceGate,
12240
12245
  leaseWaitMs: MANUAL_RUN_LEASE_WAIT_MS,
12241
- onRan: (t, detail) => {
12246
+ onRan: (t, detail, backlog) => {
12242
12247
  result.ran.push(t);
12243
12248
  if (detail)
12244
12249
  result.details?.push(detail);
12250
+ if (backlog)
12251
+ runLocalBacklogs[t] = backlog;
12245
12252
  },
12246
12253
  onFailed: (task, error) => {
12247
12254
  result.failed.push(task);
@@ -12250,7 +12257,10 @@ async function runManualDream(deps) {
12250
12257
  },
12251
12258
  onBusy: (t) => result.deferredBusy.push(t)
12252
12259
  })));
12253
- result.backlogAfter = getDreamTaskBacklogs(deps.db, deps.projectIdentity, selectedTaskNames);
12260
+ result.backlogAfter = {
12261
+ ...getDreamTaskBacklogs(deps.db, deps.projectIdentity, selectedTaskNames),
12262
+ ...runLocalBacklogs
12263
+ };
12254
12264
  return result;
12255
12265
  }
12256
12266
  async function runDueTasksForProject(deps) {
@@ -14022,6 +14032,16 @@ import {
14022
14032
  } from "node:path";
14023
14033
  import { pathToFileURL } from "node:url";
14024
14034
  var PI_CODING_AGENT_MODULE2 = "@earendil-works/pi-coding-agent";
14035
+ var OMP_CODING_AGENT_MODULE = "@oh-my-pi/pi-coding-agent";
14036
+ var CODING_AGENT_MODULES = [
14037
+ PI_CODING_AGENT_MODULE2,
14038
+ OMP_CODING_AGENT_MODULE
14039
+ ];
14040
+ var CODING_AGENT_MODULE_LABEL = CODING_AGENT_MODULES.join(" or ");
14041
+ var CODING_AGENT_PACKAGE_NAMES = new Set(CODING_AGENT_MODULES);
14042
+ function isCodingAgentPackageName(name) {
14043
+ return typeof name === "string" && CODING_AGENT_PACKAGE_NAMES.has(name);
14044
+ }
14025
14045
  var SCRIPT_ENTRY_PATTERN = /\.(mjs|cjs|mts|cts|js|ts|tsx|jsx)$/i;
14026
14046
  var TS_ENTRY_PATTERN = /\.(mts|cts|ts|tsx)$/i;
14027
14047
  function isScriptEntry(filePath) {
@@ -14056,11 +14076,11 @@ function findPackageRoot(startDir) {
14056
14076
  let dir = startDir;
14057
14077
  while (dir !== dirname2(dir)) {
14058
14078
  const pkg = readManifest(join5(dir, "package.json"));
14059
- if (pkg?.name === PI_CODING_AGENT_MODULE2) {
14079
+ if (isCodingAgentPackageName(pkg?.name)) {
14060
14080
  if (basename2(dir) === "dist") {
14061
14081
  const parentDir = dirname2(dir);
14062
14082
  const parentPkg = readManifest(join5(parentDir, "package.json"));
14063
- if (parentPkg?.name === PI_CODING_AGENT_MODULE2) {
14083
+ if (parentPkg?.name === pkg.name) {
14064
14084
  return { dir: parentDir, pkg: parentPkg };
14065
14085
  }
14066
14086
  }
@@ -14133,11 +14153,14 @@ var defaultLoaders = [
14133
14153
  }
14134
14154
  const found = findPackageRoot(dirname2(entry));
14135
14155
  if (!found) {
14136
- throw new Error(`Could not locate ${PI_CODING_AGENT_MODULE2} package.json from ${entry}`);
14156
+ throw new Error(`Could not locate ${CODING_AGENT_MODULE_LABEL} package.json from ${entry}`);
14137
14157
  }
14138
14158
  const entryPath = resolveManifestEntry(found);
14139
14159
  if (TS_ENTRY_PATTERN.test(entry)) {
14140
14160
  const srcEntry = toSourceEntry(entryPath, found.dir);
14161
+ if (!srcEntry && TS_ENTRY_PATTERN.test(entryPath) && existsSync7(entryPath)) {
14162
+ return await import(pathToFileURL(entryPath).href);
14163
+ }
14141
14164
  if (srcEntry && existsSync7(srcEntry)) {
14142
14165
  return await import(pathToFileURL(srcEntry).href);
14143
14166
  }
@@ -14149,6 +14172,10 @@ var defaultLoaders = [
14149
14172
  {
14150
14173
  name: "Bare import",
14151
14174
  load: async () => await import(PI_CODING_AGENT_MODULE2)
14175
+ },
14176
+ {
14177
+ name: "Bare import (OMP)",
14178
+ load: async () => await import(OMP_CODING_AGENT_MODULE)
14152
14179
  }
14153
14180
  ];
14154
14181
  var cachedModulePromise = null;
@@ -14166,7 +14193,7 @@ async function resolvePiCodingAgentModule(loaders) {
14166
14193
  errors.push(err);
14167
14194
  }
14168
14195
  }
14169
- throw new Error(`Failed to resolve ${PI_CODING_AGENT_MODULE2} via all strategies:
14196
+ throw new Error(`Failed to resolve a Pi/OMP coding-agent module (${CODING_AGENT_MODULE_LABEL}) via all strategies:
14170
14197
  ` + errors.map((e, i) => ` - ${activeLoaders[i].name}: ${e.message || e}`).join(`
14171
14198
  `) + `
14172
14199
  Likely cause: symlinked or nonstandard install layout.`);
@@ -16156,7 +16183,7 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
16156
16183
 
16157
16184
  // ../plugin/src/hooks/magic-context/cache-busting-signals.ts
16158
16185
  function hasReclaimRide(signals) {
16159
- return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory || signals.agentDrop;
16186
+ return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory;
16160
16187
  }
16161
16188
 
16162
16189
  // ../plugin/src/hooks/magic-context/caveman.ts
@@ -17552,6 +17579,73 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
17552
17579
  };
17553
17580
  }
17554
17581
 
17582
+ // ../plugin/src/hooks/magic-context/dropped-token-estimate.ts
17583
+ var TAG_QUERY_CHUNK_SIZE = 900;
17584
+ var ESTIMATED_CHARACTERS_PER_TOKEN = 3.5;
17585
+ function estimateCharacters(characters) {
17586
+ return Math.ceil(Math.max(0, characters) / ESTIMATED_CHARACTERS_PER_TOKEN);
17587
+ }
17588
+ function persistedCountOrByteEstimate(count, bytes) {
17589
+ return typeof count === "number" && Number.isFinite(count) ? Math.max(0, count) : estimateCharacters(bytes);
17590
+ }
17591
+ function loadPersistedTagTokenCounts(db, sessionId, tagNumbers) {
17592
+ const countsByTag = new Map;
17593
+ for (let offset = 0;offset < tagNumbers.length; offset += TAG_QUERY_CHUNK_SIZE) {
17594
+ const chunk = tagNumbers.slice(offset, offset + TAG_QUERY_CHUNK_SIZE);
17595
+ const placeholders = chunk.map(() => "?").join(",");
17596
+ const rows = db.prepare(`SELECT tag_number AS tagNumber,
17597
+ type,
17598
+ byte_size AS byteSize,
17599
+ input_byte_size AS inputByteSize,
17600
+ reasoning_byte_size AS reasoningByteSize,
17601
+ token_count AS tokenCount,
17602
+ input_token_count AS inputTokenCount,
17603
+ reasoning_token_count AS reasoningTokenCount
17604
+ FROM tags
17605
+ WHERE session_id = ? AND tag_number IN (${placeholders})`).all(sessionId, ...chunk);
17606
+ for (const row of rows)
17607
+ countsByTag.set(row.tagNumber, row);
17608
+ }
17609
+ return countsByTag;
17610
+ }
17611
+ function estimateDroppedTokensFromTagReductions(db, sessionId, reductions) {
17612
+ if (reductions.length === 0)
17613
+ return 0;
17614
+ const structuralByTag = new Map;
17615
+ const partialCharactersByTag = new Map;
17616
+ for (const reduction of reductions) {
17617
+ if (reduction.mode === "partial") {
17618
+ partialCharactersByTag.set(reduction.tagNumber, (partialCharactersByTag.get(reduction.tagNumber) ?? 0) + Math.max(0, reduction.removedCharacters));
17619
+ continue;
17620
+ }
17621
+ const prior = structuralByTag.get(reduction.tagNumber);
17622
+ if (!prior || reduction.mode === "full") {
17623
+ structuralByTag.set(reduction.tagNumber, reduction);
17624
+ }
17625
+ }
17626
+ const tagNumbers = [...new Set([...structuralByTag.keys(), ...partialCharactersByTag.keys()])];
17627
+ const countsByTag = loadPersistedTagTokenCounts(db, sessionId, tagNumbers);
17628
+ let total = 0;
17629
+ for (const [tagNumber, reduction] of structuralByTag) {
17630
+ const row = countsByTag.get(tagNumber);
17631
+ if (!row)
17632
+ continue;
17633
+ total += persistedCountOrByteEstimate(row.tokenCount, row.byteSize);
17634
+ if (reduction.mode === "full") {
17635
+ total += persistedCountOrByteEstimate(row.reasoningTokenCount, row.reasoningByteSize);
17636
+ if (row.type === "tool") {
17637
+ total += persistedCountOrByteEstimate(row.inputTokenCount, row.inputByteSize);
17638
+ }
17639
+ }
17640
+ }
17641
+ for (const [tagNumber, removedCharacters] of partialCharactersByTag) {
17642
+ if (structuralByTag.has(tagNumber) || !countsByTag.has(tagNumber))
17643
+ continue;
17644
+ total += estimateCharacters(removedCharacters);
17645
+ }
17646
+ return Math.max(0, Math.round(total));
17647
+ }
17648
+
17555
17649
  // ../plugin/src/hooks/magic-context/emergency-fail-closed.ts
17556
17650
  class EmergencyFailClosedError extends Error {
17557
17651
  code = "EMERGENCY_FAIL_CLOSED";
@@ -18898,17 +18992,65 @@ function persistFilteredNoise(db, sessionId, chunk, eligibleEnd) {
18898
18992
  }
18899
18993
 
18900
18994
  // ../plugin/src/hooks/magic-context/producer-window-guard.ts
18901
- var PRODUCER_WINDOW_REFUSAL_MARGIN = 0.15;
18995
+ var PRODUCER_WINDOW_REFUSAL_MARGIN = 0.03;
18996
+ var HISTORIAN_TRUNCATION_MARKER = "[… tokens truncated by Magic Context to fit the historian window …]";
18997
+ function producerInputTokenLimit(contextLimitTokens, maxOutputTokens) {
18998
+ if (typeof contextLimitTokens !== "number" || !Number.isFinite(contextLimitTokens) || contextLimitTokens <= 0 || !Number.isFinite(maxOutputTokens) || maxOutputTokens < 0) {
18999
+ return;
19000
+ }
19001
+ const usableInputTokens = Math.max(0, Math.floor(contextLimitTokens - maxOutputTokens));
19002
+ return Math.max(0, Math.floor(usableInputTokens * (1 - PRODUCER_WINDOW_REFUSAL_MARGIN)));
19003
+ }
18902
19004
  function producerWindowFailureReason(input) {
18903
19005
  const { producerSourceTokens, contextLimitTokens, maxOutputTokens } = input;
18904
- if (typeof contextLimitTokens !== "number" || !Number.isFinite(contextLimitTokens) || contextLimitTokens <= 0 || !Number.isFinite(producerSourceTokens) || producerSourceTokens <= 0 || !Number.isFinite(maxOutputTokens) || maxOutputTokens < 0) {
19006
+ const producerInputLimitTokens = producerInputTokenLimit(contextLimitTokens, maxOutputTokens);
19007
+ if (producerInputLimitTokens === undefined || typeof contextLimitTokens !== "number" || !Number.isFinite(producerSourceTokens) || producerSourceTokens <= 0) {
18905
19008
  return null;
18906
19009
  }
18907
19010
  const usableInputTokens = Math.max(0, Math.floor(contextLimitTokens - maxOutputTokens));
18908
- const refusalThreshold = usableInputTokens * (1 + PRODUCER_WINDOW_REFUSAL_MARGIN);
18909
- if (producerSourceTokens < refusalThreshold)
19011
+ if (producerSourceTokens <= producerInputLimitTokens)
18910
19012
  return null;
18911
- return `producer_source_exceeds_window producer_source_tokens=${Math.round(producerSourceTokens)} usable_input_tokens=${usableInputTokens} context_limit_tokens=${Math.round(contextLimitTokens)} max_output_tokens=${Math.round(maxOutputTokens)} refusal_margin=${PRODUCER_WINDOW_REFUSAL_MARGIN}`;
19013
+ return `producer_source_exceeds_window producer_source_tokens=${Math.round(producerSourceTokens)} usable_input_tokens=${usableInputTokens} producer_input_limit_tokens=${producerInputLimitTokens} context_limit_tokens=${Math.round(contextLimitTokens)} max_output_tokens=${Math.round(maxOutputTokens)} estimator_margin=${PRODUCER_WINDOW_REFUSAL_MARGIN}`;
19014
+ }
19015
+ function splitMarkerPair() {
19016
+ return `
19017
+ ${HISTORIAN_TRUNCATION_MARKER}
19018
+ ${HISTORIAN_TRUNCATION_MARKER}
19019
+ `;
19020
+ }
19021
+ function fitAtomicHistorianSourceToProducerWindow(args) {
19022
+ const producerInputLimitTokens = producerInputTokenLimit(args.contextLimitTokens, args.maxOutputTokens);
19023
+ const originalTokens = estimateTokens(args.text);
19024
+ if (producerInputLimitTokens === undefined || originalTokens < producerInputLimitTokens || producerInputLimitTokens <= 0) {
19025
+ return { text: args.text, producerInputLimitTokens, removedTokens: 0 };
19026
+ }
19027
+ const boundary = [...args.resultBoundaries ?? []].filter((candidate) => Number.isFinite(candidate.sourceOffset) && candidate.sourceOffset > 0 && candidate.sourceOffset < args.text.length).sort((a, b) => b.bodyTokens - a.bodyTokens || a.ordinal - b.ordinal)[0];
19028
+ const splitOffset = boundary?.sourceOffset ?? Math.floor(args.text.length / 2);
19029
+ const left = args.text.slice(0, splitOffset);
19030
+ const right = args.text.slice(splitOffset);
19031
+ const markers = splitMarkerPair();
19032
+ const target = producerInputLimitTokens;
19033
+ let lo = 0;
19034
+ let hi = 1;
19035
+ let best = markers;
19036
+ for (let iteration = 0;iteration < 48; iteration++) {
19037
+ const scale = (lo + hi) / 2;
19038
+ const leftLength = Math.floor(left.length * scale);
19039
+ const rightLength = Math.floor(right.length * scale);
19040
+ const candidate = left.slice(0, leftLength) + markers + right.slice(right.length - rightLength);
19041
+ if (estimateTokens(candidate) <= target) {
19042
+ best = candidate;
19043
+ lo = scale;
19044
+ } else {
19045
+ hi = scale;
19046
+ }
19047
+ }
19048
+ return {
19049
+ text: best,
19050
+ producerInputLimitTokens,
19051
+ ...boundary ? { splitBoundaryOrdinal: boundary.ordinal } : {},
19052
+ removedTokens: Math.max(0, originalTokens - estimateTokens(best))
19053
+ };
18912
19054
  }
18913
19055
 
18914
19056
  // ../plugin/src/hooks/magic-context/reference-seeds.generated.ts
@@ -21053,11 +21195,20 @@ async function runPiHistorian(deps) {
21053
21195
  chunkStart: chunk.startIndex,
21054
21196
  sessionCompartments: priorCompartments
21055
21197
  });
21056
- const chunkText = chunk.oversizeAtomicUnit ? chunk.text : truncateHistorianInputIfNeeded(chunk.text, historianChunkTokens);
21198
+ const fittedAtomicSource = chunk.oversizeAtomicUnit ? fitAtomicHistorianSourceToProducerWindow({
21199
+ text: chunk.text,
21200
+ resultBoundaries: chunk.toolResultBoundaries,
21201
+ contextLimitTokens: historianContextLimit,
21202
+ maxOutputTokens
21203
+ }) : null;
21204
+ const chunkText = chunk.oversizeAtomicUnit ? fittedAtomicSource?.text ?? chunk.text : truncateHistorianInputIfNeeded(chunk.text, historianChunkTokens);
21057
21205
  const producerSourceTokens = estimateTokens(chunkText);
21058
21206
  if (boundarySnapshot.oversizeAtomicUnit || chunk.oversizeAtomicUnit) {
21059
21207
  sessionLog(sessionId, `historian oversize admission: range=${chunk.startIndex}-${chunk.endIndex} rawComponentTokens=${boundarySnapshot.diagnostics?.head.completedFence.tokenMass ?? "unknown"} perRunCap=${perRunCap} producerSourceTokens=${producerSourceTokens} historianChunkTokens=${historianChunkTokens}; ${describeBoundaryDiagnostics(boundarySnapshot)}`);
21060
21208
  }
21209
+ if (fittedAtomicSource && fittedAtomicSource.removedTokens > 0) {
21210
+ sessionLog(sessionId, `historian pathological component split: range=${chunk.startIndex}-${chunk.endIndex} resultBoundary=${fittedAtomicSource.splitBoundaryOrdinal ?? "midpoint"} removedTokens=${fittedAtomicSource.removedTokens} producerSourceTokens=${producerSourceTokens} producerInputLimitTokens=${fittedAtomicSource.producerInputLimitTokens ?? "unknown"}`);
21211
+ }
21061
21212
  const producerWindowFailure = producerWindowFailureReason({
21062
21213
  producerSourceTokens,
21063
21214
  contextLimitTokens: historianContextLimit,
@@ -21791,6 +21942,7 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
21791
21942
  let deduplicatedTools = 0;
21792
21943
  let droppedInjections = 0;
21793
21944
  let droppedStaleReduceCalls = 0;
21945
+ const droppedTokenReductions = [];
21794
21946
  if (config.emergency) {
21795
21947
  const emergency = config.emergency;
21796
21948
  const priorInputSample = getEmergencyInputSample(db, sessionId);
@@ -21827,6 +21979,10 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
21827
21979
  updateTagDropMode(db, sessionId, tag.tagNumber, skeleton ? "truncated" : "full");
21828
21980
  droppedTools++;
21829
21981
  emergencyDroppedTools++;
21982
+ droppedTokenReductions.push({
21983
+ tagNumber: tag.tagNumber,
21984
+ mode: skeleton ? "truncated" : "full"
21985
+ });
21830
21986
  }
21831
21987
  }
21832
21988
  }).immediate();
@@ -21886,12 +22042,22 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
21886
22042
  updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
21887
22043
  if (dropResult === "removed" || didReplace) {
21888
22044
  droppedInjections++;
22045
+ droppedTokenReductions.push({
22046
+ tagNumber: tag.tagNumber,
22047
+ mode: "full"
22048
+ });
21889
22049
  }
21890
22050
  }
21891
22051
  } else {
21892
22052
  if (freezePiContentDecision(db, sessionId, "reminder-strip", tag.messageId)) {
21893
- if (target.setContent(stripped))
22053
+ if (target.setContent(stripped)) {
21894
22054
  droppedInjections++;
22055
+ droppedTokenReductions.push({
22056
+ tagNumber: tag.tagNumber,
22057
+ mode: "partial",
22058
+ removedCharacters: Math.max(0, content.length - stripped.length)
22059
+ });
22060
+ }
21895
22061
  }
21896
22062
  }
21897
22063
  }
@@ -21930,6 +22096,10 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
21930
22096
  updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
21931
22097
  if (result === "removed" || result === "truncated") {
21932
22098
  deduplicatedTools++;
22099
+ droppedTokenReductions.push({
22100
+ tagNumber: tag.tagNumber,
22101
+ mode: "full"
22102
+ });
21933
22103
  }
21934
22104
  }
21935
22105
  }
@@ -21948,6 +22118,15 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
21948
22118
  });
21949
22119
  compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
21950
22120
  mutatedTextTags = cavemanResult.mutatedTextTags;
22121
+ if (cavemanResult.textReductions) {
22122
+ for (const r of cavemanResult.textReductions) {
22123
+ droppedTokenReductions.push({
22124
+ tagNumber: r.tagNumber,
22125
+ mode: "partial",
22126
+ removedCharacters: r.removedCharacters
22127
+ });
22128
+ }
22129
+ }
21951
22130
  }
21952
22131
  return {
21953
22132
  droppedTools,
@@ -21956,7 +22135,8 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
21956
22135
  droppedStaleReduceCalls,
21957
22136
  emergencyDroppedTools,
21958
22137
  compressedTextTags,
21959
- mutatedTextTags
22138
+ mutatedTextTags,
22139
+ droppedTokenReductions
21960
22140
  };
21961
22141
  }
21962
22142
  function buildCtxReduceTagNumbers(tags) {
@@ -22023,7 +22203,7 @@ function memoizedContent(kind, content) {
22023
22203
  return cached;
22024
22204
  const measured = {
22025
22205
  hash: fnv1a32(key),
22026
- tokens: kind === "excluded" ? 0 : estimateTokens(content),
22206
+ tokens: kind === "excluded" ? 0 : undefined,
22027
22207
  keyBytes: key.length * 2 + 32
22028
22208
  };
22029
22209
  contentMemo.set(key, measured);
@@ -22040,7 +22220,11 @@ function memoizedContent(kind, content) {
22040
22220
  return measured;
22041
22221
  }
22042
22222
  function memoizedTokens(kind, content) {
22043
- return memoizedContent(kind, content).tokens;
22223
+ const measured = memoizedContent(kind, content);
22224
+ if (measured.tokens === undefined) {
22225
+ measured.tokens = estimateTokens(content);
22226
+ }
22227
+ return measured.tokens;
22044
22228
  }
22045
22229
  function partHash(kind, content) {
22046
22230
  return memoizedContent(kind, content).hash;
@@ -22518,7 +22702,7 @@ function refreshPiTailHygieneBaseline(input) {
22518
22702
  for (let index = input.previous.baselineParts.length;index < measured.parts.length; index += 1) {
22519
22703
  const part = measured.parts[index];
22520
22704
  turnDeltaT += part.tokens;
22521
- if (part.kind !== "toolOutput")
22705
+ if (part.kind !== "toolOutput" || !part.protected)
22522
22706
  turnDeltaU += part.uTokens;
22523
22707
  }
22524
22708
  return {
@@ -26497,7 +26681,7 @@ function memoryGuidanceBlock(memoryEnabled) {
26497
26681
  ` : "";
26498
26682
  }
26499
26683
  var BASE_INTRO = (memoryEnabled) => `Messages and tool outputs are tagged with §N§ identifiers (e.g., §1§, §42§).
26500
- Use \`ctx_reduce\` to mark spent tagged content as discardable and reclaim space. Marking is NOT an immediate delete — it queues the content, which stays fully visible until space is actually needed (as soon as the next turn if you're already under pressure, much later if not), so mark a tool output as soon as you're done with it rather than hoarding the call for the end of the turn. The newest token-mass window stays protected until displaced. Syntax: "3-5", "1,2,9", or "1-5,8,12-15".
26684
+ Use \`ctx_reduce\` to mark spent tagged content as discardable and reclaim space. Marking QUEUES content for release. It stays fully visible to you until it is actually released, which may be the next turn or many turns later. Mark a tool output as soon as you're done with it rather than hoarding the call for the end of the turn. The newest token-mass window stays protected until displaced. Syntax: "3-5", "1,2,9", or "1-5,8,12-15".
26501
26685
  Do not announce or narrate \`ctx_reduce\` drops — just call the tool silently. Saying "I'll drop these outputs" wastes tokens the user does not care about.
26502
26686
  ${CTX_NOTE_GUIDANCE}
26503
26687
  ${memoryGuidanceBlock(memoryEnabled)}Use \`ctx_search\` to search across project memories, indexed git commits, and this session's full conversation history (including compacted parts) from one query.
@@ -29629,7 +29813,8 @@ async function runPipeline(args) {
29629
29813
  let heuristicOrReasoningDidMutate = false;
29630
29814
  let didMutateFromFlushedStatuses = false;
29631
29815
  let droppedCount = 0;
29632
- const droppedTokens = 0;
29816
+ let droppedTokens = 0;
29817
+ const droppedTokenReductions = [];
29633
29818
  let emergency = false;
29634
29819
  let autoReclaimDidMutateThisPass = false;
29635
29820
  let suppressDeferredHistoryDrain = false;
@@ -29754,17 +29939,15 @@ async function runPipeline(args) {
29754
29939
  routinePressureAppliedBySession.set(args.sessionId, true);
29755
29940
  }
29756
29941
  const routinePressureAlreadyApplied = !args.sessionMeta.isSubagent && executePressureEligible && routinePressureAppliedBySession.get(args.sessionId) === true;
29757
- const historianRunning = inFlightHistorian.has(args.sessionId);
29758
- const publishedWorkDrainAllowed = args.schedulerDecision === "execute" || args.forceMaterialization === true || foldExecutedThisPass || firstRenderBust || hasPendingMaterialization(args.sessionId) || deferredMaterializeEligible;
29759
29942
  const hasPendingMaterializeSignal = hasPendingMaterialization(args.sessionId);
29760
29943
  const rideSignals = {
29761
29944
  hardFold: foldExecutedThisPass || firstRenderBust,
29762
- force: args.forceMaterialization === true || emergencyDropEligible,
29763
- explicitFlush: hasPendingMaterializeSignal || args.isCacheBusting,
29764
- publishedHistory: !prefixPreflightContended && (publishedM1RefreshedThisPass || canConsumeDeferredLate && deferredHistoryWasPendingAtPassStart),
29765
- agentDrop: false
29945
+ force: (args.forceMaterialization === true || emergencyDropEligible) && (args.contextUsage.percentage >= 95 || getEmergencyInputSample(args.db, args.sessionId) === 0),
29946
+ explicitFlush: hasPendingMaterializeSignal || deferredMaterializeEligible && !prefixPreflightContended,
29947
+ publishedHistory: !prefixPreflightContended && (args.isCacheBusting || publishedM1RefreshedThisPass || canConsumeDeferredLate && deferredHistoryWasPendingAtPassStart)
29766
29948
  };
29767
- let isCacheBustingPass = hasReclaimRide(rideSignals);
29949
+ const isCacheBustingPass = hasReclaimRide(rideSignals);
29950
+ const publishedWorkDrainAllowed = isCacheBustingPass;
29768
29951
  const usesTokenProtection = args.protectedTokenTierOverrides !== undefined || args.protectedTokens !== undefined;
29769
29952
  const resolveProtectionFloor = () => resolveEpochFloorForPass(args.db, args.sessionId, {
29770
29953
  configuredOverride: args.protectedTokens,
@@ -29829,15 +30012,14 @@ async function runPipeline(args) {
29829
30012
  }
29830
30013
  const deferredMaterializationWasPending = deferredMaterializationSessions.has(args.sessionId);
29831
30014
  const deferredHistoryRefreshWasPending = deferredHistoryWasPendingAtPassStart;
29832
- const shouldReadPendingOps = !args.compactionOff && (args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || foldExecutedThisPass || firstRenderBust || historianRunning);
30015
+ const shouldReadPendingOps = !args.compactionOff && (publishedWorkDrainAllowed || args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || foldExecutedThisPass || firstRenderBust);
29833
30016
  const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
29834
30017
  const protectionWindowForPass = getProtectionWindowForSession(args.db, args.sessionId, protectionFloorResolution.floor);
29835
30018
  const protectedTagNumbersForPass = usesTokenProtection ? protectionWindowForPass.protectedTagNumbers : newestActiveTagNumbersByCount(getActiveTagsBySession(args.db, args.sessionId), args.protectedTags);
29836
30019
  const pendingOperationTags = pendingOps.length > 0 ? getTagsForPendingOperations(args.db, args.sessionId, pendingOps.map((operation) => operation.tagId), usesTokenProtection ? 0 : args.protectedTags, RECENT_TOOL_SKELETON_WINDOW) : [];
29837
- const baseShouldApplyPendingOps = args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || foldExecutedThisPass || firstRenderBust;
29838
30020
  const deferredMaterialize = canConsumeDeferredLate && deferredMaterializationWasPending;
29839
30021
  const deferredHistoryRefresh = canConsumeDeferredLate && deferredHistoryRefreshWasPending;
29840
- const shouldApplyPendingOps = (baseShouldApplyPendingOps || deferredMaterialize) && publishedWorkDrainAllowed;
30022
+ const shouldApplyPendingOps = publishedWorkDrainAllowed;
29841
30023
  mutationGateObserverForTests?.({
29842
30024
  foldDue: foldDueDecision.value,
29843
30025
  foldExecuted: foldExecutedThisPass,
@@ -29853,15 +30035,11 @@ async function runPipeline(args) {
29853
30035
  pendingDecisionLogObserverForTests?.(pendingDecisionLog);
29854
30036
  try {
29855
30037
  const tApplyPending = performance.now();
29856
- pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, targets, args.contextUsage.percentage >= 95 ? newestCtxReduceTagNumbers(getTagsBySession(args.db, args.sessionId)) : protectedTagNumbersForPass, pendingOperationTags, pendingOps);
30038
+ pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, targets, args.contextUsage.percentage >= 95 ? newestCtxReduceTagNumbers(getTagsBySession(args.db, args.sessionId)) : protectedTagNumbersForPass, pendingOperationTags, pendingOps, [], new Set, (reduction) => droppedTokenReductions.push(reduction));
29857
30039
  if (pendingOpsDidMutate) {
29858
30040
  droppedCount += pendingOps.length;
29859
30041
  }
29860
30042
  logTransformTiming(args.sessionId, "applyPendingOperations", tApplyPending);
29861
- rideSignals.agentDrop = pendingOpsDidMutate;
29862
- isCacheBustingPass = hasReclaimRide(rideSignals);
29863
- if (pendingOpsDidMutate)
29864
- shouldRunHeuristics = args.heuristics !== undefined;
29865
30043
  executedWorkThisPass ||= isCacheBustingPass;
29866
30044
  materializationSatisfiedThisPass = true;
29867
30045
  pendingOpsAppliedThisPass = true;
@@ -29876,7 +30054,7 @@ async function runPipeline(args) {
29876
30054
  }
29877
30055
  } else {
29878
30056
  const pendingOpsDepth = getPendingOpsCount(args.db, args.sessionId);
29879
- const refusalReason = args.schedulerDeferReason ?? (historianRunning ? "historian_in_flight" : "scheduler_defer");
30057
+ const refusalReason = args.schedulerDeferReason ?? "no_originating_cache_bust";
29880
30058
  const pendingDecisionLog = `pending ops WILL NOT APPLY — reason=${refusalReason} pendingOps=${pendingOpsDepth === null ? "not loaded (deferred pass)" : pendingOpsDepth} context=${args.contextUsage.percentage.toFixed(1)}%`;
29881
30059
  sessionLog(args.sessionId, pendingDecisionLog);
29882
30060
  pendingDecisionLogObserverForTests?.(pendingDecisionLog);
@@ -29942,7 +30120,7 @@ async function runPipeline(args) {
29942
30120
  sessionLog(args.sessionId, heuristicsDecisionLog);
29943
30121
  pendingDecisionLogObserverForTests?.(heuristicsDecisionLog);
29944
30122
  } else {
29945
- const reason = args.heuristics === undefined ? "disabled" : args.schedulerDeferReason ?? (historianRunning ? "historian_in_flight" : alreadyRanHeuristicsThisTurn ? "already_ran_this_turn" : "scheduler_defer");
30123
+ const reason = args.heuristics === undefined ? "disabled" : args.schedulerDeferReason ?? (!isCacheBustingPass ? "no_originating_cache_bust" : alreadyRanHeuristicsThisTurn ? "already_ran_this_turn" : "scheduler_defer");
29946
30124
  const heuristicsDecisionLog = `heuristics WILL NOT RUN — reason=${reason}`;
29947
30125
  sessionLog(args.sessionId, heuristicsDecisionLog);
29948
30126
  pendingDecisionLogObserverForTests?.(heuristicsDecisionLog);
@@ -29982,7 +30160,11 @@ async function runPipeline(args) {
29982
30160
  droppedStaleReduceCalls: heuristicsResult.droppedStaleReduceCalls + ridingCleanup.droppedStaleReduceCalls,
29983
30161
  emergencyDroppedTools: heuristicsResult.emergencyDroppedTools,
29984
30162
  compressedTextTags: heuristicsResult.compressedTextTags + ridingCleanup.compressedTextTags,
29985
- mutatedTextTags: heuristicsResult.mutatedTextTags + ridingCleanup.mutatedTextTags
30163
+ mutatedTextTags: heuristicsResult.mutatedTextTags + ridingCleanup.mutatedTextTags,
30164
+ droppedTokenReductions: [
30165
+ ...heuristicsResult.droppedTokenReductions,
30166
+ ...ridingCleanup.droppedTokenReductions
30167
+ ]
29986
30168
  };
29987
30169
  routineCleanupApplied = true;
29988
30170
  }
@@ -29992,6 +30174,9 @@ async function runPipeline(args) {
29992
30174
  const heuristicMutationCount = heuristicsResult.droppedTools + heuristicsResult.deduplicatedTools + heuristicsResult.droppedInjections + heuristicsResult.droppedStaleReduceCalls + heuristicsResult.mutatedTextTags;
29993
30175
  droppedCount += heuristicsResult.droppedTools + heuristicsResult.deduplicatedTools + heuristicsResult.droppedInjections + heuristicsResult.droppedStaleReduceCalls + heuristicsResult.mutatedTextTags;
29994
30176
  emergency ||= heuristicsResult.emergencyDroppedTools > 0;
30177
+ if (heuristicsResult.droppedTokenReductions.length > 0) {
30178
+ droppedTokenReductions.push(...heuristicsResult.droppedTokenReductions);
30179
+ }
29995
30180
  if (heuristicMutationCount > 0)
29996
30181
  heuristicOrReasoningDidMutate = true;
29997
30182
  heuristicsExecuted = true;
@@ -30100,7 +30285,7 @@ async function runPipeline(args) {
30100
30285
  }
30101
30286
  autoReclaimTargetCount = syntheticPendingOps.length;
30102
30287
  if (syntheticPendingOps.length > 0) {
30103
- autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, targets, protectedTagNumbersForPass, undefined, [], syntheticPendingOps, editMarkerTagIds);
30288
+ autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, targets, protectedTagNumbersForPass, undefined, [], syntheticPendingOps, editMarkerTagIds, (reduction) => droppedTokenReductions.push(reduction));
30104
30289
  if (autoReclaimDidMutate) {
30105
30290
  droppedCount += syntheticPendingOps.length;
30106
30291
  autoReclaimDidMutateThisPass = true;
@@ -30364,6 +30549,9 @@ async function runPipeline(args) {
30364
30549
  pendingDropTagNumbers: new Set(channelPendingOps.filter((operation) => operation.operation === "drop").map((operation) => operation.tagId))
30365
30550
  };
30366
30551
  const bustedThisPass = firstRenderBust || didMutateFromFlushedStatuses || pendingOpsDidMutate || heuristicOrReasoningDidMutate || autoReclaimDidMutateThisPass || materialized || historyWasConsumedThisPass;
30552
+ if (bustedThisPass || isCacheBustingPass) {
30553
+ droppedTokens = estimateDroppedTokensFromTagReductions(args.db, args.sessionId, droppedTokenReductions);
30554
+ }
30367
30555
  return {
30368
30556
  messages: outputMessages,
30369
30557
  heuristicsExecuted,
@@ -32811,7 +32999,7 @@ function formatTailHygiene(status) {
32811
32999
  // package.json
32812
33000
  var package_default = {
32813
33001
  name: "@cortexkit/pi-magic-context",
32814
- version: "0.42.4",
33002
+ version: "0.42.6",
32815
33003
  type: "module",
32816
33004
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
32817
33005
  main: "dist/index.js",