@cortexkit/pi-magic-context 0.38.0 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -134,6 +134,7 @@ import {
134
134
  getAllStatusTagTokenTotalsFlat,
135
135
  getAutoSearchHintDecisions,
136
136
  getCachedAbsoluteMessageCount,
137
+ getChannel1NudgeState,
137
138
  getChannel2NudgeClaim,
138
139
  getChannel2NudgeState,
139
140
  getCompactionModeRecord,
@@ -149,7 +150,6 @@ import {
149
150
  getLastCompartmentEndMessage,
150
151
  getLastCompartmentEndMessageId,
151
152
  getLastIndexedOrdinal,
152
- getLastNudgeLevel,
153
153
  getLastNudgeUndropped,
154
154
  getLatestHistorianInvocationId,
155
155
  getLegacyProtectedTailStartOrdinal,
@@ -343,11 +343,11 @@ import {
343
343
  saveRecompStagingPass,
344
344
  saveSourceContent,
345
345
  scheduleAfterBootQuiet,
346
+ setChannel1NudgeState,
346
347
  setChannel2NudgeState,
347
348
  setCompactionModeRecord,
348
349
  setDeferredExecutePendingIfAbsent,
349
350
  setEmergencyDropSample,
350
- setLastNudgeLevel,
351
351
  setLastNudgeUndropped,
352
352
  setMemoryClassification,
353
353
  setMuralCue,
@@ -361,6 +361,7 @@ import {
361
361
  setSqlitePragmaConfig,
362
362
  setStoragePrivatePermissionEnforcement,
363
363
  setTodoSnapshot,
364
+ shouldUseStickyChannel1Reminder,
364
365
  sourceNameForMemory,
365
366
  stripChannel1ReminderSpans,
366
367
  stripMemoryMuralBlock,
@@ -395,7 +396,7 @@ import {
395
396
  withMigrationLanguageDirective,
396
397
  withRawMessageProvider,
397
398
  withRawSessionMessageCache
398
- } from "./index-6hs6yh6r.js";
399
+ } from "./index-qqgk7jmy.js";
399
400
  import {
400
401
  pushNotification
401
402
  } from "./index-hw34xmzk.js";
@@ -411,55 +412,110 @@ import {
411
412
  import {
412
413
  __require,
413
414
  __toESM
414
- } from "./index-wckvcay0.js";
415
+ } from "./index-1yh8g550.js";
415
416
 
416
417
  // src/index.ts
417
418
  import { createRequire as createRequire3 } from "node:module";
418
419
  import { join as join5, resolve as resolve2 } from "node:path";
419
420
 
420
- // ../plugin/src/shared/resolve-fallbacks.ts
421
- function resolveFallbackChain(userFallbacks) {
422
- const userList = normalizeUserFallbacks(userFallbacks);
423
- return dedupe(userList.filter(isValidModelSpec));
421
+ // ../plugin/src/shared/model-resolution.ts
422
+ function asRecord(value) {
423
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
424
424
  }
425
- function normalizeUserFallbacks(userFallbacks) {
426
- if (!userFallbacks)
427
- return [];
428
- if (typeof userFallbacks === "string") {
429
- const trimmed = userFallbacks.trim();
430
- return trimmed ? [trimmed] : [];
425
+ function readString(value) {
426
+ if (typeof value !== "string")
427
+ return;
428
+ const trimmed = value.trim();
429
+ return trimmed.length > 0 ? trimmed : undefined;
430
+ }
431
+ function hasOwn(record, key) {
432
+ return Object.hasOwn(record, key);
433
+ }
434
+ function normalizeModelEntry(entry, harness) {
435
+ if (typeof entry === "string") {
436
+ const model2 = readString(entry);
437
+ return model2 ? { model: model2 } : undefined;
431
438
  }
432
- return userFallbacks.map((s) => s.trim()).filter((s) => s.length > 0);
439
+ const objectEntry = asRecord(entry);
440
+ if (!objectEntry)
441
+ return;
442
+ const model = readString(objectEntry.model);
443
+ if (!model)
444
+ return;
445
+ const qualifier = readString(objectEntry[harness === "opencode" ? "variant" : "thinking_level"]);
446
+ return qualifier ? { model, qualifier } : { model };
433
447
  }
434
- function isValidModelSpec(spec) {
435
- const slash = spec.indexOf("/");
436
- return slash > 0 && slash < spec.length - 1;
448
+ function isValidModelReference(entry) {
449
+ const slash = entry.model.indexOf("/");
450
+ return slash > 0 && slash < entry.model.length - 1;
437
451
  }
438
- function dedupe(list) {
439
- const seen = new Set;
440
- const out = [];
441
- for (const item of list) {
442
- if (seen.has(item))
452
+ function sameAttempt(a, b) {
453
+ return a.model === b.model && a.qualifier === b.qualifier;
454
+ }
455
+ function resolveFallbackEntries(value, harness) {
456
+ const values = Array.isArray(value) ? value : value === undefined ? [] : [value];
457
+ const resolved = [];
458
+ for (const value2 of values) {
459
+ const entry = normalizeModelEntry(value2, harness);
460
+ if (!entry || !isValidModelReference(entry))
443
461
  continue;
444
- seen.add(item);
445
- out.push(item);
462
+ if (resolved.some((candidate) => sameAttempt(candidate, entry)))
463
+ continue;
464
+ resolved.push(entry);
446
465
  }
447
- return out;
466
+ return resolved;
448
467
  }
449
- function parseProviderModel(spec) {
450
- const slash = spec.indexOf("/");
451
- if (slash < 1 || slash >= spec.length - 1)
452
- return null;
468
+ function resolvePrimaryEntry(args) {
469
+ const entry = normalizeModelEntry(args.entry, args.harness);
470
+ if (!entry)
471
+ return;
472
+ const qualifier = entry.qualifier ?? readString(args.defaultQualifier);
473
+ return qualifier ? { ...entry, qualifier } : entry;
474
+ }
475
+ function resolveHistorianModel(config, harness) {
476
+ const historian = asRecord(asRecord(config)?.historian);
477
+ const block = asRecord(historian?.[harness]);
478
+ if (!block)
479
+ return { fallbacks: [] };
453
480
  return {
454
- providerID: spec.slice(0, slash).trim(),
455
- modelID: spec.slice(slash + 1).trim()
481
+ primary: resolvePrimaryEntry({
482
+ entry: block.model,
483
+ defaultQualifier: block[harness === "opencode" ? "variant" : "thinking_level"],
484
+ harness
485
+ }),
486
+ fallbacks: resolveFallbackEntries(block.fallback_models, harness)
456
487
  };
457
488
  }
458
- function modelBodyField(spec) {
459
- if (!spec)
460
- return {};
461
- const parsed = parseProviderModel(spec);
462
- return parsed ? { model: parsed } : {};
489
+ function resolveDreamerTaskModel(args) {
490
+ const dreamer = asRecord(asRecord(args.config)?.dreamer);
491
+ const harnessBlock = asRecord(dreamer?.[args.harness]);
492
+ const taskBlock = asRecord(asRecord(harnessBlock?.tasks)?.[args.task]);
493
+ const schedulingTask = asRecord(asRecord(dreamer?.tasks)?.[args.task]);
494
+ if (!harnessBlock) {
495
+ return {
496
+ fallbacks: [],
497
+ schedule: readString(schedulingTask?.schedule),
498
+ timeoutMinutes: typeof taskBlock?.timeout_minutes === "number" ? taskBlock.timeout_minutes : undefined,
499
+ promotionThreshold: typeof schedulingTask?.promotion_threshold === "number" ? schedulingTask.promotion_threshold : undefined
500
+ };
501
+ }
502
+ const taskQualifier = taskBlock?.[args.harness === "opencode" ? "variant" : "thinking_level"];
503
+ const harnessQualifier = harnessBlock[args.harness === "opencode" ? "variant" : "thinking_level"] ?? normalizeModelEntry(harnessBlock.model, args.harness)?.qualifier;
504
+ const taskHasModel = taskBlock !== undefined && hasOwn(taskBlock, "model");
505
+ const usesMuralModel = !taskHasModel && args.task === "compress-cues" && Boolean(readString(args.muralModel));
506
+ const primarySource = taskHasModel ? taskBlock?.model : usesMuralModel ? args.muralModel : harnessBlock.model;
507
+ const fallbackSource = taskBlock !== undefined && hasOwn(taskBlock, "fallback_models") ? taskBlock.fallback_models : harnessBlock.fallback_models;
508
+ return {
509
+ primary: resolvePrimaryEntry({
510
+ entry: primarySource,
511
+ defaultQualifier: usesMuralModel ? harnessQualifier : taskQualifier ?? harnessQualifier,
512
+ harness: args.harness
513
+ }),
514
+ fallbacks: resolveFallbackEntries(fallbackSource, args.harness),
515
+ schedule: readString(schedulingTask?.schedule),
516
+ timeoutMinutes: typeof taskBlock?.timeout_minutes === "number" ? taskBlock.timeout_minutes : undefined,
517
+ promotionThreshold: typeof schedulingTask?.promotion_threshold === "number" ? schedulingTask.promotion_threshold : undefined
518
+ };
463
519
  }
464
520
 
465
521
  // ../plugin/src/features/magic-context/dreamer/task-registry.ts
@@ -528,25 +584,23 @@ function compareTaskOrder(a, b) {
528
584
  }
529
585
 
530
586
  // ../plugin/src/features/magic-context/dreamer/task-config.ts
531
- function buildDreamTaskRuntimeConfigs(dreamer, language) {
532
- const tasks = dreamer.tasks ?? {};
587
+ function buildDreamTaskRuntimeConfigs(dreamer, harness, language, muralModel) {
533
588
  return CANONICAL_DREAM_TASKS.map((task) => {
534
- const t = tasks[task] ?? {
535
- schedule: "",
536
- timeout_minutes: 20
537
- };
538
- const model = task === "compress-cues" ? t.model : t.model ?? dreamer.model;
539
- const fallbackModels = resolveFallbackChain(t.fallback_models ?? dreamer.fallback_models);
540
- const thinkingLevel = t.thinking_level ?? dreamer.thinking_level;
589
+ const resolved = resolveDreamerTaskModel({
590
+ config: { dreamer },
591
+ harness,
592
+ task,
593
+ muralModel
594
+ });
541
595
  return {
542
596
  task,
543
- schedule: t.schedule,
544
- model,
545
- fallbackModels,
546
- thinkingLevel,
597
+ schedule: resolved.schedule ?? "",
598
+ model: resolved.primary,
599
+ fallbackModels: resolved.fallbacks,
600
+ thinkingLevel: harness === "pi" ? resolved.primary?.qualifier : undefined,
547
601
  language,
548
- timeoutMinutes: t.timeout_minutes ?? 20,
549
- promotionThreshold: t.promotion_threshold
602
+ timeoutMinutes: resolved.timeoutMinutes ?? 20,
603
+ promotionThreshold: resolved.promotionThreshold
550
604
  };
551
605
  });
552
606
  }
@@ -1951,6 +2005,59 @@ function shouldKeepSubagents() {
1951
2005
  return keepSubagents;
1952
2006
  }
1953
2007
 
2008
+ // ../plugin/src/shared/resolve-fallbacks.ts
2009
+ function resolveFallbackChain(userFallbacks) {
2010
+ const userList = normalizeUserFallbacks(userFallbacks);
2011
+ return dedupe(userList.filter(isValidModelSpec));
2012
+ }
2013
+ function normalizeUserFallbacks(userFallbacks) {
2014
+ if (!userFallbacks)
2015
+ return [];
2016
+ if (typeof userFallbacks === "string") {
2017
+ const trimmed = userFallbacks.trim();
2018
+ return trimmed ? [trimmed] : [];
2019
+ }
2020
+ return userFallbacks.map((s) => s.trim()).filter((s) => s.length > 0);
2021
+ }
2022
+ function isValidModelSpec(spec) {
2023
+ const slash = spec.indexOf("/");
2024
+ return slash > 0 && slash < spec.length - 1;
2025
+ }
2026
+ function dedupe(list) {
2027
+ const seen = new Set;
2028
+ const out = [];
2029
+ for (const item of list) {
2030
+ if (seen.has(item))
2031
+ continue;
2032
+ seen.add(item);
2033
+ out.push(item);
2034
+ }
2035
+ return out;
2036
+ }
2037
+ function parseProviderModel(spec) {
2038
+ const slash = spec.indexOf("/");
2039
+ if (slash < 1 || slash >= spec.length - 1)
2040
+ return null;
2041
+ return {
2042
+ providerID: spec.slice(0, slash).trim(),
2043
+ modelID: spec.slice(slash + 1).trim()
2044
+ };
2045
+ }
2046
+ function modelBodyField(spec) {
2047
+ const entry = toModelEntry(spec);
2048
+ if (!entry)
2049
+ return {};
2050
+ const parsed = parseProviderModel(entry.model);
2051
+ return parsed ? { model: parsed, ...entry.qualifier ? { variant: entry.qualifier } : {} } : {};
2052
+ }
2053
+ function toModelEntry(spec) {
2054
+ if (typeof spec === "string") {
2055
+ const model = spec.trim();
2056
+ return model ? { model } : undefined;
2057
+ }
2058
+ return spec;
2059
+ }
2060
+
1954
2061
  // src/clone-inheritance.ts
1955
2062
  import { readFile } from "node:fs/promises";
1956
2063
  var CONTENT_ID_SUFFIX = /:(?:p|file)\d+$/;
@@ -2530,14 +2637,35 @@ class PiSubagentRunner {
2530
2637
  return { result: isolatedResult, extensionRetryUsed: true };
2531
2638
  }
2532
2639
  async runModelChain(options, runMode, primaryModelRef) {
2533
- const models = [options.model, ...options.fallbackModels ?? []].filter((model) => typeof model === "string" && model.length > 0);
2534
- const attempts = models.length > 0 ? models : [undefined];
2640
+ const attempts = [];
2641
+ const seenAttempts = new Set;
2642
+ const appendAttempt = (candidate) => {
2643
+ if (!candidate.model)
2644
+ return;
2645
+ const key = `${candidate.model}\x00${candidate.qualifier ?? ""}`;
2646
+ if (seenAttempts.has(key))
2647
+ return;
2648
+ seenAttempts.add(key);
2649
+ attempts.push(candidate);
2650
+ };
2651
+ if (options.model) {
2652
+ appendAttempt({
2653
+ model: options.model,
2654
+ ...options.thinkingLevel ? { qualifier: options.thinkingLevel } : {}
2655
+ });
2656
+ }
2657
+ for (const candidate of options.fallbackModels ?? []) {
2658
+ appendAttempt(typeof candidate === "string" ? { model: candidate } : candidate);
2659
+ }
2660
+ if (attempts.length === 0)
2661
+ attempts.push(undefined);
2535
2662
  let lastResult = null;
2536
2663
  for (let index = 0;index < attempts.length; index += 1) {
2537
- const model = attempts[index];
2664
+ const attempt = attempts[index];
2538
2665
  const attemptOptions = {
2539
2666
  ...options,
2540
- model,
2667
+ model: attempt?.model,
2668
+ thinkingLevel: attempt?.qualifier,
2541
2669
  fallbackModels: undefined
2542
2670
  };
2543
2671
  const result = await this.runOnce(attemptOptions, runMode, index === 0 ? primaryModelRef : undefined);
@@ -3748,11 +3876,11 @@ async function trySendTuiToast(sessionId, text, params, forcePersist) {
3748
3876
  const message = text.length > 200 ? `${text.slice(0, 200)}…` : text;
3749
3877
  const toastVariant = inferToastVariant(text);
3750
3878
  const duration = params.toastDurationMs ?? 5000;
3751
- const { isTuiConnected: checkTui } = await import("./rpc-notifications-s2rw51c6.js");
3879
+ const { isTuiConnected: checkTui } = await import("./rpc-notifications-gmhvmfpy.js");
3752
3880
  if (!checkTui(sessionId))
3753
3881
  return false;
3754
3882
  try {
3755
- const { pushNotification: pushNotification2 } = await import("./rpc-notifications-s2rw51c6.js");
3883
+ const { pushNotification: pushNotification2 } = await import("./rpc-notifications-gmhvmfpy.js");
3756
3884
  pushNotification2("toast", {
3757
3885
  title,
3758
3886
  message,
@@ -3801,7 +3929,7 @@ async function sendIgnoredMessageNow(client, sessionId, text, params, forcePersi
3801
3929
  queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
3802
3930
  return "queued";
3803
3931
  }
3804
- const { waitForSafeNotificationTarget } = await import("./safe-notification-target-7n7s6xv7.js");
3932
+ const { waitForSafeNotificationTarget } = await import("./safe-notification-target-q00qgjm6.js");
3805
3933
  if (await waitForSafeNotificationTarget(client, sessionId) === "skip") {
3806
3934
  sessionLog(sessionId, "notification skipped (session not titled yet)");
3807
3935
  return "skipped";
@@ -3820,7 +3948,7 @@ async function sendIgnoredMessageNow(client, sessionId, text, params, forcePersi
3820
3948
  let model = params.providerId && params.modelId ? { providerID: params.providerId, modelID: params.modelId } : undefined;
3821
3949
  if (!agent || !model || !variant) {
3822
3950
  try {
3823
- const { resolvePromptContext } = await import("./prompt-context-602yq94t.js");
3951
+ const { resolvePromptContext } = await import("./prompt-context-3kjq9ejq.js");
3824
3952
  const resolved = await resolvePromptContext(client, sessionId);
3825
3953
  if (resolved) {
3826
3954
  agent = agent ?? resolved.agent;
@@ -4091,15 +4219,18 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
4091
4219
  log(`[${callContext}] primary (${explicitPrimaryLabel}) failed: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
4092
4220
  }
4093
4221
  for (let i = 0;i < fallbacks.length; i += 1) {
4094
- const parsed = parseProviderModel(fallbacks[i]);
4222
+ const fallback = toModelEntry(fallbacks[i]);
4223
+ const parsed = fallback ? parseProviderModel(fallback.model) : null;
4095
4224
  if (!parsed) {
4096
- log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
4225
+ log(`[${callContext}] skipping invalid fallback spec: ${String(fallbacks[i])}`);
4097
4226
  continue;
4098
4227
  }
4099
4228
  const label = `${parsed.providerID}/${parsed.modelID}`;
4229
+ const { variant: _primaryVariant, ...bodyWithoutPrimaryVariant } = baseBody;
4100
4230
  const attemptArgs = copyPromptArgs(baseArgs, {
4101
- ...baseBody,
4102
- model: parsed
4231
+ ...bodyWithoutPrimaryVariant,
4232
+ model: parsed,
4233
+ ...fallback?.qualifier ? { variant: fallback.qualifier } : {}
4103
4234
  });
4104
4235
  try {
4105
4236
  await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label);
@@ -4115,7 +4246,7 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
4115
4246
  }
4116
4247
  }
4117
4248
  }
4118
- log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; last error: ${shortErr(lastError)}`);
4249
+ log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks.map((fallback) => toModelEntry(fallback)?.model ?? String(fallback))].join(", ")}; last error: ${shortErr(lastError)}`);
4119
4250
  throw lastError ?? new Error("All fallback models failed");
4120
4251
  }
4121
4252
  async function attemptAndValidate(client, args, timeoutMs, signal, callContext, attempt, options) {
@@ -4153,15 +4284,18 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
4153
4284
  log(`[${callContext}] primary (${explicitPrimaryLabel}) failed validation/prompt: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
4154
4285
  }
4155
4286
  for (let i = 0;i < fallbacks.length; i += 1) {
4156
- const parsed = parseProviderModel(fallbacks[i]);
4287
+ const fallback = toModelEntry(fallbacks[i]);
4288
+ const parsed = fallback ? parseProviderModel(fallback.model) : null;
4157
4289
  if (!parsed) {
4158
- log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
4290
+ log(`[${callContext}] skipping invalid fallback spec: ${String(fallbacks[i])}`);
4159
4291
  continue;
4160
4292
  }
4161
4293
  const label = `${parsed.providerID}/${parsed.modelID}`;
4294
+ const { variant: _primaryVariant, ...bodyWithoutPrimaryVariant } = baseBody;
4162
4295
  const attemptArgs = copyPromptArgs(baseArgs, {
4163
- ...baseBody,
4164
- model: parsed
4296
+ ...bodyWithoutPrimaryVariant,
4297
+ model: parsed,
4298
+ ...fallback?.qualifier ? { variant: fallback.qualifier } : {}
4165
4299
  });
4166
4300
  const attempt = {
4167
4301
  label,
@@ -4186,7 +4320,7 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
4186
4320
  }
4187
4321
  }
4188
4322
  }
4189
- log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; original error: ${shortErr(firstError)}; last error: ${shortErr(lastError)}`);
4323
+ log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks.map((fallback) => toModelEntry(fallback)?.model ?? String(fallback))].join(", ")}; original error: ${shortErr(firstError)}; last error: ${shortErr(lastError)}`);
4190
4324
  throw firstError ?? lastError ?? new Error("All fallback models failed validation");
4191
4325
  }
4192
4326
  // ../plugin/src/shared/normalize-sdk-response.ts
@@ -6882,22 +7016,67 @@ var asyncModulePromise = null;
6882
7016
  function getAsyncModule() {
6883
7017
  asyncModulePromise ??= (async () => {
6884
7018
  const [{ default: singlefileAsyncifyVariant }, { newQuickJSAsyncWASMModuleFromVariant }] = await Promise.all([
6885
- import("./index-ayd60xnw.js").then((m)=>__toESM(m.default,1)),
6886
- import("./index-3pnd4qh9.js")
7019
+ import("./index-rgdqj8nj.js").then((m)=>__toESM(m.default,1)),
7020
+ import("./index-8sseka65.js")
6887
7021
  ]);
6888
7022
  return newQuickJSAsyncWASMModuleFromVariant(singlefileAsyncifyVariant);
6889
7023
  })();
6890
7024
  return asyncModulePromise;
6891
7025
  }
7026
+ function acquireSandboxModule(signal) {
7027
+ const modulePromise = getAsyncModule();
7028
+ if (!signal)
7029
+ return modulePromise;
7030
+ if (signal.aborted) {
7031
+ return Promise.reject(signal.reason ?? new Error("smart-note check aborted"));
7032
+ }
7033
+ return new Promise((resolve, reject) => {
7034
+ const cleanup = () => signal.removeEventListener("abort", onAbort);
7035
+ const onAbort = () => {
7036
+ cleanup();
7037
+ reject(signal.reason ?? new Error("smart-note check aborted"));
7038
+ };
7039
+ signal.addEventListener("abort", onAbort, { once: true });
7040
+ modulePromise.then((module) => {
7041
+ cleanup();
7042
+ resolve(module);
7043
+ }, (error) => {
7044
+ cleanup();
7045
+ reject(error);
7046
+ });
7047
+ });
7048
+ }
6892
7049
  var sandboxRunChain = Promise.resolve();
6893
- function withSandboxLock(fn) {
6894
- const run = sandboxRunChain.then(fn, fn);
7050
+ function withSandboxLock(fn, signal, cancelled) {
7051
+ const start = () => signal?.aborted && cancelled ? cancelled() : fn();
7052
+ const run = sandboxRunChain.then(start, start);
6895
7053
  sandboxRunChain = run.then(() => {
6896
7054
  return;
6897
7055
  }, () => {
6898
7056
  return;
6899
7057
  });
6900
- return run;
7058
+ return resolveBeforeAbort(run, signal, cancelled);
7059
+ }
7060
+ function resolveBeforeAbort(run, signal, cancelled) {
7061
+ if (!signal || !cancelled)
7062
+ return run;
7063
+ if (signal.aborted)
7064
+ return Promise.resolve(cancelled());
7065
+ return new Promise((resolve, reject) => {
7066
+ const cleanup = () => signal.removeEventListener("abort", abort);
7067
+ const abort = () => {
7068
+ cleanup();
7069
+ resolve(cancelled());
7070
+ };
7071
+ signal.addEventListener("abort", abort, { once: true });
7072
+ run.then((result) => {
7073
+ cleanup();
7074
+ resolve(result);
7075
+ }, (error) => {
7076
+ cleanup();
7077
+ reject(error);
7078
+ });
7079
+ });
6901
7080
  }
6902
7081
  var DEFAULT_TIMEOUT_MS = 2000;
6903
7082
  var DEFAULT_HEAP_LIMIT_BYTES = 8 * 1024 * 1024;
@@ -6924,9 +7103,17 @@ async function runCompiledSmartNoteCheck(options) {
6924
7103
  if (Buffer.byteLength(options.compiledCheck, "utf8") > MAX_COMPILED_CHECK_BYTES) {
6925
7104
  return failureResult("compiled check exceeds 64 KiB", false);
6926
7105
  }
6927
- return withSandboxLock(() => runCompiledSmartNoteCheckLocked(options));
7106
+ let quickjs;
7107
+ try {
7108
+ quickjs = await acquireSandboxModule(options.signal);
7109
+ } catch (error) {
7110
+ if (options.signal?.aborted)
7111
+ return cancelledResult(options.signal.reason);
7112
+ return failureResult(formatSandboxError(error), false);
7113
+ }
7114
+ return withSandboxLock(() => runCompiledSmartNoteCheckLocked(options, quickjs), options.signal, () => cancelledResult(options.signal?.reason));
6928
7115
  }
6929
- async function runCompiledSmartNoteCheckLocked(options) {
7116
+ async function runCompiledSmartNoteCheckLocked(options, quickjs) {
6930
7117
  if (options.signal?.aborted)
6931
7118
  return cancelledResult(options.signal.reason);
6932
7119
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
@@ -6946,8 +7133,6 @@ async function runCompiledSmartNoteCheckLocked(options) {
6946
7133
  throwIfRunAborted(controller.signal);
6947
7134
  const capabilities = resolveCapabilitiesForRun(options, controller.signal);
6948
7135
  const deadline = Date.now() + timeoutMs;
6949
- const quickjs = await getAsyncModule();
6950
- throwIfRunAborted(controller.signal);
6951
7136
  const context = quickjs.newContext();
6952
7137
  try {
6953
7138
  context.runtime.setMemoryLimit(options.heapLimitBytes ?? DEFAULT_HEAP_LIMIT_BYTES);
@@ -7552,7 +7737,7 @@ async function evaluateSmartNotes(args) {
7552
7737
  projectIdentity: args.projectIdentity,
7553
7738
  projectRoot,
7554
7739
  maxChecks: 10,
7555
- sweepBudgetMs: 1e4,
7740
+ sweepBudgetMs: args.sweepBudgetMs ?? 1e4,
7556
7741
  leaseHeld,
7557
7742
  signal: leaseAbortController.signal,
7558
7743
  retinaHandoff: args.retinaHandoff
@@ -8077,19 +8262,26 @@ function parseMapMemoriesManifest(text) {
8077
8262
  if (out.length === 0 && body.trim().length > 0) {
8078
8263
  throw new Error(describeUnrecognizedManifestShape(text, "mappings", "memory"));
8079
8264
  }
8080
- assertNoDuplicateManifestIds(out.map((entry) => entry.id), "mappings");
8081
8265
  return out;
8082
8266
  }
8083
8267
  function validateMapMemoriesManifest(text, expectedIds) {
8084
8268
  const parsed = parseMapMemoriesManifest(text);
8085
8269
  assertParsedManifestNonEmpty(parsed.length, expectedIds.size, text, "mappings", "memory");
8086
- assertManifestCoversExactly(parsed.map((entry) => entry.id), expectedIds, "mappings");
8270
+ assertNoDuplicateManifestIds(parsed.filter((entry) => expectedIds.has(entry.id)).map((entry) => entry.id), "mappings");
8087
8271
  return parsed;
8088
8272
  }
8089
8273
 
8090
8274
  // ../plugin/src/features/magic-context/dreamer/map-memories.ts
8091
8275
  var MAP_BATCH_SIZE = 80;
8276
+ var MAP_BATCH_FLOOR_MS = 240000;
8277
+ var CONSECUTIVE_TIMEOUT_LIMIT2 = 2;
8092
8278
  var MAX_INDEPENDENT_REQUEUE_PER_RUN = MAP_BATCH_SIZE;
8279
+ function computeMapBatchSliceMs(remainingMs, batchesRemaining) {
8280
+ return Math.min(remainingMs, Math.max(MAP_BATCH_FLOOR_MS, Math.floor(remainingMs / batchesRemaining)));
8281
+ }
8282
+ function isTimeoutClassError2(error) {
8283
+ return error instanceof Error && /^prompt timed out after \d+ms$/.test(error.message);
8284
+ }
8093
8285
  function shouldRequeueIndependentMapping(state2, content, repoDir) {
8094
8286
  if (!state2.hasSentinel || state2.files.length > 0)
8095
8287
  return false;
@@ -8137,27 +8329,64 @@ async function mapMemories(args) {
8137
8329
  return result;
8138
8330
  const batches = [];
8139
8331
  for (let i = 0;i < inputs.length; i += MAP_BATCH_SIZE) {
8140
- batches.push(inputs.slice(i, i + MAP_BATCH_SIZE));
8332
+ batches.push({ inputs: inputs.slice(i, i + MAP_BATCH_SIZE), isOmissionRetry: false });
8141
8333
  }
8142
8334
  result.remaining = inputs.length;
8143
8335
  const abortController = new AbortController;
8144
8336
  const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
8145
8337
  try {
8338
+ let consecutiveTimeouts = 0;
8339
+ let timeoutStreakElapsedMs = [];
8146
8340
  for (let i = 0;i < batches.length; i += 1) {
8147
8341
  const remainingMs = Math.max(0, args.deadline - Date.now());
8148
- if (remainingMs <= 0)
8342
+ if (remainingMs <= 0) {
8343
+ result.stopReason = "deadline";
8149
8344
  break;
8150
- const batchesRemaining = batches.length - i;
8151
- const sliceMs = Math.max(1, Math.floor(remainingMs / batchesRemaining));
8152
- const counts = await mapOneBatch(args, batches[i], sliceMs, abortController.signal);
8153
- result.mapped += counts.mapped;
8154
- result.independent += counts.independent;
8155
- result.remaining -= counts.mapped + counts.independent;
8156
- result.batches += 1;
8157
- args.onProgress?.(result.mapped + result.independent);
8345
+ }
8346
+ if (remainingMs < MAP_BATCH_FLOOR_MS) {
8347
+ result.stopReason = "deadline";
8348
+ log(`[dreamer] map-memories: stopping before batch ${i + 1}/${batches.length} — remaining budget ${remainingMs}ms is below the ${MAP_BATCH_FLOOR_MS}ms batch floor; banking ${result.mapped + result.independent} mapping(s)`);
8349
+ break;
8350
+ }
8351
+ const sliceMs = computeMapBatchSliceMs(remainingMs, batches.length - i);
8352
+ const batch = batches[i];
8353
+ if (!batch)
8354
+ break;
8355
+ const outcome = await mapOneBatch(args, batch.inputs, sliceMs, abortController.signal);
8356
+ const committed = outcome.mapped + outcome.independent;
8357
+ result.mapped += outcome.mapped;
8358
+ result.independent += outcome.independent;
8359
+ result.remaining -= committed;
8360
+ if (committed > 0) {
8361
+ result.batches += 1;
8362
+ args.onProgress?.(result.mapped + result.independent);
8363
+ }
8364
+ if (outcome.requeue?.length) {
8365
+ if (!batch.isOmissionRetry) {
8366
+ batches.splice(i + 1, 0, {
8367
+ inputs: outcome.requeue,
8368
+ isOmissionRetry: true
8369
+ });
8370
+ log(`[dreamer] map-memories: committed ${committed}/${batch.inputs.length} mapping(s); requeueing ${outcome.requeue.length} omitted id(s) in a targeted retry`);
8371
+ } else {
8372
+ log(`[dreamer] map-memories: targeted retry still omitted ${outcome.requeue.length} id(s); leaving them unmapped for the next run`);
8373
+ }
8374
+ }
8375
+ if (outcome.failure?.class === "timeout") {
8376
+ consecutiveTimeouts += 1;
8377
+ timeoutStreakElapsedMs.push(outcome.failure.elapsedMs);
8378
+ if (consecutiveTimeouts >= CONSECUTIVE_TIMEOUT_LIMIT2) {
8379
+ result.stopReason = "timeout-circuit-breaker";
8380
+ log(`[dreamer] map-memories starvation: circuit breaker tripped after ${consecutiveTimeouts} consecutive batch timeouts (model too slow for its time slice); per-batch elapsed [${timeoutStreakElapsedMs.join("ms, ")}ms] vs ${sliceMs}ms slice; stopping with ${result.remaining} mapping(s) remaining`);
8381
+ break;
8382
+ }
8383
+ } else {
8384
+ consecutiveTimeouts = 0;
8385
+ timeoutStreakElapsedMs = [];
8386
+ }
8158
8387
  }
8159
8388
  result.complete = result.remaining === 0;
8160
- log(`[dreamer] map-memories: mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}`);
8389
+ log(`[dreamer] map-memories: committed=${result.mapped + result.independent} mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}${result.stopReason ? ` stop_reason=${result.stopReason}` : ""}`);
8161
8390
  return result;
8162
8391
  } finally {
8163
8392
  heartbeat.stop();
@@ -8211,12 +8440,16 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
8211
8440
  const text = extractLatestAssistantText(messages);
8212
8441
  if (!text)
8213
8442
  throw new Error("map-memories returned no output");
8214
- validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
8215
- return text;
8443
+ return validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
8216
8444
  }
8217
8445
  });
8218
8446
  recordInvocation2(args, startedAt, { status: "completed", messages: run.output });
8219
- return await applyBatchMappings(args, batch, run.validated);
8447
+ const outcome = await applyParsedBatchMappings(args, batch, run.validated);
8448
+ const returnedIds = new Set(run.validated.filter((entry) => batch.some((memory) => memory.id === entry.id)).map((entry) => entry.id));
8449
+ return {
8450
+ ...outcome,
8451
+ requeue: batch.filter((memory) => !returnedIds.has(memory.id))
8452
+ };
8220
8453
  } catch (error) {
8221
8454
  const desc = describeError(error);
8222
8455
  log(`[dreamer] map-memories batch failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
@@ -8225,7 +8458,14 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
8225
8458
  throw error;
8226
8459
  if (signal.aborted)
8227
8460
  throw error;
8228
- return { mapped: 0, independent: 0 };
8461
+ return {
8462
+ mapped: 0,
8463
+ independent: 0,
8464
+ failure: {
8465
+ class: isTimeoutClassError2(error) ? "timeout" : "other",
8466
+ elapsedMs: Date.now() - startedAt
8467
+ }
8468
+ };
8229
8469
  } finally {
8230
8470
  if (agentSessionId && !shouldKeepSubagents()) {
8231
8471
  await args.client.session.delete({
@@ -8237,14 +8477,21 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
8237
8477
  }
8238
8478
  }
8239
8479
  }
8240
- async function applyBatchMappings(args, batch, manifestText) {
8241
- const batchIds = new Set(batch.map((m) => m.id));
8242
- const parsed = parseMapMemoriesManifest(manifestText);
8243
- assertManifestCoversExactly(parsed.map((entry) => entry.id), batchIds, "mappings");
8244
- if (parsed.length === 0)
8480
+ async function applyParsedBatchMappings(args, batch, parsed) {
8481
+ const batchIds = new Set(batch.map((memory) => memory.id));
8482
+ const valid = parsed.filter((entry) => batchIds.has(entry.id));
8483
+ const unknown = parsed.filter((entry) => !batchIds.has(entry.id));
8484
+ if (unknown.length > 0) {
8485
+ log(`[dreamer] map-memories warning: dropping ${unknown.length} unknown mapping entr${unknown.length === 1 ? "y" : "ies"} outside the current batch (${unknown.map((entry) => entry.id).join(", ")})`);
8486
+ }
8487
+ assertNoDuplicateManifestIds(valid.map((entry) => entry.id), "mappings");
8488
+ if (valid.length * 2 < batch.length) {
8489
+ throw new Error(`mappings manifest covers ${valid.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
8490
+ }
8491
+ if (valid.length === 0)
8245
8492
  return { mapped: 0, independent: 0 };
8246
8493
  const planned = [];
8247
- for (const p of parsed) {
8494
+ for (const p of valid) {
8248
8495
  if (p.independent) {
8249
8496
  planned.push({ id: p.id, files: [], independent: true });
8250
8497
  continue;
@@ -9549,14 +9796,13 @@ function parseVerifyManifest(text) {
9549
9796
  if (verifyIds(out).length === 0 && body.trim().length > 0) {
9550
9797
  throw new Error(describeUnrecognizedManifestShape(text, "verify", "verified"));
9551
9798
  }
9552
- assertNoDuplicateManifestIds(verifyIds(out), "verify");
9553
9799
  return out;
9554
9800
  }
9555
9801
  function validateVerifyManifest(text, expectedIds) {
9556
9802
  const parsed = parseVerifyManifest(text);
9557
9803
  const ids = verifyIds(parsed);
9558
9804
  assertParsedManifestNonEmpty(ids.length, expectedIds.size, text, "verify", "verified");
9559
- assertManifestCoversExactly(ids, expectedIds, "verify");
9805
+ assertNoDuplicateManifestIds(ids.filter((id) => expectedIds.has(id)), "verify");
9560
9806
  return parsed;
9561
9807
  }
9562
9808
 
@@ -9709,19 +9955,14 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9709
9955
  const text = extractLatestAssistantText(messages);
9710
9956
  if (!text)
9711
9957
  throw new Error("verify returned no output");
9712
- try {
9713
- validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
9714
- } catch (error) {
9715
- const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
9716
- if (providerFailure)
9717
- throw providerFailure;
9718
- throw error;
9719
- }
9720
- return text;
9958
+ const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
9959
+ if (providerFailure)
9960
+ throw providerFailure;
9961
+ return validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
9721
9962
  }
9722
9963
  });
9723
9964
  recordInvocation4(args, startedAt, { status: "completed", messages: run.output });
9724
- return await applyVerifyManifest(args, batch, run.validated);
9965
+ return await applyParsedVerifyManifest(args, batch, run.validated);
9725
9966
  } catch (error) {
9726
9967
  const desc = describeError(error);
9727
9968
  const providerFailure = error instanceof DreamerProviderOutputFailureError ? error : undefined;
@@ -9741,17 +9982,31 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9741
9982
  }
9742
9983
  }
9743
9984
  }
9744
- async function applyVerifyManifest(args, batch, manifestText) {
9985
+ async function applyParsedVerifyManifest(args, batch, parsed) {
9745
9986
  const batchIds = new Set(batch.map((m) => m.id));
9746
- const parsed = parseVerifyManifest(manifestText);
9747
- assertManifestCoversExactly([...parsed.verified, ...parsed.updated, ...parsed.archived].map((entry) => entry.id), batchIds, "verify");
9987
+ const valid = {
9988
+ verified: parsed.verified.filter((entry) => batchIds.has(entry.id)),
9989
+ updated: parsed.updated.filter((entry) => batchIds.has(entry.id)),
9990
+ archived: parsed.archived.filter((entry) => batchIds.has(entry.id))
9991
+ };
9992
+ const unknown = [...parsed.verified, ...parsed.updated, ...parsed.archived].filter((entry) => !batchIds.has(entry.id));
9993
+ if (unknown.length > 0) {
9994
+ log(`[dreamer] verify warning: dropping ${unknown.length} unknown verification entr${unknown.length === 1 ? "y" : "ies"} outside the current batch (${unknown.map((entry) => entry.id).join(", ")})`);
9995
+ }
9996
+ const validIds = [...valid.verified, ...valid.updated, ...valid.archived].map((entry) => entry.id);
9997
+ assertNoDuplicateManifestIds(validIds, "verify");
9998
+ if (validIds.length * 2 < batch.length) {
9999
+ throw new Error(`verify manifest covers ${validIds.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
10000
+ }
10001
+ if (validIds.length === 0)
10002
+ return { verified: 0, updated: 0, archived: 0 };
9748
10003
  const now = Date.now();
9749
10004
  const writes = [];
9750
- for (const v of parsed.verified) {
10005
+ for (const v of valid.verified) {
9751
10006
  const files = await normalizeFiles(args, v.files);
9752
10007
  writes.push({ kind: "verify", id: v.id, files });
9753
10008
  }
9754
- for (const u of parsed.updated) {
10009
+ for (const u of valid.updated) {
9755
10010
  const content = u.content.trim();
9756
10011
  if (!content || content.length > 20000) {
9757
10012
  const files2 = await normalizeFiles(args, u.files);
@@ -9767,7 +10022,7 @@ async function applyVerifyManifest(args, batch, manifestText) {
9767
10022
  hash: computeNormalizedHash(content)
9768
10023
  });
9769
10024
  }
9770
- for (const a of parsed.archived) {
10025
+ for (const a of valid.archived) {
9771
10026
  writes.push({ kind: "archive", id: a.id, reason: a.reason });
9772
10027
  }
9773
10028
  if (writes.length === 0)
@@ -10074,7 +10329,7 @@ function createDreamTaskExecutor(deps) {
10074
10329
  leaseKey,
10075
10330
  deadline,
10076
10331
  leaseAcquisition,
10077
- model: config.model ?? deps.mural.model ?? deps.dreamerModel,
10332
+ model: config.model,
10078
10333
  fallbackModels: config.fallbackModels,
10079
10334
  moduleRoute,
10080
10335
  onProgress: (processed) => reportProgress(processed)
@@ -10123,8 +10378,19 @@ function createDreamTaskExecutor(deps) {
10123
10378
  moduleRoute,
10124
10379
  onProgress: (processed) => reportProgress(processed)
10125
10380
  });
10126
- log(`[dreamer] map-memories: mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining}`);
10381
+ log(`[dreamer] map-memories: committed=${result.mapped + result.independent} mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}${result.stopReason ? ` stop_reason=${result.stopReason}` : ""}`);
10127
10382
  if (!result.complete) {
10383
+ if (result.stopReason === "timeout-circuit-breaker") {
10384
+ const error2 = `map-memories starvation: timeout circuit breaker stopped the run with ${result.remaining} remain`;
10385
+ recordRun("failed", error2);
10386
+ return { status: "failed", transient: true, error: error2 };
10387
+ }
10388
+ const processed = result.mapped + result.independent;
10389
+ if (processed > 0) {
10390
+ const progress = `map-memories: committed ${processed} mapping(s) (mapped ${result.mapped}, independent ${result.independent}); ${result.remaining} remain`;
10391
+ recordRun("completed", null, { progress });
10392
+ return { status: "completed" };
10393
+ }
10128
10394
  const error = incompleteMessage(result.remaining);
10129
10395
  recordRun("failed", error);
10130
10396
  return { status: "failed", transient: true, error };
@@ -10951,6 +11217,7 @@ async function runDueTasksForProject(deps) {
10951
11217
  import { statSync as statSync2 } from "node:fs";
10952
11218
 
10953
11219
  // ../plugin/src/features/magic-context/dreamer/retrospective-orphan-sweep.ts
11220
+ var HISTORIAN_CHILD_TITLE = "magic-context-compartment";
10954
11221
  var RETROSPECTIVE_CHILD_TITLE = "magic-context-dream-retrospective";
10955
11222
  var USER_MEMORIES_CHILD_TITLE = "magic-context-dream-user-memories";
10956
11223
  var CURATE_CHILD_TITLE = "magic-context-dream-curate";
@@ -10976,16 +11243,34 @@ var PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES = {
10976
11243
  ],
10977
11244
  prefixes: [SMART_NOTE_COMPILE_CHILD_TITLE_PREFIX, SMART_NOTE_CONFIRM_CHILD_TITLE_PREFIX]
10978
11245
  };
11246
+ var HISTORIAN_CHILD_TITLE_MATCHES = {
11247
+ exact: [HISTORIAN_CHILD_TITLE],
11248
+ prefixes: []
11249
+ };
11250
+ var INTERNAL_CHILD_TITLE_MATCHES = {
11251
+ exact: [HISTORIAN_CHILD_TITLE, ...PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES.exact],
11252
+ prefixes: PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES.prefixes
11253
+ };
10979
11254
  function retrospectiveOrphanStaleMs(taskTimeoutMinutes) {
10980
11255
  const timeoutCandidates = Array.isArray(taskTimeoutMinutes) ? taskTimeoutMinutes : [taskTimeoutMinutes];
10981
11256
  const maxTimeoutMinutes = Math.max(...timeoutCandidates.map((minutes) => Math.max(1, minutes ?? 20)), 20);
10982
11257
  const timeoutMs = maxTimeoutMinutes * 60000;
10983
11258
  return Math.max(60 * 60000, timeoutMs * 3);
10984
11259
  }
11260
+ var HISTORIAN_OUTER_ATTEMPTS = 3;
11261
+ var HISTORIAN_MODEL_SUGGESTION_ATTEMPTS = 2;
11262
+ var HISTORIAN_MAX_RETRY_BACKOFF_MS = 11000;
11263
+ var HISTORIAN_DETACHED_WRITER_GRACE_MS = 15 * 60000;
11264
+ function historianOrphanStaleMs(timeoutMs, fallbackModelCount) {
11265
+ const timeout = Math.max(60000, timeoutMs);
11266
+ const fallbackCount = Math.max(0, Math.floor(fallbackModelCount));
11267
+ const fullAttemptBudget = timeout * HISTORIAN_OUTER_ATTEMPTS * HISTORIAN_MODEL_SUGGESTION_ATTEMPTS * (fallbackCount + 1);
11268
+ return Math.max(60 * 60000, fullAttemptBudget + HISTORIAN_MAX_RETRY_BACKOFF_MS + HISTORIAN_DETACHED_WRITER_GRACE_MS);
11269
+ }
10985
11270
  async function sweepOrphanedRetrospectiveChildren(args) {
10986
11271
  const { opencodeDb, client, sessionDirectory, staleMs } = args;
10987
- const titleMatches = args.titleMatches ?? PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES;
10988
- if (!opencodeDb)
11272
+ const titleMatches = args.titleMatches ?? INTERNAL_CHILD_TITLE_MATCHES;
11273
+ if (!opencodeDb || args.keepSubagents === true)
10989
11274
  return 0;
10990
11275
  const now = args.now ?? Date.now();
10991
11276
  const cutoff = now - staleMs;
@@ -11008,7 +11293,7 @@ async function sweepOrphanedRetrospectiveChildren(args) {
11008
11293
  ORDER BY time_created ASC
11009
11294
  LIMIT 200`).all(...titleParams, sessionDirectory, cutoff);
11010
11295
  } catch (error) {
11011
- log(`[dreamer] retrospective orphan sweep: read skipped (${String(error)})`);
11296
+ log(`[magic-context] internal child orphan sweep: read skipped (${String(error)})`);
11012
11297
  return 0;
11013
11298
  }
11014
11299
  if (rows.length === 0)
@@ -11023,7 +11308,7 @@ async function sweepOrphanedRetrospectiveChildren(args) {
11023
11308
  }
11024
11309
  }
11025
11310
  if (deleted > 0) {
11026
- log(`[dreamer] swept ${deleted} crash-orphaned privacy-sensitive child session(s)`);
11311
+ log(`[magic-context] swept ${deleted} stale internal child session(s)`);
11027
11312
  }
11028
11313
  return deleted;
11029
11314
  }
@@ -11163,7 +11448,7 @@ function scheduleInitialProjectRun(reg, db) {
11163
11448
  startupTimers.set(reg.directory, timer);
11164
11449
  }
11165
11450
  async function runProjectMaintenance(reg, origin, db) {
11166
- const projectMaintenanceEnabled = Boolean(reg.dreamerConfig && reg.dreamerConfig.disable !== true) || reg.memoryEnabled === true || reg.gitCommitIndexing?.enabled === true;
11451
+ const projectMaintenanceEnabled = Boolean(reg.dreamerConfig && reg.dreamerConfig.disable !== true) || reg.memoryEnabled === true || reg.gitCommitIndexing?.enabled === true || reg.historianChildSweep !== undefined;
11167
11452
  if (!projectMaintenanceEnabled)
11168
11453
  return;
11169
11454
  await reg.ensureRegistered(reg.directory, db);
@@ -11200,6 +11485,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
11200
11485
  if (gcDeleted > 0) {
11201
11486
  log(`[magic-context] GC'd ${gcDeleted} stale embedding row(s) for ${reg.projectIdentity} ` + `(memory=${gc.memoryRowsDeleted} commit=${gc.commitRowsDeleted} chunk=${gc.chunkRowsDeleted})`);
11202
11487
  }
11488
+ await sweepOrphanedHistorianChildren(reg);
11203
11489
  const dreamerConfig = reg.dreamerConfig;
11204
11490
  const dreamingEnabled = Boolean(dreamerConfig && dreamerConfig.disable !== true);
11205
11491
  if (commitIndexingEnabled && reg.gitCommitIndexing) {
@@ -11215,7 +11501,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
11215
11501
  }
11216
11502
  try {
11217
11503
  await runCompiledSmartNoteSweep(reg, db);
11218
- const runtimeConfigs = buildDreamTaskRuntimeConfigs(dreamerConfig, reg.language);
11504
+ const runtimeConfigs = buildDreamTaskRuntimeConfigs(dreamerConfig, "opencode", reg.language, reg.mural?.model);
11219
11505
  const executor = createDreamTaskExecutor({
11220
11506
  client: reg.client,
11221
11507
  sessionDirectory: reg.directory,
@@ -11225,7 +11511,6 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
11225
11511
  userMemoryCollectionEnabled: userMemoryCollectionEnabled(dreamerConfig),
11226
11512
  ensureProjectRegistered: reg.ensureRegistered,
11227
11513
  language: reg.language,
11228
- dreamerModel: dreamerConfig.model,
11229
11514
  mural: reg.mural,
11230
11515
  memoryInjectionBudgetTokens: reg.memoryInjectionBudgetTokens,
11231
11516
  retinaHandoff: reg.retinaHandoff,
@@ -11263,6 +11548,27 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
11263
11548
  log(`[dreamer] timer-triggered task scheduling failed for ${reg.projectIdentity}:`, error);
11264
11549
  }
11265
11550
  }
11551
+ async function sweepOrphanedHistorianChildren(reg) {
11552
+ const config = reg.historianChildSweep;
11553
+ if (!config || config.keepSubagents)
11554
+ return;
11555
+ const ocDb = openOpenCodeDb();
11556
+ if (!ocDb)
11557
+ return;
11558
+ try {
11559
+ await sweepOrphanedRetrospectiveChildren({
11560
+ opencodeDb: ocDb,
11561
+ client: reg.client,
11562
+ sessionDirectory: reg.directory,
11563
+ staleMs: historianOrphanStaleMs(config.timeoutMs, config.fallbackModelCount),
11564
+ titleMatches: HISTORIAN_CHILD_TITLE_MATCHES
11565
+ });
11566
+ } catch (error) {
11567
+ log(`[magic-context] historian child orphan sweep failed for ${reg.projectIdentity}:`, error);
11568
+ } finally {
11569
+ closeQuietly(ocDb);
11570
+ }
11571
+ }
11266
11572
  async function runCompiledSmartNoteSweep(reg, db) {
11267
11573
  const leaseKey = leaseKeyFor("evaluate-smart-notes", reg.projectIdentity);
11268
11574
  const holderId = crypto.randomUUID();
@@ -11590,11 +11896,13 @@ function registerPiDreamerProject(opts) {
11590
11896
  startDreamScheduleTimerFn({
11591
11897
  directory: opts.projectDir,
11592
11898
  projectIdentity: opts.projectIdentity,
11899
+ harness: "pi",
11593
11900
  client,
11594
11901
  dreamerConfig: opts.config,
11595
11902
  language: opts.language,
11596
11903
  gitCommitIndexing: opts.gitCommitIndexing,
11597
11904
  retinaHandoff: opts.retinaHandoff,
11905
+ mural: opts.mural,
11598
11906
  ensureRegistered: ensureProjectRegisteredFromPiDirectory,
11599
11907
  retrospectiveRawProvider: () => new PiRetrospectiveRawProvider({ projectCwd: opts.projectDir }),
11600
11908
  primerRawProviderFactory: createPiPrimerRawProviderFactory()
@@ -11608,7 +11916,7 @@ function registerPiDreamerProject(opts) {
11608
11916
  const runManual = async (task) => runManualDream({
11609
11917
  db: opts.db,
11610
11918
  projectIdentity: opts.projectIdentity,
11611
- tasks: buildDreamTaskRuntimeConfigs(opts.config, opts.language),
11919
+ tasks: buildDreamTaskRuntimeConfigs(opts.config, "pi", opts.language, opts.mural?.model),
11612
11920
  executor: createDreamTaskExecutor({
11613
11921
  client,
11614
11922
  sessionDirectory: opts.projectDir,
@@ -11620,7 +11928,8 @@ function registerPiDreamerProject(opts) {
11620
11928
  userMemoryCollectionEnabled: userMemoryCollectionEnabled(opts.config),
11621
11929
  ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
11622
11930
  language: opts.language,
11623
- retinaHandoff: opts.retinaHandoff
11931
+ retinaHandoff: opts.retinaHandoff,
11932
+ mural: opts.mural
11624
11933
  }),
11625
11934
  task
11626
11935
  });
@@ -11656,7 +11965,6 @@ async function awaitInFlightDreamers() {
11656
11965
  }
11657
11966
  function createPiDreamerClient(opts) {
11658
11967
  const runner = piSubagentRunnerFactory();
11659
- const model = opts.config.model;
11660
11968
  const session = {
11661
11969
  create: async (args) => {
11662
11970
  const sessionId = `magic-context-pi-dream-${++sessionCounter}`;
@@ -11677,7 +11985,7 @@ function createPiDreamerClient(opts) {
11677
11985
  }
11678
11986
  const userMessage = extractUserMessage(args);
11679
11987
  const systemPrompt = extractSystemPrompt(args);
11680
- const perTaskModel = extractBodyModel(args) ?? model;
11988
+ const perTaskModel = extractBodyModel(args);
11681
11989
  const requestedAgent = extractBodyAgent(args) ?? "magic-context-dreamer";
11682
11990
  const runPromise = runner.run({
11683
11991
  agent: requestedAgent,
@@ -11688,7 +11996,7 @@ function createPiDreamerClient(opts) {
11688
11996
  timeoutMs: 30 * 60 * 1000,
11689
11997
  cwd: dreamSession.directory,
11690
11998
  signal: args.signal ?? undefined,
11691
- thinkingLevel: opts.config.thinking_level
11999
+ thinkingLevel: extractBodyVariant(args)
11692
12000
  });
11693
12001
  inFlightDreams.add(runPromise);
11694
12002
  try {
@@ -11779,6 +12087,13 @@ function extractBodyModel(args) {
11779
12087
  }
11780
12088
  return;
11781
12089
  }
12090
+ function extractBodyVariant(args) {
12091
+ const body = args.body;
12092
+ if (typeof body !== "object" || body === null)
12093
+ return;
12094
+ const variant = body.variant;
12095
+ return typeof variant === "string" && variant.length > 0 ? variant : undefined;
12096
+ }
11782
12097
  function extractBodyAgent(args) {
11783
12098
  const body = args.body;
11784
12099
  if (typeof body !== "object" || body === null)
@@ -12916,10 +13231,19 @@ function writeTransformDecisionRow(dbPath, row) {
12916
13231
  function writeTransformDecisionRowOnDatabase(db, row, configureBusyTimeout) {
12917
13232
  if (configureBusyTimeout)
12918
13233
  db.exec("PRAGMA busy_timeout=0");
13234
+ const systemHashPrev = row.materialized ? row.systemHashPrev : null;
13235
+ const systemHashNew = row.materialized ? row.systemHashNew : null;
13236
+ const m0ModelKeyPrev = row.materialized ? row.m0ModelKeyPrev : null;
13237
+ const m0ModelKeyNew = row.materialized ? row.m0ModelKeyNew : null;
13238
+ const m0ToolSetHashPrev = row.m0ToolSetHashPrev ?? null;
13239
+ const m0ToolSetHashNew = row.m0ToolSetHashNew ?? null;
12919
13240
  db.prepare(`INSERT OR REPLACE INTO transform_decisions (
12920
13241
  session_id, harness, message_id, ts_ms, decision, materialized,
12921
- materialize_reason, emergency, dropped_tokens, dropped_count, input_tokens
12922
- ) 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)));
13242
+ materialize_reason, system_hash_prev, system_hash_new,
13243
+ m0_tool_set_hash_prev, m0_tool_set_hash_new,
13244
+ m0_model_key_prev, m0_model_key_new, emergency, dropped_tokens,
13245
+ dropped_count, input_tokens
13246
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.sessionId, row.harness, row.messageId, row.tsMs, row.decision, row.materialized ? 1 : 0, row.materializeReason, systemHashPrev, systemHashNew, m0ToolSetHashPrev, m0ToolSetHashNew, 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)));
12923
13247
  db.prepare(`DELETE FROM transform_decisions
12924
13248
  WHERE session_id = ? AND harness = ?
12925
13249
  AND rowid NOT IN (
@@ -15975,6 +16299,17 @@ function isSyntheticMessage(message, index, input) {
15975
16299
  const role = typeof message.role === "string" ? message.role : "";
15976
16300
  return role === "system" || role === "custom" || role === "compactionSummary";
15977
16301
  }
16302
+ function countRealPiUserMessages(input) {
16303
+ let count = 0;
16304
+ for (let index = 0;index < input.messages.length; index += 1) {
16305
+ const message = input.messages[index];
16306
+ if (!isRecord3(message) || message.role !== "user")
16307
+ continue;
16308
+ if (!isSyntheticMessage(message, index, input))
16309
+ count += 1;
16310
+ }
16311
+ return count;
16312
+ }
15978
16313
  function imageContentAndTokens(part) {
15979
16314
  const data = typeof part.data === "string" ? part.data : "";
15980
16315
  const mimeType = typeof part.mimeType === "string" ? part.mimeType : "image/png";
@@ -16168,7 +16503,7 @@ function excludedDraft(key, value) {
16168
16503
  tokens: 0
16169
16504
  };
16170
16505
  }
16171
- function finalizeParts(drafts, protectedTags) {
16506
+ function finalizeParts(drafts, protectedTags, pendingDropTagNumbers) {
16172
16507
  const visibleTags = new Map;
16173
16508
  for (const part of drafts) {
16174
16509
  if (part.kind !== "excluded" && part.tag)
@@ -16183,7 +16518,8 @@ function finalizeParts(drafts, protectedTags) {
16183
16518
  const parts = drafts.map((draft) => {
16184
16519
  const protectedPart = draft.tag ? protectedNumbers.has(draft.tag.tagNumber) : false;
16185
16520
  const tokens = Math.max(0, draft.tokens);
16186
- const uTokens = draft.tag && !protectedPart && draft.kind !== "excluded" ? tokens : 0;
16521
+ const queuedForDrop = draft.tag ? pendingDropTagNumbers.has(draft.tag.tagNumber) : false;
16522
+ const uTokens = draft.tag && !protectedPart && !queuedForDrop && draft.kind !== "excluded" ? tokens : 0;
16187
16523
  t += tokens;
16188
16524
  u += uTokens;
16189
16525
  return {
@@ -16194,7 +16530,8 @@ function finalizeParts(drafts, protectedTags) {
16194
16530
  uTokens,
16195
16531
  tagNumber: draft.tag?.tagNumber ?? null,
16196
16532
  tagStatus: draft.tag ? "active" : null,
16197
- protected: protectedPart
16533
+ protected: protectedPart,
16534
+ queuedForDrop
16198
16535
  };
16199
16536
  });
16200
16537
  const clampedT = Math.max(0, t);
@@ -16336,29 +16673,34 @@ function measurePiTailHygiene(input) {
16336
16673
  drafts.push(excludedDraft(`${key}\x00excluded`, part));
16337
16674
  }
16338
16675
  }
16339
- return finalizeParts(drafts, input.protectedTags);
16676
+ return finalizeParts(drafts, input.protectedTags, input.pendingDropTagNumbers ?? new Set);
16340
16677
  }
16341
16678
  function sameMeasuredPrefix(baseline, current) {
16342
16679
  if (current.length < baseline.length)
16343
- return { valid: false, boundaryAdvanceU: 0 };
16680
+ return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
16344
16681
  let boundaryAdvanceU = 0;
16682
+ let queuedDropDeltaU = 0;
16345
16683
  for (let index = 0;index < baseline.length; index += 1) {
16346
16684
  const before = baseline[index];
16347
16685
  const after = current[index];
16348
16686
  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) {
16349
- return { valid: false, boundaryAdvanceU: 0 };
16687
+ return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
16350
16688
  }
16351
16689
  if (!before.protected && after.protected)
16352
- return { valid: false, boundaryAdvanceU: 0 };
16690
+ return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
16353
16691
  if (before.protected && !after.protected) {
16354
16692
  if (after.tagStatus !== "active")
16355
- return { valid: false, boundaryAdvanceU: 0 };
16356
- boundaryAdvanceU += after.tokens;
16693
+ return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
16694
+ boundaryAdvanceU += after.uTokens;
16695
+ } else if (before.queuedForDrop !== after.queuedForDrop) {
16696
+ if (before.tagStatus !== "active" || after.tagStatus !== "active")
16697
+ return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
16698
+ queuedDropDeltaU += after.uTokens - before.uTokens;
16357
16699
  } else if (before.uTokens !== after.uTokens) {
16358
- return { valid: false, boundaryAdvanceU: 0 };
16700
+ return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
16359
16701
  }
16360
16702
  }
16361
- return { valid: true, boundaryAdvanceU };
16703
+ return { valid: true, boundaryAdvanceU, queuedDropDeltaU };
16362
16704
  }
16363
16705
  function refreshPiTailHygieneBaseline(input) {
16364
16706
  const measured = measurePiTailHygiene(input);
@@ -16390,7 +16732,7 @@ function refreshPiTailHygieneBaseline(input) {
16390
16732
  };
16391
16733
  }
16392
16734
  let turnDeltaT = 0;
16393
- let turnDeltaU = prefix.boundaryAdvanceU;
16735
+ let turnDeltaU = prefix.boundaryAdvanceU + prefix.queuedDropDeltaU;
16394
16736
  for (let index = input.previous.baselineParts.length;index < measured.parts.length; index += 1) {
16395
16737
  const part = measured.parts[index];
16396
16738
  turnDeltaT += part.tokens;
@@ -16484,20 +16826,38 @@ function maybeChannel1ReminderForToolResult(args) {
16484
16826
  if (deltaTokens === 0)
16485
16827
  return null;
16486
16828
  state2.turnDeltaT += deltaTokens;
16829
+ if (state2.agentDropsAppliedThisPass)
16830
+ return null;
16831
+ const nudgeState = getChannel1NudgeState(db, sessionId);
16487
16832
  const decision = decideChannel1({
16488
16833
  ...state2,
16489
16834
  lastNudgeUndropped: getLastNudgeUndropped(db, sessionId),
16490
- lastNudgeLevel: getLastNudgeLevel(db, sessionId),
16835
+ lastNudgeLevel: nudgeState.level,
16491
16836
  hasRecentReduce: state2.reducedSinceRefresh
16492
16837
  });
16493
16838
  setLastNudgeUndropped(db, sessionId, decision.nextLastNudge);
16494
- setLastNudgeLevel(db, sessionId, decision.nextLastNudgeLevel);
16495
- if (!decision.fire)
16839
+ if (!decision.fire) {
16840
+ setChannel1NudgeState(db, sessionId, {
16841
+ level: decision.nextLastNudgeLevel,
16842
+ ordinal: decision.nextLastNudgeLevel === "" ? 0 : nudgeState.ordinal
16843
+ });
16496
16844
  return null;
16497
- return {
16845
+ }
16846
+ const sticky = shouldUseStickyChannel1Reminder({
16847
+ lastLevel: nudgeState.level,
16848
+ lastOrdinal: nudgeState.ordinal,
16849
+ level: decision.level,
16850
+ currentRealUserTurnCount: state2.realUserTurnCount
16851
+ });
16852
+ const block = {
16498
16853
  type: "text",
16499
- text: buildChannel1Reminder(decision.level, decision.undroppedTokens, state2.oldestReclaimableToolTags)
16854
+ text: buildChannel1Reminder(decision.level, decision.undroppedTokens, state2.usableWindow, state2.oldestReclaimableToolTags, sticky)
16500
16855
  };
16856
+ setChannel1NudgeState(db, sessionId, {
16857
+ level: decision.level,
16858
+ ordinal: state2.realUserTurnCount
16859
+ });
16860
+ return block;
16501
16861
  }
16502
16862
  var CHANNEL2_NUDGE_CUSTOM_TYPE = "magic-context:ceiling-nudge";
16503
16863
  function maybeDeliverChannel2Pi(pi, db, sessionId) {
@@ -16528,7 +16888,7 @@ function maybeDeliverChannel2Pi(pi, db, sessionId) {
16528
16888
  try {
16529
16889
  const message = {
16530
16890
  customType: CHANNEL2_NUDGE_CUSTOM_TYPE,
16531
- content: buildChannel2Reminder(undropped, baseline.oldestReclaimableToolTags),
16891
+ content: buildChannel2Reminder(undropped, baseline.usableWindow, baseline.oldestReclaimableToolTags),
16532
16892
  display: false,
16533
16893
  details: { kind: "channel-2-ceiling-nudge" }
16534
16894
  };
@@ -17694,6 +18054,11 @@ function injectM0M1Pi(state2, db, piMessages, entryIds, recomputeM1ThisPass = fa
17694
18054
  m0 = stripMemoryMuralBlock(m0);
17695
18055
  prependM0M1Messages(piMessages, m0, m1, muralWire);
17696
18056
  sessionLog(state2.sessionId, `injected m[0]/m[1] into Pi messages (${m0.length} + ${m1.length} bytes, materialized=${materialized}${decision.reason ? ` reason=${decision.reason}` : ""})`);
18057
+ const comparison = decision.mismatch;
18058
+ const systemHashPrev = comparison?.signal === "systemHash" && typeof comparison.cached === "string" ? comparison.cached : null;
18059
+ const systemHashNew = comparison?.signal === "systemHash" && typeof comparison.current === "string" ? comparison.current : null;
18060
+ const m0ModelKeyPrev = comparison?.signal === "modelKey" && typeof comparison.cached === "string" ? comparison.cached : null;
18061
+ const m0ModelKeyNew = comparison?.signal === "modelKey" && typeof comparison.current === "string" ? comparison.current : null;
17697
18062
  const memPath = memoryProjectPath(state2);
17698
18063
  const workspace = resolveWorkspaceRenderContextPi(state2, db);
17699
18064
  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;
@@ -17705,6 +18070,10 @@ function injectM0M1Pi(state2, db, piMessages, entryIds, recomputeM1ThisPass = fa
17705
18070
  skippedVisibleMessages,
17706
18071
  m0Materialized: materialized,
17707
18072
  m0Reason: decision.reason,
18073
+ systemHashPrev: materialized ? systemHashPrev : null,
18074
+ systemHashNew: materialized ? systemHashNew : null,
18075
+ m0ModelKeyPrev: materialized ? m0ModelKeyPrev : null,
18076
+ m0ModelKeyNew: materialized ? m0ModelKeyNew : null,
17708
18077
  m0Bytes: m0.length,
17709
18078
  m1Bytes: m1.length,
17710
18079
  contentionExhausted,
@@ -20860,7 +21229,7 @@ function buildReferenceBlocks(args) {
20860
21229
 
20861
21230
  // src/pi-historian-runner.ts
20862
21231
  var HISTORIAN_AGENT_NAME = "magic-context-historian";
20863
- var DEFAULT_HISTORIAN_TIMEOUT_MS2 = 120000;
21232
+ var DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
20864
21233
  var MAX_HISTORIAN_RETRIES = 2;
20865
21234
  var HISTORIAN_ALERT_COOLDOWN_MS = 60 * 1000;
20866
21235
  var lastHistorianAlertBySession = new Map;
@@ -20961,19 +21330,24 @@ async function runHistorianSubagentWithTransientRetries(args) {
20961
21330
  }
20962
21331
  return historianAbortResult(startedAt);
20963
21332
  }
20964
- function buildHistorianFallbackChain(primaryModel, fallbackModels, fallbackModelId) {
20965
- const seen = new Set;
20966
- if (primaryModel)
20967
- seen.add(primaryModel);
21333
+ function buildHistorianFallbackChain(primaryModel, primaryThinkingLevel, fallbackModels, fallbackModelId) {
21334
+ const seen = new Set([
21335
+ `${primaryModel}\x00${primaryThinkingLevel ?? ""}`
21336
+ ]);
20968
21337
  const chain = [];
20969
21338
  for (const candidate of fallbackModels ?? []) {
20970
- if (!candidate || seen.has(candidate))
21339
+ const entry = typeof candidate === "string" ? { model: candidate } : candidate;
21340
+ const key = `${entry.model}\x00${entry.qualifier ?? ""}`;
21341
+ if (!entry.model || seen.has(key))
20971
21342
  continue;
20972
- seen.add(candidate);
20973
- chain.push({ modelId: candidate, kind: "configured" });
21343
+ seen.add(key);
21344
+ chain.push({ entry, kind: "configured" });
20974
21345
  }
20975
- if (fallbackModelId && !seen.has(fallbackModelId)) {
20976
- chain.push({ modelId: fallbackModelId, kind: "session" });
21346
+ if (fallbackModelId) {
21347
+ const entry = { model: fallbackModelId };
21348
+ const key = `${entry.model}\x00`;
21349
+ if (!seen.has(key))
21350
+ chain.push({ entry, kind: "session" });
20977
21351
  }
20978
21352
  return chain;
20979
21353
  }
@@ -21292,11 +21666,11 @@ ${chunkText}`,
21292
21666
  validatedDraftText = repairResult.assistantText;
21293
21667
  }
21294
21668
  }
21295
- const fallbackChain = buildHistorianFallbackChain(historianModel, fallbackModels, fallbackModelId);
21669
+ const fallbackChain = buildHistorianFallbackChain(historianModel, thinkingLevel, fallbackModels, fallbackModelId);
21296
21670
  if (validatedPass.kind !== "ok" && !(validatedPass.kind === "spawn-failed" && validatedPass.reason === "abort") && fallbackChain.length > 0) {
21297
21671
  for (let i = 0;i < fallbackChain.length; i += 1) {
21298
21672
  const candidate = fallbackChain[i];
21299
- sessionLog(sessionId, `historian: escalating to ${candidate.kind === "session" ? "session-model last resort" : "configured fallback model"} ${candidate.modelId}`);
21673
+ sessionLog(sessionId, `historian: escalating to ${candidate.kind === "session" ? "session-model last resort" : "configured fallback model"} ${candidate.entry.model}`);
21300
21674
  const fbResult = await runHistorianSubagentWithTransientRetries({
21301
21675
  runner,
21302
21676
  sessionId,
@@ -21306,11 +21680,11 @@ ${chunkText}`,
21306
21680
  agent: HISTORIAN_AGENT_NAME,
21307
21681
  systemPrompt: historianSystemPrompt,
21308
21682
  userMessage: prompt,
21309
- model: candidate.modelId,
21683
+ model: candidate.entry.model,
21310
21684
  timeoutMs: historianTimeoutMs,
21311
21685
  cwd: directory,
21312
21686
  signal,
21313
- thinkingLevel,
21687
+ thinkingLevel: candidate.entry.qualifier,
21314
21688
  onProgress: buildProgressLogger("fallback"),
21315
21689
  accountingSessionId: sessionId,
21316
21690
  accountingSubagent: "historian"
@@ -24324,6 +24698,10 @@ function registerPiContextHandler(pi, baseOptions) {
24324
24698
  decision: schedulerDecision,
24325
24699
  materialized: result.materialized,
24326
24700
  materializeReason: normalizeMaterializeReason("pi", result.materializeReason, result.materialized),
24701
+ systemHashPrev: result.materialized ? result.injectionResult?.systemHashPrev ?? null : null,
24702
+ systemHashNew: result.materialized ? result.injectionResult?.systemHashNew ?? null : null,
24703
+ m0ModelKeyPrev: result.materialized ? result.injectionResult?.m0ModelKeyPrev ?? null : null,
24704
+ m0ModelKeyNew: result.materialized ? result.injectionResult?.m0ModelKeyNew ?? null : null,
24327
24705
  emergency: result.emergency,
24328
24706
  droppedTokens: result.droppedTokens,
24329
24707
  droppedCount: result.droppedCount,
@@ -24415,11 +24793,13 @@ function registerPiContextHandler(pi, baseOptions) {
24415
24793
  if (!options.compactionOff && !sessionMetaForCh1.isSubagent) {
24416
24794
  const tags = getTagsBySession(options.db, sessionId);
24417
24795
  const protectedTags = options.protectedTags ?? 20;
24796
+ const pendingDropTagNumbers = new Set(getPendingOps(options.db, sessionId).filter((operation) => operation.operation === "drop").map((operation) => operation.tagId));
24418
24797
  const stableId = (message) => message && typeof message === "object" ? result.postCommitEntryIdByRef.get(message) : undefined;
24419
24798
  const baseline = refreshPiTailHygieneBaseline({
24420
24799
  messages: outputMessages,
24421
24800
  tags,
24422
24801
  protectedTags,
24802
+ pendingDropTagNumbers,
24423
24803
  stableId,
24424
24804
  syntheticLeadingCount: result.syntheticLeadingCount,
24425
24805
  cacheBusting: result.bustedThisPass,
@@ -24430,7 +24810,17 @@ function registerPiContextHandler(pi, baseOptions) {
24430
24810
  const oldestReclaimableToolTags = getOldestActiveUnprotectedToolTags(options.db, sessionId, protectedTags);
24431
24811
  const channelState = {
24432
24812
  ...baseline,
24813
+ usableWindow: usageContextLimit ?? 0,
24814
+ realUserTurnCount: countRealPiUserMessages({
24815
+ messages: outputMessages,
24816
+ tags,
24817
+ protectedTags,
24818
+ pendingDropTagNumbers,
24819
+ stableId,
24820
+ syntheticLeadingCount: result.syntheticLeadingCount
24821
+ }),
24433
24822
  reducedSinceRefresh: false,
24823
+ agentDropsAppliedThisPass: result.agentDropsAppliedThisPass,
24434
24824
  oldestReclaimableToolTags
24435
24825
  };
24436
24826
  setPiChannel1Baseline(sessionId, channelState);
@@ -24455,6 +24845,7 @@ function registerPiContextHandler(pi, baseOptions) {
24455
24845
  messages: outputMessages,
24456
24846
  tags,
24457
24847
  protectedTags,
24848
+ pendingDropTagNumbers,
24458
24849
  stableId,
24459
24850
  syntheticLeadingCount: result.syntheticLeadingCount,
24460
24851
  expectedSignature: baseline.contentSignature
@@ -24984,6 +25375,7 @@ async function runCompactionOffPipeline(args) {
24984
25375
  droppedCount: 0,
24985
25376
  emergency: false,
24986
25377
  bustedThisPass: injectionResult?.m0Materialized === true,
25378
+ agentDropsAppliedThisPass: false,
24987
25379
  targetCount: 0,
24988
25380
  reasoningWatermark: args.sessionMeta.clearedReasoningThroughTag ?? 0,
24989
25381
  activeTags: [],
@@ -25425,7 +25817,11 @@ async function runPipeline(args) {
25425
25817
  injectionResult = preFoldInjectionResult?.m0Materialized ? {
25426
25818
  ...wireInjectionResult,
25427
25819
  m0Materialized: true,
25428
- m0Reason: preFoldInjectionResult.m0Reason ?? wireInjectionResult.m0Reason
25820
+ m0Reason: preFoldInjectionResult.m0Reason ?? wireInjectionResult.m0Reason,
25821
+ systemHashPrev: preFoldInjectionResult.systemHashPrev ?? null,
25822
+ systemHashNew: preFoldInjectionResult.systemHashNew ?? null,
25823
+ m0ModelKeyPrev: preFoldInjectionResult.m0ModelKeyPrev ?? null,
25824
+ m0ModelKeyNew: preFoldInjectionResult.m0ModelKeyNew ?? null
25429
25825
  } : wireInjectionResult;
25430
25826
  if (args.temporalAwareness && injectionResult.skippedVisibleMessages > 0) {
25431
25827
  const firstRetainedMessage = args.messages[injectionResult.syntheticLeadingCount];
@@ -25553,6 +25949,7 @@ async function runPipeline(args) {
25553
25949
  droppedCount,
25554
25950
  emergency,
25555
25951
  bustedThisPass,
25952
+ agentDropsAppliedThisPass: pendingOpsDidMutate,
25556
25953
  targetCount: targets.size,
25557
25954
  reasoningWatermark: args.sessionMeta.clearedReasoningThroughTag ?? 0,
25558
25955
  activeTags,
@@ -25845,6 +26242,7 @@ async function runValidatedHistorianPass(args) {
25845
26242
  const firstRun = await runHistorianPrompt({
25846
26243
  ...args,
25847
26244
  dumpLabel: `${args.dumpLabelBase}-initial`,
26245
+ modelOverride: args.model,
25848
26246
  agentId: args.agentId
25849
26247
  });
25850
26248
  if (!firstRun.ok || !firstRun.result) {
@@ -25873,6 +26271,7 @@ async function runValidatedHistorianPass(args) {
25873
26271
  ...args,
25874
26272
  prompt: repairPrompt,
25875
26273
  dumpLabel: `${args.dumpLabelBase}-repair`,
26274
+ modelOverride: args.model,
25876
26275
  agentId: args.agentId
25877
26276
  });
25878
26277
  if (!repairRun.ok || !repairRun.result) {
@@ -25913,7 +26312,8 @@ async function runEditorPassOrFallback(args) {
25913
26312
  timeoutMs: args.timeoutMs,
25914
26313
  dumpLabel: `${args.dumpLabelBase}-editor`,
25915
26314
  agentId: HISTORIAN_EDITOR_AGENT,
25916
- parentInvocationId: args.draftInvocationId ?? null
26315
+ parentInvocationId: args.draftInvocationId ?? null,
26316
+ modelOverride: args.model
25917
26317
  });
25918
26318
  if (!editorRun.ok || !editorRun.result) {
25919
26319
  sessionLog(args.parentSessionId, "historian two-pass: editor call failed", {
@@ -25966,7 +26366,7 @@ async function runHistorianPrompt(args) {
25966
26366
  });
25967
26367
  };
25968
26368
  try {
25969
- sessionLog(parentSessionId, `historian: creating child session (agent=${agentId}, model=${modelOverride ? `${modelOverride.providerID}/${modelOverride.modelID}` : `agent:${agentId}`})`);
26369
+ sessionLog(parentSessionId, `historian: creating child session (agent=${toModelEntry(modelOverride)?.model ?? `agent:${agentId}`})`);
25970
26370
  const createResponse = await createChildSessionWithFence({
25971
26371
  client,
25972
26372
  db,
@@ -25990,7 +26390,7 @@ async function runHistorianPrompt(args) {
25990
26390
  query: { directory: sessionDirectory },
25991
26391
  body: {
25992
26392
  agent: agentId,
25993
- ...modelOverride ? { model: modelOverride } : {},
26393
+ ...modelBodyField(modelOverride),
25994
26394
  parts: [{ type: "text", text: prompt, synthetic: true }]
25995
26395
  }
25996
26396
  }, {
@@ -26051,22 +26451,30 @@ async function runHistorianPrompt(args) {
26051
26451
  error: `Historian failed while processing this session: ${desc.brief}`
26052
26452
  };
26053
26453
  } finally {
26054
- if (agentSessionId && outcomeOk && !shouldKeepSubagents()) {
26055
- await client.session.delete({ path: { id: agentSessionId } }).catch((e) => {
26056
- sessionLog(parentSessionId, "compartment agent: session cleanup failed", getErrorMessage(e));
26057
- });
26058
- } else if (agentSessionId && (!outcomeOk || shouldKeepSubagents())) {
26059
- sessionLog(parentSessionId, `historian: KEEPING child session ${agentSessionId} (${outcomeOk ? "keep_subagents" : "failed"}) — not deleted`);
26454
+ if (agentSessionId) {
26455
+ const retentionReason = shouldKeepSubagents() ? "keep_subagents" : outcomeOk ? "prompt completed; cleanup deferred to the age-gated sweep" : "failed; cleanup deferred to the age-gated sweep";
26456
+ sessionLog(parentSessionId, `historian: KEEPING child session ${agentSessionId} (${retentionReason}) — not deleted inline`);
26060
26457
  }
26061
26458
  }
26062
26459
  }
26063
26460
  async function runFallbackHistorianPass(args) {
26064
26461
  const seen = new Set;
26065
26462
  const chain = [];
26066
- for (const candidate of [...args.fallbackModels ?? [], args.fallbackModelId ?? ""]) {
26067
- if (!candidate || seen.has(candidate))
26463
+ const primary = toModelEntry(args.model);
26464
+ for (const candidateInput of [
26465
+ ...args.fallbackModels ?? [],
26466
+ ...args.fallbackModelId ? [{ model: args.fallbackModelId }] : []
26467
+ ]) {
26468
+ const candidate = toModelEntry(candidateInput);
26469
+ if (!candidate)
26068
26470
  continue;
26069
- seen.add(candidate);
26471
+ const key = `${candidate.model}\x00${candidate.qualifier ?? ""}`;
26472
+ if (!candidate.model || seen.has(key))
26473
+ continue;
26474
+ if (primary?.model === candidate.model && primary.qualifier === candidate.qualifier) {
26475
+ continue;
26476
+ }
26477
+ seen.add(key);
26070
26478
  chain.push(candidate);
26071
26479
  }
26072
26480
  if (chain.length === 0) {
@@ -26074,9 +26482,9 @@ async function runFallbackHistorianPass(args) {
26074
26482
  }
26075
26483
  let lastError = args.error;
26076
26484
  for (let i = 0;i < chain.length; i += 1) {
26077
- const modelId = chain[i];
26078
- const modelOverride = parseModelOverride(modelId);
26079
- if (!modelOverride)
26485
+ const modelOverride = chain[i];
26486
+ const modelId = modelOverride.model;
26487
+ if (!parseModelOverride(modelId))
26080
26488
  continue;
26081
26489
  const isSessionModelLastResort = modelId === args.fallbackModelId && i === chain.length - 1;
26082
26490
  sessionLog(args.parentSessionId, `compartment agent: retrying historian with ${modelId} (${isSessionModelLastResort ? "session-model last resort" : "configured fallback"} ${i + 1}/${chain.length})`);
@@ -26405,6 +26813,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
26405
26813
  sequenceOffset: candidateCompartments.length,
26406
26814
  dumpLabelBase: `recomp-${sessionId}-${chunk.startIndex}-${chunk.endIndex}-pass-${passCount + 1}`,
26407
26815
  timeoutMs: historianTimeoutMs,
26816
+ model: deps.model,
26408
26817
  fallbackModelId: deps.fallbackModelId,
26409
26818
  fallbackModels: deps.fallbackModels,
26410
26819
  twoPass: deps.historianTwoPass,
@@ -26825,6 +27234,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
26825
27234
  sequenceOffset: candidateCompartments.length,
26826
27235
  dumpLabelBase: `partial-recomp-${sessionId}-${chunk.startIndex}-${chunk.endIndex}-pass-${passCount + 1}`,
26827
27236
  timeoutMs: historianTimeoutMs,
27237
+ model: deps.model,
26828
27238
  fallbackModelId: deps.fallbackModelId,
26829
27239
  fallbackModels: deps.fallbackModels,
26830
27240
  twoPass: deps.historianTwoPass,
@@ -27016,11 +27426,11 @@ function createPiHistorianClient(args) {
27016
27426
  agent: "magic-context-historian",
27017
27427
  systemPrompt: args.systemPrompt,
27018
27428
  userMessage: promptText,
27019
- model: modelOverride ?? args.model,
27429
+ model: modelOverride?.model ?? args.model,
27020
27430
  fallbackModels: modelOverride ? undefined : args.fallbackModels,
27021
27431
  timeoutMs: args.timeoutMs,
27022
27432
  cwd: args.directory,
27023
- thinkingLevel: args.thinkingLevel,
27433
+ thinkingLevel: modelOverride ? modelOverride.qualifier : args.thinkingLevel,
27024
27434
  accountingSessionId: args.accountingSessionId,
27025
27435
  accountingSubagent: "recomp"
27026
27436
  });
@@ -27068,7 +27478,8 @@ function readBodyModel(body) {
27068
27478
  return;
27069
27479
  const { providerID, modelID } = model;
27070
27480
  if (typeof providerID === "string" && providerID.length > 0 && typeof modelID === "string" && modelID.length > 0) {
27071
- return `${providerID}/${modelID}`;
27481
+ const qualifier = typeof body.variant === "string" && body.variant.length > 0 ? body.variant : undefined;
27482
+ return qualifier ? { model: `${providerID}/${modelID}`, qualifier } : { model: `${providerID}/${modelID}` };
27072
27483
  }
27073
27484
  return;
27074
27485
  }
@@ -27678,13 +28089,17 @@ async function runPiMemoryMigration(deps) {
27678
28089
  const prompt = buildMemoryMigrationPrompt(memories);
27679
28090
  const modelChain = [];
27680
28091
  const seenModels = new Set;
27681
- for (const m of [
27682
- deps.primaryModel ?? deps.model,
27683
- ...deps.fallbackModels ?? []
28092
+ for (const candidate of [
28093
+ {
28094
+ model: deps.primaryModel ?? deps.model,
28095
+ ...deps.primaryModel ? {} : deps.thinkingLevel ? { qualifier: deps.thinkingLevel } : {}
28096
+ },
28097
+ ...(deps.fallbackModels ?? []).map((fallback) => typeof fallback === "string" ? { model: fallback } : fallback)
27684
28098
  ]) {
27685
- if (m && !seenModels.has(m)) {
27686
- seenModels.add(m);
27687
- modelChain.push(m);
28099
+ const key = `${candidate.model}\x00${candidate.qualifier ?? ""}`;
28100
+ if (candidate.model && !seenModels.has(key)) {
28101
+ seenModels.add(key);
28102
+ modelChain.push(candidate);
27688
28103
  }
27689
28104
  }
27690
28105
  let parsed = null;
@@ -27692,17 +28107,17 @@ async function runPiMemoryMigration(deps) {
27692
28107
  for (let i = 0;i < modelChain.length; i += 1) {
27693
28108
  const model = modelChain[i];
27694
28109
  if (i > 0) {
27695
- sessionLog(deps.sessionId, `memory-migration: escalating to configured fallback model ${model} (${i}/${modelChain.length - 1})`);
28110
+ sessionLog(deps.sessionId, `memory-migration: escalating to configured fallback model ${model.model} (${i}/${modelChain.length - 1})`);
27696
28111
  }
27697
28112
  const result = await deps.runner.run({
27698
28113
  agent: "magic-context-historian",
27699
28114
  systemPrompt: withMigrationLanguageDirective(MIGRATION_SYSTEM_PROMPT2, deps.language),
27700
28115
  userMessage: prompt,
27701
- model,
28116
+ model: model.model,
27702
28117
  fallbackModels: undefined,
27703
28118
  timeoutMs: deps.timeoutMs ?? 5 * 60 * 1000,
27704
28119
  cwd: deps.directory,
27705
- thinkingLevel: deps.thinkingLevel,
28120
+ thinkingLevel: model.qualifier,
27706
28121
  accountingSessionId: deps.sessionId,
27707
28122
  accountingSubagent: "recomp"
27708
28123
  });
@@ -28096,7 +28511,7 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
28096
28511
  "### Cache TTL",
28097
28512
  `- Configured: ${meta.cacheTtl}`,
28098
28513
  `- Last response: ${meta.lastResponseTime > 0 ? `${Math.round(elapsed / 1000)}s ago` : "never"}`,
28099
- `- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never expires (always-warm lane)" : `${Math.round(remainingMs / 1000)}s`}`,
28514
+ `- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never (MC never assumes expiry — external cache-keep)" : `${Math.round(remainingMs / 1000)}s`}`,
28100
28515
  `- Queue will auto-execute: ${cacheExpired ? "yes (cache expired)" : ttlMs === Number.POSITIVE_INFINITY ? `when context >= ${executeThresholdPercentage}%` : `when TTL expires or context >= ${executeThresholdPercentage}%`}`,
28101
28516
  "",
28102
28517
  "### Execute Threshold",
@@ -28216,7 +28631,7 @@ ${c.content}
28216
28631
  // package.json
28217
28632
  var package_default = {
28218
28633
  name: "@cortexkit/pi-magic-context",
28219
- version: "0.38.0",
28634
+ version: "0.39.0",
28220
28635
  type: "module",
28221
28636
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
28222
28637
  main: "dist/index.js",
@@ -28247,7 +28662,7 @@ var package_default = {
28247
28662
  build: "tsc -p ../retina-local-fs/tsconfig.build.json && rm -f dist/index.js dist/subagent-entry.js dist/*-*.js && bun build src/index.ts src/subagent-entry.ts --outdir dist --target node --format esm --splitting --external @earendil-works/pi-coding-agent --external @earendil-works/pi-tui --external @huggingface/transformers --external node:sqlite",
28248
28663
  "build:e2e-argv": "bun build src/subagent-runner.ts --outfile ../../tests/docker/.generated/subagent-runner-e2e.mjs --target node --format esm --external node:sqlite",
28249
28664
  typecheck: "tsc -p ../retina-local-fs/tsconfig.build.json && tsc --noEmit",
28250
- test: "bun test",
28665
+ test: "bun install --frozen-lockfile && bun test",
28251
28666
  lint: "biome check src",
28252
28667
  "lint:fix": "biome check --write src",
28253
28668
  format: "biome format --write src",
@@ -28411,7 +28826,7 @@ function renderInner(s, theme, innerWidth) {
28411
28826
  lines.push(`Upgrade: ${theme.fg("accent", "up to date")}`);
28412
28827
  }
28413
28828
  lines.push(`Pending drops: ${s.pendingOpsCount}`);
28414
- 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`}`);
28829
+ 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`}`);
28415
28830
  lines.push("");
28416
28831
  lines.push(theme.fg("muted", "Tags"));
28417
28832
  lines.push(`Active ${s.activeTags} (~${formatBytes(s.activeBytes)}) · Dropped ${s.droppedTags} · Total ${s.totalTags}`);
@@ -29566,12 +29981,13 @@ function resolveHistorianFromConfig(config) {
29566
29981
  const historian = config.historian;
29567
29982
  if (historian?.disable === true)
29568
29983
  return;
29569
- const model = historian?.model?.trim();
29570
- if (!model || model.length === 0)
29984
+ const resolved = resolveHistorianModel(config, "pi");
29985
+ const model = resolved.primary?.model;
29986
+ if (!model)
29571
29987
  return;
29572
29988
  const historianContextLimit = resolveHistorianContextLimit(model);
29573
29989
  const historianChunkTokens = deriveHistorianChunkTokens(historianContextLimit);
29574
- const fallbackModels = resolveFallbackChain(historian?.fallback_models);
29990
+ const fallbackModels = resolved.fallbacks;
29575
29991
  return {
29576
29992
  runner: new PiSubagentRunner,
29577
29993
  model,
@@ -29579,7 +29995,7 @@ function resolveHistorianFromConfig(config) {
29579
29995
  historianChunkTokens,
29580
29996
  timeoutMs: config.historian_timeout_ms,
29581
29997
  twoPass: historian?.two_pass === true,
29582
- thinkingLevel: historian?.thinking_level,
29998
+ thinkingLevel: resolved.primary?.qualifier,
29583
29999
  executeThresholdPercentage: config.execute_threshold_percentage,
29584
30000
  executeThresholdTokens: config.execute_threshold_tokens,
29585
30001
  commitClusterTrigger: config.commit_cluster_trigger,
@@ -30069,6 +30485,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
30069
30485
  embeddingConfig: bootProjectDeps.config.embedding,
30070
30486
  memoryEnabled: bootProjectDeps.config.memory.enabled,
30071
30487
  retinaHandoff: bootProjectDeps.config.smart_notes.retina_handoff,
30488
+ mural: bootProjectDeps.config.mural,
30072
30489
  language: bootProjectDeps.config.language,
30073
30490
  gitCommitIndexing: bootProjectDeps.config.memory.git_commit_indexing,
30074
30491
  onAdjunctsRefreshNeeded: signalPiSystemPromptRefreshForProject
@@ -30447,16 +30864,16 @@ function formatExecuteThresholdForLog(value) {
30447
30864
  return overrides.length > 0 ? `${base} (${overrides.join(", ")})` : base;
30448
30865
  }
30449
30866
  export {
30450
- signalPiDeferredCompactionMarkerDrain,
30451
- resolveSidekickFromConfig,
30452
- resolveHistorianFromConfig,
30453
- resolveDreamerFromConfig,
30454
- persistPiPressureFromMessageEnd,
30455
- persistPiMessageEndModelMeta,
30456
- handlePiSessionBeforeCompact,
30457
- src_default as default,
30458
- capturePiTodowriteMessageIfCompatible,
30459
- capturePiTodowriteArgsIfCompatible,
30867
+ __test,
30460
30868
  canonicalPiModelKey,
30461
- __test
30869
+ capturePiTodowriteArgsIfCompatible,
30870
+ capturePiTodowriteMessageIfCompatible,
30871
+ src_default as default,
30872
+ handlePiSessionBeforeCompact,
30873
+ persistPiMessageEndModelMeta,
30874
+ persistPiPressureFromMessageEnd,
30875
+ resolveDreamerFromConfig,
30876
+ resolveHistorianFromConfig,
30877
+ resolveSidekickFromConfig,
30878
+ signalPiDeferredCompactionMarkerDrain
30462
30879
  };