@cortexkit/pi-magic-context 0.37.0 → 0.38.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,12 @@
1
1
  import {
2
2
  AGE_RECLAIM_MIN_TOKENS,
3
3
  BoundedSessionMap,
4
+ CHANNEL1_FLOOR_TOKENS,
5
+ CHANNEL1_SENTINEL,
4
6
  COMPACTION_ENABLED_PATH,
5
7
  COMPARTMENT_LEASE_RENEWAL_MS,
6
8
  COMPARTMENT_RENDER_EPOCH,
9
+ CTX_REDUCE_KEEP,
7
10
  DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE,
8
11
  DEFAULT_HISTORIAN_TIMEOUT_MS,
9
12
  DEFAULT_HISTORY_BUDGET_TOKENS,
@@ -37,6 +40,8 @@ import {
37
40
  backfillTagTokenCounts,
38
41
  beginBootQuietPeriod,
39
42
  buildCanonicalChunkTextFromFts,
43
+ buildChannel1Reminder,
44
+ buildChannel2Reminder,
40
45
  buildCompartmentSummaryFallbackText,
41
46
  buildPrimaryLanguageDirective,
42
47
  buildSyntheticTodoPart,
@@ -46,9 +51,11 @@ import {
46
51
  bumpProjectUserProfileVersion,
47
52
  byteSize,
48
53
  canonicalizeInMemoryChunkTextForEmbedding,
54
+ casChannel2NudgeClaim,
49
55
  casChannel2NudgeState,
50
56
  chunkCanonicalText,
51
57
  chunkEmbeddingWindowsAreCurrent,
58
+ claimChannel2NudgeState,
52
59
  cleanUserText,
53
60
  clearCachedM0M1,
54
61
  clearCompressionDepth,
@@ -82,6 +89,7 @@ import {
82
89
  createPrimer,
83
90
  createPromptSurfaceGuidanceEpochCache,
84
91
  createPromptSurfaceRuntime,
92
+ decideChannel1,
85
93
  decodeCachedM0UpgradeIdentity,
86
94
  deleteMemory,
87
95
  deleteUserMemoryCandidates,
@@ -91,6 +99,7 @@ import {
91
99
  describeError,
92
100
  dismissUserMemory,
93
101
  drainCommitBacklogForProject,
102
+ effectiveTailHygiene,
94
103
  embedBatchForProject,
95
104
  embedItemsForProject,
96
105
  embedPromotedFacts,
@@ -104,8 +113,10 @@ import {
104
113
  escalationBands,
105
114
  escapeXmlAttr,
106
115
  escapeXmlContent,
116
+ estimateImageTokensFromDataUrl,
107
117
  estimateTokens,
108
118
  estimateTrueRawMessageTokens,
119
+ evaluateChannel2,
109
120
  expandWorkspaceIdentitySetWithAliases,
110
121
  extractM0Block,
111
122
  extractTexts,
@@ -116,7 +127,6 @@ import {
116
127
  findPiFallbackToolOwnerTags,
117
128
  formatWindowDerivationLine,
118
129
  getActivePrimers,
119
- getActiveTagTokenAggregate,
120
130
  getActiveTagsBySession,
121
131
  getActiveToolTagsForAgeReclaim,
122
132
  getActiveUserMemories,
@@ -124,6 +134,7 @@ import {
124
134
  getAllStatusTagTokenTotalsFlat,
125
135
  getAutoSearchHintDecisions,
126
136
  getCachedAbsoluteMessageCount,
137
+ getChannel2NudgeClaim,
127
138
  getChannel2NudgeState,
128
139
  getCompactionModeRecord,
129
140
  getCompartments,
@@ -262,6 +273,7 @@ import {
262
273
  peelLeadingMcTagNotation,
263
274
  persistCachedM0,
264
275
  piModelRefToCanonical,
276
+ planEmergencyDrop,
265
277
  preloadTokenizer,
266
278
  prependTag,
267
279
  primeInMemoryTailRawMessageCache,
@@ -317,6 +329,7 @@ import {
317
329
  resolveModelRefForOmp,
318
330
  resolveModelRefForPi,
319
331
  resolveMuralWire,
332
+ resolveOutputReserve,
320
333
  resolvePiStableId,
321
334
  resolveProjectIdentity,
322
335
  resolveProjectIdentityForSession,
@@ -349,6 +362,7 @@ import {
349
362
  setStoragePrivatePermissionEnforcement,
350
363
  setTodoSnapshot,
351
364
  sourceNameForMemory,
365
+ stripChannel1ReminderSpans,
352
366
  stripMemoryMuralBlock,
353
367
  stripPersistedAssistantText,
354
368
  stripTagPrefix,
@@ -381,7 +395,7 @@ import {
381
395
  withMigrationLanguageDirective,
382
396
  withRawMessageProvider,
383
397
  withRawSessionMessageCache
384
- } from "./index-kvttksef.js";
398
+ } from "./index-8e0zezh7.js";
385
399
  import {
386
400
  pushNotification
387
401
  } from "./index-hw34xmzk.js";
@@ -397,7 +411,7 @@ import {
397
411
  import {
398
412
  __require,
399
413
  __toESM
400
- } from "./index-wckvcay0.js";
414
+ } from "./index-1yh8g550.js";
401
415
 
402
416
  // src/index.ts
403
417
  import { createRequire as createRequire3 } from "node:module";
@@ -577,24 +591,44 @@ function isMagicContextHiddenAgentName(agent) {
577
591
  return false;
578
592
  }
579
593
  var MAX_FORMATTED_BLOCKING_PROCESSES = 8;
594
+ function normalizeFailClosedProcessKind(process2) {
595
+ switch (process2.kind) {
596
+ case "OpenCode server":
597
+ case "OpenCode instance (TUI/CLI)":
598
+ case "Pi":
599
+ case "process":
600
+ return process2.kind;
601
+ }
602
+ switch (process2.harness?.trim().toLowerCase()) {
603
+ case "opencode server":
604
+ return "OpenCode server";
605
+ case "opencode instance (tui/cli)":
606
+ case "opencode instance":
607
+ return "OpenCode instance (TUI/CLI)";
608
+ case "pi":
609
+ case "pi harness":
610
+ case "omp":
611
+ return "Pi";
612
+ default:
613
+ return "process";
614
+ }
615
+ }
580
616
  function formatFailClosedBlockingProcesses(processes) {
581
617
  const uniqueProcesses = new Map;
582
618
  for (const process2 of processes) {
583
- if (!process2.harness.trim() || !Number.isInteger(process2.pid) || process2.pid <= 0)
619
+ if (!Number.isInteger(process2.pid) || process2.pid <= 0)
584
620
  continue;
585
- uniqueProcesses.set(`${process2.harness}\x00${process2.pid}`, {
586
- harness: process2.harness.trim(),
587
- pid: process2.pid
588
- });
621
+ const kind = normalizeFailClosedProcessKind(process2);
622
+ uniqueProcesses.set(`${kind}\x00${process2.pid}`, { kind, pid: process2.pid });
589
623
  }
590
624
  const entries = [...uniqueProcesses.values()];
591
625
  const visible = entries.slice(0, MAX_FORMATTED_BLOCKING_PROCESSES);
592
- const rendered = visible.map(({ harness, pid }) => `${harness} (PID ${pid})`);
626
+ const rendered = visible.map(({ kind, pid }) => `${kind} (PID ${pid})`);
593
627
  const omitted = entries.length - visible.length;
594
628
  if (omitted > 0)
595
629
  rendered.push(`${omitted} more blocking process(es)`);
596
630
  if (rendered.length === 0)
597
- return "a live harness process";
631
+ return "a live process";
598
632
  if (rendered.length === 1)
599
633
  return rendered[0];
600
634
  const last = rendered.pop();
@@ -604,9 +638,9 @@ function formatFailClosedBlockingMessage(reason) {
604
638
  if (reason.kind === "migration_guard") {
605
639
  if (reason.unreadableFile) {
606
640
  const arm = reason.unreadableArm ?? "io";
607
- const recovery = arm === "io" ? `If no OpenCode server is running, it is safe to delete ${reason.unreadableFile} and retry.` : `The file may be a recent incomplete write; retry after the file is older than the ten-minute grace window, or stop OpenCode before deleting it.`;
641
+ const recovery = arm === "io" ? `If none of these processes are running, it is safe to delete ${reason.unreadableFile} and retry.` : `The file may be a recent incomplete write; retry after the file is older than the ten-minute grace window, or stop the relevant process before deleting it.`;
608
642
  return [
609
- `Magic Context cannot migrate the shared database because RPC discovery file ${reason.unreadableFile} is uncertain (${arm} arm), so the absence of a live OpenCode server cannot be proven.`,
643
+ `Magic Context cannot migrate the shared database because RPC discovery file ${reason.unreadableFile} is uncertain (${arm} arm), so the absence of a live process cannot be proven.`,
610
644
  recovery,
611
645
  `Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
612
646
  ].join(" ");
@@ -3714,11 +3748,11 @@ async function trySendTuiToast(sessionId, text, params, forcePersist) {
3714
3748
  const message = text.length > 200 ? `${text.slice(0, 200)}…` : text;
3715
3749
  const toastVariant = inferToastVariant(text);
3716
3750
  const duration = params.toastDurationMs ?? 5000;
3717
- const { isTuiConnected: checkTui } = await import("./rpc-notifications-s2rw51c6.js");
3751
+ const { isTuiConnected: checkTui } = await import("./rpc-notifications-gmhvmfpy.js");
3718
3752
  if (!checkTui(sessionId))
3719
3753
  return false;
3720
3754
  try {
3721
- const { pushNotification: pushNotification2 } = await import("./rpc-notifications-s2rw51c6.js");
3755
+ const { pushNotification: pushNotification2 } = await import("./rpc-notifications-gmhvmfpy.js");
3722
3756
  pushNotification2("toast", {
3723
3757
  title,
3724
3758
  message,
@@ -3767,7 +3801,7 @@ async function sendIgnoredMessageNow(client, sessionId, text, params, forcePersi
3767
3801
  queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
3768
3802
  return "queued";
3769
3803
  }
3770
- const { waitForSafeNotificationTarget } = await import("./safe-notification-target-7n7s6xv7.js");
3804
+ const { waitForSafeNotificationTarget } = await import("./safe-notification-target-q00qgjm6.js");
3771
3805
  if (await waitForSafeNotificationTarget(client, sessionId) === "skip") {
3772
3806
  sessionLog(sessionId, "notification skipped (session not titled yet)");
3773
3807
  return "skipped";
@@ -3786,7 +3820,7 @@ async function sendIgnoredMessageNow(client, sessionId, text, params, forcePersi
3786
3820
  let model = params.providerId && params.modelId ? { providerID: params.providerId, modelID: params.modelId } : undefined;
3787
3821
  if (!agent || !model || !variant) {
3788
3822
  try {
3789
- const { resolvePromptContext } = await import("./prompt-context-602yq94t.js");
3823
+ const { resolvePromptContext } = await import("./prompt-context-3kjq9ejq.js");
3790
3824
  const resolved = await resolvePromptContext(client, sessionId);
3791
3825
  if (resolved) {
3792
3826
  agent = agent ?? resolved.agent;
@@ -4527,6 +4561,34 @@ function assertManifestCoversExactly(ids, expectedIds, rootName) {
4527
4561
  throw new Error(`${rootName} manifest missing id ${id}`);
4528
4562
  }
4529
4563
  }
4564
+ var OPEN_TAG_RE = /<([A-Za-z][\w:-]*)\b/;
4565
+ function describeUnrecognizedManifestShape(text, expectedRoot, expectedEntry) {
4566
+ const expected = `expected <${expectedRoot}> with <${expectedEntry}> entries`;
4567
+ const trimmed = text.trim();
4568
+ if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
4569
+ return `JSON ${trimmed.startsWith("[") ? "array" : "object"} unrecognized; ${expected}`;
4570
+ }
4571
+ const firstTag = OPEN_TAG_RE.exec(trimmed)?.[1];
4572
+ if (firstTag && firstTag.toLowerCase() !== expectedRoot.toLowerCase()) {
4573
+ return `root <${firstTag}> unrecognized; ${expected}`;
4574
+ }
4575
+ const escapedRoot = expectedRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4576
+ const bodyMatch = new RegExp(`<${escapedRoot}\\b[^>]*>([\\s\\S]*?)<\\/${escapedRoot}>`, "i").exec(text);
4577
+ const body = (bodyMatch?.[1] ?? "").trim();
4578
+ if (body.startsWith("[") || body.startsWith("{")) {
4579
+ return `JSON ${body.startsWith("[") ? "array" : "object"} unrecognized; ${expected}`;
4580
+ }
4581
+ const innerTag = OPEN_TAG_RE.exec(body)?.[1];
4582
+ if (innerTag && innerTag.toLowerCase() !== expectedEntry.toLowerCase()) {
4583
+ return `root <${innerTag}> unrecognized; ${expected}`;
4584
+ }
4585
+ return `parsed zero entries; ${expected}`;
4586
+ }
4587
+ function assertParsedManifestNonEmpty(parsedCount, expectedCount, text, expectedRoot, expectedEntry) {
4588
+ if (expectedCount > 0 && parsedCount === 0) {
4589
+ throw new Error(describeUnrecognizedManifestShape(text, expectedRoot, expectedEntry));
4590
+ }
4591
+ }
4530
4592
 
4531
4593
  // ../plugin/src/features/magic-context/dreamer/module-apply.ts
4532
4594
  class DreamerModuleBusyError extends Error {
@@ -5845,9 +5907,19 @@ ${renderAnchors(args.anchors ?? [])}### Memory pool to classify
5845
5907
  ${renderPool2(args.memories)}`;
5846
5908
  }
5847
5909
  var SCOPES = new Set(["project", "ecosystem", "universe"]);
5910
+ function classifyBody(text) {
5911
+ try {
5912
+ return extractCompleteManifestBody(text, "classify");
5913
+ } catch (error) {
5914
+ const described = describeUnrecognizedManifestShape(text, "classify", "memory");
5915
+ if (!described.startsWith("parsed zero entries"))
5916
+ throw new Error(described);
5917
+ throw error;
5918
+ }
5919
+ }
5848
5920
  function parseClassifyManifest(text) {
5849
5921
  const out = [];
5850
- const body = extractCompleteManifestBody(text, "classify");
5922
+ const body = classifyBody(text);
5851
5923
  for (const m of body.matchAll(/<memory\b([^>]*)\/?>/g)) {
5852
5924
  const attrs = m[1];
5853
5925
  const idMatch = attrs.match(/\bid\s*=\s*"(\d+)"/);
@@ -5880,9 +5952,18 @@ function parseClassifyManifest(text) {
5880
5952
  }
5881
5953
  out.push(entry);
5882
5954
  }
5955
+ if (out.length === 0 && body.trim().length > 0) {
5956
+ throw new Error(describeUnrecognizedManifestShape(text, "classify", "memory"));
5957
+ }
5883
5958
  assertNoDuplicateManifestIds(out.map((entry) => entry.id), "classify");
5884
5959
  return out;
5885
5960
  }
5961
+ function validateClassifyManifest(text, expectedIds) {
5962
+ const parsed = parseClassifyManifest(text);
5963
+ assertParsedManifestNonEmpty(parsed.length, expectedIds.size, text, "classify", "memory");
5964
+ assertManifestCoversExactly(parsed.map((entry) => entry.id), expectedIds, "classify");
5965
+ return parsed;
5966
+ }
5886
5967
 
5887
5968
  // ../plugin/src/features/magic-context/dreamer/classify.ts
5888
5969
  var MIN_POOL_TO_CLASSIFY = 10;
@@ -6081,7 +6162,7 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
6081
6162
  if (!text)
6082
6163
  throw new Error("classify returned no output");
6083
6164
  try {
6084
- parseClassifyManifest(text);
6165
+ validateClassifyManifest(text, new Set(chunk.map((candidate) => candidate.id)));
6085
6166
  } catch (error) {
6086
6167
  const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
6087
6168
  if (providerFailure)
@@ -6149,8 +6230,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
6149
6230
  if (result.truncated === true) {
6150
6231
  throw new Error("classify returned length-capped output");
6151
6232
  }
6152
- const parsed = parseClassifyManifest(manifestText);
6153
- assertManifestCoversExactly(parsed.map((entry) => entry.id), new Set(chunk.map((candidate) => candidate.id)), "classify");
6233
+ const parsed = validateClassifyManifest(manifestText, new Set(chunk.map((candidate) => candidate.id)));
6154
6234
  const rows = parsed.map((entry) => {
6155
6235
  const candidate = chunk.find((item) => item.id === entry.id);
6156
6236
  if (!candidate)
@@ -6802,8 +6882,8 @@ var asyncModulePromise = null;
6802
6882
  function getAsyncModule() {
6803
6883
  asyncModulePromise ??= (async () => {
6804
6884
  const [{ default: singlefileAsyncifyVariant }, { newQuickJSAsyncWASMModuleFromVariant }] = await Promise.all([
6805
- import("./index-ayd60xnw.js").then((m)=>__toESM(m.default,1)),
6806
- import("./index-3pnd4qh9.js")
6885
+ import("./index-rgdqj8nj.js").then((m)=>__toESM(m.default,1)),
6886
+ import("./index-8sseka65.js")
6807
6887
  ]);
6808
6888
  return newQuickJSAsyncWASMModuleFromVariant(singlefileAsyncifyVariant);
6809
6889
  })();
@@ -7947,11 +8027,33 @@ For each memory below, find the repo file(s) it makes a claim about, or mark it
7947
8027
  ${list}
7948
8028
  </memories>`;
7949
8029
  }
8030
+ var MEMORY_ELEMENT_PATTERN = "<memory\\b([^>]*)(?:\\/>|>([\\s\\S]*?)<\\/memory>)";
8031
+ var NESTED_FILE_PATTERN = "<file\\b([^>]*)\\/?>";
8032
+ function extractNestedFilePaths(inner) {
8033
+ const files = [];
8034
+ for (const match of inner.matchAll(new RegExp(NESTED_FILE_PATTERN, "gi"))) {
8035
+ const pathMatch = match[1].match(/\bpath\s*=\s*"([^"]+)"/);
8036
+ if (pathMatch)
8037
+ files.push(pathMatch[1].trim());
8038
+ }
8039
+ return files.filter(Boolean);
8040
+ }
8041
+ function mappingsBody(text) {
8042
+ try {
8043
+ return extractCompleteManifestBody(text, "mappings");
8044
+ } catch (error) {
8045
+ const described = describeUnrecognizedManifestShape(text, "mappings", "memory");
8046
+ if (!described.startsWith("parsed zero entries"))
8047
+ throw new Error(described);
8048
+ throw error;
8049
+ }
8050
+ }
7950
8051
  function parseMapMemoriesManifest(text) {
7951
8052
  const out = [];
7952
- const body = extractCompleteManifestBody(text, "mappings");
7953
- for (const m of body.matchAll(/<memory\b([^>]*)\/?>/g)) {
8053
+ const body = mappingsBody(text);
8054
+ for (const m of body.matchAll(new RegExp(MEMORY_ELEMENT_PATTERN, "gi"))) {
7954
8055
  const attrs = m[1];
8056
+ const inner = m[2];
7955
8057
  const idMatch = attrs.match(/\bid\s*=\s*"(\d+)"/);
7956
8058
  if (!idMatch)
7957
8059
  throw new Error("mappings manifest entry missing numeric id");
@@ -7960,24 +8062,67 @@ function parseMapMemoriesManifest(text) {
7960
8062
  throw new Error("mappings manifest entry missing numeric id");
7961
8063
  const independent = /\bindependent\s*=\s*"(?:true|1)"/i.test(attrs);
7962
8064
  const filesMatch = attrs.match(/\bfiles\s*=\s*"([^"]*)"/);
7963
- const files = filesMatch ? filesMatch[1].split(",").map((f) => f.trim()).filter(Boolean) : [];
7964
- out.push({ id, files, independent: independent || files.length === 0 });
8065
+ const attrFiles = filesMatch ? filesMatch[1].split(",").map((f) => f.trim()).filter(Boolean) : [];
8066
+ const nestedFiles = inner ? extractNestedFilePaths(inner) : [];
8067
+ const files = attrFiles.length > 0 ? attrFiles : nestedFiles;
8068
+ if (!independent && files.length === 0) {
8069
+ throw new Error(`mappings manifest entry ${id} has neither files nor independent="true"`);
8070
+ }
8071
+ out.push({
8072
+ id,
8073
+ files: independent && files.length === 0 ? [] : files,
8074
+ independent: independent && files.length === 0
8075
+ });
8076
+ }
8077
+ if (out.length === 0 && body.trim().length > 0) {
8078
+ throw new Error(describeUnrecognizedManifestShape(text, "mappings", "memory"));
7965
8079
  }
7966
8080
  assertNoDuplicateManifestIds(out.map((entry) => entry.id), "mappings");
7967
8081
  return out;
7968
8082
  }
8083
+ function validateMapMemoriesManifest(text, expectedIds) {
8084
+ const parsed = parseMapMemoriesManifest(text);
8085
+ assertParsedManifestNonEmpty(parsed.length, expectedIds.size, text, "mappings", "memory");
8086
+ assertManifestCoversExactly(parsed.map((entry) => entry.id), expectedIds, "mappings");
8087
+ return parsed;
8088
+ }
7969
8089
 
7970
8090
  // ../plugin/src/features/magic-context/dreamer/map-memories.ts
7971
8091
  var MAP_BATCH_SIZE = 80;
7972
- function loadUnmappedInputs(db, projectIdentity, repoDir) {
8092
+ var MAX_INDEPENDENT_REQUEUE_PER_RUN = MAP_BATCH_SIZE;
8093
+ function shouldRequeueIndependentMapping(state2, content, repoDir) {
8094
+ if (!state2.hasSentinel || state2.files.length > 0)
8095
+ return false;
8096
+ return extractMemoryCandidatePaths(content, repoDir).length > 0;
8097
+ }
8098
+ function toMapInput(memory, repoDir) {
8099
+ return {
8100
+ id: memory.id,
8101
+ category: memory.category,
8102
+ content: memory.content,
8103
+ candidates: extractMemoryCandidatePaths(memory.content, repoDir)
8104
+ };
8105
+ }
8106
+ function selectMapMemoryInputs(db, projectIdentity, repoDir) {
7973
8107
  const active = getMemoriesByProject(db, projectIdentity);
7974
- const unmapped = new Set(getUnmappedMemoryIds(db, active.map((m) => m.id)));
7975
- return active.filter((m) => unmapped.has(m.id)).map((m) => ({
7976
- id: m.id,
7977
- category: m.category,
7978
- content: m.content,
7979
- candidates: extractMemoryCandidatePaths(m.content, repoDir)
7980
- }));
8108
+ const activeIds = active.map((m) => m.id);
8109
+ const unmapped = new Set(getUnmappedMemoryIds(db, activeIds));
8110
+ const verifications = getMemoryVerifications(db, activeIds);
8111
+ const unmappedInputs = active.filter((m) => unmapped.has(m.id)).map((m) => toMapInput(m, repoDir));
8112
+ const requeue = [];
8113
+ for (const memory of active) {
8114
+ if (unmapped.has(memory.id))
8115
+ continue;
8116
+ const state2 = verifications.get(memory.id);
8117
+ if (!state2)
8118
+ continue;
8119
+ if (!shouldRequeueIndependentMapping(state2, memory.content, repoDir))
8120
+ continue;
8121
+ requeue.push(toMapInput(memory, repoDir));
8122
+ if (requeue.length >= MAX_INDEPENDENT_REQUEUE_PER_RUN)
8123
+ break;
8124
+ }
8125
+ return [...unmappedInputs, ...requeue];
7981
8126
  }
7982
8127
  async function mapMemories(args) {
7983
8128
  const result = {
@@ -7987,7 +8132,7 @@ async function mapMemories(args) {
7987
8132
  remaining: 0,
7988
8133
  complete: true
7989
8134
  };
7990
- const inputs = loadUnmappedInputs(args.db, args.projectIdentity, args.sessionDirectory);
8135
+ const inputs = selectMapMemoryInputs(args.db, args.projectIdentity, args.sessionDirectory);
7991
8136
  if (inputs.length === 0)
7992
8137
  return result;
7993
8138
  const batches = [];
@@ -8066,7 +8211,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
8066
8211
  const text = extractLatestAssistantText(messages);
8067
8212
  if (!text)
8068
8213
  throw new Error("map-memories returned no output");
8069
- parseMapMemoriesManifest(text);
8214
+ validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
8070
8215
  return text;
8071
8216
  }
8072
8217
  });
@@ -8100,10 +8245,13 @@ async function applyBatchMappings(args, batch, manifestText) {
8100
8245
  return { mapped: 0, independent: 0 };
8101
8246
  const planned = [];
8102
8247
  for (const p of parsed) {
8103
- if (p.independent || p.files.length === 0) {
8248
+ if (p.independent) {
8104
8249
  planned.push({ id: p.id, files: [], independent: true });
8105
8250
  continue;
8106
8251
  }
8252
+ if (p.files.length === 0) {
8253
+ throw new Error(`mapping entry ${p.id} has no files and no independent sentinel`);
8254
+ }
8107
8255
  const normalized = await normalizeVerificationFiles({
8108
8256
  cwd: args.sessionDirectory,
8109
8257
  files: p.files
@@ -9364,9 +9512,22 @@ function attrOf(s, name) {
9364
9512
  function filesOf(s) {
9365
9513
  return (attrOf(s, "files") ?? "").split(",").map((f) => f.trim()).filter(Boolean);
9366
9514
  }
9515
+ function verifyIds(parsed) {
9516
+ return [...parsed.verified, ...parsed.updated, ...parsed.archived].map((entry) => entry.id);
9517
+ }
9518
+ function verifyBody(text) {
9519
+ try {
9520
+ return extractCompleteManifestBody(text, "verify");
9521
+ } catch (error) {
9522
+ const described = describeUnrecognizedManifestShape(text, "verify", "verified");
9523
+ if (!described.startsWith("parsed zero entries"))
9524
+ throw new Error(described);
9525
+ throw error;
9526
+ }
9527
+ }
9367
9528
  function parseVerifyManifest(text) {
9368
9529
  const out = { verified: [], updated: [], archived: [] };
9369
- const body = extractCompleteManifestBody(text, "verify");
9530
+ const body = verifyBody(text);
9370
9531
  for (const m of body.matchAll(/<verified\b([^>]*)\/?>/g)) {
9371
9532
  const id = Number.parseInt(attrOf(m[1], "id") ?? "", 10);
9372
9533
  if (!Number.isInteger(id))
@@ -9385,9 +9546,19 @@ function parseVerifyManifest(text) {
9385
9546
  throw new Error("verify manifest entry missing numeric id");
9386
9547
  out.archived.push({ id, reason: attrOf(m[1], "reason") ?? "" });
9387
9548
  }
9388
- assertNoDuplicateManifestIds([...out.verified, ...out.updated, ...out.archived].map((entry) => entry.id), "verify");
9549
+ if (verifyIds(out).length === 0 && body.trim().length > 0) {
9550
+ throw new Error(describeUnrecognizedManifestShape(text, "verify", "verified"));
9551
+ }
9552
+ assertNoDuplicateManifestIds(verifyIds(out), "verify");
9389
9553
  return out;
9390
9554
  }
9555
+ function validateVerifyManifest(text, expectedIds) {
9556
+ const parsed = parseVerifyManifest(text);
9557
+ const ids = verifyIds(parsed);
9558
+ assertParsedManifestNonEmpty(ids.length, expectedIds.size, text, "verify", "verified");
9559
+ assertManifestCoversExactly(ids, expectedIds, "verify");
9560
+ return parsed;
9561
+ }
9391
9562
 
9392
9563
  // ../plugin/src/features/magic-context/dreamer/verify.ts
9393
9564
  var VERIFY_BATCH_SIZE = 50;
@@ -9539,7 +9710,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9539
9710
  if (!text)
9540
9711
  throw new Error("verify returned no output");
9541
9712
  try {
9542
- parseVerifyManifest(text);
9713
+ validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
9543
9714
  } catch (error) {
9544
9715
  const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
9545
9716
  if (providerFailure)
@@ -9759,6 +9930,18 @@ function loadActiveMemoryPromptMemories(db, projectIdentity) {
9759
9930
  const verificationById = getMemoryVerifications(db, memories.map((memory) => memory.id));
9760
9931
  return memories.map((memory) => toCuratePromptMemory(memory, verificationById));
9761
9932
  }
9933
+ var TEXTUAL_CURATE_TOOL_CALL_PATTERNS = [
9934
+ /\[\s*historical tool call\s*\][\s\S]*?(?:^|\n)\s*name\s*:\s*ctx_memory\b[\s\S]*?(?:^|\n)\s*arguments\s*:/im,
9935
+ /(?:^|\n)\s*name\s*:\s*ctx_memory\b[\s\S]*?(?:^|\n)\s*arguments\s*:/im,
9936
+ /(?:^|\n)\s*(?:```[^\n]*\n\s*)?ctx_memory\s*\(\s*action\s*=/im,
9937
+ /["']name["']\s*:\s*["']ctx_memory["'][\s\S]*?["']arguments["']\s*:/i
9938
+ ];
9939
+ function validateCurateAssistantText(text) {
9940
+ if (TEXTUAL_CURATE_TOOL_CALL_PATTERNS.some((pattern) => pattern.test(text))) {
9941
+ throw new Error("Curate returned an unresolved textual ctx_memory tool call.");
9942
+ }
9943
+ return text;
9944
+ }
9762
9945
  function createDreamTaskExecutor(deps) {
9763
9946
  let parentSessionIdPromise;
9764
9947
  const resolveParentSessionId = () => {
@@ -9829,7 +10012,8 @@ function createDreamTaskExecutor(deps) {
9829
10012
  name: config.task,
9830
10013
  durationMs: Date.now() - startedAt,
9831
10014
  resultChars: 0,
9832
- ...error ? { error } : {},
10015
+ ...status === "failed" && error ? { error } : {},
10016
+ ...extra?.progress ? { progress: extra.progress } : {},
9833
10017
  backlog: (() => {
9834
10018
  const end = extra?.backlogAfter ?? getDreamTaskBacklog(db, projectIdentity, config.task);
9835
10019
  const processed = processedDreamTaskItems(backlogAtStart.pending, end.pending);
@@ -9972,11 +10156,12 @@ function createDreamTaskExecutor(deps) {
9972
10156
  const backlogAfter = config.task === "verify-broad" ? { pending: result.remaining, total: backlogAtStart.total } : undefined;
9973
10157
  if (!result.complete) {
9974
10158
  if (broadProgress && processed > 0) {
9975
- recordRun("completed", broadProgress, {
10159
+ recordRun("completed", null, {
10160
+ progress: broadProgress,
9976
10161
  memoryChanges: computeMemoryDelta(memoryBefore),
9977
10162
  backlogAfter
9978
10163
  });
9979
- return { status: "completed", error: broadProgress };
10164
+ return { status: "completed" };
9980
10165
  }
9981
10166
  const error = incompleteMessage(result.remaining);
9982
10167
  recordRun("failed", error, {
@@ -9985,11 +10170,12 @@ function createDreamTaskExecutor(deps) {
9985
10170
  });
9986
10171
  return { status: "failed", transient: true, error };
9987
10172
  }
9988
- recordRun("completed", broadProgress, {
10173
+ recordRun("completed", null, {
10174
+ progress: broadProgress,
9989
10175
  memoryChanges: computeMemoryDelta(memoryBefore),
9990
10176
  backlogAfter
9991
10177
  });
9992
- return broadProgress ? { status: "completed", error: broadProgress } : { status: "completed" };
10178
+ return { status: "completed" };
9993
10179
  }
9994
10180
  if (config.task === "classify-memories") {
9995
10181
  let moduleArgs;
@@ -10456,7 +10642,7 @@ async function runAgenticTask(config, ctx, helpers) {
10456
10642
  const text = extractLatestAssistantText(messages);
10457
10643
  if (!text)
10458
10644
  throw new Error("Dreamer returned no assistant output.");
10459
- return text;
10645
+ return task === "curate" ? validateCurateAssistantText(text) : text;
10460
10646
  }
10461
10647
  });
10462
10648
  if (leaseLost)
@@ -10765,6 +10951,7 @@ async function runDueTasksForProject(deps) {
10765
10951
  import { statSync as statSync2 } from "node:fs";
10766
10952
 
10767
10953
  // ../plugin/src/features/magic-context/dreamer/retrospective-orphan-sweep.ts
10954
+ var HISTORIAN_CHILD_TITLE = "magic-context-compartment";
10768
10955
  var RETROSPECTIVE_CHILD_TITLE = "magic-context-dream-retrospective";
10769
10956
  var USER_MEMORIES_CHILD_TITLE = "magic-context-dream-user-memories";
10770
10957
  var CURATE_CHILD_TITLE = "magic-context-dream-curate";
@@ -10790,16 +10977,34 @@ var PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES = {
10790
10977
  ],
10791
10978
  prefixes: [SMART_NOTE_COMPILE_CHILD_TITLE_PREFIX, SMART_NOTE_CONFIRM_CHILD_TITLE_PREFIX]
10792
10979
  };
10980
+ var HISTORIAN_CHILD_TITLE_MATCHES = {
10981
+ exact: [HISTORIAN_CHILD_TITLE],
10982
+ prefixes: []
10983
+ };
10984
+ var INTERNAL_CHILD_TITLE_MATCHES = {
10985
+ exact: [HISTORIAN_CHILD_TITLE, ...PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES.exact],
10986
+ prefixes: PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES.prefixes
10987
+ };
10793
10988
  function retrospectiveOrphanStaleMs(taskTimeoutMinutes) {
10794
10989
  const timeoutCandidates = Array.isArray(taskTimeoutMinutes) ? taskTimeoutMinutes : [taskTimeoutMinutes];
10795
10990
  const maxTimeoutMinutes = Math.max(...timeoutCandidates.map((minutes) => Math.max(1, minutes ?? 20)), 20);
10796
10991
  const timeoutMs = maxTimeoutMinutes * 60000;
10797
10992
  return Math.max(60 * 60000, timeoutMs * 3);
10798
10993
  }
10994
+ var HISTORIAN_OUTER_ATTEMPTS = 3;
10995
+ var HISTORIAN_MODEL_SUGGESTION_ATTEMPTS = 2;
10996
+ var HISTORIAN_MAX_RETRY_BACKOFF_MS = 11000;
10997
+ var HISTORIAN_DETACHED_WRITER_GRACE_MS = 15 * 60000;
10998
+ function historianOrphanStaleMs(timeoutMs, fallbackModelCount) {
10999
+ const timeout = Math.max(60000, timeoutMs);
11000
+ const fallbackCount = Math.max(0, Math.floor(fallbackModelCount));
11001
+ const fullAttemptBudget = timeout * HISTORIAN_OUTER_ATTEMPTS * HISTORIAN_MODEL_SUGGESTION_ATTEMPTS * (fallbackCount + 1);
11002
+ return Math.max(60 * 60000, fullAttemptBudget + HISTORIAN_MAX_RETRY_BACKOFF_MS + HISTORIAN_DETACHED_WRITER_GRACE_MS);
11003
+ }
10799
11004
  async function sweepOrphanedRetrospectiveChildren(args) {
10800
11005
  const { opencodeDb, client, sessionDirectory, staleMs } = args;
10801
- const titleMatches = args.titleMatches ?? PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES;
10802
- if (!opencodeDb)
11006
+ const titleMatches = args.titleMatches ?? INTERNAL_CHILD_TITLE_MATCHES;
11007
+ if (!opencodeDb || args.keepSubagents === true)
10803
11008
  return 0;
10804
11009
  const now = args.now ?? Date.now();
10805
11010
  const cutoff = now - staleMs;
@@ -10822,7 +11027,7 @@ async function sweepOrphanedRetrospectiveChildren(args) {
10822
11027
  ORDER BY time_created ASC
10823
11028
  LIMIT 200`).all(...titleParams, sessionDirectory, cutoff);
10824
11029
  } catch (error) {
10825
- log(`[dreamer] retrospective orphan sweep: read skipped (${String(error)})`);
11030
+ log(`[magic-context] internal child orphan sweep: read skipped (${String(error)})`);
10826
11031
  return 0;
10827
11032
  }
10828
11033
  if (rows.length === 0)
@@ -10837,7 +11042,7 @@ async function sweepOrphanedRetrospectiveChildren(args) {
10837
11042
  }
10838
11043
  }
10839
11044
  if (deleted > 0) {
10840
- log(`[dreamer] swept ${deleted} crash-orphaned privacy-sensitive child session(s)`);
11045
+ log(`[magic-context] swept ${deleted} stale internal child session(s)`);
10841
11046
  }
10842
11047
  return deleted;
10843
11048
  }
@@ -10977,7 +11182,7 @@ function scheduleInitialProjectRun(reg, db) {
10977
11182
  startupTimers.set(reg.directory, timer);
10978
11183
  }
10979
11184
  async function runProjectMaintenance(reg, origin, db) {
10980
- const projectMaintenanceEnabled = Boolean(reg.dreamerConfig && reg.dreamerConfig.disable !== true) || reg.memoryEnabled === true || reg.gitCommitIndexing?.enabled === true;
11185
+ const projectMaintenanceEnabled = Boolean(reg.dreamerConfig && reg.dreamerConfig.disable !== true) || reg.memoryEnabled === true || reg.gitCommitIndexing?.enabled === true || reg.historianChildSweep !== undefined;
10981
11186
  if (!projectMaintenanceEnabled)
10982
11187
  return;
10983
11188
  await reg.ensureRegistered(reg.directory, db);
@@ -11014,6 +11219,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
11014
11219
  if (gcDeleted > 0) {
11015
11220
  log(`[magic-context] GC'd ${gcDeleted} stale embedding row(s) for ${reg.projectIdentity} ` + `(memory=${gc.memoryRowsDeleted} commit=${gc.commitRowsDeleted} chunk=${gc.chunkRowsDeleted})`);
11016
11221
  }
11222
+ await sweepOrphanedHistorianChildren(reg);
11017
11223
  const dreamerConfig = reg.dreamerConfig;
11018
11224
  const dreamingEnabled = Boolean(dreamerConfig && dreamerConfig.disable !== true);
11019
11225
  if (commitIndexingEnabled && reg.gitCommitIndexing) {
@@ -11077,6 +11283,27 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
11077
11283
  log(`[dreamer] timer-triggered task scheduling failed for ${reg.projectIdentity}:`, error);
11078
11284
  }
11079
11285
  }
11286
+ async function sweepOrphanedHistorianChildren(reg) {
11287
+ const config = reg.historianChildSweep;
11288
+ if (!config || config.keepSubagents)
11289
+ return;
11290
+ const ocDb = openOpenCodeDb();
11291
+ if (!ocDb)
11292
+ return;
11293
+ try {
11294
+ await sweepOrphanedRetrospectiveChildren({
11295
+ opencodeDb: ocDb,
11296
+ client: reg.client,
11297
+ sessionDirectory: reg.directory,
11298
+ staleMs: historianOrphanStaleMs(config.timeoutMs, config.fallbackModelCount),
11299
+ titleMatches: HISTORIAN_CHILD_TITLE_MATCHES
11300
+ });
11301
+ } catch (error) {
11302
+ log(`[magic-context] historian child orphan sweep failed for ${reg.projectIdentity}:`, error);
11303
+ } finally {
11304
+ closeQuietly(ocDb);
11305
+ }
11306
+ }
11080
11307
  async function runCompiledSmartNoteSweep(reg, db) {
11081
11308
  const leaseKey = leaseKeyFor("evaluate-smart-notes", reg.projectIdentity);
11082
11309
  const holderId = crypto.randomUUID();
@@ -12730,10 +12957,16 @@ function writeTransformDecisionRow(dbPath, row) {
12730
12957
  function writeTransformDecisionRowOnDatabase(db, row, configureBusyTimeout) {
12731
12958
  if (configureBusyTimeout)
12732
12959
  db.exec("PRAGMA busy_timeout=0");
12960
+ const systemHashPrev = row.materialized ? row.systemHashPrev : null;
12961
+ const systemHashNew = row.materialized ? row.systemHashNew : null;
12962
+ const m0ModelKeyPrev = row.materialized ? row.m0ModelKeyPrev : null;
12963
+ const m0ModelKeyNew = row.materialized ? row.m0ModelKeyNew : null;
12733
12964
  db.prepare(`INSERT OR REPLACE INTO transform_decisions (
12734
12965
  session_id, harness, message_id, ts_ms, decision, materialized,
12735
- materialize_reason, emergency, dropped_tokens, dropped_count, input_tokens
12736
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.sessionId, row.harness, row.messageId, row.tsMs, row.decision, row.materialized ? 1 : 0, row.materializeReason, row.emergency ? 1 : 0, Math.max(0, Math.floor(row.droppedTokens)), Math.max(0, Math.floor(row.droppedCount)), Math.max(0, Math.floor(row.inputTokens)));
12966
+ materialize_reason, system_hash_prev, system_hash_new,
12967
+ m0_model_key_prev, m0_model_key_new, emergency, dropped_tokens,
12968
+ dropped_count, input_tokens
12969
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.sessionId, row.harness, row.messageId, row.tsMs, row.decision, row.materialized ? 1 : 0, row.materializeReason, systemHashPrev, systemHashNew, m0ModelKeyPrev, m0ModelKeyNew, row.emergency ? 1 : 0, Math.max(0, Math.floor(row.droppedTokens)), Math.max(0, Math.floor(row.droppedCount)), Math.max(0, Math.floor(row.inputTokens)));
12737
12970
  db.prepare(`DELETE FROM transform_decisions
12738
12971
  WHERE session_id = ? AND harness = ?
12739
12972
  AND rowid NOT IN (
@@ -13275,6 +13508,21 @@ function replayCavemanCompression(sessionId, db, targets, tags) {
13275
13508
  return replayed;
13276
13509
  }
13277
13510
 
13511
+ // ../plugin/src/hooks/magic-context/channel2-cycle.ts
13512
+ function rearmChannel2AfterCoverageAdvancingHardFold(input) {
13513
+ if (input.compactionOff || !input.foldExecuted || input.previousCoverage === null || input.currentCoverage === null || input.currentCoverage <= input.previousCoverage) {
13514
+ return false;
13515
+ }
13516
+ return casChannel2NudgeState(input.db, input.sessionId, "delivered", "");
13517
+ }
13518
+ function rearmChannel2AfterMeasuredCollapse(input) {
13519
+ if (!input.baseline.evaluable || input.baseline.generationInvalidated)
13520
+ return false;
13521
+ if (effectiveTailHygiene(input.baseline).u >= CHANNEL1_FLOOR_TOKENS)
13522
+ return false;
13523
+ return casChannel2NudgeState(input.db, input.sessionId, "delivered", "");
13524
+ }
13525
+
13278
13526
  // ../plugin/src/hooks/magic-context/protected-tail-boundary.ts
13279
13527
  var ALPHA = 0.3;
13280
13528
  var FLOOR_RATIO = 0.08;
@@ -14160,132 +14408,13 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
14160
14408
  };
14161
14409
  }
14162
14410
 
14163
- // ../plugin/src/hooks/magic-context/ctx-reduce-nudge.ts
14164
- var CHANNEL1_SENTINEL = "<system-reminder>";
14165
- var TOKENS_PER_BYTE = 0.25;
14166
- var CHANNEL1_FLOOR_TOKENS = 1e4;
14167
- var CHANNEL1_REFIRE_FLOOR_TOKENS = 1e4;
14168
- function channel1RefireTokens(workingWindowTokens) {
14169
- const scaled = Math.round(0.05 * Math.max(0, workingWindowTokens));
14170
- return Math.max(CHANNEL1_REFIRE_FLOOR_TOKENS, scaled);
14171
- }
14172
- var S_GENTLE = 0.2;
14173
- var S_FIRM = 0.4;
14174
- var S_URGENT = 0.65;
14175
- var CHANNEL1_PRESSURE_FLOOR = 0.8;
14176
- var LEVEL_RANK = { gentle: 1, firm: 2, urgent: 3 };
14177
- var DROP_SENTINELS = ["[dropped", "[truncated"];
14178
- function isDroppedToolOutput(output) {
14179
- const head = output.slice(0, 16);
14180
- return DROP_SENTINELS.some((s) => head.startsWith(s));
14181
- }
14182
- function toolOutputTokens(output) {
14183
- return Math.round(byteSize(output) * TOKENS_PER_BYTE);
14184
- }
14185
- function decideChannel1(input) {
14186
- const { undroppedTokens, workingWindowTokens, hasRecentReduce } = input;
14187
- const pressure = Math.min(1, Math.max(0, input.pressure));
14188
- const resetCycle = hasRecentReduce || undroppedTokens < input.lastNudgeUndropped;
14189
- const lastNudge = resetCycle ? 0 : input.lastNudgeUndropped;
14190
- const lastLevel = resetCycle ? "" : input.lastNudgeLevel;
14191
- const quiet = () => ({
14192
- fire: false,
14193
- level: "gentle",
14194
- undroppedTokens,
14195
- nextLastNudge: lastNudge,
14196
- nextLastNudgeLevel: lastLevel
14197
- });
14198
- if (hasRecentReduce)
14199
- return quiet();
14200
- if (undroppedTokens < CHANNEL1_FLOOR_TOKENS)
14201
- return quiet();
14202
- if (pressure < CHANNEL1_PRESSURE_FLOOR)
14203
- return quiet();
14204
- const denom = Math.max(input.estimatedInputTokens, 1);
14205
- const severity = Math.min(1, undroppedTokens / denom);
14206
- if (severity < S_GENTLE)
14207
- return quiet();
14208
- let level;
14209
- if (severity >= S_URGENT)
14210
- level = "urgent";
14211
- else if (severity >= S_FIRM)
14212
- level = "firm";
14213
- else
14214
- level = "gentle";
14215
- if (lastLevel === "") {
14216
- if (undroppedTokens < lastNudge + channel1RefireTokens(workingWindowTokens)) {
14217
- return quiet();
14218
- }
14219
- } else if (LEVEL_RANK[level] <= LEVEL_RANK[lastLevel]) {
14220
- return quiet();
14221
- }
14222
- return {
14223
- fire: true,
14224
- level,
14225
- undroppedTokens,
14226
- nextLastNudge: undroppedTokens,
14227
- nextLastNudgeLevel: level
14228
- };
14229
- }
14230
- function computePressure(input) {
14231
- const { lastInputTokens, turnToolTokens, contextLimit, executeThresholdPercentage } = input;
14232
- if (contextLimit <= 0 || executeThresholdPercentage <= 0)
14233
- return 0;
14234
- const estimatedInput = lastInputTokens + turnToolTokens;
14235
- const usagePercentage = estimatedInput / contextLimit * 100;
14236
- return usagePercentage / executeThresholdPercentage;
14237
- }
14238
- function approxThousands(tokens) {
14239
- return `${Math.round(tokens / 1000)}k`;
14240
- }
14241
- function formatOldestReclaimableHint(hint) {
14242
- if (!hint || hint.length === 0)
14243
- return "";
14244
- const rendered = hint.slice(0, 4).map((tag) => `§${tag.tagNumber}§ ${tag.toolName ?? "tool"}`).join(" · ");
14245
- return rendered.length > 0 ? `
14246
- oldest reclaimable: ${rendered}.` : "";
14247
- }
14248
- var CHANNEL2_USABLE_FRACTION = 1 / 3;
14249
- var CHANNEL2_MIN_RECLAIMABLE = 1e4;
14250
- function shouldTriggerChannel2(input) {
14251
- if (input.reclaimableTokens < CHANNEL2_MIN_RECLAIMABLE)
14252
- return false;
14253
- if (input.usableTokens <= 0)
14254
- return true;
14255
- return input.reclaimableTokens >= input.usableTokens * CHANNEL2_USABLE_FRACTION;
14256
- }
14257
- function buildChannel2Reminder(undroppedTokens, hint) {
14258
- const amount = approxThousands(undroppedTokens);
14259
- const hintText = formatOldestReclaimableHint(hint);
14260
- return `<system-reminder>
14261
- ` + `Routine context housekeeping is near: a large span of this session will be comparted soon, ` + `and ~${amount} tokens of tool output remain unreduced. Drop spent outputs with ctx_reduce ` + `first so the archived span is the part that matters.${hintText}
14262
- ` + `</system-reminder>`;
14263
- }
14264
- function buildChannel1Reminder(level, undroppedTokens, hint) {
14265
- const amount = approxThousands(undroppedTokens);
14266
- const hintText = formatOldestReclaimableHint(hint);
14267
- let body;
14268
- switch (level) {
14269
- case "gentle":
14270
- body = `You have ~${amount} tokens of tool output you have not reduced. ` + `When you are done with earlier outputs, dropping them with ctx_reduce keeps context lean.`;
14271
- break;
14272
- case "firm":
14273
- body = `~${amount} tokens of unreduced tool output has built up. ` + `At your next natural stopping point, consider dropping what you have already processed with ctx_reduce.`;
14274
- break;
14275
- case "urgent":
14276
- body = `~${amount} tokens of unreduced tool output remain, and a large span of this session will be comparted before long. ` + `Consider dropping spent outputs with ctx_reduce so the archived span is the part that matters.`;
14277
- break;
14278
- }
14279
- return `
14280
-
14281
- <system-reminder>
14282
- ${body}${hintText}
14283
- </system-reminder>`;
14411
+ // ../plugin/src/hooks/magic-context/fold-execution-gate.ts
14412
+ function foldExecutesThisPass(foldDue, materialized) {
14413
+ return foldDue && materialized;
14284
14414
  }
14285
14415
 
14286
14416
  // ../plugin/src/hooks/magic-context/supersession-reclaim.ts
14287
14417
  var TODOWRITE_KEEP = 1;
14288
- var CTX_REDUCE_KEEP = 5;
14289
14418
  var ZERO_VALUE_META_TOOLS = new Set(["bash_status", "bash_kill"]);
14290
14419
  var CTX_NOTE_ZERO_VALUE_ACTIONS = new Set(["read", "dismiss"]);
14291
14420
  function buildSupersessionReclaimOps(input) {
@@ -14413,158 +14542,6 @@ function advanceToolReclaimWatermarkToCurrentMax(db, sessionId) {
14413
14542
 
14414
14543
  // ../plugin/src/shared/tag-transcript.ts
14415
14544
  import { createHash as createHash9 } from "node:crypto";
14416
-
14417
- // ../plugin/src/hooks/magic-context/image-token-estimate.ts
14418
- var IMAGE_TOKEN_DIVISOR = 750;
14419
- var IMAGE_FALLBACK_TOKENS = 1200;
14420
- var IMAGE_TOKEN_CAP = 4500;
14421
- function estimateImageTokensFromDataUrl(url) {
14422
- const comma = url.indexOf(",");
14423
- if (comma < 0)
14424
- return IMAGE_FALLBACK_TOKENS;
14425
- const header = url.slice(0, comma);
14426
- const payload = url.slice(comma + 1);
14427
- const sliceLen = Math.min(512, payload.length);
14428
- const preview = payload.slice(0, sliceLen);
14429
- let bytes;
14430
- try {
14431
- bytes = base64Decode(preview);
14432
- } catch {
14433
- return IMAGE_FALLBACK_TOKENS;
14434
- }
14435
- if (header.includes("image/png")) {
14436
- const dims = parsePngDimensions(bytes);
14437
- if (dims)
14438
- return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
14439
- } else if (header.includes("image/jpeg") || header.includes("image/jpg")) {
14440
- const dims = parseJpegDimensions(bytes);
14441
- if (dims)
14442
- return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
14443
- } else if (header.includes("image/webp")) {
14444
- const dims = parseWebpDimensions(bytes);
14445
- if (dims)
14446
- return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
14447
- } else if (header.includes("image/gif")) {
14448
- const dims = parseGifDimensions(bytes);
14449
- if (dims)
14450
- return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
14451
- }
14452
- return IMAGE_FALLBACK_TOKENS;
14453
- }
14454
- function clampImageTokens(n) {
14455
- if (n < 1)
14456
- return 1;
14457
- if (n > IMAGE_TOKEN_CAP)
14458
- return IMAGE_TOKEN_CAP;
14459
- return n;
14460
- }
14461
- function base64Decode(b64) {
14462
- const pad = b64.length % 4;
14463
- const padded = pad === 0 ? b64 : b64 + "=".repeat(4 - pad);
14464
- const binary = atob(padded);
14465
- const out = new Uint8Array(binary.length);
14466
- for (let i = 0;i < binary.length; i++)
14467
- out[i] = binary.charCodeAt(i);
14468
- return out;
14469
- }
14470
- function parsePngDimensions(b) {
14471
- if (b.length < 24)
14472
- return null;
14473
- if (b[0] !== 137 || b[1] !== 80 || b[2] !== 78 || b[3] !== 71 || b[4] !== 13 || b[5] !== 10 || b[6] !== 26 || b[7] !== 10)
14474
- return null;
14475
- const w = readUint32BE(b, 16);
14476
- const h = readUint32BE(b, 20);
14477
- if (!w || !h)
14478
- return null;
14479
- return { w, h };
14480
- }
14481
- function parseJpegDimensions(b) {
14482
- if (b.length < 4 || b[0] !== 255 || b[1] !== 216)
14483
- return null;
14484
- let i = 2;
14485
- while (i < b.length - 8) {
14486
- if (b[i] !== 255) {
14487
- i++;
14488
- continue;
14489
- }
14490
- const marker = b[i + 1];
14491
- if (marker === undefined)
14492
- break;
14493
- if (isSofMarker(marker)) {
14494
- const h = b[i + 5] << 8 | b[i + 6];
14495
- const w = b[i + 7] << 8 | b[i + 8];
14496
- if (w && h)
14497
- return { w, h };
14498
- return null;
14499
- }
14500
- if (marker === 216 || marker === 217 || marker === 1) {
14501
- i += 2;
14502
- continue;
14503
- }
14504
- const segLen = b[i + 2] << 8 | b[i + 3];
14505
- if (segLen < 2)
14506
- return null;
14507
- i += 2 + segLen;
14508
- }
14509
- return null;
14510
- }
14511
- function isSofMarker(m) {
14512
- if (m >= 192 && m <= 195)
14513
- return true;
14514
- if (m >= 197 && m <= 199)
14515
- return true;
14516
- if (m >= 201 && m <= 203)
14517
- return true;
14518
- if (m >= 205 && m <= 207)
14519
- return true;
14520
- return false;
14521
- }
14522
- function parseWebpDimensions(b) {
14523
- if (b.length < 30)
14524
- return null;
14525
- if (b[0] !== 82 || b[1] !== 73 || b[2] !== 70 || b[3] !== 70)
14526
- return null;
14527
- if (b[8] !== 87 || b[9] !== 69 || b[10] !== 66 || b[11] !== 80)
14528
- return null;
14529
- const variant = String.fromCharCode(b[12], b[13], b[14], b[15]);
14530
- if (variant === "VP8 ") {
14531
- const w = (b[26] | b[27] << 8) & 16383;
14532
- const h = (b[28] | b[29] << 8) & 16383;
14533
- if (w && h)
14534
- return { w, h };
14535
- } else if (variant === "VP8L") {
14536
- const b0 = b[21];
14537
- const b1 = b[22];
14538
- const b2 = b[23];
14539
- const b3 = b[24];
14540
- const w = 1 + ((b0 | b1 << 8) & 16383);
14541
- const h = 1 + ((b1 >> 6 | b2 << 2 | b3 << 10) & 16383);
14542
- if (w && h)
14543
- return { w, h };
14544
- } else if (variant === "VP8X") {
14545
- const w = 1 + (b[24] | b[25] << 8 | b[26] << 16);
14546
- const h = 1 + (b[27] | b[28] << 8 | b[29] << 16);
14547
- if (w && h)
14548
- return { w, h };
14549
- }
14550
- return null;
14551
- }
14552
- function parseGifDimensions(b) {
14553
- if (b.length < 10)
14554
- return null;
14555
- if (b[0] !== 71 || b[1] !== 73 || b[2] !== 70)
14556
- return null;
14557
- const w = b[6] | b[7] << 8;
14558
- const h = b[8] | b[9] << 8;
14559
- if (!w || !h)
14560
- return null;
14561
- return { w, h };
14562
- }
14563
- function readUint32BE(b, offset) {
14564
- return (b[offset] << 24 | b[offset + 1] << 16 | b[offset + 2] << 8 | b[offset + 3]) >>> 0;
14565
- }
14566
-
14567
- // ../plugin/src/shared/tag-transcript.ts
14568
14545
  var TEXT_TAG_IDENTITY_MARKER = ":mc-text-v1:";
14569
14546
  function textIdentityDigest(value) {
14570
14547
  return createHash9("sha256").update(value).digest("hex");
@@ -15583,435 +15560,76 @@ function recordPiTransformTiming(sample) {
15583
15560
  }
15584
15561
 
15585
15562
  // src/ctx-reduce-nudge-pi.ts
15586
- function sealDeliveredAfterUnconfirmedSend(db, sessionId) {
15587
- try {
15588
- if (getChannel2NudgeState(db, sessionId) === "delivered") {
15589
- return "already-delivered";
15563
+ import { randomUUID as randomUUID2 } from "node:crypto";
15564
+
15565
+ // ../plugin/src/hooks/magic-context/system-injection-stripper.ts
15566
+ var SYSTEM_INJECTION_MARKERS = [
15567
+ "<!-- OMO_INTERNAL_INITIATOR -->",
15568
+ "[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
15569
+ "[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
15570
+ "[Category+Skill Reminder]",
15571
+ "[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
15572
+ "[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
15573
+ "[EMERGENCY CONTEXT WINDOW WARNING]",
15574
+ "Unstable background agent appears idle",
15575
+ "**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
15576
+ ];
15577
+ var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
15578
+ var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
15579
+ function stripSystemInjection(text) {
15580
+ let hasInjection = false;
15581
+ for (const marker of SYSTEM_INJECTION_MARKERS) {
15582
+ if (text.includes(marker)) {
15583
+ hasInjection = true;
15584
+ break;
15590
15585
  }
15591
- } catch {}
15592
- try {
15593
- setChannel2NudgeState(db, sessionId, "delivered");
15594
- return "sealed";
15595
- } catch {
15596
- return "stuck-claimed";
15597
- }
15598
- }
15599
- var channel1StateBySession = new Map;
15600
- function setPiChannel1Baseline(sessionId, state2) {
15601
- channel1StateBySession.set(sessionId, state2);
15602
- }
15603
- function clearPiChannel1State(sessionId) {
15604
- channel1StateBySession.delete(sessionId);
15605
- }
15606
- function markPiChannel1Reduced(sessionId, db) {
15607
- const state2 = channel1StateBySession.get(sessionId);
15608
- if (state2)
15609
- state2.reducedSinceRefresh = true;
15610
- if (db)
15611
- resetLastNudgeCycle(db, sessionId);
15612
- }
15613
- function isPiTextContent(c) {
15614
- return c !== null && typeof c === "object" && c.type === "text" && typeof c.text === "string";
15615
- }
15616
- function toolResultText(content) {
15617
- let text = "";
15618
- for (const c of content) {
15619
- if (isPiTextContent(c))
15620
- text += c.text;
15621
15586
  }
15622
- return text;
15623
- }
15624
- function jsonTokens(value) {
15625
- if (value === undefined || value === null)
15626
- return 0;
15627
- try {
15628
- return toolOutputTokens(JSON.stringify(value));
15629
- } catch {
15630
- return 0;
15587
+ if (SYSTEM_REMINDER_REGEX.test(text))
15588
+ hasInjection = true;
15589
+ SYSTEM_REMINDER_REGEX.lastIndex = 0;
15590
+ if (!hasInjection)
15591
+ return null;
15592
+ let cleaned = text;
15593
+ cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
15594
+ cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
15595
+ cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
15596
+ for (const marker of SYSTEM_INJECTION_MARKERS) {
15597
+ if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
15598
+ continue;
15599
+ const idx = cleaned.indexOf(marker);
15600
+ if (idx === -1)
15601
+ continue;
15602
+ const blockEnd = cleaned.indexOf(`
15603
+
15604
+ `, idx + marker.length);
15605
+ cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
15631
15606
  }
15607
+ return cleaned.trim();
15632
15608
  }
15633
- function textTokens(content) {
15634
- if (typeof content === "string")
15635
- return toolOutputTokens(content);
15636
- if (!Array.isArray(content))
15637
- return 0;
15638
- let tokens = 0;
15639
- for (const part of content) {
15640
- if (!part || typeof part !== "object")
15609
+
15610
+ // src/heuristic-cleanup-pi.ts
15611
+ var PI_CTX_REDUCE_KEEP = 3;
15612
+ var DEDUP_SAFE_TOOLS = new Set([
15613
+ "mcp_grep",
15614
+ "mcp_read",
15615
+ "mcp_glob",
15616
+ "mcp_ast_grep_search",
15617
+ "mcp_lsp_diagnostics",
15618
+ "mcp_lsp_symbols",
15619
+ "mcp_lsp_find_references",
15620
+ "mcp_lsp_goto_definition",
15621
+ "mcp_lsp_prepare_rename"
15622
+ ]);
15623
+ function buildPiToolFingerprints(messages, resolveStableId) {
15624
+ const fingerprints = new Map;
15625
+ for (let i = 0;i < messages.length; i++) {
15626
+ const message = messages[i];
15627
+ if (!message || typeof message !== "object")
15641
15628
  continue;
15642
- const p = part;
15643
- if (typeof p.text === "string")
15644
- tokens += toolOutputTokens(p.text);
15645
- else if (typeof p.thinking === "string")
15646
- tokens += toolOutputTokens(p.thinking);
15647
- else if (p.type === "image")
15648
- tokens += 1200;
15649
- }
15650
- return tokens;
15651
- }
15652
- function computeTailTokenEstimatePi(messages) {
15653
- let tailToolTokens = 0;
15654
- let liveTailTokens = 0;
15655
- for (const raw of messages) {
15656
- if (!raw || typeof raw !== "object")
15629
+ const msg = message;
15630
+ if (msg.role !== "assistant")
15657
15631
  continue;
15658
- const msg = raw;
15659
- if (msg.role === "toolResult") {
15660
- const outputText = Array.isArray(msg.content) ? toolResultText(msg.content) : typeof msg.content === "string" ? msg.content : "";
15661
- const outputTokens = outputText && !isDroppedToolOutput(outputText) ? toolOutputTokens(outputText) : 0;
15662
- tailToolTokens += outputTokens;
15663
- liveTailTokens += outputTokens;
15664
- continue;
15665
- }
15666
- if (msg.role === "assistant" && Array.isArray(msg.content)) {
15667
- for (const part of msg.content) {
15668
- if (!part || typeof part !== "object")
15669
- continue;
15670
- const p = part;
15671
- if (p.type === "toolCall") {
15672
- if (typeof p.name === "string")
15673
- liveTailTokens += toolOutputTokens(p.name);
15674
- liveTailTokens += jsonTokens(p.arguments);
15675
- }
15676
- }
15677
- }
15678
- liveTailTokens += textTokens(msg.content);
15679
- }
15680
- return { tailToolTokens, liveTailTokens };
15681
- }
15682
- function maybeChannel1ReminderForToolResult(args) {
15683
- const { db, sessionId, toolName } = args;
15684
- const state2 = channel1StateBySession.get(sessionId);
15685
- if (!state2)
15686
- return null;
15687
- if (toolName === "ctx_reduce") {
15688
- state2.reducedSinceRefresh = true;
15689
- resetLastNudgeCycle(db, sessionId);
15690
- return null;
15691
- }
15692
- const text = toolResultText(args.content);
15693
- if (text.length === 0)
15694
- return null;
15695
- if (text.includes(CHANNEL1_SENTINEL))
15696
- return null;
15697
- state2.turnToolTokens += toolOutputTokens(text);
15698
- if (state2.reducedSinceRefresh)
15699
- return null;
15700
- const undroppedTokens = state2.tailToolTokens + state2.turnToolTokens;
15701
- const pressure = computePressure({
15702
- lastInputTokens: state2.lastInputTokens,
15703
- turnToolTokens: state2.turnToolTokens,
15704
- contextLimit: state2.contextLimit,
15705
- executeThresholdPercentage: state2.executeThresholdPercentage
15706
- });
15707
- const workingWindowTokens = Math.round(state2.contextLimit * state2.executeThresholdPercentage / 100);
15708
- const decision = decideChannel1({
15709
- undroppedTokens,
15710
- pressure,
15711
- estimatedInputTokens: state2.lastInputTokens + state2.turnToolTokens,
15712
- workingWindowTokens,
15713
- lastNudgeUndropped: getLastNudgeUndropped(db, sessionId),
15714
- lastNudgeLevel: getLastNudgeLevel(db, sessionId),
15715
- hasRecentReduce: false
15716
- });
15717
- setLastNudgeUndropped(db, sessionId, decision.nextLastNudge);
15718
- setLastNudgeLevel(db, sessionId, decision.nextLastNudgeLevel);
15719
- if (!decision.fire)
15720
- return null;
15721
- return {
15722
- type: "text",
15723
- text: buildChannel1Reminder(decision.level, decision.undroppedTokens, state2.oldestReclaimableToolTags)
15724
- };
15725
- }
15726
- var CHANNEL2_NUDGE_CUSTOM_TYPE = "magic-context:ceiling-nudge";
15727
- function maybeDeliverChannel2Pi(pi, db, sessionId, deliverAs = "followUp") {
15728
- let state2;
15729
- try {
15730
- state2 = getChannel2NudgeState(db, sessionId);
15731
- } catch {
15732
- return false;
15733
- }
15734
- if (state2 !== "pending")
15735
- return false;
15736
- const baseline = channel1StateBySession.get(sessionId);
15737
- if (!baseline)
15738
- return false;
15739
- if (baseline.reducedSinceRefresh)
15740
- return false;
15741
- const undropped = baseline.tailToolTokens + baseline.turnToolTokens;
15742
- if (!shouldTriggerChannel2({
15743
- reclaimableTokens: undropped,
15744
- usableTokens: baseline.usableTokens
15745
- })) {
15746
- try {
15747
- casChannel2NudgeState(db, sessionId, "pending", "");
15748
- } catch {}
15749
- return false;
15750
- }
15751
- if (!casChannel2NudgeState(db, sessionId, "pending", "claimed"))
15752
- return false;
15753
- try {
15754
- pi.sendMessage({
15755
- customType: CHANNEL2_NUDGE_CUSTOM_TYPE,
15756
- content: buildChannel2Reminder(undropped, baseline.oldestReclaimableToolTags),
15757
- display: false,
15758
- details: { kind: "channel-2-ceiling-nudge" }
15759
- }, { deliverAs });
15760
- } catch (error) {
15761
- try {
15762
- casChannel2NudgeState(db, sessionId, "claimed", "pending");
15763
- } catch (revertError) {
15764
- sessionLog(sessionId, "channel2 ceiling nudge delivery failed; pending restore was busy so the stale claim will heal later:", { deliveryError: error, revertError });
15765
- return false;
15766
- }
15767
- sessionLog(sessionId, "channel2 ceiling nudge delivery failed (will retry):", error);
15768
- return false;
15769
- }
15770
- try {
15771
- const confirmed = casChannel2NudgeState(db, sessionId, "claimed", "delivered");
15772
- if (confirmed) {
15773
- sessionLog(sessionId, "channel2 ceiling nudge delivered");
15774
- return true;
15775
- }
15776
- const outcome = sealDeliveredAfterUnconfirmedSend(db, sessionId);
15777
- if (outcome === "already-delivered") {
15778
- sessionLog(sessionId, "channel2 ceiling nudge duplicate window: our send returned after a sibling reclaimed the stale lease and already delivered");
15779
- } else if (outcome === "sealed") {
15780
- sessionLog(sessionId, "channel2 ceiling nudge sent but claim confirmation was lost; sealed delivered without an authoritative confirm");
15781
- } else {
15782
- sessionLog(sessionId, "channel2 ceiling nudge sent but claim confirmation was lost; lease stayed claimed and will heal later");
15783
- }
15784
- return false;
15785
- } catch (error) {
15786
- const outcome = sealDeliveredAfterUnconfirmedSend(db, sessionId);
15787
- if (outcome === "already-delivered") {
15788
- sessionLog(sessionId, "channel2 ceiling nudge duplicate window: our send returned after a sibling reclaimed the stale lease and already delivered");
15789
- } else if (outcome === "sealed") {
15790
- sessionLog(sessionId, "channel2 ceiling nudge sent but confirm failed:", error);
15791
- } else {
15792
- sessionLog(sessionId, "channel2 ceiling nudge sent but confirm failed; lease stayed claimed and will heal later:", error);
15793
- }
15794
- return false;
15795
- }
15796
- }
15797
-
15798
- // src/detect-recent-commit.ts
15799
- var COMMIT_LOOKBACK = 5;
15800
- function detectRecentCommit(messages) {
15801
- let assistantsScanned = 0;
15802
- for (let i = messages.length - 1;i >= 0; i--) {
15803
- const message = messages[i];
15804
- if (!message || typeof message !== "object" || !("role" in message) || message.role !== "assistant") {
15805
- continue;
15806
- }
15807
- assistantsScanned++;
15808
- if (assistantsScanned > COMMIT_LOOKBACK)
15809
- break;
15810
- if (!("content" in message))
15811
- continue;
15812
- const content = message.content;
15813
- if (!Array.isArray(content))
15814
- continue;
15815
- for (const part of content) {
15816
- if (part && typeof part === "object" && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string") {
15817
- if (textMentionsRecentCommit(part.text)) {
15818
- return true;
15819
- }
15820
- }
15821
- }
15822
- }
15823
- return false;
15824
- }
15825
-
15826
- // ../plugin/src/hooks/magic-context/emergency-drop.ts
15827
- var TARGET_FRACTION = 0.3;
15828
- var TIER_RECENCY_RESERVE = 0.2;
15829
- var EMERGENCY_REARM_MIN_TOKENS = 2000;
15830
- var T1_TOOLS = new Set(["read", "todowrite", "task", "aft_outline", "aft_zoom"]);
15831
- var T2_TOOLS = new Set(["edit", "write", "apply_patch", "grep", "glob", "aft_search"]);
15832
- function normalizeToolName(toolName) {
15833
- if (!toolName)
15834
- return "";
15835
- let name = toolName.toLowerCase();
15836
- if (name.startsWith("mcp_"))
15837
- name = name.slice(4);
15838
- return name;
15839
- }
15840
- function resolveToolTier(toolName) {
15841
- const name = normalizeToolName(toolName);
15842
- if (T1_TOOLS.has(name))
15843
- return 1;
15844
- if (T2_TOOLS.has(name))
15845
- return 2;
15846
- return 3;
15847
- }
15848
- function tagReclaimBytes(tag) {
15849
- return tag.byteSize + tag.inputByteSize + tag.reasoningByteSize;
15850
- }
15851
- function estimateEmergencyDropReclaimTokens(tag) {
15852
- return Math.round(tagReclaimBytes(tag) * TOKENS_PER_BYTE);
15853
- }
15854
- function planEmergencyDrop(input) {
15855
- const {
15856
- tags,
15857
- floorTags,
15858
- maxTag,
15859
- protectedTags,
15860
- currentTotalInputTokens,
15861
- ceilingTokens,
15862
- priorInputSample,
15863
- hasPriorDrop
15864
- } = input;
15865
- const noop = (reason) => ({
15866
- shouldDrop: false,
15867
- tagNumbers: [],
15868
- reclaimTokens: 0,
15869
- reason
15870
- });
15871
- if (!Number.isFinite(ceilingTokens) || ceilingTokens <= 0) {
15872
- return noop("unknown-ceiling");
15873
- }
15874
- if (!Number.isFinite(currentTotalInputTokens) || currentTotalInputTokens <= 0) {
15875
- return noop("unknown-usage");
15876
- }
15877
- if (hasPriorDrop && currentTotalInputTokens === priorInputSample) {
15878
- return noop("same-input-sample (awaiting fresh usage after prior drop)");
15879
- }
15880
- let tailTokens = 0;
15881
- for (const tag of floorTags) {
15882
- if (tag.status !== "active")
15883
- continue;
15884
- tailTokens += estimateEmergencyDropReclaimTokens(tag);
15885
- }
15886
- const fixedFloor = Math.max(currentTotalInputTokens - tailTokens, 0);
15887
- const workingSpan = Math.max(ceilingTokens - fixedFloor, 0);
15888
- const target = fixedFloor + TARGET_FRACTION * workingSpan;
15889
- const reclaimTokens = Math.round(currentTotalInputTokens - target);
15890
- if (reclaimTokens <= EMERGENCY_REARM_MIN_TOKENS) {
15891
- return noop(`reclaim<=min (${reclaimTokens} <= ${EMERGENCY_REARM_MIN_TOKENS})`);
15892
- }
15893
- const protectedCutoff = maxTag - protectedTags;
15894
- const tierActive = { 1: [], 2: [] };
15895
- for (const tag of tags) {
15896
- if (tag.status !== "active" || tag.type !== "tool")
15897
- continue;
15898
- const tier = resolveToolTier(tag.toolName);
15899
- if (tier === 1 || tier === 2)
15900
- tierActive[tier].push(tag.tagNumber);
15901
- }
15902
- const reserved = new Set;
15903
- for (const tier of [1, 2]) {
15904
- const nums = tierActive[tier];
15905
- if (nums.length === 0)
15906
- continue;
15907
- nums.sort((a, b) => b - a);
15908
- const reserveCount = Math.ceil(TIER_RECENCY_RESERVE * nums.length);
15909
- for (let i = 0;i < reserveCount && i < nums.length; i++) {
15910
- reserved.add(nums[i]);
15911
- }
15912
- }
15913
- const byTier = { 1: [], 2: [], 3: [] };
15914
- for (const tag of tags) {
15915
- if (tag.status !== "active" || tag.type !== "tool")
15916
- continue;
15917
- if (tag.tagNumber > protectedCutoff)
15918
- continue;
15919
- const tier = resolveToolTier(tag.toolName);
15920
- if ((tier === 1 || tier === 2) && reserved.has(tag.tagNumber))
15921
- continue;
15922
- byTier[tier].push(tag);
15923
- }
15924
- const selected = [];
15925
- let reclaimed = 0;
15926
- outer:
15927
- for (const tier of [3, 2, 1]) {
15928
- const group = byTier[tier];
15929
- group.sort((a, b) => a.tagNumber - b.tagNumber);
15930
- for (const tag of group) {
15931
- selected.push(tag.tagNumber);
15932
- reclaimed += estimateEmergencyDropReclaimTokens(tag);
15933
- if (reclaimed >= reclaimTokens)
15934
- break outer;
15935
- }
15936
- }
15937
- if (selected.length === 0) {
15938
- return noop("no-candidates");
15939
- }
15940
- return {
15941
- shouldDrop: true,
15942
- tagNumbers: selected,
15943
- reclaimTokens,
15944
- reason: `tiered drop: ${selected.length} tags, reclaim≈${reclaimed}/${reclaimTokens} tokens (floor≈${fixedFloor}, ceiling=${Math.round(ceilingTokens)})`
15945
- };
15946
- }
15947
-
15948
- // ../plugin/src/hooks/magic-context/system-injection-stripper.ts
15949
- var SYSTEM_INJECTION_MARKERS = [
15950
- "<!-- OMO_INTERNAL_INITIATOR -->",
15951
- "[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
15952
- "[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
15953
- "[Category+Skill Reminder]",
15954
- "[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
15955
- "[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
15956
- "[EMERGENCY CONTEXT WINDOW WARNING]",
15957
- "Unstable background agent appears idle",
15958
- "**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
15959
- ];
15960
- var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
15961
- var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
15962
- function stripSystemInjection(text) {
15963
- let hasInjection = false;
15964
- for (const marker of SYSTEM_INJECTION_MARKERS) {
15965
- if (text.includes(marker)) {
15966
- hasInjection = true;
15967
- break;
15968
- }
15969
- }
15970
- if (SYSTEM_REMINDER_REGEX.test(text))
15971
- hasInjection = true;
15972
- SYSTEM_REMINDER_REGEX.lastIndex = 0;
15973
- if (!hasInjection)
15974
- return null;
15975
- let cleaned = text;
15976
- cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
15977
- cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
15978
- cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
15979
- for (const marker of SYSTEM_INJECTION_MARKERS) {
15980
- if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
15981
- continue;
15982
- const idx = cleaned.indexOf(marker);
15983
- if (idx === -1)
15984
- continue;
15985
- const blockEnd = cleaned.indexOf(`
15986
-
15987
- `, idx + marker.length);
15988
- cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
15989
- }
15990
- return cleaned.trim();
15991
- }
15992
-
15993
- // src/heuristic-cleanup-pi.ts
15994
- var DEDUP_SAFE_TOOLS = new Set([
15995
- "mcp_grep",
15996
- "mcp_read",
15997
- "mcp_glob",
15998
- "mcp_ast_grep_search",
15999
- "mcp_lsp_diagnostics",
16000
- "mcp_lsp_symbols",
16001
- "mcp_lsp_find_references",
16002
- "mcp_lsp_goto_definition",
16003
- "mcp_lsp_prepare_rename"
16004
- ]);
16005
- function buildPiToolFingerprints(messages, resolveStableId) {
16006
- const fingerprints = new Map;
16007
- for (let i = 0;i < messages.length; i++) {
16008
- const message = messages[i];
16009
- if (!message || typeof message !== "object")
16010
- continue;
16011
- const msg = message;
16012
- if (msg.role !== "assistant")
16013
- continue;
16014
- if (!Array.isArray(msg.content))
15632
+ if (!Array.isArray(msg.content))
16015
15633
  continue;
16016
15634
  const ownerMsgId = resolveStableId(message, i);
16017
15635
  if (!ownerMsgId)
@@ -16045,9 +15663,8 @@ function buildPiToolFingerprints(messages, resolveStableId) {
16045
15663
  }
16046
15664
  return fingerprints;
16047
15665
  }
16048
- function collectStaleReduceCallIds(messages, messageIdToMaxTag, toolAgeCutoff, resolveStableId) {
16049
- const composite = new Set;
16050
- const bareCallIds = new Set;
15666
+ function collectStaleReduceCallIds(messages, messageIdToMaxTag, ctxReduceTagNumbers, toolAgeCutoff, resolveStableId) {
15667
+ const reduceCalls = new Map;
16051
15668
  for (let i = 0;i < messages.length; i++) {
16052
15669
  const raw = messages[i];
16053
15670
  if (!raw || typeof raw !== "object")
@@ -16058,9 +15675,7 @@ function collectStaleReduceCallIds(messages, messageIdToMaxTag, toolAgeCutoff, r
16058
15675
  const stableId = resolveStableId(raw, i);
16059
15676
  if (!stableId)
16060
15677
  continue;
16061
- const maxTag = messageIdToMaxTag.get(stableId) ?? 0;
16062
- if (maxTag === 0 || maxTag > toolAgeCutoff)
16063
- continue;
15678
+ const ownerMaxTag = messageIdToMaxTag.get(stableId) ?? 0;
16064
15679
  for (const part of msg.content) {
16065
15680
  if (!part || typeof part !== "object")
16066
15681
  continue;
@@ -16071,10 +15686,35 @@ function collectStaleReduceCallIds(messages, messageIdToMaxTag, toolAgeCutoff, r
16071
15686
  continue;
16072
15687
  if (typeof p.id !== "string" || p.id.length === 0)
16073
15688
  continue;
16074
- composite.add(`${stableId}\x00${p.id}`);
16075
- bareCallIds.add(p.id);
15689
+ const composite2 = `${stableId}\x00${p.id}`;
15690
+ const maxTag = ctxReduceTagNumbers.get(composite2) ?? ownerMaxTag;
15691
+ if (maxTag === 0)
15692
+ continue;
15693
+ reduceCalls.set(composite2, {
15694
+ composite: composite2,
15695
+ callId: p.id,
15696
+ maxTag,
15697
+ messageIndex: i
15698
+ });
16076
15699
  }
16077
15700
  }
15701
+ const newestFirst = [...reduceCalls.values()].sort((left, right) => {
15702
+ const byPosition = right.maxTag - left.maxTag || right.messageIndex - left.messageIndex;
15703
+ if (byPosition !== 0)
15704
+ return byPosition;
15705
+ if (left.composite === right.composite)
15706
+ return 0;
15707
+ return left.composite < right.composite ? 1 : -1;
15708
+ });
15709
+ const protectedComposite = new Set(newestFirst.slice(0, PI_CTX_REDUCE_KEEP).map((call) => call.composite));
15710
+ const composite = new Set;
15711
+ const bareCallIds = new Set;
15712
+ for (const call of newestFirst) {
15713
+ if (call.maxTag > toolAgeCutoff || protectedComposite.has(call.composite))
15714
+ continue;
15715
+ composite.add(call.composite);
15716
+ bareCallIds.add(call.callId);
15717
+ }
16078
15718
  return { composite, bareCallIds };
16079
15719
  }
16080
15720
  function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, preloadedTags, resolveId) {
@@ -16137,7 +15777,7 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
16137
15777
  }
16138
15778
  setEmergencyDropSample(db, sessionId, emergency.currentTotalInputTokens);
16139
15779
  }
16140
- const staleReduce = config.staleReduceStripEnabled ? collectStaleReduceCallIds(piMessages, buildMessageIdToMaxTagFromTargets(targets), toolAgeCutoff, resolveStableId) : { composite: new Set, bareCallIds: new Set };
15780
+ const staleReduce = config.staleReduceStripEnabled ? collectStaleReduceCallIds(piMessages, buildMessageIdToMaxTagFromTargets(targets), buildCtxReduceTagNumbers(tags), toolAgeCutoff, resolveStableId) : { composite: new Set, bareCallIds: new Set };
16141
15781
  if (config.staleReduceStripEnabled && (staleReduce.composite.size > 0 || staleReduce.bareCallIds.size > 0)) {
16142
15782
  db.transaction(() => {
16143
15783
  for (const tag of tags) {
@@ -16235,42 +15875,770 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
16235
15875
  }
16236
15876
  }
16237
15877
  }
16238
- })();
15878
+ })();
15879
+ }
15880
+ if (droppedTools > 0 || deduplicatedTools > 0 || droppedInjections > 0 || droppedStaleReduceCalls > 0) {
15881
+ sessionLog(sessionId, `heuristic cleanup: dropped ${droppedTools} tool tags, stale ctx_reduce=${droppedStaleReduceCalls}, deduplicated ${deduplicatedTools} tool calls, dropped ${droppedInjections} system injections`);
15882
+ }
15883
+ let compressedTextTags = 0;
15884
+ let mutatedTextTags = 0;
15885
+ if (config.caveman?.enabled) {
15886
+ const cavemanResult = applyCavemanCleanup(sessionId, db, targets, tags, {
15887
+ enabled: true,
15888
+ minChars: config.caveman.minChars,
15889
+ protectedTags: config.protectedTags
15890
+ });
15891
+ compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
15892
+ mutatedTextTags = cavemanResult.mutatedTextTags;
15893
+ }
15894
+ return {
15895
+ droppedTools,
15896
+ deduplicatedTools,
15897
+ droppedInjections,
15898
+ droppedStaleReduceCalls,
15899
+ emergencyDroppedTools,
15900
+ compressedTextTags,
15901
+ mutatedTextTags
15902
+ };
15903
+ }
15904
+ function buildCtxReduceTagNumbers(tags) {
15905
+ const byComposite = new Map;
15906
+ for (const tag of tags) {
15907
+ if (tag.status !== "active" || tag.type !== "tool" || tag.toolName !== "ctx_reduce" || !tag.toolOwnerMessageId) {
15908
+ continue;
15909
+ }
15910
+ byComposite.set(`${tag.toolOwnerMessageId}\x00${tag.messageId}`, tag.tagNumber);
15911
+ }
15912
+ return byComposite;
15913
+ }
15914
+ function buildMessageIdToMaxTagFromTargets(targets) {
15915
+ const byMessage = new Map;
15916
+ for (const [tagNumber, target] of targets) {
15917
+ const id = target.message?.info?.id;
15918
+ if (typeof id !== "string" || id.length === 0)
15919
+ continue;
15920
+ if (tagNumber > (byMessage.get(id) ?? 0))
15921
+ byMessage.set(id, tagNumber);
15922
+ }
15923
+ return byMessage;
15924
+ }
15925
+
15926
+ // src/tail-hygiene-walk-pi.ts
15927
+ var TAG_PREFIX = /^§(\d+)§\s*/;
15928
+ var SYNTHETIC_TODO_PREFIX = "mc_synthetic_todo_";
15929
+ var MAX_CONTENT_MEMO_ENTRIES = 1e5;
15930
+ var MAX_CONTENT_MEMO_BYTES = 64 * 1024 * 1024;
15931
+ var contentMemo = new Map;
15932
+ var contentMemoBytes = 0;
15933
+ var FNV1A_32_OFFSET = 2166136261;
15934
+ var FNV1A_32_PRIME = 16777619;
15935
+ function isRecord3(value) {
15936
+ return value !== null && typeof value === "object";
15937
+ }
15938
+ function fnv1a32(value) {
15939
+ let hash = FNV1A_32_OFFSET;
15940
+ for (let index = 0;index < value.length; index += 1) {
15941
+ hash ^= value.charCodeAt(index);
15942
+ hash = Math.imul(hash, FNV1A_32_PRIME);
15943
+ }
15944
+ return (hash >>> 0).toString(16).padStart(8, "0");
15945
+ }
15946
+ function safeStableStringify(value) {
15947
+ const seen = new Set;
15948
+ try {
15949
+ return JSON.stringify(value, (_key, current) => {
15950
+ if (!isRecord3(current) || Array.isArray(current))
15951
+ return current;
15952
+ if (seen.has(current))
15953
+ return "[Circular]";
15954
+ seen.add(current);
15955
+ return Object.fromEntries(Object.entries(current).sort(([left], [right]) => left.localeCompare(right)));
15956
+ }) ?? "";
15957
+ } catch {
15958
+ return "";
15959
+ }
15960
+ }
15961
+ function memoizedContent(kind, content) {
15962
+ const key = `${kind}\x00${content}`;
15963
+ const cached = contentMemo.get(key);
15964
+ if (cached)
15965
+ return cached;
15966
+ const measured = {
15967
+ hash: fnv1a32(key),
15968
+ tokens: kind === "excluded" ? 0 : estimateTokens(content),
15969
+ keyBytes: key.length * 2 + 32
15970
+ };
15971
+ contentMemo.set(key, measured);
15972
+ contentMemoBytes += measured.keyBytes;
15973
+ while (contentMemo.size > MAX_CONTENT_MEMO_ENTRIES || contentMemoBytes > MAX_CONTENT_MEMO_BYTES) {
15974
+ const oldest = contentMemo.keys().next().value;
15975
+ if (typeof oldest !== "string")
15976
+ break;
15977
+ const removed = contentMemo.get(oldest);
15978
+ if (removed)
15979
+ contentMemoBytes -= removed.keyBytes;
15980
+ contentMemo.delete(oldest);
15981
+ }
15982
+ return measured;
15983
+ }
15984
+ function memoizedTokens(kind, content) {
15985
+ return memoizedContent(kind, content).tokens;
15986
+ }
15987
+ function partHash(kind, content) {
15988
+ return memoizedContent(kind, content).hash;
15989
+ }
15990
+ function parseVisibleTag(content, tagsByNumber) {
15991
+ const match = content.trimStart().match(TAG_PREFIX);
15992
+ if (!match)
15993
+ return;
15994
+ const tagNumber = Number(match[1]);
15995
+ return Number.isSafeInteger(tagNumber) ? tagsByNumber.get(tagNumber) : undefined;
15996
+ }
15997
+ function isDropSentinel(content) {
15998
+ const head = content.trimStart().replace(TAG_PREFIX, "").trimStart().toLowerCase();
15999
+ return head.startsWith("[dropped") || head.startsWith("[truncated");
16000
+ }
16001
+ function messageIdentity(message, index, stableId) {
16002
+ const resolved = stableId?.(message, index);
16003
+ if (resolved)
16004
+ return resolved;
16005
+ if (isRecord3(message)) {
16006
+ if (typeof message.responseId === "string" && message.responseId.length > 0) {
16007
+ return `response:${message.responseId}`;
16008
+ }
16009
+ if (typeof message.timestamp === "number") {
16010
+ return `timestamp:${message.timestamp}:${String(message.role ?? "unknown")}`;
16011
+ }
16012
+ }
16013
+ return `pi-message:${index}`;
16014
+ }
16015
+ function isSyntheticMessage(message, index, input) {
16016
+ if (index < Math.max(0, input.syntheticLeadingCount ?? 0))
16017
+ return true;
16018
+ if (input.syntheticMessages?.has(message))
16019
+ return true;
16020
+ if (message.syntheticTodoMarker === true)
16021
+ return true;
16022
+ const role = typeof message.role === "string" ? message.role : "";
16023
+ return role === "system" || role === "custom" || role === "compactionSummary";
16024
+ }
16025
+ function imageContentAndTokens(part) {
16026
+ const data = typeof part.data === "string" ? part.data : "";
16027
+ const mimeType = typeof part.mimeType === "string" ? part.mimeType : "image/png";
16028
+ const content = data.startsWith("data:") ? data : `data:${mimeType};base64,${data}`;
16029
+ return {
16030
+ content,
16031
+ tokens: content.length > 0 ? estimateImageTokensFromDataUrl(content) : 0
16032
+ };
16033
+ }
16034
+ function messageIdForTag(tag) {
16035
+ if (tag.type === "tool")
16036
+ return tag.toolOwnerMessageId;
16037
+ const positional = tag.messageId.match(/^(.*):(?:p|file)\d+$/);
16038
+ if (positional)
16039
+ return positional[1] ?? null;
16040
+ const contentDerived = tag.messageId.indexOf(":mc-text-v1:");
16041
+ return contentDerived >= 0 ? tag.messageId.slice(0, contentDerived) : null;
16042
+ }
16043
+ function neighborhoodConsistent(input) {
16044
+ let previousMax = null;
16045
+ for (let index = 0;index <= input.messageIndex; index += 1) {
16046
+ const bound = input.boundsByMessageIndex.get(index);
16047
+ if (bound)
16048
+ previousMax = previousMax === null ? bound.max : Math.max(previousMax, bound.max);
16049
+ }
16050
+ let nextMin = null;
16051
+ for (let index = input.messageIndex + 1;index < input.messageCount; index += 1) {
16052
+ const bound = input.boundsByMessageIndex.get(index);
16053
+ if (bound)
16054
+ nextMin = nextMin === null ? bound.min : Math.min(nextMin, bound.min);
16055
+ }
16056
+ return previousMax !== null && nextMin !== null && input.orphanTagNumber >= previousMax && input.orphanTagNumber <= nextMin;
16057
+ }
16058
+ function collectToolArcs(input) {
16059
+ const arcs = [];
16060
+ const arcByPart = new Map;
16061
+ const pendingByCall = new Map;
16062
+ const messageIds = input.messages.map((message, index) => messageIdentity(message, index, input.stableId));
16063
+ for (let messageIndex = 0;messageIndex < input.messages.length; messageIndex += 1) {
16064
+ const raw = input.messages[messageIndex];
16065
+ if (!isRecord3(raw))
16066
+ continue;
16067
+ const role = raw.role;
16068
+ if (role === "assistant" && Array.isArray(raw.content)) {
16069
+ for (let partIndex = 0;partIndex < raw.content.length; partIndex += 1) {
16070
+ const part = raw.content[partIndex];
16071
+ if (!isRecord3(part) || part.type !== "toolCall")
16072
+ continue;
16073
+ if (typeof part.id !== "string" || part.id.length === 0)
16074
+ continue;
16075
+ const ownerId2 = messageIds[messageIndex] ?? `pi-message:${messageIndex}`;
16076
+ const arc2 = {
16077
+ key: `${ownerId2}\x00${part.id}\x00${partIndex}`,
16078
+ callId: part.id,
16079
+ ownerId: ownerId2,
16080
+ ownerIndex: messageIndex,
16081
+ toolName: typeof part.name === "string" ? part.name : null,
16082
+ sentinel: isRecord3(part.arguments) && typeof part.arguments.__magic_context_dropped__ === "string",
16083
+ parts: [part]
16084
+ };
16085
+ arcs.push(arc2);
16086
+ arcByPart.set(part, arc2);
16087
+ const pending2 = pendingByCall.get(part.id) ?? [];
16088
+ pending2.push(arc2);
16089
+ pendingByCall.set(part.id, pending2);
16090
+ }
16091
+ continue;
16092
+ }
16093
+ if (role !== "toolResult")
16094
+ continue;
16095
+ if (typeof raw.toolCallId !== "string" || raw.toolCallId.length === 0)
16096
+ continue;
16097
+ const pending = pendingByCall.get(raw.toolCallId);
16098
+ const matched = pending?.pop();
16099
+ const ownerId = matched?.ownerId ?? messageIds[messageIndex] ?? `pi-message:${messageIndex}`;
16100
+ const arc = matched ?? {
16101
+ key: `${ownerId}\x00${raw.toolCallId}\x00result:${messageIndex}`,
16102
+ callId: raw.toolCallId,
16103
+ ownerId,
16104
+ ownerIndex: messageIndex,
16105
+ toolName: typeof raw.toolName === "string" ? raw.toolName : null,
16106
+ sentinel: false,
16107
+ parts: []
16108
+ };
16109
+ if (!matched)
16110
+ arcs.push(arc);
16111
+ if (!Array.isArray(raw.content))
16112
+ continue;
16113
+ for (const part of raw.content) {
16114
+ if (!isRecord3(part))
16115
+ continue;
16116
+ arc.parts.push(part);
16117
+ arcByPart.set(part, arc);
16118
+ if (part.type === "text" && typeof part.text === "string" && isDropSentinel(part.text)) {
16119
+ arc.sentinel = true;
16120
+ }
16121
+ }
16122
+ }
16123
+ return { arcs, arcByPart, messageIds };
16124
+ }
16125
+ function attributeTags(input, arcs, messageIds) {
16126
+ const messageTags = new Map;
16127
+ const tagsByNumber = new Map;
16128
+ const exactToolTags = new Map;
16129
+ const orphanTagsByCall = new Map;
16130
+ const messageIndexById = new Map;
16131
+ for (let index = 0;index < messageIds.length; index += 1) {
16132
+ const id = input.stableId?.(input.messages[index], index);
16133
+ if (id)
16134
+ messageIndexById.set(id, index);
16135
+ }
16136
+ const boundsByMessageIndex = new Map;
16137
+ for (const tag of input.tags) {
16138
+ tagsByNumber.set(tag.tagNumber, tag);
16139
+ if (tag.type === "tool") {
16140
+ if (tag.toolOwnerMessageId === null) {
16141
+ const rows = orphanTagsByCall.get(tag.messageId) ?? [];
16142
+ rows.push(tag);
16143
+ orphanTagsByCall.set(tag.messageId, rows);
16144
+ } else {
16145
+ exactToolTags.set(`${tag.toolOwnerMessageId}\x00${tag.messageId}`, tag);
16146
+ }
16147
+ } else {
16148
+ messageTags.set(tag.messageId, tag);
16149
+ }
16150
+ const ownerId = messageIdForTag(tag);
16151
+ const messageIndex = ownerId === null ? undefined : messageIndexById.get(ownerId);
16152
+ if (messageIndex === undefined)
16153
+ continue;
16154
+ const current = boundsByMessageIndex.get(messageIndex);
16155
+ boundsByMessageIndex.set(messageIndex, {
16156
+ min: current ? Math.min(current.min, tag.tagNumber) : tag.tagNumber,
16157
+ max: current ? Math.max(current.max, tag.tagNumber) : tag.tagNumber
16158
+ });
16159
+ }
16160
+ const orphanCandidates = new Map;
16161
+ for (const arc of arcs) {
16162
+ const exact = exactToolTags.get(`${arc.ownerId}\x00${arc.callId}`);
16163
+ if (exact) {
16164
+ arc.tag = exact;
16165
+ continue;
16166
+ }
16167
+ const orphans = orphanTagsByCall.get(arc.callId);
16168
+ if (orphans?.length !== 1)
16169
+ continue;
16170
+ if (!neighborhoodConsistent({
16171
+ orphanTagNumber: orphans[0].tagNumber,
16172
+ messageIndex: arc.ownerIndex,
16173
+ boundsByMessageIndex,
16174
+ messageCount: input.messages.length
16175
+ })) {
16176
+ continue;
16177
+ }
16178
+ const byOwner = orphanCandidates.get(arc.callId) ?? new Map;
16179
+ const ownerArcs = byOwner.get(arc.ownerId) ?? [];
16180
+ ownerArcs.push(arc);
16181
+ byOwner.set(arc.ownerId, ownerArcs);
16182
+ orphanCandidates.set(arc.callId, byOwner);
16183
+ }
16184
+ for (const [callId, byOwner] of orphanCandidates) {
16185
+ if (byOwner.size !== 1)
16186
+ continue;
16187
+ const orphan = orphanTagsByCall.get(callId)?.[0];
16188
+ if (!orphan)
16189
+ continue;
16190
+ for (const ownerArcs of byOwner.values()) {
16191
+ for (const arc of ownerArcs)
16192
+ arc.tag = orphan;
16193
+ }
16194
+ }
16195
+ for (const arc of arcs) {
16196
+ if (arc.tag)
16197
+ continue;
16198
+ for (const part of arc.parts) {
16199
+ if (part.type !== "text" || typeof part.text !== "string")
16200
+ continue;
16201
+ const visible = parseVisibleTag(part.text, tagsByNumber);
16202
+ if (visible?.type === "tool") {
16203
+ arc.tag = visible;
16204
+ break;
16205
+ }
16206
+ }
16207
+ }
16208
+ return { messageTags, tagsByNumber };
16209
+ }
16210
+ function excludedDraft(key, value) {
16211
+ return {
16212
+ key,
16213
+ kind: "excluded",
16214
+ content: typeof value === "string" ? value : safeStableStringify(value),
16215
+ tokens: 0
16216
+ };
16217
+ }
16218
+ function finalizeParts(drafts, protectedTags) {
16219
+ const visibleTags = new Map;
16220
+ for (const part of drafts) {
16221
+ if (part.kind !== "excluded" && part.tag)
16222
+ visibleTags.set(part.tag.tagNumber, part.tag);
16223
+ }
16224
+ const protectedNumbers = new Set([...visibleTags.keys()].sort((left, right) => right - left).slice(0, Math.max(0, protectedTags)));
16225
+ const exemplarNumbers = [...visibleTags.values()].filter((tag) => tag.type === "tool" && tag.toolName === "ctx_reduce").sort((left, right) => right.tagNumber - left.tagNumber).slice(0, PI_CTX_REDUCE_KEEP).map((tag) => tag.tagNumber);
16226
+ for (const tagNumber of exemplarNumbers)
16227
+ protectedNumbers.add(tagNumber);
16228
+ let u = 0;
16229
+ let t = 0;
16230
+ const parts = drafts.map((draft) => {
16231
+ const protectedPart = draft.tag ? protectedNumbers.has(draft.tag.tagNumber) : false;
16232
+ const tokens = Math.max(0, draft.tokens);
16233
+ const uTokens = draft.tag && !protectedPart && draft.kind !== "excluded" ? tokens : 0;
16234
+ t += tokens;
16235
+ u += uTokens;
16236
+ return {
16237
+ key: draft.key,
16238
+ contentHash: partHash(draft.kind, draft.content),
16239
+ kind: draft.kind,
16240
+ tokens,
16241
+ uTokens,
16242
+ tagNumber: draft.tag?.tagNumber ?? null,
16243
+ tagStatus: draft.tag ? "active" : null,
16244
+ protected: protectedPart
16245
+ };
16246
+ });
16247
+ const clampedT = Math.max(0, t);
16248
+ return {
16249
+ u: Math.min(clampedT, Math.max(0, u)),
16250
+ t: clampedT,
16251
+ contentSignature: fnv1a32(parts.map((part) => `${part.key}:${part.contentHash}`).join("\x00")),
16252
+ parts
16253
+ };
16254
+ }
16255
+ function measurePiTailHygiene(input) {
16256
+ const { arcs, arcByPart, messageIds } = collectToolArcs(input);
16257
+ const { messageTags, tagsByNumber } = attributeTags(input, arcs, messageIds);
16258
+ const drafts = [];
16259
+ for (let messageIndex = 0;messageIndex < input.messages.length; messageIndex += 1) {
16260
+ const raw = input.messages[messageIndex];
16261
+ const messageKey = messageIds[messageIndex] ?? `pi-message:${messageIndex}`;
16262
+ if (!isRecord3(raw)) {
16263
+ drafts.push(excludedDraft(`${messageKey}\x00excluded`, raw));
16264
+ continue;
16265
+ }
16266
+ if (isSyntheticMessage(raw, messageIndex, input)) {
16267
+ drafts.push(excludedDraft(`${messageKey}\x00synthetic`, raw));
16268
+ continue;
16269
+ }
16270
+ const role = raw.role;
16271
+ if (role !== "user" && role !== "assistant" && role !== "toolResult") {
16272
+ drafts.push(excludedDraft(`${messageKey}\x00excluded-role`, raw));
16273
+ continue;
16274
+ }
16275
+ if (typeof raw.content === "string") {
16276
+ const content = raw.content;
16277
+ const tag = parseVisibleTag(content, tagsByNumber) ?? messageTags.get(`${messageKey}:p0`);
16278
+ if (!content || isDropSentinel(content)) {
16279
+ drafts.push(excludedDraft(`${messageKey}\x00text:0`, content));
16280
+ } else {
16281
+ drafts.push({
16282
+ key: `${messageKey}\x00text:0`,
16283
+ kind: "text",
16284
+ content,
16285
+ tokens: memoizedTokens("text", content),
16286
+ tag
16287
+ });
16288
+ }
16289
+ continue;
16290
+ }
16291
+ if (!Array.isArray(raw.content)) {
16292
+ drafts.push(excludedDraft(`${messageKey}\x00excluded-content`, raw.content));
16293
+ continue;
16294
+ }
16295
+ let textOrdinal = 0;
16296
+ for (let partIndex = 0;partIndex < raw.content.length; partIndex += 1) {
16297
+ const part = raw.content[partIndex];
16298
+ const key = `${messageKey}\x00${partIndex}`;
16299
+ if (!isRecord3(part)) {
16300
+ drafts.push(excludedDraft(`${key}\x00excluded`, part));
16301
+ continue;
16302
+ }
16303
+ if (part.syntheticTodoMarker === true) {
16304
+ drafts.push(excludedDraft(`${key}\x00synthetic-todo`, part));
16305
+ continue;
16306
+ }
16307
+ if (part.type === "thinking" || part.type === "reasoning" || part.type === "redacted_thinking") {
16308
+ drafts.push(excludedDraft(`${key}\x00reasoning`, part));
16309
+ continue;
16310
+ }
16311
+ if (part.type === "text" && typeof part.text === "string") {
16312
+ if (role === "toolResult") {
16313
+ const arc = arcByPart.get(part);
16314
+ const content2 = stripChannel1ReminderSpans(part.text);
16315
+ const tag2 = parseVisibleTag(content2, tagsByNumber) ?? arc?.tag;
16316
+ if (arc?.sentinel || !content2 || isDropSentinel(content2)) {
16317
+ drafts.push(excludedDraft(`${key}\x00toolOutput`, content2));
16318
+ } else {
16319
+ drafts.push({
16320
+ key: `${key}\x00toolOutput`,
16321
+ kind: "toolOutput",
16322
+ content: content2,
16323
+ tokens: memoizedTokens("toolOutput", content2),
16324
+ tag: tag2
16325
+ });
16326
+ }
16327
+ continue;
16328
+ }
16329
+ const content = part.text;
16330
+ const tag = parseVisibleTag(content, tagsByNumber) ?? messageTags.get(`${messageKey}:p${textOrdinal}`);
16331
+ textOrdinal += 1;
16332
+ if (!content || isDropSentinel(content)) {
16333
+ drafts.push(excludedDraft(`${key}\x00text`, content));
16334
+ } else {
16335
+ drafts.push({
16336
+ key: `${key}\x00text`,
16337
+ kind: "text",
16338
+ content,
16339
+ tokens: memoizedTokens("text", content),
16340
+ tag
16341
+ });
16342
+ }
16343
+ continue;
16344
+ }
16345
+ if (part.type === "image") {
16346
+ const image = imageContentAndTokens(part);
16347
+ const arc = role === "toolResult" ? arcByPart.get(part) : undefined;
16348
+ const tag = arc?.tag ?? messageTags.get(`${messageKey}:file${partIndex}`);
16349
+ if (arc?.sentinel || !image.content) {
16350
+ drafts.push(excludedDraft(`${key}\x00image`, part));
16351
+ } else {
16352
+ drafts.push({
16353
+ key: `${key}\x00${role === "toolResult" ? "toolOutput" : "file"}`,
16354
+ kind: role === "toolResult" ? "toolOutput" : "file",
16355
+ content: image.content,
16356
+ tokens: image.tokens,
16357
+ tag
16358
+ });
16359
+ }
16360
+ continue;
16361
+ }
16362
+ if (part.type === "toolCall") {
16363
+ const arc = arcByPart.get(part);
16364
+ const callId = typeof part.id === "string" ? part.id : "";
16365
+ if (part.syntheticTodoMarker === true || callId.startsWith(SYNTHETIC_TODO_PREFIX) || arc?.sentinel) {
16366
+ drafts.push(excludedDraft(`${key}\x00toolInput`, part));
16367
+ continue;
16368
+ }
16369
+ const content = safeStableStringify(part.arguments);
16370
+ if (!content) {
16371
+ drafts.push(excludedDraft(`${key}\x00toolInput`, part));
16372
+ } else {
16373
+ drafts.push({
16374
+ key: `${key}\x00toolInput`,
16375
+ kind: "toolInput",
16376
+ content,
16377
+ tokens: memoizedTokens("toolInput", content),
16378
+ tag: arc?.tag
16379
+ });
16380
+ }
16381
+ continue;
16382
+ }
16383
+ drafts.push(excludedDraft(`${key}\x00excluded`, part));
16384
+ }
16239
16385
  }
16240
- if (droppedTools > 0 || deduplicatedTools > 0 || droppedInjections > 0 || droppedStaleReduceCalls > 0) {
16241
- sessionLog(sessionId, `heuristic cleanup: dropped ${droppedTools} tool tags, stale ctx_reduce=${droppedStaleReduceCalls}, deduplicated ${deduplicatedTools} tool calls, dropped ${droppedInjections} system injections`);
16386
+ return finalizeParts(drafts, input.protectedTags);
16387
+ }
16388
+ function sameMeasuredPrefix(baseline, current) {
16389
+ if (current.length < baseline.length)
16390
+ return { valid: false, boundaryAdvanceU: 0 };
16391
+ let boundaryAdvanceU = 0;
16392
+ for (let index = 0;index < baseline.length; index += 1) {
16393
+ const before = baseline[index];
16394
+ const after = current[index];
16395
+ if (before.key !== after.key || before.contentHash !== after.contentHash || before.kind !== after.kind || before.tokens !== after.tokens || before.tagNumber !== after.tagNumber || before.tagStatus !== after.tagStatus) {
16396
+ return { valid: false, boundaryAdvanceU: 0 };
16397
+ }
16398
+ if (!before.protected && after.protected)
16399
+ return { valid: false, boundaryAdvanceU: 0 };
16400
+ if (before.protected && !after.protected) {
16401
+ if (after.tagStatus !== "active")
16402
+ return { valid: false, boundaryAdvanceU: 0 };
16403
+ boundaryAdvanceU += after.tokens;
16404
+ } else if (before.uTokens !== after.uTokens) {
16405
+ return { valid: false, boundaryAdvanceU: 0 };
16406
+ }
16242
16407
  }
16243
- let compressedTextTags = 0;
16244
- let mutatedTextTags = 0;
16245
- if (config.caveman?.enabled) {
16246
- const cavemanResult = applyCavemanCleanup(sessionId, db, targets, tags, {
16247
- enabled: true,
16248
- minChars: config.caveman.minChars,
16249
- protectedTags: config.protectedTags
16250
- });
16251
- compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
16252
- mutatedTextTags = cavemanResult.mutatedTextTags;
16408
+ return { valid: true, boundaryAdvanceU };
16409
+ }
16410
+ function refreshPiTailHygieneBaseline(input) {
16411
+ const measured = measurePiTailHygiene(input);
16412
+ const now = input.now ?? Date.now();
16413
+ if (!input.cacheBusting && input.previous?.generationInvalidated) {
16414
+ return { ...input.previous, contentSignature: measured.contentSignature };
16415
+ }
16416
+ if (input.cacheBusting || !input.previous) {
16417
+ return {
16418
+ baselineU: measured.u,
16419
+ baselineT: measured.t,
16420
+ turnDeltaU: 0,
16421
+ turnDeltaT: 0,
16422
+ baselineGeneration: (input.previous?.baselineGeneration ?? 0) + 1,
16423
+ computedAt: now,
16424
+ evaluable: true,
16425
+ generationInvalidated: false,
16426
+ baselineParts: measured.parts,
16427
+ contentSignature: measured.contentSignature
16428
+ };
16429
+ }
16430
+ const prefix = sameMeasuredPrefix(input.previous.baselineParts, measured.parts);
16431
+ if (!prefix.valid) {
16432
+ return {
16433
+ ...input.previous,
16434
+ evaluable: false,
16435
+ generationInvalidated: true,
16436
+ contentSignature: measured.contentSignature
16437
+ };
16438
+ }
16439
+ let turnDeltaT = 0;
16440
+ let turnDeltaU = prefix.boundaryAdvanceU;
16441
+ for (let index = input.previous.baselineParts.length;index < measured.parts.length; index += 1) {
16442
+ const part = measured.parts[index];
16443
+ turnDeltaT += part.tokens;
16444
+ if (part.kind !== "toolOutput")
16445
+ turnDeltaU += part.uTokens;
16253
16446
  }
16254
16447
  return {
16255
- droppedTools,
16256
- deduplicatedTools,
16257
- droppedInjections,
16258
- droppedStaleReduceCalls,
16259
- emergencyDroppedTools,
16260
- compressedTextTags,
16261
- mutatedTextTags
16448
+ ...input.previous,
16449
+ turnDeltaU,
16450
+ turnDeltaT,
16451
+ evaluable: true,
16452
+ generationInvalidated: false,
16453
+ contentSignature: measured.contentSignature
16262
16454
  };
16263
16455
  }
16264
- function buildMessageIdToMaxTagFromTargets(targets) {
16265
- const byMessage = new Map;
16266
- for (const [tagNumber, target] of targets) {
16267
- const id = target.message?.info?.id;
16268
- if (typeof id !== "string" || id.length === 0)
16456
+ function effectivePiTailHygiene(baseline) {
16457
+ const t = Math.max(0, baseline.baselineT + baseline.turnDeltaT);
16458
+ const u = Math.min(t, Math.max(0, baseline.baselineU + baseline.turnDeltaU));
16459
+ return { u, t };
16460
+ }
16461
+ function measurePiToolResultDelta(content) {
16462
+ let tokens = 0;
16463
+ for (const part of content) {
16464
+ if (!isRecord3(part))
16269
16465
  continue;
16270
- if (tagNumber > (byMessage.get(id) ?? 0))
16271
- byMessage.set(id, tagNumber);
16466
+ if (part.type === "text" && typeof part.text === "string") {
16467
+ const text = stripChannel1ReminderSpans(part.text);
16468
+ if (text && !isDropSentinel(text))
16469
+ tokens += memoizedTokens("toolOutput", text);
16470
+ } else if (part.type === "image") {
16471
+ tokens += imageContentAndTokens(part).tokens;
16472
+ }
16272
16473
  }
16273
- return byMessage;
16474
+ return Math.max(0, tokens);
16475
+ }
16476
+ function assertPiTailHygieneContentUnchanged(input) {
16477
+ const current = measurePiTailHygiene(input);
16478
+ if (current.contentSignature !== input.expectedSignature) {
16479
+ throw new Error("Pi tail hygiene walk was not the last byte-affecting operation");
16480
+ }
16481
+ }
16482
+
16483
+ // src/ctx-reduce-nudge-pi.ts
16484
+ var channel1StateBySession = new Map;
16485
+ function setPiChannel1Baseline(sessionId, state2) {
16486
+ channel1StateBySession.set(sessionId, state2);
16487
+ }
16488
+ function getPiChannel1Baseline(sessionId) {
16489
+ return channel1StateBySession.get(sessionId);
16490
+ }
16491
+ function clearPiChannel1State(sessionId) {
16492
+ channel1StateBySession.delete(sessionId);
16493
+ }
16494
+ function markPiChannel1Reduced(sessionId, db) {
16495
+ const state2 = channel1StateBySession.get(sessionId);
16496
+ if (state2) {
16497
+ state2.reducedSinceRefresh = true;
16498
+ state2.evaluable = false;
16499
+ state2.generationInvalidated = true;
16500
+ }
16501
+ if (db)
16502
+ resetLastNudgeCycle(db, sessionId);
16503
+ }
16504
+ function isPiTextContent(c) {
16505
+ return c !== null && typeof c === "object" && c.type === "text" && typeof c.text === "string";
16506
+ }
16507
+ function toolResultText(content) {
16508
+ let text = "";
16509
+ for (const c of content) {
16510
+ if (isPiTextContent(c))
16511
+ text += c.text;
16512
+ }
16513
+ return text;
16514
+ }
16515
+ function maybeChannel1ReminderForToolResult(args) {
16516
+ const { db, sessionId, toolName } = args;
16517
+ const state2 = channel1StateBySession.get(sessionId);
16518
+ if (!state2)
16519
+ return null;
16520
+ if (toolName === "ctx_reduce") {
16521
+ state2.reducedSinceRefresh = true;
16522
+ state2.evaluable = false;
16523
+ state2.generationInvalidated = true;
16524
+ resetLastNudgeCycle(db, sessionId);
16525
+ return null;
16526
+ }
16527
+ const text = toolResultText(args.content);
16528
+ if (text.includes(CHANNEL1_SENTINEL))
16529
+ return null;
16530
+ const deltaTokens = measurePiToolResultDelta(args.content);
16531
+ if (deltaTokens === 0)
16532
+ return null;
16533
+ state2.turnDeltaT += deltaTokens;
16534
+ const decision = decideChannel1({
16535
+ ...state2,
16536
+ lastNudgeUndropped: getLastNudgeUndropped(db, sessionId),
16537
+ lastNudgeLevel: getLastNudgeLevel(db, sessionId),
16538
+ hasRecentReduce: state2.reducedSinceRefresh
16539
+ });
16540
+ setLastNudgeUndropped(db, sessionId, decision.nextLastNudge);
16541
+ setLastNudgeLevel(db, sessionId, decision.nextLastNudgeLevel);
16542
+ if (!decision.fire)
16543
+ return null;
16544
+ return {
16545
+ type: "text",
16546
+ text: buildChannel1Reminder(decision.level, decision.undroppedTokens, state2.oldestReclaimableToolTags)
16547
+ };
16548
+ }
16549
+ var CHANNEL2_NUDGE_CUSTOM_TYPE = "magic-context:ceiling-nudge";
16550
+ function maybeDeliverChannel2Pi(pi, db, sessionId) {
16551
+ let state2;
16552
+ try {
16553
+ state2 = getChannel2NudgeState(db, sessionId);
16554
+ } catch {
16555
+ return false;
16556
+ }
16557
+ if (state2 !== "pending")
16558
+ return false;
16559
+ const baseline = channel1StateBySession.get(sessionId);
16560
+ if (!baseline)
16561
+ return false;
16562
+ const evaluation = evaluateChannel2(baseline);
16563
+ if (!evaluation.evaluable)
16564
+ return false;
16565
+ if (!evaluation.shouldTrigger) {
16566
+ try {
16567
+ casChannel2NudgeState(db, sessionId, "pending", "");
16568
+ } catch {}
16569
+ return false;
16570
+ }
16571
+ const undropped = evaluation.reclaimableTokens;
16572
+ const claimToken = randomUUID2();
16573
+ if (!claimChannel2NudgeState(db, sessionId, claimToken))
16574
+ return false;
16575
+ try {
16576
+ const message = {
16577
+ customType: CHANNEL2_NUDGE_CUSTOM_TYPE,
16578
+ content: buildChannel2Reminder(undropped, baseline.oldestReclaimableToolTags),
16579
+ display: false,
16580
+ details: { kind: "channel-2-ceiling-nudge" }
16581
+ };
16582
+ const claim = getChannel2NudgeClaim(db, sessionId);
16583
+ if (claim.state !== "claimed" || claim.claimToken !== claimToken) {
16584
+ sessionLog(sessionId, `channel2 ceiling nudge delivery skipped: claim no longer owned before send (state=${claim.state || "empty"})`);
16585
+ return false;
16586
+ }
16587
+ pi.sendMessage(message, { deliverAs: "nextTurn" });
16588
+ } catch (error) {
16589
+ try {
16590
+ const restored = casChannel2NudgeClaim(db, sessionId, "pending", claimToken);
16591
+ if (restored) {
16592
+ sessionLog(sessionId, "channel2 ceiling nudge delivery failed (will retry):", error);
16593
+ } else {
16594
+ sessionLog(sessionId, "channel2 ceiling nudge delivery failed after its claim was no longer owned; lease state left unchanged:", error);
16595
+ }
16596
+ } catch (revertError) {
16597
+ sessionLog(sessionId, "channel2 ceiling nudge delivery failed; token-bound pending restore was busy so the stale claim will heal later:", { deliveryError: error, revertError });
16598
+ }
16599
+ return false;
16600
+ }
16601
+ try {
16602
+ const confirmed = casChannel2NudgeClaim(db, sessionId, "delivered", claimToken);
16603
+ if (confirmed) {
16604
+ sessionLog(sessionId, "channel2 ceiling nudge delivered");
16605
+ return true;
16606
+ }
16607
+ const claim = getChannel2NudgeClaim(db, sessionId);
16608
+ sessionLog(sessionId, `channel2 ceiling nudge sent but claim confirmation was not ours (state=${claim.state || "empty"}); leaving existing lease state unchanged`);
16609
+ return false;
16610
+ } catch (error) {
16611
+ sessionLog(sessionId, "channel2 ceiling nudge sent but token-confirm failed; lease state left unchanged:", error);
16612
+ return false;
16613
+ }
16614
+ }
16615
+
16616
+ // src/detect-recent-commit.ts
16617
+ var COMMIT_LOOKBACK = 5;
16618
+ function detectRecentCommit(messages) {
16619
+ let assistantsScanned = 0;
16620
+ for (let i = messages.length - 1;i >= 0; i--) {
16621
+ const message = messages[i];
16622
+ if (!message || typeof message !== "object" || !("role" in message) || message.role !== "assistant") {
16623
+ continue;
16624
+ }
16625
+ assistantsScanned++;
16626
+ if (assistantsScanned > COMMIT_LOOKBACK)
16627
+ break;
16628
+ if (!("content" in message))
16629
+ continue;
16630
+ const content = message.content;
16631
+ if (!Array.isArray(content))
16632
+ continue;
16633
+ for (const part of content) {
16634
+ if (part && typeof part === "object" && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string") {
16635
+ if (textMentionsRecentCommit(part.text)) {
16636
+ return true;
16637
+ }
16638
+ }
16639
+ }
16640
+ }
16641
+ return false;
16274
16642
  }
16275
16643
 
16276
16644
  // src/inject-compartments-pi.ts
@@ -16465,6 +16833,9 @@ var EMPTY_PI_HARD_SIGNALS = {
16465
16833
  function renderBudgetIdentityPi(state2) {
16466
16834
  return `m${state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS}-h${state2.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS}`;
16467
16835
  }
16836
+ function piMaterializeMismatch(reason, signal, cached, current) {
16837
+ return { value: true, reason, mismatch: { signal, cached, current } };
16838
+ }
16468
16839
  var injectionTokenCountsBySession = new Map;
16469
16840
  var cachedMuralBySession = new Map;
16470
16841
  function rememberPiMuralPayload(sessionId, dataUrl, contentHash) {
@@ -16637,38 +17008,41 @@ function mustMaterializePi(state2, db, currentCompartmentsOverride) {
16637
17008
  return { value: true, reason: "cache_invalid" };
16638
17009
  }
16639
17010
  if (cached.compartmentRenderEpoch !== current.compartmentRenderEpoch) {
16640
- return { value: true, reason: "compartment_render_epoch" };
17011
+ return piMaterializeMismatch("compartment_render_epoch", "compartmentRenderEpoch", cached.compartmentRenderEpoch, current.compartmentRenderEpoch);
16641
17012
  }
16642
- if (cached.muralEnabled !== current.muralEnabled || cached.renderBudgetIdentity !== current.renderBudgetIdentity) {
16643
- return { value: true, reason: "render_config" };
17013
+ if (cached.muralEnabled !== current.muralEnabled) {
17014
+ return piMaterializeMismatch("render_config", "muralEnabled", cached.muralEnabled, current.muralEnabled);
17015
+ }
17016
+ if (cached.renderBudgetIdentity !== current.renderBudgetIdentity) {
17017
+ return piMaterializeMismatch("render_config", "renderBudgetIdentity", cached.renderBudgetIdentity, current.renderBudgetIdentity);
16644
17018
  }
16645
17019
  const hard = state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS;
16646
17020
  const canonicalHardModelKey = piModelRefToCanonical(hard.modelKey);
16647
17021
  const canonicalCachedModelKey = piModelRefToCanonical(meta.cachedM0ModelKey ?? "");
16648
17022
  if (canonicalHardModelKey !== "" && canonicalHardModelKey !== canonicalCachedModelKey) {
16649
- return { value: true, reason: "model_change" };
17023
+ return piMaterializeMismatch("model_change", "modelKey", canonicalCachedModelKey, canonicalHardModelKey);
16650
17024
  }
16651
17025
  if (hard.systemHash !== "" && hard.systemHash !== (meta.cachedM0SystemHash ?? "")) {
16652
- return { value: true, reason: "system_hash" };
17026
+ return piMaterializeMismatch("system_hash", "systemHash", meta.cachedM0SystemHash ?? "", hard.systemHash);
16653
17027
  }
16654
17028
  if (meta.cachedM0ProjectIdentity !== null && meta.cachedM0ProjectIdentity !== state2.projectIdentity) {
16655
- return { value: true, reason: "project_change" };
17029
+ return piMaterializeMismatch("project_change", "projectIdentity", meta.cachedM0ProjectIdentity, state2.projectIdentity);
16656
17030
  }
16657
17031
  if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (meta.cachedM0MaterializedAt ?? 0)) {
16658
- return { value: true, reason: "ttl_idle" };
17032
+ return piMaterializeMismatch("ttl_idle", "lastResponseTimeAfterMaterialization", meta.cachedM0MaterializedAt ?? 0, hard.lastResponseTime);
16659
17033
  }
16660
17034
  if (cached.upgradeState !== current.upgradeState) {
16661
- return { value: true, reason: "renderer_upgrade" };
17035
+ return piMaterializeMismatch("renderer_upgrade", "upgradeState", cached.upgradeState, current.upgradeState);
16662
17036
  }
16663
17037
  if (current.workspaceFingerprint !== null || (meta.cachedM0WorkspaceFingerprint ?? null) !== null) {
16664
17038
  if (current.workspaceFingerprint !== (meta.cachedM0WorkspaceFingerprint ?? null)) {
16665
- return { value: true, reason: "project_memory_change" };
17039
+ return piMaterializeMismatch("project_memory_change", "workspaceFingerprint", meta.cachedM0WorkspaceFingerprint ?? null, current.workspaceFingerprint);
16666
17040
  }
16667
17041
  } else if (current.projectMemoryEpoch !== (meta.cachedM0ProjectMemoryEpoch ?? 0)) {
16668
- return { value: true, reason: "project_memory_change" };
17042
+ return piMaterializeMismatch("project_memory_change", "projectMemoryEpoch", meta.cachedM0ProjectMemoryEpoch ?? 0, current.projectMemoryEpoch);
16669
17043
  }
16670
17044
  if (current.maxMutationId !== (meta.cachedM0MaxMutationId ?? 0)) {
16671
- return { value: true, reason: "pending_mutations" };
17045
+ return piMaterializeMismatch("pending_mutations", "maxMutationId", meta.cachedM0MaxMutationId ?? 0, current.maxMutationId);
16672
17046
  }
16673
17047
  return { value: false, reason: null };
16674
17048
  }
@@ -17233,6 +17607,10 @@ function prependM0M1Messages(piMessages, m0, m1, mural) {
17233
17607
  function injectM0M1Pi(state2, db, piMessages, entryIds, recomputeM1ThisPass = false) {
17234
17608
  const currentCompartments = getRenderableCompartmentsPi(db, state2);
17235
17609
  let decision = mustMaterializePi(state2, db, currentCompartments);
17610
+ if (decision.value) {
17611
+ const mismatch = decision.mismatch ? ` mismatch=${JSON.stringify(decision.mismatch)}` : "";
17612
+ sessionLog(state2.sessionId, `pi m[0] HARD fold firing: reason=${decision.reason ?? "unknown"}${mismatch}`);
17613
+ }
17236
17614
  let m0 = "";
17237
17615
  let m1 = PI_M1_PLACEHOLDER;
17238
17616
  let markers = null;
@@ -17363,6 +17741,11 @@ function injectM0M1Pi(state2, db, piMessages, entryIds, recomputeM1ThisPass = fa
17363
17741
  m0 = stripMemoryMuralBlock(m0);
17364
17742
  prependM0M1Messages(piMessages, m0, m1, muralWire);
17365
17743
  sessionLog(state2.sessionId, `injected m[0]/m[1] into Pi messages (${m0.length} + ${m1.length} bytes, materialized=${materialized}${decision.reason ? ` reason=${decision.reason}` : ""})`);
17744
+ const comparison = decision.mismatch;
17745
+ const systemHashPrev = comparison?.signal === "systemHash" && typeof comparison.cached === "string" ? comparison.cached : null;
17746
+ const systemHashNew = comparison?.signal === "systemHash" && typeof comparison.current === "string" ? comparison.current : null;
17747
+ const m0ModelKeyPrev = comparison?.signal === "modelKey" && typeof comparison.cached === "string" ? comparison.cached : null;
17748
+ const m0ModelKeyNew = comparison?.signal === "modelKey" && typeof comparison.current === "string" ? comparison.current : null;
17366
17749
  const memPath = memoryProjectPath(state2);
17367
17750
  const workspace = resolveWorkspaceRenderContextPi(state2, db);
17368
17751
  const memoryCount = memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories).length : getMemoriesByProject(db, memPath, ["active", "permanent"]).length : 0;
@@ -17374,6 +17757,10 @@ function injectM0M1Pi(state2, db, piMessages, entryIds, recomputeM1ThisPass = fa
17374
17757
  skippedVisibleMessages,
17375
17758
  m0Materialized: materialized,
17376
17759
  m0Reason: decision.reason,
17760
+ systemHashPrev: materialized ? systemHashPrev : null,
17761
+ systemHashNew: materialized ? systemHashNew : null,
17762
+ m0ModelKeyPrev: materialized ? m0ModelKeyPrev : null,
17763
+ m0ModelKeyNew: materialized ? m0ModelKeyNew : null,
17377
17764
  m0Bytes: m0.length,
17378
17765
  m1Bytes: m1.length,
17379
17766
  contentionExhausted,
@@ -17445,16 +17832,17 @@ function resolvePiWindowGeometry(args) {
17445
17832
  return;
17446
17833
  const providerID = args.model?.provider ?? "unknown";
17447
17834
  const modelID = args.model?.id ?? "unknown";
17835
+ const outputReserveOverride = resolveOutputReserve(providerID, modelID, args.reserveConfig);
17448
17836
  const result = deriveWindowGeometry(providerID, modelID, {
17449
17837
  context,
17450
17838
  output: args.model?.maxTokens
17451
17839
  }, {
17452
17840
  overlay: resolveWindowOverlayFacts(providerID, modelID, getWindowOverlay()),
17453
17841
  contextCap: isSaneLimit2(args.detectedContextLimit) ? args.detectedContextLimit : undefined,
17454
- reserveConfig: args.reserveConfig,
17842
+ outputReserveOverride,
17455
17843
  harness: "pi"
17456
17844
  });
17457
- if (!result || !isSaneLimit2(persistedUsable))
17845
+ if (!result || outputReserveOverride !== undefined || !isSaneLimit2(persistedUsable))
17458
17846
  return result;
17459
17847
  const usableSoft = Math.round(persistedUsable);
17460
17848
  return {
@@ -20528,7 +20916,7 @@ function buildReferenceBlocks(args) {
20528
20916
 
20529
20917
  // src/pi-historian-runner.ts
20530
20918
  var HISTORIAN_AGENT_NAME = "magic-context-historian";
20531
- var DEFAULT_HISTORIAN_TIMEOUT_MS2 = 120000;
20919
+ var DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
20532
20920
  var MAX_HISTORIAN_RETRIES = 2;
20533
20921
  var HISTORIAN_ALERT_COOLDOWN_MS = 60 * 1000;
20534
20922
  var lastHistorianAlertBySession = new Map;
@@ -22011,6 +22399,11 @@ function buildMagicContextBlock(opts) {
22011
22399
  return null;
22012
22400
  return buildMagicContextSection(null, opts.protectedTags ?? 20, opts.ctxReduceCallable ?? true, opts.dreamerEnabled ?? false, opts.temporalAwarenessEnabled ?? false, opts.cavemanTextCompressionEnabled ?? false, false, opts.language, opts.memoryEnabled !== false, opts.promptSurfacePreset, opts.primaryGuidanceOverride);
22013
22401
  }
22402
+ function composeMagicContextSystemPrompt(basePrompt, block) {
22403
+ return block ? `${basePrompt}
22404
+
22405
+ ${block}` : basePrompt;
22406
+ }
22014
22407
  var DATE_PATTERN = /Today's date: .+/;
22015
22408
  function processSystemPromptForCache(args) {
22016
22409
  const { db, sessionId, systemPrompt, isCacheBusting } = args;
@@ -22891,6 +23284,7 @@ var injectM0M1PiForRun = injectM0M1Pi;
22891
23284
  var persistReasoningWatermarkForRun = updateSessionMeta;
22892
23285
  var persistStableIdSchemeForRun = updateSessionMeta;
22893
23286
  var afterFallbackAdoptionForTests;
23287
+ var mutationGateObserverForTests;
22894
23288
  var DEFAULT_CLEAR_REASONING_AGE = 50;
22895
23289
  var PI_STABLE_ID_SCHEME = 1;
22896
23290
  var lastEmergencyNotificationAtMs = new Map;
@@ -23986,6 +24380,10 @@ function registerPiContextHandler(pi, baseOptions) {
23986
24380
  decision: schedulerDecision,
23987
24381
  materialized: result.materialized,
23988
24382
  materializeReason: normalizeMaterializeReason("pi", result.materializeReason, result.materialized),
24383
+ systemHashPrev: result.materialized ? result.injectionResult?.systemHashPrev ?? null : null,
24384
+ systemHashNew: result.materialized ? result.injectionResult?.systemHashNew ?? null : null,
24385
+ m0ModelKeyPrev: result.materialized ? result.injectionResult?.m0ModelKeyPrev ?? null : null,
24386
+ m0ModelKeyNew: result.materialized ? result.injectionResult?.m0ModelKeyNew ?? null : null,
23989
24387
  emergency: result.emergency,
23990
24388
  droppedTokens: result.droppedTokens,
23991
24389
  droppedCount: result.droppedCount,
@@ -24011,6 +24409,7 @@ function registerPiContextHandler(pi, baseOptions) {
24011
24409
  logTransformTiming(sessionId, "historianScheduling", tHistorianScheduling);
24012
24410
  const tPostTransform = performance.now();
24013
24411
  let outputMessages = result.messages;
24412
+ let assertTailHygieneLastWriter;
24014
24413
  const tNoteNudges = performance.now();
24015
24414
  try {
24016
24415
  if (!options.compactionOff) {
@@ -24074,60 +24473,61 @@ function registerPiContextHandler(pi, baseOptions) {
24074
24473
  try {
24075
24474
  const sessionMetaForCh1 = getOrCreateSessionMeta(options.db, sessionId);
24076
24475
  if (!options.compactionOff && !sessionMetaForCh1.isSubagent) {
24077
- const resolvedExecuteThresholdPct = resolveExecuteThreshold(schedulerConfig.executeThresholdPercentage ?? 65, liveModelBySession.get(sessionId), 65, {
24078
- tokensConfig: schedulerConfig.executeThresholdTokens,
24079
- contextLimit: usageContextLimit ?? 0
24080
- });
24081
- const historyBudgetTokens = resolveHistoryBudgetTokensForPi({
24082
- historyBudgetPercentage: options.historian?.historyBudgetPercentage,
24083
- usagePercentage,
24084
- usageInputTokens,
24085
- usageContextLimit,
24086
- executeThresholdPercentage: schedulerConfig.executeThresholdPercentage,
24087
- executeThresholdTokens: schedulerConfig.executeThresholdTokens,
24088
- modelKey: liveModelBySession.get(sessionId)
24476
+ const tags = getTagsBySession(options.db, sessionId);
24477
+ const protectedTags = options.protectedTags ?? 20;
24478
+ const stableId = (message) => message && typeof message === "object" ? result.postCommitEntryIdByRef.get(message) : undefined;
24479
+ const baseline = refreshPiTailHygieneBaseline({
24480
+ messages: outputMessages,
24481
+ tags,
24482
+ protectedTags,
24483
+ stableId,
24484
+ syntheticLeadingCount: result.syntheticLeadingCount,
24485
+ cacheBusting: result.bustedThisPass,
24486
+ previous: getPiChannel1Baseline(sessionId)
24089
24487
  });
24090
- let tailToolTokens;
24091
- let liveTailTokens;
24092
- try {
24093
- const agg = getActiveTagTokenAggregate(options.db, sessionId, options.protectedTags ?? 20);
24094
- tailToolTokens = agg.toolOutput;
24095
- liveTailTokens = agg.conversation + agg.toolCall;
24096
- } catch {
24097
- const estimate = computeTailTokenEstimatePi(outputMessages);
24098
- tailToolTokens = estimate.tailToolTokens;
24099
- liveTailTokens = estimate.liveTailTokens;
24100
- }
24101
- const executeThresholdTokensPi = Math.round((usageContextLimit ?? 0) * resolvedExecuteThresholdPct / 100);
24102
- const usableTokensPi = Math.max(0, executeThresholdTokensPi - usageInputTokens + liveTailTokens);
24103
- resetLastNudgeCycleIfTailShrank(options.db, sessionId, tailToolTokens);
24104
- const oldestReclaimableToolTags = getOldestActiveUnprotectedToolTags(options.db, sessionId, options.protectedTags ?? 20);
24105
- setPiChannel1Baseline(sessionId, {
24106
- tailToolTokens,
24107
- historyBudgetTokens: historyBudgetTokens ?? 0,
24108
- contextLimit: usageContextLimit ?? 0,
24109
- executeThresholdPercentage: resolvedExecuteThresholdPct,
24110
- lastInputTokens: usageInputTokens,
24111
- turnToolTokens: 0,
24112
- usableTokens: usableTokensPi,
24488
+ const effective = effectivePiTailHygiene(baseline);
24489
+ resetLastNudgeCycleIfTailShrank(options.db, sessionId, effective.u);
24490
+ const oldestReclaimableToolTags = getOldestActiveUnprotectedToolTags(options.db, sessionId, protectedTags);
24491
+ const channelState = {
24492
+ ...baseline,
24113
24493
  reducedSinceRefresh: false,
24114
24494
  oldestReclaimableToolTags
24115
- });
24116
- if (usageContextLimit && usageContextLimit > 0 && resolvedExecuteThresholdPct > 0) {
24117
- const channel2ShouldTrigger = shouldTriggerChannel2({
24118
- reclaimableTokens: tailToolTokens,
24119
- usableTokens: usableTokensPi
24120
- });
24121
- if (channel2ShouldTrigger) {
24495
+ };
24496
+ setPiChannel1Baseline(sessionId, channelState);
24497
+ const channel2Evaluation = evaluateChannel2(channelState);
24498
+ if (channel2Evaluation.evaluable) {
24499
+ try {
24500
+ rearmChannel2AfterMeasuredCollapse({
24501
+ db: options.db,
24502
+ sessionId,
24503
+ baseline: channelState
24504
+ });
24505
+ } catch (error) {
24506
+ sessionLog(sessionId, `pi channel2 U-collapse reset failed: ${error instanceof Error ? error.message : String(error)}`);
24507
+ }
24508
+ if (channel2Evaluation.shouldTrigger) {
24122
24509
  casChannel2NudgeState(options.db, sessionId, "", "pending");
24123
24510
  } else {
24124
24511
  casChannel2NudgeState(options.db, sessionId, "pending", "");
24125
24512
  }
24126
24513
  }
24514
+ assertTailHygieneLastWriter = () => assertPiTailHygieneContentUnchanged({
24515
+ messages: outputMessages,
24516
+ tags,
24517
+ protectedTags,
24518
+ stableId,
24519
+ syntheticLeadingCount: result.syntheticLeadingCount,
24520
+ expectedSignature: baseline.contentSignature
24521
+ });
24127
24522
  } else {
24128
24523
  clearPiChannel1State(sessionId);
24129
24524
  }
24130
24525
  } catch (err) {
24526
+ const stale = getPiChannel1Baseline(sessionId);
24527
+ if (stale) {
24528
+ stale.evaluable = false;
24529
+ stale.generationInvalidated = true;
24530
+ }
24131
24531
  sessionLog(sessionId, `channel1 baseline / channel2 trigger failed: ${err instanceof Error ? err.message : String(err)}`);
24132
24532
  }
24133
24533
  logTransformTiming(sessionId, "channelNudgeAccounting", tChannelAccounting);
@@ -24163,6 +24563,9 @@ function registerPiContextHandler(pi, baseOptions) {
24163
24563
  extra: `messages=${outputMessages.length} targets=${result.targetCount}`
24164
24564
  });
24165
24565
  sessionLog(sessionId, `transform completed in ${transformElapsedMs.toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
24566
+ if (assertTailHygieneLastWriter && true) {
24567
+ assertTailHygieneLastWriter();
24568
+ }
24166
24569
  return { messages: outputMessages };
24167
24570
  } catch (err) {
24168
24571
  if (isFailClosedBlockingError(err) && !baseOptions.compactionOff)
@@ -24704,19 +25107,49 @@ async function runPipeline(args) {
24704
25107
  lastResponseTime: hardMeta.lastResponseTime
24705
25108
  };
24706
25109
  })() : undefined;
24707
- const m0HardFoldThisPass = args.injection && piHardSignals ? mustMaterializePi({
25110
+ const piM0State = args.injection && piHardSignals ? {
24708
25111
  sessionId: args.sessionId,
24709
25112
  projectIdentity: args.projectIdentity,
24710
25113
  projectDirectory: args.projectDirectory,
24711
25114
  memoryEnabled: args.injection.memoryEnabled,
25115
+ injectDocs: args.injection.injectDocs,
24712
25116
  injectionBudgetTokens: args.injection.injectionBudgetTokens,
24713
25117
  historyBudgetTokens: args.injection.historyBudgetTokens,
24714
- hardSignals: piHardSignals
24715
- }, args.db, getCompartments(args.db, args.sessionId)).value : false;
25118
+ hardSignals: piHardSignals,
25119
+ muralEnabled: args.injection.muralEnabled === true
25120
+ } : undefined;
25121
+ const foldDueDecision = piM0State ? mustMaterializePi(piM0State, args.db, getCompartments(args.db, args.sessionId)) : { value: false, reason: null };
25122
+ let foldExecutedThisPass = false;
25123
+ let preFoldInjectionResult = null;
25124
+ const persistedM0BeforeFold = getOrCreateSessionMeta(args.db, args.sessionId);
25125
+ const m0CoverageBeforeFold = persistedM0BeforeFold.cachedM0Bytes === null ? -1 : persistedM0BeforeFold.cachedM0MaxCompartmentSeq;
25126
+ if (foldDueDecision.value && piM0State) {
25127
+ try {
25128
+ preFoldInjectionResult = injectM0M1PiForRun(piM0State, args.db, [], undefined, false);
25129
+ foldExecutedThisPass = foldExecutesThisPass(foldDueDecision.value, preFoldInjectionResult.m0Materialized === true);
25130
+ const m0CoverageAfterFold = getOrCreateSessionMeta(args.db, args.sessionId).cachedM0MaxCompartmentSeq;
25131
+ try {
25132
+ rearmChannel2AfterCoverageAdvancingHardFold({
25133
+ db: args.db,
25134
+ sessionId: args.sessionId,
25135
+ foldExecuted: foldExecutedThisPass,
25136
+ compactionOff: false,
25137
+ previousCoverage: m0CoverageBeforeFold,
25138
+ currentCoverage: m0CoverageAfterFold
25139
+ });
25140
+ } catch (error) {
25141
+ sessionLog(args.sessionId, `pi channel2 fold-cycle reset failed: ${error instanceof Error ? error.message : String(error)}`);
25142
+ }
25143
+ } catch (error) {
25144
+ sessionLog(args.sessionId, `pi m[0] HARD fold pre-execution failed: ${error instanceof Error ? error.message : String(error)}`);
25145
+ }
25146
+ const mismatch = foldDueDecision.mismatch ? ` mismatch=${JSON.stringify(foldDueDecision.mismatch)}` : "";
25147
+ sessionLog(args.sessionId, `pi m[0] HARD fold decision: reason=${foldDueDecision.reason ?? "unknown"}${mismatch} executed=${foldExecutedThisPass}`);
25148
+ }
24716
25149
  const historianRunning = inFlightHistorian.has(args.sessionId);
24717
- const bypassHistorianGate = args.forceMaterialization === true || m0HardFoldThisPass;
25150
+ const bypassHistorianGate = args.forceMaterialization === true || foldExecutedThisPass;
24718
25151
  const hasPendingMaterializeSignal = hasPendingMaterialization(args.sessionId);
24719
- const shouldRunHeuristics = args.heuristics !== undefined && (!historianRunning || bypassHistorianGate) && (args.forceMaterialization === true || hasPendingMaterializeSignal || deferredMaterializeEligible || m0HardFoldThisPass || args.schedulerDecision === "execute" && !alreadyRanHeuristicsThisTurn);
25152
+ const shouldRunHeuristics = args.heuristics !== undefined && (!historianRunning || bypassHistorianGate) && (args.forceMaterialization === true || hasPendingMaterializeSignal || deferredMaterializeEligible || foldExecutedThisPass || args.schedulerDecision === "execute" && !alreadyRanHeuristicsThisTurn);
24720
25153
  const tFallbackIdentity = performance.now();
24721
25154
  const hasFallbackMessageTags = hasPiFallbackMessageTags(args.db, args.sessionId);
24722
25155
  const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, hasFallbackMessageTags);
@@ -24771,15 +25204,22 @@ async function runPipeline(args) {
24771
25204
  }
24772
25205
  const deferredMaterializationWasPending = deferredMaterializationSessions.has(args.sessionId);
24773
25206
  const deferredHistoryRefreshWasPending = deferredHistoryWasPendingAtPassStart;
24774
- const shouldReadPendingOps = !args.compactionOff && (args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || m0HardFoldThisPass || historianRunning);
25207
+ const shouldReadPendingOps = !args.compactionOff && (args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || foldExecutedThisPass || historianRunning);
24775
25208
  const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
24776
25209
  const pendingOperationTags = pendingOps.length > 0 ? getTagsForPendingOperations(args.db, args.sessionId, pendingOps.map((operation) => operation.tagId), args.protectedTags, RECENT_TOOL_SKELETON_WINDOW) : [];
24777
- const baseShouldApplyPendingOps = args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || m0HardFoldThisPass;
25210
+ const baseShouldApplyPendingOps = args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || foldExecutedThisPass;
24778
25211
  const deferredMaterialize = canConsumeDeferredLate && deferredMaterializationWasPending;
24779
25212
  const deferredHistoryRefresh = canConsumeDeferredLate && deferredHistoryRefreshWasPending;
24780
25213
  const shouldApplyPendingOps = (baseShouldApplyPendingOps || deferredMaterialize) && (!historianRunning || bypassHistorianGate);
25214
+ mutationGateObserverForTests?.({
25215
+ foldDue: foldDueDecision.value,
25216
+ foldExecuted: foldExecutedThisPass,
25217
+ shouldApplyPendingOps,
25218
+ shouldRunHeuristics,
25219
+ shouldRunReasoningCleanup: args.reasoningClearing !== undefined && shouldRunHeuristics
25220
+ });
24781
25221
  if (shouldApplyPendingOps) {
24782
- const applyReason = hasPendingMaterializeSignal ? "explicit_flush" : deferredMaterialize ? "deferred_publication" : args.forceMaterialization ? "force_materialization" : m0HardFoldThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into known m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (scheduler=${args.schedulerDecision})`;
25222
+ const applyReason = hasPendingMaterializeSignal ? "explicit_flush" : deferredMaterialize ? "deferred_publication" : args.forceMaterialization ? "force_materialization" : foldExecutedThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (scheduler=${args.schedulerDecision})`;
24783
25223
  sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
24784
25224
  try {
24785
25225
  const tApplyPending = performance.now();
@@ -24857,7 +25297,7 @@ async function runPipeline(args) {
24857
25297
  const activeTags = getActiveTagsBySession(args.db, args.sessionId);
24858
25298
  logTransformTiming(args.sessionId, "getActiveTagsBySession", tActiveTags, `count=${activeTags.length}`);
24859
25299
  if (shouldRunHeuristics) {
24860
- const reason = args.forceMaterialization ? "force_materialization" : m0HardFoldThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into known m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
25300
+ const reason = args.forceMaterialization ? "force_materialization" : foldExecutedThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
24861
25301
  sessionLog(args.sessionId, `heuristics WILL RUN — reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=n/a`);
24862
25302
  } else {
24863
25303
  const reason = args.heuristics === undefined ? "disabled" : "scheduler_defer";
@@ -25041,17 +25481,16 @@ async function runPipeline(args) {
25041
25481
  if (args.injection) {
25042
25482
  try {
25043
25483
  const tInjection = performance.now();
25044
- injectionResult = injectM0M1PiForRun({
25045
- sessionId: args.sessionId,
25046
- projectIdentity: args.projectIdentity,
25047
- projectDirectory: args.projectDirectory,
25048
- memoryEnabled: args.injection.memoryEnabled,
25049
- injectDocs: args.injection.injectDocs,
25050
- injectionBudgetTokens: args.injection.injectionBudgetTokens,
25051
- historyBudgetTokens: args.injection.historyBudgetTokens,
25052
- hardSignals: piHardSignals,
25053
- muralEnabled: args.injection.muralEnabled === true
25054
- }, args.db, args.messages, args.entryIds, args.isCacheBusting || deferredHistoryRefresh || executedWorkThisPass);
25484
+ const wireInjectionResult = injectM0M1PiForRun(piM0State, args.db, args.messages, args.entryIds, args.isCacheBusting || deferredHistoryRefresh || executedWorkThisPass);
25485
+ injectionResult = preFoldInjectionResult?.m0Materialized ? {
25486
+ ...wireInjectionResult,
25487
+ m0Materialized: true,
25488
+ m0Reason: preFoldInjectionResult.m0Reason ?? wireInjectionResult.m0Reason,
25489
+ systemHashPrev: preFoldInjectionResult.systemHashPrev ?? null,
25490
+ systemHashNew: preFoldInjectionResult.systemHashNew ?? null,
25491
+ m0ModelKeyPrev: preFoldInjectionResult.m0ModelKeyPrev ?? null,
25492
+ m0ModelKeyNew: preFoldInjectionResult.m0ModelKeyNew ?? null
25493
+ } : wireInjectionResult;
25055
25494
  if (args.temporalAwareness && injectionResult.skippedVisibleMessages > 0) {
25056
25495
  const firstRetainedMessage = args.messages[injectionResult.syntheticLeadingCount];
25057
25496
  stripPiLeadingTemporalMarker(firstRetainedMessage);
@@ -25676,12 +26115,9 @@ async function runHistorianPrompt(args) {
25676
26115
  error: `Historian failed while processing this session: ${desc.brief}`
25677
26116
  };
25678
26117
  } finally {
25679
- if (agentSessionId && outcomeOk && !shouldKeepSubagents()) {
25680
- await client.session.delete({ path: { id: agentSessionId } }).catch((e) => {
25681
- sessionLog(parentSessionId, "compartment agent: session cleanup failed", getErrorMessage(e));
25682
- });
25683
- } else if (agentSessionId && (!outcomeOk || shouldKeepSubagents())) {
25684
- sessionLog(parentSessionId, `historian: KEEPING child session ${agentSessionId} (${outcomeOk ? "keep_subagents" : "failed"}) — not deleted`);
26118
+ if (agentSessionId) {
26119
+ const retentionReason = shouldKeepSubagents() ? "keep_subagents" : outcomeOk ? "prompt completed; cleanup deferred to the age-gated sweep" : "failed; cleanup deferred to the age-gated sweep";
26120
+ sessionLog(parentSessionId, `historian: KEEPING child session ${agentSessionId} (${retentionReason}) — not deleted inline`);
25685
26121
  }
25686
26122
  }
25687
26123
  }
@@ -26794,9 +27230,19 @@ function updateStatusLine(ctx, deps, force = false) {
26794
27230
  }
26795
27231
  function renderStatusText(ctx, db, sessionId) {
26796
27232
  const usage = ctx.getContextUsage?.();
26797
- const inputTokens = typeof usage?.tokens === "number" ? usage.tokens : undefined;
26798
- const pct = typeof usage?.percent === "number" ? usage.percent : undefined;
26799
27233
  const meta = readSessionMetaStatus(db, sessionId);
27234
+ const liveInputTokens = typeof usage?.tokens === "number" && Number.isFinite(usage.tokens) ? usage.tokens : undefined;
27235
+ const persistedInputTokens = typeof meta?.last_input_tokens === "number" && Number.isFinite(meta.last_input_tokens) && meta.last_input_tokens >= 0 ? meta.last_input_tokens : undefined;
27236
+ const inputTokens = liveInputTokens ?? persistedInputTokens;
27237
+ const windowGeometry = resolvePiWindowGeometry({
27238
+ rawContextWindow: usage?.contextWindow ?? ctx.model?.contextWindow,
27239
+ model: ctx.model,
27240
+ detectedContextLimit: typeof meta?.detected_context_limit === "number" && meta.detected_context_limit > 0 ? meta.detected_context_limit : undefined,
27241
+ persistedInputTokens,
27242
+ persistedPercentage: typeof meta?.last_context_percentage === "number" ? meta.last_context_percentage : undefined
27243
+ });
27244
+ const usableSoft = windowGeometry?.usableSoft;
27245
+ const pct = inputTokens !== undefined && usableSoft !== undefined && usableSoft > 0 ? inputTokens / usableSoft * 100 : typeof meta?.last_context_percentage === "number" ? meta.last_context_percentage : undefined;
26800
27246
  const state2 = renderHistorianState(meta, recompSessions.has(sessionId));
26801
27247
  return `mc: ${inputTokens === undefined ? "--" : fmt(inputTokens)} (${pct === undefined ? "--" : `${Math.round(pct)}%`}) · ${state2}`;
26802
27248
  }
@@ -26816,7 +27262,10 @@ function renderHistorianState(meta, recompActive) {
26816
27262
  }
26817
27263
  function readSessionMetaStatus(db, sessionId) {
26818
27264
  try {
26819
- return db.prepare("SELECT compartment_in_progress, historian_failure_count, historian_last_failure_at FROM session_meta WHERE session_id = ?").get(sessionId);
27265
+ return db.prepare(`SELECT compartment_in_progress, historian_failure_count,
27266
+ historian_last_failure_at, last_input_tokens,
27267
+ last_context_percentage, detected_context_limit
27268
+ FROM session_meta WHERE session_id = ?`).get(sessionId);
26820
27269
  } catch {
26821
27270
  return;
26822
27271
  }
@@ -27597,6 +28046,44 @@ function formatThresholdClampNote(opts) {
27597
28046
  return ` [clamped: ${opts.configuredValue}% > ${opts.maxPercentage}%]`;
27598
28047
  }
27599
28048
 
28049
+ // ../plugin/src/shared/tail-hygiene-status.ts
28050
+ function finiteNumber(value, fallback = 0) {
28051
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
28052
+ }
28053
+ function resolveTailHygieneStatus(tsBaseline, rustBaseline) {
28054
+ if (rustBaseline !== undefined && rustBaseline !== null) {
28055
+ const t2 = Math.max(0, finiteNumber(rustBaseline.t));
28056
+ const u2 = Math.min(t2, Math.max(0, finiteNumber(rustBaseline.u)));
28057
+ return {
28058
+ u: u2,
28059
+ t: t2,
28060
+ severity: Math.min(1, Math.max(0, finiteNumber(rustBaseline.severity, u2 / Math.max(t2, 1)))),
28061
+ evaluable: rustBaseline.evaluable === true,
28062
+ generationInvalidated: rustBaseline.generation_invalidated === true,
28063
+ baselineGeneration: Math.max(0, finiteNumber(rustBaseline.baseline_generation)),
28064
+ computedAt: Math.max(0, finiteNumber(rustBaseline.computed_at_ms))
28065
+ };
28066
+ }
28067
+ if (tsBaseline === undefined)
28068
+ return;
28069
+ const t = Math.max(0, tsBaseline.baselineT + tsBaseline.turnDeltaT);
28070
+ const u = Math.min(t, Math.max(0, tsBaseline.baselineU + tsBaseline.turnDeltaU));
28071
+ return {
28072
+ u,
28073
+ t,
28074
+ severity: Math.min(1, Math.max(0, u / Math.max(t, 1))),
28075
+ evaluable: tsBaseline.evaluable && !tsBaseline.generationInvalidated,
28076
+ generationInvalidated: tsBaseline.generationInvalidated,
28077
+ baselineGeneration: Math.max(0, tsBaseline.baselineGeneration),
28078
+ computedAt: Math.max(0, tsBaseline.computedAt)
28079
+ };
28080
+ }
28081
+ function formatTailHygiene(status) {
28082
+ const percentage = (status.severity * 100).toFixed(1);
28083
+ const state2 = status.evaluable ? "" : " · held until baseline refresh";
28084
+ return `${percentage}% · ${status.u.toLocaleString()} / ${status.t.toLocaleString()} tok${state2}`;
28085
+ }
28086
+
27600
28087
  // ../plugin/src/shared/format-bytes.ts
27601
28088
  function formatBytes(bytes) {
27602
28089
  if (bytes < 1024)
@@ -27625,7 +28112,7 @@ function formatExecuteThreshold(detail, contextLimit) {
27625
28112
  }
27626
28113
  return `${percentage}%${clampNote}`;
27627
28114
  }
27628
- function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageConfig = DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, liveModelKey, historyBudgetPercentage, commitClusterTrigger, executeThresholdTokens, contextLimit, dreamer, windowGeometry) {
28115
+ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageConfig = DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, liveModelKey, historyBudgetPercentage, commitClusterTrigger, executeThresholdTokens, contextLimit, dreamer, windowGeometry, tailHygiene) {
27629
28116
  const thresholdDetail = resolveExecuteThresholdDetail(executeThresholdPercentageConfig, liveModelKey, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, {
27630
28117
  tokensConfig: executeThresholdTokens,
27631
28118
  contextLimit,
@@ -27670,7 +28157,7 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
27670
28157
  "### Cache TTL",
27671
28158
  `- Configured: ${meta.cacheTtl}`,
27672
28159
  `- Last response: ${meta.lastResponseTime > 0 ? `${Math.round(elapsed / 1000)}s ago` : "never"}`,
27673
- `- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never expires (always-warm lane)" : `${Math.round(remainingMs / 1000)}s`}`,
28160
+ `- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never (MC never assumes expiry — external cache-keep)" : `${Math.round(remainingMs / 1000)}s`}`,
27674
28161
  `- Queue will auto-execute: ${cacheExpired ? "yes (cache expired)" : ttlMs === Number.POSITIVE_INFINITY ? `when context >= ${executeThresholdPercentage}%` : `when TTL expires or context >= ${executeThresholdPercentage}%`}`,
27675
28162
  "",
27676
28163
  "### Execute Threshold",
@@ -27680,6 +28167,9 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
27680
28167
  `**Protected tags:** ${protectedTags}`,
27681
28168
  `**Subagent session:** ${meta.isSubagent}`
27682
28169
  ];
28170
+ if (tailHygiene !== undefined) {
28171
+ lines.push("", "### Tail Hygiene", `- Reclaimable / eligible: ${formatTailHygiene(tailHygiene)}`, "- Reasoning is excluded from both terms.");
28172
+ }
27683
28173
  if (dreamer?.backlog && Object.keys(dreamer.backlog).length > 0) {
27684
28174
  lines.push("", "### Dreamer", ...dreamer.progress ? [
27685
28175
  `- Running: ${dreamer.progress.task} — ${dreamer.progress.processed}/${dreamer.progress.total} processed`
@@ -27787,7 +28277,7 @@ ${c.content}
27787
28277
  // package.json
27788
28278
  var package_default = {
27789
28279
  name: "@cortexkit/pi-magic-context",
27790
- version: "0.37.0",
28280
+ version: "0.38.1",
27791
28281
  type: "module",
27792
28282
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
27793
28283
  main: "dist/index.js",
@@ -27838,8 +28328,9 @@ var package_default = {
27838
28328
  },
27839
28329
  devDependencies: {
27840
28330
  "@biomejs/biome": "^2.5.1",
27841
- "@earendil-works/pi-coding-agent": "^0.80.2",
27842
- "@earendil-works/pi-tui": "^0.80.2",
28331
+ "@earendil-works/pi-ai": "0.83.0",
28332
+ "@earendil-works/pi-coding-agent": "0.83.0",
28333
+ "@earendil-works/pi-tui": "0.83.0",
27843
28334
  "@types/better-sqlite3": "^7.6.13",
27844
28335
  "@types/bun": "^1.3.10",
27845
28336
  "@types/node": "^22.20.0",
@@ -27956,9 +28447,12 @@ function renderInner(s, theme, innerWidth) {
27956
28447
  lines.push("");
27957
28448
  lines.push(`Context ${theme.fg(pctColor, theme.bold(`${s.usagePercentage.toFixed(1)}%`))} · ${fmt2(s.inputTokens)} / ${s.contextLimit > 0 ? fmt2(s.contextLimit) : "?"} tokens`);
27958
28449
  if (s.windowGeometry) {
27959
- lines.push(formatWindowDerivationLine(s.inputTokens, s.windowGeometry));
28450
+ lines.push(formatWindowDerivationLine(s.inputTokens, s.windowGeometry).replace(/^Context:.* — window /, "Window "));
27960
28451
  }
27961
28452
  lines.push(`Work tokens ${fmt2(s.newWorkTokens)} new · ${fmt2(s.totalInputTokens)} total input`);
28453
+ if (s.tailHygiene !== undefined) {
28454
+ lines.push(`Hygiene ${formatTailHygiene(s.tailHygiene)}`);
28455
+ }
27962
28456
  lines.push(renderBar(s, innerWidth));
27963
28457
  for (const seg of breakdownSegments(s)) {
27964
28458
  const pct = (seg.tokens / (s.inputTokens || 1) * 100).toFixed(1);
@@ -27966,6 +28460,7 @@ function renderInner(s, theme, innerWidth) {
27966
28460
  const right = theme.fg("muted", `${fmt2(seg.tokens)} (${pct}%)`);
27967
28461
  lines.push(`${left} ${right}`);
27968
28462
  }
28463
+ lines.push("* Conversation includes model Reasoning; hygiene excludes it.");
27969
28464
  lines.push("");
27970
28465
  lines.push(`Counts: ${s.compartmentCount} compartments · ${s.memoryCount} memories (${s.memoryBlockCount} injected) · ${s.sessionNoteCount + s.readySmartNoteCount} notes`);
27971
28466
  lines.push(`Historian: ${s.historianRunning ? theme.fg("warning", "running") : theme.fg("accent", "idle")}${s.historianFailureCount > 0 ? ` · ${theme.fg("error", `last failure ${s.historianLastFailureAt ? relTime(s.historianLastFailureAt) : "unknown"}`)}` : ""}`);
@@ -27977,7 +28472,7 @@ function renderInner(s, theme, innerWidth) {
27977
28472
  lines.push(`Upgrade: ${theme.fg("accent", "up to date")}`);
27978
28473
  }
27979
28474
  lines.push(`Pending drops: ${s.pendingOpsCount}`);
27980
- lines.push(`Cache TTL: ${s.cacheTtl} · last response ${s.lastResponseTime > 0 ? `${Math.round((Date.now() - s.lastResponseTime) / 1000)}s ago` : "never"} · ${s.cacheExpired ? theme.fg("warning", "expired") : s.cacheRemainingMs === Number.POSITIVE_INFINITY ? "never expires (always-warm lane)" : `${Math.round(s.cacheRemainingMs / 1000)}s remaining`}`);
28475
+ lines.push(`Cache TTL: ${s.cacheTtl} · last response ${s.lastResponseTime > 0 ? `${Math.round((Date.now() - s.lastResponseTime) / 1000)}s ago` : "never"} · ${s.cacheExpired ? theme.fg("warning", "expired") : s.cacheRemainingMs === Number.POSITIVE_INFINITY ? "never (MC never assumes expiry — external cache-keep)" : `${Math.round(s.cacheRemainingMs / 1000)}s remaining`}`);
27981
28476
  lines.push("");
27982
28477
  lines.push(theme.fg("muted", "Tags"));
27983
28478
  lines.push(`Active ${s.activeTags} (~${formatBytes(s.activeBytes)}) · Dropped ${s.droppedTags} · Total ${s.totalTags}`);
@@ -28075,6 +28570,7 @@ ${safeStringify(tool.parameters)}`);
28075
28570
  } catch {}
28076
28571
  const conversationTokens = Math.max(0, inputTokens - systemPromptTokens - compartmentTokens - factTokens - memoryTokens - docsTokens - profileTokens - toolCallTokens - toolDefinitionTokens);
28077
28572
  const workMetrics = getSessionWorkMetrics(deps.db, sessionId);
28573
+ const tailHygiene = resolveTailHygieneStatus(getPiChannel1Baseline(sessionId));
28078
28574
  const modelKey = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
28079
28575
  const threshold = resolveExecuteThresholdDetail(deps.executeThresholdPercentage ?? 65, modelKey, 65, {
28080
28576
  tokensConfig: deps.executeThresholdTokens,
@@ -28148,6 +28644,7 @@ ${safeStringify(tool.parameters)}`);
28148
28644
  conversationTokens,
28149
28645
  toolCallTokens,
28150
28646
  toolDefinitionTokens,
28647
+ ...tailHygiene === undefined ? {} : { tailHygiene },
28151
28648
  newWorkTokens: workMetrics.newWorkTokens,
28152
28649
  totalInputTokens: workMetrics.totalInputTokens,
28153
28650
  upgradeNeededCount: safeRead(() => countCompartmentsNeedingUpgrade(deps.db, sessionId), 0),
@@ -28195,7 +28692,7 @@ function breakdownSegments(s) {
28195
28692
  });
28196
28693
  if (s.conversationTokens > 0)
28197
28694
  segs.push({
28198
- label: "Conversation",
28695
+ label: "Conversation*",
28199
28696
  tokens: s.conversationTokens,
28200
28697
  color: COLORS.conversation
28201
28698
  });
@@ -28326,7 +28823,7 @@ No active Pi session is available.`,
28326
28823
  const usableContextLimit = windowGeometry?.usableSoft;
28327
28824
  const statusText = executeStatus(currentDeps.db, sessionId, currentDeps.protectedTags ?? 20, currentDeps.executeThresholdPercentage, modelKey, currentDeps.historyBudgetPercentage, currentDeps.commitClusterTrigger, currentDeps.executeThresholdTokens, usableContextLimit, {
28328
28825
  backlog: getDreamTaskBacklogs(currentDeps.db, currentDeps.projectIdentity, CANONICAL_DREAM_TASKS)
28329
- }, windowGeometry);
28826
+ }, windowGeometry, resolveTailHygieneStatus(getPiChannel1Baseline(sessionId)));
28330
28827
  const details = buildStatusDetails(currentDeps, sessionId);
28331
28828
  sendCtxStatusMessage(pi, { title: "/ctx-status", text: statusText, level: "info" }, details);
28332
28829
  } catch (error) {
@@ -29207,10 +29704,7 @@ async function src_default(pi) {
29207
29704
  return;
29208
29705
  }
29209
29706
  const migration = getMigrationOnOpenRefusal();
29210
- const blockingProcesses = migration?.serverPids.map((pid) => ({
29211
- harness: "OpenCode server",
29212
- pid
29213
- })) ?? [];
29707
+ const blockingProcesses = migration?.blockingProcesses ?? migration?.serverPids.map((pid) => ({ kind: "process", pid })) ?? [];
29214
29708
  const fence = getSchemaFenceRejection();
29215
29709
  const reason = migration && blockingProcesses.length > 0 ? {
29216
29710
  kind: "migration_guard",
@@ -29761,9 +30255,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
29761
30255
  isCacheBusting,
29762
30256
  existingSystemPrompt: event.systemPrompt
29763
30257
  });
29764
- const composedPrompt = block ? `${event.systemPrompt}
29765
-
29766
- ${block}` : event.systemPrompt;
30258
+ const composedPrompt = composeMagicContextSystemPrompt(event.systemPrompt, block);
29767
30259
  if (!sessionId) {
29768
30260
  if (block)
29769
30261
  return { systemPrompt: composedPrompt };
@@ -29853,14 +30345,14 @@ ${block}` : event.systemPrompt;
29853
30345
  return;
29854
30346
  if (compactionOff)
29855
30347
  return;
29856
- if (db)
29857
- maybeDeliverChannel2Pi(pi, db, sessionId, "steer");
29858
30348
  const block = maybeChannel1ReminderForToolResult({
29859
30349
  db,
29860
30350
  sessionId,
29861
30351
  toolName: event.toolName,
29862
30352
  content: event.content
29863
30353
  });
30354
+ if (db)
30355
+ maybeDeliverChannel2Pi(pi, db, sessionId);
29864
30356
  if (!block)
29865
30357
  return;
29866
30358
  return { content: [...event.content, block] };
@@ -30016,16 +30508,16 @@ function formatExecuteThresholdForLog(value) {
30016
30508
  return overrides.length > 0 ? `${base} (${overrides.join(", ")})` : base;
30017
30509
  }
30018
30510
  export {
30019
- signalPiDeferredCompactionMarkerDrain,
30020
- resolveSidekickFromConfig,
30021
- resolveHistorianFromConfig,
30022
- resolveDreamerFromConfig,
30023
- persistPiPressureFromMessageEnd,
30024
- persistPiMessageEndModelMeta,
30025
- handlePiSessionBeforeCompact,
30026
- src_default as default,
30027
- capturePiTodowriteMessageIfCompatible,
30028
- capturePiTodowriteArgsIfCompatible,
30511
+ __test,
30029
30512
  canonicalPiModelKey,
30030
- __test
30513
+ capturePiTodowriteArgsIfCompatible,
30514
+ capturePiTodowriteMessageIfCompatible,
30515
+ src_default as default,
30516
+ handlePiSessionBeforeCompact,
30517
+ persistPiMessageEndModelMeta,
30518
+ persistPiPressureFromMessageEnd,
30519
+ resolveDreamerFromConfig,
30520
+ resolveHistorianFromConfig,
30521
+ resolveSidekickFromConfig,
30522
+ signalPiDeferredCompactionMarkerDrain
30031
30523
  };