@cortexkit/pi-magic-context 0.35.1 → 0.36.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
@@ -128,6 +128,7 @@ import {
128
128
  getCompartmentsByEndMessageId,
129
129
  getContextStoreUuid,
130
130
  getDatabasePath,
131
+ getDroppedTagsByNumbers,
131
132
  getEmbeddingCoverageStatus,
132
133
  getEmergencyInputSample,
133
134
  getErrorMessage,
@@ -246,6 +247,7 @@ import {
246
247
  normalizeText,
247
248
  normalizeTodoStateJson,
248
249
  normalizeVerificationFiles,
250
+ ompModelRefToCanonical,
249
251
  openDatabase,
250
252
  openDatabaseAsync,
251
253
  parkGitSweepNonIndexable,
@@ -256,6 +258,7 @@ import {
256
258
  peelLeadingMcTagNotation,
257
259
  persistCachedM0,
258
260
  piModelRefToCanonical,
261
+ preloadTokenizer,
259
262
  prependTag,
260
263
  primeInMemoryTailRawMessageCache,
261
264
  primeTailRawMessageCache,
@@ -309,6 +312,7 @@ import {
309
312
  resolveGitTopLevel,
310
313
  resolveLimit,
311
314
  resolveModelConfigOrDefault,
315
+ resolveModelRefForOmp,
312
316
  resolveModelRefForPi,
313
317
  resolveMuralWire,
314
318
  resolvePiStableId,
@@ -373,7 +377,7 @@ import {
373
377
  withMigrationLanguageDirective,
374
378
  withRawMessageProvider,
375
379
  withRawSessionMessageCache
376
- } from "./index-gxftx2a4.js";
380
+ } from "./index-zxgbtsnj.js";
377
381
  import {
378
382
  pushNotification
379
383
  } from "./index-hw34xmzk.js";
@@ -385,7 +389,7 @@ import {
385
389
  log,
386
390
  sessionLog,
387
391
  setHarness
388
- } from "./index-zmyx6nf5.js";
392
+ } from "./index-npnqc564.js";
389
393
  import {
390
394
  __require,
391
395
  __toESM
@@ -1948,6 +1952,7 @@ function createCloneFilter(entries) {
1948
1952
  const rawMessages = convertEntriesToRawMessages([...entries]);
1949
1953
  const rawOrdinalById = new Map(rawMessages.map((message) => [message.id, message.ordinal]));
1950
1954
  const validStateIds = new Set(rawOrdinalById.keys());
1955
+ const validOrdinals = new Set(rawOrdinalById.values());
1951
1956
  for (const entry of entries) {
1952
1957
  const id = entryId(entry);
1953
1958
  if (id)
@@ -1957,6 +1962,8 @@ function createCloneFilter(entries) {
1957
1962
  return {
1958
1963
  resolveBoundaryOrdinal: (id) => rawOrdinalById.get(id),
1959
1964
  includeMessageId,
1965
+ copySessionNotesAndFacts: true,
1966
+ mapOrdinal: (ordinal) => validOrdinals.has(ordinal) ? ordinal : undefined,
1960
1967
  includeTag: (tag) => {
1961
1968
  if (tag.type === "tool") {
1962
1969
  return typeof tag.toolOwnerMessageId === "string" && includeMessageId(tag.toolOwnerMessageId);
@@ -2034,7 +2041,7 @@ async function handlePiCloneSessionStart(event, ctx, deps) {
2034
2041
  if (result.pendingMarkerMigrated) {
2035
2042
  deps.signalPendingMarker(destinationSessionId);
2036
2043
  }
2037
- writeLog(`[magic-context][pi] clone-inheritance: migrated compartments=${result.compartmentsCopied} tags=${result.tagsCopied} source=${sourceSessionId} dest=${destinationSessionId} reason=fork`);
2044
+ writeLog(`[magic-context][pi] clone-inheritance: migrated compartments=${result.compartmentsCopied} tags=${result.tagsCopied} notes=${result.notesCopied} facts=${result.factsCopied} source=${sourceSessionId} dest=${destinationSessionId} reason=fork`);
2038
2045
  return result;
2039
2046
  } catch (error) {
2040
2047
  writeLog(`[magic-context][pi] clone-inheritance: failed source=${sourceSessionId} dest=${destinationSessionId} stage=${stage} error=${error instanceof Error ? error.message : String(error)}; run /ctx-wrapup to rebuild, or re-clone`);
@@ -2064,7 +2071,13 @@ function isEmptySidekickResult(text) {
2064
2071
 
2065
2072
  // src/subagent-runner.ts
2066
2073
  import * as childProcess from "node:child_process";
2067
- import { existsSync as existsSync3, mkdtempSync, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
2074
+ import {
2075
+ existsSync as existsSync3,
2076
+ mkdtempSync,
2077
+ readFileSync as readFileSync2,
2078
+ rmSync,
2079
+ writeFileSync as writeFileSync2
2080
+ } from "node:fs";
2068
2081
  import { createRequire } from "node:module";
2069
2082
  import { homedir, tmpdir } from "node:os";
2070
2083
  import {
@@ -2087,13 +2100,14 @@ var state = {
2087
2100
  noticeEmitted: false,
2088
2101
  failure: null
2089
2102
  };
2090
- function recordStaleFence(persistedVersion, supportedVersion) {
2103
+ function recordStaleFence(persistedVersion, supportedVersion, reason = "newer_schema") {
2091
2104
  state.consecutiveFailures += 1;
2092
2105
  state.totalFailures += 1;
2093
2106
  const latched = state.consecutiveFailures >= STALE_CHILD_SPAWN_LATCH_THRESHOLD;
2094
2107
  state.latched ||= latched;
2095
2108
  const failure = {
2096
2109
  failureClass: STALE_CHILD_SPAWN_FAILURE,
2110
+ reason,
2097
2111
  persistedVersion,
2098
2112
  supportedVersion,
2099
2113
  consecutiveFailures: state.consecutiveFailures,
@@ -2120,7 +2134,7 @@ function probeChildSpawnFence(db) {
2120
2134
  return recordStaleFence(persistedVersion, LATEST_SUPPORTED_VERSION);
2121
2135
  }
2122
2136
  } catch {
2123
- return { allowSpawn: true };
2137
+ return recordStaleFence(LATEST_SUPPORTED_VERSION, LATEST_SUPPORTED_VERSION, "read_error");
2124
2138
  }
2125
2139
  state.consecutiveFailures = 0;
2126
2140
  state.latched = false;
@@ -2263,7 +2277,61 @@ function resolveSubagentEntryPath() {
2263
2277
  var SUBAGENT_ENTRY_PATH = resolveSubagentEntryPath();
2264
2278
  var TERMINAL_DRAIN_GRACE_MS = 2000;
2265
2279
  var MAGIC_CONTEXT_PI_SUBAGENT_ENV = "MAGIC_CONTEXT_PI_SUBAGENT";
2266
- var PI_AGENT_SETTINGS_DIR = join2(homedir(), ".pi", "agent");
2280
+ function packageRootIsOmp(packageRoot) {
2281
+ try {
2282
+ const manifest = JSON.parse(readFileSync2(join2(packageRoot, "package.json"), "utf-8"));
2283
+ return manifest.name === "@oh-my-pi/pi-coding-agent";
2284
+ } catch {
2285
+ return false;
2286
+ }
2287
+ }
2288
+ function expandHomePath(value) {
2289
+ if (value === "~")
2290
+ return homedir();
2291
+ if (value.startsWith("~/") || value.startsWith("~\\")) {
2292
+ return resolvePath(homedir(), value.slice(2));
2293
+ }
2294
+ return resolvePath(value);
2295
+ }
2296
+ function isOmpHostProcess() {
2297
+ const execName = basename(process.execPath).toLowerCase();
2298
+ if (/^omp(?:\.exe)?$/.test(execName))
2299
+ return true;
2300
+ const packageOverride = process.env.PI_PACKAGE_DIR?.trim();
2301
+ if (packageOverride && packageRootIsOmp(expandHomePath(packageOverride))) {
2302
+ return true;
2303
+ }
2304
+ let current = process.argv[1] ? dirname(resolvePath(process.argv[1])) : "";
2305
+ while (current) {
2306
+ if (packageRootIsOmp(current))
2307
+ return true;
2308
+ const parent = dirname(current);
2309
+ if (parent === current)
2310
+ break;
2311
+ current = parent;
2312
+ }
2313
+ return false;
2314
+ }
2315
+ function normalizedOmpProfile() {
2316
+ const raw = (process.env.OMP_PROFILE ?? process.env.PI_PROFILE)?.trim();
2317
+ return raw && raw !== "default" && /^[a-z0-9][a-z0-9._-]{0,63}$/.test(raw) ? raw : undefined;
2318
+ }
2319
+ function getHostAgentSettingsDir() {
2320
+ if (!isOmpHostProcess())
2321
+ return join2(homedir(), ".pi", "agent");
2322
+ const configRoot = join2(homedir(), process.env.PI_CONFIG_DIR?.trim() || ".omp");
2323
+ const profile = normalizedOmpProfile();
2324
+ if (profile)
2325
+ return join2(configRoot, "profiles", profile, "agent");
2326
+ const configured = process.env.PI_CODING_AGENT_DIR?.trim();
2327
+ return configured ? resolvePath(configured) : join2(configRoot, "agent");
2328
+ }
2329
+ function modelRefToCanonicalForHost(ref) {
2330
+ return isOmpHostProcess() ? ompModelRefToCanonical(ref) : piModelRefToCanonical(ref);
2331
+ }
2332
+ function resolveModelRefForHost(ref) {
2333
+ return isOmpHostProcess() ? resolveModelRefForOmp(ref) : resolveModelRefForPi(ref);
2334
+ }
2267
2335
  var configuredSubagentExtensions;
2268
2336
  function configurePiSubagentExtensions(extensions) {
2269
2337
  configuredSubagentExtensions = extensions?.slice();
@@ -2271,7 +2339,7 @@ function configurePiSubagentExtensions(extensions) {
2271
2339
  function resolveSubagentExtensionEntry(entry) {
2272
2340
  const trimmed = entry.trim();
2273
2341
  const isNpmSource = trimmed.startsWith("npm:");
2274
- return !isNpmSource && !isAbsolute(trimmed) ? resolvePath(PI_AGENT_SETTINGS_DIR, trimmed) : trimmed;
2342
+ return !isNpmSource && !isAbsolute(trimmed) ? resolvePath(getHostAgentSettingsDir(), trimmed) : trimmed;
2275
2343
  }
2276
2344
  var PI_READ_ONLY_BUILTINS = ["read", "grep", "find", "ls"];
2277
2345
  var PI_AFT_READ_TOOLS = ["aft_outline", "aft_zoom", "aft_search"];
@@ -2309,6 +2377,32 @@ var STRICT_TOOL_ALLOWLIST_ENTRIES = [
2309
2377
  ];
2310
2378
  var STRICT_TOOL_ALLOWLIST = new Map(STRICT_TOOL_ALLOWLIST_ENTRIES);
2311
2379
  var ZERO_TOOL_PROMPT_REQUIRED_AGENTS = new Set(STRICT_TOOL_ALLOWLIST_ENTRIES.filter(([, tools]) => tools.length === 0).map(([agent]) => agent));
2380
+ var OMP_TOOL_ALIASES = {
2381
+ find: "glob",
2382
+ ls: "glob"
2383
+ };
2384
+ var OMP_ALLOWLISTABLE_TOOLS = {
2385
+ read: true,
2386
+ grep: true,
2387
+ glob: true,
2388
+ bash: true,
2389
+ edit: true,
2390
+ write: true
2391
+ };
2392
+ function resolveHostToolAllowlist(tools, ompHost = isOmpHostProcess()) {
2393
+ if (!ompHost)
2394
+ return tools;
2395
+ const resolved = [];
2396
+ const seen = new Set;
2397
+ for (const tool of tools) {
2398
+ const mapped = OMP_TOOL_ALIASES[tool] ?? tool;
2399
+ if (OMP_ALLOWLISTABLE_TOOLS[mapped] !== true || seen.has(mapped))
2400
+ continue;
2401
+ seen.add(mapped);
2402
+ resolved.push(mapped);
2403
+ }
2404
+ return resolved;
2405
+ }
2312
2406
  function inferAccountingSubagent(agent) {
2313
2407
  if (agent.includes("sidekick"))
2314
2408
  return "sidekick";
@@ -2882,11 +2976,11 @@ function replaceProviderPrefix(ref, provider) {
2882
2976
  function resolveProviderModelAttempt(model) {
2883
2977
  if (typeof model !== "string" || model.length === 0)
2884
2978
  return;
2885
- const canonicalRef = piModelRefToCanonical(model);
2979
+ const canonicalRef = modelRefToCanonicalForHost(model);
2886
2980
  const canonicalProvider = providerPrefix(canonicalRef);
2887
2981
  if (!canonicalProvider)
2888
2982
  return;
2889
- const translatedRef = resolveModelRefForPi(canonicalRef);
2983
+ const translatedRef = resolveModelRefForHost(canonicalRef);
2890
2984
  const translatedProvider = providerPrefix(translatedRef);
2891
2985
  const cachedProvider = PI_PROVIDER_FORM_CACHE.get(canonicalProvider);
2892
2986
  if (!translatedProvider || translatedProvider === canonicalProvider && cachedProvider === undefined) {
@@ -2906,14 +3000,14 @@ function isProviderCredentialFailure(result, attempt) {
2906
3000
  }
2907
3001
  var PROMPT_ARGV_MAX_BYTES = 96 * 1024;
2908
3002
  function buildArgs(options, opts) {
3003
+ const ompHost = isOmpHostProcess();
2909
3004
  const args = [
2910
3005
  "--print",
2911
3006
  "--mode",
2912
3007
  "json",
2913
3008
  "--no-session",
2914
3009
  "--no-skills",
2915
- "--no-prompt-templates",
2916
- "--no-context-files"
3010
+ ...ompHost ? ["--no-rules"] : ["--no-prompt-templates", "--no-context-files"]
2917
3011
  ];
2918
3012
  if (opts?.disableDiscoveredExtensions || opts?.subagentExtensions !== undefined) {
2919
3013
  args.push("--no-extensions");
@@ -2936,8 +3030,9 @@ function buildArgs(options, opts) {
2936
3030
  sessionLog(options.accountingSessionId ?? "pi-subagent", `Pi subagent agent "${options.agent}" has no strict tool allow-list; forcing --no-tools`);
2937
3031
  args.push("--no-tools");
2938
3032
  } else {
2939
- if (strictTools.length > 0) {
2940
- args.push("--tools", strictTools.join(","));
3033
+ const hostTools = resolveHostToolAllowlist(strictTools, ompHost);
3034
+ if (hostTools.length > 0) {
3035
+ args.push("--tools", hostTools.join(","));
2941
3036
  } else {
2942
3037
  args.push("--no-tools");
2943
3038
  }
@@ -2946,7 +3041,7 @@ function buildArgs(options, opts) {
2946
3041
  args.push("--system-prompt", opts.systemPromptPath);
2947
3042
  }
2948
3043
  if (typeof options.model === "string" && options.model.length > 0) {
2949
- args.push("--model", opts?.modelRef ?? resolveModelRefForPi(options.model));
3044
+ args.push("--model", opts?.modelRef ?? resolveModelRefForHost(options.model));
2950
3045
  }
2951
3046
  if (options.thinkingLevel) {
2952
3047
  args.push("--thinking", options.thinkingLevel);
@@ -3206,16 +3301,16 @@ function claimExpectedState(db, expected) {
3206
3301
  WHERE id = ? AND type = 'smart' AND status = 'pending'
3207
3302
  AND content = ? AND surface_condition IS ? AND updated_at = ?${statusClause}`).run(...params).changes > 0;
3208
3303
  }
3209
- function getDueCompiledSmartNoteChecks(db, projectPath, now, limit) {
3210
- return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && (note.checkQuarantinedUntil === null || note.checkQuarantinedUntil <= now) && (note.checkNextDueAt === null || note.checkNextDueAt <= now)).sort((a, b) => (a.checkNextDueAt ?? 0) - (b.checkNextDueAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
3304
+ function getDueCompiledSmartNoteChecks(db, projectPath, now, limit, retinaHandoff = false) {
3305
+ return getPendingSmartNotes(db, projectPath).filter((note) => !retinaHandoff || note.compileStatus !== "compiled").map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && (note.checkQuarantinedUntil === null || note.checkQuarantinedUntil <= now) && (note.checkNextDueAt === null || note.checkNextDueAt <= now)).sort((a, b) => (a.checkNextDueAt ?? 0) - (b.checkNextDueAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
3211
3306
  }
3212
- function getSmartNotesNeedingCompilation(db, projectPath, now, limit) {
3213
- return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => (note.checkNextDueAt === null || note.checkNextDueAt <= now) && (note.checkStatus === "uncompiled" || note.checkStatus === "failing" || note.compiledCheck === null || note.policyVersion !== SMART_NOTE_CHECK_POLICY_VERSION)).sort((a, b) => a.createdAt - b.createdAt || a.id - b.id).slice(0, Math.max(1, limit));
3307
+ function getSmartNotesNeedingCompilation(db, projectPath, now, limit, retinaHandoff = false) {
3308
+ return getPendingSmartNotes(db, projectPath).filter((note) => !retinaHandoff || note.compileStatus !== "compiled").map(toSmartNote).filter((note) => (note.checkNextDueAt === null || note.checkNextDueAt <= now) && (note.checkStatus === "uncompiled" || note.checkStatus === "failing" || note.compiledCheck === null || note.policyVersion !== SMART_NOTE_CHECK_POLICY_VERSION)).sort((a, b) => a.createdAt - b.createdAt || a.id - b.id).slice(0, Math.max(1, limit));
3214
3309
  }
3215
- function getStaleCompiledSmartNotes(db, projectPath, now, limit) {
3310
+ function getStaleCompiledSmartNotes(db, projectPath, now, limit, retinaHandoff = false) {
3216
3311
  const staleBefore = now - SMART_NOTE_CHECK_MAX_STALENESS_MS;
3217
3312
  const livenessBefore = now - SMART_NOTE_CHECK_LIVENESS_RECHECK_MS;
3218
- return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && note.checkFalseSinceAt !== null && note.checkFalseSinceAt <= staleBefore && (note.checkLastLivenessAt === null || note.checkLastLivenessAt <= livenessBefore)).sort((a, b) => (a.checkFalseSinceAt ?? 0) - (b.checkFalseSinceAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
3313
+ return getPendingSmartNotes(db, projectPath).filter((note) => !retinaHandoff || note.compileStatus !== "compiled").map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && note.checkFalseSinceAt !== null && note.checkFalseSinceAt <= staleBefore && (note.checkLastLivenessAt === null || note.checkLastLivenessAt <= livenessBefore)).sort((a, b) => (a.checkFalseSinceAt ?? 0) - (b.checkFalseSinceAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
3219
3314
  }
3220
3315
  function storeCompiledSmartNoteCheck(db, args) {
3221
3316
  db.prepare(`UPDATE notes
@@ -3666,7 +3761,7 @@ async function sendIgnoredMessageNow(client, sessionId, text, params, forcePersi
3666
3761
  queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
3667
3762
  return "queued";
3668
3763
  }
3669
- const { waitForSafeNotificationTarget } = await import("./safe-notification-target-ng8ygena.js");
3764
+ const { waitForSafeNotificationTarget } = await import("./safe-notification-target-0s6j4m9f.js");
3670
3765
  if (await waitForSafeNotificationTarget(client, sessionId) === "skip") {
3671
3766
  sessionLog(sessionId, "notification skipped (session not titled yet)");
3672
3767
  return "skipped";
@@ -3743,25 +3838,31 @@ async function sendIgnoredMessage(client, sessionId, text, params, forcePersist
3743
3838
 
3744
3839
  // ../plugin/src/hooks/magic-context/child-session-spawn.ts
3745
3840
  var STALE_PLUGIN_RESTART_NOTICE = "Magic Context: plugin build is older than its database — restart OpenCode";
3746
- async function surfaceStalePluginBuild(args) {
3841
+ var SCHEMA_PROBE_FAILURE_NOTICE = `Magic Context: unable to verify the database schema before spawning a child — run ${FAIL_CLOSED_DOCTOR_COMMAND}`;
3842
+ async function surfaceSchemaFenceFailure(args, failure) {
3747
3843
  if (!args.parentSessionId)
3748
3844
  return;
3749
- try {
3750
- if (args.db) {
3845
+ const notice = failure.reason === "read_error" ? SCHEMA_PROBE_FAILURE_NOTICE : STALE_PLUGIN_RESTART_NOTICE;
3846
+ if (args.db) {
3847
+ try {
3751
3848
  updateSessionMeta(args.db, args.parentSessionId, {
3752
- lastTransformError: STALE_PLUGIN_RESTART_NOTICE
3849
+ lastTransformError: notice
3753
3850
  });
3851
+ } catch (error) {
3852
+ sessionLog(args.parentSessionId, `schema-fence warning persistence failed: ${error instanceof Error ? error.message : String(error)}`);
3754
3853
  }
3854
+ }
3855
+ try {
3755
3856
  pushNotification("toast", {
3756
3857
  title: "Magic Context",
3757
- message: STALE_PLUGIN_RESTART_NOTICE,
3858
+ message: notice,
3758
3859
  variant: "error",
3759
3860
  duration: 1e4
3760
3861
  }, args.parentSessionId);
3761
3862
  pushNotification("action", { action: "refresh-sidebar" }, args.parentSessionId);
3762
- await sendIgnoredMessage(args.client, args.parentSessionId, STALE_PLUGIN_RESTART_NOTICE, args.notificationParams ?? {}, true);
3863
+ await sendIgnoredMessage(args.client, args.parentSessionId, notice, args.notificationParams ?? {}, true);
3763
3864
  } catch (error) {
3764
- sessionLog(args.parentSessionId, `stale plugin-build warning delivery failed: ${error instanceof Error ? error.message : String(error)}`);
3865
+ sessionLog(args.parentSessionId, `schema-fence warning delivery failed: ${error instanceof Error ? error.message : String(error)}`);
3765
3866
  }
3766
3867
  }
3767
3868
  async function createChildSessionWithFence(args) {
@@ -3774,7 +3875,7 @@ async function createChildSessionWithFence(args) {
3774
3875
  if (args.onFenceLatched)
3775
3876
  await args.onFenceLatched(verdict.failure);
3776
3877
  else
3777
- await surfaceStalePluginBuild(args);
3878
+ await surfaceSchemaFenceFailure(args, verdict.failure);
3778
3879
  }
3779
3880
  return null;
3780
3881
  }
@@ -4166,7 +4267,7 @@ function parseFields(json) {
4166
4267
  }
4167
4268
 
4168
4269
  // ../plugin/src/features/magic-context/mural/compress-cues.ts
4169
- import { createHash as createHash2 } from "node:crypto";
4270
+ import { createHash as createHash3 } from "node:crypto";
4170
4271
 
4171
4272
  // ../plugin/src/features/magic-context/dreamer/storage-dream-state.ts
4172
4273
  var getDreamStateStatements = new WeakMap;
@@ -4215,13 +4316,15 @@ function rowKeys(leaseKey) {
4215
4316
  return {
4216
4317
  holder: "dreaming_lease_holder",
4217
4318
  heartbeat: "dreaming_lease_heartbeat",
4218
- expiry: "dreaming_lease_expiry"
4319
+ expiry: "dreaming_lease_expiry",
4320
+ generation: "dreaming_lease_generation"
4219
4321
  };
4220
4322
  }
4221
4323
  return {
4222
4324
  holder: `lease:${leaseKey}:holder`,
4223
4325
  heartbeat: `lease:${leaseKey}:heartbeat`,
4224
- expiry: `lease:${leaseKey}:expiry`
4326
+ expiry: `lease:${leaseKey}:expiry`,
4327
+ generation: `lease:${leaseKey}:generation`
4225
4328
  };
4226
4329
  }
4227
4330
  function getLeaseExpiry(db, keys) {
@@ -4239,6 +4342,13 @@ function isLeaseActive(db, leaseKey = DREAMING_LEASE_KEY) {
4239
4342
  function getLeaseHolder(db, leaseKey = DREAMING_LEASE_KEY) {
4240
4343
  return getDreamState(db, rowKeys(leaseKey).holder);
4241
4344
  }
4345
+ function getLeaseGeneration(db, leaseKey = DREAMING_LEASE_KEY) {
4346
+ const value = getDreamState(db, rowKeys(leaseKey).generation);
4347
+ if (!value)
4348
+ return null;
4349
+ const generation = Number(value);
4350
+ return Number.isSafeInteger(generation) && generation > 0 ? generation : null;
4351
+ }
4242
4352
  function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_KEY) {
4243
4353
  const keys = rowKeys(leaseKey);
4244
4354
  const holder = getDreamState(db, keys.holder);
@@ -4250,6 +4360,9 @@ function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_
4250
4360
  const expiry = Number(expiryStr);
4251
4361
  return Number.isFinite(expiry) && expiry >= Date.now();
4252
4362
  }
4363
+ function leaseOwnershipMatches(db, expectedHolder, expectedGeneration, leaseKey = DREAMING_LEASE_KEY) {
4364
+ return getLeaseGeneration(db, leaseKey) === expectedGeneration && peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey);
4365
+ }
4253
4366
  function runImmediate(db, body) {
4254
4367
  db.exec("BEGIN IMMEDIATE");
4255
4368
  let committed = false;
@@ -4266,26 +4379,30 @@ function runImmediate(db, body) {
4266
4379
  }
4267
4380
  }
4268
4381
  }
4269
- function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
4382
+ function acquireLeaseWithAcquisition(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
4270
4383
  const keys = rowKeys(leaseKey);
4271
4384
  return runImmediate(db, () => {
4272
- if (isLeaseActive(db, leaseKey)) {
4273
- const existingHolder = getLeaseHolder(db, leaseKey);
4274
- if (existingHolder && existingHolder !== holderId) {
4275
- return false;
4276
- }
4385
+ const existingHolder = getLeaseHolder(db, leaseKey);
4386
+ if (isLeaseActive(db, leaseKey) && existingHolder && existingHolder !== holderId) {
4387
+ return null;
4277
4388
  }
4278
4389
  const now = Date.now();
4390
+ const priorGeneration = getLeaseGeneration(db, leaseKey) ?? 0;
4391
+ const generation = existingHolder === holderId ? Math.max(1, priorGeneration) : priorGeneration + 1;
4279
4392
  setDreamState(db, keys.holder, holderId);
4280
4393
  setDreamState(db, keys.heartbeat, String(now));
4281
4394
  setDreamState(db, keys.expiry, String(now + LEASE_DURATION_MS));
4282
- return true;
4395
+ setDreamState(db, keys.generation, String(generation));
4396
+ return { acquiredAt: now, generation };
4283
4397
  });
4284
4398
  }
4285
- function renewLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
4399
+ function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
4400
+ return acquireLeaseWithAcquisition(db, holderId, leaseKey) !== null;
4401
+ }
4402
+ function renewLease(db, holderId, leaseKey = DREAMING_LEASE_KEY, expectedGeneration) {
4286
4403
  const keys = rowKeys(leaseKey);
4287
4404
  return runImmediate(db, () => {
4288
- if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey)) {
4405
+ if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey) || expectedGeneration !== undefined && getLeaseGeneration(db, leaseKey) !== expectedGeneration) {
4289
4406
  return false;
4290
4407
  }
4291
4408
  const now = Date.now();
@@ -4303,9 +4420,12 @@ function runLeaseGuardedWrite(db, holderId, leaseKey, fn) {
4303
4420
  });
4304
4421
  }
4305
4422
  var LEASE_HEARTBEAT_INTERVAL_MS = 60 * 1000;
4306
- function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalMs = LEASE_HEARTBEAT_INTERVAL_MS) {
4423
+ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalOrAcquisition = LEASE_HEARTBEAT_INTERVAL_MS) {
4424
+ const intervalMs = typeof intervalOrAcquisition === "number" ? intervalOrAcquisition : LEASE_HEARTBEAT_INTERVAL_MS;
4425
+ const acquisition = typeof intervalOrAcquisition === "number" ? undefined : intervalOrAcquisition;
4307
4426
  let lost = false;
4308
- let lastConfirmedAt = Date.now();
4427
+ let expectedGeneration = acquisition?.generation ?? getLeaseGeneration(db, leaseKey);
4428
+ let lastConfirmedAt = acquisition?.acquiredAt ?? Date.now();
4309
4429
  const declareLost = (reason) => {
4310
4430
  if (lost)
4311
4431
  return;
@@ -4316,15 +4436,25 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalMs = LEASE_
4316
4436
  if (lost)
4317
4437
  return;
4318
4438
  try {
4319
- if (renewLease(db, holderId, leaseKey)) {
4439
+ if (renewLease(db, holderId, leaseKey, expectedGeneration === null ? undefined : expectedGeneration)) {
4320
4440
  lastConfirmedAt = Date.now();
4321
4441
  return;
4322
4442
  }
4443
+ if (expectedGeneration !== null && getLeaseGeneration(db, leaseKey) !== expectedGeneration) {
4444
+ declareLost("lease generation changed — another holder acquired it");
4445
+ return;
4446
+ }
4323
4447
  if (Date.now() - lastConfirmedAt > LEASE_DURATION_MS) {
4324
4448
  declareLost("lease lapsed past TTL — another holder may have run");
4325
4449
  return;
4326
4450
  }
4327
- if (acquireLease(db, holderId, leaseKey)) {
4451
+ const reacquired = acquireLeaseWithAcquisition(db, holderId, leaseKey);
4452
+ if (reacquired) {
4453
+ if (expectedGeneration !== null && reacquired.generation !== expectedGeneration) {
4454
+ declareLost("lease generation changed during reacquisition");
4455
+ return;
4456
+ }
4457
+ expectedGeneration = reacquired.generation;
4328
4458
  lastConfirmedAt = Date.now();
4329
4459
  return;
4330
4460
  }
@@ -4393,6 +4523,16 @@ function assertManifestCoversExactly(ids, expectedIds, rootName) {
4393
4523
  }
4394
4524
 
4395
4525
  // ../plugin/src/features/magic-context/dreamer/module-apply.ts
4526
+ class DreamerModuleBusyError extends Error {
4527
+ state;
4528
+ transient = true;
4529
+ constructor(state2) {
4530
+ super(`Rust memory authority is ${state2}; dreamer mutation deferred until authority settles.`);
4531
+ this.state = state2;
4532
+ this.name = "DreamerModuleBusyError";
4533
+ }
4534
+ }
4535
+
4396
4536
  class DreamerModuleFailureError extends Error {
4397
4537
  transient = true;
4398
4538
  constructor(operation, cause) {
@@ -4414,9 +4554,12 @@ async function resolveDreamerModuleRoute(args) {
4414
4554
  projectRoot: args.projectRoot,
4415
4555
  domain: "memories"
4416
4556
  });
4417
- if (result.authority?.state !== "MODULE")
4557
+ const authority = result.authority;
4558
+ if (authority?.state === "DRAINING")
4559
+ throw new DreamerModuleBusyError(authority.state);
4560
+ if (authority?.state !== "MODULE")
4418
4561
  return;
4419
- const generation = result.authority.generation;
4562
+ const generation = authority.generation;
4420
4563
  if (typeof generation !== "number")
4421
4564
  throw new Error("Rust authority status omitted generation");
4422
4565
  return {
@@ -4450,6 +4593,68 @@ function getModuleMemoryIdentities(db, projectIdentity, contextIds) {
4450
4593
  ] : []));
4451
4594
  }
4452
4595
 
4596
+ // ../plugin/src/features/magic-context/dreamer/provider-output-failure.ts
4597
+ import { createHash as createHash2 } from "node:crypto";
4598
+ var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
4599
+
4600
+ class DreamerProviderOutputFailureError extends Error {
4601
+ fingerprint;
4602
+ outputTokens;
4603
+ reasoningTokens;
4604
+ transient = true;
4605
+ constructor(fingerprint, outputTokens, reasoningTokens, responseText) {
4606
+ const preview = responseText.trim().replace(/\s+/g, " ").slice(0, 160);
4607
+ super(`dreamer provider-outage completion (output_tokens=${outputTokens}, reasoning_tokens=${reasoningTokens}): ${JSON.stringify(preview)}`);
4608
+ this.fingerprint = fingerprint;
4609
+ this.outputTokens = outputTokens;
4610
+ this.reasoningTokens = reasoningTokens;
4611
+ this.name = "DreamerProviderOutputFailureError";
4612
+ }
4613
+ }
4614
+ function finiteTokenCount(value) {
4615
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
4616
+ }
4617
+ function completionShape(value) {
4618
+ if (!isRecord(value))
4619
+ return null;
4620
+ const info = isRecord(value.info) ? value.info : value;
4621
+ if (info.role !== "assistant")
4622
+ return null;
4623
+ const time = isRecord(info.time) ? info.time : null;
4624
+ const tokens = isRecord(info.tokens) ? info.tokens : null;
4625
+ return {
4626
+ createdAt: typeof time?.created === "number" ? time.created : 0,
4627
+ finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : null,
4628
+ error: info.error,
4629
+ outputTokens: finiteTokenCount(tokens?.output),
4630
+ reasoningTokens: finiteTokenCount(tokens?.reasoning)
4631
+ };
4632
+ }
4633
+ function latestAssistantCompletion(messages) {
4634
+ if (!Array.isArray(messages))
4635
+ return null;
4636
+ let latest = null;
4637
+ for (const message of messages) {
4638
+ const completion = completionShape(message);
4639
+ if (completion && (!latest || completion.createdAt >= latest.createdAt))
4640
+ latest = completion;
4641
+ }
4642
+ return latest;
4643
+ }
4644
+ function providerOutputFailureFromInvalidManifest(messages, responseText) {
4645
+ const completion = latestAssistantCompletion(messages);
4646
+ if (completion?.finish?.toLowerCase() !== "stop")
4647
+ return null;
4648
+ if (completion.error != null || completion.outputTokens === null || completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS || completion.reasoningTokens !== 0) {
4649
+ return null;
4650
+ }
4651
+ const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
4652
+ if (!normalized)
4653
+ return null;
4654
+ const fingerprint = createHash2("sha256").update(normalized).digest("hex").slice(0, 16);
4655
+ return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
4656
+ }
4657
+
4453
4658
  // ../plugin/src/features/magic-context/mural/compress-cues-prompt.ts
4454
4659
  var CUE_BUDGET_HIGH = 90;
4455
4660
  var CUE_BUDGET_LOW = 50;
@@ -4622,7 +4827,7 @@ async function runCompressCues(args) {
4622
4827
  chunks.push(candidates.slice(i, i + COMPRESS_CUES_CHUNK_SIZE));
4623
4828
  }
4624
4829
  const abortController = new AbortController;
4625
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
4830
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
4626
4831
  try {
4627
4832
  let consecutiveTimeouts = 0;
4628
4833
  let timeoutStreakElapsedMs = [];
@@ -4717,7 +4922,14 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
4717
4922
  const text = extractLatestAssistantText(messages);
4718
4923
  if (!text)
4719
4924
  throw new Error("compress-cues returned no output");
4720
- parseCuesManifest(text);
4925
+ try {
4926
+ parseCuesManifest(text);
4927
+ } catch (error) {
4928
+ const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
4929
+ if (providerFailure)
4930
+ throw providerFailure;
4931
+ throw error;
4932
+ }
4721
4933
  return text;
4722
4934
  }
4723
4935
  });
@@ -4725,7 +4937,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
4725
4937
  } catch (error) {
4726
4938
  const desc = describeError(error);
4727
4939
  log(`[dreamer] compress-cues chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
4728
- if (signal.aborted)
4940
+ if (signal.aborted || error instanceof DreamerProviderOutputFailureError)
4729
4941
  throw error;
4730
4942
  return {
4731
4943
  compressed: 0,
@@ -4833,7 +5045,7 @@ async function applyCuesThroughModule(args, chunk, manifestText, signal) {
4833
5045
  log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason}; rejection ${rejectionCount}/${CUE_REJECTION_LATCH_THRESHOLD})`);
4834
5046
  }
4835
5047
  }
4836
- const commandId = `mural-cues:${route.moduleCommandId}:${createHash2("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
5048
+ const commandId = `mural-cues:${route.moduleCommandId}:${createHash3("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
4837
5049
  let response;
4838
5050
  try {
4839
5051
  response = await route.moduleClient.call({
@@ -5275,7 +5487,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
5275
5487
  const heartbeat = startLeaseHeartbeat(args.db, args.holderId, leaseKey, (reason) => {
5276
5488
  log(`[dreamer] user-memories: lease lost (${reason}) — aborting`);
5277
5489
  abortController.abort();
5278
- });
5490
+ }, args.leaseAcquisition);
5279
5491
  try {
5280
5492
  const createResponse = await createChildSessionWithFence({
5281
5493
  client: args.client,
@@ -5398,7 +5610,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
5398
5610
  }
5399
5611
 
5400
5612
  // ../plugin/src/features/magic-context/dreamer/classify.ts
5401
- import { createHash as createHash3 } from "node:crypto";
5613
+ import { createHash as createHash4 } from "node:crypto";
5402
5614
 
5403
5615
  // ../plugin/src/plugin/rust-tool-backends.ts
5404
5616
  function isRustAuthorityDrainingError(error) {
@@ -5782,7 +5994,7 @@ async function runClassify(args) {
5782
5994
  chunks.push(toClassify.slice(i, i + CLASSIFY_CHUNK_SIZE));
5783
5995
  }
5784
5996
  const abortController = new AbortController;
5785
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
5997
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
5786
5998
  try {
5787
5999
  for (let i = 0;i < chunks.length; i += 1) {
5788
6000
  const remainingMs = Math.max(0, args.deadline - Date.now());
@@ -5862,7 +6074,14 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
5862
6074
  const text = extractLatestAssistantText(messages);
5863
6075
  if (!text)
5864
6076
  throw new Error("classify returned no output");
5865
- parseClassifyManifest(text);
6077
+ try {
6078
+ parseClassifyManifest(text);
6079
+ } catch (error) {
6080
+ const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
6081
+ if (providerFailure)
6082
+ throw providerFailure;
6083
+ throw error;
6084
+ }
5866
6085
  return text;
5867
6086
  }
5868
6087
  });
@@ -5873,7 +6092,7 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
5873
6092
  const desc = describeError(failure);
5874
6093
  log(`[dreamer] classify chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
5875
6094
  recordInvocation(args, startedAt, { status: "failed", error: failure });
5876
- if (moduleRoute || signal.aborted)
6095
+ if (moduleRoute || signal.aborted || failure instanceof DreamerProviderOutputFailureError)
5877
6096
  throw failure;
5878
6097
  return { classified: 0, changed: 0 };
5879
6098
  } finally {
@@ -5902,7 +6121,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
5902
6121
  v: 1,
5903
6122
  session_id: args.moduleSessionId,
5904
6123
  task: "classify",
5905
- command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash3("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
6124
+ command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash4("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
5906
6125
  authority_generation: args.moduleAuthorityGeneration,
5907
6126
  payload: {
5908
6127
  prompt_body: prompt,
@@ -6540,7 +6759,7 @@ function throwIfAborted2(signal) {
6540
6759
  }
6541
6760
 
6542
6761
  // ../plugin/src/features/magic-context/smart-notes/compiler.ts
6543
- import { createHash as createHash4 } from "node:crypto";
6762
+ import { createHash as createHash5 } from "node:crypto";
6544
6763
 
6545
6764
  // ../plugin/src/features/magic-context/smart-notes/compiler-prompt.ts
6546
6765
  var SMART_NOTE_COMPILER_SYSTEM_PROMPT = `You are the Magic Context smart-note compiler for the magic-context system.
@@ -6964,7 +7183,7 @@ function manifestAdvisoryWarnings(code, manifest) {
6964
7183
  return warnings;
6965
7184
  }
6966
7185
  function hashCheck(surfaceCondition, compiledCheck, manifest, checkCron) {
6967
- return createHash4("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
7186
+ return createHash5("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
6968
7187
  }
6969
7188
  function extractJsonObject(output) {
6970
7189
  const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
@@ -7055,7 +7274,7 @@ var MAX_FAILURES_BEFORE_REAUTHOR = 3;
7055
7274
  async function runDueCompiledSmartNoteChecks(args) {
7056
7275
  const startedAt = Date.now();
7057
7276
  const now = args.now ?? startedAt;
7058
- const due = getDueCompiledSmartNoteChecks(args.db, args.projectIdentity, now, args.maxChecks ?? DEFAULT_MAX_CHECKS);
7277
+ const due = getDueCompiledSmartNoteChecks(args.db, args.projectIdentity, now, args.maxChecks ?? DEFAULT_MAX_CHECKS, args.retinaHandoff);
7059
7278
  let ran = 0;
7060
7279
  let surfaced = 0;
7061
7280
  let failed = 0;
@@ -7185,7 +7404,8 @@ async function evaluateSmartNotes(args) {
7185
7404
  const projectRoot = args.sessionDirectory ?? args.projectIdentity;
7186
7405
  const moduleBridge = getModuleNoteEvaluationBridge(args.projectIdentity);
7187
7406
  await moduleBridge?.sync();
7188
- const pendingAtStart = getPendingSmartNotes(args.db, args.projectIdentity).length;
7407
+ const pendingNotes = () => getPendingSmartNotes(args.db, args.projectIdentity).filter((note) => !args.retinaHandoff || note.compileStatus !== "compiled");
7408
+ const pendingAtStart = pendingNotes().length;
7189
7409
  if (pendingAtStart === 0) {
7190
7410
  log("[dreamer] smart notes: no pending notes");
7191
7411
  return { surfaced: 0, pending: 0, ran: false };
@@ -7204,12 +7424,12 @@ async function evaluateSmartNotes(args) {
7204
7424
  leaseAbortController.abort(new Error("Dream lease lost during smart notes"));
7205
7425
  log("[dreamer] smart notes: lease lost — aborting");
7206
7426
  args.onLeaseLost?.("smart notes");
7207
- });
7427
+ }, args.leaseAcquisition);
7208
7428
  let surfaced = 0;
7209
7429
  let didWork = false;
7210
7430
  try {
7211
7431
  if (moduleBridge) {
7212
- const candidates2 = getPendingSmartNotes(args.db, args.projectIdentity).slice(0, MAX_COMPILE_PER_RUN);
7432
+ const candidates2 = pendingNotes().slice(0, MAX_COMPILE_PER_RUN);
7213
7433
  for (const note of candidates2) {
7214
7434
  if (Date.now() >= args.deadline)
7215
7435
  break;
@@ -7230,7 +7450,7 @@ async function evaluateSmartNotes(args) {
7230
7450
  surfaced += 1;
7231
7451
  }
7232
7452
  await moduleBridge.sync();
7233
- const pending2 = getPendingSmartNotes(args.db, args.projectIdentity).length;
7453
+ const pending2 = pendingNotes().length;
7234
7454
  return { surfaced, pending: pending2, ran: didWork };
7235
7455
  }
7236
7456
  const dueRun = await runDueCompiledSmartNoteChecks({
@@ -7240,11 +7460,12 @@ async function evaluateSmartNotes(args) {
7240
7460
  maxChecks: 10,
7241
7461
  sweepBudgetMs: 1e4,
7242
7462
  leaseHeld,
7243
- signal: leaseAbortController.signal
7463
+ signal: leaseAbortController.signal,
7464
+ retinaHandoff: args.retinaHandoff
7244
7465
  });
7245
7466
  surfaced += dueRun.surfaced;
7246
7467
  didWork ||= dueRun.ran > 0;
7247
- const candidates = getSmartNotesNeedingCompilation(args.db, args.projectIdentity, Date.now(), MAX_COMPILE_PER_RUN);
7468
+ const candidates = getSmartNotesNeedingCompilation(args.db, args.projectIdentity, Date.now(), MAX_COMPILE_PER_RUN, args.retinaHandoff);
7248
7469
  for (const note of candidates) {
7249
7470
  if (Date.now() >= args.deadline)
7250
7471
  break;
@@ -7254,7 +7475,7 @@ async function evaluateSmartNotes(args) {
7254
7475
  if (compiled)
7255
7476
  surfaced += 1;
7256
7477
  }
7257
- const stale = getStaleCompiledSmartNotes(args.db, args.projectIdentity, Date.now(), MAX_FALLBACK_PER_RUN);
7478
+ const stale = getStaleCompiledSmartNotes(args.db, args.projectIdentity, Date.now(), MAX_FALLBACK_PER_RUN, args.retinaHandoff);
7258
7479
  for (const note of stale) {
7259
7480
  if (Date.now() >= args.deadline)
7260
7481
  break;
@@ -7264,7 +7485,7 @@ async function evaluateSmartNotes(args) {
7264
7485
  if (met)
7265
7486
  surfaced += 1;
7266
7487
  }
7267
- const fallbackNotes = getPendingSmartNotes(args.db, args.projectIdentity).filter((note) => note.checkStatus === "fallback").slice(0, MAX_FALLBACK_PER_RUN);
7488
+ const fallbackNotes = pendingNotes().filter((note) => note.checkStatus === "fallback").slice(0, MAX_FALLBACK_PER_RUN);
7268
7489
  for (const note of fallbackNotes) {
7269
7490
  if (Date.now() >= args.deadline)
7270
7491
  break;
@@ -7515,7 +7736,7 @@ Output exactly JSON: {"met": false}`;
7515
7736
  }
7516
7737
 
7517
7738
  // ../plugin/src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
7518
- import { existsSync as existsSync5, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
7739
+ import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
7519
7740
  import { join as join3 } from "node:path";
7520
7741
 
7521
7742
  // ../plugin/src/features/magic-context/dreamer/protected-regions.ts
@@ -7620,7 +7841,7 @@ function snapshotMaintainDocsFiles(docsDir) {
7620
7841
  const path4 = join3(docsDir, name);
7621
7842
  try {
7622
7843
  if (existsSync5(path4)) {
7623
- snapshot.set(name, readFileSync2(path4, "utf8"));
7844
+ snapshot.set(name, readFileSync3(path4, "utf8"));
7624
7845
  }
7625
7846
  } catch {}
7626
7847
  }
@@ -7630,7 +7851,7 @@ function enforceMaintainDocsProtectedRegions(args) {
7630
7851
  for (const [fileName, original] of args.snapshot) {
7631
7852
  const path4 = join3(args.docsDir, fileName);
7632
7853
  try {
7633
- const current = readFileSync2(path4, "utf8");
7854
+ const current = readFileSync3(path4, "utf8");
7634
7855
  const { text, violated } = enforceProtectedRegions(original, current);
7635
7856
  if (!violated) {
7636
7857
  continue;
@@ -7644,7 +7865,7 @@ function enforceMaintainDocsProtectedRegions(args) {
7644
7865
  }
7645
7866
 
7646
7867
  // ../plugin/src/features/magic-context/dreamer/map-memories.ts
7647
- import { createHash as createHash5 } from "node:crypto";
7868
+ import { createHash as createHash6 } from "node:crypto";
7648
7869
 
7649
7870
  // ../plugin/src/features/magic-context/dreamer/map-memories-prompt.ts
7650
7871
  import { existsSync as existsSync6, statSync } from "node:fs";
@@ -7761,7 +7982,7 @@ async function mapMemories(args) {
7761
7982
  }
7762
7983
  result.remaining = inputs.length;
7763
7984
  const abortController = new AbortController;
7764
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
7985
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
7765
7986
  try {
7766
7987
  for (let i = 0;i < batches.length; i += 1) {
7767
7988
  const remainingMs = Math.max(0, args.deadline - Date.now());
@@ -7905,7 +8126,7 @@ async function applyBatchMappings(args, batch, manifestText) {
7905
8126
  memory_project: args.projectIdentity,
7906
8127
  context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
7907
8128
  authority_generation: args.moduleRoute.moduleAuthorityGeneration,
7908
- command_id: `${args.moduleRoute.moduleCommandId}:${createHash5("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
8129
+ command_id: `${args.moduleRoute.moduleCommandId}:${createHash6("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
7909
8130
  rows
7910
8131
  }
7911
8132
  }
@@ -8130,7 +8351,7 @@ async function promotePrimers(args) {
8130
8351
  const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => {
8131
8352
  leaseLost = true;
8132
8353
  log("[dreamer] primers: lease lost during promote-primers — aborting");
8133
- });
8354
+ }, args.leaseAcquisition);
8134
8355
  try {
8135
8356
  assertLeaseHeld("prune start");
8136
8357
  result.pruned = pruneExpiredPrimerCandidatesForProject(args.db, args.projectIdentity, Date.now(), PRIMER_CANDIDATE_TTL_MS);
@@ -8362,7 +8583,7 @@ async function refreshPrimers(args) {
8362
8583
  if (primers.length === 0)
8363
8584
  return result;
8364
8585
  const abortController = new AbortController;
8365
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
8586
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
8366
8587
  try {
8367
8588
  for (let i = 0;i < primers.length; i += 1) {
8368
8589
  const primer = primers[i];
@@ -8965,68 +9186,6 @@ function insertDreamRun(db, run) {
8965
9186
  // ../plugin/src/features/magic-context/dreamer/verify.ts
8966
9187
  import { createHash as createHash7 } from "node:crypto";
8967
9188
 
8968
- // ../plugin/src/features/magic-context/dreamer/provider-output-failure.ts
8969
- import { createHash as createHash6 } from "node:crypto";
8970
- var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
8971
-
8972
- class DreamerProviderOutputFailureError extends Error {
8973
- fingerprint;
8974
- outputTokens;
8975
- reasoningTokens;
8976
- transient = true;
8977
- constructor(fingerprint, outputTokens, reasoningTokens, responseText) {
8978
- const preview = responseText.trim().replace(/\s+/g, " ").slice(0, 160);
8979
- super(`verify provider-outage completion (output_tokens=${outputTokens}, reasoning_tokens=${reasoningTokens}): ${JSON.stringify(preview)}`);
8980
- this.fingerprint = fingerprint;
8981
- this.outputTokens = outputTokens;
8982
- this.reasoningTokens = reasoningTokens;
8983
- this.name = "DreamerProviderOutputFailureError";
8984
- }
8985
- }
8986
- function finiteTokenCount(value) {
8987
- return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
8988
- }
8989
- function completionShape(value) {
8990
- if (!isRecord(value))
8991
- return null;
8992
- const info = isRecord(value.info) ? value.info : value;
8993
- if (info.role !== "assistant")
8994
- return null;
8995
- const time = isRecord(info.time) ? info.time : null;
8996
- const tokens = isRecord(info.tokens) ? info.tokens : null;
8997
- return {
8998
- createdAt: typeof time?.created === "number" ? time.created : 0,
8999
- finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : null,
9000
- error: info.error,
9001
- outputTokens: finiteTokenCount(tokens?.output),
9002
- reasoningTokens: finiteTokenCount(tokens?.reasoning)
9003
- };
9004
- }
9005
- function latestAssistantCompletion(messages) {
9006
- if (!Array.isArray(messages))
9007
- return null;
9008
- let latest = null;
9009
- for (const message of messages) {
9010
- const completion = completionShape(message);
9011
- if (completion && (!latest || completion.createdAt >= latest.createdAt))
9012
- latest = completion;
9013
- }
9014
- return latest;
9015
- }
9016
- function providerOutputFailureFromInvalidManifest(messages, responseText) {
9017
- const completion = latestAssistantCompletion(messages);
9018
- if (completion?.finish?.toLowerCase() !== "stop")
9019
- return null;
9020
- if (completion.error != null || completion.outputTokens === null || completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS || completion.reasoningTokens !== 0) {
9021
- return null;
9022
- }
9023
- const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
9024
- if (!normalized)
9025
- return null;
9026
- const fingerprint = createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
9027
- return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
9028
- }
9029
-
9030
9189
  // ../plugin/src/features/magic-context/dreamer/verify-gate.ts
9031
9190
  import path5 from "node:path";
9032
9191
  function minOf(values) {
@@ -9271,7 +9430,7 @@ async function runVerify(args) {
9271
9430
  batches.push(gate.inScope.slice(i, i + VERIFY_BATCH_SIZE));
9272
9431
  }
9273
9432
  const abortController = new AbortController;
9274
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
9433
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
9275
9434
  let consecutiveProviderFailures = 0;
9276
9435
  let priorProviderFailureFingerprint = null;
9277
9436
  let lastProviderFailure = null;
@@ -9607,6 +9766,9 @@ function createDreamTaskExecutor(deps) {
9607
9766
  return async (config, ctx) => {
9608
9767
  const { db, projectIdentity, holderId, leaseKey } = ctx;
9609
9768
  const startedAt = Date.now();
9769
+ const leaseAcquisition = ctx.leaseAcquisition ?? acquireLeaseWithAcquisition(db, holderId, leaseKey) ?? (() => {
9770
+ throw new Error("Dream lease unavailable during executor setup");
9771
+ })();
9610
9772
  const deadline = startedAt + config.timeoutMinutes * 60 * 1000;
9611
9773
  const backlogAtStart = getDreamTaskBacklog(db, projectIdentity, config.task);
9612
9774
  const reportProgress = (processed) => {
@@ -9624,7 +9786,7 @@ function createDreamTaskExecutor(deps) {
9624
9786
  };
9625
9787
  const parent = await resolveParentSessionId();
9626
9788
  let moduleRoute;
9627
- if (config.task === "map-memories" || config.task === "compress-cues" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
9789
+ if (config.task === "map-memories" || config.task === "compress-cues" || config.task === "classify-memories" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
9628
9790
  try {
9629
9791
  moduleRoute = await resolveDreamerModuleRoute({
9630
9792
  db,
@@ -9638,6 +9800,9 @@ function createDreamTaskExecutor(deps) {
9638
9800
  throw new DreamerModuleFailureError("authority.status", error);
9639
9801
  }
9640
9802
  }
9803
+ if (!leaseOwnershipMatches(db, holderId, leaseAcquisition.generation, leaseKey)) {
9804
+ throw new Error("Dream lease lost during executor setup");
9805
+ }
9641
9806
  const recordRun = (status, error, extra) => {
9642
9807
  try {
9643
9808
  insertDreamRun(db, {
@@ -9710,6 +9875,7 @@ function createDreamTaskExecutor(deps) {
9710
9875
  holderId,
9711
9876
  leaseKey,
9712
9877
  deadline,
9878
+ leaseAcquisition,
9713
9879
  model: config.model ?? deps.mural.model ?? deps.dreamerModel,
9714
9880
  fallbackModels: config.fallbackModels,
9715
9881
  moduleRoute,
@@ -9733,6 +9899,7 @@ function createDreamTaskExecutor(deps) {
9733
9899
  holderId,
9734
9900
  leaseKey,
9735
9901
  deadline,
9902
+ leaseAcquisition,
9736
9903
  promotionThreshold: config.promotionThreshold ?? 3,
9737
9904
  model: config.model,
9738
9905
  fallbackModels: config.fallbackModels,
@@ -9752,6 +9919,7 @@ function createDreamTaskExecutor(deps) {
9752
9919
  holderId,
9753
9920
  leaseKey,
9754
9921
  deadline,
9922
+ leaseAcquisition,
9755
9923
  model: config.model,
9756
9924
  fallbackModels: config.fallbackModels,
9757
9925
  moduleRoute,
@@ -9777,6 +9945,7 @@ function createDreamTaskExecutor(deps) {
9777
9945
  holderId,
9778
9946
  leaseKey,
9779
9947
  deadline,
9948
+ leaseAcquisition,
9780
9949
  forceBroad: config.task === "verify-broad",
9781
9950
  model: config.model,
9782
9951
  fallbackModels: config.fallbackModels,
@@ -9810,40 +9979,15 @@ function createDreamTaskExecutor(deps) {
9810
9979
  }
9811
9980
  if (config.task === "classify-memories") {
9812
9981
  let moduleArgs;
9813
- const moduleTransport = deps.transformMode === "ts" ? undefined : deps.moduleClient;
9814
- if (moduleTransport?.authorityStatus) {
9815
- const contextStoreUuid = getContextStoreUuid(db);
9816
- if (!contextStoreUuid) {
9817
- throw new Error("Rust classify requires a context store identity");
9818
- }
9819
- let authority;
9820
- try {
9821
- authority = await moduleTransport.authorityStatus({
9822
- context_store_uuid: contextStoreUuid,
9823
- project: projectIdentity,
9824
- projectRoot: deps.sessionDirectory,
9825
- domain: "memories"
9826
- });
9827
- } catch (error) {
9828
- throw new ClassifyModuleFailureError("authority.status", error);
9829
- }
9830
- if (authority.authority?.state === "MODULE") {
9831
- const generation = authority.authority.generation;
9832
- if (typeof generation !== "number") {
9833
- throw new ClassifyModuleFailureError("authority.status", new Error("response omitted generation"));
9834
- }
9835
- const moduleClient = {
9836
- call: (callArgs) => moduleTransport.call(callArgs)
9837
- };
9838
- moduleArgs = {
9839
- moduleClient,
9840
- moduleSessionId: projectIdentity,
9841
- moduleProjectRoot: deps.sessionDirectory,
9842
- moduleContextStoreUuid: contextStoreUuid,
9843
- moduleAuthorityGeneration: generation,
9844
- moduleCommandId: `${startedAt}:${holderId}`
9845
- };
9846
- }
9982
+ if (moduleRoute) {
9983
+ moduleArgs = {
9984
+ moduleClient: moduleRoute.moduleClient,
9985
+ moduleSessionId: moduleRoute.moduleSessionId,
9986
+ moduleProjectRoot: moduleRoute.moduleProjectRoot,
9987
+ moduleContextStoreUuid: moduleRoute.moduleContextStoreUuid,
9988
+ moduleAuthorityGeneration: moduleRoute.moduleAuthorityGeneration,
9989
+ moduleCommandId: moduleRoute.moduleCommandId
9990
+ };
9847
9991
  }
9848
9992
  const result = await runClassify({
9849
9993
  db,
@@ -9854,6 +9998,7 @@ function createDreamTaskExecutor(deps) {
9854
9998
  holderId,
9855
9999
  leaseKey,
9856
10000
  deadline,
10001
+ leaseAcquisition,
9857
10002
  model: config.model,
9858
10003
  fallbackModels: config.fallbackModels,
9859
10004
  ...moduleArgs,
@@ -9877,6 +10022,7 @@ function createDreamTaskExecutor(deps) {
9877
10022
  holderId,
9878
10023
  leaseKey,
9879
10024
  deadline,
10025
+ leaseAcquisition,
9880
10026
  promotionThreshold: config.promotionThreshold ?? 2,
9881
10027
  ensureProjectRegistered: deps.ensureProjectRegistered
9882
10028
  });
@@ -9894,6 +10040,7 @@ function createDreamTaskExecutor(deps) {
9894
10040
  holderId,
9895
10041
  leaseKey,
9896
10042
  deadline,
10043
+ leaseAcquisition,
9897
10044
  model: config.model,
9898
10045
  fallbackModels: config.fallbackModels,
9899
10046
  language: config.language ?? deps.language,
@@ -9914,8 +10061,10 @@ function createDreamTaskExecutor(deps) {
9914
10061
  holderId,
9915
10062
  leaseKey,
9916
10063
  deadline,
10064
+ leaseAcquisition,
9917
10065
  model: config.model,
9918
- fallbackModels: config.fallbackModels
10066
+ fallbackModels: config.fallbackModels,
10067
+ retinaHandoff: deps.retinaHandoff
9919
10068
  });
9920
10069
  recordRun("completed", null, {
9921
10070
  smartNotesSurfaced: result.surfaced,
@@ -10058,7 +10207,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
10058
10207
  const heartbeat = startLeaseHeartbeat(db, holderId, leaseKey, () => {
10059
10208
  leaseLost = true;
10060
10209
  abortController.abort();
10061
- });
10210
+ }, ctx.leaseAcquisition);
10062
10211
  let childSessionId = null;
10063
10212
  try {
10064
10213
  const createResponse = await createChildSessionWithFence({
@@ -10248,7 +10397,7 @@ async function runAgenticTask(config, ctx, helpers) {
10248
10397
  const heartbeat = startLeaseHeartbeat(db, holderId, leaseKey, () => {
10249
10398
  leaseLost = true;
10250
10399
  abortController.abort();
10251
- });
10400
+ }, ctx.leaseAcquisition);
10252
10401
  let childSessionId = null;
10253
10402
  try {
10254
10403
  const createResponse = await createChildSessionWithFence({
@@ -10431,15 +10580,15 @@ async function runDomainGroup(deps, group, cb) {
10431
10580
  const { db, projectIdentity, executor } = deps;
10432
10581
  const leaseKey = leaseKeyFor(group[0].config.task, projectIdentity);
10433
10582
  const holderId = crypto.randomUUID();
10434
- let acquired = acquireLease(db, holderId, leaseKey);
10435
- if (!acquired && cb?.leaseWaitMs) {
10583
+ let acquisition = acquireLeaseWithAcquisition(db, holderId, leaseKey);
10584
+ if (!acquisition && cb?.leaseWaitMs) {
10436
10585
  const deadline = Date.now() + cb.leaseWaitMs;
10437
- while (!acquired && Date.now() < deadline) {
10586
+ while (!acquisition && Date.now() < deadline) {
10438
10587
  await new Promise((resolve) => setTimeout(resolve, LEASE_WAIT_POLL_MS));
10439
- acquired = acquireLease(db, holderId, leaseKey);
10588
+ acquisition = acquireLeaseWithAcquisition(db, holderId, leaseKey);
10440
10589
  }
10441
10590
  }
10442
- if (!acquired) {
10591
+ if (!acquisition) {
10443
10592
  log(`[dreamer] domain lease busy (${leaseKey}) — deferring ${group.length} task(s)`);
10444
10593
  for (const due of group)
10445
10594
  cb?.onBusy?.(due.config.task);
@@ -10447,7 +10596,7 @@ async function runDomainGroup(deps, group, cb) {
10447
10596
  }
10448
10597
  try {
10449
10598
  for (const due of [...group].sort((a, b) => compareTaskOrder(a.config.task, b.config.task))) {
10450
- if (!peekLeaseHolderAndExpiry(db, holderId, leaseKey)) {
10599
+ if (!leaseOwnershipMatches(db, holderId, acquisition.generation, leaseKey)) {
10451
10600
  log(`[dreamer] domain lease lost (${leaseKey}) — stopping remaining task(s)`);
10452
10601
  break;
10453
10602
  }
@@ -10466,7 +10615,13 @@ async function runDomainGroup(deps, group, cb) {
10466
10615
  }
10467
10616
  let outcome;
10468
10617
  try {
10469
- outcome = await executor(due.config, { db, projectIdentity, holderId, leaseKey });
10618
+ outcome = await executor(due.config, {
10619
+ db,
10620
+ projectIdentity,
10621
+ holderId,
10622
+ leaseKey,
10623
+ leaseAcquisition: acquisition
10624
+ });
10470
10625
  } catch (error) {
10471
10626
  outcome = { status: "failed", transient: true, error: String(error) };
10472
10627
  }
@@ -10873,6 +11028,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
10873
11028
  dreamerModel: dreamerConfig.model,
10874
11029
  mural: reg.mural,
10875
11030
  memoryInjectionBudgetTokens: reg.memoryInjectionBudgetTokens,
11031
+ retinaHandoff: reg.retinaHandoff,
10876
11032
  transformMode: reg.transformMode,
10877
11033
  moduleClient: reg.moduleClient,
10878
11034
  onProgress: (progress, completedTask) => reg.onDreamerProgress?.(progress, completedTask)
@@ -10916,7 +11072,8 @@ async function runCompiledSmartNoteSweep(reg, db) {
10916
11072
  const result = await runDueCompiledSmartNoteChecks({
10917
11073
  db,
10918
11074
  projectIdentity: reg.projectIdentity,
10919
- projectRoot: reg.directory
11075
+ projectRoot: reg.directory,
11076
+ retinaHandoff: reg.retinaHandoff
10920
11077
  });
10921
11078
  if (result.ran > 0) {
10922
11079
  log(`[dreamer] compiled smart-note sweep ${reg.projectIdentity}: ran=${result.ran} surfaced=${result.surfaced} logic_failed=${result.failed} network_failed=${result.networkFailed}`);
@@ -10991,7 +11148,7 @@ async function sweepGitCommits(args) {
10991
11148
  }
10992
11149
 
10993
11150
  // src/dreamer/pi-session-api.ts
10994
- import { readFileSync as readFileSync3 } from "node:fs";
11151
+ import { readFileSync as readFileSync4 } from "node:fs";
10995
11152
  import { createRequire as createRequire2 } from "node:module";
10996
11153
  import { pathToFileURL } from "node:url";
10997
11154
  var PI_CODING_AGENT_MODULE = "@earendil-works/pi-coding-agent";
@@ -11047,7 +11204,7 @@ async function loadDefaultPiSessionApi(loaders) {
11047
11204
  throw new Error("Pi session APIs unavailable: expected SessionManager.listAll on pi-coding-agent");
11048
11205
  }
11049
11206
  const loadEntriesFromFile = mod.loadEntriesFromFile ?? ((filePath) => {
11050
- const content = readFileSync3(filePath, "utf8");
11207
+ const content = readFileSync4(filePath, "utf8");
11051
11208
  return mod.parseSessionEntries?.(content) ?? [];
11052
11209
  });
11053
11210
  return {
@@ -11237,6 +11394,7 @@ function registerPiDreamerProject(opts) {
11237
11394
  dreamerConfig: opts.config,
11238
11395
  language: opts.language,
11239
11396
  gitCommitIndexing: opts.gitCommitIndexing,
11397
+ retinaHandoff: opts.retinaHandoff,
11240
11398
  ensureRegistered: ensureProjectRegisteredFromPiDirectory,
11241
11399
  retrospectiveRawProvider: () => new PiRetrospectiveRawProvider({ projectCwd: opts.projectDir }),
11242
11400
  primerRawProviderFactory: createPiPrimerRawProviderFactory()
@@ -11261,7 +11419,8 @@ function registerPiDreamerProject(opts) {
11261
11419
  primerRawProviderFactory: createPiPrimerRawProviderFactory(),
11262
11420
  userMemoryCollectionEnabled: userMemoryCollectionEnabled(opts.config),
11263
11421
  ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
11264
- language: opts.language
11422
+ language: opts.language,
11423
+ retinaHandoff: opts.retinaHandoff
11265
11424
  }),
11266
11425
  task
11267
11426
  });
@@ -11866,6 +12025,7 @@ function maybeAutoEmbedPiSession(deps, sessionId, projectDir, projectIdentity, n
11866
12025
  return;
11867
12026
  autoEmbedAttemptedBySession.add(sessionId);
11868
12027
  (async () => {
12028
+ let completedDrainWithWork = false;
11869
12029
  try {
11870
12030
  await new Promise((resolve2) => setTimeout(resolve2, 0));
11871
12031
  await ensureProjectRegisteredFromPiDirectory(projectDir, deps.db);
@@ -11876,9 +12036,13 @@ function maybeAutoEmbedPiSession(deps, sessionId, projectDir, projectIdentity, n
11876
12036
  if (remaining <= 0)
11877
12037
  return;
11878
12038
  notify(`Embedding ${remaining} compartment${remaining === 1 ? "" : "s"} of history in the background…`);
11879
- const { text } = await runEmbedDrain(deps.db, projectIdentity, sessionId);
12039
+ const { text, level } = await runEmbedDrain(deps.db, projectIdentity, sessionId);
12040
+ completedDrainWithWork = level === "success";
11880
12041
  notify(text.replace(/^## \/ctx-embed\n\n/, ""));
11881
- } catch {}
12042
+ } catch {} finally {
12043
+ if (!completedDrainWithWork)
12044
+ autoEmbedAttemptedBySession.delete(sessionId);
12045
+ }
11882
12046
  })();
11883
12047
  }
11884
12048
 
@@ -16283,6 +16447,9 @@ var EMPTY_PI_HARD_SIGNALS = {
16283
16447
  cacheExpired: false,
16284
16448
  lastResponseTime: 0
16285
16449
  };
16450
+ function renderBudgetIdentityPi(state2) {
16451
+ return `m${state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS}-h${state2.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS}`;
16452
+ }
16286
16453
  var injectionTokenCountsBySession = new Map;
16287
16454
  var cachedMuralBySession = new Map;
16288
16455
  function rememberPiMuralPayload(sessionId, dataUrl, contentHash) {
@@ -16400,7 +16567,9 @@ function getCachedMarkers(db, state2, compartmentsForNormalization) {
16400
16567
  lastBaselineEndMessageId: cachedBoundary,
16401
16568
  systemHash: meta.cachedM0SystemHash ?? "",
16402
16569
  modelKey: meta.cachedM0ModelKey ?? "",
16403
- projectIdentity: meta.cachedM0ProjectIdentity ?? null
16570
+ projectIdentity: meta.cachedM0ProjectIdentity ?? null,
16571
+ muralEnabled: cachedUpgradeIdentity.muralEnabled ?? false,
16572
+ renderBudgetIdentity: cachedUpgradeIdentity.renderBudgetIdentity ?? ""
16404
16573
  };
16405
16574
  }
16406
16575
  function lastBaselineEndMessageId(compartments) {
@@ -16432,7 +16601,9 @@ function readCurrentMarkersFromCompartments(db, state2, compartments, projectDoc
16432
16601
  lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
16433
16602
  systemHash: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
16434
16603
  modelKey: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey,
16435
- projectIdentity: state2.projectIdentity
16604
+ projectIdentity: state2.projectIdentity,
16605
+ muralEnabled: state2.muralEnabled === true,
16606
+ renderBudgetIdentity: renderBudgetIdentityPi(state2)
16436
16607
  };
16437
16608
  }
16438
16609
  function mustMaterializePi(state2, db, currentCompartmentsOverride) {
@@ -16453,6 +16624,9 @@ function mustMaterializePi(state2, db, currentCompartmentsOverride) {
16453
16624
  if (cached.compartmentRenderEpoch !== current.compartmentRenderEpoch) {
16454
16625
  return { value: true, reason: "compartment_render_epoch" };
16455
16626
  }
16627
+ if (cached.muralEnabled !== current.muralEnabled || cached.renderBudgetIdentity !== current.renderBudgetIdentity) {
16628
+ return { value: true, reason: "render_config" };
16629
+ }
16456
16630
  const hard = state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS;
16457
16631
  if (hard.modelKey !== "" && hard.modelKey !== (meta.cachedM0ModelKey ?? "")) {
16458
16632
  return { value: true, reason: "model_change" };
@@ -16590,7 +16764,9 @@ function readFrozenM0InputsPi(state2, db, docs = readProjectDocsForPiM0(state2),
16590
16764
  lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
16591
16765
  systemHash: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
16592
16766
  modelKey: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey,
16593
- projectIdentity: state2.projectIdentity
16767
+ projectIdentity: state2.projectIdentity,
16768
+ muralEnabled: state2.muralEnabled === true,
16769
+ renderBudgetIdentity: renderBudgetIdentityPi(state2)
16594
16770
  };
16595
16771
  return { docs, markers, compartments, memories, userProfile, workspace };
16596
16772
  });
@@ -16677,7 +16853,7 @@ function materializeM0Pi(state2, db) {
16677
16853
  projectDocsHash: snapshotMarkers.projectDocsHash,
16678
16854
  materializedAt: snapshotMarkers.materializedAt,
16679
16855
  sessionFactsVersion: snapshotMarkers.sessionFactsVersion,
16680
- upgradeState: encodeCachedM0UpgradeIdentity(snapshotMarkers.upgradeState, snapshotMarkers.compartmentRenderEpoch),
16856
+ upgradeState: encodeCachedM0UpgradeIdentity(snapshotMarkers.upgradeState, snapshotMarkers.compartmentRenderEpoch, snapshotMarkers.muralEnabled, snapshotMarkers.renderBudgetIdentity),
16681
16857
  systemHash: snapshotMarkers.systemHash,
16682
16858
  modelKey: snapshotMarkers.modelKey,
16683
16859
  projectIdentity: snapshotMarkers.projectIdentity
@@ -16887,7 +17063,9 @@ function markersFromCachedPiRow(row, compartmentsForNormalization) {
16887
17063
  lastBaselineEndMessageId: typeof row.cached_m0_last_baseline_end_message_id === "string" && row.cached_m0_last_baseline_end_message_id.length > 0 ? row.cached_m0_last_baseline_end_message_id : null,
16888
17064
  systemHash: row.cached_m0_system_hash ?? "",
16889
17065
  modelKey: row.cached_m0_model_key ?? "",
16890
- projectIdentity: row.cached_m0_project_identity ?? null
17066
+ projectIdentity: row.cached_m0_project_identity ?? null,
17067
+ muralEnabled: cachedUpgradeIdentity.muralEnabled ?? false,
17068
+ renderBudgetIdentity: cachedUpgradeIdentity.renderBudgetIdentity ?? ""
16891
17069
  };
16892
17070
  }
16893
17071
  function cachedPiRowMatchesSnapshot(args) {
@@ -21772,10 +21950,14 @@ function processSystemPromptForCache(args) {
21772
21950
  const dateMatch = systemPrompt.match(DATE_PATTERN);
21773
21951
  const liveDate = dateMatch ? dateMatch[0] : null;
21774
21952
  const stickyDate = stickyDateBySession.get(sessionId);
21953
+ const stableCandidate = liveDate && stickyDate && liveDate !== stickyDate ? systemPrompt.replace(DATE_PATTERN, stickyDate) : systemPrompt;
21954
+ const stableCandidateHash = createHash10("md5").update(promptSurfaceHashMaterial(stableCandidate, args.promptSurfacePreset)).digest("hex");
21955
+ const contentOrPresetChanged = !isFirstHash && stableCandidateHash !== previousHash;
21956
+ const dateMayAdvance = isCacheBusting || contentOrPresetChanged;
21775
21957
  if (liveDate && !stickyDate) {
21776
21958
  stickyDateBySession.set(sessionId, liveDate);
21777
21959
  } else if (liveDate && stickyDate && liveDate !== stickyDate) {
21778
- if (isCacheBusting) {
21960
+ if (dateMayAdvance) {
21779
21961
  stickyDateBySession.set(sessionId, liveDate);
21780
21962
  sessionLog(sessionId, `system prompt date updated: ${stickyDate} → ${liveDate} (cache-busting pass)`);
21781
21963
  } else {
@@ -21812,6 +21994,37 @@ function clearPiSystemPromptSession(sessionId) {
21812
21994
  }
21813
21995
 
21814
21996
  // src/temporal-awareness-pi.ts
21997
+ function withoutPiLeadingTemporalMarker(text) {
21998
+ const { tagPrefix, body } = peelLeadingMcTagNotation(text);
21999
+ return tagPrefix + body.replace(TEMPORAL_MARKER_PATTERN, "");
22000
+ }
22001
+ function stripPiLeadingTemporalMarker(message) {
22002
+ if (!message || typeof message !== "object")
22003
+ return false;
22004
+ const userMessage = message;
22005
+ if (userMessage.role !== "user")
22006
+ return false;
22007
+ if (typeof userMessage.content === "string") {
22008
+ const stripped2 = withoutPiLeadingTemporalMarker(userMessage.content);
22009
+ if (stripped2 === userMessage.content)
22010
+ return false;
22011
+ userMessage.content = stripped2;
22012
+ return true;
22013
+ }
22014
+ if (!Array.isArray(userMessage.content))
22015
+ return false;
22016
+ const firstTextIndex = userMessage.content.findIndex((part) => part?.type === "text");
22017
+ if (firstTextIndex < 0)
22018
+ return false;
22019
+ const firstText = userMessage.content[firstTextIndex];
22020
+ const stripped = withoutPiLeadingTemporalMarker(firstText.text);
22021
+ if (stripped === firstText.text)
22022
+ return false;
22023
+ const content = userMessage.content.slice();
22024
+ content[firstTextIndex] = { ...firstText, text: stripped };
22025
+ userMessage.content = content;
22026
+ return true;
22027
+ }
21815
22028
  function injectPiTemporalMarkers(messages) {
21816
22029
  let injected = 0;
21817
22030
  let prevTimestampMs;
@@ -22636,7 +22849,7 @@ function buildPiTextIdentityPlan(db, sessionId, tagger, transcript, reuseCandida
22636
22849
  const messageId = message.info.id;
22637
22850
  if (messageId === undefined)
22638
22851
  continue;
22639
- currentSourcesByMessageId.set(messageId, message.parts.filter((part) => part.kind === "text").map((part) => stripTagPrefix(part.getText() ?? "")));
22852
+ currentSourcesByMessageId.set(messageId, message.parts.filter((part) => part.kind === "text").map((part) => withoutPiLeadingTemporalMarker(stripTagPrefix(part.getText() ?? ""))));
22640
22853
  }
22641
22854
  const legacyRowsByMessageId = new Map;
22642
22855
  const versionedMessageIds = new Set;
@@ -22682,7 +22895,7 @@ function buildPiTextIdentityPlan(db, sessionId, tagger, transcript, reuseCandida
22682
22895
  if (legacyRows.length === 0)
22683
22896
  continue;
22684
22897
  legacyRows.sort((left, right) => left.ordinal - right.ordinal);
22685
- const vectorMatches = legacyRows.length === currentSources.length && legacyRows.every((row, index) => row.ordinal === index && sourceCache.get(row.tagId) === currentSources[index]);
22898
+ const vectorMatches = legacyRows.length === currentSources.length && legacyRows.every((row, index) => row.ordinal === index && withoutPiLeadingTemporalMarker(sourceCache.get(row.tagId) ?? "") === currentSources[index]);
22686
22899
  if (!vectorMatches)
22687
22900
  driftedMessageIds.add(messageId);
22688
22901
  }
@@ -22990,6 +23203,30 @@ function buildPiAlignedEntryIds(entries) {
22990
23203
  }
22991
23204
  return ids;
22992
23205
  }
23206
+ function stripMcOwnedPiCompactionSummary(messages, entryIds, branchEntries) {
23207
+ const summaryMessage = messages[0];
23208
+ if (summaryMessage?.role !== "compactionSummary")
23209
+ return false;
23210
+ let compaction;
23211
+ for (let index = branchEntries.length - 1;index >= 0; index -= 1) {
23212
+ const entry = branchEntries[index];
23213
+ if (entry?.type === "compaction") {
23214
+ compaction = entry;
23215
+ break;
23216
+ }
23217
+ }
23218
+ if (compaction?.fromHook !== true)
23219
+ return false;
23220
+ const details = compaction.details;
23221
+ if (details?.source !== "magic-context")
23222
+ return false;
23223
+ if (summaryMessage.summary !== compaction.summary || summaryMessage.tokensBefore !== compaction.tokensBefore || entryIds[0] !== undefined) {
23224
+ return false;
23225
+ }
23226
+ messages.splice(0, 1);
23227
+ entryIds.splice(0, 1);
23228
+ return true;
23229
+ }
22993
23230
  function getPiBranchEntryLookup(entries) {
22994
23231
  const cached = piBranchLookupByProjection.get(entries);
22995
23232
  if (cached)
@@ -23351,6 +23588,9 @@ function registerPiContextHandler(pi, baseOptions) {
23351
23588
  const alignedEntryIds = branchLookup?.alignedEntryIds ?? null;
23352
23589
  const resolvedEntryIds = alignedEntryIds?.length === event.messages.length ? alignedEntryIds : branchEntries === null ? null : collectMessageEntryIdsByRef(ctx, event.messages, sessionId, branchEntries);
23353
23590
  const strictEntryIds = resolvedEntryIds ? [...resolvedEntryIds] : null;
23591
+ if (strictEntryIds && branchEntries && options.injection && !options.compactionOff && stripMcOwnedPiCompactionSummary(event.messages, strictEntryIds, branchEntries)) {
23592
+ logTransformTiming(sessionId, "mcCompactionSummarySuppression", tEntryBranch);
23593
+ }
23354
23594
  if (strictEntryIds && options.injection && !options.compactionOff) {
23355
23595
  const removed = trimPiMessagesToCachedBoundary(options.db, sessionId, event.messages, strictEntryIds);
23356
23596
  if (removed > 0) {
@@ -24482,10 +24722,10 @@ async function runPipeline(args) {
24482
24722
  }
24483
24723
  const targetTagNumbers = [...targets.keys()];
24484
24724
  const tGetTags = performance.now();
24485
- const flushedSliceTags = getTagsByNumbers(args.db, args.sessionId, targetTagNumbers);
24486
- logTransformTiming(args.sessionId, "getTagsByNumbers", tGetTags, `targets=${targetTagNumbers.length} fetched=${flushedSliceTags.length}`);
24725
+ const flushedDroppedTags = getDroppedTagsByNumbers(args.db, args.sessionId, targetTagNumbers);
24726
+ logTransformTiming(args.sessionId, "getDroppedTagsByNumbers", tGetTags, `targets=${targetTagNumbers.length} fetched=${flushedDroppedTags.length}`);
24487
24727
  const tFlushed = performance.now();
24488
- didMutateFromFlushedStatuses = applyFlushedStatuses(args.sessionId, args.db, targets, flushedSliceTags);
24728
+ didMutateFromFlushedStatuses = applyFlushedStatuses(args.sessionId, args.db, targets, flushedDroppedTags);
24489
24729
  logTransformTiming(args.sessionId, "applyFlushedStatuses", tFlushed);
24490
24730
  logTransformTiming(args.sessionId, "batchFinalize:flushed", tFlushed);
24491
24731
  const messageIdToMaxTag = buildMessageIdToMaxTag(targets);
@@ -24729,6 +24969,10 @@ async function runPipeline(args) {
24729
24969
  hardSignals: piHardSignals,
24730
24970
  muralEnabled: args.injection.muralEnabled === true
24731
24971
  }, args.db, args.messages, args.entryIds, args.isCacheBusting || deferredHistoryRefresh || executedWorkThisPass);
24972
+ if (args.temporalAwareness && injectionResult.skippedVisibleMessages > 0) {
24973
+ const firstRetainedMessage = args.messages[injectionResult.syntheticLeadingCount];
24974
+ stripPiLeadingTemporalMarker(firstRetainedMessage);
24975
+ }
24732
24976
  if (args.isCacheBusting) {
24733
24977
  historyRefreshSessions.delete(args.sessionId);
24734
24978
  historyWasConsumedThisPass = true;
@@ -26907,6 +27151,14 @@ var MIGRATION_SYSTEM_PROMPT = "You re-organize a software project's long-term me
26907
27151
  var LKG_TOTAL_BYTES = 64 * 1024 * 1024;
26908
27152
  var LKG_SINGLE_SLOT_BYTES = 24 * 1024 * 1024;
26909
27153
  var slots = new Map;
27154
+ var LKG_SNAPSHOT_ARRAY = Symbol("array");
27155
+ var LKG_SNAPSHOT_OBJECT = Symbol("object");
27156
+ var LKG_SNAPSHOT_KEY = Symbol("key");
27157
+ var LKG_SNAPSHOT_STRING = Symbol("string");
27158
+ var LKG_SNAPSHOT_NUMBER = Symbol("number");
27159
+ var LKG_SNAPSHOT_BOOLEAN = Symbol("boolean");
27160
+ var LKG_SNAPSHOT_NULL = Symbol("null");
27161
+ var LKG_SNAPSHOT_UNDEFINED = Symbol("undefined");
26910
27162
 
26911
27163
  // ../plugin/src/hooks/magic-context/recomp-orchestrator.ts
26912
27164
  function isRecompFailure(message) {
@@ -27452,15 +27704,17 @@ ${c.content}
27452
27704
  // package.json
27453
27705
  var package_default = {
27454
27706
  name: "@cortexkit/pi-magic-context",
27455
- version: "0.35.1",
27707
+ version: "0.36.1",
27456
27708
  type: "module",
27457
- description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
27709
+ description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
27458
27710
  main: "dist/index.js",
27459
27711
  license: "MIT",
27460
27712
  author: "ualtinok",
27461
27713
  keywords: [
27462
27714
  "pi",
27463
27715
  "pi-coding-agent",
27716
+ "omp",
27717
+ "oh-my-pi",
27464
27718
  "extension",
27465
27719
  "context",
27466
27720
  "memory",
@@ -27478,8 +27732,9 @@ var package_default = {
27478
27732
  "README.md"
27479
27733
  ],
27480
27734
  scripts: {
27481
- build: "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",
27482
- typecheck: "tsc --noEmit",
27735
+ 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",
27736
+ "build:e2e-argv": "bun build src/subagent-runner.ts --outfile ../../tests/docker/.generated/subagent-runner-e2e.mjs --target node --format esm --external node:sqlite",
27737
+ typecheck: "tsc -p ../retina-local-fs/tsconfig.build.json && tsc --noEmit",
27483
27738
  test: "bun test",
27484
27739
  lint: "biome check src",
27485
27740
  "lint:fix": "biome check --write src",
@@ -27510,6 +27765,14 @@ var package_default = {
27510
27765
  "@earendil-works/pi-coding-agent": "^0.80.2",
27511
27766
  "@earendil-works/pi-tui": "^0.80.2"
27512
27767
  },
27768
+ peerDependenciesMeta: {
27769
+ "@earendil-works/pi-coding-agent": {
27770
+ optional: true
27771
+ },
27772
+ "@earendil-works/pi-tui": {
27773
+ optional: true
27774
+ }
27775
+ },
27513
27776
  exports: {
27514
27777
  ".": {
27515
27778
  import: "./dist/index.js"
@@ -27519,6 +27782,11 @@ var package_default = {
27519
27782
  extensions: [
27520
27783
  "./dist/index.js"
27521
27784
  ]
27785
+ },
27786
+ omp: {
27787
+ extensions: [
27788
+ "./dist/index.js"
27789
+ ]
27522
27790
  }
27523
27791
  };
27524
27792
 
@@ -28555,6 +28823,9 @@ async function handlePiSessionBeforeCompact(args) {
28555
28823
  info("session_before_compact: cancelling — magic-context owns compaction");
28556
28824
  return { cancel: true };
28557
28825
  }
28826
+ function canonicalPiModelKey(provider, model) {
28827
+ return piModelRefToCanonical(`${provider}/${model}`);
28828
+ }
28558
28829
  function persistPiMessageEndModelMeta(args) {
28559
28830
  if (!args.message || typeof args.message !== "object")
28560
28831
  return;
@@ -28562,7 +28833,7 @@ function persistPiMessageEndModelMeta(args) {
28562
28833
  if (msg.role !== "assistant" || typeof msg.provider !== "string" || msg.provider.length === 0 || typeof msg.model !== "string" || msg.model.length === 0) {
28563
28834
  return;
28564
28835
  }
28565
- const modelKey = `${msg.provider}/${msg.model}`;
28836
+ const modelKey = canonicalPiModelKey(msg.provider, msg.model);
28566
28837
  recordPiLiveModel(args.sessionId, modelKey);
28567
28838
  const cacheTtl = resolveCacheTtl(args.cacheTtlConfig, modelKey);
28568
28839
  const currentMeta = getOrCreateSessionMeta(args.db, args.sessionId);
@@ -29268,6 +29539,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
29268
29539
  config: dreamerConfig,
29269
29540
  embeddingConfig: bootProjectDeps.config.embedding,
29270
29541
  memoryEnabled: bootProjectDeps.config.memory.enabled,
29542
+ retinaHandoff: bootProjectDeps.config.smart_notes.retina_handoff,
29271
29543
  language: bootProjectDeps.config.language,
29272
29544
  gitCommitIndexing: bootProjectDeps.config.memory.git_commit_indexing,
29273
29545
  onAdjunctsRefreshNeeded: signalPiSystemPromptRefreshForProject
@@ -29277,6 +29549,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
29277
29549
  info(bootProjectDeps.dreamerEnabled ? "registered dreamer: DISABLED (no dreamer config)" : "registered dreamer: DISABLED (dreamer.disable=true or no dreamer config)");
29278
29550
  }
29279
29551
  pi.on("before_agent_start", async (event, ctx) => {
29552
+ await preloadTokenizer();
29280
29553
  try {
29281
29554
  if (ctx.hasUI && shouldShowAnnouncement()) {
29282
29555
  const featureText = ANNOUNCEMENT_FEATURES.map((line) => ` • ${line}`).join(`
@@ -29312,6 +29585,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
29312
29585
  config: effectiveDreamerConfig,
29313
29586
  embeddingConfig: effectiveConfig.embedding,
29314
29587
  memoryEnabled: effectiveConfig.memory.enabled,
29588
+ retinaHandoff: effectiveConfig.smart_notes.retina_handoff,
29315
29589
  language: effectiveConfig.language,
29316
29590
  gitCommitIndexing: effectiveConfig.memory.git_commit_indexing,
29317
29591
  onAdjunctsRefreshNeeded: signalPiSystemPromptRefreshForProject
@@ -29371,7 +29645,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
29371
29645
  }
29372
29646
  const isCacheBusting = sessionId ? hasSystemPromptRefresh(sessionId) : true;
29373
29647
  const promptSurfaceModel = ctx.model;
29374
- const promptSurfaceModelKey = typeof promptSurfaceModel?.provider === "string" && promptSurfaceModel.provider.length > 0 && typeof promptSurfaceModel.id === "string" && promptSurfaceModel.id.length > 0 ? `${promptSurfaceModel.provider}/${promptSurfaceModel.id}` : undefined;
29648
+ const promptSurfaceModelKey = typeof promptSurfaceModel?.provider === "string" && promptSurfaceModel.provider.length > 0 && typeof promptSurfaceModel.id === "string" && promptSurfaceModel.id.length > 0 ? canonicalPiModelKey(promptSurfaceModel.provider, promptSurfaceModel.id) : undefined;
29375
29649
  const promptSurface = sessionId ? promptSurfaceGuidanceEpochs.resolve(sessionId, effectiveConfig.prompt_surface, promptSurfaceModelKey) : promptSurfaceRuntime.resolveGuidance(effectiveConfig.prompt_surface, promptSurfaceModelKey);
29376
29650
  const block = buildMagicContextBlock({
29377
29651
  db,
@@ -29656,5 +29930,6 @@ export {
29656
29930
  src_default as default,
29657
29931
  capturePiTodowriteMessageIfCompatible,
29658
29932
  capturePiTodowriteArgsIfCompatible,
29933
+ canonicalPiModelKey,
29659
29934
  __test
29660
29935
  };