@cortexkit/pi-magic-context 0.36.0 → 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,
@@ -257,6 +258,7 @@ import {
257
258
  peelLeadingMcTagNotation,
258
259
  persistCachedM0,
259
260
  piModelRefToCanonical,
261
+ preloadTokenizer,
260
262
  prependTag,
261
263
  primeInMemoryTailRawMessageCache,
262
264
  primeTailRawMessageCache,
@@ -375,7 +377,7 @@ import {
375
377
  withMigrationLanguageDirective,
376
378
  withRawMessageProvider,
377
379
  withRawSessionMessageCache
378
- } from "./index-9t7jhq83.js";
380
+ } from "./index-zxgbtsnj.js";
379
381
  import {
380
382
  pushNotification
381
383
  } from "./index-hw34xmzk.js";
@@ -1950,6 +1952,7 @@ function createCloneFilter(entries) {
1950
1952
  const rawMessages = convertEntriesToRawMessages([...entries]);
1951
1953
  const rawOrdinalById = new Map(rawMessages.map((message) => [message.id, message.ordinal]));
1952
1954
  const validStateIds = new Set(rawOrdinalById.keys());
1955
+ const validOrdinals = new Set(rawOrdinalById.values());
1953
1956
  for (const entry of entries) {
1954
1957
  const id = entryId(entry);
1955
1958
  if (id)
@@ -1959,6 +1962,8 @@ function createCloneFilter(entries) {
1959
1962
  return {
1960
1963
  resolveBoundaryOrdinal: (id) => rawOrdinalById.get(id),
1961
1964
  includeMessageId,
1965
+ copySessionNotesAndFacts: true,
1966
+ mapOrdinal: (ordinal) => validOrdinals.has(ordinal) ? ordinal : undefined,
1962
1967
  includeTag: (tag) => {
1963
1968
  if (tag.type === "tool") {
1964
1969
  return typeof tag.toolOwnerMessageId === "string" && includeMessageId(tag.toolOwnerMessageId);
@@ -2036,7 +2041,7 @@ async function handlePiCloneSessionStart(event, ctx, deps) {
2036
2041
  if (result.pendingMarkerMigrated) {
2037
2042
  deps.signalPendingMarker(destinationSessionId);
2038
2043
  }
2039
- 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`);
2040
2045
  return result;
2041
2046
  } catch (error) {
2042
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`);
@@ -2095,13 +2100,14 @@ var state = {
2095
2100
  noticeEmitted: false,
2096
2101
  failure: null
2097
2102
  };
2098
- function recordStaleFence(persistedVersion, supportedVersion) {
2103
+ function recordStaleFence(persistedVersion, supportedVersion, reason = "newer_schema") {
2099
2104
  state.consecutiveFailures += 1;
2100
2105
  state.totalFailures += 1;
2101
2106
  const latched = state.consecutiveFailures >= STALE_CHILD_SPAWN_LATCH_THRESHOLD;
2102
2107
  state.latched ||= latched;
2103
2108
  const failure = {
2104
2109
  failureClass: STALE_CHILD_SPAWN_FAILURE,
2110
+ reason,
2105
2111
  persistedVersion,
2106
2112
  supportedVersion,
2107
2113
  consecutiveFailures: state.consecutiveFailures,
@@ -2128,7 +2134,7 @@ function probeChildSpawnFence(db) {
2128
2134
  return recordStaleFence(persistedVersion, LATEST_SUPPORTED_VERSION);
2129
2135
  }
2130
2136
  } catch {
2131
- return { allowSpawn: true };
2137
+ return recordStaleFence(LATEST_SUPPORTED_VERSION, LATEST_SUPPORTED_VERSION, "read_error");
2132
2138
  }
2133
2139
  state.consecutiveFailures = 0;
2134
2140
  state.latched = false;
@@ -3832,25 +3838,31 @@ async function sendIgnoredMessage(client, sessionId, text, params, forcePersist
3832
3838
 
3833
3839
  // ../plugin/src/hooks/magic-context/child-session-spawn.ts
3834
3840
  var STALE_PLUGIN_RESTART_NOTICE = "Magic Context: plugin build is older than its database — restart OpenCode";
3835
- 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) {
3836
3843
  if (!args.parentSessionId)
3837
3844
  return;
3838
- try {
3839
- if (args.db) {
3845
+ const notice = failure.reason === "read_error" ? SCHEMA_PROBE_FAILURE_NOTICE : STALE_PLUGIN_RESTART_NOTICE;
3846
+ if (args.db) {
3847
+ try {
3840
3848
  updateSessionMeta(args.db, args.parentSessionId, {
3841
- lastTransformError: STALE_PLUGIN_RESTART_NOTICE
3849
+ lastTransformError: notice
3842
3850
  });
3851
+ } catch (error) {
3852
+ sessionLog(args.parentSessionId, `schema-fence warning persistence failed: ${error instanceof Error ? error.message : String(error)}`);
3843
3853
  }
3854
+ }
3855
+ try {
3844
3856
  pushNotification("toast", {
3845
3857
  title: "Magic Context",
3846
- message: STALE_PLUGIN_RESTART_NOTICE,
3858
+ message: notice,
3847
3859
  variant: "error",
3848
3860
  duration: 1e4
3849
3861
  }, args.parentSessionId);
3850
3862
  pushNotification("action", { action: "refresh-sidebar" }, args.parentSessionId);
3851
- await sendIgnoredMessage(args.client, args.parentSessionId, STALE_PLUGIN_RESTART_NOTICE, args.notificationParams ?? {}, true);
3863
+ await sendIgnoredMessage(args.client, args.parentSessionId, notice, args.notificationParams ?? {}, true);
3852
3864
  } catch (error) {
3853
- 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)}`);
3854
3866
  }
3855
3867
  }
3856
3868
  async function createChildSessionWithFence(args) {
@@ -3863,7 +3875,7 @@ async function createChildSessionWithFence(args) {
3863
3875
  if (args.onFenceLatched)
3864
3876
  await args.onFenceLatched(verdict.failure);
3865
3877
  else
3866
- await surfaceStalePluginBuild(args);
3878
+ await surfaceSchemaFenceFailure(args, verdict.failure);
3867
3879
  }
3868
3880
  return null;
3869
3881
  }
@@ -4255,7 +4267,7 @@ function parseFields(json) {
4255
4267
  }
4256
4268
 
4257
4269
  // ../plugin/src/features/magic-context/mural/compress-cues.ts
4258
- import { createHash as createHash2 } from "node:crypto";
4270
+ import { createHash as createHash3 } from "node:crypto";
4259
4271
 
4260
4272
  // ../plugin/src/features/magic-context/dreamer/storage-dream-state.ts
4261
4273
  var getDreamStateStatements = new WeakMap;
@@ -4304,13 +4316,15 @@ function rowKeys(leaseKey) {
4304
4316
  return {
4305
4317
  holder: "dreaming_lease_holder",
4306
4318
  heartbeat: "dreaming_lease_heartbeat",
4307
- expiry: "dreaming_lease_expiry"
4319
+ expiry: "dreaming_lease_expiry",
4320
+ generation: "dreaming_lease_generation"
4308
4321
  };
4309
4322
  }
4310
4323
  return {
4311
4324
  holder: `lease:${leaseKey}:holder`,
4312
4325
  heartbeat: `lease:${leaseKey}:heartbeat`,
4313
- expiry: `lease:${leaseKey}:expiry`
4326
+ expiry: `lease:${leaseKey}:expiry`,
4327
+ generation: `lease:${leaseKey}:generation`
4314
4328
  };
4315
4329
  }
4316
4330
  function getLeaseExpiry(db, keys) {
@@ -4328,6 +4342,13 @@ function isLeaseActive(db, leaseKey = DREAMING_LEASE_KEY) {
4328
4342
  function getLeaseHolder(db, leaseKey = DREAMING_LEASE_KEY) {
4329
4343
  return getDreamState(db, rowKeys(leaseKey).holder);
4330
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
+ }
4331
4352
  function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_KEY) {
4332
4353
  const keys = rowKeys(leaseKey);
4333
4354
  const holder = getDreamState(db, keys.holder);
@@ -4339,6 +4360,9 @@ function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_
4339
4360
  const expiry = Number(expiryStr);
4340
4361
  return Number.isFinite(expiry) && expiry >= Date.now();
4341
4362
  }
4363
+ function leaseOwnershipMatches(db, expectedHolder, expectedGeneration, leaseKey = DREAMING_LEASE_KEY) {
4364
+ return getLeaseGeneration(db, leaseKey) === expectedGeneration && peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey);
4365
+ }
4342
4366
  function runImmediate(db, body) {
4343
4367
  db.exec("BEGIN IMMEDIATE");
4344
4368
  let committed = false;
@@ -4355,26 +4379,30 @@ function runImmediate(db, body) {
4355
4379
  }
4356
4380
  }
4357
4381
  }
4358
- function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
4382
+ function acquireLeaseWithAcquisition(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
4359
4383
  const keys = rowKeys(leaseKey);
4360
4384
  return runImmediate(db, () => {
4361
- if (isLeaseActive(db, leaseKey)) {
4362
- const existingHolder = getLeaseHolder(db, leaseKey);
4363
- if (existingHolder && existingHolder !== holderId) {
4364
- return false;
4365
- }
4385
+ const existingHolder = getLeaseHolder(db, leaseKey);
4386
+ if (isLeaseActive(db, leaseKey) && existingHolder && existingHolder !== holderId) {
4387
+ return null;
4366
4388
  }
4367
4389
  const now = Date.now();
4390
+ const priorGeneration = getLeaseGeneration(db, leaseKey) ?? 0;
4391
+ const generation = existingHolder === holderId ? Math.max(1, priorGeneration) : priorGeneration + 1;
4368
4392
  setDreamState(db, keys.holder, holderId);
4369
4393
  setDreamState(db, keys.heartbeat, String(now));
4370
4394
  setDreamState(db, keys.expiry, String(now + LEASE_DURATION_MS));
4371
- return true;
4395
+ setDreamState(db, keys.generation, String(generation));
4396
+ return { acquiredAt: now, generation };
4372
4397
  });
4373
4398
  }
4374
- 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) {
4375
4403
  const keys = rowKeys(leaseKey);
4376
4404
  return runImmediate(db, () => {
4377
- if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey)) {
4405
+ if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey) || expectedGeneration !== undefined && getLeaseGeneration(db, leaseKey) !== expectedGeneration) {
4378
4406
  return false;
4379
4407
  }
4380
4408
  const now = Date.now();
@@ -4392,9 +4420,12 @@ function runLeaseGuardedWrite(db, holderId, leaseKey, fn) {
4392
4420
  });
4393
4421
  }
4394
4422
  var LEASE_HEARTBEAT_INTERVAL_MS = 60 * 1000;
4395
- 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;
4396
4426
  let lost = false;
4397
- let lastConfirmedAt = Date.now();
4427
+ let expectedGeneration = acquisition?.generation ?? getLeaseGeneration(db, leaseKey);
4428
+ let lastConfirmedAt = acquisition?.acquiredAt ?? Date.now();
4398
4429
  const declareLost = (reason) => {
4399
4430
  if (lost)
4400
4431
  return;
@@ -4405,15 +4436,25 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalMs = LEASE_
4405
4436
  if (lost)
4406
4437
  return;
4407
4438
  try {
4408
- if (renewLease(db, holderId, leaseKey)) {
4439
+ if (renewLease(db, holderId, leaseKey, expectedGeneration === null ? undefined : expectedGeneration)) {
4409
4440
  lastConfirmedAt = Date.now();
4410
4441
  return;
4411
4442
  }
4443
+ if (expectedGeneration !== null && getLeaseGeneration(db, leaseKey) !== expectedGeneration) {
4444
+ declareLost("lease generation changed — another holder acquired it");
4445
+ return;
4446
+ }
4412
4447
  if (Date.now() - lastConfirmedAt > LEASE_DURATION_MS) {
4413
4448
  declareLost("lease lapsed past TTL — another holder may have run");
4414
4449
  return;
4415
4450
  }
4416
- 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;
4417
4458
  lastConfirmedAt = Date.now();
4418
4459
  return;
4419
4460
  }
@@ -4482,6 +4523,16 @@ function assertManifestCoversExactly(ids, expectedIds, rootName) {
4482
4523
  }
4483
4524
 
4484
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
+
4485
4536
  class DreamerModuleFailureError extends Error {
4486
4537
  transient = true;
4487
4538
  constructor(operation, cause) {
@@ -4503,9 +4554,12 @@ async function resolveDreamerModuleRoute(args) {
4503
4554
  projectRoot: args.projectRoot,
4504
4555
  domain: "memories"
4505
4556
  });
4506
- 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")
4507
4561
  return;
4508
- const generation = result.authority.generation;
4562
+ const generation = authority.generation;
4509
4563
  if (typeof generation !== "number")
4510
4564
  throw new Error("Rust authority status omitted generation");
4511
4565
  return {
@@ -4539,6 +4593,68 @@ function getModuleMemoryIdentities(db, projectIdentity, contextIds) {
4539
4593
  ] : []));
4540
4594
  }
4541
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
+
4542
4658
  // ../plugin/src/features/magic-context/mural/compress-cues-prompt.ts
4543
4659
  var CUE_BUDGET_HIGH = 90;
4544
4660
  var CUE_BUDGET_LOW = 50;
@@ -4711,7 +4827,7 @@ async function runCompressCues(args) {
4711
4827
  chunks.push(candidates.slice(i, i + COMPRESS_CUES_CHUNK_SIZE));
4712
4828
  }
4713
4829
  const abortController = new AbortController;
4714
- 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);
4715
4831
  try {
4716
4832
  let consecutiveTimeouts = 0;
4717
4833
  let timeoutStreakElapsedMs = [];
@@ -4806,7 +4922,14 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
4806
4922
  const text = extractLatestAssistantText(messages);
4807
4923
  if (!text)
4808
4924
  throw new Error("compress-cues returned no output");
4809
- 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
+ }
4810
4933
  return text;
4811
4934
  }
4812
4935
  });
@@ -4814,7 +4937,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
4814
4937
  } catch (error) {
4815
4938
  const desc = describeError(error);
4816
4939
  log(`[dreamer] compress-cues chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
4817
- if (signal.aborted)
4940
+ if (signal.aborted || error instanceof DreamerProviderOutputFailureError)
4818
4941
  throw error;
4819
4942
  return {
4820
4943
  compressed: 0,
@@ -4922,7 +5045,7 @@ async function applyCuesThroughModule(args, chunk, manifestText, signal) {
4922
5045
  log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason}; rejection ${rejectionCount}/${CUE_REJECTION_LATCH_THRESHOLD})`);
4923
5046
  }
4924
5047
  }
4925
- 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)}`;
4926
5049
  let response;
4927
5050
  try {
4928
5051
  response = await route.moduleClient.call({
@@ -5364,7 +5487,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
5364
5487
  const heartbeat = startLeaseHeartbeat(args.db, args.holderId, leaseKey, (reason) => {
5365
5488
  log(`[dreamer] user-memories: lease lost (${reason}) — aborting`);
5366
5489
  abortController.abort();
5367
- });
5490
+ }, args.leaseAcquisition);
5368
5491
  try {
5369
5492
  const createResponse = await createChildSessionWithFence({
5370
5493
  client: args.client,
@@ -5487,7 +5610,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
5487
5610
  }
5488
5611
 
5489
5612
  // ../plugin/src/features/magic-context/dreamer/classify.ts
5490
- import { createHash as createHash3 } from "node:crypto";
5613
+ import { createHash as createHash4 } from "node:crypto";
5491
5614
 
5492
5615
  // ../plugin/src/plugin/rust-tool-backends.ts
5493
5616
  function isRustAuthorityDrainingError(error) {
@@ -5871,7 +5994,7 @@ async function runClassify(args) {
5871
5994
  chunks.push(toClassify.slice(i, i + CLASSIFY_CHUNK_SIZE));
5872
5995
  }
5873
5996
  const abortController = new AbortController;
5874
- 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);
5875
5998
  try {
5876
5999
  for (let i = 0;i < chunks.length; i += 1) {
5877
6000
  const remainingMs = Math.max(0, args.deadline - Date.now());
@@ -5951,7 +6074,14 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
5951
6074
  const text = extractLatestAssistantText(messages);
5952
6075
  if (!text)
5953
6076
  throw new Error("classify returned no output");
5954
- 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
+ }
5955
6085
  return text;
5956
6086
  }
5957
6087
  });
@@ -5962,7 +6092,7 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
5962
6092
  const desc = describeError(failure);
5963
6093
  log(`[dreamer] classify chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
5964
6094
  recordInvocation(args, startedAt, { status: "failed", error: failure });
5965
- if (moduleRoute || signal.aborted)
6095
+ if (moduleRoute || signal.aborted || failure instanceof DreamerProviderOutputFailureError)
5966
6096
  throw failure;
5967
6097
  return { classified: 0, changed: 0 };
5968
6098
  } finally {
@@ -5991,7 +6121,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
5991
6121
  v: 1,
5992
6122
  session_id: args.moduleSessionId,
5993
6123
  task: "classify",
5994
- 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)}`,
5995
6125
  authority_generation: args.moduleAuthorityGeneration,
5996
6126
  payload: {
5997
6127
  prompt_body: prompt,
@@ -6629,7 +6759,7 @@ function throwIfAborted2(signal) {
6629
6759
  }
6630
6760
 
6631
6761
  // ../plugin/src/features/magic-context/smart-notes/compiler.ts
6632
- import { createHash as createHash4 } from "node:crypto";
6762
+ import { createHash as createHash5 } from "node:crypto";
6633
6763
 
6634
6764
  // ../plugin/src/features/magic-context/smart-notes/compiler-prompt.ts
6635
6765
  var SMART_NOTE_COMPILER_SYSTEM_PROMPT = `You are the Magic Context smart-note compiler for the magic-context system.
@@ -7053,7 +7183,7 @@ function manifestAdvisoryWarnings(code, manifest) {
7053
7183
  return warnings;
7054
7184
  }
7055
7185
  function hashCheck(surfaceCondition, compiledCheck, manifest, checkCron) {
7056
- 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");
7057
7187
  }
7058
7188
  function extractJsonObject(output) {
7059
7189
  const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
@@ -7294,7 +7424,7 @@ async function evaluateSmartNotes(args) {
7294
7424
  leaseAbortController.abort(new Error("Dream lease lost during smart notes"));
7295
7425
  log("[dreamer] smart notes: lease lost — aborting");
7296
7426
  args.onLeaseLost?.("smart notes");
7297
- });
7427
+ }, args.leaseAcquisition);
7298
7428
  let surfaced = 0;
7299
7429
  let didWork = false;
7300
7430
  try {
@@ -7735,7 +7865,7 @@ function enforceMaintainDocsProtectedRegions(args) {
7735
7865
  }
7736
7866
 
7737
7867
  // ../plugin/src/features/magic-context/dreamer/map-memories.ts
7738
- import { createHash as createHash5 } from "node:crypto";
7868
+ import { createHash as createHash6 } from "node:crypto";
7739
7869
 
7740
7870
  // ../plugin/src/features/magic-context/dreamer/map-memories-prompt.ts
7741
7871
  import { existsSync as existsSync6, statSync } from "node:fs";
@@ -7852,7 +7982,7 @@ async function mapMemories(args) {
7852
7982
  }
7853
7983
  result.remaining = inputs.length;
7854
7984
  const abortController = new AbortController;
7855
- 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);
7856
7986
  try {
7857
7987
  for (let i = 0;i < batches.length; i += 1) {
7858
7988
  const remainingMs = Math.max(0, args.deadline - Date.now());
@@ -7996,7 +8126,7 @@ async function applyBatchMappings(args, batch, manifestText) {
7996
8126
  memory_project: args.projectIdentity,
7997
8127
  context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
7998
8128
  authority_generation: args.moduleRoute.moduleAuthorityGeneration,
7999
- 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)}`,
8000
8130
  rows
8001
8131
  }
8002
8132
  }
@@ -8221,7 +8351,7 @@ async function promotePrimers(args) {
8221
8351
  const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => {
8222
8352
  leaseLost = true;
8223
8353
  log("[dreamer] primers: lease lost during promote-primers — aborting");
8224
- });
8354
+ }, args.leaseAcquisition);
8225
8355
  try {
8226
8356
  assertLeaseHeld("prune start");
8227
8357
  result.pruned = pruneExpiredPrimerCandidatesForProject(args.db, args.projectIdentity, Date.now(), PRIMER_CANDIDATE_TTL_MS);
@@ -8453,7 +8583,7 @@ async function refreshPrimers(args) {
8453
8583
  if (primers.length === 0)
8454
8584
  return result;
8455
8585
  const abortController = new AbortController;
8456
- 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);
8457
8587
  try {
8458
8588
  for (let i = 0;i < primers.length; i += 1) {
8459
8589
  const primer = primers[i];
@@ -9056,68 +9186,6 @@ function insertDreamRun(db, run) {
9056
9186
  // ../plugin/src/features/magic-context/dreamer/verify.ts
9057
9187
  import { createHash as createHash7 } from "node:crypto";
9058
9188
 
9059
- // ../plugin/src/features/magic-context/dreamer/provider-output-failure.ts
9060
- import { createHash as createHash6 } from "node:crypto";
9061
- var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
9062
-
9063
- class DreamerProviderOutputFailureError extends Error {
9064
- fingerprint;
9065
- outputTokens;
9066
- reasoningTokens;
9067
- transient = true;
9068
- constructor(fingerprint, outputTokens, reasoningTokens, responseText) {
9069
- const preview = responseText.trim().replace(/\s+/g, " ").slice(0, 160);
9070
- super(`verify provider-outage completion (output_tokens=${outputTokens}, reasoning_tokens=${reasoningTokens}): ${JSON.stringify(preview)}`);
9071
- this.fingerprint = fingerprint;
9072
- this.outputTokens = outputTokens;
9073
- this.reasoningTokens = reasoningTokens;
9074
- this.name = "DreamerProviderOutputFailureError";
9075
- }
9076
- }
9077
- function finiteTokenCount(value) {
9078
- return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
9079
- }
9080
- function completionShape(value) {
9081
- if (!isRecord(value))
9082
- return null;
9083
- const info = isRecord(value.info) ? value.info : value;
9084
- if (info.role !== "assistant")
9085
- return null;
9086
- const time = isRecord(info.time) ? info.time : null;
9087
- const tokens = isRecord(info.tokens) ? info.tokens : null;
9088
- return {
9089
- createdAt: typeof time?.created === "number" ? time.created : 0,
9090
- finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : null,
9091
- error: info.error,
9092
- outputTokens: finiteTokenCount(tokens?.output),
9093
- reasoningTokens: finiteTokenCount(tokens?.reasoning)
9094
- };
9095
- }
9096
- function latestAssistantCompletion(messages) {
9097
- if (!Array.isArray(messages))
9098
- return null;
9099
- let latest = null;
9100
- for (const message of messages) {
9101
- const completion = completionShape(message);
9102
- if (completion && (!latest || completion.createdAt >= latest.createdAt))
9103
- latest = completion;
9104
- }
9105
- return latest;
9106
- }
9107
- function providerOutputFailureFromInvalidManifest(messages, responseText) {
9108
- const completion = latestAssistantCompletion(messages);
9109
- if (completion?.finish?.toLowerCase() !== "stop")
9110
- return null;
9111
- if (completion.error != null || completion.outputTokens === null || completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS || completion.reasoningTokens !== 0) {
9112
- return null;
9113
- }
9114
- const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
9115
- if (!normalized)
9116
- return null;
9117
- const fingerprint = createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
9118
- return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
9119
- }
9120
-
9121
9189
  // ../plugin/src/features/magic-context/dreamer/verify-gate.ts
9122
9190
  import path5 from "node:path";
9123
9191
  function minOf(values) {
@@ -9362,7 +9430,7 @@ async function runVerify(args) {
9362
9430
  batches.push(gate.inScope.slice(i, i + VERIFY_BATCH_SIZE));
9363
9431
  }
9364
9432
  const abortController = new AbortController;
9365
- 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);
9366
9434
  let consecutiveProviderFailures = 0;
9367
9435
  let priorProviderFailureFingerprint = null;
9368
9436
  let lastProviderFailure = null;
@@ -9698,6 +9766,9 @@ function createDreamTaskExecutor(deps) {
9698
9766
  return async (config, ctx) => {
9699
9767
  const { db, projectIdentity, holderId, leaseKey } = ctx;
9700
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
+ })();
9701
9772
  const deadline = startedAt + config.timeoutMinutes * 60 * 1000;
9702
9773
  const backlogAtStart = getDreamTaskBacklog(db, projectIdentity, config.task);
9703
9774
  const reportProgress = (processed) => {
@@ -9715,7 +9786,7 @@ function createDreamTaskExecutor(deps) {
9715
9786
  };
9716
9787
  const parent = await resolveParentSessionId();
9717
9788
  let moduleRoute;
9718
- 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") {
9719
9790
  try {
9720
9791
  moduleRoute = await resolveDreamerModuleRoute({
9721
9792
  db,
@@ -9729,6 +9800,9 @@ function createDreamTaskExecutor(deps) {
9729
9800
  throw new DreamerModuleFailureError("authority.status", error);
9730
9801
  }
9731
9802
  }
9803
+ if (!leaseOwnershipMatches(db, holderId, leaseAcquisition.generation, leaseKey)) {
9804
+ throw new Error("Dream lease lost during executor setup");
9805
+ }
9732
9806
  const recordRun = (status, error, extra) => {
9733
9807
  try {
9734
9808
  insertDreamRun(db, {
@@ -9801,6 +9875,7 @@ function createDreamTaskExecutor(deps) {
9801
9875
  holderId,
9802
9876
  leaseKey,
9803
9877
  deadline,
9878
+ leaseAcquisition,
9804
9879
  model: config.model ?? deps.mural.model ?? deps.dreamerModel,
9805
9880
  fallbackModels: config.fallbackModels,
9806
9881
  moduleRoute,
@@ -9824,6 +9899,7 @@ function createDreamTaskExecutor(deps) {
9824
9899
  holderId,
9825
9900
  leaseKey,
9826
9901
  deadline,
9902
+ leaseAcquisition,
9827
9903
  promotionThreshold: config.promotionThreshold ?? 3,
9828
9904
  model: config.model,
9829
9905
  fallbackModels: config.fallbackModels,
@@ -9843,6 +9919,7 @@ function createDreamTaskExecutor(deps) {
9843
9919
  holderId,
9844
9920
  leaseKey,
9845
9921
  deadline,
9922
+ leaseAcquisition,
9846
9923
  model: config.model,
9847
9924
  fallbackModels: config.fallbackModels,
9848
9925
  moduleRoute,
@@ -9868,6 +9945,7 @@ function createDreamTaskExecutor(deps) {
9868
9945
  holderId,
9869
9946
  leaseKey,
9870
9947
  deadline,
9948
+ leaseAcquisition,
9871
9949
  forceBroad: config.task === "verify-broad",
9872
9950
  model: config.model,
9873
9951
  fallbackModels: config.fallbackModels,
@@ -9901,40 +9979,15 @@ function createDreamTaskExecutor(deps) {
9901
9979
  }
9902
9980
  if (config.task === "classify-memories") {
9903
9981
  let moduleArgs;
9904
- const moduleTransport = deps.transformMode === "ts" ? undefined : deps.moduleClient;
9905
- if (moduleTransport?.authorityStatus) {
9906
- const contextStoreUuid = getContextStoreUuid(db);
9907
- if (!contextStoreUuid) {
9908
- throw new Error("Rust classify requires a context store identity");
9909
- }
9910
- let authority;
9911
- try {
9912
- authority = await moduleTransport.authorityStatus({
9913
- context_store_uuid: contextStoreUuid,
9914
- project: projectIdentity,
9915
- projectRoot: deps.sessionDirectory,
9916
- domain: "memories"
9917
- });
9918
- } catch (error) {
9919
- throw new ClassifyModuleFailureError("authority.status", error);
9920
- }
9921
- if (authority.authority?.state === "MODULE") {
9922
- const generation = authority.authority.generation;
9923
- if (typeof generation !== "number") {
9924
- throw new ClassifyModuleFailureError("authority.status", new Error("response omitted generation"));
9925
- }
9926
- const moduleClient = {
9927
- call: (callArgs) => moduleTransport.call(callArgs)
9928
- };
9929
- moduleArgs = {
9930
- moduleClient,
9931
- moduleSessionId: projectIdentity,
9932
- moduleProjectRoot: deps.sessionDirectory,
9933
- moduleContextStoreUuid: contextStoreUuid,
9934
- moduleAuthorityGeneration: generation,
9935
- moduleCommandId: `${startedAt}:${holderId}`
9936
- };
9937
- }
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
+ };
9938
9991
  }
9939
9992
  const result = await runClassify({
9940
9993
  db,
@@ -9945,6 +9998,7 @@ function createDreamTaskExecutor(deps) {
9945
9998
  holderId,
9946
9999
  leaseKey,
9947
10000
  deadline,
10001
+ leaseAcquisition,
9948
10002
  model: config.model,
9949
10003
  fallbackModels: config.fallbackModels,
9950
10004
  ...moduleArgs,
@@ -9968,6 +10022,7 @@ function createDreamTaskExecutor(deps) {
9968
10022
  holderId,
9969
10023
  leaseKey,
9970
10024
  deadline,
10025
+ leaseAcquisition,
9971
10026
  promotionThreshold: config.promotionThreshold ?? 2,
9972
10027
  ensureProjectRegistered: deps.ensureProjectRegistered
9973
10028
  });
@@ -9985,6 +10040,7 @@ function createDreamTaskExecutor(deps) {
9985
10040
  holderId,
9986
10041
  leaseKey,
9987
10042
  deadline,
10043
+ leaseAcquisition,
9988
10044
  model: config.model,
9989
10045
  fallbackModels: config.fallbackModels,
9990
10046
  language: config.language ?? deps.language,
@@ -10005,6 +10061,7 @@ function createDreamTaskExecutor(deps) {
10005
10061
  holderId,
10006
10062
  leaseKey,
10007
10063
  deadline,
10064
+ leaseAcquisition,
10008
10065
  model: config.model,
10009
10066
  fallbackModels: config.fallbackModels,
10010
10067
  retinaHandoff: deps.retinaHandoff
@@ -10150,7 +10207,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
10150
10207
  const heartbeat = startLeaseHeartbeat(db, holderId, leaseKey, () => {
10151
10208
  leaseLost = true;
10152
10209
  abortController.abort();
10153
- });
10210
+ }, ctx.leaseAcquisition);
10154
10211
  let childSessionId = null;
10155
10212
  try {
10156
10213
  const createResponse = await createChildSessionWithFence({
@@ -10340,7 +10397,7 @@ async function runAgenticTask(config, ctx, helpers) {
10340
10397
  const heartbeat = startLeaseHeartbeat(db, holderId, leaseKey, () => {
10341
10398
  leaseLost = true;
10342
10399
  abortController.abort();
10343
- });
10400
+ }, ctx.leaseAcquisition);
10344
10401
  let childSessionId = null;
10345
10402
  try {
10346
10403
  const createResponse = await createChildSessionWithFence({
@@ -10523,15 +10580,15 @@ async function runDomainGroup(deps, group, cb) {
10523
10580
  const { db, projectIdentity, executor } = deps;
10524
10581
  const leaseKey = leaseKeyFor(group[0].config.task, projectIdentity);
10525
10582
  const holderId = crypto.randomUUID();
10526
- let acquired = acquireLease(db, holderId, leaseKey);
10527
- if (!acquired && cb?.leaseWaitMs) {
10583
+ let acquisition = acquireLeaseWithAcquisition(db, holderId, leaseKey);
10584
+ if (!acquisition && cb?.leaseWaitMs) {
10528
10585
  const deadline = Date.now() + cb.leaseWaitMs;
10529
- while (!acquired && Date.now() < deadline) {
10586
+ while (!acquisition && Date.now() < deadline) {
10530
10587
  await new Promise((resolve) => setTimeout(resolve, LEASE_WAIT_POLL_MS));
10531
- acquired = acquireLease(db, holderId, leaseKey);
10588
+ acquisition = acquireLeaseWithAcquisition(db, holderId, leaseKey);
10532
10589
  }
10533
10590
  }
10534
- if (!acquired) {
10591
+ if (!acquisition) {
10535
10592
  log(`[dreamer] domain lease busy (${leaseKey}) — deferring ${group.length} task(s)`);
10536
10593
  for (const due of group)
10537
10594
  cb?.onBusy?.(due.config.task);
@@ -10539,7 +10596,7 @@ async function runDomainGroup(deps, group, cb) {
10539
10596
  }
10540
10597
  try {
10541
10598
  for (const due of [...group].sort((a, b) => compareTaskOrder(a.config.task, b.config.task))) {
10542
- if (!peekLeaseHolderAndExpiry(db, holderId, leaseKey)) {
10599
+ if (!leaseOwnershipMatches(db, holderId, acquisition.generation, leaseKey)) {
10543
10600
  log(`[dreamer] domain lease lost (${leaseKey}) — stopping remaining task(s)`);
10544
10601
  break;
10545
10602
  }
@@ -10558,7 +10615,13 @@ async function runDomainGroup(deps, group, cb) {
10558
10615
  }
10559
10616
  let outcome;
10560
10617
  try {
10561
- 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
+ });
10562
10625
  } catch (error) {
10563
10626
  outcome = { status: "failed", transient: true, error: String(error) };
10564
10627
  }
@@ -11962,6 +12025,7 @@ function maybeAutoEmbedPiSession(deps, sessionId, projectDir, projectIdentity, n
11962
12025
  return;
11963
12026
  autoEmbedAttemptedBySession.add(sessionId);
11964
12027
  (async () => {
12028
+ let completedDrainWithWork = false;
11965
12029
  try {
11966
12030
  await new Promise((resolve2) => setTimeout(resolve2, 0));
11967
12031
  await ensureProjectRegisteredFromPiDirectory(projectDir, deps.db);
@@ -11972,9 +12036,13 @@ function maybeAutoEmbedPiSession(deps, sessionId, projectDir, projectIdentity, n
11972
12036
  if (remaining <= 0)
11973
12037
  return;
11974
12038
  notify(`Embedding ${remaining} compartment${remaining === 1 ? "" : "s"} of history in the background…`);
11975
- const { text } = await runEmbedDrain(deps.db, projectIdentity, sessionId);
12039
+ const { text, level } = await runEmbedDrain(deps.db, projectIdentity, sessionId);
12040
+ completedDrainWithWork = level === "success";
11976
12041
  notify(text.replace(/^## \/ctx-embed\n\n/, ""));
11977
- } catch {}
12042
+ } catch {} finally {
12043
+ if (!completedDrainWithWork)
12044
+ autoEmbedAttemptedBySession.delete(sessionId);
12045
+ }
11978
12046
  })();
11979
12047
  }
11980
12048
 
@@ -16379,6 +16447,9 @@ var EMPTY_PI_HARD_SIGNALS = {
16379
16447
  cacheExpired: false,
16380
16448
  lastResponseTime: 0
16381
16449
  };
16450
+ function renderBudgetIdentityPi(state2) {
16451
+ return `m${state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS}-h${state2.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS}`;
16452
+ }
16382
16453
  var injectionTokenCountsBySession = new Map;
16383
16454
  var cachedMuralBySession = new Map;
16384
16455
  function rememberPiMuralPayload(sessionId, dataUrl, contentHash) {
@@ -16496,7 +16567,9 @@ function getCachedMarkers(db, state2, compartmentsForNormalization) {
16496
16567
  lastBaselineEndMessageId: cachedBoundary,
16497
16568
  systemHash: meta.cachedM0SystemHash ?? "",
16498
16569
  modelKey: meta.cachedM0ModelKey ?? "",
16499
- projectIdentity: meta.cachedM0ProjectIdentity ?? null
16570
+ projectIdentity: meta.cachedM0ProjectIdentity ?? null,
16571
+ muralEnabled: cachedUpgradeIdentity.muralEnabled ?? false,
16572
+ renderBudgetIdentity: cachedUpgradeIdentity.renderBudgetIdentity ?? ""
16500
16573
  };
16501
16574
  }
16502
16575
  function lastBaselineEndMessageId(compartments) {
@@ -16528,7 +16601,9 @@ function readCurrentMarkersFromCompartments(db, state2, compartments, projectDoc
16528
16601
  lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
16529
16602
  systemHash: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
16530
16603
  modelKey: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey,
16531
- projectIdentity: state2.projectIdentity
16604
+ projectIdentity: state2.projectIdentity,
16605
+ muralEnabled: state2.muralEnabled === true,
16606
+ renderBudgetIdentity: renderBudgetIdentityPi(state2)
16532
16607
  };
16533
16608
  }
16534
16609
  function mustMaterializePi(state2, db, currentCompartmentsOverride) {
@@ -16549,6 +16624,9 @@ function mustMaterializePi(state2, db, currentCompartmentsOverride) {
16549
16624
  if (cached.compartmentRenderEpoch !== current.compartmentRenderEpoch) {
16550
16625
  return { value: true, reason: "compartment_render_epoch" };
16551
16626
  }
16627
+ if (cached.muralEnabled !== current.muralEnabled || cached.renderBudgetIdentity !== current.renderBudgetIdentity) {
16628
+ return { value: true, reason: "render_config" };
16629
+ }
16552
16630
  const hard = state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS;
16553
16631
  if (hard.modelKey !== "" && hard.modelKey !== (meta.cachedM0ModelKey ?? "")) {
16554
16632
  return { value: true, reason: "model_change" };
@@ -16686,7 +16764,9 @@ function readFrozenM0InputsPi(state2, db, docs = readProjectDocsForPiM0(state2),
16686
16764
  lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
16687
16765
  systemHash: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
16688
16766
  modelKey: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey,
16689
- projectIdentity: state2.projectIdentity
16767
+ projectIdentity: state2.projectIdentity,
16768
+ muralEnabled: state2.muralEnabled === true,
16769
+ renderBudgetIdentity: renderBudgetIdentityPi(state2)
16690
16770
  };
16691
16771
  return { docs, markers, compartments, memories, userProfile, workspace };
16692
16772
  });
@@ -16773,7 +16853,7 @@ function materializeM0Pi(state2, db) {
16773
16853
  projectDocsHash: snapshotMarkers.projectDocsHash,
16774
16854
  materializedAt: snapshotMarkers.materializedAt,
16775
16855
  sessionFactsVersion: snapshotMarkers.sessionFactsVersion,
16776
- upgradeState: encodeCachedM0UpgradeIdentity(snapshotMarkers.upgradeState, snapshotMarkers.compartmentRenderEpoch),
16856
+ upgradeState: encodeCachedM0UpgradeIdentity(snapshotMarkers.upgradeState, snapshotMarkers.compartmentRenderEpoch, snapshotMarkers.muralEnabled, snapshotMarkers.renderBudgetIdentity),
16777
16857
  systemHash: snapshotMarkers.systemHash,
16778
16858
  modelKey: snapshotMarkers.modelKey,
16779
16859
  projectIdentity: snapshotMarkers.projectIdentity
@@ -16983,7 +17063,9 @@ function markersFromCachedPiRow(row, compartmentsForNormalization) {
16983
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,
16984
17064
  systemHash: row.cached_m0_system_hash ?? "",
16985
17065
  modelKey: row.cached_m0_model_key ?? "",
16986
- projectIdentity: row.cached_m0_project_identity ?? null
17066
+ projectIdentity: row.cached_m0_project_identity ?? null,
17067
+ muralEnabled: cachedUpgradeIdentity.muralEnabled ?? false,
17068
+ renderBudgetIdentity: cachedUpgradeIdentity.renderBudgetIdentity ?? ""
16987
17069
  };
16988
17070
  }
16989
17071
  function cachedPiRowMatchesSnapshot(args) {
@@ -21868,10 +21950,14 @@ function processSystemPromptForCache(args) {
21868
21950
  const dateMatch = systemPrompt.match(DATE_PATTERN);
21869
21951
  const liveDate = dateMatch ? dateMatch[0] : null;
21870
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;
21871
21957
  if (liveDate && !stickyDate) {
21872
21958
  stickyDateBySession.set(sessionId, liveDate);
21873
21959
  } else if (liveDate && stickyDate && liveDate !== stickyDate) {
21874
- if (isCacheBusting) {
21960
+ if (dateMayAdvance) {
21875
21961
  stickyDateBySession.set(sessionId, liveDate);
21876
21962
  sessionLog(sessionId, `system prompt date updated: ${stickyDate} → ${liveDate} (cache-busting pass)`);
21877
21963
  } else {
@@ -21908,6 +21994,37 @@ function clearPiSystemPromptSession(sessionId) {
21908
21994
  }
21909
21995
 
21910
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
+ }
21911
22028
  function injectPiTemporalMarkers(messages) {
21912
22029
  let injected = 0;
21913
22030
  let prevTimestampMs;
@@ -22732,7 +22849,7 @@ function buildPiTextIdentityPlan(db, sessionId, tagger, transcript, reuseCandida
22732
22849
  const messageId = message.info.id;
22733
22850
  if (messageId === undefined)
22734
22851
  continue;
22735
- 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() ?? ""))));
22736
22853
  }
22737
22854
  const legacyRowsByMessageId = new Map;
22738
22855
  const versionedMessageIds = new Set;
@@ -22778,7 +22895,7 @@ function buildPiTextIdentityPlan(db, sessionId, tagger, transcript, reuseCandida
22778
22895
  if (legacyRows.length === 0)
22779
22896
  continue;
22780
22897
  legacyRows.sort((left, right) => left.ordinal - right.ordinal);
22781
- 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]);
22782
22899
  if (!vectorMatches)
22783
22900
  driftedMessageIds.add(messageId);
22784
22901
  }
@@ -23086,6 +23203,30 @@ function buildPiAlignedEntryIds(entries) {
23086
23203
  }
23087
23204
  return ids;
23088
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
+ }
23089
23230
  function getPiBranchEntryLookup(entries) {
23090
23231
  const cached = piBranchLookupByProjection.get(entries);
23091
23232
  if (cached)
@@ -23447,6 +23588,9 @@ function registerPiContextHandler(pi, baseOptions) {
23447
23588
  const alignedEntryIds = branchLookup?.alignedEntryIds ?? null;
23448
23589
  const resolvedEntryIds = alignedEntryIds?.length === event.messages.length ? alignedEntryIds : branchEntries === null ? null : collectMessageEntryIdsByRef(ctx, event.messages, sessionId, branchEntries);
23449
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
+ }
23450
23594
  if (strictEntryIds && options.injection && !options.compactionOff) {
23451
23595
  const removed = trimPiMessagesToCachedBoundary(options.db, sessionId, event.messages, strictEntryIds);
23452
23596
  if (removed > 0) {
@@ -24578,10 +24722,10 @@ async function runPipeline(args) {
24578
24722
  }
24579
24723
  const targetTagNumbers = [...targets.keys()];
24580
24724
  const tGetTags = performance.now();
24581
- const flushedSliceTags = getTagsByNumbers(args.db, args.sessionId, targetTagNumbers);
24582
- 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}`);
24583
24727
  const tFlushed = performance.now();
24584
- didMutateFromFlushedStatuses = applyFlushedStatuses(args.sessionId, args.db, targets, flushedSliceTags);
24728
+ didMutateFromFlushedStatuses = applyFlushedStatuses(args.sessionId, args.db, targets, flushedDroppedTags);
24585
24729
  logTransformTiming(args.sessionId, "applyFlushedStatuses", tFlushed);
24586
24730
  logTransformTiming(args.sessionId, "batchFinalize:flushed", tFlushed);
24587
24731
  const messageIdToMaxTag = buildMessageIdToMaxTag(targets);
@@ -24825,6 +24969,10 @@ async function runPipeline(args) {
24825
24969
  hardSignals: piHardSignals,
24826
24970
  muralEnabled: args.injection.muralEnabled === true
24827
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
+ }
24828
24976
  if (args.isCacheBusting) {
24829
24977
  historyRefreshSessions.delete(args.sessionId);
24830
24978
  historyWasConsumedThisPass = true;
@@ -27556,7 +27704,7 @@ ${c.content}
27556
27704
  // package.json
27557
27705
  var package_default = {
27558
27706
  name: "@cortexkit/pi-magic-context",
27559
- version: "0.36.0",
27707
+ version: "0.36.1",
27560
27708
  type: "module",
27561
27709
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
27562
27710
  main: "dist/index.js",
@@ -28675,6 +28823,9 @@ async function handlePiSessionBeforeCompact(args) {
28675
28823
  info("session_before_compact: cancelling — magic-context owns compaction");
28676
28824
  return { cancel: true };
28677
28825
  }
28826
+ function canonicalPiModelKey(provider, model) {
28827
+ return piModelRefToCanonical(`${provider}/${model}`);
28828
+ }
28678
28829
  function persistPiMessageEndModelMeta(args) {
28679
28830
  if (!args.message || typeof args.message !== "object")
28680
28831
  return;
@@ -28682,7 +28833,7 @@ function persistPiMessageEndModelMeta(args) {
28682
28833
  if (msg.role !== "assistant" || typeof msg.provider !== "string" || msg.provider.length === 0 || typeof msg.model !== "string" || msg.model.length === 0) {
28683
28834
  return;
28684
28835
  }
28685
- const modelKey = `${msg.provider}/${msg.model}`;
28836
+ const modelKey = canonicalPiModelKey(msg.provider, msg.model);
28686
28837
  recordPiLiveModel(args.sessionId, modelKey);
28687
28838
  const cacheTtl = resolveCacheTtl(args.cacheTtlConfig, modelKey);
28688
28839
  const currentMeta = getOrCreateSessionMeta(args.db, args.sessionId);
@@ -29398,6 +29549,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
29398
29549
  info(bootProjectDeps.dreamerEnabled ? "registered dreamer: DISABLED (no dreamer config)" : "registered dreamer: DISABLED (dreamer.disable=true or no dreamer config)");
29399
29550
  }
29400
29551
  pi.on("before_agent_start", async (event, ctx) => {
29552
+ await preloadTokenizer();
29401
29553
  try {
29402
29554
  if (ctx.hasUI && shouldShowAnnouncement()) {
29403
29555
  const featureText = ANNOUNCEMENT_FEATURES.map((line) => ` • ${line}`).join(`
@@ -29493,7 +29645,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
29493
29645
  }
29494
29646
  const isCacheBusting = sessionId ? hasSystemPromptRefresh(sessionId) : true;
29495
29647
  const promptSurfaceModel = ctx.model;
29496
- 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;
29497
29649
  const promptSurface = sessionId ? promptSurfaceGuidanceEpochs.resolve(sessionId, effectiveConfig.prompt_surface, promptSurfaceModelKey) : promptSurfaceRuntime.resolveGuidance(effectiveConfig.prompt_surface, promptSurfaceModelKey);
29498
29650
  const block = buildMagicContextBlock({
29499
29651
  db,
@@ -29778,5 +29930,6 @@ export {
29778
29930
  src_default as default,
29779
29931
  capturePiTodowriteMessageIfCompatible,
29780
29932
  capturePiTodowriteArgsIfCompatible,
29933
+ canonicalPiModelKey,
29781
29934
  __test
29782
29935
  };