@cortexkit/opencode-magic-context 0.49.28 → 0.49.29

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 (114) hide show
  1. package/dist/auto-search-worker.js +3 -3
  2. package/dist/chunk-embedding-write-worker.js +1 -1
  3. package/dist/config/commit-retention-recovery.d.ts +9 -0
  4. package/dist/config/commit-retention-recovery.d.ts.map +1 -0
  5. package/dist/config/index.d.ts +2 -1
  6. package/dist/config/index.d.ts.map +1 -1
  7. package/dist/config/live-child-output-cap.d.ts.map +1 -1
  8. package/dist/config/live-run-config.d.ts.map +1 -1
  9. package/dist/config/project-security.d.ts +1 -0
  10. package/dist/config/project-security.d.ts.map +1 -1
  11. package/dist/{conflict-warning-hook-tgnw019g.js → conflict-warning-hook-xgskea1v.js} +3 -3
  12. package/dist/{context-dxfztzsd.js → context-836j3vte.js} +63 -27
  13. package/dist/{embedding-backfill-cwnyr4fj.js → embedding-backfill-mms9nb0h.js} +2 -2
  14. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  15. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -1
  16. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  18. package/dist/features/magic-context/dreamer/verify-diff.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  20. package/dist/features/magic-context/git-commits/indexer.d.ts +2 -0
  21. package/dist/features/magic-context/git-commits/indexer.d.ts.map +1 -1
  22. package/dist/features/magic-context/project-embedding-registry.d.ts +3 -1
  23. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  24. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  25. package/dist/features/magic-context/work-metrics.d.ts +5 -3
  26. package/dist/features/magic-context/work-metrics.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/apply-operations.d.ts +2 -0
  28. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/compartment-runner-types.d.ts +5 -1
  30. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +3 -1
  32. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/lkg-slot.d.ts +7 -0
  35. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/read-session-db.d.ts +3 -2
  38. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/replay-committed-drops.d.ts.map +1 -1
  40. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  41. package/dist/{index-n8qmmd7f.js → index-093c4g1c.js} +3 -3
  42. package/dist/{index-89k1w6x2.js → index-a1h316s9.js} +2 -2
  43. package/dist/{index-fq2p158w.js → index-bps8vn9r.js} +13 -7
  44. package/dist/{index-tvzvjggy.js → index-gkee6p4g.js} +1 -1
  45. package/dist/{index-a2fz9hpa.js → index-gxkhzmjq.js} +4 -2
  46. package/dist/{index-4cpc59jv.js → index-h4s5jk7f.js} +1 -1
  47. package/dist/{index-t3rbb8wr.js → index-pe6b4bhs.js} +1 -1
  48. package/dist/{index-dcqk0y27.js → index-q9zvphbq.js} +104 -24
  49. package/dist/{index-7gbcg8xv.js → index-tx68g9nc.js} +1 -1
  50. package/dist/{index-4ypqzvhf.js → index-vnn5405n.js} +1 -1
  51. package/dist/{index-077ht5cq.js → index-waktfbjy.js} +1 -1
  52. package/dist/{index-k9jx7ma9.js → index-wpcdk76y.js} +325 -249
  53. package/dist/{index-dzfevacx.js → index-wvffze8y.js} +10 -6
  54. package/dist/{index-31y1mznz.js → index-wyt5m81v.js} +4 -4
  55. package/dist/{index-v0dhhxsq.js → index-y1qwzvxn.js} +5 -5
  56. package/dist/{index-yzjhx10y.js → index-zhgqgxtt.js} +5 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +26 -30
  59. package/dist/{message-index-bounded-7ayzb2ah.js → message-index-bounded-7qsn4fd3.js} +3 -3
  60. package/dist/migration-worker.js +1 -1
  61. package/dist/plugin/dream-timer.d.ts.map +1 -1
  62. package/dist/plugin/embedding-bootstrap-helpers.d.ts +5 -1
  63. package/dist/plugin/embedding-bootstrap-helpers.d.ts.map +1 -1
  64. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  65. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  66. package/dist/{project-embedding-registry-94nncs5g.js → project-embedding-registry-cg281d9j.js} +1 -1
  67. package/dist/raw-ordinal-warmup-worker.js +2 -2
  68. package/dist/{read-session-chunk-jzb6w9w5.js → read-session-chunk-a5d0q3m0.js} +2 -2
  69. package/dist/{recomp-orchestrator-02sa2ngr.js → recomp-orchestrator-na34m4c5.js} +10 -10
  70. package/dist/{search-spq6nfyf.js → search-0cd6hx7a.js} +7 -7
  71. package/dist/{search-archive-q1vw7zg4.js → search-archive-66pm17gm.js} +3 -3
  72. package/dist/{send-session-notification-afzzqy5b.js → send-session-notification-vz86nt79.js} +2 -2
  73. package/dist/{transform-postprocess-phase-6menyyxc.js → transform-postprocess-phase-27we33af.js} +10 -10
  74. package/dist/v2/auto-search-worker.js +3 -3
  75. package/dist/v2/chunk-embedding-write-worker.js +1 -1
  76. package/dist/v2/{context-0qhz1nnj.js → context-g4ptae4x.js} +197 -80
  77. package/dist/v2/{embedding-backfill-rh5dgsva.js → embedding-backfill-35k6czrr.js} +2 -2
  78. package/dist/v2/hidden-completion.d.ts.map +1 -1
  79. package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
  80. package/dist/v2/hooks/store.d.ts.map +1 -1
  81. package/dist/v2/{message-index-bounded-n09b74vr.js → message-index-bounded-7363502m.js} +3 -3
  82. package/dist/v2/migration-worker.js +1 -1
  83. package/dist/v2/{project-embedding-registry-6pak822h.js → project-embedding-registry-p1p10ks7.js} +1 -1
  84. package/dist/v2/raw-ordinal-warmup-worker.js +2 -2
  85. package/dist/v2/{read-session-chunk-vpt69tw9.js → read-session-chunk-kkppfhft.js} +2 -2
  86. package/dist/v2/{recomp-orchestrator-txsmbnvw.js → recomp-orchestrator-f1df1gb8.js} +10 -10
  87. package/dist/v2/{search-dcy9b6gd.js → search-2v3xyzse.js} +7 -7
  88. package/dist/v2/{search-archive-t9bcz4ht.js → search-archive-v07jpw25.js} +3 -3
  89. package/dist/v2/{send-session-notification-vdsgnf4c.js → send-session-notification-x5nzy34v.js} +2 -2
  90. package/dist/v2/{server-e3hc93wk.js → server-77gznpmf.js} +1 -1
  91. package/dist/v2/{server-94wk1ey3.js → server-835q39kd.js} +45 -5
  92. package/dist/v2/{server-txbc3czn.js → server-976dxaxh.js} +10 -6
  93. package/dist/v2/{server-3vhxy2k5.js → server-a7x00tw8.js} +5 -5
  94. package/dist/v2/{server-z2n2xaeh.js → server-k9je35ev.js} +1 -1
  95. package/dist/v2/{server-xkvxss5g.js → server-mxzj3r0y.js} +5 -1
  96. package/dist/v2/{server-6avtp9jp.js → server-p0snacz3.js} +1 -1
  97. package/dist/v2/{server-z3mk9jdc.js → server-ph300d6m.js} +1 -1
  98. package/dist/v2/{server-jj9qye8y.js → server-q50ttc2g.js} +62 -21
  99. package/dist/v2/{server-6v3cdzsx.js → server-qc915kw2.js} +1 -1
  100. package/dist/v2/{server-zmcrvpm3.js → server-w79f8ejn.js} +2 -2
  101. package/dist/v2/{server-yqek3s4k.js → server-zh3esb0z.js} +4 -2
  102. package/dist/v2/server.js +3 -3
  103. package/dist/v2/{wrapup-orchestrator-gjkszser.js → wrapup-orchestrator-jq33fda8.js} +10 -10
  104. package/dist/{wrapup-orchestrator-n5h5sr1x.js → wrapup-orchestrator-f0xr7pft.js} +11 -11
  105. package/package.json +1 -1
  106. package/src/config/commit-retention-recovery.ts +34 -0
  107. package/src/config/index.ts +22 -2
  108. package/src/config/live-child-output-cap.test.ts +28 -0
  109. package/src/config/live-child-output-cap.ts +2 -0
  110. package/src/config/live-run-config.test.ts +44 -1
  111. package/src/config/live-run-config.ts +8 -1
  112. package/src/config/project-config-trust-boundary.test.ts +57 -0
  113. package/src/config/project-security.ts +6 -2
  114. package/src/shared/windows-hidden-spawns.test.ts +133 -23
@@ -15,11 +15,12 @@ import {
15
15
  parseTree,
16
16
  parseJsoncRecovering,
17
17
  detectConfigFile,
18
+ copyCommitRetentionRecovery,
18
19
  cortexKitUserConfigBasePath,
19
20
  cortexKitProjectConfigBasePath,
20
21
  resolveLegacyConfigSourcesForHarness,
21
22
  loadPluginConfigDetailed
22
- } from "./server-94wk1ey3.js";
23
+ } from "./server-835q39kd.js";
23
24
  import {
24
25
  catalogOutputReserve,
25
26
  getSdkContextLimit,
@@ -41,7 +42,7 @@ import {
41
42
  getProjectChunkEmbeddingModelId2,
42
43
  getProjectEmbeddingMaxInputTokens2,
43
44
  embedItemsForProject2
44
- } from "./server-yqek3s4k.js";
45
+ } from "./server-zh3esb0z.js";
45
46
  import {
46
47
  hasMeaningfulUserText2,
47
48
  estimateTokens,
@@ -87,7 +88,7 @@ import {
87
88
  toMessageIndexSource,
88
89
  clearIndexedMessagesInTransaction,
89
90
  indexSourcesAfterOrdinal
90
- } from "./server-z2n2xaeh.js";
91
+ } from "./server-k9je35ev.js";
91
92
  import {
92
93
  retreatPastHostUnservedRows,
93
94
  snapTerminalCompartmentToServedRow,
@@ -186,7 +187,7 @@ import {
186
187
  getRawSessionTagKeysThrough2,
187
188
  getLegacyProtectedTailStartOrdinal2,
188
189
  readSessionChunk2
189
- } from "./server-xkvxss5g.js";
190
+ } from "./server-mxzj3r0y.js";
190
191
  import {
191
192
  getTableColumnNames,
192
193
  tagTombstoneOwnerRange,
@@ -201,7 +202,7 @@ import {
201
202
  LATEST_SUPPORTED_VERSION,
202
203
  getPersistedSchemaVersion,
203
204
  openDatabase
204
- } from "./server-e3hc93wk.js";
205
+ } from "./server-77gznpmf.js";
205
206
  import {
206
207
  providerMass,
207
208
  calibrationForModelKey,
@@ -230,7 +231,7 @@ import {
230
231
  openCodeDbExists,
231
232
  withReadOnlySessionDb,
232
233
  getMessageTimesFromOpenCodeDb
233
- } from "./server-3vhxy2k5.js";
234
+ } from "./server-a7x00tw8.js";
234
235
  import {
235
236
  BoundedSessionMap,
236
237
  getMeasuredToolDefinitionTokens
@@ -263,7 +264,7 @@ import {
263
264
  userFacingFailureCode,
264
265
  promoteSessionFactsDurable,
265
266
  embedPromotedFacts
266
- } from "./server-z3mk9jdc.js";
267
+ } from "./server-ph300d6m.js";
267
268
  import {
268
269
  isMarkerCandidateBasisCurrent2,
269
270
  invalidateMarkerCandidateBasis2,
@@ -288,7 +289,7 @@ import {
288
289
  } from "./server-53eh1r8r.js";
289
290
  import {
290
291
  sendStatusNotification2
291
- } from "./server-6v3cdzsx.js";
292
+ } from "./server-qc915kw2.js";
292
293
  import {
293
294
  piModelRefToCanonical
294
295
  } from "./server-avwt563y.js";
@@ -473,7 +474,13 @@ function sampleLiveConfig(boot, fresh) {
473
474
  if (leaf !== undefined)
474
475
  target[leaf] = value;
475
476
  }
476
- return result;
477
+ const sampled = result;
478
+ const freshCommitIndexing = fresh.memory?.git_commit_indexing;
479
+ const sampledCommitIndexing = sampled.memory?.git_commit_indexing;
480
+ if (freshCommitIndexing && sampledCommitIndexing) {
481
+ copyCommitRetentionRecovery(freshCommitIndexing, sampledCommitIndexing);
482
+ }
483
+ return sampled;
477
484
  }
478
485
  function removeLeaf(root, parts) {
479
486
  const parents = parts.slice(0, -1);
@@ -538,6 +545,7 @@ function withLiveDreamerOutputCap(executor, boot, fresh) {
538
545
  }),
539
546
  attempt: (handle, request) => executor.attempt(handle, request),
540
547
  collect: (handle, limit) => executor.collect(handle, limit),
548
+ collectPartial: (handle, limit) => executor.collectPartial?.(handle, limit) ?? executor.collect(handle, limit),
541
549
  close: (handle, settlement) => executor.close(handle, settlement)
542
550
  };
543
551
  }
@@ -3358,6 +3366,8 @@ function projectEntryWithDigests(messages, digests) {
3358
3366
  value: () => contentDigest,
3359
3367
  enumerable: false
3360
3368
  });
3369
+ if (isCoveredInstructionRow(message.info))
3370
+ markCoveredInstructionRow(projection);
3361
3371
  return projection;
3362
3372
  });
3363
3373
  }
@@ -3434,7 +3444,7 @@ function asEntryProjection(input) {
3434
3444
  }
3435
3445
  return projectLkgEntry(input);
3436
3446
  }
3437
- function outputMessageIsPostAnchor(message, inputIndexById, anchorIndex) {
3447
+ function outputMessageIsPostAnchor(message, inputIndexById, anchorIndex, systemIndices) {
3438
3448
  const id = messageId(message);
3439
3449
  if (id !== null) {
3440
3450
  const inputIndex = inputIndexById.get(id);
@@ -3453,6 +3463,10 @@ function outputMessageIsPostAnchor(message, inputIndexById, anchorIndex) {
3453
3463
  }
3454
3464
  if (isCoveredInstructionRow(message.info))
3455
3465
  return false;
3466
+ if (messageRole(message) === "system") {
3467
+ const index = systemIndices.get(message);
3468
+ return index === undefined ? null : index > anchorIndex;
3469
+ }
3456
3470
  if (!isSyntheticOutput(message))
3457
3471
  return null;
3458
3472
  const linked = ["sourceMessageId", "ownerMessageId", "anchorMessageId"].map((key) => recordValue(message.info, key)).find((value) => typeof value === "string");
@@ -3466,7 +3480,7 @@ function buildLkgPrefix(input, output, completeOutput = false) {
3466
3480
  const anchorIndex = completeOutput && projected.length > 0 ? projected.length - 1 : findLkgAnchor(projected);
3467
3481
  if (anchorIndex === null)
3468
3482
  return null;
3469
- const ids = projected.map((message) => message.id);
3483
+ const ids = projected.map((message, index) => lkgInputIdentity(message.id, message.role, index));
3470
3484
  if (ids.some((id) => id === null))
3471
3485
  return null;
3472
3486
  const validIds = ids;
@@ -3477,9 +3491,27 @@ function buildLkgPrefix(input, output, completeOutput = false) {
3477
3491
  if (inputContentDigests.some((digest) => digest === null))
3478
3492
  return null;
3479
3493
  const inputIndexById = new Map(validIds.map((id, index) => [id, index]));
3494
+ const systemIndices = new Map;
3495
+ if (!completeOutput) {
3496
+ const inputSystems = projected.flatMap((message, index) => message.id === null && message.role === "system" && !isCoveredInstructionRow(message) ? [{ message, index }] : []);
3497
+ const outputSystems = output.filter((message) => messageId(message) === null && messageRole(message) === "system");
3498
+ const restoredCount = outputSystems.length - inputSystems.length;
3499
+ if (restoredCount < 0 || outputSystems.slice(0, restoredCount).some((message) => !isCoveredInstructionRow(message.info)))
3500
+ return null;
3501
+ for (let index = 0;index < inputSystems.length; index += 1) {
3502
+ const source = inputSystems[index];
3503
+ const message = outputSystems[index + restoredCount];
3504
+ const digest = source.message.contentDigest?.();
3505
+ if (!digest || lkgContentDigest(message) !== digest)
3506
+ return null;
3507
+ if (isCoveredInstructionRow(message.info) && source.index > anchorIndex)
3508
+ return null;
3509
+ systemIndices.set(message, source.index);
3510
+ }
3511
+ }
3480
3512
  const prefix = [];
3481
3513
  for (const message of output) {
3482
- const postAnchor = completeOutput ? false : outputMessageIsPostAnchor(message, inputIndexById, anchorIndex);
3514
+ const postAnchor = completeOutput ? false : outputMessageIsPostAnchor(message, inputIndexById, anchorIndex, systemIndices);
3483
3515
  if (postAnchor === null)
3484
3516
  return null;
3485
3517
  if (!postAnchor)
@@ -3906,6 +3938,12 @@ function noteLkgRecoveryPrefix(args) {
3906
3938
  return true;
3907
3939
  }
3908
3940
  function readLkgRecoveryPrefix(sessionId, inputs, messages, db) {
3941
+ return readRecoveryIdentityPrefix(sessionId, inputs.map((input, index) => ({
3942
+ id: lkgInputIdentity(input.id, input.role, index),
3943
+ contentDigest: input.contentDigest
3944
+ })), messages, db);
3945
+ }
3946
+ function readRecoveryIdentityPrefix(sessionId, inputs, messages, db) {
3909
3947
  const state = sessions.get(sessionId);
3910
3948
  const slot = db && (!state || state.prefix || state.uncertifiedNormal) ? loadPersistedLkgSlot(db, sessionId, true) ?? getSlot(sessionId) : getSlot(sessionId);
3911
3949
  const prefix = state?.prefix;
@@ -3924,8 +3962,8 @@ function noteLkgHealthyPrefix(sessionId, inputs, messages, release) {
3924
3962
  fenceRevision: sessions.get(sessionId)?.fenceRevision,
3925
3963
  prefix: prefix && !release ? {
3926
3964
  ...prefix,
3927
- inputs: inputs.map((input) => ({
3928
- id: input.id ?? "",
3965
+ inputs: inputs.map((input, index) => ({
3966
+ id: lkgInputIdentity(input.id, input.role, index) ?? "",
3929
3967
  digest: input.contentDigest?.() ?? ""
3930
3968
  })),
3931
3969
  json: JSON.stringify(messages)
@@ -3944,10 +3982,16 @@ function lkgRecoveryEntryUnproven(sessionId, entry, messages) {
3944
3982
  id,
3945
3983
  contentDigest: () => digests[index] ?? null
3946
3984
  }));
3947
- return !!readLkgRecoveryPrefix(sessionId, inputs, messages).rebuildReason;
3985
+ return !!readRecoveryIdentityPrefix(sessionId, inputs, messages).rebuildReason;
3948
3986
  }
3949
3987
 
3950
3988
  // src/hooks/magic-context/lkg-slot.ts
3989
+ var POSITIONAL_SYSTEM_KEY = "\x00mc-system:";
3990
+ function lkgInputIdentity(id, role, index) {
3991
+ if (typeof id === "string" && id.length > 0)
3992
+ return id.startsWith(POSITIONAL_SYSTEM_KEY) ? null : id;
3993
+ return role === "system" ? `${POSITIONAL_SYSTEM_KEY}${index}` : null;
3994
+ }
3951
3995
  var LKG_SINGLE_SLOT_BYTES = 72 * 1024 * 1024;
3952
3996
  var LKG_TOTAL_BYTES = 160 * 1024 * 1024;
3953
3997
  var LKG_METADATA_BYTES = 256;
@@ -4441,11 +4485,8 @@ function noteEntry(sessionId, input) {
4441
4485
  const slot = getSlot(sessionId);
4442
4486
  if (!slot)
4443
4487
  return null;
4444
- const messages = input.some((message) => isCoveredInstructionRow(message.info)) ? input.filter((message) => !isCoveredInstructionRow(message.info)) : input;
4445
- const entryInputIds = messages.map((message) => {
4446
- const id = message.info?.id;
4447
- return typeof id === "string" ? id : "";
4448
- });
4488
+ const messages = input;
4489
+ const entryInputIds = messages.map((message, index) => lkgInputIdentity(message.info?.id, message.info?.role, index) ?? "");
4449
4490
  const anchorIndex = entryInputIds.indexOf(slot.lastInputMessageId);
4450
4491
  if (anchorIndex < 0)
4451
4492
  return null;
@@ -20502,4 +20543,4 @@ ${failure}`;
20502
20543
  }
20503
20544
  }
20504
20545
 
20505
- export { historianRunConfig, dreamerRunConfig, pluginConfigReader, currentPluginConfigReader, withLiveDreamerOutputCap, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, queueM0Mutation, getMaxM0MutationId, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getUncoveredCompartmentEndsThrough, providerResponseFailed, isSuccessfulProviderCompletion, LkgRecoveryFenceError, lkgServedArrayDigest, hasCleanLkgRecoveryFence, dirtyLkgRecoveryRevision, ownsLkgDirtyFence, invalidateCleanLkgRecoveryFence, prepareLkgCaptureFence, certifyCommittedLkgCapture, markLkgRecoveryDirty, rememberUnpublishedAutoSearchNoHint, getUnpublishedAutoSearchNoHint, forgetUnpublishedAutoSearchNoHint, registerAutoSearchWork, gaDatabasePath, RAW_MESSAGE_TYPES, V2StoreReaderPool, V2StoreReader, advanceSessionActivity, backfillSessionActivity, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, clearSession, requestPendingMaterialization, pendingMaterializationOrigin, hasPendingMaterializationOrigin, clearPendingMaterialization, recordSystemPromptForRequest, recordHeldHeadForRequest, bindSystemPromptResponse, isHeldHeadForRequest, deferDeliveredSystemRefresh, retirePendingSystemPromptDelivery, lkgProviderInputTotal, beginV2LkgRequest, claimLkgRequestIdentity, currentLkgRequestIdentity, noteCapturedLkgRequest, noteLkgProviderResponse, measuredLkgPrefix, clearLkgMeasuredRequest, saveLkgSlotToDb, clearPersistedLkgSlotStrict, loadPersistedLkgSlot, drainStaleLkgSlots, resolveLkgModelKeys, createLkgEntryProjector, captureLkgSlot, validateAnthropicReasoningRuns, validateLkgSeam, replayLkg, coldStartRawServedIndex, coldStartUncapturedReplay, noteUncertifiedNormalLkg, hasProcessLocalLkgProof, lkgDirtyRevision, rememberLkgDirtyRevision, readPersistedLkgUntaggedInputIds, persistLkgUntaggedInputIds, noteLkgRecoveryPrefix, readLkgRecoveryPrefix, noteLkgHealthyPrefix, lkgRecoveryReplayUnproven, lkgRecoveryEntryUnproven, beginLkgPass, visitMessageContentFields, contentSnapshotValue, messageContentFields, signatureForFields, exactReusablePrefix, incrementalLkgContentDigests, lkgSlotRejection, captureSlot, getInMemorySlot, getSlot, forgetInMemorySlot, dropSlot, noteEntry, getLkgSlotHeapStats, TOOL_SWEEP_SCOPED_MARKER, useScopedToolSweep, createPreAdoptionToolSweepResolver, copySessionStateForClone, queueMemoryMutation, getMaxMemoryMutationIdForProjects, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, readCoordinateGeneration, rebaseSessionCoordinatesAsync, HiddenCompletionRefusal, getOpenCodeDbPath, compareOpenCodeMessagesByCanonicalOrder, prepareCompactionMarkerCandidates, removeMcOwnedCompactionMarkers, getCompartmentEvents, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, DreamerProviderOutputFailureError, withDreamerModelCooldown, providerOutputFailureFromInvalidManifest, DREAMER_AGENT, DREAMER_RETROSPECTIVE_AGENT, DREAMER_PRIMER_INVESTIGATOR_AGENT, DREAMER_MEMORY_MAPPER_AGENT, DREAMER_CLASSIFIER_AGENT, DREAMER_DOCS_AGENT, DREAMER_REVIEWER_AGENT, HIDDEN_HISTORIAN_AGENT, HIDDEN_DREAMER_AGENT, HIDDEN_CURATE_AGENT, hiddenAgentFor, hiddenToolLoop, HIDDEN_RUN_DISPOSED_REASON, noteChildOfDisposedInstance, hiddenChildPermissions, registerHiddenChildAgents, hiddenToolCallRefusal, HiddenAgentStepLimit, HiddenChildHook, extractLatestAssistantText, hasLengthCappedOutput, parseProviderModel, modelBodyField, toModelEntry, ModelProducedNoOutputError, noteModelActivityMonitored, noteModelOutputReceived, isPromptTimeoutError, getPromptFailureDetail, raceWithSignal, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, annotateSubagentInvocationError, failedInvocationStatus, sumTokensFromChildMessages, recordChildInvocation, createPromptAsyncTransport, CTX_NOTE_LIGHT_DESCRIPTION, ACTIVE_TOOL_IDS, systemPromptFingerprint, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, MARKER_SUMMARY_TEXT, markerUpdateDefinitelyDidNotCut, applyDeferredCompactionMarker, teardownChildSession, runTokenLog, formatRunTokenLog, createChildSessionWithFence, buildMagicContextSection, getMuralIdentity, getMural, modelKeyAcceptsImages, resolveMuralWire, extractM0Block, formatDate, TEMPORAL_MARKER_REPLAY_PATTERN, collectTemporalCandidates, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, selectHiddenMessagesAtCompactionSeam, prepareCompartmentInjection, renderCompartmentInjection, MaterializeContentionError, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, materializeM0, hydrateCachedM0Mural, resetPrefixTrimFallbackState, findHostCompactionWindow, capturePrefixTrimSourceOrder, prepareCachedM0M1Replay, hasCompleteCachedM0M1, injectM0M1, clampProducerAtomChars, producerInputTokenLimit, historianProducerReserve, producerPromptFailureReason, resolveHiddenCompletionExecutor, createV1HiddenCompletionExecutor, shouldWaitForNewHistorianHistory, EMPTY_READ_REPLY, noteTouchedAt, renderGlance, renderNotesById, formatWriteReply, observeNoteNudgeServe, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, omitIncompleteFileTokenTotals, describeBoundaryDiagnostics, RECOVERY_NO_HEAD_LIMIT, deriveProtectedTailTokenTarget, selectPerRunCap, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, noteTransformPassForExactOrdinalReads, runCompartmentAgent, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, isRecompFailure2, isRecompSkip2, extractRecompReason2, setRecompStarting2, setRecompNote2, setRecompTerminal2, buildRecompDeps2, runManagedRecomp2 };
20546
+ export { historianRunConfig, dreamerRunConfig, pluginConfigReader, currentPluginConfigReader, withLiveDreamerOutputCap, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, queueM0Mutation, getMaxM0MutationId, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getUncoveredCompartmentEndsThrough, providerResponseFailed, isSuccessfulProviderCompletion, LkgRecoveryFenceError, lkgServedArrayDigest, hasCleanLkgRecoveryFence, dirtyLkgRecoveryRevision, ownsLkgDirtyFence, invalidateCleanLkgRecoveryFence, prepareLkgCaptureFence, certifyCommittedLkgCapture, markLkgRecoveryDirty, rememberUnpublishedAutoSearchNoHint, getUnpublishedAutoSearchNoHint, forgetUnpublishedAutoSearchNoHint, registerAutoSearchWork, gaDatabasePath, RAW_MESSAGE_TYPES, V2StoreReaderPool, V2StoreReader, advanceSessionActivity, backfillSessionActivity, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, clearSession, requestPendingMaterialization, pendingMaterializationOrigin, hasPendingMaterializationOrigin, clearPendingMaterialization, recordSystemPromptForRequest, recordHeldHeadForRequest, bindSystemPromptResponse, isHeldHeadForRequest, deferDeliveredSystemRefresh, retirePendingSystemPromptDelivery, lkgProviderInputTotal, beginV2LkgRequest, claimLkgRequestIdentity, currentLkgRequestIdentity, noteCapturedLkgRequest, noteLkgProviderResponse, measuredLkgPrefix, clearLkgMeasuredRequest, saveLkgSlotToDb, clearPersistedLkgSlotStrict, loadPersistedLkgSlot, drainStaleLkgSlots, resolveLkgModelKeys, createLkgEntryProjector, captureLkgSlot, validateAnthropicReasoningRuns, validateLkgSeam, replayLkg, coldStartRawServedIndex, coldStartUncapturedReplay, noteUncertifiedNormalLkg, hasProcessLocalLkgProof, lkgDirtyRevision, rememberLkgDirtyRevision, readPersistedLkgUntaggedInputIds, persistLkgUntaggedInputIds, noteLkgRecoveryPrefix, readLkgRecoveryPrefix, noteLkgHealthyPrefix, lkgRecoveryReplayUnproven, lkgRecoveryEntryUnproven, lkgInputIdentity, beginLkgPass, visitMessageContentFields, contentSnapshotValue, messageContentFields, signatureForFields, exactReusablePrefix, incrementalLkgContentDigests, lkgSlotRejection, captureSlot, getInMemorySlot, getSlot, forgetInMemorySlot, dropSlot, noteEntry, getLkgSlotHeapStats, TOOL_SWEEP_SCOPED_MARKER, useScopedToolSweep, createPreAdoptionToolSweepResolver, copySessionStateForClone, queueMemoryMutation, getMaxMemoryMutationIdForProjects, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, readCoordinateGeneration, rebaseSessionCoordinatesAsync, HiddenCompletionRefusal, getOpenCodeDbPath, compareOpenCodeMessagesByCanonicalOrder, prepareCompactionMarkerCandidates, removeMcOwnedCompactionMarkers, getCompartmentEvents, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, DreamerProviderOutputFailureError, withDreamerModelCooldown, providerOutputFailureFromInvalidManifest, DREAMER_AGENT, DREAMER_RETROSPECTIVE_AGENT, DREAMER_PRIMER_INVESTIGATOR_AGENT, DREAMER_MEMORY_MAPPER_AGENT, DREAMER_CLASSIFIER_AGENT, DREAMER_DOCS_AGENT, DREAMER_REVIEWER_AGENT, HIDDEN_HISTORIAN_AGENT, HIDDEN_DREAMER_AGENT, HIDDEN_CURATE_AGENT, hiddenAgentFor, hiddenToolLoop, HIDDEN_RUN_DISPOSED_REASON, noteChildOfDisposedInstance, hiddenChildPermissions, registerHiddenChildAgents, hiddenToolCallRefusal, HiddenAgentStepLimit, HiddenChildHook, extractLatestAssistantText, hasLengthCappedOutput, parseProviderModel, modelBodyField, toModelEntry, ModelProducedNoOutputError, noteModelActivityMonitored, noteModelOutputReceived, isPromptTimeoutError, getPromptFailureDetail, raceWithSignal, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, annotateSubagentInvocationError, failedInvocationStatus, emptyTokenTotals, sumTokensFromChildMessages, recordChildInvocation, createPromptAsyncTransport, CTX_NOTE_LIGHT_DESCRIPTION, ACTIVE_TOOL_IDS, systemPromptFingerprint, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, MARKER_SUMMARY_TEXT, markerUpdateDefinitelyDidNotCut, applyDeferredCompactionMarker, teardownChildSession, runTokenLog, formatRunTokenLog, createChildSessionWithFence, buildMagicContextSection, getMuralIdentity, getMural, modelKeyAcceptsImages, resolveMuralWire, extractM0Block, formatDate, TEMPORAL_MARKER_REPLAY_PATTERN, collectTemporalCandidates, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, selectHiddenMessagesAtCompactionSeam, prepareCompartmentInjection, renderCompartmentInjection, MaterializeContentionError, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, materializeM0, hydrateCachedM0Mural, resetPrefixTrimFallbackState, findHostCompactionWindow, capturePrefixTrimSourceOrder, prepareCachedM0M1Replay, hasCompleteCachedM0M1, injectM0M1, clampProducerAtomChars, producerInputTokenLimit, historianProducerReserve, producerPromptFailureReason, resolveHiddenCompletionExecutor, createV1HiddenCompletionExecutor, shouldWaitForNewHistorianHistory, EMPTY_READ_REPLY, noteTouchedAt, renderGlance, renderNotesById, formatWriteReply, observeNoteNudgeServe, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, omitIncompleteFileTokenTotals, describeBoundaryDiagnostics, RECOVERY_NO_HEAD_LIMIT, deriveProtectedTailTokenTarget, selectPerRunCap, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, noteTransformPassForExactOrdinalReads, runCompartmentAgent, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, isRecompFailure2, isRecompSkip2, extractRecompReason2, setRecompStarting2, setRecompNote2, setRecompTerminal2, buildRecompDeps2, runManagedRecomp2 };
@@ -10,7 +10,7 @@ import {
10
10
  } from "./server-1bw1wcbp.js";
11
11
  import {
12
12
  shouldHoldIgnoredNotification
13
- } from "./server-3vhxy2k5.js";
13
+ } from "./server-a7x00tw8.js";
14
14
  import {
15
15
  getErrorMessage
16
16
  } from "./server-y8v6yerm.js";
@@ -13,11 +13,11 @@ import {
13
13
  import {
14
14
  openCodeDbExists,
15
15
  withReadOnlySessionDb
16
- } from "./server-3vhxy2k5.js";
16
+ } from "./server-a7x00tw8.js";
17
17
  import {
18
18
  hasRawMessageProvider2,
19
19
  readRawSessionMessageIdOrdinalsForRange2
20
- } from "./server-xkvxss5g.js";
20
+ } from "./server-mxzj3r0y.js";
21
21
 
22
22
  // src/tools/ctx-expand/search-archive.ts
23
23
  var archiveReadsOnThisThread = 0;
@@ -1397,6 +1397,7 @@ function snapshotFor(registration) {
1397
1397
  runtimeFingerprint: registration.runtimeFingerprint,
1398
1398
  generation: registration.generation,
1399
1399
  features: { ...registration.features },
1400
+ ...registration.memoryDisabledReason ? { memoryDisabledReason: registration.memoryDisabledReason } : {},
1400
1401
  enabled,
1401
1402
  historyEnabled,
1402
1403
  gitCommitEnabled,
@@ -2366,7 +2367,7 @@ async function runShadowWorker() {
2366
2367
  await new Promise((resolve) => setTimeout(resolve, 0));
2367
2368
  }
2368
2369
  }
2369
- function registerProjectInObservationMode2(db, projectIdentity, sourceDirectory, failedConfig, failureSummary) {
2370
+ function registerProjectInObservationMode2(db, projectIdentity, sourceDirectory, failedConfig, failureSummary, memoryDisabledReason) {
2370
2371
  const prior = projectRegistrations.get(projectIdentity);
2371
2372
  const runtimeFingerprint = `observation:${sha256Prefix(failureSummary)}`;
2372
2373
  const generation = prior?.runtimeFingerprint === runtimeFingerprint && prior.observationMode ? prior.generation : ++globalRegistrationGeneration;
@@ -2381,7 +2382,8 @@ function registerProjectInObservationMode2(db, projectIdentity, sourceDirectory,
2381
2382
  features: { memoryEnabled: false, gitCommitEnabled: false },
2382
2383
  modelId: "off",
2383
2384
  chunkModelId: "off",
2384
- observationMode: true
2385
+ observationMode: true,
2386
+ memoryDisabledReason
2385
2387
  };
2386
2388
  projectRegistrations.set(projectIdentity, registration);
2387
2389
  disposeProvider(prior?.provider ?? null);
package/dist/v2/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadPluginConfigDetailed
3
- } from "./server-94wk1ey3.js";
3
+ } from "./server-835q39kd.js";
4
4
  import {
5
5
  setHarness2
6
6
  } from "./server-pavzsdc6.js";
@@ -7874,7 +7874,7 @@ var require_src2 = __commonJS(function(exports, module) {
7874
7874
  // package.json
7875
7875
  var package_default = {
7876
7876
  name: "@cortexkit/opencode-magic-context",
7877
- version: "0.49.28",
7877
+ version: "0.49.29",
7878
7878
  type: "module",
7879
7879
  description: "OpenCode plugin for Magic Context — cross-session memory and context management",
7880
7880
  main: "dist/index.js",
@@ -8195,7 +8195,7 @@ async function setup(context) {
8195
8195
  if (claimStorageBackupWarningCheck() && isMagicContextStorageOutsideEngram(storageDir)) {
8196
8196
  log2(`[magic-context] Magic Context storage is at ${storageDir}, outside the folder Engram backs up (~/.local/share/cortexkit/magic-context). It is not included in CortexKit backups.`);
8197
8197
  }
8198
- const { registerContext } = await import("./context-0qhz1nnj.js");
8198
+ const { registerContext } = await import("./context-g4ptae4x.js");
8199
8199
  setHarness2("opencode2");
8200
8200
  bindStaleBuildNotice({}, import.meta.url, "opencode2");
8201
8201
  const duties = await registerContext(context);
@@ -19,8 +19,8 @@ import {
19
19
  registerActiveCompartmentRun,
20
20
  setRecompStarting2,
21
21
  setRecompTerminal2
22
- } from "./server-jj9qye8y.js";
23
- import"./server-yqek3s4k.js";
22
+ } from "./server-q50ttc2g.js";
23
+ import"./server-zh3esb0z.js";
24
24
  import"./server-3mz2qh5a.js";
25
25
  import"./server-ab1g0wn9.js";
26
26
  import {
@@ -31,7 +31,7 @@ import"./server-cpjk5jd2.js";
31
31
  import"./server-6vd2n183.js";
32
32
  import"./server-awr8qa4c.js";
33
33
  import"./server-4sn3at8p.js";
34
- import"./server-z2n2xaeh.js";
34
+ import"./server-k9je35ev.js";
35
35
  import {
36
36
  getWrapupInProgressState,
37
37
  acquireWrapupInProgress,
@@ -40,20 +40,20 @@ import {
40
40
  getHistorianFailureState,
41
41
  clearEmergencyRecovery,
42
42
  prepareRawSessionOrdinals2
43
- } from "./server-xkvxss5g.js";
43
+ } from "./server-mxzj3r0y.js";
44
44
  import"./server-v77xa5wj.js";
45
- import"./server-e3hc93wk.js";
45
+ import"./server-77gznpmf.js";
46
46
  import"./server-1zx87sdm.js";
47
47
  import"./server-nxas8v1d.js";
48
48
  import"./server-24g8r2d0.js";
49
49
  import"./server-2ra6pwf3.js";
50
- import"./server-3vhxy2k5.js";
50
+ import"./server-a7x00tw8.js";
51
51
  import"./server-cqjvxyrp.js";
52
52
  import"./server-fr0wbhdn.js";
53
53
  import"./server-6g98c227.js";
54
54
  import"./server-qjvk4a9t.js";
55
55
  import"./server-fb3zxn06.js";
56
- import"./server-z3mk9jdc.js";
56
+ import"./server-ph300d6m.js";
57
57
  import {
58
58
  pushNotification2
59
59
  } from "./server-x8a7jmkh.js";
@@ -62,15 +62,15 @@ import"./server-qt1qqasc.js";
62
62
  import"./server-bsgd4dk1.js";
63
63
  import"./server-4dhv7mqz.js";
64
64
  import"./server-vr4szghm.js";
65
- import"./server-6avtp9jp.js";
65
+ import"./server-p0snacz3.js";
66
66
  import"./server-jjvbk92s.js";
67
- import"./server-94wk1ey3.js";
67
+ import"./server-835q39kd.js";
68
68
  import"./server-29qp8nz4.js";
69
69
  import"./server-53eh1r8r.js";
70
70
  import"./server-1bw1wcbp.js";
71
71
  import {
72
72
  sendStatusNotification2
73
- } from "./server-6v3cdzsx.js";
73
+ } from "./server-qc915kw2.js";
74
74
  import"./server-gyy4k6mf.js";
75
75
 
76
76
  // src/hooks/magic-context/wrapup-orchestrator.ts
@@ -1,23 +1,23 @@
1
1
  import {
2
2
  runManagedWrapup2
3
- } from "./index-31y1mznz.js";
4
- import"./index-n8qmmd7f.js";
5
- import"./index-dcqk0y27.js";
3
+ } from "./index-wyt5m81v.js";
4
+ import"./index-093c4g1c.js";
5
+ import"./index-q9zvphbq.js";
6
6
  import"./index-qgh1qwjj.js";
7
- import"./index-t3rbb8wr.js";
8
- import"./index-7gbcg8xv.js";
7
+ import"./index-pe6b4bhs.js";
8
+ import"./index-tx68g9nc.js";
9
9
  import"./index-sd3egckz.js";
10
- import"./index-4ypqzvhf.js";
11
- import"./index-a2fz9hpa.js";
10
+ import"./index-vnn5405n.js";
11
+ import"./index-gxkhzmjq.js";
12
12
  import"./index-jjvbk92s.js";
13
13
  import"./index-4dhv7mqz.js";
14
14
  import"./index-spwjbkc7.js";
15
- import"./index-077ht5cq.js";
15
+ import"./index-waktfbjy.js";
16
16
  import"./index-qt1qqasc.js";
17
- import"./index-yzjhx10y.js";
17
+ import"./index-zhgqgxtt.js";
18
18
  import"./index-np3rgfw4.js";
19
19
  import"./index-1zx87sdm.js";
20
- import"./index-v0dhhxsq.js";
20
+ import"./index-y1qwzvxn.js";
21
21
  import"./index-x8a7jmkh.js";
22
22
  import"./index-rrv26qjz.js";
23
23
  import"./index-51rdvtkz.js";
@@ -25,7 +25,7 @@ import"./index-nxrsns5x.js";
25
25
  import"./index-kfyb3k6n.js";
26
26
  import"./index-mm93m7y6.js";
27
27
  import"./index-wfybj1dw.js";
28
- import"./index-4cpc59jv.js";
28
+ import"./index-h4s5jk7f.js";
29
29
  import"./index-fb3zxn06.js";
30
30
  import"./index-7kkphb6c.js";
31
31
  import"./index-kq5w68dp.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.49.28",
3
+ "version": "0.49.29",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,34 @@
1
+ import type { MagicContextConfig } from "./schema/magic-context";
2
+
3
+ type CommitIndexing = MagicContextConfig["memory"]["git_commit_indexing"];
4
+ const pausedRetention = new WeakSet<CommitIndexing>();
5
+ const RETENTION_FIELD = "memory.git_commit_indexing.max_commits";
6
+
7
+ /** Keep a defaulted cap useful for bounded reads without letting it delete stored history. */
8
+ export function applyCommitRetentionRecovery(
9
+ config: MagicContextConfig,
10
+ recoveredFieldPaths: readonly string[],
11
+ warnings: string[],
12
+ ): void {
13
+ if (
14
+ !recoveredFieldPaths.some(
15
+ (path) => RETENTION_FIELD === path || RETENTION_FIELD.startsWith(`${path}.`),
16
+ )
17
+ )
18
+ return;
19
+ pausedRetention.add(config.memory.git_commit_indexing);
20
+ const message = `${RETENTION_FIELD}: retention eviction is paused until the invalid value is fixed.`;
21
+ const index = warnings.findIndex((warning) => warning.includes(RETENTION_FIELD));
22
+ if (index >= 0) warnings[index] = `${warnings[index]} ${message}`;
23
+ else warnings.push(message);
24
+ }
25
+
26
+ export function isCommitRetentionPaused(settings: CommitIndexing): boolean {
27
+ return pausedRetention.has(settings);
28
+ }
29
+
30
+ /** Live sampling copies settings objects; recovery state must follow the sampled cap. */
31
+ export function copyCommitRetentionRecovery(from: CommitIndexing, to: CommitIndexing): void {
32
+ if (pausedRetention.has(from)) pausedRetention.add(to);
33
+ else pausedRetention.delete(to);
34
+ }
@@ -15,6 +15,7 @@ import { log } from "../shared/logger";
15
15
  import { setOutputReserveConfig } from "../shared/models-dev-cache";
16
16
  import type { PromptSurfaceConfig } from "../shared/prompt-surface";
17
17
  import { isCompactionEnabled, migrateLegacyAgentEnabledInMemory } from "./agent-disable";
18
+ import { applyCommitRetentionRecovery } from "./commit-retention-recovery";
18
19
  import { warnDeprecatedMuralModel, warnDeprecatedWindowOverlayPath } from "./deprecated-config";
19
20
  import {
20
21
  cortexKitProjectConfigBasePath,
@@ -121,6 +122,7 @@ export interface LoadResultDetailed {
121
122
  };
122
123
  substitutionFailures: Array<{ keyPath: string; source: "user" | "project"; message: string }>;
123
124
  recoveredTopLevelKeys: string[];
125
+ recoveredFieldPaths: string[];
124
126
  configParseFailures: ConfigParseFailure[];
125
127
  warningDetails: ConfigWarningDetail[];
126
128
  cacheTtlConfigured: boolean;
@@ -410,6 +412,7 @@ export function warnProtectedTagsDeprecationOnce(): void {
410
412
  export function parsePluginConfig(
411
413
  rawConfig: Record<string, unknown>,
412
414
  recoveredTopLevelKeys: string[] = [],
415
+ recoveredFieldPaths: string[] = [],
413
416
  ): MagicContextPluginConfig & { configWarnings?: string[] } {
414
417
  // Pre-Zod shim: reshape legacy experimental.* graduated keys so the user's
415
418
  // opt-in/out state survives upgrades even when they never run `doctor`.
@@ -543,6 +546,7 @@ export function parsePluginConfig(
543
546
  }
544
547
  if (prunedLeaves.length === issuePaths.length) {
545
548
  patched[key] = prunedBlock;
549
+ recoveredFieldPaths.push(...prunedLeaves.map((leaf) => `${key}.${leaf}`));
546
550
  const reason = customMessagesByKey.get(key);
547
551
  warnings.push(
548
552
  `"${key}": invalid nested field(s) ${prunedLeaves.map((leaf) => `"${key}.${leaf}"`).join(", ")}, using defaults for those.${reason ? ` ${reason}` : ""}`,
@@ -553,6 +557,7 @@ export function parsePluginConfig(
553
557
 
554
558
  // Root-level or unreachable agent errors cannot be repaired safely because
555
559
  // guessing a model configuration could select an expensive unintended model.
560
+ recoveredFieldPaths.push(key);
556
561
  if (isAgentConfig) {
557
562
  delete patched[key];
558
563
  warnings.push(
@@ -609,6 +614,13 @@ export function parsePluginConfig(
609
614
  // If even the patched version fails (shouldn't happen), fall back to full defaults
610
615
  // but keep enabled:true — the user intended to use the plugin.
611
616
  warnings.push("Config recovery failed, using all defaults.");
617
+ recoveredFieldPaths.push(
618
+ "embedding",
619
+ "memory",
620
+ "subc",
621
+ "shadow_embedding",
622
+ "allow_home_project",
623
+ );
612
624
  return {
613
625
  ...defaults,
614
626
  disabled_hooks: disabledHooks,
@@ -819,6 +831,7 @@ export function loadPluginConfigDetailed(
819
831
  // way that forces extra historian work on the user's account.
820
832
  const trustedBaseConfig = parsePluginConfig(trustedProfiledRaw);
821
833
  let projectRestoredTopLevelKeys: string[] = [];
834
+ let projectRestoredFieldPaths: string[] = [];
822
835
 
823
836
  if (projectLoaded) {
824
837
  mergedRaw = deepMergeRawConfig(mergedRaw, profileResolution.projectBase);
@@ -846,6 +859,7 @@ export function loadPluginConfigDetailed(
846
859
  allWarnings.push(`[project config] ${warning}`);
847
860
  }
848
861
  projectRestoredTopLevelKeys = restoredOverProject.restoredTopLevelKeys;
862
+ projectRestoredFieldPaths = restoredOverProject.restoredFieldPaths;
849
863
  for (const warning of constrainProjectCommands({
850
864
  mergedRaw,
851
865
  trustedRaw: trustedProfiledRaw,
@@ -857,8 +871,10 @@ export function loadPluginConfigDetailed(
857
871
  }
858
872
 
859
873
  const recoveredTopLevelKeys: string[] = [];
874
+ const recoveredFieldPaths: string[] = [];
860
875
  const cacheTtlConfigured = Object.hasOwn(mergedRaw, "cache_ttl");
861
- const config = parsePluginConfig(mergedRaw, recoveredTopLevelKeys);
876
+ const config = parsePluginConfig(mergedRaw, recoveredTopLevelKeys, recoveredFieldPaths);
877
+ recoveredFieldPaths.push(...projectRestoredFieldPaths);
862
878
  // An ignored invalid project value is still a config the user must fix, so
863
879
  // keep reporting it as schema recovery (live reload keeps the last good
864
880
  // config on that outcome, as it did before the user's value was restored).
@@ -873,7 +889,10 @@ export function loadPluginConfigDetailed(
873
889
  if (applyRuntimeGlobals) {
874
890
  setOutputReserveConfig(config.output_reserve);
875
891
  }
876
- const leafValidationWarnings = [...(config.configWarnings ?? [])];
892
+ const recoveryWarnings = config.configWarnings ?? [];
893
+ applyCommitRetentionRecovery(config, recoveredFieldPaths, recoveryWarnings);
894
+ if (recoveryWarnings.length > 0) config.configWarnings = recoveryWarnings;
895
+ const leafValidationWarnings = [...recoveryWarnings];
877
896
  if (config.configWarnings?.length) {
878
897
  allWarnings.push(
879
898
  ...config.configWarnings.map((w) => {
@@ -933,6 +952,7 @@ export function loadPluginConfigDetailed(
933
952
  sources,
934
953
  substitutionFailures,
935
954
  recoveredTopLevelKeys,
955
+ recoveredFieldPaths,
936
956
  configParseFailures,
937
957
  warningDetails,
938
958
  cacheTtlConfigured,
@@ -1,4 +1,5 @@
1
1
  import { expect, test } from "bun:test";
2
+ import type { HiddenCompletionExecutor } from "../hooks/magic-context/compartment-runner-types";
2
3
 
3
4
  import { producerInputTokenLimit } from "../hooks/magic-context/producer-window-guard";
4
5
  import {
@@ -53,6 +54,33 @@ test("OpenCode 2 dreamer passes a fresh output cap to each hidden child", async
53
54
  expect(received).toEqual([4096, 8192]);
54
55
  });
55
56
 
57
+ test("OpenCode 2 dreamer output-cap wrapper forwards partial output reads", async () => {
58
+ const boot = MagicContextConfigSchema.parse({});
59
+ const reads: Array<{ id: string; limit: number }> = [];
60
+ const executor: HiddenCompletionExecutor = {
61
+ capabilities: { tools: true, harness: "opencode2" },
62
+ open: async () => ({ id: "child" }),
63
+ attempt: async () => {},
64
+ collect: async () => {
65
+ throw new Error("no settled completion");
66
+ },
67
+ collectPartial: async (handle, limit) => {
68
+ reads.push({ id: handle.id, limit });
69
+ return {
70
+ text: "unfinished manifest",
71
+ usage: { input: 101, output: 11, cacheRead: 7, cacheWrite: 5 },
72
+ lengthCapped: false,
73
+ };
74
+ },
75
+ close: async () => {},
76
+ };
77
+ const wrapped = withLiveDreamerOutputCap(executor, boot, () => boot);
78
+ expect((await wrapped.collectPartial?.({ id: "child" }, 200))?.text).toBe(
79
+ "unfinished manifest",
80
+ );
81
+ expect(reads).toEqual([{ id: "child", limit: 200 }]);
82
+ });
83
+
56
84
  test("OpenCode 1 historian keeps the sampled reserve and child output cap", () => {
57
85
  const boot = MagicContextConfigSchema.parse({ historian: { maxTokens: 2048 } });
58
86
  let current = MagicContextConfigSchema.parse({ historian: { maxTokens: 4096 } });
@@ -29,6 +29,8 @@ export function withLiveDreamerOutputCap<T extends MagicContextConfig>(
29
29
  }),
30
30
  attempt: (handle, request) => executor.attempt(handle, request),
31
31
  collect: (handle, limit) => executor.collect(handle, limit),
32
+ collectPartial: (handle, limit) =>
33
+ executor.collectPartial?.(handle, limit) ?? executor.collect(handle, limit),
32
34
  close: (handle, settlement) => executor.close(handle, settlement),
33
35
  };
34
36
  }