@cortexkit/opencode-magic-context 0.49.2 → 0.49.3

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/README.md +2 -38
  2. package/dist/auto-search-worker.js +3 -3
  3. package/dist/compaction-marker-candidates-dd638ypn.js +19 -0
  4. package/dist/compaction-marker-candidates-worker.js +24 -0
  5. package/dist/{conflict-warning-hook-asnt6hfc.js → conflict-warning-hook-ae8nmv7c.js} +5 -4
  6. package/dist/{context-tfyhtdcs.js → context-9tbxh883.js} +63 -29
  7. package/dist/{embedding-backfill-wyc3ykyf.js → embedding-backfill-aj488s8x.js} +5 -5
  8. package/dist/features/magic-context/compaction-marker-candidates-worker.d.ts +2 -0
  9. package/dist/features/magic-context/compaction-marker-candidates-worker.d.ts.map +1 -0
  10. package/dist/features/magic-context/compaction-marker-candidates.d.ts +47 -0
  11. package/dist/features/magic-context/compaction-marker-candidates.d.ts.map +1 -0
  12. package/dist/features/magic-context/compaction-marker.d.ts +12 -0
  13. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  14. package/dist/features/magic-context/memory/project-identity.d.ts +5 -1
  15. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  16. package/dist/features/magic-context/message-index-async.d.ts +3 -0
  17. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  18. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  19. package/dist/features/magic-context/storage-clone.d.ts +2 -0
  20. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  21. package/dist/features/magic-context/storage-tags.d.ts +1 -1
  22. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/compaction-marker-manager.d.ts +3 -0
  24. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  26. package/dist/hooks/magic-context/history-boundary-repair.d.ts +11 -2
  27. package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -1
  28. package/dist/hooks/magic-context/protected-tail-boundary.d.ts +4 -3
  29. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  30. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +10 -0
  31. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -1
  32. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  35. package/dist/{index-sfhndpcb.js → index-3wckxwfp.js} +39 -39
  36. package/dist/{index-gzky5rva.js → index-41gqa557.js} +4 -2
  37. package/dist/{index-r2zcs71c.js → index-7ndnvw7a.js} +1 -1
  38. package/dist/{index-sv0bb7vg.js → index-7zg9dvx0.js} +35 -4
  39. package/dist/{index-xgrwmj82.js → index-bhk710rw.js} +1 -1
  40. package/dist/{index-fg00p1cg.js → index-c0b01zrc.js} +2 -2
  41. package/dist/{index-rafsaxac.js → index-fjtgekd4.js} +2 -2
  42. package/dist/{index-fdtkt5r1.js → index-fst3t0d9.js} +9 -9
  43. package/dist/{index-6tfxmc4n.js → index-je2na55n.js} +4 -4
  44. package/dist/{index-h5zfkjyk.js → index-jpm52v9x.js} +6 -24
  45. package/dist/{index-s7fc0fkn.js → index-m4p77myp.js} +1 -1
  46. package/dist/{index-xnanvj3w.js → index-mgy5dwcw.js} +607 -579
  47. package/dist/{index-0pjvpfkf.js → index-qvr78ej6.js} +1 -1
  48. package/dist/{index-zfzdpeq2.js → index-s4ztdn8v.js} +1311 -1271
  49. package/dist/index-v0p37hm2.js +22 -0
  50. package/dist/{index-eypn4ba6.js → index-w9pe0nx1.js} +3 -3
  51. package/dist/{index-p0n5ryq8.js → index-ws3gcy5m.js} +19 -9
  52. package/dist/{index-att4bfan.js → index-xfbfrngb.js} +1 -1
  53. package/dist/{index-nydv6g8r.js → index-yqps2zsv.js} +44 -6
  54. package/dist/index-yxawqmdd.js +212 -0
  55. package/dist/{index-zg8yq4ya.js → index-znzgze2v.js} +3 -3
  56. package/dist/index.js +38 -35
  57. package/dist/{message-index-bounded-hqktkhdy.js → message-index-bounded-pv6ct15d.js} +18 -17
  58. package/dist/message-index-jqa7qd0s.js +60 -0
  59. package/dist/migration-worker.js +3 -3
  60. package/dist/{project-embedding-registry-0gv3h6y8.js → project-embedding-registry-fcmszatg.js} +4 -4
  61. package/dist/raw-ordinal-warmup-worker.js +22 -5
  62. package/dist/{read-session-chunk-5mh0bh8y.js → read-session-chunk-cwgjwjd0.js} +7 -6
  63. package/dist/{read-session-raw-8sjbc9h0.js → read-session-raw-z38cn0as.js} +2 -1
  64. package/dist/{recomp-orchestrator-kpkhkjhq.js → recomp-orchestrator-txcc802e.js} +19 -17
  65. package/dist/{search-p9w39qv4.js → search-v1t47s2q.js} +14 -13
  66. package/dist/{send-session-notification-xffh3bbe.js → send-session-notification-yp9m5g4p.js} +4 -3
  67. package/dist/shared/tag-owner-id.d.ts +1 -0
  68. package/dist/shared/tag-owner-id.d.ts.map +1 -1
  69. package/dist/{storage-tags-k0pda32s.js → storage-tags-0ssbmzg9.js} +2 -2
  70. package/dist/{transform-postprocess-phase-481j5a7z.js → transform-postprocess-phase-113rwew1.js} +19 -17
  71. package/dist/v2/auto-search-worker.js +3 -3
  72. package/dist/v2/compaction-marker-candidates-1s21e2fz.js +18 -0
  73. package/dist/v2/compaction-marker-candidates-worker.js +24 -0
  74. package/dist/v2/{context-gsdtha5v.js → context-p1xf3w5q.js} +115 -44
  75. package/dist/v2/{embedding-backfill-dbvjbcmm.js → embedding-backfill-9hbkfvnz.js} +5 -5
  76. package/dist/v2/{message-index-bounded-p6v0n8qh.js → message-index-bounded-c0810p5w.js} +17 -16
  77. package/dist/v2/message-index-h8ssgq3q.js +59 -0
  78. package/dist/v2/migration-worker.js +3 -3
  79. package/dist/v2/{project-embedding-registry-nyq7z8y6.js → project-embedding-registry-42th7k1z.js} +4 -4
  80. package/dist/v2/raw-ordinal-warmup-worker.js +22 -5
  81. package/dist/v2/{read-session-chunk-fhyfe4qa.js → read-session-chunk-n86v9xfg.js} +6 -5
  82. package/dist/v2/{read-session-raw-j8dvp7f4.js → read-session-raw-3b3ehga4.js} +2 -1
  83. package/dist/v2/{recomp-orchestrator-5xy7w136.js → recomp-orchestrator-v168jwgg.js} +16 -14
  84. package/dist/v2/{search-j7bakcwa.js → search-048v8y02.js} +13 -12
  85. package/dist/v2/{send-session-notification-f6v698r5.js → send-session-notification-a4h2azxa.js} +2 -1
  86. package/dist/v2/{server-bgzy0phk.js → server-3bc6k4k4.js} +62 -33
  87. package/dist/v2/{server-7h861yms.js → server-3dqjhchy.js} +5 -18
  88. package/dist/v2/{server-c7n2ftng.js → server-4n2tknpc.js} +34 -3
  89. package/dist/v2/server-51779zs2.js +19 -0
  90. package/dist/v2/{server-kh958yj8.js → server-5zrpr764.js} +1 -1
  91. package/dist/v2/{server-6tcrjfw8.js → server-8pqnnmf9.js} +1 -1
  92. package/dist/v2/server-9290a1mb.js +212 -0
  93. package/dist/v2/{server-7vkj6zhb.js → server-9a6v0wth.js} +3 -3
  94. package/dist/v2/{server-1fszbabv.js → server-cjz51jm2.js} +2 -2
  95. package/dist/v2/{server-7spkq1y6.js → server-cxxjb33r.js} +2286 -2246
  96. package/dist/v2/{server-mqvtz7wz.js → server-hetyb88z.js} +9 -9
  97. package/dist/v2/{server-4c7jt8gq.js → server-pcygfdbs.js} +44 -6
  98. package/dist/v2/{server-8xmq9h3f.js → server-q6j5dasr.js} +4 -2
  99. package/dist/v2/{server-zbxjj2mz.js → server-rygvffsf.js} +2 -2
  100. package/dist/v2/server.js +4 -4
  101. package/dist/v2/{storage-tags-5yxrvkaf.js → storage-tags-3a4cavqb.js} +2 -2
  102. package/dist/v2/{wrapup-orchestrator-yem5422s.js → wrapup-orchestrator-zcyf8ymw.js} +14 -12
  103. package/dist/{wrapup-orchestrator-xvrr27ws.js → wrapup-orchestrator-5aa2q4v3.js} +20 -18
  104. package/package.json +3 -3
  105. package/src/config/latch-permanence-guard.test.ts +6 -1
  106. package/src/shared/sqlite-writer-diagnostics.test.ts +21 -10
  107. package/src/shared/tag-owner-id.ts +13 -0
  108. package/src/shared/tag-transcript.test.ts +6 -1
  109. package/src/shared/tag-transcript.ts +2 -1
  110. package/src/shared/windows-hidden-spawns.test.ts +60 -4
  111. /package/dist/{index-69vas84q.js → index-e6xnpach.js} +0 -0
  112. /package/dist/{index-p1hnwfd8.js → index-gcdb3rqw.js} +0 -0
  113. /package/dist/v2/{index-69vas84q.js → index-e6xnpach.js} +0 -0
  114. /package/dist/v2/{server-s2st631p.js → server-8wcf79fe.js} +0 -0
@@ -64,7 +64,7 @@ import {
64
64
  LATEST_SUPPORTED_VERSION,
65
65
  getPersistedSchemaVersion,
66
66
  openDatabase
67
- } from "./index-zg8yq4ya.js";
67
+ } from "./index-znzgze2v.js";
68
68
  import {
69
69
  isPidAlive
70
70
  } from "./index-6m7rdv7y.js";
@@ -87,7 +87,7 @@ import {
87
87
  resolveStoredPathWorkspaceIdentity,
88
88
  sourceNameForMemory,
89
89
  computeWorkspaceEpochFingerprint
90
- } from "./index-att4bfan.js";
90
+ } from "./index-xfbfrngb.js";
91
91
  import {
92
92
  getTableColumnNames
93
93
  } from "./index-1bt88epp.js";
@@ -105,7 +105,7 @@ import {
105
105
  import {
106
106
  shouldSkipHomeProjectMemory,
107
107
  resolveProjectIdentity
108
- } from "./index-gzky5rva.js";
108
+ } from "./index-41gqa557.js";
109
109
  import {
110
110
  getMeasuredToolDefinitionTokens
111
111
  } from "./index-h2wc01qk.js";
@@ -118,7 +118,7 @@ import {
118
118
  replaceCompartmentChunkEmbeddings,
119
119
  deleteChunkEmbedBackoffForSession,
120
120
  chunkWindowSourceKey
121
- } from "./index-p1hnwfd8.js";
121
+ } from "./index-gcdb3rqw.js";
122
122
  import {
123
123
  BoundedSessionMap,
124
124
  clearCompressionDepth,
@@ -130,10 +130,10 @@ import {
130
130
  commitLkgWithRecoveryFence,
131
131
  clearLkgRecoveryFence,
132
132
  deleteSessionScopedRows,
133
- toMessageIndexSource,
134
- clearIndexedMessagesInTransaction,
135
- indexSourcesAfterOrdinal
136
- } from "./index-sfhndpcb.js";
133
+ toMessageIndexSource2,
134
+ clearIndexedMessagesInTransaction2,
135
+ indexSourcesAfterOrdinal2
136
+ } from "./index-3wckxwfp.js";
137
137
  import {
138
138
  retreatPastHostUnservedRows,
139
139
  snapTerminalCompartmentToServedRow,
@@ -218,7 +218,7 @@ import {
218
218
  getRawSessionTagKeysThrough2,
219
219
  getLegacyProtectedTailStartOrdinal2,
220
220
  readSessionChunk2
221
- } from "./index-sv0bb7vg.js";
221
+ } from "./index-7zg9dvx0.js";
222
222
  import {
223
223
  stripWellFormedLeadingTagPrefix,
224
224
  stripTagPrefix,
@@ -231,15 +231,15 @@ import {
231
231
  foldShrunkPartTags2,
232
232
  getTagNumberByMessageId2,
233
233
  getActiveTagsBySession2
234
- } from "./index-nydv6g8r.js";
234
+ } from "./index-yqps2zsv.js";
235
235
  import {
236
236
  isStrictGapHealingMessage2,
237
237
  noteRawSessionSummaryRowWritten2
238
- } from "./index-h5zfkjyk.js";
238
+ } from "./index-jpm52v9x.js";
239
239
  import {
240
240
  withReadOnlySessionDb,
241
241
  getMessageTimesFromOpenCodeDb
242
- } from "./index-0pjvpfkf.js";
242
+ } from "./index-qvr78ej6.js";
243
243
  import {
244
244
  drainBackgroundBatches,
245
245
  contentSha2562,
@@ -247,7 +247,7 @@ import {
247
247
  getProjectChunkEmbeddingModelId2,
248
248
  getProjectEmbeddingMaxInputTokens2,
249
249
  embedItemsForProject2
250
- } from "./index-fg00p1cg.js";
250
+ } from "./index-c0b01zrc.js";
251
251
  import {
252
252
  renderUserFacingFailure,
253
253
  userFacingFailureCode,
@@ -256,10 +256,16 @@ import {
256
256
  insertPrimerCandidates,
257
257
  promoteSessionFactsDurable,
258
258
  embedPromotedFacts
259
- } from "./index-rafsaxac.js";
259
+ } from "./index-fjtgekd4.js";
260
260
  import {
261
261
  pushNotification2
262
262
  } from "./index-x8a7jmkh.js";
263
+ import {
264
+ isMarkerCandidateBasisCurrent2,
265
+ invalidateMarkerCandidateBasis2,
266
+ readMarkerCandidateBasis2,
267
+ prepareMarkerCandidateBasis2
268
+ } from "./index-yxawqmdd.js";
263
269
  import {
264
270
  computeCueContentHash,
265
271
  getMuralCueState,
@@ -270,7 +276,7 @@ import {
270
276
  } from "./index-7jzrrxap.js";
271
277
  import {
272
278
  sendStatusNotification2
273
- } from "./index-xgrwmj82.js";
279
+ } from "./index-bhk710rw.js";
274
280
  import {
275
281
  getErrorMessage,
276
282
  describeError
@@ -8239,7 +8245,7 @@ function clampWatermark(value, maxCopiedTag) {
8239
8245
  function copySessionStateForClone(db, sourceSessionId, destinationSessionId, filter) {
8240
8246
  return runImmediate(db, () => {
8241
8247
  const hasTemporalDecisions = tableExists(db, "temporal_decisions");
8242
- if (countRows(db, "compartments", destinationSessionId) > 0 || countRows(db, "tags", destinationSessionId) > 0 || hasTemporalDecisions && countRows(db, "temporal_decisions", destinationSessionId) > 0 || filter.copySessionNotesAndFacts === true && (tableExists(db, "notes") && countRows(db, "notes", destinationSessionId) > 0 || tableExists(db, "session_facts") && countRows(db, "session_facts", destinationSessionId) > 0)) {
8248
+ if (filter.requireEmptyDestinationMeta === true && countRows(db, "session_meta", destinationSessionId) > 0 || countRows(db, "compartments", destinationSessionId) > 0 || countRows(db, "tags", destinationSessionId) > 0 || hasTemporalDecisions && countRows(db, "temporal_decisions", destinationSessionId) > 0 || filter.copySessionNotesAndFacts === true && (tableExists(db, "notes") && countRows(db, "notes", destinationSessionId) > 0 || tableExists(db, "session_facts") && countRows(db, "session_facts", destinationSessionId) > 0)) {
8243
8249
  return {
8244
8250
  kind: "destination-not-empty",
8245
8251
  compartmentsCopied: 0,
@@ -11381,1367 +11387,1394 @@ function upsertMural(db, input) {
11381
11387
  db.prepare("INSERT INTO mural_manifest (project_path, image, content_hash, rendered_at, model, memory_ids_json, width, height) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(project_path) DO UPDATE SET image = excluded.image, content_hash = excluded.content_hash, rendered_at = excluded.rendered_at, model = excluded.model, memory_ids_json = excluded.memory_ids_json, width = excluded.width, height = excluded.height").run(input.projectPath, input.image, input.contentHash, input.renderedAt, input.model, JSON.stringify(input.memoryIds), input.width, input.height);
11382
11388
  }
11383
11389
 
11384
- // src/features/magic-context/compartment-embedding.ts
11385
- async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compartments) {
11386
- if (compartments.length === 0)
11387
- return;
11388
- if (getProjectChunkEmbeddingModelId2(projectPath) === "off")
11389
- return;
11390
- const maxInputTokens = getProjectEmbeddingMaxInputTokens2(projectPath);
11391
- for (const compartment of compartments) {
11392
- try {
11393
- const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
11394
- const mappedText = fromMemory ? fromMemory : buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
11395
- if (mappedText === null)
11396
- continue;
11397
- const canonicalText = mappedText || buildCompartmentSummaryFallbackText(db, compartment.id);
11398
- if (canonicalText.length === 0)
11399
- continue;
11400
- const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
11401
- if (windows.length === 0)
11402
- continue;
11403
- const windowSourceKey = chunkWindowSourceKey(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
11404
- const currentModelId = getProjectChunkEmbeddingModelId2(projectPath);
11405
- if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
11406
- continue;
11407
- }
11408
- const result = await embedItemsForProject2(projectPath, windows.map((window) => ({
11409
- id: `chunk:${compartment.id}:${window.windowIndex}`,
11410
- text: window.text,
11411
- contentSha256: contentSha2562(window.text)
11412
- })), undefined, db, sessionId);
11413
- if (!result)
11414
- continue;
11415
- if (chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
11416
- continue;
11417
- }
11418
- const rows = [];
11419
- for (const window of windows) {
11420
- const vector = result.vectors.get(`chunk:${compartment.id}:${window.windowIndex}`);
11421
- if (!vector)
11422
- continue;
11423
- rows.push({
11424
- compartmentId: compartment.id,
11425
- sessionId,
11426
- projectPath,
11427
- window,
11428
- modelId: currentModelId,
11429
- vector
11430
- });
11431
- }
11432
- if (rows.length === windows.length) {
11433
- replaceCompartmentChunkEmbeddings(db, rows, windowSourceKey);
11434
- enqueueShadowEmbeddingItems2(projectPath, "chunk", [String(compartment.id)]);
11435
- }
11436
- } catch (error) {
11437
- sessionLog2(sessionId, `compartment chunk embedding failed for compartment ${compartment.id}:`, error);
11438
- } finally {
11439
- await new Promise((resolve) => setTimeout(resolve, 0));
11440
- }
11390
+ // src/features/magic-context/compaction-marker.ts
11391
+ import { createHash as createHash9 } from "node:crypto";
11392
+ import { existsSync as existsSync6 } from "node:fs";
11393
+ var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
11394
+ var ID_PREFIX_HEX_LENGTH = 12;
11395
+ var ID_SUFFIX_LENGTH = 14;
11396
+ var ID_PREFIX_MASK = (1n << BigInt(ID_PREFIX_HEX_LENGTH * 4)) - 1n;
11397
+ function deterministicBase62(seed, length) {
11398
+ let value = BigInt(`0x${createHash9("sha256").update(seed).digest("hex")}`);
11399
+ const chars = Array(length);
11400
+ for (let index = length - 1;index >= 0; index -= 1) {
11401
+ chars[index] = BASE62_CHARS[Number(value % 62n)];
11402
+ value /= 62n;
11441
11403
  }
11404
+ return chars.join("");
11442
11405
  }
11443
-
11444
- // src/features/magic-context/store-generation-rebase.ts
11445
- function emptyOutcome(status, generation, previousGeneration) {
11446
- return {
11447
- status,
11448
- generation,
11449
- previousGeneration,
11450
- compartmentsRebased: 0,
11451
- compartmentsUnresolved: 0,
11452
- compartmentsDerived: 0,
11453
- compartmentsResolvedAgain: 0,
11454
- recompCompartmentsRebased: 0,
11455
- recompCompartmentsUnresolved: 0,
11456
- notesRebased: 0,
11457
- notesCleared: 0,
11458
- priorBoundaryRebased: false,
11459
- recompPartialRangeRebased: false,
11460
- compressionDepthRowsDropped: 0,
11461
- chunkEmbeddingsDeleted: 0,
11462
- indexRebuilt: false,
11463
- indexRowsRebuilt: 0,
11464
- partTagsFolded: 0,
11465
- partTagsRekeyed: 0,
11466
- queuedReductionsDiscarded: 0,
11467
- lkgSlotsDropped: 0,
11468
- frozenPartEntriesDropped: 0,
11469
- healedGaps: 0,
11470
- narrativeGaps: 0
11471
- };
11406
+ function generateId(prefix, timestampMs, counter, identity) {
11407
+ const encoded = BigInt(Math.max(0, Math.floor(timestampMs))) * 0x1000n + counter & ID_PREFIX_MASK;
11408
+ const hex = encoded.toString(16).padStart(ID_PREFIX_HEX_LENGTH, "0");
11409
+ return `${prefix}_${hex}${deterministicBase62(`${prefix}\x00${identity}`, ID_SUFFIX_LENGTH)}`;
11472
11410
  }
11473
- function sessionIsOpenCodeOwned(db, sessionId) {
11474
- const row = db.prepare("SELECT harness FROM session_meta WHERE session_id = ?").get(sessionId);
11475
- const harness = row?.harness;
11476
- if (harness === undefined || harness === null)
11477
- return true;
11478
- return harness === "opencode" || harness === "opencode2";
11411
+ function generateMessageId(timestampMs, counter = 0n, identity = "") {
11412
+ return generateId("msg", timestampMs, counter, identity);
11479
11413
  }
11480
- function generationImpliedByHarness(db, sessionId) {
11481
- const row = db.prepare("SELECT harness FROM session_meta WHERE session_id = ?").get(sessionId);
11482
- if (row?.harness === "opencode")
11483
- return "v1";
11484
- if (row?.harness === "opencode2")
11485
- return "v2";
11486
- return null;
11414
+ function generatePartId(timestampMs, counter = 0n, identity = "") {
11415
+ return generateId("prt", timestampMs, counter, identity);
11487
11416
  }
11488
- function readCoordinateGeneration(db, sessionId) {
11489
- const row = db.prepare("SELECT coordinate_generation FROM session_meta WHERE session_id = ?").get(sessionId);
11490
- const value = row?.coordinate_generation;
11491
- return value === "v1" || value === "v2" ? value : null;
11417
+ function getOpenCodeDbPath() {
11418
+ return resolveOpenCodeDbPath().path;
11492
11419
  }
11493
- function readCoordinateRebaseNotice(db, sessionId) {
11494
- const row = db.prepare("SELECT coordinate_rebase_notice FROM session_meta WHERE session_id = ?").get(sessionId);
11495
- const raw = row?.coordinate_rebase_notice;
11496
- if (typeof raw !== "string" || raw.length === 0)
11497
- return null;
11420
+ var cachedWriteDb = null;
11421
+ var cachedRemovalDb = null;
11422
+ var MARKER_BUSY_TIMEOUT_MS = 250;
11423
+ var MARKER_REMOVAL_BUSY_TIMEOUT_MS = 5000;
11424
+ function runMarkerRemovalTransaction(db, operation) {
11425
+ return withoutSqliteTransformPass2(() => db.transaction(operation).immediate());
11426
+ }
11427
+ function runMarkerWriteTransaction(db, site, operation) {
11428
+ if (db.inTransaction)
11429
+ return db.transaction(operation).immediate();
11430
+ const startedAt = performance.now();
11431
+ let acquiredAt;
11432
+ let workFinishedAt;
11433
+ let committed = false;
11498
11434
  try {
11499
- const parsed = JSON.parse(raw);
11500
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
11501
- return null;
11502
- const record = parsed;
11503
- if (record.generation !== "v1" && record.generation !== "v2")
11504
- return null;
11505
- const count = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
11506
- const ranges = (value) => Array.isArray(value) ? value.flatMap((entry) => {
11507
- if (!entry || typeof entry !== "object")
11508
- return [];
11509
- const { sequence, start, end } = entry;
11510
- return typeof sequence === "number" && typeof start === "number" && typeof end === "number" ? [{ sequence, start, end }] : [];
11511
- }) : [];
11512
- return {
11513
- generation: record.generation,
11514
- previousGeneration: record.previousGeneration === "v1" || record.previousGeneration === "v2" ? record.previousGeneration : null,
11515
- at: count(record.at),
11516
- unresolvedCompartments: count(record.unresolvedCompartments),
11517
- discardedReductions: count(record.discardedReductions),
11518
- droppedDepthRows: count(record.droppedDepthRows),
11519
- healedGaps: count(record.healedGaps),
11520
- narrativeGaps: count(record.narrativeGaps),
11521
- derivedCompartments: ranges(record.derivedCompartments),
11522
- unresolvedCompartmentRanges: ranges(record.unresolvedCompartmentRanges),
11523
- neighbourRecoveryAt: typeof record.neighbourRecoveryAt === "number" && Number.isFinite(record.neighbourRecoveryAt) ? record.neighbourRecoveryAt : null
11524
- };
11525
- } catch {
11526
- return null;
11435
+ const result = db.transaction(() => {
11436
+ acquiredAt = performance.now();
11437
+ try {
11438
+ return operation();
11439
+ } finally {
11440
+ workFinishedAt = performance.now();
11441
+ }
11442
+ }).immediate();
11443
+ committed = true;
11444
+ return result;
11445
+ } finally {
11446
+ const finishedAt = performance.now();
11447
+ const acquireMs = (acquiredAt ?? finishedAt) - startedAt;
11448
+ const holdMs = acquiredAt === undefined ? 0 : finishedAt - acquiredAt;
11449
+ const workMs = acquiredAt === undefined ? 0 : (workFinishedAt ?? finishedAt) - acquiredAt;
11450
+ const endMs = workFinishedAt === undefined ? 0 : finishedAt - workFinishedAt;
11451
+ try {
11452
+ log2(`[magic-context] sqlite writer site=${site} db=opencode acquire_ms=${Math.round(acquireMs)} hold_ms=${Math.round(holdMs)} work_ms=${Math.round(workMs)} end_ms=${Math.round(endMs)} outcome=${acquiredAt === undefined ? "not_acquired" : committed ? "committed" : "failed"}`);
11453
+ } catch {}
11527
11454
  }
11528
11455
  }
11529
- function formatCoordinateRebaseNotice(notice) {
11530
- const parts = [];
11531
- if (notice.discardedReductions > 0) {
11532
- parts.push(`${notice.discardedReductions} queued reduction${notice.discardedReductions === 1 ? " was" : "s were"} discarded because their targets merged in the host's store conversion`);
11456
+ var REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
11457
+ var REQUIRED_PART_COLUMNS = [
11458
+ "id",
11459
+ "message_id",
11460
+ "session_id",
11461
+ "time_created",
11462
+ "time_updated",
11463
+ "data"
11464
+ ];
11465
+ var cachedSchemaCompatible = null;
11466
+ function isOpenCodeSchemaCompatible(db, dbPath) {
11467
+ if (cachedSchemaCompatible?.path === dbPath) {
11468
+ return cachedSchemaCompatible.compatible;
11533
11469
  }
11534
- if (notice.derivedCompartments.length > 0) {
11535
- const count = notice.derivedCompartments.length;
11536
- parts.push(`${count} compartment${count === 1 ? " was" : "s were"} re-anchored from the compartments around ${count === 1 ? "it" : "them"} (${formatRangeNotes(notice.derivedCompartments)})`);
11470
+ try {
11471
+ const messageCols = new Set(db.prepare("PRAGMA table_info(message)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
11472
+ const partCols = new Set(db.prepare("PRAGMA table_info(part)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
11473
+ const missingMessage = REQUIRED_MESSAGE_COLUMNS.filter((c) => !messageCols.has(c));
11474
+ const missingPart = REQUIRED_PART_COLUMNS.filter((c) => !partCols.has(c));
11475
+ if (missingMessage.length > 0 || missingPart.length > 0) {
11476
+ log2(`[magic-context] compaction-marker: OpenCode DB schema missing required columns ` + `(message: [${missingMessage.join(", ")}], part: [${missingPart.join(", ")}]). ` + `Marker injection disabled for this process. ` + `This usually means OpenCode was updated and magic-context is out of date.`);
11477
+ cachedSchemaCompatible = { path: dbPath, compatible: false };
11478
+ return false;
11479
+ }
11480
+ cachedSchemaCompatible = { path: dbPath, compatible: true };
11481
+ return true;
11482
+ } catch (error) {
11483
+ log2(`[magic-context] compaction-marker: schema probe failed: ${error instanceof Error ? error.message : String(error)}. ` + `Marker injection disabled until next process restart.`);
11484
+ cachedSchemaCompatible = { path: dbPath, compatible: false };
11485
+ return false;
11537
11486
  }
11538
- if (notice.unresolvedCompartments > 0) {
11539
- const listed = notice.unresolvedCompartmentRanges.length > 0 ? ` (${formatRangeNotes(notice.unresolvedCompartmentRanges)})` : "";
11540
- parts.push(`${notice.unresolvedCompartments} compartment${notice.unresolvedCompartments === 1 ? "" : "s"} could not be re-anchored and are excluded from range recovery${listed}`);
11487
+ }
11488
+ function getWritableOpenCodeDb(purpose = "publication") {
11489
+ if (!harnessOwnsOpenCodeStore2()) {
11490
+ throw new Error("OpenCode database is not writable from a Pi-compatible process");
11541
11491
  }
11542
- if (notice.droppedDepthRows > 0) {
11543
- parts.push(`${notice.droppedDepthRows} compression-depth records were rebuilt from zero`);
11492
+ const resolution = resolveOpenCodeDbPath();
11493
+ const dbPath = resolution.path;
11494
+ const cached = purpose === "removal" ? cachedRemovalDb : cachedWriteDb;
11495
+ if (cached?.path === dbPath) {
11496
+ return cached.db;
11544
11497
  }
11545
- if (notice.healedGaps > 0) {
11546
- parts.push(`${notice.healedGaps} non-narrative compartment gap${notice.healedGaps === 1 ? " was" : "s were"} healed`);
11498
+ if (cached) {
11499
+ try {
11500
+ closeQuietly(cached.db);
11501
+ } catch {}
11547
11502
  }
11548
- if (notice.narrativeGaps > 0) {
11549
- parts.push(`${notice.narrativeGaps} narrative compartment gap${notice.narrativeGaps === 1 ? " remains" : "s remain"} for review`);
11503
+ if (!existsSync6(dbPath)) {
11504
+ throw new Error(`OpenCode database not found at ${dbPath} (source=${resolution.source}; is OpenCode installed?)`);
11550
11505
  }
11551
- return parts.length === 0 ? null : parts.join("; ");
11552
- }
11553
- function formatRangeNotes(notes) {
11554
- return notes.map((note) => `messages ${note.start}-${note.end}`).join(", ");
11555
- }
11556
- function isCompartmentCoordinateRow(row) {
11557
- if (row === null || typeof row !== "object")
11558
- return false;
11559
- const candidate = row;
11560
- return typeof candidate.id === "number" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number";
11561
- }
11562
- function emptyProjection() {
11563
- return {
11564
- ordinalById: new Map,
11565
- partCountById: new Map,
11566
- nonNarrativeOrdinals: new Set,
11567
- messageCount: 0,
11568
- indexSources: []
11569
- };
11570
- }
11571
- function addToProjection(projection, messages, withIndexSources) {
11572
- for (const message of messages) {
11573
- projection.ordinalById.set(message.id, message.ordinal);
11574
- projection.partCountById.set(message.id, Array.isArray(message.parts) ? message.parts.length : 0);
11575
- if (isStrictGapHealingMessage2(message))
11576
- projection.nonNarrativeOrdinals.add(message.ordinal);
11577
- if (withIndexSources)
11578
- projection.indexSources.push(toMessageIndexSource(message));
11506
+ const db = new Database2(dbPath);
11507
+ try {
11508
+ assertOpenCodeStoreGeneration(db, "v1", dbPath);
11509
+ } catch (error) {
11510
+ closeQuietly(db);
11511
+ throw error;
11579
11512
  }
11580
- projection.messageCount += messages.length;
11581
- }
11582
- function readProjectionPages(args) {
11583
- if (args.readMessagePages)
11584
- return args.readMessagePages(args.sessionId);
11585
- return [args.readMessages(args.sessionId)];
11513
+ const timeoutMs = purpose === "removal" ? MARKER_REMOVAL_BUSY_TIMEOUT_MS : MARKER_BUSY_TIMEOUT_MS;
11514
+ db.exec(`PRAGMA busy_timeout=${timeoutMs}`);
11515
+ db.exec("PRAGMA journal_mode=WAL");
11516
+ if (purpose === "removal")
11517
+ cachedRemovalDb = { path: dbPath, db };
11518
+ else
11519
+ cachedWriteDb = { path: dbPath, db };
11520
+ return db;
11586
11521
  }
11587
- function* buildProjectionSteps(args, withIndexSources) {
11588
- const projection = emptyProjection();
11589
- for (const page of readProjectionPages(args)) {
11590
- addToProjection(projection, page, withIndexSources);
11591
- yield;
11522
+ function getNonSummaryMessageSortKey(sessionId, messageId) {
11523
+ const db = getWritableOpenCodeDb();
11524
+ const row = db.prepare(`SELECT time_created, id
11525
+ FROM message
11526
+ WHERE session_id = ?
11527
+ AND id = ?
11528
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
11529
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
11530
+ LIMIT 1`).get(sessionId, messageId);
11531
+ if (typeof row?.time_created !== "number" || typeof row.id !== "string") {
11532
+ return null;
11592
11533
  }
11593
- return projection;
11534
+ return { id: row.id, timeCreated: row.time_created };
11594
11535
  }
11595
- var INDEX_REBUILD_CHUNK = 2000;
11596
- function messageIdFromAnchorBlockId(anchorBlockId) {
11597
- const hash = anchorBlockId.lastIndexOf("#");
11598
- return hash > 0 ? anchorBlockId.slice(0, hash) : anchorBlockId;
11536
+ function findBoundaryUserMessage(sessionId, endMessageId) {
11537
+ const db = getWritableOpenCodeDb();
11538
+ const target = getNonSummaryMessageSortKey(sessionId, endMessageId);
11539
+ if (!target)
11540
+ return null;
11541
+ const boundary = db.prepare(`SELECT id, time_created, data
11542
+ FROM message
11543
+ WHERE session_id = ?
11544
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
11545
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
11546
+ AND COALESCE(json_extract(data, '$.role'), '') = 'user'
11547
+ AND (time_created, id) <= (?, ?)
11548
+ AND NOT (
11549
+ EXISTS (SELECT 1 FROM part p
11550
+ WHERE likelihood(p.message_id = message.id, 0.000001) AND +p.session_id = message.session_id
11551
+ AND COALESCE(json_extract(p.data, '$.type'), '') <> 'compaction')
11552
+ AND NOT EXISTS (SELECT 1 FROM part p
11553
+ WHERE likelihood(p.message_id = message.id, 0.000001) AND +p.session_id = message.session_id
11554
+ AND COALESCE(json_extract(p.data, '$.type'), '') <> 'compaction'
11555
+ AND COALESCE(json_extract(p.data, '$.synthetic'), 0) <> 1
11556
+ AND COALESCE(json_extract(p.data, '$.syntheticTodoMarker'), 0) <> 1)
11557
+ )
11558
+ ORDER BY time_created DESC, id DESC
11559
+ LIMIT 1`).get(sessionId, target.timeCreated, target.id);
11560
+ if (typeof boundary?.id !== "string" || typeof boundary.time_created !== "number") {
11561
+ return null;
11562
+ }
11563
+ return { id: boundary.id, timeCreated: boundary.time_created };
11599
11564
  }
11600
- function readCompartmentRows(db, table, sessionId) {
11601
- return db.prepare(`SELECT id, sequence, start_message, end_message, start_message_id, end_message_id, rebase_status
11602
- FROM ${table} WHERE session_id = ? ORDER BY sequence ASC`).all(sessionId).filter(isCompartmentCoordinateRow);
11565
+ function compareOpenCodeMessagesByCanonicalOrder(sessionId, leftMessageId, rightMessageId) {
11566
+ const left = getNonSummaryMessageSortKey(sessionId, leftMessageId);
11567
+ const right = getNonSummaryMessageSortKey(sessionId, rightMessageId);
11568
+ if (!left || !right)
11569
+ return null;
11570
+ if (left.timeCreated < right.timeCreated)
11571
+ return -1;
11572
+ if (left.timeCreated > right.timeCreated)
11573
+ return 1;
11574
+ if (left.id < right.id)
11575
+ return -1;
11576
+ if (left.id > right.id)
11577
+ return 1;
11578
+ return 0;
11603
11579
  }
11604
- function resolveAnchor(messageId, resolveOrdinal) {
11605
- return messageId && messageId.length > 0 ? resolveOrdinal(messageId) : undefined;
11580
+ function isOpenCodeGapHistorianAbsent(sessionId, endId, nextId) {
11581
+ const end = getNonSummaryMessageSortKey(sessionId, endId);
11582
+ const next = getNonSummaryMessageSortKey(sessionId, nextId);
11583
+ if (!end || !next || end.timeCreated > next.timeCreated || end.timeCreated === next.timeCreated && end.id >= next.id)
11584
+ return false;
11585
+ const row = getWritableOpenCodeDb().prepare(`SELECT 1 FROM message m
11586
+ WHERE m.session_id=?
11587
+ AND (m.time_created, m.id) > (?, ?)
11588
+ AND (m.time_created, m.id) < (?, ?)
11589
+ AND NOT (COALESCE(json_type(m.data,'$.summary'),'')='true' AND COALESCE(json_extract(m.data,'$.finish'),'')='stop')
11590
+ AND NOT (
11591
+ EXISTS (SELECT 1 FROM part p WHERE likelihood(p.message_id=m.id, 0.000001) AND +p.session_id=m.session_id AND COALESCE(json_extract(p.data,'$.type'),'')<>'compaction')
11592
+ AND NOT EXISTS (SELECT 1 FROM part p WHERE likelihood(p.message_id=m.id, 0.000001) AND +p.session_id=m.session_id
11593
+ AND COALESCE(json_extract(p.data,'$.type'),'')<>'compaction'
11594
+ AND COALESCE(json_type(p.data,'$.synthetic'),'')<>'true'
11595
+ AND COALESCE(json_type(p.data,'$.syntheticTodoMarker'),'')<>'true')
11596
+ ) LIMIT 1`).get(sessionId, end.timeCreated, end.id, next.timeCreated, next.id);
11597
+ return !row;
11606
11598
  }
11607
- function planCompartments(rows, table, projection) {
11608
- const resolveOrdinal = (messageId) => projection.ordinalById.get(messageId);
11609
- return recoverFromNeighbours(rows, table, rows.map((row) => ({
11610
- start: resolveAnchor(row.start_message_id, resolveOrdinal),
11611
- end: resolveAnchor(row.end_message_id, resolveOrdinal)
11612
- })));
11599
+ function getOpenCodeMessageById(sessionId, messageId) {
11600
+ const db = getWritableOpenCodeDb();
11601
+ const row = db.prepare(`SELECT id FROM message WHERE session_id = ? AND id = ? LIMIT 1`).get(sessionId, messageId);
11602
+ return row ?? null;
11613
11603
  }
11614
- function recoverFromNeighbours(rows, table, known) {
11615
- const plans = rows.map((row, index) => {
11616
- const own = known[index] ?? { start: undefined, end: undefined };
11617
- const previousEnd = index === 0 ? 0 : known[index - 1]?.end;
11618
- const nextStart = index === rows.length - 1 ? undefined : known[index + 1]?.start;
11619
- const start = own.start ?? (previousEnd === undefined ? undefined : previousEnd + 1);
11620
- const end = own.end ?? (nextStart === undefined ? undefined : nextStart - 1);
11621
- const base = {
11622
- table,
11623
- id: row.id,
11624
- sequence: row.sequence,
11625
- previousStart: row.start_message,
11626
- previousEnd: row.end_message,
11627
- previousStatus: row.rebase_status === "unresolved" ? "unresolved" : "ok"
11628
- };
11629
- if (start !== undefined && end !== undefined && start <= end) {
11630
- return {
11631
- ...base,
11632
- start,
11633
- end,
11634
- status: "ok",
11635
- derived: own.start === undefined || own.end === undefined
11636
- };
11637
- }
11638
- return {
11639
- ...base,
11640
- start: start ?? row.start_message,
11641
- end: end ?? row.end_message,
11642
- status: "unresolved",
11643
- derived: false
11644
- };
11645
- });
11646
- for (let index = 0;index < plans.length; index += 1) {
11647
- const plan = plans[index];
11648
- if (plan?.status !== "unresolved")
11649
- continue;
11650
- const previous = plans[index - 1];
11651
- const next = plans[index + 1];
11652
- if (previous?.status === "ok" && plan.start <= previous.end) {
11653
- plan.start = previous.end + 1;
11654
- }
11655
- if (next?.status === "ok" && plan.end >= next.start) {
11656
- plan.end = next.start - 1;
11657
- }
11604
+ var LEGACY_MARKER_LINEAGE_SQL = `SELECT m.id
11605
+ FROM message m
11606
+ WHERE +m.session_id = ? AND m.id IN (SELECT value FROM json_each(?)) AND m.id <> ?
11607
+ AND COALESCE(json_extract(m.data, '$.summary'), 0) = 1
11608
+ AND COALESCE(json_extract(m.data, '$.finish'), '') = 'stop'
11609
+ AND COALESCE(json_extract(m.data, '$.parentID'), '') = ?
11610
+ AND EXISTS (SELECT 1 FROM part p
11611
+ WHERE +p.session_id = m.session_id AND p.message_id = m.id
11612
+ AND COALESCE(json_extract(p.data, '$.type'), '') = 'text'
11613
+ AND COALESCE(json_extract(p.data, '$.text'), '') = ?)`;
11614
+ function removeLegacyMarkerLineageRows(db, args) {
11615
+ const legacySummaries = db.prepare(LEGACY_MARKER_LINEAGE_SQL).all(args.sessionId, JSON.stringify(args.candidateIds), args.summaryMessageId, args.boundaryMessageId, args.summaryText);
11616
+ const legacySummaryIds = legacySummaries.flatMap((row) => typeof row.id === "string" ? [row.id] : []);
11617
+ if (legacySummaryIds.length === 0)
11618
+ return;
11619
+ const deleteSummaryParts = db.prepare("DELETE FROM part WHERE +session_id = ? AND message_id = ?");
11620
+ const deleteSummary = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
11621
+ for (const summaryMessageId of legacySummaryIds) {
11622
+ deleteSummaryParts.run(args.sessionId, summaryMessageId);
11623
+ deleteSummary.run(args.sessionId, summaryMessageId);
11658
11624
  }
11659
- return plans;
11625
+ db.prepare(`DELETE FROM part
11626
+ WHERE +session_id = ?
11627
+ AND message_id = ?
11628
+ AND id <> ?
11629
+ AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'
11630
+ AND COALESCE(json_extract(data, '$.auto'), 0) = 1`).run(args.sessionId, args.boundaryMessageId, args.compactionPartId);
11660
11631
  }
11661
- function healNonNarrativeCompartmentGaps(plans, projection) {
11662
- let healed = 0;
11663
- let narrative = 0;
11664
- for (let index = 1;index < plans.length; index += 1) {
11665
- const previous = plans[index - 1];
11666
- const current = plans[index];
11667
- if (!previous || !current || previous.status !== "ok" || current.status !== "ok")
11668
- continue;
11669
- const gapStart = previous.end + 1;
11670
- const gapEnd = current.start - 1;
11671
- if (gapEnd < gapStart)
11672
- continue;
11673
- let safeToHeal = true;
11674
- for (let ordinal = gapStart;ordinal <= gapEnd; ordinal += 1) {
11675
- if (!projection.nonNarrativeOrdinals.has(ordinal)) {
11676
- safeToHeal = false;
11677
- break;
11678
- }
11679
- }
11680
- if (safeToHeal) {
11681
- previous.end = gapEnd;
11682
- healed += 1;
11683
- } else {
11684
- narrative += 1;
11685
- }
11632
+ async function prepareCompactionMarkerCandidates(sessionId, options = {}) {
11633
+ if (!harnessOwnsOpenCodeStore2())
11634
+ return true;
11635
+ try {
11636
+ return await prepareMarkerCandidateBasis2(getWritableOpenCodeDb(), sessionId, options);
11637
+ } catch (error) {
11638
+ log2(`[magic-context] compaction-marker: deferred candidate preparation for ${sessionId}: ${error instanceof Error ? error.message : String(error)}; marker unchanged`);
11639
+ return false;
11686
11640
  }
11687
- return { healed, narrative };
11688
- }
11689
- function compartmentPlanChanges(plan) {
11690
- return plan.status !== plan.previousStatus || plan.start !== plan.previousStart || plan.end !== plan.previousEnd;
11691
- }
11692
- function rangeNotes(plans, predicate) {
11693
- return plans.filter((plan) => plan.table === "compartments" && predicate(plan)).map((plan) => ({ sequence: plan.sequence, start: plan.start, end: plan.end }));
11694
- }
11695
- function planNotes(db, sessionId, projection) {
11696
- const rows = db.prepare("SELECT id, anchor_ordinal, anchor_block_id FROM notes WHERE session_id = ? AND anchor_ordinal IS NOT NULL").all(sessionId);
11697
- return rows.flatMap((row) => {
11698
- if (typeof row.id !== "number")
11699
- return [];
11700
- const previousOrdinal = typeof row.anchor_ordinal === "number" ? row.anchor_ordinal : null;
11701
- const anchorBlockId = typeof row.anchor_block_id === "string" ? row.anchor_block_id : "";
11702
- if (anchorBlockId.length === 0) {
11703
- return [{ id: row.id, ordinal: null, previousOrdinal }];
11704
- }
11705
- const ordinal = projection.ordinalById.get(messageIdFromAnchorBlockId(anchorBlockId));
11706
- return [{ id: row.id, ordinal: ordinal ?? null, previousOrdinal }];
11707
- });
11708
- }
11709
- function countRows2(db, sql, ...params) {
11710
- const row = db.prepare(sql).get(...params);
11711
- return typeof row?.count === "number" ? row.count : 0;
11712
11641
  }
11713
- function stampGeneration(db, sessionId, generation, notice) {
11714
- ensureSessionMetaRow(db, sessionId);
11715
- if (notice === null) {
11716
- db.prepare("UPDATE session_meta SET coordinate_generation = ? WHERE session_id = ?").run(generation, sessionId);
11717
- return;
11642
+ function injectCompactionMarkerFromBasis(args, validatedBasis) {
11643
+ const db = getWritableOpenCodeDb();
11644
+ if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath())) {
11645
+ return null;
11718
11646
  }
11719
- db.prepare("UPDATE session_meta SET coordinate_generation = ?, coordinate_rebase_notice = ? WHERE session_id = ?").run(generation, JSON.stringify(notice), sessionId);
11720
- }
11721
- function pruneShrunkPartEntries(db, sessionId, column, shrunk) {
11722
- if (shrunk.length === 0)
11723
- return 0;
11724
- const row = db.prepare(`SELECT ${column} AS value FROM session_meta WHERE session_id = ?`).get(sessionId);
11725
- const raw = row?.value;
11726
- if (typeof raw !== "string" || raw.length === 0)
11727
- return 0;
11728
- let parsed;
11729
- try {
11730
- parsed = JSON.parse(raw);
11731
- } catch {
11732
- return 0;
11647
+ const boundary = args.resolvedBoundary ?? findBoundaryUserMessage(args.sessionId, args.endMessageId);
11648
+ if (!boundary) {
11649
+ log2(`[magic-context] compaction-marker: no user message found at or before endMessageId ${args.endMessageId} (ordinal ${args.endOrdinal})`);
11650
+ return null;
11733
11651
  }
11734
- const partCountByMessage = new Map(shrunk.map((entry) => [entry.messageId, entry.partCount]));
11735
- const isStale = (candidate) => {
11736
- const marker = candidate.lastIndexOf(":p");
11737
- if (marker < 0)
11738
- return false;
11739
- const suffix = candidate.slice(marker + 2);
11740
- if (!/^\d+$/.test(suffix))
11741
- return false;
11742
- const partCount = partCountByMessage.get(candidate.slice(0, marker));
11743
- return partCount !== undefined && Number.parseInt(suffix, 10) >= partCount;
11744
- };
11745
- let dropped = 0;
11746
- const pruneArray = (values) => values.filter((value) => {
11747
- if (typeof value === "string" && isStale(value)) {
11748
- dropped += 1;
11749
- return false;
11750
- }
11751
- return true;
11652
+ const boundaryTime = boundary.timeCreated;
11653
+ const markerIdentity = `${args.sessionId}\x00${args.endMessageId}`;
11654
+ const summaryMsgId = generateMessageId(boundaryTime + 1, 1n, `${markerIdentity}\x00summary-message`);
11655
+ const compactionPartId = generatePartId(boundaryTime, 1n, `${markerIdentity}\x00compaction-part`);
11656
+ const summaryPartId = generatePartId(boundaryTime + 1, 2n, `${markerIdentity}\x00summary-part`);
11657
+ const summaryMsgData = JSON.stringify({
11658
+ role: "assistant",
11659
+ parentID: boundary.id,
11660
+ summary: true,
11661
+ finish: "stop",
11662
+ mode: "compaction",
11663
+ agent: "compaction",
11664
+ path: { cwd: args.directory, root: args.directory },
11665
+ cost: 0,
11666
+ tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
11667
+ modelID: "magic-context",
11668
+ providerID: "magic-context",
11669
+ time: { created: boundaryTime + 1, completed: boundaryTime + 1 }
11752
11670
  });
11753
- let next;
11754
- if (Array.isArray(parsed)) {
11755
- next = pruneArray(parsed);
11756
- } else if (parsed && typeof parsed === "object") {
11757
- const source = parsed;
11758
- const result = {};
11759
- for (const [key, value] of Object.entries(source)) {
11760
- if (isStale(key)) {
11761
- dropped += 1;
11762
- continue;
11763
- }
11764
- result[key] = Array.isArray(value) ? pruneArray(value) : value;
11765
- }
11766
- next = result;
11767
- } else {
11768
- return 0;
11769
- }
11770
- if (dropped === 0)
11771
- return 0;
11772
- db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ?`).run(JSON.stringify(next), sessionId);
11773
- return dropped;
11774
- }
11775
- var REBASE_SLICE_MS = 20;
11776
- var rebasesInFlight = new WeakMap;
11777
- async function rebaseSessionCoordinatesAsync(args) {
11778
- let sessions = rebasesInFlight.get(args.db);
11779
- if (!sessions) {
11780
- sessions = new Map;
11781
- rebasesInFlight.set(args.db, sessions);
11782
- }
11783
- const earlier = sessions.get(args.sessionId);
11784
- if (earlier)
11785
- await earlier.catch(() => {
11786
- return;
11787
- });
11788
- const run = runSliced(args);
11789
- sessions.set(args.sessionId, run);
11790
11671
  try {
11791
- return await run;
11792
- } finally {
11793
- if (sessions.get(args.sessionId) === run)
11794
- sessions.delete(args.sessionId);
11672
+ const basis = validatedBasis ?? readMarkerCandidateBasis2(db, args.sessionId);
11673
+ if (!basis)
11674
+ return null;
11675
+ runMarkerWriteTransaction(db, "compaction-marker-inject", () => {
11676
+ if (!validatedBasis && !isMarkerCandidateBasisCurrent2(db, basis))
11677
+ throw new Error("host store changed after marker candidate preparation; marker unchanged");
11678
+ removeLegacyMarkerLineageRows(db, {
11679
+ sessionId: args.sessionId,
11680
+ boundaryMessageId: boundary.id,
11681
+ candidateIds: basis.ids,
11682
+ summaryText: args.summaryText,
11683
+ summaryMessageId: summaryMsgId,
11684
+ compactionPartId
11685
+ });
11686
+ db.prepare(`INSERT INTO part (id, message_id, session_id, time_created, time_updated, data)
11687
+ VALUES (?, ?, ?, ?, ?, ?)
11688
+ ON CONFLICT(id) DO UPDATE SET
11689
+ message_id = excluded.message_id,
11690
+ session_id = excluded.session_id,
11691
+ time_created = excluded.time_created,
11692
+ time_updated = excluded.time_updated,
11693
+ data = excluded.data`).run(compactionPartId, boundary.id, args.sessionId, boundaryTime, boundaryTime, '{"type":"compaction","auto":true}');
11694
+ db.prepare(`INSERT INTO message (id, session_id, time_created, time_updated, data)
11695
+ VALUES (?, ?, ?, ?, ?)
11696
+ ON CONFLICT(id) DO UPDATE SET
11697
+ session_id = excluded.session_id,
11698
+ time_created = excluded.time_created,
11699
+ time_updated = excluded.time_updated,
11700
+ data = excluded.data`).run(summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, summaryMsgData);
11701
+ noteRawSessionSummaryRowWritten2(args.sessionId, summaryMsgId);
11702
+ invalidateMarkerCandidateBasis2(db, args.sessionId);
11703
+ db.prepare(`INSERT INTO part (id, message_id, session_id, time_created, time_updated, data)
11704
+ VALUES (?, ?, ?, ?, ?, ?)
11705
+ ON CONFLICT(id) DO UPDATE SET
11706
+ message_id = excluded.message_id,
11707
+ session_id = excluded.session_id,
11708
+ time_created = excluded.time_created,
11709
+ time_updated = excluded.time_updated,
11710
+ data = excluded.data`).run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
11711
+ });
11712
+ log2(`[magic-context] compaction-marker: injected boundary at user msg ${boundary.id} (ordinal ~${args.endOrdinal}), summary msg ${summaryMsgId}`);
11713
+ return {
11714
+ boundaryMessageId: boundary.id,
11715
+ summaryMessageId: summaryMsgId,
11716
+ compactionPartId,
11717
+ summaryPartId
11718
+ };
11719
+ } catch (error) {
11720
+ log2(`[magic-context] compaction-marker: injection failed: ${error instanceof Error ? error.message : String(error)}`);
11721
+ return null;
11795
11722
  }
11796
11723
  }
11797
- async function runSliced(args) {
11798
- const steps = rebaseSteps(args);
11799
- let finished = false;
11724
+
11725
+ class MarkerCandidateUnavailableError extends Error {
11726
+ }
11727
+ function replaceCompactionMarker(existing, args) {
11728
+ let connection;
11729
+ let entered = false;
11730
+ let readyToCommit = false;
11800
11731
  try {
11801
- let sliceStartedAt = performance.now();
11802
- for (;; ) {
11803
- const step = steps.next();
11804
- if (step.done) {
11805
- finished = true;
11806
- return step.value;
11732
+ const db = getWritableOpenCodeDb();
11733
+ connection = db;
11734
+ const basis = readMarkerCandidateBasis2(db, args.sessionId);
11735
+ if (!basis) {
11736
+ return {
11737
+ kind: "deferred",
11738
+ error: new Error("marker candidate preparation pending; marker unchanged")
11739
+ };
11740
+ }
11741
+ const marker = runMarkerWriteTransaction(db, "compaction-marker-replace", () => {
11742
+ entered = true;
11743
+ if (!isMarkerCandidateBasisCurrent2(db, basis))
11744
+ throw new MarkerCandidateUnavailableError("host store changed after marker candidate preparation; marker unchanged");
11745
+ if (existing) {
11746
+ db.prepare("DELETE FROM part WHERE id = ?").run(existing.summaryPartId);
11747
+ db.prepare("DELETE FROM message WHERE id = ?").run(existing.summaryMessageId);
11748
+ db.prepare("DELETE FROM part WHERE id = ?").run(existing.compactionPartId);
11807
11749
  }
11808
- if (performance.now() - sliceStartedAt >= REBASE_SLICE_MS) {
11809
- await new Promise((resolve) => setImmediate(resolve));
11810
- sliceStartedAt = performance.now();
11750
+ const replacement = injectCompactionMarkerFromBasis(args, basis);
11751
+ if (!replacement) {
11752
+ throw new Error(`failed to inject replacement marker at ordinal ${args.endOrdinal}`);
11811
11753
  }
11812
- }
11813
- } finally {
11814
- if (!finished)
11815
- steps.return(emptyOutcome("unchanged", args.generation, null));
11754
+ readyToCommit = true;
11755
+ return replacement;
11756
+ });
11757
+ return { kind: "committed", marker };
11758
+ } catch (error) {
11759
+ if (error instanceof MarkerCandidateUnavailableError)
11760
+ return { kind: "deferred", error };
11761
+ log2(`[magic-context] compaction-marker: atomic replacement failed: ${error instanceof Error ? error.message : String(error)}`);
11762
+ const definitelyNoCut = !entered || !readyToCommit && connection?.inTransaction === false;
11763
+ return {
11764
+ kind: definitelyNoCut ? "definitely-no-cut" : "uncertain",
11765
+ error: error instanceof Error ? error : new Error(String(error))
11766
+ };
11816
11767
  }
11817
11768
  }
11818
- function* rebaseSteps(args) {
11819
- const { db, sessionId, generation } = args;
11820
- const startedAt = performance.now();
11821
- if (!sessionIsOpenCodeOwned(db, sessionId)) {
11822
- return emptyOutcome("unchanged", generation, null);
11769
+ function listSessionCompactionMarkers(sessionId) {
11770
+ const db = getWritableOpenCodeDb();
11771
+ const summaryRows = db.prepare(`SELECT id, json_extract(data, '$.parentID') AS boundary_message_id
11772
+ FROM message
11773
+ WHERE session_id = ?
11774
+ AND COALESCE(json_extract(data, '$.summary'), 0) = 1
11775
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop'
11776
+ AND COALESCE(json_extract(data, '$.providerID'), '') = 'magic-context'
11777
+ ORDER BY time_created ASC, id ASC`).all(sessionId);
11778
+ const summaryIdsByBoundary = new Map;
11779
+ for (const row of summaryRows) {
11780
+ if (typeof row.id !== "string" || typeof row.boundary_message_id !== "string")
11781
+ continue;
11782
+ const summaryIds = summaryIdsByBoundary.get(row.boundary_message_id) ?? [];
11783
+ summaryIds.push(row.id);
11784
+ summaryIdsByBoundary.set(row.boundary_message_id, summaryIds);
11823
11785
  }
11824
- const previousGeneration = readCoordinateGeneration(db, sessionId);
11825
- if (previousGeneration === generation) {
11826
- const outcome = emptyOutcome("unchanged", generation, previousGeneration);
11827
- const repair = repairStampedSessionOnce(db, sessionId, args);
11828
- if (repair !== null && repair.rowsRewritten > 0) {
11829
- outcome.status = "repaired";
11830
- outcome.compartmentsDerived = repair.derived.length;
11831
- outcome.compartmentsUnresolved = repair.unresolved.length;
11786
+ const boundaryIds = [...summaryIdsByBoundary.keys()];
11787
+ const markers = [];
11788
+ const chunkSize = 800;
11789
+ for (let offset = 0;offset < boundaryIds.length; offset += chunkSize) {
11790
+ const boundaryChunk = boundaryIds.slice(offset, offset + chunkSize);
11791
+ const placeholders = boundaryChunk.map(() => "?").join(", ");
11792
+ const partRows = db.prepare(`SELECT id, message_id, time_created
11793
+ FROM part
11794
+ WHERE +session_id = ?
11795
+ AND likelihood(message_id IN (${placeholders}), 0.000001)
11796
+ AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'
11797
+ ORDER BY time_created ASC, id ASC`).all(sessionId, ...boundaryChunk);
11798
+ for (const row of partRows) {
11799
+ if (typeof row.id !== "string" || typeof row.message_id !== "string" || typeof row.time_created !== "number") {
11800
+ continue;
11801
+ }
11802
+ const summaryMessageIds = summaryIdsByBoundary.get(row.message_id);
11803
+ if (!summaryMessageIds)
11804
+ continue;
11805
+ markers.push({
11806
+ compactionPartId: row.id,
11807
+ boundaryMessageId: row.message_id,
11808
+ summaryMessageIds: [...summaryMessageIds],
11809
+ timeCreated: row.time_created
11810
+ });
11832
11811
  }
11833
- return outcome;
11834
11812
  }
11835
- const impliedGeneration = previousGeneration ?? generationImpliedByHarness(db, sessionId) ?? generation;
11836
- if (impliedGeneration === generation) {
11837
- stampGeneration(db, sessionId, generation, null);
11838
- return emptyOutcome("stamped", generation, previousGeneration);
11839
- }
11840
- const projection = yield* buildProjectionSteps(args, true);
11841
- const outcome = emptyOutcome("rebased", generation, impliedGeneration);
11842
- const compartmentRows = readCompartmentRows(db, "compartments", sessionId);
11843
- const recompRows = readCompartmentRows(db, "recomp_compartments", sessionId);
11844
- const compartmentPlans = planCompartments(compartmentRows, "compartments", projection);
11845
- const recompPlans = planCompartments(recompRows, "recomp_compartments", projection);
11846
- const compartmentGapResult = healNonNarrativeCompartmentGaps(compartmentPlans, projection);
11847
- const recompGapResult = healNonNarrativeCompartmentGaps(recompPlans, projection);
11848
- const notePlans = planNotes(db, sessionId, projection);
11849
- const shrunkMessages = [];
11850
- const taggedMessageIds = new Set(db.prepare("SELECT message_id FROM tags WHERE session_id = ? AND type = 'message'").all(sessionId).flatMap((row) => typeof row.message_id === "string" ? [row.message_id] : []));
11851
- const highestTaggedPartIndex = new Map;
11852
- for (const contentId of taggedMessageIds) {
11853
- const marker = contentId.lastIndexOf(":p");
11854
- if (marker <= 0)
11855
- continue;
11856
- const suffix = contentId.slice(marker + 2);
11857
- if (!/^\d+$/.test(suffix))
11858
- continue;
11859
- const messageId = contentId.slice(0, marker);
11860
- const partIndex = Number.parseInt(suffix, 10);
11861
- highestTaggedPartIndex.set(messageId, Math.max(highestTaggedPartIndex.get(messageId) ?? 0, partIndex));
11862
- }
11863
- for (const [messageId, highestIndex] of highestTaggedPartIndex) {
11864
- const partCount = projection.partCountById.get(messageId);
11865
- if (partCount === undefined || highestIndex < partCount)
11866
- continue;
11867
- shrunkMessages.push({ messageId, partCount });
11868
- }
11869
- const indexNeedsRebuild = indexDisagreesWithProjection(db, sessionId, projection);
11870
- const chunkEmbeddingCount = countRows2(db, "SELECT COUNT(*) AS count FROM compartment_chunk_embeddings WHERE session_id = ?", sessionId);
11871
- const depthRowCount = countRows2(db, "SELECT COUNT(*) AS count FROM compression_depth WHERE session_id = ?", sessionId);
11872
- const lkgSlotCount = countRows2(db, "SELECT COUNT(*) AS count FROM lkg_slots WHERE session_id = ?", sessionId);
11873
- const boundaryPlan = planPriorBoundary(db, sessionId, compartmentPlans);
11874
- const partialRangePlan = planRecompPartialRange(db, sessionId, recompPlans);
11875
- outcome.healedGaps = compartmentGapResult.healed + recompGapResult.healed;
11876
- outcome.narrativeGaps = compartmentGapResult.narrative + recompGapResult.narrative;
11877
- const movedCompartments = compartmentPlans.filter(compartmentPlanChanges);
11878
- const movedRecomp = recompPlans.filter(compartmentPlanChanges);
11879
- const movedNotes = notePlans.filter((plan) => plan.ordinal !== plan.previousOrdinal);
11880
- const anythingMoved = movedCompartments.length > 0 || movedRecomp.length > 0 || movedNotes.length > 0 || shrunkMessages.length > 0 || indexNeedsRebuild || boundaryPlan !== null || partialRangePlan !== null || outcome.healedGaps > 0 || outcome.narrativeGaps > 0;
11881
- if (!anythingMoved) {
11882
- stampGeneration(db, sessionId, generation, null);
11883
- return emptyOutcome("stamped", generation, impliedGeneration);
11884
- }
11885
- db.exec("BEGIN IMMEDIATE");
11886
- let closed = false;
11813
+ markers.sort((left, right) => left.timeCreated - right.timeCreated || left.compactionPartId.localeCompare(right.compactionPartId));
11814
+ return markers.map(({ timeCreated: _, ...marker }) => marker);
11815
+ }
11816
+ function removeForeignCompactionMarker(sessionId, marker, protectedSummaryMessageId) {
11887
11817
  try {
11888
- if (readCoordinateGeneration(db, sessionId) !== previousGeneration) {
11889
- db.exec("ROLLBACK");
11890
- closed = true;
11891
- return emptyOutcome("unchanged", generation, readCoordinateGeneration(db, sessionId));
11892
- }
11893
- clearCachedM0M1(db, sessionId);
11894
- db.prepare("UPDATE session_meta SET system_prompt_hash = '' WHERE session_id = ?").run(sessionId);
11895
- for (const column of [
11896
- "stripped_placeholder_ids",
11897
- "merged_reasoning_stripped_ids",
11898
- "trailing_blank_decisions"
11899
- ]) {
11900
- outcome.frozenPartEntriesDropped += pruneShrunkPartEntries(db, sessionId, column, shrunkMessages);
11901
- }
11902
- const fold = foldShrunkPartTags2(db, sessionId, shrunkMessages);
11903
- outcome.partTagsFolded = fold.foldedTagNumbers.length;
11904
- outcome.partTagsRekeyed = fold.rekeyedTagNumbers.length;
11905
- outcome.queuedReductionsDiscarded = fold.discardedDropTagNumbers.length;
11906
- const updateCompartment = {
11907
- compartments: db.prepare("UPDATE compartments SET start_message = ?, end_message = ?, rebase_status = ? WHERE id = ?"),
11908
- recomp_compartments: db.prepare("UPDATE recomp_compartments SET start_message = ?, end_message = ?, rebase_status = ? WHERE id = ?")
11909
- };
11910
- for (const plan of [...compartmentPlans, ...recompPlans]) {
11911
- if (!compartmentPlanChanges(plan))
11912
- continue;
11913
- updateCompartment[plan.table].run(plan.start, plan.end, plan.status, plan.id);
11914
- const rebased = plan.status === "ok" ? 1 : 0;
11915
- const unresolved = plan.status === "unresolved" ? 1 : 0;
11916
- if (plan.table === "compartments") {
11917
- outcome.compartmentsRebased += rebased;
11918
- outcome.compartmentsUnresolved += unresolved;
11919
- if (rebased === 1 && plan.derived)
11920
- outcome.compartmentsDerived += 1;
11921
- if (rebased === 1 && plan.previousStatus === "unresolved")
11922
- outcome.compartmentsResolvedAgain += 1;
11923
- } else {
11924
- outcome.recompCompartmentsRebased += rebased;
11925
- outcome.recompCompartmentsUnresolved += unresolved;
11818
+ const db = getWritableOpenCodeDb("removal");
11819
+ runMarkerRemovalTransaction(db, () => {
11820
+ const deletePartsOfMessage = db.prepare("DELETE FROM part WHERE +session_id = ? AND message_id = ?");
11821
+ const deleteMessage = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
11822
+ for (const summaryMessageId of marker.summaryMessageIds) {
11823
+ if (summaryMessageId === protectedSummaryMessageId)
11824
+ continue;
11825
+ deletePartsOfMessage.run(sessionId, summaryMessageId);
11826
+ deleteMessage.run(sessionId, summaryMessageId);
11926
11827
  }
11927
- }
11928
- const updateNote = db.prepare("UPDATE notes SET anchor_ordinal = ? WHERE id = ? AND session_id = ?");
11929
- for (const plan of movedNotes) {
11930
- updateNote.run(plan.ordinal, plan.id, sessionId);
11931
- if (plan.ordinal === null)
11932
- outcome.notesCleared += 1;
11933
- else
11934
- outcome.notesRebased += 1;
11935
- }
11936
- if (boundaryPlan !== null) {
11937
- db.prepare("UPDATE session_meta SET prior_boundary_ordinal = ? WHERE session_id = ?").run(boundaryPlan, sessionId);
11938
- outcome.priorBoundaryRebased = true;
11939
- }
11940
- if (partialRangePlan !== null) {
11941
- db.prepare("UPDATE session_meta SET recomp_partial_range_start = ?, recomp_partial_range_end = ? WHERE session_id = ?").run(partialRangePlan.start, partialRangePlan.end, sessionId);
11942
- outcome.recompPartialRangeRebased = true;
11943
- }
11944
- if (indexNeedsRebuild) {
11945
- clearIndexedMessagesInTransaction(db, sessionId);
11946
- outcome.indexRebuilt = true;
11947
- outcome.compressionDepthRowsDropped = depthRowCount;
11948
- }
11949
- if (chunkEmbeddingCount > 0) {
11950
- db.prepare("DELETE FROM compartment_chunk_embeddings WHERE session_id = ?").run(sessionId);
11951
- outcome.chunkEmbeddingsDeleted = chunkEmbeddingCount;
11952
- }
11953
- if (lkgSlotCount > 0) {
11954
- db.prepare("DELETE FROM lkg_slot_chunks WHERE session_id = ?").run(sessionId);
11955
- db.prepare("DELETE FROM lkg_slots WHERE session_id = ?").run(sessionId);
11956
- outcome.lkgSlotsDropped = lkgSlotCount;
11957
- }
11958
- stampGeneration(db, sessionId, generation, {
11959
- generation,
11960
- previousGeneration: impliedGeneration,
11961
- at: Date.now(),
11962
- unresolvedCompartments: outcome.compartmentsUnresolved + outcome.recompCompartmentsUnresolved,
11963
- discardedReductions: outcome.queuedReductionsDiscarded,
11964
- droppedDepthRows: outcome.compressionDepthRowsDropped,
11965
- healedGaps: outcome.healedGaps,
11966
- narrativeGaps: outcome.narrativeGaps,
11967
- derivedCompartments: rangeNotes(compartmentPlans, (plan) => plan.status === "ok" && plan.derived),
11968
- unresolvedCompartmentRanges: rangeNotes(compartmentPlans, (plan) => plan.status === "unresolved"),
11969
- neighbourRecoveryAt: Date.now()
11828
+ db.prepare("DELETE FROM part WHERE session_id = ? AND id = ?").run(sessionId, marker.compactionPartId);
11970
11829
  });
11971
- db.exec("COMMIT");
11972
- closed = true;
11973
- } finally {
11974
- if (!closed) {
11975
- try {
11976
- db.exec("ROLLBACK");
11977
- } catch {}
11978
- }
11830
+ return true;
11831
+ } catch (error) {
11832
+ log2(`[magic-context] compaction-marker: foreign-marker removal failed (${sessionId}, part ${marker.compactionPartId}): ${error instanceof Error ? error.message : String(error)}`);
11833
+ return false;
11979
11834
  }
11980
- if (outcome.indexRebuilt) {
11981
- const sources = projection.indexSources;
11982
- for (let start = 0;start < sources.length; start += INDEX_REBUILD_CHUNK) {
11983
- indexSourcesAfterOrdinal(db, sessionId, sources.slice(start, start + INDEX_REBUILD_CHUNK), sources.length);
11984
- yield;
11985
- }
11986
- outcome.indexRowsRebuilt = countRows2(db, "SELECT COUNT(*) AS count FROM message_history_source WHERE session_id = ?", sessionId);
11835
+ }
11836
+ function dataReferencesTailStart(data) {
11837
+ if (typeof data !== "object" || data === null)
11838
+ return null;
11839
+ const record = data;
11840
+ if (typeof record.tail_start_id === "string" && record.tail_start_id.length > 0) {
11841
+ return record.tail_start_id;
11987
11842
  }
11988
- sessionLog2(sessionId, formatRebaseLogLine(outcome, performance.now() - startedAt));
11989
- return outcome;
11843
+ const nested = record.compaction;
11844
+ if (typeof nested === "object" && nested !== null) {
11845
+ const nestedTail = nested.tail_start_id;
11846
+ if (typeof nestedTail === "string" && nestedTail.length > 0)
11847
+ return nestedTail;
11848
+ }
11849
+ return null;
11990
11850
  }
11991
- function recoverUnresolvedCompartments(args) {
11992
- const { db, sessionId } = args;
11993
- const rows = readCompartmentRows(db, "compartments", sessionId);
11994
- const result = { rowsRewritten: 0, derived: [], unresolved: [] };
11995
- if (!rows.some((row) => row.rebase_status === "unresolved"))
11996
- return result;
11997
- const known = rows.map((row) => {
11998
- if (row.rebase_status !== "unresolved") {
11999
- return { start: row.start_message, end: row.end_message };
12000
- }
11851
+ function isMcCanonicalCompactionPartData(data) {
11852
+ if (typeof data !== "object" || data === null || Array.isArray(data))
11853
+ return false;
11854
+ const record = data;
11855
+ const keys = Object.keys(record).sort();
11856
+ return keys.length === 2 && keys[0] === "auto" && keys[1] === "type" && record.type === "compaction" && record.auto === true;
11857
+ }
11858
+ function removeMcOwnedCompactionMarkers(sessionId, summaryText) {
11859
+ const db = getWritableOpenCodeDb("removal");
11860
+ if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath())) {
12001
11861
  return {
12002
- start: resolveAnchor(row.start_message_id, args.resolveOrdinal),
12003
- end: resolveAnchor(row.end_message_id, args.resolveOrdinal)
11862
+ verified: false,
11863
+ removedLineages: 0,
11864
+ removedRows: 0,
11865
+ retainedLineages: 0
12004
11866
  };
12005
- });
12006
- const plans = recoverFromNeighbours(rows, "compartments", known);
12007
- const wasUnresolved = (plan) => plan.previousStatus === "unresolved";
12008
- result.derived = rangeNotes(plans, (plan) => wasUnresolved(plan) && plan.status === "ok" && plan.derived);
12009
- result.unresolved = rangeNotes(plans, (plan) => plan.status === "unresolved");
12010
- const changed = plans.filter(compartmentPlanChanges);
12011
- const now = Date.now();
12012
- db.exec("BEGIN IMMEDIATE");
12013
- let committed = false;
12014
- try {
12015
- for (const plan of changed) {
12016
- db.prepare("UPDATE compartments SET start_message = ?, end_message = ?, rebase_status = ? WHERE id = ?").run(plan.start, plan.end, plan.status, plan.id);
12017
- }
12018
- const previous = readCoordinateRebaseNotice(db, sessionId);
12019
- const generation = previous?.generation ?? readCoordinateGeneration(db, sessionId);
12020
- if (generation !== null) {
12021
- const derivedSequences = new Set(result.derived.map((note) => note.sequence));
12022
- const notice = {
12023
- generation,
12024
- previousGeneration: previous?.previousGeneration ?? null,
12025
- at: previous?.at ?? now,
12026
- unresolvedCompartments: result.unresolved.length,
12027
- discardedReductions: previous?.discardedReductions ?? 0,
12028
- droppedDepthRows: previous?.droppedDepthRows ?? 0,
12029
- healedGaps: previous?.healedGaps ?? 0,
12030
- narrativeGaps: previous?.narrativeGaps ?? 0,
12031
- derivedCompartments: [
12032
- ...(previous?.derivedCompartments ?? []).filter((note) => !derivedSequences.has(note.sequence)),
12033
- ...result.derived
12034
- ],
12035
- unresolvedCompartmentRanges: result.unresolved,
12036
- neighbourRecoveryAt: now
12037
- };
12038
- ensureSessionMetaRow(db, sessionId);
12039
- db.prepare("UPDATE session_meta SET coordinate_rebase_notice = ? WHERE session_id = ?").run(JSON.stringify(notice), sessionId);
12040
- }
12041
- db.exec("COMMIT");
12042
- committed = true;
12043
- } finally {
12044
- if (!committed) {
12045
- try {
12046
- db.exec("ROLLBACK");
12047
- } catch {}
11867
+ }
11868
+ const canonicalSummaries = db.prepare(`SELECT id, COALESCE(json_extract(data, '$.parentID'), '') AS parent_id
11869
+ FROM message
11870
+ WHERE session_id = ?
11871
+ AND COALESCE(json_extract(data, '$.summary'), 0) = 1
11872
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop'
11873
+ AND COALESCE(json_extract(data, '$.providerID'), '') = 'magic-context'`).all(sessionId);
11874
+ const legacySummaries = db.prepare(`SELECT m.id, COALESCE(json_extract(m.data, '$.parentID'), '') AS parent_id
11875
+ FROM message m
11876
+ WHERE m.session_id = ?
11877
+ AND COALESCE(json_extract(m.data, '$.summary'), 0) = 1
11878
+ AND COALESCE(json_extract(m.data, '$.finish'), '') = 'stop'
11879
+ AND COALESCE(json_extract(m.data, '$.providerID'), '') <> 'magic-context'
11880
+ AND EXISTS (
11881
+ SELECT 1
11882
+ FROM part p
11883
+ WHERE +p.session_id = m.session_id
11884
+ AND p.message_id = m.id
11885
+ AND COALESCE(json_extract(p.data, '$.type'), '') = 'text'
11886
+ AND COALESCE(json_extract(p.data, '$.text'), '') = ?
11887
+ )`).all(sessionId, summaryText);
11888
+ const summariesByBoundary = new Map;
11889
+ const orphanSummaryIds = new Set;
11890
+ for (const row of [...canonicalSummaries, ...legacySummaries]) {
11891
+ if (typeof row.id !== "string")
11892
+ continue;
11893
+ if (typeof row.parent_id === "string" && row.parent_id.length > 0) {
11894
+ const set = summariesByBoundary.get(row.parent_id) ?? new Set;
11895
+ set.add(row.id);
11896
+ summariesByBoundary.set(row.parent_id, set);
11897
+ } else {
11898
+ orphanSummaryIds.add(row.id);
12048
11899
  }
12049
11900
  }
12050
- result.rowsRewritten = changed.length;
12051
- sessionLog2(sessionId, `INFO compartment neighbour recovery (${args.reason}) rows_rewritten=${changed.length} ` + `derived=${result.derived.map((note) => `${note.start}-${note.end}`).join(",") || "none"} ` + `unresolved=${result.unresolved.map((note) => `${note.start}-${note.end}`).join(",") || "none"}`);
12052
- return result;
12053
- }
12054
- var repairCheckedSessions = new WeakMap;
12055
- function unresolvedRowBreaksTiling(rows) {
12056
- let expectedStart = 1;
12057
- for (let index = 0;index < rows.length; index += 1) {
12058
- const row = rows[index];
12059
- if (!row)
11901
+ const compactionParts = db.prepare(`SELECT id, message_id, data
11902
+ FROM part
11903
+ WHERE session_id = ?
11904
+ AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'`).all(sessionId);
11905
+ const parsedParts = [];
11906
+ for (const part of compactionParts) {
11907
+ if (typeof part.id !== "string" || typeof part.message_id !== "string")
12060
11908
  continue;
12061
- const broken = row.start_message !== expectedStart || row.end_message < row.start_message;
12062
- const touchesUnresolved = row.rebase_status === "unresolved" || rows[index - 1]?.rebase_status === "unresolved";
12063
- if (broken && touchesUnresolved)
12064
- return true;
12065
- expectedStart = row.end_message + 1;
11909
+ let data;
11910
+ try {
11911
+ data = typeof part.data === "string" ? JSON.parse(part.data) : part.data;
11912
+ } catch {
11913
+ data = null;
11914
+ }
11915
+ parsedParts.push({
11916
+ id: part.id,
11917
+ messageId: part.message_id,
11918
+ data,
11919
+ tailStartId: dataReferencesTailStart(data)
11920
+ });
12066
11921
  }
12067
- return false;
12068
- }
12069
- function repairStampedSessionOnce(db, sessionId, readArgs) {
12070
- let checked = repairCheckedSessions.get(db);
12071
- if (!checked) {
12072
- checked = new Set;
12073
- repairCheckedSessions.set(db, checked);
11922
+ const messageTailRefs = db.prepare(`SELECT id, data
11923
+ FROM message
11924
+ WHERE session_id = ?
11925
+ AND json_extract(data, '$.compaction.tail_start_id') IS NOT NULL`).all(sessionId);
11926
+ const messageTailStartIds = new Set;
11927
+ for (const row of messageTailRefs) {
11928
+ if (typeof row.id !== "string")
11929
+ continue;
11930
+ let data;
11931
+ try {
11932
+ data = typeof row.data === "string" ? JSON.parse(row.data) : row.data;
11933
+ } catch {
11934
+ data = null;
11935
+ }
11936
+ const ref = dataReferencesTailStart(data);
11937
+ if (ref)
11938
+ messageTailStartIds.add(ref);
12074
11939
  }
12075
- if (checked.has(sessionId))
12076
- return null;
12077
- checked.add(sessionId);
12078
- const rows = readCompartmentRows(db, "compartments", sessionId);
12079
- if (!rows.some((row) => row.rebase_status === "unresolved"))
12080
- return null;
12081
- if (readCoordinateRebaseNotice(db, sessionId)?.neighbourRecoveryAt != null)
12082
- return null;
12083
- if (!unresolvedRowBreaksTiling(rows))
12084
- return null;
12085
- let ordinalById = null;
12086
- return recoverUnresolvedCompartments({
12087
- db,
12088
- sessionId,
12089
- resolveOrdinal: (messageId) => {
12090
- if (ordinalById === null) {
12091
- const projection = emptyProjection();
12092
- for (const page of readProjectionPages(readArgs)) {
12093
- addToProjection(projection, page, false);
12094
- }
12095
- ordinalById = projection.ordinalById;
11940
+ let removedLineages = 0;
11941
+ let removedRows = 0;
11942
+ let retainedLineages = 0;
11943
+ const deletePartsOfMessage = db.prepare("DELETE FROM part WHERE +session_id = ? AND message_id = ?");
11944
+ const deleteMessage = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
11945
+ const deletePart = db.prepare("DELETE FROM part WHERE session_id = ? AND id = ?");
11946
+ const deleteSummaries = (summaryIds) => {
11947
+ let rows = 0;
11948
+ for (const summaryId of summaryIds) {
11949
+ rows += deletePartsOfMessage.run(sessionId, summaryId).changes;
11950
+ rows += deleteMessage.run(sessionId, summaryId).changes;
11951
+ }
11952
+ return rows;
11953
+ };
11954
+ for (const [boundaryMessageId, summaryIds] of summariesByBoundary) {
11955
+ const boundaryParts = parsedParts.filter((part) => part.messageId === boundaryMessageId);
11956
+ const mcPartIds = boundaryParts.filter((part) => isMcCanonicalCompactionPartData(part.data)).map((part) => part.id);
11957
+ const rowsToDelete = new Set([...summaryIds, ...mcPartIds]);
11958
+ const survivingPartsReferenceDeletion = parsedParts.some((part) => !mcPartIds.includes(part.id) && part.tailStartId !== null && rowsToDelete.has(part.tailStartId));
11959
+ const messageFieldReferencesDeletion = [...rowsToDelete].some((id) => messageTailStartIds.has(id));
11960
+ if (survivingPartsReferenceDeletion || messageFieldReferencesDeletion) {
11961
+ retainedLineages += 1;
11962
+ log2(`[magic-context] compaction-marker: flip-off cleanup RETAINED lineage at boundary ${boundaryMessageId} — a surviving tail_start_id references a row the deletion would remove`);
11963
+ continue;
11964
+ }
11965
+ const rows = runMarkerRemovalTransaction(db, () => {
11966
+ let changed = deleteSummaries(summaryIds);
11967
+ for (const partId of mcPartIds) {
11968
+ changed += deletePart.run(sessionId, partId).changes;
12096
11969
  }
12097
- return ordinalById.get(messageId);
12098
- },
12099
- reason: "stamped-session repair"
12100
- });
12101
- }
12102
- function formatRebaseLogLine(outcome, elapsedMs) {
12103
- const rowsRewritten = outcome.compartmentsRebased + outcome.recompCompartmentsRebased + outcome.notesRebased + outcome.notesCleared + (outcome.priorBoundaryRebased ? 1 : 0) + (outcome.recompPartialRangeRebased ? 1 : 0);
12104
- const unresolved = outcome.compartmentsUnresolved + outcome.recompCompartmentsUnresolved;
12105
- return `INFO store-generation-rebase ${outcome.previousGeneration ?? "unrecorded"}->${outcome.generation} ` + `rows_rewritten=${rowsRewritten} unresolved=${unresolved} derived=${outcome.compartmentsDerived} ` + `index_rows_rebuilt=${outcome.indexRowsRebuilt} drops_discarded=${outcome.queuedReductionsDiscarded} ` + `healed_gaps=${outcome.healedGaps} narrative_gaps=${outcome.narrativeGaps} ` + `ms=${Math.round(elapsedMs)} ` + `(chunk_windows_deleted=${outcome.chunkEmbeddingsDeleted} depth_rows_dropped=${outcome.compressionDepthRowsDropped} ` + `part_tags_folded=${outcome.partTagsFolded} lkg_slots_dropped=${outcome.lkgSlotsDropped} ` + `frozen_part_entries_dropped=${outcome.frozenPartEntriesDropped})`;
12106
- }
12107
- function planPriorBoundary(db, sessionId, plans) {
12108
- const row = db.prepare("SELECT prior_boundary_ordinal FROM session_meta WHERE session_id = ?").get(sessionId);
12109
- const current = typeof row?.prior_boundary_ordinal === "number" ? row.prior_boundary_ordinal : 1;
12110
- if (current <= 1)
12111
- return null;
12112
- const source = plans.find((plan) => plan.status === "ok" && plan.previousEnd === current && plan.end !== current);
12113
- return source ? source.end : null;
12114
- }
12115
- function planRecompPartialRange(db, sessionId, plans) {
12116
- const row = db.prepare("SELECT recomp_partial_range_start AS start, recomp_partial_range_end AS end FROM session_meta WHERE session_id = ?").get(sessionId);
12117
- const start = typeof row?.start === "number" ? row.start : 0;
12118
- const end = typeof row?.end === "number" ? row.end : 0;
12119
- if (start <= 0 && end <= 0)
12120
- return null;
12121
- const startSource = plans.find((plan) => plan.status === "ok" && plan.previousStart === start);
12122
- const endSource = plans.find((plan) => plan.status === "ok" && plan.previousEnd === end);
12123
- if (!startSource || !endSource)
12124
- return null;
12125
- if (startSource.start === start && endSource.end === end)
12126
- return null;
12127
- return { start: startSource.start, end: endSource.end };
12128
- }
12129
- function indexDisagreesWithProjection(db, sessionId, projection) {
12130
- const sourceRows = db.prepare("SELECT message_id, message_ordinal FROM message_history_source WHERE session_id = ?").all(sessionId);
12131
- if (sourceRows.length === 0) {
12132
- return countRows2(db, "SELECT COUNT(*) AS count FROM message_fts_rowid_map WHERE session_id = ?", sessionId) > 0;
11970
+ return changed;
11971
+ });
11972
+ if (rows > 0 || summaryIds.size > 0 || mcPartIds.length > 0) {
11973
+ removedLineages += 1;
11974
+ removedRows += rows;
11975
+ }
12133
11976
  }
12134
- for (const row of sourceRows) {
12135
- if (typeof row.message_id !== "string" || typeof row.message_ordinal !== "number") {
12136
- return true;
11977
+ if (orphanSummaryIds.size > 0) {
11978
+ const rowsToDelete = new Set(orphanSummaryIds);
11979
+ const survivingPartsReferenceDeletion = parsedParts.some((part) => part.tailStartId !== null && rowsToDelete.has(part.tailStartId));
11980
+ const messageFieldReferencesDeletion = [...rowsToDelete].some((id) => messageTailStartIds.has(id));
11981
+ if (survivingPartsReferenceDeletion || messageFieldReferencesDeletion) {
11982
+ retainedLineages += 1;
11983
+ } else {
11984
+ const rows = runMarkerRemovalTransaction(db, () => deleteSummaries(orphanSummaryIds));
11985
+ removedLineages += 1;
11986
+ removedRows += rows;
12137
11987
  }
12138
- if (projection.ordinalById.get(row.message_id) !== row.message_ordinal)
12139
- return true;
12140
11988
  }
12141
- const orphanedMapRows = countRows2(db, `SELECT COUNT(*) AS count FROM message_fts_rowid_map AS m
12142
- WHERE m.session_id = ?
12143
- AND NOT EXISTS (
12144
- SELECT 1 FROM message_history_source AS s
12145
- WHERE s.session_id = m.session_id AND s.message_ordinal = m.message_ordinal
12146
- )`, sessionId);
12147
- return orphanedMapRows > 0;
12148
- }
12149
-
12150
- // src/features/magic-context/compaction-marker.ts
12151
- import { createHash as createHash9 } from "node:crypto";
12152
- import { existsSync as existsSync6 } from "node:fs";
12153
- var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
12154
- var ID_PREFIX_HEX_LENGTH = 12;
12155
- var ID_SUFFIX_LENGTH = 14;
12156
- var ID_PREFIX_MASK = (1n << BigInt(ID_PREFIX_HEX_LENGTH * 4)) - 1n;
12157
- function deterministicBase62(seed, length) {
12158
- let value = BigInt(`0x${createHash9("sha256").update(seed).digest("hex")}`);
12159
- const chars = Array(length);
12160
- for (let index = length - 1;index >= 0; index -= 1) {
12161
- chars[index] = BASE62_CHARS[Number(value % 62n)];
12162
- value /= 62n;
11989
+ if (removedLineages > 0 || retainedLineages > 0) {
11990
+ log2(`[magic-context] compaction-marker: flip-off cleanup for ${sessionId} removed ${removedLineages} lineage(s) (${removedRows} rows), retained ${retainedLineages}`);
12163
11991
  }
12164
- return chars.join("");
11992
+ return {
11993
+ verified: retainedLineages === 0,
11994
+ removedLineages,
11995
+ removedRows,
11996
+ retainedLineages
11997
+ };
12165
11998
  }
12166
- function generateId(prefix, timestampMs, counter, identity) {
12167
- const encoded = BigInt(Math.max(0, Math.floor(timestampMs))) * 0x1000n + counter & ID_PREFIX_MASK;
12168
- const hex = encoded.toString(16).padStart(ID_PREFIX_HEX_LENGTH, "0");
12169
- return `${prefix}_${hex}${deterministicBase62(`${prefix}\x00${identity}`, ID_SUFFIX_LENGTH)}`;
11999
+ function removeCompactionMarker(state) {
12000
+ try {
12001
+ const db = getWritableOpenCodeDb("removal");
12002
+ runMarkerRemovalTransaction(db, () => {
12003
+ db.prepare("DELETE FROM part WHERE id = ?").run(state.summaryPartId);
12004
+ db.prepare("DELETE FROM message WHERE id = ?").run(state.summaryMessageId);
12005
+ db.prepare("DELETE FROM part WHERE id = ?").run(state.compactionPartId);
12006
+ });
12007
+ return true;
12008
+ } catch (error) {
12009
+ log2(`[magic-context] compaction-marker: removal failed: ${error instanceof Error ? error.message : String(error)}`);
12010
+ return false;
12011
+ }
12170
12012
  }
12171
- function generateMessageId(timestampMs, counter = 0n, identity = "") {
12172
- return generateId("msg", timestampMs, counter, identity);
12013
+
12014
+ // src/features/magic-context/compartment-embedding.ts
12015
+ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compartments) {
12016
+ if (compartments.length === 0)
12017
+ return;
12018
+ if (getProjectChunkEmbeddingModelId2(projectPath) === "off")
12019
+ return;
12020
+ const maxInputTokens = getProjectEmbeddingMaxInputTokens2(projectPath);
12021
+ for (const compartment of compartments) {
12022
+ try {
12023
+ const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
12024
+ const mappedText = fromMemory ? fromMemory : buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
12025
+ if (mappedText === null)
12026
+ continue;
12027
+ const canonicalText = mappedText || buildCompartmentSummaryFallbackText(db, compartment.id);
12028
+ if (canonicalText.length === 0)
12029
+ continue;
12030
+ const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
12031
+ if (windows.length === 0)
12032
+ continue;
12033
+ const windowSourceKey = chunkWindowSourceKey(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
12034
+ const currentModelId = getProjectChunkEmbeddingModelId2(projectPath);
12035
+ if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
12036
+ continue;
12037
+ }
12038
+ const result = await embedItemsForProject2(projectPath, windows.map((window) => ({
12039
+ id: `chunk:${compartment.id}:${window.windowIndex}`,
12040
+ text: window.text,
12041
+ contentSha256: contentSha2562(window.text)
12042
+ })), undefined, db, sessionId);
12043
+ if (!result)
12044
+ continue;
12045
+ if (chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
12046
+ continue;
12047
+ }
12048
+ const rows = [];
12049
+ for (const window of windows) {
12050
+ const vector = result.vectors.get(`chunk:${compartment.id}:${window.windowIndex}`);
12051
+ if (!vector)
12052
+ continue;
12053
+ rows.push({
12054
+ compartmentId: compartment.id,
12055
+ sessionId,
12056
+ projectPath,
12057
+ window,
12058
+ modelId: currentModelId,
12059
+ vector
12060
+ });
12061
+ }
12062
+ if (rows.length === windows.length) {
12063
+ replaceCompartmentChunkEmbeddings(db, rows, windowSourceKey);
12064
+ enqueueShadowEmbeddingItems2(projectPath, "chunk", [String(compartment.id)]);
12065
+ }
12066
+ } catch (error) {
12067
+ sessionLog2(sessionId, `compartment chunk embedding failed for compartment ${compartment.id}:`, error);
12068
+ } finally {
12069
+ await new Promise((resolve) => setTimeout(resolve, 0));
12070
+ }
12071
+ }
12173
12072
  }
12174
- function generatePartId(timestampMs, counter = 0n, identity = "") {
12175
- return generateId("prt", timestampMs, counter, identity);
12073
+
12074
+ // src/features/magic-context/store-generation-rebase.ts
12075
+ function emptyOutcome(status, generation, previousGeneration) {
12076
+ return {
12077
+ status,
12078
+ generation,
12079
+ previousGeneration,
12080
+ compartmentsRebased: 0,
12081
+ compartmentsUnresolved: 0,
12082
+ compartmentsDerived: 0,
12083
+ compartmentsResolvedAgain: 0,
12084
+ recompCompartmentsRebased: 0,
12085
+ recompCompartmentsUnresolved: 0,
12086
+ notesRebased: 0,
12087
+ notesCleared: 0,
12088
+ priorBoundaryRebased: false,
12089
+ recompPartialRangeRebased: false,
12090
+ compressionDepthRowsDropped: 0,
12091
+ chunkEmbeddingsDeleted: 0,
12092
+ indexRebuilt: false,
12093
+ indexRowsRebuilt: 0,
12094
+ partTagsFolded: 0,
12095
+ partTagsRekeyed: 0,
12096
+ queuedReductionsDiscarded: 0,
12097
+ lkgSlotsDropped: 0,
12098
+ frozenPartEntriesDropped: 0,
12099
+ healedGaps: 0,
12100
+ narrativeGaps: 0
12101
+ };
12176
12102
  }
12177
- function getOpenCodeDbPath() {
12178
- return resolveOpenCodeDbPath().path;
12103
+ function sessionIsOpenCodeOwned(db, sessionId) {
12104
+ const row = db.prepare("SELECT harness FROM session_meta WHERE session_id = ?").get(sessionId);
12105
+ const harness = row?.harness;
12106
+ if (harness === undefined || harness === null)
12107
+ return true;
12108
+ return harness === "opencode" || harness === "opencode2";
12179
12109
  }
12180
- var cachedWriteDb = null;
12181
- var cachedRemovalDb = null;
12182
- var MARKER_BUSY_TIMEOUT_MS = 250;
12183
- var MARKER_REMOVAL_BUSY_TIMEOUT_MS = 5000;
12184
- function runMarkerRemovalTransaction(db, operation) {
12185
- return withoutSqliteTransformPass2(() => db.transaction(operation).immediate());
12110
+ function generationImpliedByHarness(db, sessionId) {
12111
+ const row = db.prepare("SELECT harness FROM session_meta WHERE session_id = ?").get(sessionId);
12112
+ if (row?.harness === "opencode")
12113
+ return "v1";
12114
+ if (row?.harness === "opencode2")
12115
+ return "v2";
12116
+ return null;
12186
12117
  }
12187
- function runMarkerWriteTransaction(db, site, operation) {
12188
- if (db.inTransaction)
12189
- return db.transaction(operation).immediate();
12190
- const startedAt = performance.now();
12191
- let acquiredAt;
12192
- let workFinishedAt;
12193
- let committed = false;
12194
- try {
12195
- const result = db.transaction(() => {
12196
- acquiredAt = performance.now();
12197
- try {
12198
- return operation();
12199
- } finally {
12200
- workFinishedAt = performance.now();
12201
- }
12202
- }).immediate();
12203
- committed = true;
12204
- return result;
12205
- } finally {
12206
- const finishedAt = performance.now();
12207
- const acquireMs = (acquiredAt ?? finishedAt) - startedAt;
12208
- const holdMs = acquiredAt === undefined ? 0 : finishedAt - acquiredAt;
12209
- const workMs = acquiredAt === undefined ? 0 : (workFinishedAt ?? finishedAt) - acquiredAt;
12210
- const endMs = workFinishedAt === undefined ? 0 : finishedAt - workFinishedAt;
12211
- try {
12212
- log2(`[magic-context] sqlite writer site=${site} db=opencode acquire_ms=${Math.round(acquireMs)} hold_ms=${Math.round(holdMs)} work_ms=${Math.round(workMs)} end_ms=${Math.round(endMs)} outcome=${acquiredAt === undefined ? "not_acquired" : committed ? "committed" : "failed"}`);
12213
- } catch {}
12214
- }
12118
+ function readCoordinateGeneration(db, sessionId) {
12119
+ const row = db.prepare("SELECT coordinate_generation FROM session_meta WHERE session_id = ?").get(sessionId);
12120
+ const value = row?.coordinate_generation;
12121
+ return value === "v1" || value === "v2" ? value : null;
12215
12122
  }
12216
- var REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
12217
- var REQUIRED_PART_COLUMNS = [
12218
- "id",
12219
- "message_id",
12220
- "session_id",
12221
- "time_created",
12222
- "time_updated",
12223
- "data"
12224
- ];
12225
- var cachedSchemaCompatible = null;
12226
- function isOpenCodeSchemaCompatible(db, dbPath) {
12227
- if (cachedSchemaCompatible?.path === dbPath) {
12228
- return cachedSchemaCompatible.compatible;
12229
- }
12123
+ function readCoordinateRebaseNotice(db, sessionId) {
12124
+ const row = db.prepare("SELECT coordinate_rebase_notice FROM session_meta WHERE session_id = ?").get(sessionId);
12125
+ const raw = row?.coordinate_rebase_notice;
12126
+ if (typeof raw !== "string" || raw.length === 0)
12127
+ return null;
12230
12128
  try {
12231
- const messageCols = new Set(db.prepare("PRAGMA table_info(message)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
12232
- const partCols = new Set(db.prepare("PRAGMA table_info(part)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
12233
- const missingMessage = REQUIRED_MESSAGE_COLUMNS.filter((c) => !messageCols.has(c));
12234
- const missingPart = REQUIRED_PART_COLUMNS.filter((c) => !partCols.has(c));
12235
- if (missingMessage.length > 0 || missingPart.length > 0) {
12236
- log2(`[magic-context] compaction-marker: OpenCode DB schema missing required columns ` + `(message: [${missingMessage.join(", ")}], part: [${missingPart.join(", ")}]). ` + `Marker injection disabled for this process. ` + `This usually means OpenCode was updated and magic-context is out of date.`);
12237
- cachedSchemaCompatible = { path: dbPath, compatible: false };
12238
- return false;
12239
- }
12240
- cachedSchemaCompatible = { path: dbPath, compatible: true };
12241
- return true;
12242
- } catch (error) {
12243
- log2(`[magic-context] compaction-marker: schema probe failed: ${error instanceof Error ? error.message : String(error)}. ` + `Marker injection disabled until next process restart.`);
12244
- cachedSchemaCompatible = { path: dbPath, compatible: false };
12245
- return false;
12129
+ const parsed = JSON.parse(raw);
12130
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
12131
+ return null;
12132
+ const record = parsed;
12133
+ if (record.generation !== "v1" && record.generation !== "v2")
12134
+ return null;
12135
+ const count = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
12136
+ const ranges = (value) => Array.isArray(value) ? value.flatMap((entry) => {
12137
+ if (!entry || typeof entry !== "object")
12138
+ return [];
12139
+ const { sequence, start, end } = entry;
12140
+ return typeof sequence === "number" && typeof start === "number" && typeof end === "number" ? [{ sequence, start, end }] : [];
12141
+ }) : [];
12142
+ return {
12143
+ generation: record.generation,
12144
+ previousGeneration: record.previousGeneration === "v1" || record.previousGeneration === "v2" ? record.previousGeneration : null,
12145
+ at: count(record.at),
12146
+ unresolvedCompartments: count(record.unresolvedCompartments),
12147
+ discardedReductions: count(record.discardedReductions),
12148
+ droppedDepthRows: count(record.droppedDepthRows),
12149
+ healedGaps: count(record.healedGaps),
12150
+ narrativeGaps: count(record.narrativeGaps),
12151
+ derivedCompartments: ranges(record.derivedCompartments),
12152
+ unresolvedCompartmentRanges: ranges(record.unresolvedCompartmentRanges),
12153
+ neighbourRecoveryAt: typeof record.neighbourRecoveryAt === "number" && Number.isFinite(record.neighbourRecoveryAt) ? record.neighbourRecoveryAt : null
12154
+ };
12155
+ } catch {
12156
+ return null;
12246
12157
  }
12247
12158
  }
12248
- function getWritableOpenCodeDb(purpose = "publication") {
12249
- if (!harnessOwnsOpenCodeStore2()) {
12250
- throw new Error("OpenCode database is not writable from a Pi-compatible process");
12251
- }
12252
- const resolution = resolveOpenCodeDbPath();
12253
- const dbPath = resolution.path;
12254
- const cached = purpose === "removal" ? cachedRemovalDb : cachedWriteDb;
12255
- if (cached?.path === dbPath) {
12256
- return cached.db;
12159
+ function formatCoordinateRebaseNotice(notice) {
12160
+ const parts = [];
12161
+ if (notice.discardedReductions > 0) {
12162
+ parts.push(`${notice.discardedReductions} queued reduction${notice.discardedReductions === 1 ? " was" : "s were"} discarded because their targets merged in the host's store conversion`);
12257
12163
  }
12258
- if (cached) {
12259
- try {
12260
- closeQuietly(cached.db);
12261
- } catch {}
12164
+ if (notice.derivedCompartments.length > 0) {
12165
+ const count = notice.derivedCompartments.length;
12166
+ parts.push(`${count} compartment${count === 1 ? " was" : "s were"} re-anchored from the compartments around ${count === 1 ? "it" : "them"} (${formatRangeNotes(notice.derivedCompartments)})`);
12262
12167
  }
12263
- if (!existsSync6(dbPath)) {
12264
- throw new Error(`OpenCode database not found at ${dbPath} (source=${resolution.source}; is OpenCode installed?)`);
12168
+ if (notice.unresolvedCompartments > 0) {
12169
+ const listed = notice.unresolvedCompartmentRanges.length > 0 ? ` (${formatRangeNotes(notice.unresolvedCompartmentRanges)})` : "";
12170
+ parts.push(`${notice.unresolvedCompartments} compartment${notice.unresolvedCompartments === 1 ? "" : "s"} could not be re-anchored and are excluded from range recovery${listed}`);
12265
12171
  }
12266
- const db = new Database2(dbPath);
12267
- try {
12268
- assertOpenCodeStoreGeneration(db, "v1", dbPath);
12269
- } catch (error) {
12270
- closeQuietly(db);
12271
- throw error;
12172
+ if (notice.droppedDepthRows > 0) {
12173
+ parts.push(`${notice.droppedDepthRows} compression-depth records were rebuilt from zero`);
12272
12174
  }
12273
- const timeoutMs = purpose === "removal" ? MARKER_REMOVAL_BUSY_TIMEOUT_MS : MARKER_BUSY_TIMEOUT_MS;
12274
- db.exec(`PRAGMA busy_timeout=${timeoutMs}`);
12275
- db.exec("PRAGMA journal_mode=WAL");
12276
- if (purpose === "removal")
12277
- cachedRemovalDb = { path: dbPath, db };
12278
- else
12279
- cachedWriteDb = { path: dbPath, db };
12280
- return db;
12281
- }
12282
- function getNonSummaryMessageSortKey(sessionId, messageId) {
12283
- const db = getWritableOpenCodeDb();
12284
- const row = db.prepare(`SELECT time_created, id
12285
- FROM message
12286
- WHERE session_id = ?
12287
- AND id = ?
12288
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
12289
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
12290
- LIMIT 1`).get(sessionId, messageId);
12291
- if (typeof row?.time_created !== "number" || typeof row.id !== "string") {
12292
- return null;
12175
+ if (notice.healedGaps > 0) {
12176
+ parts.push(`${notice.healedGaps} non-narrative compartment gap${notice.healedGaps === 1 ? " was" : "s were"} healed`);
12293
12177
  }
12294
- return { id: row.id, timeCreated: row.time_created };
12295
- }
12296
- function findBoundaryUserMessage(sessionId, endMessageId) {
12297
- const db = getWritableOpenCodeDb();
12298
- const target = getNonSummaryMessageSortKey(sessionId, endMessageId);
12299
- if (!target)
12300
- return null;
12301
- const boundary = db.prepare(`SELECT id, time_created, data
12302
- FROM message
12303
- WHERE session_id = ?
12304
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
12305
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
12306
- AND COALESCE(json_extract(data, '$.role'), '') = 'user'
12307
- AND (time_created, id) <= (?, ?)
12308
- AND NOT (
12309
- EXISTS (SELECT 1 FROM part p
12310
- WHERE likelihood(p.message_id = message.id, 0.000001) AND +p.session_id = message.session_id
12311
- AND COALESCE(json_extract(p.data, '$.type'), '') <> 'compaction')
12312
- AND NOT EXISTS (SELECT 1 FROM part p
12313
- WHERE likelihood(p.message_id = message.id, 0.000001) AND +p.session_id = message.session_id
12314
- AND COALESCE(json_extract(p.data, '$.type'), '') <> 'compaction'
12315
- AND COALESCE(json_extract(p.data, '$.synthetic'), 0) <> 1
12316
- AND COALESCE(json_extract(p.data, '$.syntheticTodoMarker'), 0) <> 1)
12317
- )
12318
- ORDER BY time_created DESC, id DESC
12319
- LIMIT 1`).get(sessionId, target.timeCreated, target.id);
12320
- if (typeof boundary?.id !== "string" || typeof boundary.time_created !== "number") {
12321
- return null;
12178
+ if (notice.narrativeGaps > 0) {
12179
+ parts.push(`${notice.narrativeGaps} narrative compartment gap${notice.narrativeGaps === 1 ? " remains" : "s remain"} for review`);
12322
12180
  }
12323
- return { id: boundary.id, timeCreated: boundary.time_created };
12181
+ return parts.length === 0 ? null : parts.join("; ");
12324
12182
  }
12325
- function compareOpenCodeMessagesByCanonicalOrder(sessionId, leftMessageId, rightMessageId) {
12326
- const left = getNonSummaryMessageSortKey(sessionId, leftMessageId);
12327
- const right = getNonSummaryMessageSortKey(sessionId, rightMessageId);
12328
- if (!left || !right)
12329
- return null;
12330
- if (left.timeCreated < right.timeCreated)
12331
- return -1;
12332
- if (left.timeCreated > right.timeCreated)
12333
- return 1;
12334
- if (left.id < right.id)
12335
- return -1;
12336
- if (left.id > right.id)
12337
- return 1;
12338
- return 0;
12183
+ function formatRangeNotes(notes) {
12184
+ return notes.map((note) => `messages ${note.start}-${note.end}`).join(", ");
12339
12185
  }
12340
- function isOpenCodeGapHistorianAbsent(sessionId, endId, nextId) {
12341
- const end = getNonSummaryMessageSortKey(sessionId, endId);
12342
- const next = getNonSummaryMessageSortKey(sessionId, nextId);
12343
- if (!end || !next || end.timeCreated > next.timeCreated || end.timeCreated === next.timeCreated && end.id >= next.id)
12186
+ function isCompartmentCoordinateRow(row) {
12187
+ if (row === null || typeof row !== "object")
12344
12188
  return false;
12345
- const row = getWritableOpenCodeDb().prepare(`SELECT 1 FROM message m
12346
- WHERE m.session_id=?
12347
- AND (m.time_created, m.id) > (?, ?)
12348
- AND (m.time_created, m.id) < (?, ?)
12349
- AND NOT (COALESCE(json_type(m.data,'$.summary'),'')='true' AND COALESCE(json_extract(m.data,'$.finish'),'')='stop')
12350
- AND NOT (
12351
- EXISTS (SELECT 1 FROM part p WHERE likelihood(p.message_id=m.id, 0.000001) AND +p.session_id=m.session_id AND COALESCE(json_extract(p.data,'$.type'),'')<>'compaction')
12352
- AND NOT EXISTS (SELECT 1 FROM part p WHERE likelihood(p.message_id=m.id, 0.000001) AND +p.session_id=m.session_id
12353
- AND COALESCE(json_extract(p.data,'$.type'),'')<>'compaction'
12354
- AND COALESCE(json_type(p.data,'$.synthetic'),'')<>'true'
12355
- AND COALESCE(json_type(p.data,'$.syntheticTodoMarker'),'')<>'true')
12356
- ) LIMIT 1`).get(sessionId, end.timeCreated, end.id, next.timeCreated, next.id);
12357
- return !row;
12189
+ const candidate = row;
12190
+ return typeof candidate.id === "number" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number";
12358
12191
  }
12359
- function getOpenCodeMessageById(sessionId, messageId) {
12360
- const db = getWritableOpenCodeDb();
12361
- const row = db.prepare(`SELECT id FROM message WHERE session_id = ? AND id = ? LIMIT 1`).get(sessionId, messageId);
12362
- return row ?? null;
12192
+ function emptyProjection() {
12193
+ return {
12194
+ ordinalById: new Map,
12195
+ partCountById: new Map,
12196
+ nonNarrativeOrdinals: new Set,
12197
+ messageCount: 0,
12198
+ indexSources: []
12199
+ };
12363
12200
  }
12364
- function removeLegacyMarkerLineageRows(db, args) {
12365
- const legacySummaries = db.prepare(`SELECT m.id
12366
- FROM message m
12367
- WHERE m.session_id = ?
12368
- AND m.id <> ?
12369
- AND COALESCE(json_extract(m.data, '$.summary'), 0) = 1
12370
- AND COALESCE(json_extract(m.data, '$.finish'), '') = 'stop'
12371
- AND COALESCE(json_extract(m.data, '$.parentID'), '') = ?
12372
- AND EXISTS (
12373
- SELECT 1
12374
- FROM part p
12375
- WHERE +p.session_id = m.session_id
12376
- AND p.message_id = m.id
12377
- AND COALESCE(json_extract(p.data, '$.type'), '') = 'text'
12378
- AND COALESCE(json_extract(p.data, '$.text'), '') = ?
12379
- )`).all(args.sessionId, args.summaryMessageId, args.boundaryMessageId, args.summaryText);
12380
- const legacySummaryIds = legacySummaries.flatMap((row) => typeof row.id === "string" ? [row.id] : []);
12381
- if (legacySummaryIds.length === 0)
12382
- return;
12383
- const deleteSummaryParts = db.prepare("DELETE FROM part WHERE +session_id = ? AND message_id = ?");
12384
- const deleteSummary = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
12385
- for (const summaryMessageId of legacySummaryIds) {
12386
- deleteSummaryParts.run(args.sessionId, summaryMessageId);
12387
- deleteSummary.run(args.sessionId, summaryMessageId);
12201
+ function addToProjection(projection, messages, withIndexSources) {
12202
+ for (const message of messages) {
12203
+ projection.ordinalById.set(message.id, message.ordinal);
12204
+ projection.partCountById.set(message.id, Array.isArray(message.parts) ? message.parts.length : 0);
12205
+ if (isStrictGapHealingMessage2(message))
12206
+ projection.nonNarrativeOrdinals.add(message.ordinal);
12207
+ if (withIndexSources)
12208
+ projection.indexSources.push(toMessageIndexSource2(message));
12388
12209
  }
12389
- db.prepare(`DELETE FROM part
12390
- WHERE +session_id = ?
12391
- AND message_id = ?
12392
- AND id <> ?
12393
- AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'
12394
- AND COALESCE(json_extract(data, '$.auto'), 0) = 1`).run(args.sessionId, args.boundaryMessageId, args.compactionPartId);
12210
+ projection.messageCount += messages.length;
12395
12211
  }
12396
- function injectCompactionMarker(args) {
12397
- const db = getWritableOpenCodeDb();
12398
- if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath())) {
12399
- return null;
12400
- }
12401
- const boundary = args.resolvedBoundary ?? findBoundaryUserMessage(args.sessionId, args.endMessageId);
12402
- if (!boundary) {
12403
- log2(`[magic-context] compaction-marker: no user message found at or before endMessageId ${args.endMessageId} (ordinal ${args.endOrdinal})`);
12404
- return null;
12405
- }
12406
- const boundaryTime = boundary.timeCreated;
12407
- const markerIdentity = `${args.sessionId}\x00${args.endMessageId}`;
12408
- const summaryMsgId = generateMessageId(boundaryTime + 1, 1n, `${markerIdentity}\x00summary-message`);
12409
- const compactionPartId = generatePartId(boundaryTime, 1n, `${markerIdentity}\x00compaction-part`);
12410
- const summaryPartId = generatePartId(boundaryTime + 1, 2n, `${markerIdentity}\x00summary-part`);
12411
- const summaryMsgData = JSON.stringify({
12412
- role: "assistant",
12413
- parentID: boundary.id,
12414
- summary: true,
12415
- finish: "stop",
12416
- mode: "compaction",
12417
- agent: "compaction",
12418
- path: { cwd: args.directory, root: args.directory },
12419
- cost: 0,
12420
- tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
12421
- modelID: "magic-context",
12422
- providerID: "magic-context",
12423
- time: { created: boundaryTime + 1, completed: boundaryTime + 1 }
12424
- });
12425
- try {
12426
- runMarkerWriteTransaction(db, "compaction-marker-inject", () => {
12427
- removeLegacyMarkerLineageRows(db, {
12428
- sessionId: args.sessionId,
12429
- boundaryMessageId: boundary.id,
12430
- summaryText: args.summaryText,
12431
- summaryMessageId: summaryMsgId,
12432
- compactionPartId
12433
- });
12434
- db.prepare(`INSERT INTO part (id, message_id, session_id, time_created, time_updated, data)
12435
- VALUES (?, ?, ?, ?, ?, ?)
12436
- ON CONFLICT(id) DO UPDATE SET
12437
- message_id = excluded.message_id,
12438
- session_id = excluded.session_id,
12439
- time_created = excluded.time_created,
12440
- time_updated = excluded.time_updated,
12441
- data = excluded.data`).run(compactionPartId, boundary.id, args.sessionId, boundaryTime, boundaryTime, '{"type":"compaction","auto":true}');
12442
- db.prepare(`INSERT INTO message (id, session_id, time_created, time_updated, data)
12443
- VALUES (?, ?, ?, ?, ?)
12444
- ON CONFLICT(id) DO UPDATE SET
12445
- session_id = excluded.session_id,
12446
- time_created = excluded.time_created,
12447
- time_updated = excluded.time_updated,
12448
- data = excluded.data`).run(summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, summaryMsgData);
12449
- noteRawSessionSummaryRowWritten2(args.sessionId, summaryMsgId);
12450
- db.prepare(`INSERT INTO part (id, message_id, session_id, time_created, time_updated, data)
12451
- VALUES (?, ?, ?, ?, ?, ?)
12452
- ON CONFLICT(id) DO UPDATE SET
12453
- message_id = excluded.message_id,
12454
- session_id = excluded.session_id,
12455
- time_created = excluded.time_created,
12456
- time_updated = excluded.time_updated,
12457
- data = excluded.data`).run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
12458
- });
12459
- log2(`[magic-context] compaction-marker: injected boundary at user msg ${boundary.id} (ordinal ~${args.endOrdinal}), summary msg ${summaryMsgId}`);
12460
- return {
12461
- boundaryMessageId: boundary.id,
12462
- summaryMessageId: summaryMsgId,
12463
- compactionPartId,
12464
- summaryPartId
12465
- };
12466
- } catch (error) {
12467
- log2(`[magic-context] compaction-marker: injection failed: ${error instanceof Error ? error.message : String(error)}`);
12468
- return null;
12212
+ function readProjectionPages(args) {
12213
+ if (args.readMessagePages)
12214
+ return args.readMessagePages(args.sessionId);
12215
+ return [args.readMessages(args.sessionId)];
12216
+ }
12217
+ function* buildProjectionSteps(args, withIndexSources) {
12218
+ const projection = emptyProjection();
12219
+ for (const page of readProjectionPages(args)) {
12220
+ addToProjection(projection, page, withIndexSources);
12221
+ yield;
12469
12222
  }
12223
+ return projection;
12470
12224
  }
12471
- function replaceCompactionMarker(existing, args) {
12472
- let connection;
12473
- let entered = false;
12474
- let readyToCommit = false;
12475
- try {
12476
- const db = getWritableOpenCodeDb();
12477
- connection = db;
12478
- const marker = runMarkerWriteTransaction(db, "compaction-marker-replace", () => {
12479
- entered = true;
12480
- if (existing) {
12481
- db.prepare("DELETE FROM part WHERE id = ?").run(existing.summaryPartId);
12482
- db.prepare("DELETE FROM message WHERE id = ?").run(existing.summaryMessageId);
12483
- db.prepare("DELETE FROM part WHERE id = ?").run(existing.compactionPartId);
12484
- }
12485
- const replacement = injectCompactionMarker(args);
12486
- if (!replacement) {
12487
- throw new Error(`failed to inject replacement marker at ordinal ${args.endOrdinal}`);
12488
- }
12489
- readyToCommit = true;
12490
- return replacement;
12491
- });
12492
- return { kind: "committed", marker };
12493
- } catch (error) {
12494
- log2(`[magic-context] compaction-marker: atomic replacement failed: ${error instanceof Error ? error.message : String(error)}`);
12495
- const definitelyNoCut = !entered || !readyToCommit && connection?.inTransaction === false;
12225
+ var INDEX_REBUILD_CHUNK = 2000;
12226
+ function messageIdFromAnchorBlockId(anchorBlockId) {
12227
+ const hash = anchorBlockId.lastIndexOf("#");
12228
+ return hash > 0 ? anchorBlockId.slice(0, hash) : anchorBlockId;
12229
+ }
12230
+ function readCompartmentRows(db, table, sessionId) {
12231
+ return db.prepare(`SELECT id, sequence, start_message, end_message, start_message_id, end_message_id, rebase_status
12232
+ FROM ${table} WHERE session_id = ? ORDER BY sequence ASC`).all(sessionId).filter(isCompartmentCoordinateRow);
12233
+ }
12234
+ function resolveAnchor(messageId, resolveOrdinal) {
12235
+ return messageId && messageId.length > 0 ? resolveOrdinal(messageId) : undefined;
12236
+ }
12237
+ function planCompartments(rows, table, projection) {
12238
+ const resolveOrdinal = (messageId) => projection.ordinalById.get(messageId);
12239
+ return recoverFromNeighbours(rows, table, rows.map((row) => ({
12240
+ start: resolveAnchor(row.start_message_id, resolveOrdinal),
12241
+ end: resolveAnchor(row.end_message_id, resolveOrdinal)
12242
+ })));
12243
+ }
12244
+ function recoverFromNeighbours(rows, table, known) {
12245
+ const plans = rows.map((row, index) => {
12246
+ const own = known[index] ?? { start: undefined, end: undefined };
12247
+ const previousEnd = index === 0 ? 0 : known[index - 1]?.end;
12248
+ const nextStart = index === rows.length - 1 ? undefined : known[index + 1]?.start;
12249
+ const start = own.start ?? (previousEnd === undefined ? undefined : previousEnd + 1);
12250
+ const end = own.end ?? (nextStart === undefined ? undefined : nextStart - 1);
12251
+ const base = {
12252
+ table,
12253
+ id: row.id,
12254
+ sequence: row.sequence,
12255
+ previousStart: row.start_message,
12256
+ previousEnd: row.end_message,
12257
+ previousStatus: row.rebase_status === "unresolved" ? "unresolved" : "ok"
12258
+ };
12259
+ if (start !== undefined && end !== undefined && start <= end) {
12260
+ return {
12261
+ ...base,
12262
+ start,
12263
+ end,
12264
+ status: "ok",
12265
+ derived: own.start === undefined || own.end === undefined
12266
+ };
12267
+ }
12496
12268
  return {
12497
- kind: definitelyNoCut ? "definitely-no-cut" : "uncertain",
12498
- error: error instanceof Error ? error : new Error(String(error))
12269
+ ...base,
12270
+ start: start ?? row.start_message,
12271
+ end: end ?? row.end_message,
12272
+ status: "unresolved",
12273
+ derived: false
12499
12274
  };
12275
+ });
12276
+ for (let index = 0;index < plans.length; index += 1) {
12277
+ const plan = plans[index];
12278
+ if (plan?.status !== "unresolved")
12279
+ continue;
12280
+ const previous = plans[index - 1];
12281
+ const next = plans[index + 1];
12282
+ if (previous?.status === "ok" && plan.start <= previous.end) {
12283
+ plan.start = previous.end + 1;
12284
+ }
12285
+ if (next?.status === "ok" && plan.end >= next.start) {
12286
+ plan.end = next.start - 1;
12287
+ }
12500
12288
  }
12289
+ return plans;
12501
12290
  }
12502
- function listSessionCompactionMarkers(sessionId) {
12503
- const db = getWritableOpenCodeDb();
12504
- const summaryRows = db.prepare(`SELECT id, json_extract(data, '$.parentID') AS boundary_message_id
12505
- FROM message
12506
- WHERE session_id = ?
12507
- AND COALESCE(json_extract(data, '$.summary'), 0) = 1
12508
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop'
12509
- AND COALESCE(json_extract(data, '$.providerID'), '') = 'magic-context'
12510
- ORDER BY time_created ASC, id ASC`).all(sessionId);
12511
- const summaryIdsByBoundary = new Map;
12512
- for (const row of summaryRows) {
12513
- if (typeof row.id !== "string" || typeof row.boundary_message_id !== "string")
12291
+ function healNonNarrativeCompartmentGaps(plans, projection) {
12292
+ let healed = 0;
12293
+ let narrative = 0;
12294
+ for (let index = 1;index < plans.length; index += 1) {
12295
+ const previous = plans[index - 1];
12296
+ const current = plans[index];
12297
+ if (!previous || !current || previous.status !== "ok" || current.status !== "ok")
12514
12298
  continue;
12515
- const summaryIds = summaryIdsByBoundary.get(row.boundary_message_id) ?? [];
12516
- summaryIds.push(row.id);
12517
- summaryIdsByBoundary.set(row.boundary_message_id, summaryIds);
12299
+ const gapStart = previous.end + 1;
12300
+ const gapEnd = current.start - 1;
12301
+ if (gapEnd < gapStart)
12302
+ continue;
12303
+ let safeToHeal = true;
12304
+ for (let ordinal = gapStart;ordinal <= gapEnd; ordinal += 1) {
12305
+ if (!projection.nonNarrativeOrdinals.has(ordinal)) {
12306
+ safeToHeal = false;
12307
+ break;
12308
+ }
12309
+ }
12310
+ if (safeToHeal) {
12311
+ previous.end = gapEnd;
12312
+ healed += 1;
12313
+ } else {
12314
+ narrative += 1;
12315
+ }
12518
12316
  }
12519
- const boundaryIds = [...summaryIdsByBoundary.keys()];
12520
- const markers = [];
12521
- const chunkSize = 800;
12522
- for (let offset = 0;offset < boundaryIds.length; offset += chunkSize) {
12523
- const boundaryChunk = boundaryIds.slice(offset, offset + chunkSize);
12524
- const placeholders = boundaryChunk.map(() => "?").join(", ");
12525
- const partRows = db.prepare(`SELECT id, message_id, time_created
12526
- FROM part
12527
- WHERE +session_id = ?
12528
- AND likelihood(message_id IN (${placeholders}), 0.000001)
12529
- AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'
12530
- ORDER BY time_created ASC, id ASC`).all(sessionId, ...boundaryChunk);
12531
- for (const row of partRows) {
12532
- if (typeof row.id !== "string" || typeof row.message_id !== "string" || typeof row.time_created !== "number") {
12317
+ return { healed, narrative };
12318
+ }
12319
+ function compartmentPlanChanges(plan) {
12320
+ return plan.status !== plan.previousStatus || plan.start !== plan.previousStart || plan.end !== plan.previousEnd;
12321
+ }
12322
+ function rangeNotes(plans, predicate) {
12323
+ return plans.filter((plan) => plan.table === "compartments" && predicate(plan)).map((plan) => ({ sequence: plan.sequence, start: plan.start, end: plan.end }));
12324
+ }
12325
+ function planNotes(db, sessionId, projection) {
12326
+ const rows = db.prepare("SELECT id, anchor_ordinal, anchor_block_id FROM notes WHERE session_id = ? AND anchor_ordinal IS NOT NULL").all(sessionId);
12327
+ return rows.flatMap((row) => {
12328
+ if (typeof row.id !== "number")
12329
+ return [];
12330
+ const previousOrdinal = typeof row.anchor_ordinal === "number" ? row.anchor_ordinal : null;
12331
+ const anchorBlockId = typeof row.anchor_block_id === "string" ? row.anchor_block_id : "";
12332
+ if (anchorBlockId.length === 0) {
12333
+ return [{ id: row.id, ordinal: null, previousOrdinal }];
12334
+ }
12335
+ const ordinal = projection.ordinalById.get(messageIdFromAnchorBlockId(anchorBlockId));
12336
+ return [{ id: row.id, ordinal: ordinal ?? null, previousOrdinal }];
12337
+ });
12338
+ }
12339
+ function countRows2(db, sql, ...params) {
12340
+ const row = db.prepare(sql).get(...params);
12341
+ return typeof row?.count === "number" ? row.count : 0;
12342
+ }
12343
+ function stampGeneration(db, sessionId, generation, notice) {
12344
+ ensureSessionMetaRow(db, sessionId);
12345
+ if (notice === null) {
12346
+ db.prepare("UPDATE session_meta SET coordinate_generation = ? WHERE session_id = ?").run(generation, sessionId);
12347
+ return;
12348
+ }
12349
+ db.prepare("UPDATE session_meta SET coordinate_generation = ?, coordinate_rebase_notice = ? WHERE session_id = ?").run(generation, JSON.stringify(notice), sessionId);
12350
+ }
12351
+ function pruneShrunkPartEntries(db, sessionId, column, shrunk) {
12352
+ if (shrunk.length === 0)
12353
+ return 0;
12354
+ const row = db.prepare(`SELECT ${column} AS value FROM session_meta WHERE session_id = ?`).get(sessionId);
12355
+ const raw = row?.value;
12356
+ if (typeof raw !== "string" || raw.length === 0)
12357
+ return 0;
12358
+ let parsed;
12359
+ try {
12360
+ parsed = JSON.parse(raw);
12361
+ } catch {
12362
+ return 0;
12363
+ }
12364
+ const partCountByMessage = new Map(shrunk.map((entry) => [entry.messageId, entry.partCount]));
12365
+ const isStale = (candidate) => {
12366
+ const marker = candidate.lastIndexOf(":p");
12367
+ if (marker < 0)
12368
+ return false;
12369
+ const suffix = candidate.slice(marker + 2);
12370
+ if (!/^\d+$/.test(suffix))
12371
+ return false;
12372
+ const partCount = partCountByMessage.get(candidate.slice(0, marker));
12373
+ return partCount !== undefined && Number.parseInt(suffix, 10) >= partCount;
12374
+ };
12375
+ let dropped = 0;
12376
+ const pruneArray = (values) => values.filter((value) => {
12377
+ if (typeof value === "string" && isStale(value)) {
12378
+ dropped += 1;
12379
+ return false;
12380
+ }
12381
+ return true;
12382
+ });
12383
+ let next;
12384
+ if (Array.isArray(parsed)) {
12385
+ next = pruneArray(parsed);
12386
+ } else if (parsed && typeof parsed === "object") {
12387
+ const source = parsed;
12388
+ const result = {};
12389
+ for (const [key, value] of Object.entries(source)) {
12390
+ if (isStale(key)) {
12391
+ dropped += 1;
12533
12392
  continue;
12534
12393
  }
12535
- const summaryMessageIds = summaryIdsByBoundary.get(row.message_id);
12536
- if (!summaryMessageIds)
12537
- continue;
12538
- markers.push({
12539
- compactionPartId: row.id,
12540
- boundaryMessageId: row.message_id,
12541
- summaryMessageIds: [...summaryMessageIds],
12542
- timeCreated: row.time_created
12543
- });
12394
+ result[key] = Array.isArray(value) ? pruneArray(value) : value;
12544
12395
  }
12396
+ next = result;
12397
+ } else {
12398
+ return 0;
12399
+ }
12400
+ if (dropped === 0)
12401
+ return 0;
12402
+ db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ?`).run(JSON.stringify(next), sessionId);
12403
+ return dropped;
12404
+ }
12405
+ var REBASE_SLICE_MS = 20;
12406
+ var rebasesInFlight = new WeakMap;
12407
+ async function rebaseSessionCoordinatesAsync(args) {
12408
+ let sessions = rebasesInFlight.get(args.db);
12409
+ if (!sessions) {
12410
+ sessions = new Map;
12411
+ rebasesInFlight.set(args.db, sessions);
12412
+ }
12413
+ const earlier = sessions.get(args.sessionId);
12414
+ if (earlier)
12415
+ await earlier.catch(() => {
12416
+ return;
12417
+ });
12418
+ const run = runSliced(args);
12419
+ sessions.set(args.sessionId, run);
12420
+ try {
12421
+ return await run;
12422
+ } finally {
12423
+ if (sessions.get(args.sessionId) === run)
12424
+ sessions.delete(args.sessionId);
12545
12425
  }
12546
- markers.sort((left, right) => left.timeCreated - right.timeCreated || left.compactionPartId.localeCompare(right.compactionPartId));
12547
- return markers.map(({ timeCreated: _, ...marker }) => marker);
12548
12426
  }
12549
- function removeForeignCompactionMarker(sessionId, marker, protectedSummaryMessageId) {
12427
+ async function runSliced(args) {
12428
+ const steps = rebaseSteps(args);
12429
+ let finished = false;
12550
12430
  try {
12551
- const db = getWritableOpenCodeDb("removal");
12552
- runMarkerRemovalTransaction(db, () => {
12553
- const deletePartsOfMessage = db.prepare("DELETE FROM part WHERE +session_id = ? AND message_id = ?");
12554
- const deleteMessage = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
12555
- for (const summaryMessageId of marker.summaryMessageIds) {
12556
- if (summaryMessageId === protectedSummaryMessageId)
12557
- continue;
12558
- deletePartsOfMessage.run(sessionId, summaryMessageId);
12559
- deleteMessage.run(sessionId, summaryMessageId);
12431
+ let sliceStartedAt = performance.now();
12432
+ for (;; ) {
12433
+ const step = steps.next();
12434
+ if (step.done) {
12435
+ finished = true;
12436
+ return step.value;
12560
12437
  }
12561
- db.prepare("DELETE FROM part WHERE session_id = ? AND id = ?").run(sessionId, marker.compactionPartId);
12562
- });
12563
- return true;
12564
- } catch (error) {
12565
- log2(`[magic-context] compaction-marker: foreign-marker removal failed (${sessionId}, part ${marker.compactionPartId}): ${error instanceof Error ? error.message : String(error)}`);
12566
- return false;
12438
+ if (performance.now() - sliceStartedAt >= REBASE_SLICE_MS) {
12439
+ await new Promise((resolve) => setImmediate(resolve));
12440
+ sliceStartedAt = performance.now();
12441
+ }
12442
+ }
12443
+ } finally {
12444
+ if (!finished)
12445
+ steps.return(emptyOutcome("unchanged", args.generation, null));
12567
12446
  }
12568
12447
  }
12569
- function dataReferencesTailStart(data) {
12570
- if (typeof data !== "object" || data === null)
12571
- return null;
12572
- const record = data;
12573
- if (typeof record.tail_start_id === "string" && record.tail_start_id.length > 0) {
12574
- return record.tail_start_id;
12448
+ function* rebaseSteps(args) {
12449
+ const { db, sessionId, generation } = args;
12450
+ const startedAt = performance.now();
12451
+ if (!sessionIsOpenCodeOwned(db, sessionId)) {
12452
+ return emptyOutcome("unchanged", generation, null);
12575
12453
  }
12576
- const nested = record.compaction;
12577
- if (typeof nested === "object" && nested !== null) {
12578
- const nestedTail = nested.tail_start_id;
12579
- if (typeof nestedTail === "string" && nestedTail.length > 0)
12580
- return nestedTail;
12454
+ const previousGeneration = readCoordinateGeneration(db, sessionId);
12455
+ if (previousGeneration === generation) {
12456
+ const outcome = emptyOutcome("unchanged", generation, previousGeneration);
12457
+ const repair = repairStampedSessionOnce(db, sessionId, args);
12458
+ if (repair !== null && repair.rowsRewritten > 0) {
12459
+ outcome.status = "repaired";
12460
+ outcome.compartmentsDerived = repair.derived.length;
12461
+ outcome.compartmentsUnresolved = repair.unresolved.length;
12462
+ }
12463
+ return outcome;
12581
12464
  }
12582
- return null;
12583
- }
12584
- function isMcCanonicalCompactionPartData(data) {
12585
- if (typeof data !== "object" || data === null || Array.isArray(data))
12586
- return false;
12587
- const record = data;
12588
- const keys = Object.keys(record).sort();
12589
- return keys.length === 2 && keys[0] === "auto" && keys[1] === "type" && record.type === "compaction" && record.auto === true;
12590
- }
12591
- function removeMcOwnedCompactionMarkers(sessionId, summaryText) {
12592
- const db = getWritableOpenCodeDb("removal");
12593
- if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath())) {
12594
- return {
12595
- verified: false,
12596
- removedLineages: 0,
12597
- removedRows: 0,
12598
- retainedLineages: 0
12599
- };
12465
+ const impliedGeneration = previousGeneration ?? generationImpliedByHarness(db, sessionId) ?? generation;
12466
+ if (impliedGeneration === generation) {
12467
+ stampGeneration(db, sessionId, generation, null);
12468
+ return emptyOutcome("stamped", generation, previousGeneration);
12600
12469
  }
12601
- const canonicalSummaries = db.prepare(`SELECT id, COALESCE(json_extract(data, '$.parentID'), '') AS parent_id
12602
- FROM message
12603
- WHERE session_id = ?
12604
- AND COALESCE(json_extract(data, '$.summary'), 0) = 1
12605
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop'
12606
- AND COALESCE(json_extract(data, '$.providerID'), '') = 'magic-context'`).all(sessionId);
12607
- const legacySummaries = db.prepare(`SELECT m.id, COALESCE(json_extract(m.data, '$.parentID'), '') AS parent_id
12608
- FROM message m
12609
- WHERE m.session_id = ?
12610
- AND COALESCE(json_extract(m.data, '$.summary'), 0) = 1
12611
- AND COALESCE(json_extract(m.data, '$.finish'), '') = 'stop'
12612
- AND COALESCE(json_extract(m.data, '$.providerID'), '') <> 'magic-context'
12613
- AND EXISTS (
12614
- SELECT 1
12615
- FROM part p
12616
- WHERE +p.session_id = m.session_id
12617
- AND p.message_id = m.id
12618
- AND COALESCE(json_extract(p.data, '$.type'), '') = 'text'
12619
- AND COALESCE(json_extract(p.data, '$.text'), '') = ?
12620
- )`).all(sessionId, summaryText);
12621
- const summariesByBoundary = new Map;
12622
- const orphanSummaryIds = new Set;
12623
- for (const row of [...canonicalSummaries, ...legacySummaries]) {
12624
- if (typeof row.id !== "string")
12470
+ const projection = yield* buildProjectionSteps(args, true);
12471
+ const outcome = emptyOutcome("rebased", generation, impliedGeneration);
12472
+ const compartmentRows = readCompartmentRows(db, "compartments", sessionId);
12473
+ const recompRows = readCompartmentRows(db, "recomp_compartments", sessionId);
12474
+ const compartmentPlans = planCompartments(compartmentRows, "compartments", projection);
12475
+ const recompPlans = planCompartments(recompRows, "recomp_compartments", projection);
12476
+ const compartmentGapResult = healNonNarrativeCompartmentGaps(compartmentPlans, projection);
12477
+ const recompGapResult = healNonNarrativeCompartmentGaps(recompPlans, projection);
12478
+ const notePlans = planNotes(db, sessionId, projection);
12479
+ const shrunkMessages = [];
12480
+ const taggedMessageIds = new Set(db.prepare("SELECT message_id FROM tags WHERE session_id = ? AND type = 'message'").all(sessionId).flatMap((row) => typeof row.message_id === "string" ? [row.message_id] : []));
12481
+ const highestTaggedPartIndex = new Map;
12482
+ for (const contentId of taggedMessageIds) {
12483
+ const marker = contentId.lastIndexOf(":p");
12484
+ if (marker <= 0)
12625
12485
  continue;
12626
- if (typeof row.parent_id === "string" && row.parent_id.length > 0) {
12627
- const set = summariesByBoundary.get(row.parent_id) ?? new Set;
12628
- set.add(row.id);
12629
- summariesByBoundary.set(row.parent_id, set);
12630
- } else {
12631
- orphanSummaryIds.add(row.id);
12632
- }
12486
+ const suffix = contentId.slice(marker + 2);
12487
+ if (!/^\d+$/.test(suffix))
12488
+ continue;
12489
+ const messageId = contentId.slice(0, marker);
12490
+ const partIndex = Number.parseInt(suffix, 10);
12491
+ highestTaggedPartIndex.set(messageId, Math.max(highestTaggedPartIndex.get(messageId) ?? 0, partIndex));
12633
12492
  }
12634
- const compactionParts = db.prepare(`SELECT id, message_id, data
12635
- FROM part
12636
- WHERE session_id = ?
12637
- AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'`).all(sessionId);
12638
- const parsedParts = [];
12639
- for (const part of compactionParts) {
12640
- if (typeof part.id !== "string" || typeof part.message_id !== "string")
12493
+ for (const [messageId, highestIndex] of highestTaggedPartIndex) {
12494
+ const partCount = projection.partCountById.get(messageId);
12495
+ if (partCount === undefined || highestIndex < partCount)
12641
12496
  continue;
12642
- let data;
12643
- try {
12644
- data = typeof part.data === "string" ? JSON.parse(part.data) : part.data;
12645
- } catch {
12646
- data = null;
12497
+ shrunkMessages.push({ messageId, partCount });
12498
+ }
12499
+ const indexNeedsRebuild = indexDisagreesWithProjection(db, sessionId, projection);
12500
+ const chunkEmbeddingCount = countRows2(db, "SELECT COUNT(*) AS count FROM compartment_chunk_embeddings WHERE session_id = ?", sessionId);
12501
+ const depthRowCount = countRows2(db, "SELECT COUNT(*) AS count FROM compression_depth WHERE session_id = ?", sessionId);
12502
+ const lkgSlotCount = countRows2(db, "SELECT COUNT(*) AS count FROM lkg_slots WHERE session_id = ?", sessionId);
12503
+ const boundaryPlan = planPriorBoundary(db, sessionId, compartmentPlans);
12504
+ const partialRangePlan = planRecompPartialRange(db, sessionId, recompPlans);
12505
+ outcome.healedGaps = compartmentGapResult.healed + recompGapResult.healed;
12506
+ outcome.narrativeGaps = compartmentGapResult.narrative + recompGapResult.narrative;
12507
+ const movedCompartments = compartmentPlans.filter(compartmentPlanChanges);
12508
+ const movedRecomp = recompPlans.filter(compartmentPlanChanges);
12509
+ const movedNotes = notePlans.filter((plan) => plan.ordinal !== plan.previousOrdinal);
12510
+ const anythingMoved = movedCompartments.length > 0 || movedRecomp.length > 0 || movedNotes.length > 0 || shrunkMessages.length > 0 || indexNeedsRebuild || boundaryPlan !== null || partialRangePlan !== null || outcome.healedGaps > 0 || outcome.narrativeGaps > 0;
12511
+ if (!anythingMoved) {
12512
+ stampGeneration(db, sessionId, generation, null);
12513
+ return emptyOutcome("stamped", generation, impliedGeneration);
12514
+ }
12515
+ db.exec("BEGIN IMMEDIATE");
12516
+ let closed = false;
12517
+ try {
12518
+ if (readCoordinateGeneration(db, sessionId) !== previousGeneration) {
12519
+ db.exec("ROLLBACK");
12520
+ closed = true;
12521
+ return emptyOutcome("unchanged", generation, readCoordinateGeneration(db, sessionId));
12647
12522
  }
12648
- parsedParts.push({
12649
- id: part.id,
12650
- messageId: part.message_id,
12651
- data,
12652
- tailStartId: dataReferencesTailStart(data)
12523
+ clearCachedM0M1(db, sessionId);
12524
+ db.prepare("UPDATE session_meta SET system_prompt_hash = '' WHERE session_id = ?").run(sessionId);
12525
+ for (const column of [
12526
+ "stripped_placeholder_ids",
12527
+ "merged_reasoning_stripped_ids",
12528
+ "trailing_blank_decisions"
12529
+ ]) {
12530
+ outcome.frozenPartEntriesDropped += pruneShrunkPartEntries(db, sessionId, column, shrunkMessages);
12531
+ }
12532
+ const fold = foldShrunkPartTags2(db, sessionId, shrunkMessages);
12533
+ outcome.partTagsFolded = fold.foldedTagNumbers.length;
12534
+ outcome.partTagsRekeyed = fold.rekeyedTagNumbers.length;
12535
+ outcome.queuedReductionsDiscarded = fold.discardedDropTagNumbers.length;
12536
+ const updateCompartment = {
12537
+ compartments: db.prepare("UPDATE compartments SET start_message = ?, end_message = ?, rebase_status = ? WHERE id = ?"),
12538
+ recomp_compartments: db.prepare("UPDATE recomp_compartments SET start_message = ?, end_message = ?, rebase_status = ? WHERE id = ?")
12539
+ };
12540
+ for (const plan of [...compartmentPlans, ...recompPlans]) {
12541
+ if (!compartmentPlanChanges(plan))
12542
+ continue;
12543
+ updateCompartment[plan.table].run(plan.start, plan.end, plan.status, plan.id);
12544
+ const rebased = plan.status === "ok" ? 1 : 0;
12545
+ const unresolved = plan.status === "unresolved" ? 1 : 0;
12546
+ if (plan.table === "compartments") {
12547
+ outcome.compartmentsRebased += rebased;
12548
+ outcome.compartmentsUnresolved += unresolved;
12549
+ if (rebased === 1 && plan.derived)
12550
+ outcome.compartmentsDerived += 1;
12551
+ if (rebased === 1 && plan.previousStatus === "unresolved")
12552
+ outcome.compartmentsResolvedAgain += 1;
12553
+ } else {
12554
+ outcome.recompCompartmentsRebased += rebased;
12555
+ outcome.recompCompartmentsUnresolved += unresolved;
12556
+ }
12557
+ }
12558
+ const updateNote = db.prepare("UPDATE notes SET anchor_ordinal = ? WHERE id = ? AND session_id = ?");
12559
+ for (const plan of movedNotes) {
12560
+ updateNote.run(plan.ordinal, plan.id, sessionId);
12561
+ if (plan.ordinal === null)
12562
+ outcome.notesCleared += 1;
12563
+ else
12564
+ outcome.notesRebased += 1;
12565
+ }
12566
+ if (boundaryPlan !== null) {
12567
+ db.prepare("UPDATE session_meta SET prior_boundary_ordinal = ? WHERE session_id = ?").run(boundaryPlan, sessionId);
12568
+ outcome.priorBoundaryRebased = true;
12569
+ }
12570
+ if (partialRangePlan !== null) {
12571
+ db.prepare("UPDATE session_meta SET recomp_partial_range_start = ?, recomp_partial_range_end = ? WHERE session_id = ?").run(partialRangePlan.start, partialRangePlan.end, sessionId);
12572
+ outcome.recompPartialRangeRebased = true;
12573
+ }
12574
+ if (indexNeedsRebuild) {
12575
+ clearIndexedMessagesInTransaction2(db, sessionId);
12576
+ outcome.indexRebuilt = true;
12577
+ outcome.compressionDepthRowsDropped = depthRowCount;
12578
+ }
12579
+ if (chunkEmbeddingCount > 0) {
12580
+ db.prepare("DELETE FROM compartment_chunk_embeddings WHERE session_id = ?").run(sessionId);
12581
+ outcome.chunkEmbeddingsDeleted = chunkEmbeddingCount;
12582
+ }
12583
+ if (lkgSlotCount > 0) {
12584
+ db.prepare("DELETE FROM lkg_slot_chunks WHERE session_id = ?").run(sessionId);
12585
+ db.prepare("DELETE FROM lkg_slots WHERE session_id = ?").run(sessionId);
12586
+ outcome.lkgSlotsDropped = lkgSlotCount;
12587
+ }
12588
+ stampGeneration(db, sessionId, generation, {
12589
+ generation,
12590
+ previousGeneration: impliedGeneration,
12591
+ at: Date.now(),
12592
+ unresolvedCompartments: outcome.compartmentsUnresolved + outcome.recompCompartmentsUnresolved,
12593
+ discardedReductions: outcome.queuedReductionsDiscarded,
12594
+ droppedDepthRows: outcome.compressionDepthRowsDropped,
12595
+ healedGaps: outcome.healedGaps,
12596
+ narrativeGaps: outcome.narrativeGaps,
12597
+ derivedCompartments: rangeNotes(compartmentPlans, (plan) => plan.status === "ok" && plan.derived),
12598
+ unresolvedCompartmentRanges: rangeNotes(compartmentPlans, (plan) => plan.status === "unresolved"),
12599
+ neighbourRecoveryAt: Date.now()
12653
12600
  });
12601
+ db.exec("COMMIT");
12602
+ closed = true;
12603
+ } finally {
12604
+ if (!closed) {
12605
+ try {
12606
+ db.exec("ROLLBACK");
12607
+ } catch {}
12608
+ }
12654
12609
  }
12655
- const messageTailRefs = db.prepare(`SELECT id, data
12656
- FROM message
12657
- WHERE session_id = ?
12658
- AND json_extract(data, '$.compaction.tail_start_id') IS NOT NULL`).all(sessionId);
12659
- const messageTailStartIds = new Set;
12660
- for (const row of messageTailRefs) {
12661
- if (typeof row.id !== "string")
12662
- continue;
12663
- let data;
12664
- try {
12665
- data = typeof row.data === "string" ? JSON.parse(row.data) : row.data;
12666
- } catch {
12667
- data = null;
12610
+ if (outcome.indexRebuilt) {
12611
+ const sources = projection.indexSources;
12612
+ for (let start = 0;start < sources.length; start += INDEX_REBUILD_CHUNK) {
12613
+ indexSourcesAfterOrdinal2(db, sessionId, sources.slice(start, start + INDEX_REBUILD_CHUNK), sources.length);
12614
+ yield;
12668
12615
  }
12669
- const ref = dataReferencesTailStart(data);
12670
- if (ref)
12671
- messageTailStartIds.add(ref);
12616
+ outcome.indexRowsRebuilt = countRows2(db, "SELECT COUNT(*) AS count FROM message_history_source WHERE session_id = ?", sessionId);
12672
12617
  }
12673
- let removedLineages = 0;
12674
- let removedRows = 0;
12675
- let retainedLineages = 0;
12676
- const deletePartsOfMessage = db.prepare("DELETE FROM part WHERE +session_id = ? AND message_id = ?");
12677
- const deleteMessage = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
12678
- const deletePart = db.prepare("DELETE FROM part WHERE session_id = ? AND id = ?");
12679
- const deleteSummaries = (summaryIds) => {
12680
- let rows = 0;
12681
- for (const summaryId of summaryIds) {
12682
- rows += deletePartsOfMessage.run(sessionId, summaryId).changes;
12683
- rows += deleteMessage.run(sessionId, summaryId).changes;
12618
+ sessionLog2(sessionId, formatRebaseLogLine(outcome, performance.now() - startedAt));
12619
+ return outcome;
12620
+ }
12621
+ function recoverUnresolvedCompartments(args) {
12622
+ const { db, sessionId } = args;
12623
+ const rows = readCompartmentRows(db, "compartments", sessionId);
12624
+ const result = { rowsRewritten: 0, derived: [], unresolved: [] };
12625
+ if (!rows.some((row) => row.rebase_status === "unresolved"))
12626
+ return result;
12627
+ const known = rows.map((row) => {
12628
+ if (row.rebase_status !== "unresolved") {
12629
+ return { start: row.start_message, end: row.end_message };
12684
12630
  }
12685
- return rows;
12686
- };
12687
- for (const [boundaryMessageId, summaryIds] of summariesByBoundary) {
12688
- const boundaryParts = parsedParts.filter((part) => part.messageId === boundaryMessageId);
12689
- const mcPartIds = boundaryParts.filter((part) => isMcCanonicalCompactionPartData(part.data)).map((part) => part.id);
12690
- const rowsToDelete = new Set([...summaryIds, ...mcPartIds]);
12691
- const survivingPartsReferenceDeletion = parsedParts.some((part) => !mcPartIds.includes(part.id) && part.tailStartId !== null && rowsToDelete.has(part.tailStartId));
12692
- const messageFieldReferencesDeletion = [...rowsToDelete].some((id) => messageTailStartIds.has(id));
12693
- if (survivingPartsReferenceDeletion || messageFieldReferencesDeletion) {
12694
- retainedLineages += 1;
12695
- log2(`[magic-context] compaction-marker: flip-off cleanup RETAINED lineage at boundary ${boundaryMessageId} — a surviving tail_start_id references a row the deletion would remove`);
12696
- continue;
12631
+ return {
12632
+ start: resolveAnchor(row.start_message_id, args.resolveOrdinal),
12633
+ end: resolveAnchor(row.end_message_id, args.resolveOrdinal)
12634
+ };
12635
+ });
12636
+ const plans = recoverFromNeighbours(rows, "compartments", known);
12637
+ const wasUnresolved = (plan) => plan.previousStatus === "unresolved";
12638
+ result.derived = rangeNotes(plans, (plan) => wasUnresolved(plan) && plan.status === "ok" && plan.derived);
12639
+ result.unresolved = rangeNotes(plans, (plan) => plan.status === "unresolved");
12640
+ const changed = plans.filter(compartmentPlanChanges);
12641
+ const now = Date.now();
12642
+ db.exec("BEGIN IMMEDIATE");
12643
+ let committed = false;
12644
+ try {
12645
+ for (const plan of changed) {
12646
+ db.prepare("UPDATE compartments SET start_message = ?, end_message = ?, rebase_status = ? WHERE id = ?").run(plan.start, plan.end, plan.status, plan.id);
12697
12647
  }
12698
- const rows = runMarkerRemovalTransaction(db, () => {
12699
- let changed = deleteSummaries(summaryIds);
12700
- for (const partId of mcPartIds) {
12701
- changed += deletePart.run(sessionId, partId).changes;
12702
- }
12703
- return changed;
12704
- });
12705
- if (rows > 0 || summaryIds.size > 0 || mcPartIds.length > 0) {
12706
- removedLineages += 1;
12707
- removedRows += rows;
12648
+ const previous = readCoordinateRebaseNotice(db, sessionId);
12649
+ const generation = previous?.generation ?? readCoordinateGeneration(db, sessionId);
12650
+ if (generation !== null) {
12651
+ const derivedSequences = new Set(result.derived.map((note) => note.sequence));
12652
+ const notice = {
12653
+ generation,
12654
+ previousGeneration: previous?.previousGeneration ?? null,
12655
+ at: previous?.at ?? now,
12656
+ unresolvedCompartments: result.unresolved.length,
12657
+ discardedReductions: previous?.discardedReductions ?? 0,
12658
+ droppedDepthRows: previous?.droppedDepthRows ?? 0,
12659
+ healedGaps: previous?.healedGaps ?? 0,
12660
+ narrativeGaps: previous?.narrativeGaps ?? 0,
12661
+ derivedCompartments: [
12662
+ ...(previous?.derivedCompartments ?? []).filter((note) => !derivedSequences.has(note.sequence)),
12663
+ ...result.derived
12664
+ ],
12665
+ unresolvedCompartmentRanges: result.unresolved,
12666
+ neighbourRecoveryAt: now
12667
+ };
12668
+ ensureSessionMetaRow(db, sessionId);
12669
+ db.prepare("UPDATE session_meta SET coordinate_rebase_notice = ? WHERE session_id = ?").run(JSON.stringify(notice), sessionId);
12708
12670
  }
12709
- }
12710
- if (orphanSummaryIds.size > 0) {
12711
- const rowsToDelete = new Set(orphanSummaryIds);
12712
- const survivingPartsReferenceDeletion = parsedParts.some((part) => part.tailStartId !== null && rowsToDelete.has(part.tailStartId));
12713
- const messageFieldReferencesDeletion = [...rowsToDelete].some((id) => messageTailStartIds.has(id));
12714
- if (survivingPartsReferenceDeletion || messageFieldReferencesDeletion) {
12715
- retainedLineages += 1;
12716
- } else {
12717
- const rows = runMarkerRemovalTransaction(db, () => deleteSummaries(orphanSummaryIds));
12718
- removedLineages += 1;
12719
- removedRows += rows;
12671
+ db.exec("COMMIT");
12672
+ committed = true;
12673
+ } finally {
12674
+ if (!committed) {
12675
+ try {
12676
+ db.exec("ROLLBACK");
12677
+ } catch {}
12720
12678
  }
12721
12679
  }
12722
- if (removedLineages > 0 || retainedLineages > 0) {
12723
- log2(`[magic-context] compaction-marker: flip-off cleanup for ${sessionId} removed ${removedLineages} lineage(s) (${removedRows} rows), retained ${retainedLineages}`);
12680
+ result.rowsRewritten = changed.length;
12681
+ sessionLog2(sessionId, `INFO compartment neighbour recovery (${args.reason}) rows_rewritten=${changed.length} ` + `derived=${result.derived.map((note) => `${note.start}-${note.end}`).join(",") || "none"} ` + `unresolved=${result.unresolved.map((note) => `${note.start}-${note.end}`).join(",") || "none"}`);
12682
+ return result;
12683
+ }
12684
+ var repairCheckedSessions = new WeakMap;
12685
+ function unresolvedRowBreaksTiling(rows) {
12686
+ let expectedStart = 1;
12687
+ for (let index = 0;index < rows.length; index += 1) {
12688
+ const row = rows[index];
12689
+ if (!row)
12690
+ continue;
12691
+ const broken = row.start_message !== expectedStart || row.end_message < row.start_message;
12692
+ const touchesUnresolved = row.rebase_status === "unresolved" || rows[index - 1]?.rebase_status === "unresolved";
12693
+ if (broken && touchesUnresolved)
12694
+ return true;
12695
+ expectedStart = row.end_message + 1;
12724
12696
  }
12725
- return {
12726
- verified: retainedLineages === 0,
12727
- removedLineages,
12728
- removedRows,
12729
- retainedLineages
12730
- };
12697
+ return false;
12731
12698
  }
12732
- function removeCompactionMarker(state) {
12733
- try {
12734
- const db = getWritableOpenCodeDb("removal");
12735
- runMarkerRemovalTransaction(db, () => {
12736
- db.prepare("DELETE FROM part WHERE id = ?").run(state.summaryPartId);
12737
- db.prepare("DELETE FROM message WHERE id = ?").run(state.summaryMessageId);
12738
- db.prepare("DELETE FROM part WHERE id = ?").run(state.compactionPartId);
12739
- });
12740
- return true;
12741
- } catch (error) {
12742
- log2(`[magic-context] compaction-marker: removal failed: ${error instanceof Error ? error.message : String(error)}`);
12743
- return false;
12699
+ function repairStampedSessionOnce(db, sessionId, readArgs) {
12700
+ let checked = repairCheckedSessions.get(db);
12701
+ if (!checked) {
12702
+ checked = new Set;
12703
+ repairCheckedSessions.set(db, checked);
12704
+ }
12705
+ if (checked.has(sessionId))
12706
+ return null;
12707
+ checked.add(sessionId);
12708
+ const rows = readCompartmentRows(db, "compartments", sessionId);
12709
+ if (!rows.some((row) => row.rebase_status === "unresolved"))
12710
+ return null;
12711
+ if (readCoordinateRebaseNotice(db, sessionId)?.neighbourRecoveryAt != null)
12712
+ return null;
12713
+ if (!unresolvedRowBreaksTiling(rows))
12714
+ return null;
12715
+ let ordinalById = null;
12716
+ return recoverUnresolvedCompartments({
12717
+ db,
12718
+ sessionId,
12719
+ resolveOrdinal: (messageId) => {
12720
+ if (ordinalById === null) {
12721
+ const projection = emptyProjection();
12722
+ for (const page of readProjectionPages(readArgs)) {
12723
+ addToProjection(projection, page, false);
12724
+ }
12725
+ ordinalById = projection.ordinalById;
12726
+ }
12727
+ return ordinalById.get(messageId);
12728
+ },
12729
+ reason: "stamped-session repair"
12730
+ });
12731
+ }
12732
+ function formatRebaseLogLine(outcome, elapsedMs) {
12733
+ const rowsRewritten = outcome.compartmentsRebased + outcome.recompCompartmentsRebased + outcome.notesRebased + outcome.notesCleared + (outcome.priorBoundaryRebased ? 1 : 0) + (outcome.recompPartialRangeRebased ? 1 : 0);
12734
+ const unresolved = outcome.compartmentsUnresolved + outcome.recompCompartmentsUnresolved;
12735
+ return `INFO store-generation-rebase ${outcome.previousGeneration ?? "unrecorded"}->${outcome.generation} ` + `rows_rewritten=${rowsRewritten} unresolved=${unresolved} derived=${outcome.compartmentsDerived} ` + `index_rows_rebuilt=${outcome.indexRowsRebuilt} drops_discarded=${outcome.queuedReductionsDiscarded} ` + `healed_gaps=${outcome.healedGaps} narrative_gaps=${outcome.narrativeGaps} ` + `ms=${Math.round(elapsedMs)} ` + `(chunk_windows_deleted=${outcome.chunkEmbeddingsDeleted} depth_rows_dropped=${outcome.compressionDepthRowsDropped} ` + `part_tags_folded=${outcome.partTagsFolded} lkg_slots_dropped=${outcome.lkgSlotsDropped} ` + `frozen_part_entries_dropped=${outcome.frozenPartEntriesDropped})`;
12736
+ }
12737
+ function planPriorBoundary(db, sessionId, plans) {
12738
+ const row = db.prepare("SELECT prior_boundary_ordinal FROM session_meta WHERE session_id = ?").get(sessionId);
12739
+ const current = typeof row?.prior_boundary_ordinal === "number" ? row.prior_boundary_ordinal : 1;
12740
+ if (current <= 1)
12741
+ return null;
12742
+ const source = plans.find((plan) => plan.status === "ok" && plan.previousEnd === current && plan.end !== current);
12743
+ return source ? source.end : null;
12744
+ }
12745
+ function planRecompPartialRange(db, sessionId, plans) {
12746
+ const row = db.prepare("SELECT recomp_partial_range_start AS start, recomp_partial_range_end AS end FROM session_meta WHERE session_id = ?").get(sessionId);
12747
+ const start = typeof row?.start === "number" ? row.start : 0;
12748
+ const end = typeof row?.end === "number" ? row.end : 0;
12749
+ if (start <= 0 && end <= 0)
12750
+ return null;
12751
+ const startSource = plans.find((plan) => plan.status === "ok" && plan.previousStart === start);
12752
+ const endSource = plans.find((plan) => plan.status === "ok" && plan.previousEnd === end);
12753
+ if (!startSource || !endSource)
12754
+ return null;
12755
+ if (startSource.start === start && endSource.end === end)
12756
+ return null;
12757
+ return { start: startSource.start, end: endSource.end };
12758
+ }
12759
+ function indexDisagreesWithProjection(db, sessionId, projection) {
12760
+ const sourceRows = db.prepare("SELECT message_id, message_ordinal FROM message_history_source WHERE session_id = ?").all(sessionId);
12761
+ if (sourceRows.length === 0) {
12762
+ return countRows2(db, "SELECT COUNT(*) AS count FROM message_fts_rowid_map WHERE session_id = ?", sessionId) > 0;
12763
+ }
12764
+ for (const row of sourceRows) {
12765
+ if (typeof row.message_id !== "string" || typeof row.message_ordinal !== "number") {
12766
+ return true;
12767
+ }
12768
+ if (projection.ordinalById.get(row.message_id) !== row.message_ordinal)
12769
+ return true;
12744
12770
  }
12771
+ const orphanedMapRows = countRows2(db, `SELECT COUNT(*) AS count FROM message_fts_rowid_map AS m
12772
+ WHERE m.session_id = ?
12773
+ AND NOT EXISTS (
12774
+ SELECT 1 FROM message_history_source AS s
12775
+ WHERE s.session_id = m.session_id AND s.message_ordinal = m.message_ordinal
12776
+ )`, sessionId);
12777
+ return orphanedMapRows > 0;
12745
12778
  }
12746
12779
 
12747
12780
  // src/hooks/magic-context/compaction-marker-manager.ts
@@ -12763,7 +12796,7 @@ function persistMarkerStateAndDropReplacedTag(db, sessionId, state, replacedSumm
12763
12796
  logSlowWriteTransaction("marker-drain", transactionStartedAt);
12764
12797
  }
12765
12798
  function markerUpdateDefinitelyDidNotCut(outcome) {
12766
- return outcome.kind === "already-current" || outcome.kind === "stale-skip" || outcome.kind === "retryable-failure" && outcome.cut === "definitely-no-cut";
12799
+ return outcome.kind === "already-current" || outcome.kind === "deferred" || outcome.kind === "stale-skip" || outcome.kind === "retryable-failure" && outcome.cut === "definitely-no-cut";
12767
12800
  }
12768
12801
  function validatePendingTarget(db, sessionId, pending) {
12769
12802
  const ocMessage = getOpenCodeMessageById(sessionId, pending.endMessageId);
@@ -12875,6 +12908,8 @@ function applyDeferredCompactionMarker(db, sessionId, pending, directory, truste
12875
12908
  resolvedBoundary: boundary
12876
12909
  });
12877
12910
  endStep("replace");
12911
+ if (replacement.kind === "deferred")
12912
+ return { kind: "deferred", reason: "candidate-preparation" };
12878
12913
  if (replacement.kind !== "committed") {
12879
12914
  return {
12880
12915
  kind: "retryable-failure",
@@ -19260,7 +19295,7 @@ function resolveProtectedTailBoundary(ctx) {
19260
19295
  const offset = Math.max(1, ctx.lastCompartmentEndOrdinal + 1);
19261
19296
  const absoluteMessageCount = getCachedAbsoluteMessageCount2(ctx.sessionId) ?? getRawSessionMessageOrdinalCount2(ctx.sessionId);
19262
19297
  const messages = readRawSessionMessageRange2(ctx.sessionId, Math.max(1, offset - 1), absoluteMessageCount);
19263
- const storedTotals = ctx.storedTokenTotals;
19298
+ const storedTotals = ctx.storedTokenTotalsForMessages?.(messages.map((m) => m.id)) ?? ctx.storedTokenTotals;
19264
19299
  const index = buildTrueRawTokenIndex(ctx.sessionId, messages, {
19265
19300
  providerShapeVersion: ctx.providerShapeVersion,
19266
19301
  cacheNamespace: ctx.cacheNamespace,
@@ -19503,12 +19538,14 @@ function resolveBoundaryContext(args) {
19503
19538
  migrationFloorActive = seedResult.seeded;
19504
19539
  }
19505
19540
  const calibration = sessionDecisionCalibration(args.db, args.sessionId);
19506
- let storedTokenTotals;
19507
- try {
19508
- storedTokenTotals = getAllStatusTagTokenTotalsFlat2(args.db, args.sessionId, args.taggerFloor ?? 0, calibration).totals;
19509
- } catch (error) {
19510
- sessionLog2(args.sessionId, "protected-tail stored-token map unavailable (live fallback):", error);
19511
- }
19541
+ const storedTokenTotalsForMessages = (messageIds) => {
19542
+ try {
19543
+ return getAllStatusTagTokenTotalsFlat2(args.db, args.sessionId, args.taggerFloor ?? 0, calibration, messageIds).totals;
19544
+ } catch (error) {
19545
+ sessionLog2(args.sessionId, "protected-tail stored-token map unavailable (live fallback):", error);
19546
+ return;
19547
+ }
19548
+ };
19512
19549
  return {
19513
19550
  sessionId: args.sessionId,
19514
19551
  mode: args.mode,
@@ -19525,7 +19562,7 @@ function resolveBoundaryContext(args) {
19525
19562
  emergencyTailScale: args.emergencyTailScale,
19526
19563
  providerShapeVersion: args.providerShapeVersion ?? "opencode-v1",
19527
19564
  cacheNamespace: args.cacheNamespace ?? `opencode:${args.sessionId}`,
19528
- storedTokenTotals,
19565
+ storedTokenTotalsForMessages,
19529
19566
  calibration
19530
19567
  };
19531
19568
  }
@@ -19538,13 +19575,14 @@ function resolveWrapupProtectedTailBoundary(args) {
19538
19575
  const offset = Math.max(1, ctx.lastCompartmentEndOrdinal + 1);
19539
19576
  const absoluteMessageCount = getCachedAbsoluteMessageCount2(ctx.sessionId) ?? getRawSessionMessageOrdinalCount2(ctx.sessionId);
19540
19577
  const messages = readRawSessionMessageRange2(ctx.sessionId, Math.max(1, offset - 1), absoluteMessageCount);
19578
+ const storedTotals = ctx.storedTokenTotalsForMessages?.(messages.map((m) => m.id)) ?? ctx.storedTokenTotals;
19541
19579
  const index = buildTrueRawTokenIndex(ctx.sessionId, messages, {
19542
19580
  providerShapeVersion: ctx.providerShapeVersion,
19543
19581
  cacheNamespace: ctx.cacheNamespace,
19544
19582
  calibration: ctx.calibration,
19545
19583
  absoluteMessageCount,
19546
- storedTotalForMessage: ctx.storedTokenTotals ? (m) => {
19547
- const value = ctx.storedTokenTotals?.get(m.id);
19584
+ storedTotalForMessage: storedTotals ? (m) => {
19585
+ const value = storedTotals?.get(m.id);
19548
19586
  return value === undefined ? null : value;
19549
19587
  } : undefined
19550
19588
  });
@@ -20338,6 +20376,8 @@ ${chunkText}`,
20338
20376
  deps.onDeferredMarkerPending?.(sessionId);
20339
20377
  } else {
20340
20378
  try {
20379
+ if (!deps.compactionMarkerStrategy?.publish || deps.compactionMarkerStrategy.publish === updateCompactionMarkerAfterPublication)
20380
+ await prepareCompactionMarkerCandidates(sessionId);
20341
20381
  (deps.compactionMarkerStrategy?.publish ?? updateCompactionMarkerAfterPublication)(db, sessionId, lastCompartmentEnd, sessionDirectory);
20342
20382
  } catch (error) {
20343
20383
  sessionLog2(sessionId, "compaction-marker update after publish failed:", error);
@@ -21446,4 +21486,4 @@ async function executeContextRecomp(deps, options = {}) {
21446
21486
  return (await executeContextRecompWithResult(deps, options)).message;
21447
21487
  }
21448
21488
 
21449
- export { denyTaskRoutingToCallerAgents, buildHiddenAgentRegistrations, buildHiddenAgentConfig, getMagicContextBuiltinCommands, formatConfigParseStatusLine, claimConfigParseFailuresOnce, COMPACTION_ENABLED_PATH, isDreamerRunnable, isHistorianRunnable, isCompactionEnabled, cortexKitUserConfigBasePath, cortexKitProjectConfigBasePath, resolveLegacyConfigSources, migrateMagicContextConfigLocations, getProtectedTokensTierOverrides, loadPluginConfigDetailed, historianRunConfig, dreamerRunConfig, pluginConfigReader, currentPluginConfigReader, withLiveDreamerOutputCap, createDreamerOutputCapSampler, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_EDITOR_SYSTEM_PROMPT, COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, clampProducerAtomChars, producerInputTokenLimit, historianProducerReserve, producerPromptFailureReason, DREAMER_AGENT, DREAMER_RETROSPECTIVE_AGENT, DREAMER_PRIMER_INVESTIGATOR_AGENT, DREAMER_MEMORY_MAPPER_AGENT, DREAMER_CLASSIFIER_AGENT, DREAMER_DOCS_AGENT, DREAMER_REVIEWER_AGENT, embedPauseBySession, embedRunStateBySession, autoEmbedAttemptedBySession, autoEmbedIdentityBySession, invalidateAutoEmbedSession, getEmbedDrainUiStatus, clearEmbedSessionState, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, queueM0Mutation, getMaxM0MutationId, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getUncoveredCompartmentEndsThrough, providerResponseFailed, isSuccessfulProviderCompletion, rememberUnpublishedAutoSearchNoHint, getUnpublishedAutoSearchNoHint, forgetUnpublishedAutoSearchNoHint, registerAutoSearchWork, cancelAutoSearchWork, gaDatabasePath, RAW_MESSAGE_TYPES, V2StoreReaderPool, V2StoreReader, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, clearSession, requestPendingMaterialization, pendingMaterializationOrigin, clearPendingMaterialization, recordSystemPromptForRequest, recordHeldHeadForRequest, bindSystemPromptResponse, isHeldHeadForRequest, deferDeliveredSystemRefresh, retirePendingSystemPromptDelivery, lkgProviderInputTotal, beginV2LkgRequest, claimLkgRequestIdentity, currentLkgRequestIdentity, noteCapturedLkgRequest, noteLkgProviderResponse, measuredLkgPrefix, clearLkgMeasuredRequest, saveLkgSlotToDb, clearPersistedLkgSlotStrict, loadPersistedLkgSlot, drainStaleLkgSlots, createDbLkgPersistence, resolveLkgModelKeys, createLkgEntryProjector, captureLkgSlot, replayLkg, coldStartRawServedIndex, coldStartUncapturedReplay, noteUncertifiedNormalLkg, hasProcessLocalLkgProof, lkgDirtyRevision, rememberLkgDirtyRevision, noteLkgRecoveryPrefix, readLkgRecoveryPrefix, noteLkgHealthyPrefix, lkgRecoveryReplayUnproven, lkgRecoveryEntryUnproven, registerLkgPersistence, 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, createChildSessionWithFence, HiddenCompletionRefusal, DreamerProviderOutputFailureError, withDreamerModelCooldown, providerOutputFailureFromInvalidManifest, HIDDEN_HISTORIAN_AGENT, HIDDEN_DREAMER_AGENT, HIDDEN_CURATE_AGENT, hiddenAgentFor, hiddenToolLoop, hiddenChildPermissions, registerHiddenChildAgents, hiddenToolCallRefusal, HiddenAgentStepLimit, HiddenChildHook, extractLatestAssistantText, hasLengthCappedOutput, parseProviderModel, modelBodyField, toModelEntry, isPromptTimeoutError, getPromptFailureDetail, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, failedInvocationStatus, recordChildInvocation, recordPromptSessionError, createPromptAsyncTransport, CTX_NOTE_LIGHT_DESCRIPTION, ACTIVE_TOOL_IDS, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, setKeepSubagents, teardownChildSession, getCompartmentEvents, runTokenLog, formatRunTokenLog, resolveHiddenCompletionExecutor, createV1HiddenCompletionExecutor, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, getMuralIdentity, getMural, readCoordinateGeneration, readCoordinateRebaseNotice, formatCoordinateRebaseNotice, rebaseSessionCoordinatesAsync, getOpenCodeDbPath, compareOpenCodeMessagesByCanonicalOrder, removeMcOwnedCompactionMarkers, MARKER_SUMMARY_TEXT, markerUpdateDefinitelyDidNotCut, applyDeferredCompactionMarker, removeCompactionMarkerForSession, checkCompactionMarkerConsistency, buildMagicContextSection, 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, EMPTY_READ_REPLY, noteTouchedAt, renderGlance, renderNotesById, formatWriteReply, observeNoteNudgeServe, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, resetNoteNudgeCooldownOnly, clearNoteNudgeTriggerOnly, describeBoundaryDiagnostics, RECOVERY_NO_HEAD_LIMIT, deriveProtectedTailTokenTarget, selectPerRunCap, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, runCompartmentAgent, snapRangeToCompartments, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, executeContextRecomp };
21489
+ export { denyTaskRoutingToCallerAgents, buildHiddenAgentRegistrations, buildHiddenAgentConfig, getMagicContextBuiltinCommands, formatConfigParseStatusLine, claimConfigParseFailuresOnce, COMPACTION_ENABLED_PATH, isDreamerRunnable, isHistorianRunnable, isCompactionEnabled, cortexKitUserConfigBasePath, cortexKitProjectConfigBasePath, resolveLegacyConfigSources, migrateMagicContextConfigLocations, getProtectedTokensTierOverrides, loadPluginConfigDetailed, historianRunConfig, dreamerRunConfig, pluginConfigReader, currentPluginConfigReader, withLiveDreamerOutputCap, createDreamerOutputCapSampler, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_EDITOR_SYSTEM_PROMPT, COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, clampProducerAtomChars, producerInputTokenLimit, historianProducerReserve, producerPromptFailureReason, DREAMER_AGENT, DREAMER_RETROSPECTIVE_AGENT, DREAMER_PRIMER_INVESTIGATOR_AGENT, DREAMER_MEMORY_MAPPER_AGENT, DREAMER_CLASSIFIER_AGENT, DREAMER_DOCS_AGENT, DREAMER_REVIEWER_AGENT, embedPauseBySession, embedRunStateBySession, autoEmbedAttemptedBySession, autoEmbedIdentityBySession, invalidateAutoEmbedSession, getEmbedDrainUiStatus, clearEmbedSessionState, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, queueM0Mutation, getMaxM0MutationId, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getUncoveredCompartmentEndsThrough, providerResponseFailed, isSuccessfulProviderCompletion, rememberUnpublishedAutoSearchNoHint, getUnpublishedAutoSearchNoHint, forgetUnpublishedAutoSearchNoHint, registerAutoSearchWork, cancelAutoSearchWork, gaDatabasePath, RAW_MESSAGE_TYPES, V2StoreReaderPool, V2StoreReader, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, clearSession, requestPendingMaterialization, pendingMaterializationOrigin, clearPendingMaterialization, recordSystemPromptForRequest, recordHeldHeadForRequest, bindSystemPromptResponse, isHeldHeadForRequest, deferDeliveredSystemRefresh, retirePendingSystemPromptDelivery, lkgProviderInputTotal, beginV2LkgRequest, claimLkgRequestIdentity, currentLkgRequestIdentity, noteCapturedLkgRequest, noteLkgProviderResponse, measuredLkgPrefix, clearLkgMeasuredRequest, saveLkgSlotToDb, clearPersistedLkgSlotStrict, loadPersistedLkgSlot, drainStaleLkgSlots, createDbLkgPersistence, resolveLkgModelKeys, createLkgEntryProjector, captureLkgSlot, replayLkg, coldStartRawServedIndex, coldStartUncapturedReplay, noteUncertifiedNormalLkg, hasProcessLocalLkgProof, lkgDirtyRevision, rememberLkgDirtyRevision, noteLkgRecoveryPrefix, readLkgRecoveryPrefix, noteLkgHealthyPrefix, lkgRecoveryReplayUnproven, lkgRecoveryEntryUnproven, registerLkgPersistence, 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, createChildSessionWithFence, HiddenCompletionRefusal, DreamerProviderOutputFailureError, withDreamerModelCooldown, providerOutputFailureFromInvalidManifest, HIDDEN_HISTORIAN_AGENT, HIDDEN_DREAMER_AGENT, HIDDEN_CURATE_AGENT, hiddenAgentFor, hiddenToolLoop, hiddenChildPermissions, registerHiddenChildAgents, hiddenToolCallRefusal, HiddenAgentStepLimit, HiddenChildHook, extractLatestAssistantText, hasLengthCappedOutput, parseProviderModel, modelBodyField, toModelEntry, isPromptTimeoutError, getPromptFailureDetail, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, failedInvocationStatus, recordChildInvocation, recordPromptSessionError, createPromptAsyncTransport, CTX_NOTE_LIGHT_DESCRIPTION, ACTIVE_TOOL_IDS, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, setKeepSubagents, teardownChildSession, getCompartmentEvents, runTokenLog, formatRunTokenLog, resolveHiddenCompletionExecutor, createV1HiddenCompletionExecutor, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, getMuralIdentity, getMural, getOpenCodeDbPath, compareOpenCodeMessagesByCanonicalOrder, prepareCompactionMarkerCandidates, removeMcOwnedCompactionMarkers, readCoordinateGeneration, readCoordinateRebaseNotice, formatCoordinateRebaseNotice, rebaseSessionCoordinatesAsync, MARKER_SUMMARY_TEXT, markerUpdateDefinitelyDidNotCut, applyDeferredCompactionMarker, removeCompactionMarkerForSession, checkCompactionMarkerConsistency, buildMagicContextSection, 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, EMPTY_READ_REPLY, noteTouchedAt, renderGlance, renderNotesById, formatWriteReply, observeNoteNudgeServe, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, resetNoteNudgeCooldownOnly, clearNoteNudgeTriggerOnly, describeBoundaryDiagnostics, RECOVERY_NO_HEAD_LIMIT, deriveProtectedTailTokenTarget, selectPerRunCap, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, runCompartmentAgent, snapRangeToCompartments, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, executeContextRecomp };