@cortexkit/opencode-magic-context 0.34.1 → 0.34.2

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.
Files changed (36) hide show
  1. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts +9 -5
  2. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts.map +1 -1
  3. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  4. package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
  5. package/dist/features/magic-context/dreamer/verify-gate.d.ts +8 -2
  6. package/dist/features/magic-context/dreamer/verify-gate.d.ts.map +1 -1
  7. package/dist/features/magic-context/dreamer/verify.d.ts +2 -0
  8. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  9. package/dist/features/magic-context/fail-closed-block.d.ts +2 -0
  10. package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
  11. package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
  12. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  13. package/dist/features/magic-context/mural/compress-cues.d.ts +7 -3
  14. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  15. package/dist/features/magic-context/mural/cue-validation.d.ts +7 -7
  16. package/dist/features/magic-context/mural/cue-validation.d.ts.map +1 -1
  17. package/dist/features/magic-context/mural/storage-mural-cues.d.ts +13 -3
  18. package/dist/features/magic-context/mural/storage-mural-cues.d.ts.map +1 -1
  19. package/dist/features/magic-context/storage-db.d.ts +21 -3
  20. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  21. package/dist/features/magic-context/storage-meta-persisted.d.ts +1 -0
  22. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/event-handler.d.ts +1 -0
  24. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  26. package/dist/hooks/magic-context/rust-mode-transform.d.ts +16 -0
  27. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  28. package/dist/hooks/magic-context/transform-context-state.d.ts +1 -0
  29. package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
  30. package/dist/hooks/magic-context/transform.d.ts +1 -0
  31. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  32. package/dist/{index-x8spt5wy.js → index-z70pxrq1.js} +126 -25
  33. package/dist/index.js +217 -34
  34. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  35. package/dist/{recomp-orchestrator-k72ejkkh.js → recomp-orchestrator-6cd3nrt7.js} +1 -1
  36. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -138,6 +138,7 @@ import {
138
138
  getDroppedTagsBySession,
139
139
  getEmbeddingCoverageStatus,
140
140
  getEmergencyInputSample,
141
+ getEmergencyRecoveryArmedAt,
141
142
  getHistorianFailureState,
142
143
  getLastCompartmentEndMessage,
143
144
  getLastCompartmentEndMessageId,
@@ -279,6 +280,7 @@ import {
279
280
  recordHighPressureNoEligibleHead,
280
281
  recordMemoryMapping,
281
282
  recordMemoryVerifications,
283
+ recordMuralCueRejection,
282
284
  recordOverflowDetected,
283
285
  recordSessionProjectIdentity,
284
286
  recordToolDefinition,
@@ -372,7 +374,7 @@ import {
372
374
  upsertCommits,
373
375
  verificationFileExists,
374
376
  withContentLanguageDirective
375
- } from "./index-x8spt5wy.js";
377
+ } from "./index-z70pxrq1.js";
376
378
  import {
377
379
  deriveHistorianChunkTokens,
378
380
  deriveTriggerBudget,
@@ -10469,6 +10471,15 @@ function formatFailClosedBlockingProcesses(processes) {
10469
10471
  }
10470
10472
  function formatFailClosedBlockingMessage(reason) {
10471
10473
  if (reason.kind === "migration_guard") {
10474
+ if (reason.unreadableFile) {
10475
+ const arm = reason.unreadableArm ?? "io";
10476
+ const recovery = arm === "io" ? `If no OpenCode server is running, it is safe to delete ${reason.unreadableFile} and retry.` : `The file may be a recent incomplete write; retry after the file is older than the ten-minute grace window, or stop OpenCode before deleting it.`;
10477
+ return [
10478
+ `Magic Context cannot migrate the shared database because RPC discovery file ${reason.unreadableFile} is uncertain (${arm} arm), so the absence of a live OpenCode server cannot be proven.`,
10479
+ recovery,
10480
+ `Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
10481
+ ].join(" ");
10482
+ }
10472
10483
  return [
10473
10484
  `Magic Context cannot migrate the shared database because ${formatFailClosedBlockingProcesses(reason.blockingProcesses)} may be running an older Magic Context build that would fail against the migrated database.`,
10474
10485
  "Restart the blocking process (it will pick up the new build and migrate on start), or shut it down and retry.",
@@ -12847,6 +12858,7 @@ function seedTaskScheduleState(db, projectPath, task, nextDueAt, lastRunAt, sche
12847
12858
  db.prepare("INSERT INTO task_schedule_state (project_path, task, last_run_at, next_due_at, schedule, last_status, last_error, retry_count) VALUES (?, ?, ?, ?, ?, NULL, NULL, 0) ON CONFLICT(project_path, task) DO NOTHING").run(projectPath, task, lastRunAt, nextDueAt, schedule);
12848
12859
  }
12849
12860
  function writeTaskScheduleState(db, row) {
12861
+ const broadCycleUpdate = row.lastBroadRunAt === undefined ? "last_broad_run_at = task_schedule_state.last_broad_run_at" : "last_broad_run_at = excluded.last_broad_run_at";
12850
12862
  db.prepare(`INSERT INTO task_schedule_state
12851
12863
  (project_path, task, last_run_at, next_due_at, schedule, last_status, last_error, retry_count, last_checked_commit, last_broad_run_at, retrospective_watermark_ms)
12852
12864
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -12858,7 +12870,7 @@ function writeTaskScheduleState(db, row) {
12858
12870
  last_error = excluded.last_error,
12859
12871
  retry_count = excluded.retry_count,
12860
12872
  last_checked_commit = COALESCE(excluded.last_checked_commit, task_schedule_state.last_checked_commit),
12861
- last_broad_run_at = COALESCE(excluded.last_broad_run_at, task_schedule_state.last_broad_run_at),
12873
+ ${broadCycleUpdate},
12862
12874
  retrospective_watermark_ms = COALESCE(excluded.retrospective_watermark_ms, task_schedule_state.retrospective_watermark_ms)`).run(row.projectPath, row.task, row.lastRunAt, row.nextDueAt, row.schedule, row.lastStatus, row.lastError, row.retryCount, row.lastCheckedCommit ?? null, row.lastBroadRunAt ?? null, row.retrospectiveWatermarkMs ?? null);
12863
12875
  }
12864
12876
  function isRetrospectiveWindowProcessed(db, projectPath, windowKey) {
@@ -12986,7 +12998,7 @@ function hasBalancedParentheses(cue) {
12986
12998
  }
12987
12999
  return depth === 0;
12988
13000
  }
12989
- function validateCue(cue, importance) {
13001
+ function validateCue(cue, importance, ownId) {
12990
13002
  const trimmed = cue.trim();
12991
13003
  if (trimmed.length === 0)
12992
13004
  return { reason: "empty" };
@@ -12994,8 +13006,9 @@ function validateCue(cue, importance) {
12994
13006
  const length = [...trimmed].length;
12995
13007
  if (length > budget)
12996
13008
  return { reason: `over-budget ${length}>${budget}` };
12997
- if (/#\d+/.test(trimmed))
13009
+ if (ownId !== undefined && new RegExp(`#${ownId}\\b`).test(trimmed)) {
12998
13010
  return { reason: "leaked-id" };
13011
+ }
12999
13012
  if (!hasBalancedParentheses(trimmed))
13000
13013
  return { reason: "unbalanced-parens" };
13001
13014
  const markers = trimmed.split("⊘").length - 1;
@@ -13011,6 +13024,7 @@ function validateCue(cue, importance) {
13011
13024
  // src/features/magic-context/mural/compress-cues.ts
13012
13025
  var COMPRESS_CUES_CHUNK_SIZE = 40;
13013
13026
  var CHUNK_TIMEOUT_FLOOR_MS = 240000;
13027
+ var CUE_REJECTION_LATCH_THRESHOLD = 3;
13014
13028
  var CONSECUTIVE_TIMEOUT_LIMIT = 2;
13015
13029
  function toPromptMemory(candidate) {
13016
13030
  const memory = candidate.memory;
@@ -13021,6 +13035,38 @@ function toPromptMemory(candidate) {
13021
13035
  content: memory.content
13022
13036
  };
13023
13037
  }
13038
+ function stripOwnIdToken(value, ownId) {
13039
+ return value.replace(new RegExp(`#${ownId}\\b`, "g"), "");
13040
+ }
13041
+ function truncateCue(value, budget) {
13042
+ const trimmed = value.trim();
13043
+ const codepoints = [...trimmed];
13044
+ if (codepoints.length <= budget)
13045
+ return trimmed;
13046
+ const prefix = codepoints.slice(0, budget).join("");
13047
+ const boundary = prefix.search(/\s+\S*$/);
13048
+ return (boundary > 0 ? prefix.slice(0, boundary) : prefix).trim();
13049
+ }
13050
+ function sanitizeCue(value, candidate) {
13051
+ return truncateCue(stripOwnIdToken(value, candidate.memory.id), cueBudgetFor(candidate.memory.importance ?? 50));
13052
+ }
13053
+ function deterministicFallbackCue(candidate, lastCandidate) {
13054
+ const importance = candidate.memory.importance ?? 50;
13055
+ const budget = cueBudgetFor(importance);
13056
+ const sanitizedCandidate = sanitizeCue(lastCandidate, candidate);
13057
+ if (validateCue(sanitizedCandidate, importance, candidate.memory.id) === null) {
13058
+ return sanitizedCandidate;
13059
+ }
13060
+ const sourceSlice = sanitizeCue(candidate.memory.content, candidate);
13061
+ if (validateCue(sourceSlice, importance, candidate.memory.id) === null) {
13062
+ return sourceSlice;
13063
+ }
13064
+ const grammarSafe = truncateCue(sourceSlice.replaceAll("⊘", "").replace(/[()]/g, "").replace(/\b(?:must not|never|without|instead of|exclude|excludes)\b/gi, "").replace(/\s+/g, " "), budget);
13065
+ if (validateCue(grammarSafe, importance, candidate.memory.id) === null) {
13066
+ return grammarSafe;
13067
+ }
13068
+ return "memory";
13069
+ }
13024
13070
  function selectCandidates(db, projectIdentity) {
13025
13071
  const memories = getMemoriesByProject(db, projectIdentity, ["active", "permanent"]);
13026
13072
  const cueState = getMuralCueState(db, memories.map((memory) => memory.id));
@@ -13189,10 +13235,19 @@ function applyCues(args, chunk, manifestText) {
13189
13235
  const candidate = byId.get(entry.id);
13190
13236
  if (!candidate)
13191
13237
  throw new Error(`cues manifest contains unknown id ${entry.id}`);
13192
- const failure = validateCue(entry.cue, candidate.memory.importance ?? 50);
13238
+ const importance = candidate.memory.importance ?? 50;
13239
+ const failure = validateCue(entry.cue, importance, candidate.memory.id);
13193
13240
  if (failure) {
13241
+ const rejectionCount = recordMuralCueRejection(args.db, args.projectIdentity, entry.id, candidate.contentHash);
13242
+ if (rejectionCount >= CUE_REJECTION_LATCH_THRESHOLD) {
13243
+ const fallback = deterministicFallbackCue(candidate, entry.cue);
13244
+ setMuralCue(args.db, args.projectIdentity, entry.id, fallback, candidate.contentHash);
13245
+ compressed += 1;
13246
+ log(`[dreamer] compress-cues: fallback cue for memory ${entry.id} (${failure.reason}; ${rejectionCount} rejections; fallback)`);
13247
+ continue;
13248
+ }
13194
13249
  skipped += 1;
13195
- log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason})`);
13250
+ log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason}; rejection ${rejectionCount}/${CUE_REJECTION_LATCH_THRESHOLD})`);
13196
13251
  continue;
13197
13252
  }
13198
13253
  setMuralCue(args.db, args.projectIdentity, entry.id, entry.cue.trim(), candidate.contentHash);
@@ -16954,6 +17009,19 @@ function countUnverifiedMappedMemories(db, projectPath) {
16954
17009
  AND v.verified_at = 0`).get(projectPath);
16955
17010
  return row?.cnt ?? 0;
16956
17011
  }
17012
+ function countBroadCycleCandidates(db, projectPath, cycleStartAt) {
17013
+ const row = db.prepare(`SELECT COUNT(*) AS cnt
17014
+ FROM memories m
17015
+ WHERE m.project_path = ?
17016
+ AND m.status IN ('active','permanent')
17017
+ AND (
17018
+ SELECT MAX(v.verified_at)
17019
+ FROM memory_verifications v
17020
+ WHERE v.memory_id = m.id
17021
+ AND v.file_path <> ''
17022
+ ) < ?`).get(projectPath, cycleStartAt);
17023
+ return row?.cnt ?? 0;
17024
+ }
16957
17025
  function countCueCandidates(db, projectPath) {
16958
17026
  if (!hasMuralCueColumns(db))
16959
17027
  return countActiveMemories(db, projectPath);
@@ -17009,7 +17077,9 @@ function getDreamTaskBacklog(db, projectPath, task, options = {}) {
17009
17077
  }
17010
17078
  case "verify-broad": {
17011
17079
  const total = countMappedMemories(db, projectPath);
17012
- return { pending: total, total };
17080
+ const cycleStartAt = getTaskScheduleState(db, projectPath, "verify-broad")?.lastBroadRunAt;
17081
+ const pending = cycleStartAt == null ? total : countBroadCycleCandidates(db, projectPath, cycleStartAt);
17082
+ return { pending, total };
17013
17083
  }
17014
17084
  case "curate": {
17015
17085
  const total = countActiveMemories(db, projectPath);
@@ -17068,7 +17138,7 @@ function evaluateTaskGate(task, ctx) {
17068
17138
  case "verify":
17069
17139
  return countActiveMemories(db, project) > 0;
17070
17140
  case "verify-broad":
17071
- return countActiveMemories(db, project) > 0;
17141
+ return getTaskScheduleState(db, project, "verify-broad")?.lastBroadRunAt != null || countActiveMemories(db, project) > 0;
17072
17142
  case "curate":
17073
17143
  return countActiveMemories(db, project) > 0;
17074
17144
  case "compress-cues":
@@ -17102,6 +17172,30 @@ import path4 from "node:path";
17102
17172
  function minOf(values) {
17103
17173
  return values.reduce((acc, v) => v < acc ? v : acc, Number.POSITIVE_INFINITY);
17104
17174
  }
17175
+ function ensureBroadCycleStart(args) {
17176
+ const current = getTaskScheduleState(args.db, args.projectIdentity, "verify-broad");
17177
+ if (current?.lastBroadRunAt != null && current.lastBroadRunAt > 0) {
17178
+ return current.lastBroadRunAt;
17179
+ }
17180
+ if (!current)
17181
+ return args.runStartedAt;
17182
+ if (!args.holderId || !args.leaseKey) {
17183
+ throw new Error("verify-broad cycle opening requires the task lease");
17184
+ }
17185
+ return runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
17186
+ const latest = getTaskScheduleState(args.db, args.projectIdentity, "verify-broad");
17187
+ if (!latest)
17188
+ return args.runStartedAt;
17189
+ if (latest.lastBroadRunAt != null && latest.lastBroadRunAt > 0) {
17190
+ return latest.lastBroadRunAt;
17191
+ }
17192
+ writeTaskScheduleState(args.db, {
17193
+ ...latest,
17194
+ lastBroadRunAt: args.runStartedAt
17195
+ });
17196
+ return args.runStartedAt;
17197
+ });
17198
+ }
17105
17199
  async function partitionVerifyScope(args) {
17106
17200
  const runStartedAt = args.now ?? Date.now();
17107
17201
  const active = getMemoriesByProject(args.db, args.projectIdentity);
@@ -17113,6 +17207,29 @@ async function partitionVerifyScope(args) {
17113
17207
  content: m.content,
17114
17208
  mappedFiles: verById.get(m.id)?.files ?? []
17115
17209
  });
17210
+ if (args.forceBroad) {
17211
+ const broadCycleStartAt = ensureBroadCycleStart({
17212
+ db: args.db,
17213
+ projectIdentity: args.projectIdentity,
17214
+ holderId: args.holderId,
17215
+ leaseKey: args.leaseKey,
17216
+ runStartedAt
17217
+ });
17218
+ const broadCandidates = candidates.filter((m) => (verById.get(m.id)?.verifiedAt ?? 0) < broadCycleStartAt).sort((a, b) => {
17219
+ const verifiedAtA = verById.get(a.id)?.verifiedAt ?? 0;
17220
+ const verifiedAtB = verById.get(b.id)?.verifiedAt ?? 0;
17221
+ return verifiedAtA - verifiedAtB || a.id - b.id;
17222
+ });
17223
+ return {
17224
+ runStartedAt,
17225
+ mode: "broad",
17226
+ inScope: broadCandidates.map(toPrompt),
17227
+ inScopeIds: broadCandidates.map((m) => m.id),
17228
+ skippedIds: candidates.filter((m) => !broadCandidates.some((candidate) => candidate.id === m.id)).map((m) => m.id),
17229
+ broadCycleStartAt,
17230
+ reason: `broad cycle (${broadCandidates.length} remain; started ${broadCycleStartAt})`
17231
+ };
17232
+ }
17116
17233
  if (candidates.length === 0) {
17117
17234
  return {
17118
17235
  runStartedAt,
@@ -17123,16 +17240,6 @@ async function partitionVerifyScope(args) {
17123
17240
  reason: "no file-mapped memories in scope"
17124
17241
  };
17125
17242
  }
17126
- if (args.forceBroad) {
17127
- return {
17128
- runStartedAt,
17129
- mode: "broad",
17130
- inScope: candidates.map(toPrompt),
17131
- inScopeIds: candidates.map((m) => m.id),
17132
- skippedIds: [],
17133
- reason: "broad full-pool verification of file-mapped memories"
17134
- };
17135
- }
17136
17243
  const allInScope = (mode, reason) => ({
17137
17244
  runStartedAt,
17138
17245
  mode,
@@ -17251,7 +17358,25 @@ function parseVerifyManifest(text) {
17251
17358
 
17252
17359
  // src/features/magic-context/dreamer/verify.ts
17253
17360
  var VERIFY_BATCH_SIZE = 50;
17361
+ function closeBroadCycle(args, cycleStartAt) {
17362
+ if (!args.forceBroad || cycleStartAt === undefined)
17363
+ return;
17364
+ if (!getTaskScheduleState(args.db, args.projectIdentity, "verify-broad"))
17365
+ return;
17366
+ runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
17367
+ const current = getTaskScheduleState(args.db, args.projectIdentity, "verify-broad");
17368
+ if (current?.lastBroadRunAt !== cycleStartAt)
17369
+ return;
17370
+ if (!current)
17371
+ return;
17372
+ writeTaskScheduleState(args.db, {
17373
+ ...current,
17374
+ lastBroadRunAt: null
17375
+ });
17376
+ });
17377
+ }
17254
17378
  async function runVerify(args) {
17379
+ const runStartedAt = Date.now();
17255
17380
  const result = {
17256
17381
  verified: 0,
17257
17382
  updated: 0,
@@ -17266,14 +17391,20 @@ async function runVerify(args) {
17266
17391
  db: args.db,
17267
17392
  projectIdentity: args.projectIdentity,
17268
17393
  projectDirectory: args.sessionDirectory,
17269
- forceBroad: args.forceBroad
17394
+ forceBroad: args.forceBroad,
17395
+ now: runStartedAt,
17396
+ holderId: args.holderId,
17397
+ leaseKey: args.leaseKey
17270
17398
  });
17271
17399
  result.mode = gate.mode;
17400
+ result.broadCycleStartAt = gate.broadCycleStartAt;
17272
17401
  result.inScope = gate.inScope.length;
17273
17402
  result.remaining = gate.inScope.length;
17274
17403
  log(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"} gate: mode=${gate.mode} in_scope=${gate.inScope.length} skipped=${gate.skippedIds.length} reason=${gate.reason}`);
17275
- if (gate.inScope.length === 0)
17404
+ if (gate.inScope.length === 0) {
17405
+ closeBroadCycle(args, gate.broadCycleStartAt);
17276
17406
  return result;
17407
+ }
17277
17408
  const batches = [];
17278
17409
  for (let i = 0;i < gate.inScope.length; i += VERIFY_BATCH_SIZE) {
17279
17410
  batches.push(gate.inScope.slice(i, i + VERIFY_BATCH_SIZE));
@@ -17296,6 +17427,8 @@ async function runVerify(args) {
17296
17427
  args.onProgress?.(result.verified + result.updated + result.archived);
17297
17428
  }
17298
17429
  result.complete = result.remaining === 0;
17430
+ if (result.complete)
17431
+ closeBroadCycle(args, gate.broadCycleStartAt);
17299
17432
  log(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: verified=${result.verified} updated=${result.updated} archived=${result.archived} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}`);
17300
17433
  return result;
17301
17434
  } finally {
@@ -17629,7 +17762,7 @@ function createDreamTaskExecutor(deps) {
17629
17762
  resultChars: 0,
17630
17763
  ...error ? { error } : {},
17631
17764
  backlog: (() => {
17632
- const end = getDreamTaskBacklog(db, projectIdentity, config.task);
17765
+ const end = extra?.backlogAfter ?? getDreamTaskBacklog(db, projectIdentity, config.task);
17633
17766
  const processed = processedDreamTaskItems(backlogAtStart.pending, end.pending);
17634
17767
  const value = {
17635
17768
  pendingAtStart: backlogAtStart.pending,
@@ -17764,19 +17897,31 @@ function createDreamTaskExecutor(deps) {
17764
17897
  fallbackModels: config.fallbackModels,
17765
17898
  language: config.language ?? deps.language,
17766
17899
  moduleRoute,
17767
- onProgress: (processed) => reportProgress(processed)
17900
+ onProgress: (processed2) => reportProgress(processed2)
17768
17901
  });
17902
+ const processed = result.verified + result.updated + result.archived;
17903
+ const broadProgress = config.task === "verify-broad" ? `verify-broad cycle ${result.broadCycleStartAt ?? "open"}: verified ${processed}, ${result.remaining} remain` : null;
17904
+ const backlogAfter = config.task === "verify-broad" ? { pending: result.remaining, total: backlogAtStart.total } : undefined;
17769
17905
  if (!result.complete) {
17906
+ if (broadProgress && processed > 0) {
17907
+ recordRun("completed", broadProgress, {
17908
+ memoryChanges: computeMemoryDelta(memoryBefore),
17909
+ backlogAfter
17910
+ });
17911
+ return { status: "completed", error: broadProgress };
17912
+ }
17770
17913
  const error = incompleteMessage(result.remaining);
17771
17914
  recordRun("failed", error, {
17772
- memoryChanges: computeMemoryDelta(memoryBefore)
17915
+ memoryChanges: computeMemoryDelta(memoryBefore),
17916
+ backlogAfter
17773
17917
  });
17774
17918
  return { status: "failed", transient: true, error };
17775
17919
  }
17776
- recordRun("completed", null, {
17777
- memoryChanges: computeMemoryDelta(memoryBefore)
17920
+ recordRun("completed", broadProgress, {
17921
+ memoryChanges: computeMemoryDelta(memoryBefore),
17922
+ backlogAfter
17778
17923
  });
17779
- return { status: "completed" };
17924
+ return broadProgress ? { status: "completed", error: broadProgress } : { status: "completed" };
17780
17925
  }
17781
17926
  if (config.task === "classify-memories") {
17782
17927
  let moduleArgs;
@@ -25110,7 +25255,8 @@ function loadContextUsage(contextUsageMap, db, sessionId) {
25110
25255
  if (persisted) {
25111
25256
  contextUsageMap.set(sessionId, {
25112
25257
  ...persisted,
25113
- lastResponseTime: persistedLastResponseTime ?? persisted.updatedAt
25258
+ lastResponseTime: persistedLastResponseTime ?? persisted.updatedAt,
25259
+ hasUsageTokens: false
25114
25260
  });
25115
25261
  return persisted.usage;
25116
25262
  }
@@ -29599,6 +29745,19 @@ function passUsage(usage, limit) {
29599
29745
  context_limit_tokens: limit
29600
29746
  };
29601
29747
  }
29748
+ function shouldDisarmRustEmergencyRecovery(input) {
29749
+ if (input.finalWireEstimate?.trusted === true && input.providerProvenLimitTokens > 0 && input.finalWireEstimate.tokens < input.providerProvenLimitTokens * 0.8) {
29750
+ return "trusted-final-wire";
29751
+ }
29752
+ if (!input.materialized || input.usagePercentage >= 80)
29753
+ return null;
29754
+ if (input.recoveryOrigin !== "provider_overflow")
29755
+ return "fresh-usage";
29756
+ if (input.usageEntry?.hasUsageTokens === true && (input.recoveryArmedAt === null || input.usageEntry.updatedAt > input.recoveryArmedAt)) {
29757
+ return "fresh-usage";
29758
+ }
29759
+ return null;
29760
+ }
29602
29761
  function directiveTextOf(response) {
29603
29762
  const directives = isRecord3(response.host_directives) ? response.host_directives : undefined;
29604
29763
  const channel2 = isRecord3(directives?.channel2_nudge) ? directives.channel2_nudge : undefined;
@@ -30078,6 +30237,7 @@ function createRustModeTransform(deps, options) {
30078
30237
  }
30079
30238
  }
30080
30239
  const reduceAvailability = resolveCtxReduceAvailability(sessionId);
30240
+ resolveTodowriteAvailabilityFromMessages(sessionId, messages);
30081
30241
  const toolPresent = reduceAvailability.frozen && reduceAvailability.callable;
30082
30242
  try {
30083
30243
  if (preflightError)
@@ -30337,6 +30497,7 @@ function createRustModeTransform(deps, options) {
30337
30497
  const pages = buildPagedModuleTransformPayloads(body);
30338
30498
  logStage(sessionId, "wireBuild", wireBuildStartedAt, timings, wireDelta ? `mode=tail_delta input=${encodedInput.length}` : "mode=full");
30339
30499
  let response;
30500
+ let servedFinalWireEstimate;
30340
30501
  for (const [index, page] of pages.entries()) {
30341
30502
  timings.transportBytes += Buffer.byteLength(JSON.stringify(page));
30342
30503
  const transportStartedAt = performance.now();
@@ -30484,6 +30645,15 @@ function createRustModeTransform(deps, options) {
30484
30645
  if (typeof boundaryId === "string" && boundaryId.length > 0) {
30485
30646
  assertNativeBoundary(appliedMessages, sessionId, boundaryId);
30486
30647
  }
30648
+ if (passInputs.emergency_recovery_armed === true) {
30649
+ servedFinalWireEstimate = estimateFinalWireInputTokens({
30650
+ messages: appliedMessages,
30651
+ systemPromptTokens: sessionMeta.systemPromptTokens,
30652
+ providerID: model?.providerID,
30653
+ modelID: model?.modelID,
30654
+ agentName: deps.getNotificationParams?.(sessionId)?.agent
30655
+ });
30656
+ }
30487
30657
  logStage(sessionId, "apply", applyStartedAt, timings);
30488
30658
  const lkgSnapshotStartedAt = performance.now();
30489
30659
  const explicitDecision = typeof response.decision === "string" || typeof response.action === "string" || typeof response.cache_bust === "boolean";
@@ -30572,10 +30742,20 @@ function createRustModeTransform(deps, options) {
30572
30742
  sessionLog(sessionId, "rust compartment mirror-back failed (ignored):", error);
30573
30743
  }
30574
30744
  }
30575
- if (materializeReason !== "none" && passUsageSnapshot.percentage < 80 && getOverflowState(deps.db, sessionId).needsEmergencyRecovery) {
30745
+ const currentOverflowState = getOverflowState(deps.db, sessionId, modelKey);
30746
+ const disarmEvidence = currentOverflowState.needsEmergencyRecovery ? shouldDisarmRustEmergencyRecovery({
30747
+ materialized: materializeReason !== "none",
30748
+ usagePercentage: passUsageSnapshot.percentage,
30749
+ recoveryOrigin: currentOverflowState.emergencyRecoveryOrigin,
30750
+ recoveryArmedAt: getEmergencyRecoveryArmedAt(sessionId),
30751
+ usageEntry: deps.contextUsageMap.get(sessionId),
30752
+ finalWireEstimate: servedFinalWireEstimate,
30753
+ providerProvenLimitTokens: currentOverflowState.detectedContextLimit
30754
+ }) : null;
30755
+ if (disarmEvidence) {
30576
30756
  try {
30577
30757
  clearEmergencyRecovery(deps.db, sessionId);
30578
- sessionLog(sessionId, `rust pass disarmed emergency recovery after ${materializeReason} at ${passUsageSnapshot.percentage.toFixed(1)}% usage`);
30758
+ sessionLog(sessionId, `rust pass disarmed emergency recovery via ${disarmEvidence} after ${materializeReason} at ${passUsageSnapshot.percentage.toFixed(1)}% usage`);
30579
30759
  } catch {}
30580
30760
  }
30581
30761
  wireCaches.set(sessionId, pendingWireCache);
@@ -32143,7 +32323,8 @@ function createEventHandler2(deps) {
32143
32323
  inputTokens: totalInputTokens
32144
32324
  },
32145
32325
  updatedAt: now,
32146
- lastResponseTime: now
32326
+ lastResponseTime: now,
32327
+ hasUsageTokens: true
32147
32328
  });
32148
32329
  updates.lastContextPercentage = percentage;
32149
32330
  updates.lastInputTokens = totalInputTokens;
@@ -33335,11 +33516,13 @@ function createMagicContextHook(deps) {
33335
33516
  const fence = getSchemaFenceRejection();
33336
33517
  recordHookInitFailure({
33337
33518
  type: "storage",
33338
- reason: migration && blockingProcesses.length > 0 ? {
33519
+ reason: migration && (blockingProcesses.length > 0 || migration.unreadableFile) ? {
33339
33520
  kind: "migration_guard",
33340
33521
  persistedVersion: migration.persistedVersion,
33341
33522
  supportedVersion: migration.supportedVersion,
33342
- blockingProcesses
33523
+ blockingProcesses,
33524
+ ...migration.unreadableFile ? { unreadableFile: migration.unreadableFile } : {},
33525
+ ...migration.unreadableArm ? { unreadableArm: migration.unreadableArm } : {}
33343
33526
  } : fence ? {
33344
33527
  kind: "schema_fence",
33345
33528
  persistedVersion: fence.persistedVersion,
@@ -35024,7 +35207,7 @@ function registerRpcHandlers(rpcServer, args) {
35024
35207
  const db = getDb();
35025
35208
  if (!db)
35026
35209
  return { ok: false, error: "db unavailable" };
35027
- const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-k72ejkkh.js");
35210
+ const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-6cd3nrt7.js");
35028
35211
  const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-6njqewzk.js");
35029
35212
  log(`[rpc] recomp requested for session ${sessionId}`);
35030
35213
  const ctx = await buildManagedCtx(db);
@@ -35040,7 +35223,7 @@ function registerRpcHandlers(rpcServer, args) {
35040
35223
  const db = getDb();
35041
35224
  if (!db)
35042
35225
  return { ok: false, error: "db unavailable" };
35043
- const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-k72ejkkh.js");
35226
+ const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-6cd3nrt7.js");
35044
35227
  const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-6njqewzk.js");
35045
35228
  log(`[rpc] session-upgrade requested for session ${sessionId}`);
35046
35229
  const ctx = await buildManagedCtx(db);
@@ -1 +1 @@
1
- {"version":3,"file":"create-session-hooks.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/create-session-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAO7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,wBAAwB;;;;;;;;;mBAC5C,CAAC;aAA2B,CAAC;aACnD,CAAC;eAA6B,CAAC;;;;;;;;;;;;;;;;;;;;eAsFq9gB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAzEpghB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC/C;;;;;;;;;qBAkE4zI,CAAC;;;;;;;;;;;;qBAA38C,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAAk1vD,CAAC;;;;;;;;;EArCjz1D;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAChD,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC/C;;;;;;;;;qBA8B4zI,CAAC;;;;;;;;;;;;qBAA38C,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAAk1vD,CAAC;;;;;;;;;GADjz1D"}
1
+ {"version":3,"file":"create-session-hooks.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/create-session-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAO7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,wBAAwB;;;;;;;;;mBAC5C,CAAC;aAA2B,CAAC;aACnD,CAAC;eAA6B,CAAC;;;;;;;;;;;;;;;;;;;;eAsFq9gB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAzEpghB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC/C;;;;;;;;;qBAkE4zI,CAAC;;;;;;;;;;;;qBAA38C,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAAutwD,CAAC;;;;;;;;;EArCtr2D;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAChD,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC/C;;;;;;;;;qBA8B4zI,CAAC;;;;;;;;;;;;qBAA38C,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAAutwD,CAAC;;;;;;;;;GADtr2D"}
@@ -9,7 +9,7 @@ import {
9
9
  setRecompNote,
10
10
  setRecompStarting,
11
11
  setRecompTerminal
12
- } from "./index-x8spt5wy.js";
12
+ } from "./index-z70pxrq1.js";
13
13
  import"./index-ry8rh8cv.js";
14
14
  import"./index-td9depx5.js";
15
15
  import"./index-cn960ffd.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.34.1",
3
+ "version": "0.34.2",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",