@cortexkit/opencode-magic-context 0.49.26 → 0.49.28

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 (110) hide show
  1. package/dist/auto-search-worker.js +4 -4
  2. package/dist/chunk-embedding-write-worker.js +7 -7
  3. package/dist/{compartment-chunk-embedding-96ec8a7h.js → compartment-chunk-embedding-qgp0tbf7.js} +3 -3
  4. package/dist/config/schema/magic-context.d.ts +393 -393
  5. package/dist/{conflict-warning-hook-dv8fdc2w.js → conflict-warning-hook-tgnw019g.js} +4 -4
  6. package/dist/{context-pjqa24nd.js → context-dxfztzsd.js} +116 -116
  7. package/dist/{embedding-backfill-a91rvdf9.js → embedding-backfill-cwnyr4fj.js} +5 -5
  8. package/dist/features/magic-context/dreamer/map-memories.d.ts +2 -2
  9. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  10. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  11. package/dist/features/magic-context/message-index-async.d.ts +1 -4
  12. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  13. package/dist/features/magic-context/message-index.d.ts +1 -28
  14. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  15. package/dist/features/magic-context/session-retention.fixture.d.ts +4 -0
  16. package/dist/features/magic-context/session-retention.fixture.d.ts.map +1 -0
  17. package/dist/features/magic-context/storage-session-tables.d.ts +5 -12
  18. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  19. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  20. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  21. package/dist/hooks/magic-context/historian-history-wait.d.ts +10 -0
  22. package/dist/hooks/magic-context/historian-history-wait.d.ts.map +1 -0
  23. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +0 -5
  24. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +0 -10
  26. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/todo-view.d.ts +2 -2
  28. package/dist/{index-w55zp7kf.js → index-077ht5cq.js} +1 -1
  29. package/dist/{index-xyx2ge2y.js → index-31y1mznz.js} +4 -4
  30. package/dist/{index-6g1zq1sk.js → index-4cpc59jv.js} +5 -5
  31. package/dist/{index-e5b61ty6.js → index-4ypqzvhf.js} +1 -1
  32. package/dist/index-7gbcg8xv.js +559 -0
  33. package/dist/{index-9q1g3c5q.js → index-7kkphb6c.js} +1 -1
  34. package/dist/{index-zn2n24yr.js → index-89k1w6x2.js} +3 -3
  35. package/dist/{index-sgchhbvy.js → index-a2fz9hpa.js} +1 -1
  36. package/dist/{index-hjnrp6vy.js → index-dcqk0y27.js} +1508 -85
  37. package/dist/{index-r3bteyev.js → index-dzfevacx.js} +9 -9
  38. package/dist/{index-rp78nqvr.js → index-fq2p158w.js} +10 -10
  39. package/dist/{index-56tfs78r.js → index-k9jx7ma9.js} +598 -610
  40. package/dist/{index-6tmf87w0.js → index-mm93m7y6.js} +1 -1
  41. package/dist/{index-va2g2q57.js → index-n8qmmd7f.js} +3 -3
  42. package/dist/{index-whcgcfrv.js → index-np3rgfw4.js} +1 -1
  43. package/dist/{index-m8va3mma.js → index-rverk2vz.js} +0 -2
  44. package/dist/{index-cfaet9cg.js → index-s1n8dd2n.js} +1 -1
  45. package/dist/{index-mphkpyap.js → index-t3rbb8wr.js} +2 -2
  46. package/dist/{index-064v90e8.js → index-tvzvjggy.js} +1 -1
  47. package/dist/{index-j43m40zd.js → index-v0dhhxsq.js} +1 -1
  48. package/dist/{index-xbbgcwd2.js → index-v15ne3a3.js} +2 -5
  49. package/dist/{index-x9k3mqrf.js → index-xrnsygfq.js} +1 -1
  50. package/dist/{index-dn2ke3b9.js → index-yzjhx10y.js} +5 -5
  51. package/dist/index.js +38 -38
  52. package/dist/{message-fts-rowid-map-4ksatb6f.js → message-fts-rowid-map-va36knh4.js} +2 -4
  53. package/dist/{message-index-bounded-whh5wv4a.js → message-index-bounded-7ayzb2ah.js} +22 -25
  54. package/dist/migration-worker.js +6 -6
  55. package/dist/plugin/dream-timer.d.ts.map +1 -1
  56. package/dist/{project-embedding-registry-t9fx6jwh.js → project-embedding-registry-94nncs5g.js} +4 -4
  57. package/dist/raw-ordinal-warmup-worker.js +7 -30
  58. package/dist/{read-session-chunk-mqmkgdx0.js → read-session-chunk-jzb6w9w5.js} +6 -6
  59. package/dist/{read-session-raw-dy2xxafq.js → read-session-raw-b2sd67v4.js} +1 -1
  60. package/dist/{recomp-orchestrator-qwcz86r1.js → recomp-orchestrator-02sa2ngr.js} +17 -17
  61. package/dist/{search-archive-8md3twv2.js → search-archive-q1vw7zg4.js} +7 -7
  62. package/dist/{search-y2t97tbb.js → search-spq6nfyf.js} +14 -15
  63. package/dist/{send-session-notification-kzazs7fy.js → send-session-notification-afzzqy5b.js} +3 -3
  64. package/dist/{storage-tags-a77q4v77.js → storage-tags-6hvkk01c.js} +2 -2
  65. package/dist/{transform-postprocess-phase-ppm1tfa7.js → transform-postprocess-phase-6menyyxc.js} +17 -17
  66. package/dist/v2/auto-search-worker.js +4 -4
  67. package/dist/v2/chunk-embedding-write-worker.js +7 -7
  68. package/dist/v2/{compartment-chunk-embedding-5rmrn09z.js → compartment-chunk-embedding-63dzs31c.js} +3 -3
  69. package/dist/v2/{context-10pj3bwd.js → context-0qhz1nnj.js} +199 -209
  70. package/dist/v2/{embedding-backfill-r9mzt2eg.js → embedding-backfill-rh5dgsva.js} +5 -5
  71. package/dist/v2/hooks/context.d.ts.map +1 -1
  72. package/dist/v2/{message-fts-rowid-map-2s3ta05x.js → message-fts-rowid-map-78awh03v.js} +2 -4
  73. package/dist/v2/{message-index-bounded-f4269d3a.js → message-index-bounded-n09b74vr.js} +21 -24
  74. package/dist/v2/migration-worker.js +6 -6
  75. package/dist/v2/{project-embedding-registry-tgtmart7.js → project-embedding-registry-6pak822h.js} +4 -4
  76. package/dist/v2/raw-ordinal-warmup-worker.js +7 -30
  77. package/dist/v2/{read-session-chunk-ym5zvexn.js → read-session-chunk-vpt69tw9.js} +5 -5
  78. package/dist/v2/{read-session-raw-484g8kf2.js → read-session-raw-5x088amc.js} +1 -1
  79. package/dist/v2/{recomp-orchestrator-b44s2snm.js → recomp-orchestrator-txsmbnvw.js} +14 -14
  80. package/dist/v2/{search-archive-pmf2c1kb.js → search-archive-t9bcz4ht.js} +6 -6
  81. package/dist/v2/{search-75tf953m.js → search-dcy9b6gd.js} +13 -14
  82. package/dist/v2/{send-session-notification-gd21f5rq.js → send-session-notification-vdsgnf4c.js} +1 -1
  83. package/dist/v2/{server-7dpnt0ys.js → server-4sn3at8p.js} +1 -1
  84. package/dist/v2/{server-wj8h2q21.js → server-6avtp9jp.js} +1 -1
  85. package/dist/v2/{server-wwaw5npa.js → server-6g98c227.js} +1 -1
  86. package/dist/v2/{server-erk2bvdf.js → server-6vd2n183.js} +0 -2
  87. package/dist/v2/{server-4frtg2z1.js → server-awr8qa4c.js} +2 -5
  88. package/dist/v2/{server-7d6m1p2b.js → server-cqjvxyrp.js} +1 -1
  89. package/dist/v2/{server-317f3x9y.js → server-e3hc93wk.js} +5 -5
  90. package/dist/v2/{server-9zh78t8y.js → server-jj9qye8y.js} +1468 -73
  91. package/dist/v2/{server-fa7vtp40.js → server-nxas8v1d.js} +1 -1
  92. package/dist/v2/{server-vjer2jdn.js → server-txbc3czn.js} +9 -9
  93. package/dist/v2/{server-rqebawx1.js → server-v77xa5wj.js} +1 -1
  94. package/dist/v2/{server-jcsw05aa.js → server-xkvxss5g.js} +4 -4
  95. package/dist/v2/{server-hnmm8yzq.js → server-yqek3s4k.js} +1 -1
  96. package/dist/v2/server-z2n2xaeh.js +538 -0
  97. package/dist/v2/{server-nmwhe524.js → server-z3mk9jdc.js} +2 -2
  98. package/dist/v2/{server-w7x9wgm0.js → server-zmcrvpm3.js} +2 -2
  99. package/dist/v2/server.js +2 -2
  100. package/dist/v2/{storage-tags-q71rnr9f.js → storage-tags-18nbaanf.js} +2 -2
  101. package/dist/v2/store-reader.d.ts +0 -2
  102. package/dist/v2/store-reader.d.ts.map +1 -1
  103. package/dist/v2/{wrapup-orchestrator-gwww44st.js → wrapup-orchestrator-gjkszser.js} +14 -14
  104. package/dist/{wrapup-orchestrator-a9r8r4sk.js → wrapup-orchestrator-n5h5sr1x.js} +18 -18
  105. package/package.json +1 -1
  106. package/src/shared/write-transaction-attribution.test.ts +1 -6
  107. package/dist/index-40ma8m0c.js +0 -2251
  108. package/dist/message-index-ywx53y30.js +0 -61
  109. package/dist/v2/message-index-v6g8mgn7.js +0 -60
  110. package/dist/v2/server-k46ec388.js +0 -2220
@@ -6,6 +6,7 @@ import {
6
6
  getDataDir,
7
7
  ensureCortexKitArtifactGitignore,
8
8
  getProjectMagicContextHistorianDir,
9
+ getMagicContextStorageDir,
9
10
  sanitizeDiagnosticText,
10
11
  log2,
11
12
  sessionLog2
@@ -40,7 +41,7 @@ import {
40
41
  getProjectChunkEmbeddingModelId2,
41
42
  getProjectEmbeddingMaxInputTokens2,
42
43
  embedItemsForProject2
43
- } from "./server-hnmm8yzq.js";
44
+ } from "./server-yqek3s4k.js";
44
45
  import {
45
46
  hasMeaningfulUserText2,
46
47
  estimateTokens,
@@ -50,6 +51,7 @@ import {
50
51
  inRootAsyncContext2,
51
52
  Database2,
52
53
  getSqliteDatabasePath2,
54
+ prepareCachedStatement2,
53
55
  withSqliteBackgroundWriter2,
54
56
  withoutSqliteTransformPass2,
55
57
  beginSqliteWriterAsync2
@@ -61,7 +63,10 @@ import {
61
63
  RawOrdinalsNotReady2,
62
64
  dropRawSessionOrdinalCheckpoints2,
63
65
  runSessionWarmupWorker
64
- } from "./server-erk2bvdf.js";
66
+ } from "./server-6vd2n183.js";
67
+ import {
68
+ deleteUnmappedMessageFtsRows2
69
+ } from "./server-awr8qa4c.js";
65
70
  import {
66
71
  buildCanonicalChunkTextFromFts2,
67
72
  buildCompartmentSummaryFallbackText2,
@@ -71,26 +76,18 @@ import {
71
76
  replaceCompartmentChunkEmbeddings2,
72
77
  deleteChunkEmbedBackoffForSession2,
73
78
  chunkWindowSourceKey2
74
- } from "./server-7dpnt0ys.js";
79
+ } from "./server-4sn3at8p.js";
75
80
  import {
76
- isPidAlive
81
+ isPidAlive,
82
+ readProcessStartTime
77
83
  } from "./server-k3t06fxr.js";
78
84
  import {
79
- clearLkgFenceProcessState,
80
- lkgFenceRequiresRebuild,
81
- lkgRecoveryFenceUnclean,
82
- ownsLkgDirtyFence,
83
- commitLkgWithRecoveryFence,
84
- clearLkgRecoveryFence,
85
- gaDatabasePath,
86
- V2StoreReader,
87
85
  clearCompressionDepth,
88
86
  clearCompressionDepthRange,
89
- deleteSessionScopedRows,
90
- toMessageIndexSource2,
91
- clearIndexedMessagesInTransaction2,
92
- indexSourcesAfterOrdinal2
93
- } from "./server-k46ec388.js";
87
+ toMessageIndexSource,
88
+ clearIndexedMessagesInTransaction,
89
+ indexSourcesAfterOrdinal
90
+ } from "./server-z2n2xaeh.js";
94
91
  import {
95
92
  retreatPastHostUnservedRows,
96
93
  snapTerminalCompartmentToServedRow,
@@ -189,17 +186,22 @@ import {
189
186
  getRawSessionTagKeysThrough2,
190
187
  getLegacyProtectedTailStartOrdinal2,
191
188
  readSessionChunk2
192
- } from "./server-jcsw05aa.js";
189
+ } from "./server-xkvxss5g.js";
193
190
  import {
194
- getTableColumnNames
195
- } from "./server-rqebawx1.js";
191
+ getTableColumnNames,
192
+ tagTombstoneOwnerRange,
193
+ tagTombstoneOwnerKey,
194
+ tagRevisionKey,
195
+ tagIdentityRevisionKey,
196
+ deleteTagIdentityRevisions
197
+ } from "./server-v77xa5wj.js";
196
198
  import {
197
199
  FAIL_CLOSED_DOCTOR_COMMAND,
198
200
  getSchemaFenceRejection,
199
201
  LATEST_SUPPORTED_VERSION,
200
202
  getPersistedSchemaVersion,
201
203
  openDatabase
202
- } from "./server-317f3x9y.js";
204
+ } from "./server-e3hc93wk.js";
203
205
  import {
204
206
  providerMass,
205
207
  calibrationForModelKey,
@@ -217,7 +219,7 @@ import {
217
219
  foldShrunkPartTags2,
218
220
  getTagNumberByMessageId2,
219
221
  getActiveTagsBySession2
220
- } from "./server-fa7vtp40.js";
222
+ } from "./server-nxas8v1d.js";
221
223
  import {
222
224
  resolveOpenCodeDbPath,
223
225
  assertOpenCodeStoreGeneration,
@@ -232,7 +234,7 @@ import {
232
234
  import {
233
235
  BoundedSessionMap,
234
236
  getMeasuredToolDefinitionTokens
235
- } from "./server-7d6m1p2b.js";
237
+ } from "./server-cqjvxyrp.js";
236
238
  import {
237
239
  V2_MEMORY_CATEGORIES,
238
240
  CATEGORY_PRIORITY,
@@ -248,7 +250,7 @@ import {
248
250
  resolveStoredPathWorkspaceIdentity,
249
251
  sourceNameForMemory,
250
252
  computeWorkspaceEpochFingerprint
251
- } from "./server-wwaw5npa.js";
253
+ } from "./server-6g98c227.js";
252
254
  import {
253
255
  shouldSkipHomeProjectMemory,
254
256
  resolveProjectIdentity
@@ -261,7 +263,7 @@ import {
261
263
  userFacingFailureCode,
262
264
  promoteSessionFactsDurable,
263
265
  embedPromotedFacts
264
- } from "./server-nmwhe524.js";
266
+ } from "./server-z3mk9jdc.js";
265
267
  import {
266
268
  isMarkerCandidateBasisCurrent2,
267
269
  invalidateMarkerCandidateBasis2,
@@ -290,6 +292,9 @@ import {
290
292
  import {
291
293
  piModelRefToCanonical
292
294
  } from "./server-avwt563y.js";
295
+ import {
296
+ sameProjectDirectory
297
+ } from "./server-knvkbfvh.js";
293
298
  import {
294
299
  getErrorMessage,
295
300
  describeError
@@ -301,6 +306,13 @@ import {
301
306
  logSlowWriteTransaction,
302
307
  WriteTransactionSteps
303
308
  } from "./server-gyy4k6mf.js";
309
+ import {
310
+ ensurePrivateStorageDirectorySync,
311
+ writeStorageFileSync,
312
+ writeStorageFileAtomicSync,
313
+ syncStorageDirectorySync,
314
+ writeStorageFileDurableAtomicSync
315
+ } from "./server-fvnzcnww.js";
304
316
 
305
317
  // src/config/live-snapshot.ts
306
318
  import { createHash } from "node:crypto";
@@ -1010,10 +1022,10 @@ function readProjectDocsCanonical(projectDirectory) {
1010
1022
  return { renderedBlock, canonicalHash };
1011
1023
  }
1012
1024
  // src/hooks/magic-context/lkg-slot.ts
1013
- import { createHash as createHash5 } from "node:crypto";
1025
+ import { createHash as createHash8 } from "node:crypto";
1014
1026
 
1015
1027
  // src/hooks/magic-context/lkg-measured-request.ts
1016
- import { createHash as createHash3 } from "node:crypto";
1028
+ import { createHash as createHash6 } from "node:crypto";
1017
1029
 
1018
1030
  // src/shared/provider-response-completion.ts
1019
1031
  function providerResponseFailed(input) {
@@ -1030,6 +1042,430 @@ function isSuccessfulProviderCompletion(input) {
1030
1042
  // src/features/magic-context/storage-meta-session.ts
1031
1043
  import { Buffer as Buffer2 } from "node:buffer";
1032
1044
 
1045
+ // src/hooks/magic-context/lkg-recovery-fence.ts
1046
+ import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
1047
+ import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync4, rmdirSync, rmSync as rmSync2 } from "node:fs";
1048
+ import { basename, dirname, join as join2 } from "node:path";
1049
+
1050
+ // src/shared/storage-file-mutex.ts
1051
+ import { execFileSync } from "node:child_process";
1052
+ import { createHash as createHash3, randomUUID } from "node:crypto";
1053
+ import { readdirSync, readFileSync as readFileSync3, rmSync } from "node:fs";
1054
+ import { join } from "node:path";
1055
+ var ticketChecksum = (name, ticket) => createHash3("sha256").update(JSON.stringify([name, ticket.choosing, ticket.number, ticket.birth])).digest("hex");
1056
+ function processBirth(pid) {
1057
+ if (process.platform === "linux") {
1058
+ try {
1059
+ const stat = readFileSync3(`/proc/${pid}/stat`, "utf8");
1060
+ const ticks = stat.slice(stat.lastIndexOf(")") + 2).trim().split(/\s+/)[19];
1061
+ if (!ticks || !/^\d+$/.test(ticks))
1062
+ return null;
1063
+ return `${readFileSync3("/proc/sys/kernel/random/boot_id", "utf8").trim()}:${ticks}`;
1064
+ } catch {
1065
+ return null;
1066
+ }
1067
+ }
1068
+ if (process.platform === "darwin") {
1069
+ try {
1070
+ return execFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
1071
+ encoding: "utf8",
1072
+ timeout: 1000,
1073
+ windowsHide: true,
1074
+ env: { ...process.env, TZ: "UTC", LC_ALL: "C" },
1075
+ stdio: ["ignore", "pipe", "pipe"]
1076
+ }).trim() || null;
1077
+ } catch {
1078
+ return null;
1079
+ }
1080
+ }
1081
+ const start = readProcessStartTime(pid);
1082
+ return start === null ? null : String(start);
1083
+ }
1084
+ var pause = new Int32Array(new SharedArrayBuffer(4));
1085
+ function withStorageFileMutex(directory, work, timeoutMs = 1000) {
1086
+ ensurePrivateStorageDirectorySync(directory);
1087
+ const name = `${process.pid}-${randomUUID()}.lock`;
1088
+ const ownPath = join(directory, name);
1089
+ const birth = processBirth(process.pid);
1090
+ const ticket = { choosing: true, number: 0, birth, checksum: "" };
1091
+ const encodedTicket = () => JSON.stringify({ ...ticket, checksum: ticketChecksum(name, ticket) });
1092
+ for (let attempt = 0;; attempt++) {
1093
+ try {
1094
+ writeStorageFileSync(ownPath, encodedTicket(), { flag: "wx", forcePrivate: true });
1095
+ break;
1096
+ } catch (error) {
1097
+ if (error.code !== "ENOENT" || attempt >= 2)
1098
+ throw error;
1099
+ ensurePrivateStorageDirectorySync(directory);
1100
+ }
1101
+ }
1102
+ const deadline = performance.now() + timeoutMs;
1103
+ const peers = () => {
1104
+ const found = [];
1105
+ for (const other of readdirSync(directory)) {
1106
+ if (other === name || !/^\d+-[\da-f-]+\.lock$/.test(other))
1107
+ continue;
1108
+ const pid = Number(other.split("-")[0]);
1109
+ const otherPath = join(directory, other);
1110
+ let value = null;
1111
+ try {
1112
+ const parsed = JSON.parse(readFileSync3(otherPath, "utf8"));
1113
+ if (typeof parsed.choosing === "boolean" && Number.isSafeInteger(parsed.number) && parsed.number >= 0 && (parsed.birth === null || typeof parsed.birth === "string") && parsed.checksum === ticketChecksum(other, parsed))
1114
+ value = parsed;
1115
+ } catch (error) {
1116
+ if (error.code === "ENOENT")
1117
+ continue;
1118
+ }
1119
+ const alive = isPidAlive(pid);
1120
+ const actualBirth = alive === "alive" && value?.birth ? processBirth(pid) : null;
1121
+ if (alive === "dead" || actualBirth !== null && value?.birth && actualBirth !== value.birth) {
1122
+ rmSync(otherPath, { force: true });
1123
+ continue;
1124
+ }
1125
+ found.push([other, value]);
1126
+ }
1127
+ return found;
1128
+ };
1129
+ try {
1130
+ ticket.number = 1 + Math.max(0, ...peers().map(([, value]) => value?.number ?? 0));
1131
+ ticket.choosing = false;
1132
+ writeStorageFileAtomicSync(ownPath, encodedTicket(), true);
1133
+ while (peers().some(([other, value]) => !value || value.choosing || value.number < ticket.number || value.number === ticket.number && other < name)) {
1134
+ if (performance.now() >= deadline)
1135
+ throw new Error("Storage safety publication lock is unavailable");
1136
+ Atomics.wait(pause, 0, 0, 10);
1137
+ }
1138
+ const result = work();
1139
+ if (result && typeof result.then === "function")
1140
+ throw new TypeError("Storage publication mutex requires synchronous work");
1141
+ return result;
1142
+ } finally {
1143
+ rmSync(ownPath, { force: true });
1144
+ }
1145
+ }
1146
+
1147
+ // src/hooks/magic-context/lkg-recovery-fence.ts
1148
+ class LkgRecoveryFenceError extends Error {
1149
+ constructor(message) {
1150
+ super(message);
1151
+ this.name = "LkgRecoveryFenceError";
1152
+ }
1153
+ }
1154
+ var platform = process.platform;
1155
+ var observer;
1156
+ var knownFences = new BoundedSessionMap(1000);
1157
+ var ioObserver;
1158
+ var cacheKey = (sessionId) => `${getMagicContextStorageDir()}\x00${getHarness2()}\x00${sessionId}`;
1159
+ function remember(sessionId, value) {
1160
+ knownFences.set(cacheKey(sessionId), value);
1161
+ return value;
1162
+ }
1163
+ function known(sessionId) {
1164
+ const prior = knownFences.get(cacheKey(sessionId));
1165
+ if (prior)
1166
+ return prior;
1167
+ const record = read(sessionId);
1168
+ if (record)
1169
+ return remember(sessionId, { state: record.state, record });
1170
+ try {
1171
+ lstatSync2(lkgRecoveryFencePath(sessionId));
1172
+ } catch (error) {
1173
+ if (error.code === "ENOENT")
1174
+ return remember(sessionId, { state: "clean", record: null });
1175
+ }
1176
+ return remember(sessionId, { state: "invalid", record: null });
1177
+ }
1178
+ function clearLkgFenceProcessState(sessionId) {
1179
+ if (sessionId)
1180
+ knownFences.delete(cacheKey(sessionId));
1181
+ else
1182
+ knownFences.clear();
1183
+ }
1184
+ var durableFencesSupported = () => platform !== "win32";
1185
+ var hash = (value) => createHash4("sha256").update(value).digest("hex");
1186
+ var lkgServedArrayDigest = hash;
1187
+ function lkgRecoveryFencePath(sessionId) {
1188
+ return join2(getMagicContextStorageDir(), "lkg-recovery-fences", `${hash(sessionId)}.json`);
1189
+ }
1190
+ function metadata(slot) {
1191
+ return [
1192
+ slot.inputIdSeq,
1193
+ slot.inputContentDigests,
1194
+ slot.inputContentSignatures ?? null,
1195
+ slot.piOutputEntryIds ?? null,
1196
+ slot.lastInputMessageId,
1197
+ slot.modelKey,
1198
+ slot.providerKey
1199
+ ];
1200
+ }
1201
+ function representationKey(slot) {
1202
+ return createHash4("sha256").update(slot.jsonPrefix).update(JSON.stringify(metadata(slot))).digest("hex");
1203
+ }
1204
+ function lkgRecoverySlotKey(slot) {
1205
+ return hash(JSON.stringify([
1206
+ representationKey(slot),
1207
+ slot.capturedAt,
1208
+ slot.rowVersion ?? null,
1209
+ slot.captureSequence ?? null
1210
+ ]));
1211
+ }
1212
+ function payload(record) {
1213
+ return [
1214
+ record.version,
1215
+ record.sessionId,
1216
+ record.host,
1217
+ record.modelKey,
1218
+ record.providerKey,
1219
+ record.slotKey,
1220
+ record.servedDigest,
1221
+ record.revision,
1222
+ record.state
1223
+ ];
1224
+ }
1225
+ function publishRecord(record) {
1226
+ ioObserver?.("write");
1227
+ try {
1228
+ if (record.state === "clean")
1229
+ observer?.("clean");
1230
+ writeStorageFileDurableAtomicSync(lkgRecoveryFencePath(record.sessionId), JSON.stringify({ ...record, checksum: hash(JSON.stringify(payload(record))) }), () => observer?.("temp-synced"));
1231
+ if (record.state === "dirty")
1232
+ observer?.("dirty");
1233
+ remember(record.sessionId, {
1234
+ state: record.state,
1235
+ record: { ...record, checksum: hash(JSON.stringify(payload(record))) }
1236
+ });
1237
+ } catch (error) {
1238
+ const visible = read(record.sessionId);
1239
+ if (record.state === "clean" && visible?.state === "clean" && visible.revision === record.revision && visible.slotKey === record.slotKey) {
1240
+ const dirty = { ...record, state: "dirty" };
1241
+ writeStorageFileDurableAtomicSync(lkgRecoveryFencePath(record.sessionId), JSON.stringify({ ...dirty, checksum: hash(JSON.stringify(payload(dirty))) }));
1242
+ }
1243
+ remember(record.sessionId, { state: "invalid", record: null });
1244
+ throw error;
1245
+ }
1246
+ }
1247
+ function read(sessionId) {
1248
+ ioObserver?.("read");
1249
+ try {
1250
+ const path = lkgRecoveryFencePath(sessionId);
1251
+ const stat = lstatSync2(path);
1252
+ const directory = lstatSync2(dirname(path));
1253
+ if (!stat.isFile() || stat.size > 4096 || !directory.isDirectory() || directory.isSymbolicLink() || process.platform !== "win32" && ((stat.mode & 63) !== 0 || (directory.mode & 63) !== 0 || process.getuid && stat.uid !== process.getuid()))
1254
+ return null;
1255
+ const value = JSON.parse(readFileSync4(path, "utf8"));
1256
+ if (value.version !== 1 || value.sessionId !== sessionId || value.host !== getHarness2() || value.modelKey !== null && typeof value.modelKey !== "string" || value.providerKey !== null && typeof value.providerKey !== "string" || !/^[a-f0-9]{64}$/.test(value.slotKey) || !/^[a-f0-9]{64}$/.test(value.servedDigest) || typeof value.revision !== "string" || !["clean", "dirty"].includes(value.state) || value.checksum !== hash(JSON.stringify(payload(value))))
1257
+ return null;
1258
+ return value;
1259
+ } catch {
1260
+ return null;
1261
+ }
1262
+ }
1263
+ function publish(sessionId, slot, state, revision) {
1264
+ const record = {
1265
+ version: 1,
1266
+ sessionId,
1267
+ host: getHarness2(),
1268
+ modelKey: slot.modelKey,
1269
+ providerKey: slot.providerKey,
1270
+ slotKey: lkgRecoverySlotKey(slot),
1271
+ servedDigest: hash(slot.jsonPrefix),
1272
+ revision,
1273
+ state
1274
+ };
1275
+ publishRecord(record);
1276
+ }
1277
+ function locked(sessionId, work) {
1278
+ ioObserver?.("mutex");
1279
+ return withStorageFileMutex(`${lkgRecoveryFencePath(sessionId)}.locks`, () => {
1280
+ const path = lkgRecoveryFencePath(sessionId);
1281
+ for (const name of readdirSync2(dirname(path))) {
1282
+ if (name.startsWith(`${basename(path)}.`) && name.endsWith(".tmp"))
1283
+ rmSync2(join2(dirname(path), name), { force: true });
1284
+ }
1285
+ return work();
1286
+ });
1287
+ }
1288
+ function hasCleanLkgRecoveryFence(sessionId, _slot) {
1289
+ if (!durableFencesSupported())
1290
+ return false;
1291
+ const state = known(sessionId);
1292
+ return state.state === "clean";
1293
+ }
1294
+ function lkgFenceRequiresRebuild(sessionId, slot, processLocalProof) {
1295
+ return !processLocalProof && (durableFencesSupported() ? !hasCleanLkgRecoveryFence(sessionId, slot) : true);
1296
+ }
1297
+ function lkgRecoveryFenceUnclean(sessionId) {
1298
+ return durableFencesSupported() && known(sessionId).state !== "clean";
1299
+ }
1300
+ function dirtyLkgRecoveryRevision(sessionId, _slot) {
1301
+ if (!durableFencesSupported())
1302
+ return;
1303
+ const record = known(sessionId).record;
1304
+ return record?.state === "dirty" ? record.revision : undefined;
1305
+ }
1306
+ function ownsLkgDirtyFence(sessionId, revision) {
1307
+ if (!durableFencesSupported())
1308
+ return revision === "process-local";
1309
+ const record = known(sessionId).record;
1310
+ return revision !== undefined && record?.state === "dirty" && record.revision === revision;
1311
+ }
1312
+ function invalidateCleanLkgRecoveryFence(sessionId, load, ownRevision) {
1313
+ if (!durableFencesSupported())
1314
+ return "process-local";
1315
+ const prior = known(sessionId);
1316
+ if (prior.state === "dirty")
1317
+ return prior.record?.revision === ownRevision ? ownRevision : undefined;
1318
+ return locked(sessionId, () => {
1319
+ const slot = load() ?? {
1320
+ jsonPrefix: "",
1321
+ inputIdSeq: [],
1322
+ inputContentDigests: [],
1323
+ lastInputMessageId: "",
1324
+ modelKey: null,
1325
+ providerKey: null,
1326
+ capturedAt: 0
1327
+ };
1328
+ const record = read(sessionId);
1329
+ if (record?.state !== "dirty") {
1330
+ const revision = randomUUID2();
1331
+ publish(sessionId, slot, "dirty", revision);
1332
+ return revision;
1333
+ }
1334
+ return record?.state === "dirty" && record.revision === ownRevision ? ownRevision : undefined;
1335
+ });
1336
+ }
1337
+ function prepareLkgCaptureFence(args) {
1338
+ if (!durableFencesSupported())
1339
+ return "process-local";
1340
+ return locked(args.sessionId, () => {
1341
+ const before = read(args.sessionId);
1342
+ const owns = before?.state === "dirty" && before.revision === args.ownDirtyRevision;
1343
+ const unchangedBytes = before?.state === "clean" && before.servedDigest === hash(args.slot.jsonPrefix);
1344
+ if (!args.rebuild && before && !owns && !unchangedBytes && before.state !== "clean")
1345
+ throw new LkgRecoveryFenceError(`A concurrent recovery requires a declared prefix rebuild (state=${before?.state}, owned=${owns}, previous=${!!args.previousSlot}, bytes=${unchangedBytes})`);
1346
+ const revision = randomUUID2();
1347
+ if (before)
1348
+ publishRecord({ ...before, state: "dirty", revision });
1349
+ else
1350
+ publish(args.sessionId, args.previousSlot ?? args.slot, "dirty", revision);
1351
+ return revision;
1352
+ });
1353
+ }
1354
+ function certifyCommittedLkgCapture(args) {
1355
+ if (!durableFencesSupported())
1356
+ return false;
1357
+ const state = known(args.sessionId);
1358
+ if (state.state !== "dirty" || state.record?.revision !== args.revision)
1359
+ return false;
1360
+ return locked(args.sessionId, () => {
1361
+ const before = read(args.sessionId);
1362
+ if (before?.state !== "dirty" || before.revision !== args.revision)
1363
+ return false;
1364
+ const saved = args.load();
1365
+ if (!saved || representationKey(saved) !== representationKey(args.slot) || hash(saved.jsonPrefix) !== args.latestServedDigest)
1366
+ return false;
1367
+ publish(args.sessionId, saved, "clean", args.revision);
1368
+ return true;
1369
+ });
1370
+ }
1371
+ function markLkgRecoveryDirty(args) {
1372
+ if (!durableFencesSupported()) {
1373
+ if (!args.processLocalProof)
1374
+ throw new LkgRecoveryFenceError("Restart replay requires a healthy rebuild on Windows");
1375
+ return "process-local";
1376
+ }
1377
+ const state = known(args.sessionId);
1378
+ if (state.state === "dirty" && args.processLocalProof && state.record && state.record.revision === args.ownDirtyRevision)
1379
+ return state.record.revision;
1380
+ if (state.state === "invalid")
1381
+ throw new LkgRecoveryFenceError("No clean durable recovery certificate");
1382
+ return locked(args.sessionId, () => {
1383
+ const slot = args.slot;
1384
+ const before = read(args.sessionId);
1385
+ if (before?.state === "dirty") {
1386
+ if (!args.processLocalProof || before.revision !== args.ownDirtyRevision)
1387
+ throw new LkgRecoveryFenceError(`Recovery superseded this process's last-good request (local=${args.processLocalProof}, owned=${before.revision === args.ownDirtyRevision})`);
1388
+ return before.revision;
1389
+ }
1390
+ if (before && before.state !== "clean")
1391
+ throw new LkgRecoveryFenceError("No clean durable recovery certificate");
1392
+ const revision = randomUUID2();
1393
+ publish(args.sessionId, slot, "dirty", revision);
1394
+ return revision;
1395
+ });
1396
+ }
1397
+ function commitLkgWithRecoveryFence(args) {
1398
+ if (!durableFencesSupported())
1399
+ return args.commit();
1400
+ const state = known(args.sessionId);
1401
+ if (state.state === "clean" && !args.requiredRevision && !args.retainDirtyRevision) {
1402
+ const committed = args.commit();
1403
+ if (committed) {
1404
+ observer?.("committed");
1405
+ remember(args.sessionId, { state: "clean", record: null });
1406
+ }
1407
+ return committed;
1408
+ }
1409
+ if (state.state === "invalid" && !args.rebuild)
1410
+ throw new LkgRecoveryFenceError("Unproven prior request requires a prefix rebuild");
1411
+ return locked(args.sessionId, () => {
1412
+ const before = read(args.sessionId);
1413
+ if (args.requiredRevision && before?.revision !== args.requiredRevision)
1414
+ throw new LkgRecoveryFenceError("A later publisher superseded the rollback snapshot");
1415
+ const ownsDirty = before?.state === "dirty" && (before.revision === args.retainDirtyRevision || before.revision === args.ownDirtyRevision);
1416
+ if (before?.state === "dirty" && !ownsDirty && !args.rebuild)
1417
+ throw new LkgRecoveryFenceError("A concurrent recovery requires a declared prefix rebuild");
1418
+ if (before?.state !== "dirty" && state.state === "invalid")
1419
+ publish(args.sessionId, args.load() ?? args.slot, "dirty", randomUUID2());
1420
+ if (!args.commit())
1421
+ return false;
1422
+ observer?.("committed");
1423
+ const saved = args.load();
1424
+ if (!saved || representationKey(saved) !== representationKey(args.slot))
1425
+ throw new LkgRecoveryFenceError("Last-good commit did not match its certificate");
1426
+ if (args.retainDirtyRevision || args.cleanDigest !== undefined && hash(saved.jsonPrefix) !== args.cleanDigest)
1427
+ return true;
1428
+ const dirty = read(args.sessionId);
1429
+ if (dirty?.state === "dirty")
1430
+ publish(args.sessionId, saved, "clean", dirty.revision);
1431
+ else
1432
+ remember(args.sessionId, { state: "clean", record: null });
1433
+ return true;
1434
+ });
1435
+ }
1436
+ function clearLkgRecoveryFence(sessionId, remove, shouldClear) {
1437
+ if (!durableFencesSupported())
1438
+ return remove?.();
1439
+ const path = lkgRecoveryFencePath(sessionId);
1440
+ const missing = (file) => {
1441
+ try {
1442
+ lstatSync2(file);
1443
+ return false;
1444
+ } catch (error) {
1445
+ return error.code === "ENOENT";
1446
+ }
1447
+ };
1448
+ if (!remove && !shouldClear && missing(path) && missing(`${path}.locks`)) {
1449
+ clearLkgFenceProcessState(sessionId);
1450
+ return;
1451
+ }
1452
+ try {
1453
+ return locked(sessionId, () => {
1454
+ const result = remove?.();
1455
+ if (shouldClear && !shouldClear(result))
1456
+ return result;
1457
+ rmSync2(lkgRecoveryFencePath(sessionId), { force: true });
1458
+ syncStorageDirectorySync(dirname(lkgRecoveryFencePath(sessionId)));
1459
+ clearLkgFenceProcessState(sessionId);
1460
+ return result;
1461
+ });
1462
+ } finally {
1463
+ try {
1464
+ rmdirSync(`${path}.locks`);
1465
+ } catch {}
1466
+ }
1467
+ }
1468
+
1033
1469
  // src/shared/auto-search-lifecycle.ts
1034
1470
  var pending = new Map;
1035
1471
  var unpublishedNoHints = new Map;
@@ -1081,6 +1517,709 @@ function cancelAutoSearchWork(sessionId) {
1081
1517
  }
1082
1518
  }
1083
1519
 
1520
+ // src/v2/store-reader.ts
1521
+ import { createHash as createHash5 } from "node:crypto";
1522
+ import { statSync as statSync3 } from "node:fs";
1523
+ import { hostname } from "node:os";
1524
+ import { resolve } from "node:path";
1525
+ function gaDatabasePath(dataHome, channel = "latest", env = process.env) {
1526
+ return resolveOpenCodeDbPath("v2", { dataHome, channel, env }).path;
1527
+ }
1528
+ var RAW_MESSAGE_TYPES = [
1529
+ "user",
1530
+ "synthetic",
1531
+ "assistant",
1532
+ "skill",
1533
+ "shell",
1534
+ "system"
1535
+ ];
1536
+ var RAW_MESSAGE_TYPE_PARAMETERS = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
1537
+ var V2_MESSAGE_PAGE_SQL = `WITH bounds AS (
1538
+ SELECT
1539
+ CASE WHEN ? = 0 THEN -1 ELSE COALESCE((
1540
+ SELECT seq FROM session_message
1541
+ WHERE session_id = ? AND type IN (${RAW_MESSAGE_TYPE_PARAMETERS})
1542
+ ORDER BY seq ASC LIMIT 1 OFFSET ?
1543
+ ), (SELECT MAX(seq) FROM session_message WHERE session_id = ?), -1) END AS after_seq,
1544
+ COALESCE((
1545
+ SELECT seq FROM session_message
1546
+ WHERE session_id = ? AND type IN (${RAW_MESSAGE_TYPE_PARAMETERS})
1547
+ ORDER BY seq ASC LIMIT 1 OFFSET ?
1548
+ ), ?) AS watermark_seq
1549
+ )
1550
+ SELECT id, session_id, type, seq, time_created, data FROM session_message, bounds
1551
+ WHERE session_id = ?
1552
+ AND type IN (${RAW_MESSAGE_TYPE_PARAMETERS})
1553
+ AND seq > bounds.after_seq
1554
+ AND seq <= bounds.watermark_seq
1555
+ ORDER BY seq ASC LIMIT ?`;
1556
+ var V2_STORE_READER_DEBUG_COUNTER_KEY = "magic-context.v2.store-reader-debug";
1557
+ var debugSymbol = Symbol.for(V2_STORE_READER_DEBUG_COUNTER_KEY);
1558
+ var debugGlobal = globalThis;
1559
+ var QUERY_STATEMENTS = {
1560
+ messagePage: V2_MESSAGE_PAGE_SQL,
1561
+ messageCount: "SELECT COUNT(*) AS count FROM session_message WHERE session_id = ? AND type IN (?)",
1562
+ storedMessageCount: "SELECT COUNT(*) AS count FROM session_message WHERE session_id = ?",
1563
+ messageById: "SELECT id, session_id, type, seq, time_created, data FROM session_message WHERE session_id = ? AND id = ? AND type IN (?) LIMIT 1",
1564
+ messageExistsById: "SELECT 1 FROM session_message WHERE id = ? AND session_id = ? AND type IN (?) LIMIT 1",
1565
+ messageOrdinalById: `WITH target AS (
1566
+ SELECT seq FROM session_message WHERE session_id = ? AND id = ? AND type IN (?) LIMIT 1
1567
+ )
1568
+ SELECT (SELECT COUNT(*) FROM session_message WHERE session_id = ? AND type IN (?) AND seq <= target.seq) AS ordinal FROM target`,
1569
+ messageIdOrdinals: "SELECT id FROM session_message WHERE session_id = ? AND type IN (?) ORDER BY seq ASC LIMIT ? OFFSET ?",
1570
+ messageOrdinalPage: "SELECT id, type, seq, json_valid(data) AS valid FROM session_message WHERE session_id = ? AND seq > ? ORDER BY seq ASC, id ASC LIMIT ?",
1571
+ rawRowsThrough: "SELECT id, session_id, type, seq, time_created, data FROM session_message WHERE session_id = ? AND type IN (?) AND seq <= ? ORDER BY seq DESC LIMIT ?"
1572
+ };
1573
+ function debugCounters() {
1574
+ const counters = debugGlobal[debugSymbol] ??= {
1575
+ decodedRows: 0,
1576
+ operations: {},
1577
+ openReaders: 0,
1578
+ maxOpenReaders: 0,
1579
+ readersOpened: 0,
1580
+ readersClosed: 0
1581
+ };
1582
+ counters.openReaders ??= 0;
1583
+ counters.maxOpenReaders ??= 0;
1584
+ counters.readersOpened ??= 0;
1585
+ counters.readersClosed ??= 0;
1586
+ return counters;
1587
+ }
1588
+ function returnedRowCount(value) {
1589
+ if (Array.isArray(value))
1590
+ return value.length;
1591
+ if (value === null || value === undefined || value === false)
1592
+ return 0;
1593
+ return 1;
1594
+ }
1595
+ function trackDecodeOperation(name, operation) {
1596
+ const counters = debugCounters();
1597
+ const before = counters.decodedRows;
1598
+ const started = performance.now();
1599
+ let value;
1600
+ try {
1601
+ value = operation();
1602
+ return value;
1603
+ } finally {
1604
+ const decodedRows = counters.decodedRows - before;
1605
+ const current = counters.operations[name] ?? {
1606
+ calls: 0,
1607
+ decodedRows: 0,
1608
+ maxDecodedRows: 0
1609
+ };
1610
+ current.calls += 1;
1611
+ current.decodedRows += decodedRows;
1612
+ current.maxDecodedRows = Math.max(current.maxDecodedRows, decodedRows);
1613
+ counters.operations[name] = current;
1614
+ const statement = QUERY_STATEMENTS[name];
1615
+ if (counters.captureQueries && statement) {
1616
+ (counters.queries ??= []).push({
1617
+ operation: name,
1618
+ statement,
1619
+ rows: returnedRowCount(value),
1620
+ elapsedMs: performance.now() - started
1621
+ });
1622
+ }
1623
+ }
1624
+ }
1625
+ function decode(row) {
1626
+ debugCounters().decodedRows += 1;
1627
+ const data = JSON.parse(row.data);
1628
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
1629
+ throw new Error(`Invalid session_message data at seq ${row.seq}`);
1630
+ }
1631
+ if (row.type === "idle" && !["succeeded", "failed", "interrupted"].includes(String(data.outcome))) {
1632
+ throw new Error(`Invalid idle outcome at seq ${row.seq}`);
1633
+ }
1634
+ return { ...row, data };
1635
+ }
1636
+ function connect(path, identity = "") {
1637
+ const stat = statSync3(path);
1638
+ const acquiredIdentity = identity || `${stat.dev}:${stat.ino}:${stat.birthtimeMs}`;
1639
+ const db = new Database2(path, { readonly: true, fileMustExist: true });
1640
+ try {
1641
+ assertOpenCodeStoreGeneration(db, "v2", path);
1642
+ } catch (error) {
1643
+ db.close();
1644
+ throw error;
1645
+ }
1646
+ const counters = debugCounters();
1647
+ counters.openReaders += 1;
1648
+ counters.readersOpened += 1;
1649
+ counters.maxOpenReaders = Math.max(counters.maxOpenReaders, counters.openReaders);
1650
+ return { db, statements: new Map, identity: acquiredIdentity, leases: 0, retired: false };
1651
+ }
1652
+ function closeConnection(connection) {
1653
+ connection.statements.clear();
1654
+ try {
1655
+ connection.db.close();
1656
+ } finally {
1657
+ const counters = debugCounters();
1658
+ counters.openReaders = Math.max(0, counters.openReaders - 1);
1659
+ counters.readersClosed += 1;
1660
+ }
1661
+ }
1662
+
1663
+ class V2StoreReaderPool {
1664
+ capacity;
1665
+ connections = new Map;
1666
+ closed = false;
1667
+ closing = false;
1668
+ holds = 0;
1669
+ idleWaiters = new Set;
1670
+ constructor(capacity = 4) {
1671
+ this.capacity = capacity;
1672
+ if (!Number.isSafeInteger(capacity) || capacity < 1)
1673
+ throw new Error("Invalid reader capacity");
1674
+ }
1675
+ open(path) {
1676
+ return new V2StoreReader(path, this);
1677
+ }
1678
+ acquire(path) {
1679
+ if (this.closed)
1680
+ throw new Error("Store reader pool is closed");
1681
+ const key = resolve(path);
1682
+ const stat = statSync3(key);
1683
+ const identity = `${stat.dev}:${stat.ino}:${stat.birthtimeMs}`;
1684
+ let connection = this.connections.get(key);
1685
+ if (connection && connection.identity !== identity) {
1686
+ this.connections.delete(key);
1687
+ this.retire(connection);
1688
+ connection = undefined;
1689
+ }
1690
+ if (!connection)
1691
+ connection = connect(key, identity);
1692
+ connection.leases++;
1693
+ this.connections.delete(key);
1694
+ this.connections.set(key, connection);
1695
+ while (this.connections.size > this.capacity) {
1696
+ const oldest = this.connections.entries().next().value;
1697
+ if (!oldest)
1698
+ break;
1699
+ this.connections.delete(oldest[0]);
1700
+ this.retire(oldest[1]);
1701
+ }
1702
+ return connection;
1703
+ }
1704
+ release(connection) {
1705
+ connection.leases--;
1706
+ if (connection.retired && connection.leases === 0)
1707
+ closeConnection(connection);
1708
+ }
1709
+ retire(connection) {
1710
+ connection.retired = true;
1711
+ if (connection.leases === 0)
1712
+ closeConnection(connection);
1713
+ }
1714
+ hold() {
1715
+ if (this.closed || this.closing)
1716
+ throw new Error("Store reader pool is closed");
1717
+ this.holds++;
1718
+ let released = false;
1719
+ return () => {
1720
+ if (released)
1721
+ return;
1722
+ released = true;
1723
+ this.holds--;
1724
+ if (this.holds === 0 && this.closing)
1725
+ this.finishClose();
1726
+ };
1727
+ }
1728
+ isClosed() {
1729
+ return this.closed;
1730
+ }
1731
+ holdCount() {
1732
+ return this.holds;
1733
+ }
1734
+ close() {
1735
+ if (this.closed || this.closing)
1736
+ return;
1737
+ this.closing = true;
1738
+ if (this.holds === 0)
1739
+ this.finishClose();
1740
+ }
1741
+ async closeWhenIdle(timeoutMs) {
1742
+ this.close();
1743
+ if (this.closed)
1744
+ return true;
1745
+ let timer;
1746
+ let waiter;
1747
+ try {
1748
+ await new Promise((resolve) => {
1749
+ waiter = resolve;
1750
+ this.idleWaiters.add(resolve);
1751
+ timer = setTimeout(resolve, Math.max(0, timeoutMs));
1752
+ });
1753
+ } finally {
1754
+ if (timer)
1755
+ clearTimeout(timer);
1756
+ if (waiter)
1757
+ this.idleWaiters.delete(waiter);
1758
+ }
1759
+ return this.closed;
1760
+ }
1761
+ finishClose() {
1762
+ if (this.closed)
1763
+ return;
1764
+ this.closed = true;
1765
+ for (const connection of this.connections.values())
1766
+ this.retire(connection);
1767
+ this.connections.clear();
1768
+ for (const resolve of this.idleWaiters)
1769
+ resolve();
1770
+ this.idleWaiters.clear();
1771
+ }
1772
+ }
1773
+ function messageTimesQuery(count) {
1774
+ return `SELECT id, COALESCE(time_created, json_extract(data, '$.time.created')) AS created,
1775
+ json_extract(data, '$.time.completed') AS completed
1776
+ FROM session_message WHERE +session_id = ? AND id IN (${Array.from({ length: count }, () => "?").join(",")})`;
1777
+ }
1778
+
1779
+ class V2StoreReader {
1780
+ path;
1781
+ pool;
1782
+ db;
1783
+ connection;
1784
+ closed = false;
1785
+ constructor(path, pool) {
1786
+ this.path = path;
1787
+ this.pool = pool;
1788
+ this.connection = pool ? pool.acquire(path) : connect(path);
1789
+ this.db = this.connection.db;
1790
+ }
1791
+ hostIdentity() {
1792
+ return createHash5("sha256").update(JSON.stringify([hostname(), resolve(this.path), this.connection.identity])).digest("hex");
1793
+ }
1794
+ prepare(sql) {
1795
+ if (this.closed)
1796
+ throw new Error("Store reader is closed");
1797
+ const statements = this.connection.statements;
1798
+ let statement = statements.get(sql);
1799
+ if (!statement) {
1800
+ statement = this.db.prepare(sql);
1801
+ if (statements.size >= 128)
1802
+ statements.clear();
1803
+ statements.set(sql, statement);
1804
+ }
1805
+ return statement;
1806
+ }
1807
+ close() {
1808
+ if (this.closed)
1809
+ return;
1810
+ this.closed = true;
1811
+ if (this.pool)
1812
+ this.pool.release(this.connection);
1813
+ else
1814
+ closeConnection(this.connection);
1815
+ }
1816
+ page(sessionID, options = {}) {
1817
+ return trackDecodeOperation("page", () => {
1818
+ const limit = options.limit ?? 100;
1819
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e4)
1820
+ throw new Error("Invalid page limit");
1821
+ const after = options.after ?? -1;
1822
+ if (!Number.isSafeInteger(after))
1823
+ throw new Error("Invalid seq cursor");
1824
+ if (options.through !== undefined && !Number.isSafeInteger(options.through))
1825
+ throw new Error("Invalid seq upper bound");
1826
+ const predicates = ["session_id = ?", "seq > ?"];
1827
+ const parameters = [sessionID, after];
1828
+ if (options.through !== undefined) {
1829
+ predicates.push("seq <= ?");
1830
+ parameters.push(options.through);
1831
+ }
1832
+ if (options.type) {
1833
+ predicates.push("type = ?");
1834
+ parameters.push(options.type);
1835
+ }
1836
+ const rows = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
1837
+ WHERE ${predicates.join(" AND ")}
1838
+ ORDER BY seq ASC LIMIT ?`).all(...parameters, limit).map(decode);
1839
+ return { rows, cursor: rows.at(-1)?.seq };
1840
+ });
1841
+ }
1842
+ messagePage(sessionID, afterOrdinal, limit, finalWatermark, after) {
1843
+ return trackDecodeOperation("messagePage", () => {
1844
+ if (!Number.isSafeInteger(afterOrdinal) || afterOrdinal < 0)
1845
+ throw new Error("Invalid raw-message ordinal cursor");
1846
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e4)
1847
+ throw new Error("Invalid page limit");
1848
+ if (!Number.isSafeInteger(finalWatermark) || finalWatermark < 0)
1849
+ throw new Error("Invalid raw-message watermark");
1850
+ const pageSize = Math.min(limit, finalWatermark - afterOrdinal);
1851
+ if (pageSize <= 0)
1852
+ return [];
1853
+ if (after) {
1854
+ const anchor = this.prepare("SELECT seq FROM session_message WHERE session_id = ? AND id = ?").get(sessionID, after.id);
1855
+ if (anchor) {
1856
+ return this.prepare(`SELECT id, session_id, type, seq, time_created, data
1857
+ FROM session_message WHERE session_id = ? AND seq > ?
1858
+ AND type IN (${RAW_MESSAGE_TYPE_PARAMETERS}) ORDER BY seq ASC LIMIT ?`).all(sessionID, anchor.seq, ...RAW_MESSAGE_TYPES, pageSize).map(decode);
1859
+ }
1860
+ }
1861
+ const maximumSeq = Number.MAX_SAFE_INTEGER;
1862
+ const rows = this.prepare(V2_MESSAGE_PAGE_SQL).all(afterOrdinal, sessionID, ...RAW_MESSAGE_TYPES, Math.max(0, afterOrdinal - 1), sessionID, sessionID, ...RAW_MESSAGE_TYPES, finalWatermark - 1, maximumSeq, sessionID, ...RAW_MESSAGE_TYPES, pageSize);
1863
+ return rows.map(decode);
1864
+ });
1865
+ }
1866
+ messageCount(sessionID) {
1867
+ return trackDecodeOperation("messageCount", () => {
1868
+ const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
1869
+ const row = this.prepare(`SELECT COUNT(*) AS count FROM session_message
1870
+ WHERE session_id = ? AND type IN (${rawTypes})`).get(sessionID, ...RAW_MESSAGE_TYPES);
1871
+ return typeof row?.count === "number" ? row.count : 0;
1872
+ });
1873
+ }
1874
+ messageCountAfterSequence(sessionID, after, through) {
1875
+ const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
1876
+ const row = this.prepare(`SELECT COUNT(*) AS count FROM session_message
1877
+ WHERE session_id = ? AND seq > ? AND seq <= ? AND type IN (${rawTypes})`).get(sessionID, after, through, ...RAW_MESSAGE_TYPES);
1878
+ return typeof row?.count === "number" ? row.count : 0;
1879
+ }
1880
+ sessionDirectoryPage(afterSessionID, limit) {
1881
+ const rows = this.prepare(`SELECT id, COALESCE(directory, '') AS directory FROM session_v2
1882
+ WHERE id > ? ORDER BY id ASC LIMIT ?`).all(afterSessionID ?? "", limit);
1883
+ return rows.map((row) => ({ sessionId: row.id, directory: row.directory }));
1884
+ }
1885
+ latestMessageTime(sessionID) {
1886
+ const row = this.prepare("SELECT MAX(time_created) AS time FROM session_message WHERE session_id = ?").get(sessionID);
1887
+ return row?.time ?? undefined;
1888
+ }
1889
+ isSubagent(sessionID) {
1890
+ const row = this.prepare("SELECT parent_id FROM session_v2 WHERE id = ?").get(sessionID);
1891
+ if (!row)
1892
+ return null;
1893
+ return typeof row.parent_id === "string" && row.parent_id.length > 0;
1894
+ }
1895
+ latestRootSessionInDirectory(directory) {
1896
+ const columns = new Set(this.prepare("PRAGMA table_info(session_v2)").all().map((column) => column.name));
1897
+ const archived = columns.has("time_archived") ? " AND time_archived IS NULL" : "";
1898
+ const order = columns.has("time_updated") ? "time_updated DESC, id DESC" : "id DESC";
1899
+ const page = this.prepare(`SELECT id, COALESCE(directory, '') AS directory FROM session_v2
1900
+ WHERE parent_id IS NULL${archived}
1901
+ AND COALESCE(json_extract(metadata, '$.magic_context'), '') <> 'hidden-run'
1902
+ ORDER BY ${order} LIMIT ? OFFSET ?`);
1903
+ const pageSize = 500;
1904
+ for (let offset = 0;; offset += pageSize) {
1905
+ const rows = page.all(pageSize, offset);
1906
+ const match = rows.find((row) => sameProjectDirectory(row.directory, directory));
1907
+ if (match)
1908
+ return match.id;
1909
+ if (rows.length < pageSize)
1910
+ return;
1911
+ }
1912
+ }
1913
+ rootSessionActivity(sessionIDs) {
1914
+ const roots = new Map;
1915
+ for (let offset = 0;offset < sessionIDs.length; offset += 500) {
1916
+ const chunk = sessionIDs.slice(offset, offset + 500);
1917
+ const rows = this.prepare(`SELECT id, (
1918
+ SELECT MAX(time_created) FROM session_message
1919
+ WHERE session_id = session_v2.id AND type = 'user'
1920
+ ) AS time FROM session_v2
1921
+ WHERE parent_id IS NULL
1922
+ AND COALESCE(json_extract(metadata, '$.magic_context'), '') <> 'hidden-run'
1923
+ AND id IN (${chunk.map(() => "?").join(",")})`).all(...chunk);
1924
+ for (const row of rows)
1925
+ if (row.time !== null)
1926
+ roots.set(row.id, row.time);
1927
+ }
1928
+ return roots;
1929
+ }
1930
+ oldestUserMessageTimesSince(sessionIDs, sinceMs) {
1931
+ const result = new Map;
1932
+ for (let offset = 0;offset < sessionIDs.length; offset += 500) {
1933
+ const chunk = sessionIDs.slice(offset, offset + 500);
1934
+ const rows = this.prepare(`SELECT session_id, MIN(time_created) AS time FROM session_message
1935
+ WHERE type = 'user' AND time_created > ? AND session_id IN (${chunk.map(() => "?").join(",")})
1936
+ GROUP BY session_id`).all(sinceMs, ...chunk);
1937
+ for (const row of rows)
1938
+ result.set(row.session_id, row.time);
1939
+ }
1940
+ return result;
1941
+ }
1942
+ retrospectiveUserPage(sessionID, options) {
1943
+ const { boundaryMs, before, limit, maxChars, truncationMarker } = options;
1944
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e4)
1945
+ throw new Error("Invalid page limit");
1946
+ if (!Number.isSafeInteger(maxChars) || maxChars <= truncationMarker.length)
1947
+ throw new Error("Invalid text limit");
1948
+ const direction = before ? "DESC" : "ASC";
1949
+ const head = Math.floor((maxChars - truncationMarker.length) / 2);
1950
+ const tail = maxChars - truncationMarker.length - head;
1951
+ return this.prepare(`WITH users AS (
1952
+ SELECT session_id, seq, time_created, data FROM session_message
1953
+ WHERE session_id = ? AND type = 'user' AND time_created ${before ? "<=" : ">"}
1954
+ ?
1955
+ ORDER BY time_created ${direction}, seq ${direction} LIMIT ?
1956
+ ), texts AS (
1957
+ SELECT session_id, seq, time_created, CASE
1958
+ WHEN json_extract(data, '$.synthetic') = 1 OR json_extract(data, '$.ignored') = 1 THEN ''
1959
+ WHEN json_type(data, '$.text') = 'text' THEN json_extract(data, '$.text')
1960
+ ELSE COALESCE((SELECT group_concat(json_extract(value, '$.text'), char(10))
1961
+ FROM json_each(users.data, '$.content')
1962
+ WHERE json_extract(value, '$.type') IN ('text', 'input_text')
1963
+ AND COALESCE(json_extract(value, '$.synthetic'), 0) <> 1
1964
+ AND COALESCE(json_extract(value, '$.ignored'), 0) <> 1), '') END AS text
1965
+ FROM users WHERE json_valid(data)
1966
+ ) SELECT seq, time_created, CASE WHEN length(text) > ?
1967
+ THEN substr(text, 1, ?) || ? || substr(text, -?) ELSE text END AS text,
1968
+ EXISTS (
1969
+ SELECT 1 FROM session_message assistant_reply
1970
+ WHERE assistant_reply.session_id = texts.session_id
1971
+ AND assistant_reply.type = 'assistant'
1972
+ AND assistant_reply.seq < texts.seq
1973
+ AND EXISTS (
1974
+ SELECT 1 FROM session_message prior_user
1975
+ WHERE prior_user.session_id = texts.session_id
1976
+ AND prior_user.type = 'user'
1977
+ AND prior_user.seq < assistant_reply.seq
1978
+ )
1979
+ ) AS follows_assistant_reply
1980
+ FROM texts ORDER BY time_created ${direction}, seq ${direction}`).all(sessionID, boundaryMs, limit, maxChars, head, truncationMarker, tail);
1981
+ }
1982
+ storedRowsAfter(sessionID, after) {
1983
+ const row = this.prepare("SELECT COUNT(*) AS count FROM session_message WHERE session_id = ? AND seq > ?").get(sessionID, after);
1984
+ return row.count;
1985
+ }
1986
+ storedMessageCount(sessionID) {
1987
+ return trackDecodeOperation("storedMessageCount", () => {
1988
+ const row = this.prepare("SELECT COUNT(*) AS count FROM session_message WHERE session_id = ?").get(sessionID);
1989
+ return typeof row?.count === "number" ? row.count : 0;
1990
+ });
1991
+ }
1992
+ messageById(sessionID, id) {
1993
+ return trackDecodeOperation("messageById", () => {
1994
+ const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
1995
+ const row = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
1996
+ WHERE session_id = ? AND id = ? AND type IN (${rawTypes}) LIMIT 1`).get(sessionID, id, ...RAW_MESSAGE_TYPES);
1997
+ return row ? decode(row) : null;
1998
+ });
1999
+ }
2000
+ messageTimes(sessionID, ids) {
2001
+ const times = new Map;
2002
+ for (let offset = 0;offset < ids.length; offset += 500) {
2003
+ const batch = ids.slice(offset, offset + 500);
2004
+ const rows = this.prepare(messageTimesQuery(batch.length)).all(sessionID, ...batch);
2005
+ for (const row of rows)
2006
+ times.set(row.id, {
2007
+ created: typeof row.created === "number" ? row.created : undefined,
2008
+ completed: typeof row.completed === "number" ? row.completed : undefined
2009
+ });
2010
+ }
2011
+ return times;
2012
+ }
2013
+ messageExistsById(sessionID, id) {
2014
+ return trackDecodeOperation("messageExistsById", () => {
2015
+ const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
2016
+ const row = this.prepare(`SELECT 1 FROM session_message
2017
+ WHERE id = ? AND session_id = ? AND type IN (${rawTypes}) LIMIT 1`).get(id, sessionID, ...RAW_MESSAGE_TYPES);
2018
+ return row != null;
2019
+ });
2020
+ }
2021
+ messageOrdinalById(sessionID, id) {
2022
+ return trackDecodeOperation("messageOrdinalById", () => {
2023
+ const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
2024
+ const row = this.prepare(`WITH target AS (
2025
+ SELECT seq FROM session_message
2026
+ WHERE session_id = ? AND id = ? AND type IN (${rawTypes})
2027
+ LIMIT 1
2028
+ )
2029
+ SELECT (
2030
+ SELECT COUNT(*) FROM session_message
2031
+ WHERE session_id = ?
2032
+ AND type IN (${rawTypes})
2033
+ AND seq <= target.seq
2034
+ ) AS ordinal
2035
+ FROM target`).get(sessionID, id, ...RAW_MESSAGE_TYPES, sessionID, ...RAW_MESSAGE_TYPES);
2036
+ return typeof row?.ordinal === "number" ? row.ordinal : null;
2037
+ });
2038
+ }
2039
+ messageIdOrdinals(sessionID, fromOrdinal, toOrdinal) {
2040
+ return trackDecodeOperation("messageIdOrdinals", () => {
2041
+ if (!Number.isSafeInteger(fromOrdinal) || fromOrdinal < 1)
2042
+ throw new Error("Invalid raw-message range start");
2043
+ if (!Number.isSafeInteger(toOrdinal) || toOrdinal < fromOrdinal)
2044
+ throw new Error("Invalid raw-message range end");
2045
+ const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
2046
+ const rows = this.prepare(`SELECT id FROM session_message
2047
+ WHERE session_id = ? AND type IN (${rawTypes})
2048
+ ORDER BY seq ASC LIMIT ? OFFSET ?`).all(sessionID, ...RAW_MESSAGE_TYPES, toOrdinal - fromOrdinal + 1, fromOrdinal - 1);
2049
+ return new Map(rows.map((row, index) => [row.id, fromOrdinal + index]));
2050
+ });
2051
+ }
2052
+ messageOrdinalPage(sessionID, after, limit) {
2053
+ return trackDecodeOperation("messageOrdinalPage", () => {
2054
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e4)
2055
+ throw new Error("Invalid page limit");
2056
+ const rows = after ? this.prepare(`SELECT id, type, seq, json_valid(data) AS valid
2057
+ FROM session_message
2058
+ WHERE session_id = ? AND (seq > ? OR (seq = ? AND id > ?))
2059
+ ORDER BY seq ASC, id ASC LIMIT ?`).all(sessionID, after.timeCreated, after.timeCreated, after.id, limit) : this.prepare(`SELECT id, type, seq, json_valid(data) AS valid
2060
+ FROM session_message
2061
+ WHERE session_id = ?
2062
+ ORDER BY seq ASC, id ASC LIMIT ?`).all(sessionID, limit);
2063
+ const rawTypes = new Set(RAW_MESSAGE_TYPES);
2064
+ return rows.map((row) => ({
2065
+ id: row.id,
2066
+ timeCreated: row.seq,
2067
+ contributesOrdinal: rawTypes.has(row.type),
2068
+ hasValidInfo: row.valid === 1
2069
+ }));
2070
+ });
2071
+ }
2072
+ range(sessionID, after, through) {
2073
+ return trackDecodeOperation("range", () => through <= after ? [] : this.all(sessionID, after, undefined, through));
2074
+ }
2075
+ spanRowStamps(sessionID, after, through) {
2076
+ if (!Number.isSafeInteger(after) || !Number.isSafeInteger(through))
2077
+ throw new Error("Invalid seq span");
2078
+ const rows = this.prepare(`SELECT seq, id, time_updated AS updated, length(CAST(data AS BLOB)) AS bytes
2079
+ FROM session_message WHERE session_id = ? AND seq > ? AND seq <= ?
2080
+ ORDER BY seq ASC`).all(sessionID, after, through);
2081
+ const stamps = new Map;
2082
+ for (const row of rows)
2083
+ stamps.set(row.seq, `${row.id}\x00${row.updated ?? ""}\x00${row.bytes ?? ""}`);
2084
+ return stamps;
2085
+ }
2086
+ rawRowsThrough(sessionID, throughSeq, limit) {
2087
+ return trackDecodeOperation("rawRowsThrough", () => {
2088
+ if (!Number.isSafeInteger(throughSeq))
2089
+ throw new Error("Invalid seq upper bound");
2090
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e4)
2091
+ throw new Error("Invalid page limit");
2092
+ const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
2093
+ return this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
2094
+ WHERE session_id = ? AND type IN (${rawTypes}) AND seq <= ?
2095
+ ORDER BY seq DESC LIMIT ?`).all(sessionID, ...RAW_MESSAGE_TYPES, throughSeq, limit).map(decode);
2096
+ });
2097
+ }
2098
+ instructionRowsThrough(sessionID, throughSeq) {
2099
+ return trackDecodeOperation("instructionRowsThrough", () => {
2100
+ if (!Number.isSafeInteger(throughSeq))
2101
+ throw new Error("Invalid seq upper bound");
2102
+ return this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
2103
+ WHERE session_id = ? AND type = 'system' AND seq <= ?
2104
+ ORDER BY seq ASC`).all(sessionID, throughSeq).map(decode);
2105
+ });
2106
+ }
2107
+ sequenceForId(sessionID, id) {
2108
+ if (!id)
2109
+ return;
2110
+ const row = this.prepare("SELECT seq FROM session_message WHERE session_id = ? AND id = ? LIMIT 1").get(sessionID, id);
2111
+ return typeof row?.seq === "number" ? row.seq : undefined;
2112
+ }
2113
+ syntheticMessageIDs(sessionID) {
2114
+ const rows = this.prepare("SELECT id FROM session_message WHERE session_id = ? AND type = 'synthetic'").all(sessionID);
2115
+ return new Set(rows.map((row) => row.id));
2116
+ }
2117
+ forkOrigin(sessionID) {
2118
+ const columns = new Set(this.prepare("PRAGMA table_info(session_v2)").all().map((column) => column.name));
2119
+ if (!columns.has("fork_session_id") || !columns.has("fork_boundary"))
2120
+ return null;
2121
+ const row = this.prepare("SELECT fork_session_id, fork_boundary FROM session_v2 WHERE id = ?").get(sessionID);
2122
+ if (!row?.fork_session_id || !row.fork_boundary)
2123
+ return null;
2124
+ try {
2125
+ const boundary = JSON.parse(row.fork_boundary);
2126
+ if (boundary.type !== "before" && boundary.type !== "through" || typeof boundary.messageID !== "string" || boundary.messageID.length === 0)
2127
+ return null;
2128
+ return {
2129
+ parentSessionID: row.fork_session_id,
2130
+ boundary: { type: boundary.type, messageID: boundary.messageID }
2131
+ };
2132
+ } catch {
2133
+ return null;
2134
+ }
2135
+ }
2136
+ sessionExists(sessionID) {
2137
+ return this.prepare("SELECT 1 FROM session_v2 WHERE id = ?").get(sessionID) != null;
2138
+ }
2139
+ rowStampsThrough(sessionID, throughSeq) {
2140
+ return this.prepare(`SELECT id, type, seq, time_created FROM session_message
2141
+ WHERE session_id = ? AND seq <= ? ORDER BY seq ASC`).all(sessionID, throughSeq);
2142
+ }
2143
+ latestSequenceForIds(sessionID, ids) {
2144
+ let latest = -1;
2145
+ for (let offset = 0;offset < ids.length; offset += 500) {
2146
+ const chunk = ids.slice(offset, offset + 500);
2147
+ const row = this.prepare(`SELECT MAX(seq) AS seq FROM session_message
2148
+ WHERE session_id = ? AND id IN (${chunk.map(() => "?").join(", ")})`).get(sessionID, ...chunk);
2149
+ if (typeof row?.seq === "number")
2150
+ latest = Math.max(latest, row.seq);
2151
+ }
2152
+ return latest;
2153
+ }
2154
+ compactionByStatus(sessionID, status) {
2155
+ const row = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
2156
+ WHERE session_id = ? AND type = 'compaction'
2157
+ AND json_extract(data, '$.status') = ?
2158
+ ORDER BY seq DESC LIMIT 1`).get(sessionID, status);
2159
+ return row ? decode(row) : undefined;
2160
+ }
2161
+ latestCompaction(sessionID) {
2162
+ return trackDecodeOperation("latestCompaction", () => this.compactionByStatus(sessionID, "completed"));
2163
+ }
2164
+ latestRunningCompaction(sessionID) {
2165
+ return trackDecodeOperation("latestRunningCompaction", () => this.compactionByStatus(sessionID, "running"));
2166
+ }
2167
+ idleRows(sessionID, after = -1) {
2168
+ return trackDecodeOperation("idleRows", () => this.all(sessionID, after, "idle"));
2169
+ }
2170
+ earliestSequence(sessionID) {
2171
+ const row = this.prepare("SELECT MIN(seq) AS seq FROM session_message WHERE session_id = ?").get(sessionID);
2172
+ return typeof row?.seq === "number" ? row.seq : undefined;
2173
+ }
2174
+ latestSequence(sessionID) {
2175
+ const row = this.prepare("SELECT MAX(seq) AS seq FROM session_message WHERE session_id = ?").get(sessionID);
2176
+ return typeof row?.seq === "number" ? row.seq : -1;
2177
+ }
2178
+ assistantSince(sessionID, afterSeq) {
2179
+ return trackDecodeOperation("assistantSince", () => {
2180
+ const rows = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
2181
+ WHERE session_id = ? AND type = 'assistant' AND seq > ?
2182
+ ORDER BY seq ASC`).all(sessionID, afterSeq);
2183
+ return rows.map((row) => decode(row));
2184
+ });
2185
+ }
2186
+ latestAssistant(sessionID) {
2187
+ return trackDecodeOperation("latestAssistant", () => {
2188
+ const row = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
2189
+ WHERE session_id = ? AND type = 'assistant'
2190
+ ORDER BY seq DESC LIMIT 1`).get(sessionID);
2191
+ return row ? decode(row) : undefined;
2192
+ });
2193
+ }
2194
+ latestIdle(sessionID) {
2195
+ return trackDecodeOperation("latestIdle", () => {
2196
+ const row = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
2197
+ WHERE session_id = ? AND type = 'idle'
2198
+ ORDER BY seq DESC LIMIT 1`).get(sessionID);
2199
+ return row ? decode(row) : undefined;
2200
+ });
2201
+ }
2202
+ window(sessionID) {
2203
+ return trackDecodeOperation("window", () => this.db.transaction(() => {
2204
+ const cut = this.latestCompaction(sessionID);
2205
+ return this.all(sessionID, cut ? cut.seq - 1 : -1);
2206
+ }).deferred());
2207
+ }
2208
+ history(sessionID) {
2209
+ return trackDecodeOperation("history", () => this.all(sessionID, -1));
2210
+ }
2211
+ all(sessionID, after, type, through) {
2212
+ const rows = [];
2213
+ for (;; ) {
2214
+ const page = this.page(sessionID, { after, through, type });
2215
+ rows.push(...page.rows);
2216
+ if (page.rows.length < 100 || page.cursor === undefined)
2217
+ return rows;
2218
+ after = page.cursor;
2219
+ }
2220
+ }
2221
+ }
2222
+
1084
2223
  // src/features/magic-context/resolve-subagent-fallback.ts
1085
2224
  function resolveIsSubagentFromOpenCodeDb(sessionId) {
1086
2225
  try {
@@ -1108,6 +2247,189 @@ function resolveIsSubagentFromOpenCode2Db(sessionId) {
1108
2247
  }
1109
2248
  }
1110
2249
 
2250
+ // src/features/magic-context/session-activity.ts
2251
+ var PREFIX = "retrospective_activity:";
2252
+ var pending2 = new WeakMap;
2253
+ function sessionActivityKey(sessionId) {
2254
+ return `${PREFIX}${sessionId}`;
2255
+ }
2256
+ function deleteSessionActivity(db, sessionIds) {
2257
+ if (sessionIds.length === 0)
2258
+ return;
2259
+ const sessions = pending2.get(db);
2260
+ for (const sessionId of sessionIds) {
2261
+ const state = sessions?.get(sessionId);
2262
+ if (state?.timer)
2263
+ clearTimeout(state.timer);
2264
+ sessions?.delete(sessionId);
2265
+ }
2266
+ const placeholders = sessionIds.map(() => "?").join(", ");
2267
+ db.prepare(`DELETE FROM schema_migrations_meta WHERE key IN (${placeholders})`).run(...sessionIds.map(sessionActivityKey));
2268
+ deleteTagIdentityRevisions(db, sessionIds);
2269
+ }
2270
+ function advanceSessionActivity(db, sessionId, time) {
2271
+ if (!sessionId || !Number.isFinite(time) || time <= 0)
2272
+ return;
2273
+ db.prepare(`INSERT INTO schema_migrations_meta (key, value) VALUES (?, ?)
2274
+ ON CONFLICT(key) DO UPDATE SET value = CAST(MAX(CAST(value AS INTEGER), CAST(excluded.value AS INTEGER)) AS TEXT)`).run(sessionActivityKey(sessionId), String(Math.floor(time)));
2275
+ }
2276
+ async function backfillSessionActivity(db, harness, latestTime) {
2277
+ const completedKey = `retrospective_activity_backfill:${harness}:v1`;
2278
+ if (db.prepare("SELECT 1 FROM schema_migrations_meta WHERE key = ?").get(completedKey))
2279
+ return;
2280
+ let cursor = "";
2281
+ while (true) {
2282
+ const rows = db.prepare(`SELECT session_id FROM session_projects
2283
+ WHERE harness = ? AND session_id > ? ORDER BY session_id LIMIT 100`).all(harness, cursor);
2284
+ if (rows.length === 0)
2285
+ break;
2286
+ for (const row of rows) {
2287
+ const time = await latestTime(row.session_id);
2288
+ if (time !== undefined)
2289
+ advanceSessionActivity(db, row.session_id, time);
2290
+ }
2291
+ cursor = rows[rows.length - 1].session_id;
2292
+ await new Promise((resolve) => setTimeout(resolve, 0));
2293
+ }
2294
+ db.prepare("INSERT OR IGNORE INTO schema_migrations_meta (key, value) VALUES (?, 'completed')").run(completedKey);
2295
+ }
2296
+
2297
+ // src/features/magic-context/storage-session-tables.ts
2298
+ var SESSION_SCOPED_TABLES = [
2299
+ { table: "pending_ops", harnessScoped: true },
2300
+ { table: "source_contents", harnessScoped: true },
2301
+ { table: "tool_owner_backfill_state" },
2302
+ { table: "tags", harnessScoped: true },
2303
+ { table: "session_meta", harnessScoped: true },
2304
+ {
2305
+ table: "temporal_decisions",
2306
+ extraPredicate: "NOT EXISTS (SELECT 1 FROM session_meta AS remaining WHERE remaining.session_id = temporal_decisions.session_id)"
2307
+ },
2308
+ {
2309
+ table: "session_replay_decisions",
2310
+ extraPredicate: "NOT EXISTS (SELECT 1 FROM session_meta AS remaining WHERE remaining.session_id = session_replay_decisions.session_id)"
2311
+ },
2312
+ { table: "session_projects", harnessScoped: true },
2313
+ { table: "compartment_chunk_embeddings", harnessScoped: true },
2314
+ { table: "compartments", harnessScoped: true },
2315
+ {
2316
+ table: "compartment_history_versions",
2317
+ extraPredicate: "NOT EXISTS (SELECT 1 FROM compartments AS remaining WHERE remaining.session_id = compartment_history_versions.session_id)"
2318
+ },
2319
+ { table: "compression_depth", harnessScoped: true },
2320
+ { table: "session_facts", harnessScoped: true },
2321
+ { table: "compartment_state_lease" },
2322
+ { table: "notes", harnessScoped: true, extraPredicate: "type = 'session'" },
2323
+ { table: "recomp_compartments", harnessScoped: true },
2324
+ { table: "recomp_facts", harnessScoped: true },
2325
+ { table: "user_memory_candidates" },
2326
+ { table: "primer_candidates", harnessScoped: true },
2327
+ { table: "m0_mutation_log" },
2328
+ { table: "compartment_events", harnessScoped: true },
2329
+ { table: "subagent_invocations", harnessScoped: true },
2330
+ { table: "historian_runs", harnessScoped: true },
2331
+ { table: "plugin_messages" },
2332
+ { table: "transform_decisions", harnessScoped: true },
2333
+ { table: "synapse_batch_ledger" },
2334
+ { table: "embedding_measurement_corpus" },
2335
+ { table: "pending_session_cleanup", harnessScoped: true },
2336
+ { table: "message_history_fts" },
2337
+ { table: "message_fts_rowid_map" },
2338
+ { table: "message_history_source", harnessScoped: true },
2339
+ { table: "message_history_index", harnessScoped: true },
2340
+ { table: "lkg_slots" },
2341
+ { table: "lkg_slot_chunks" }
2342
+ ];
2343
+ var cleanupStatements = new WeakMap;
2344
+ function cleanupStatement(db, sql) {
2345
+ let cache = cleanupStatements.get(db);
2346
+ if (!cache) {
2347
+ cache = new Map;
2348
+ cleanupStatements.set(db, cache);
2349
+ }
2350
+ let statement = cache.get(sql);
2351
+ if (!statement) {
2352
+ if (cache.size >= 256)
2353
+ cache.clear();
2354
+ statement = prepareCachedStatement2(db, sql);
2355
+ cache.set(sql, statement);
2356
+ }
2357
+ return statement;
2358
+ }
2359
+ function deleteSessionScopedRows(db, sessionIds, harness, options = {}) {
2360
+ if (sessionIds.length === 0)
2361
+ return 0;
2362
+ let deletableSessionIds = [...sessionIds];
2363
+ if (options.rustModuleCleanupAcknowledged !== true) {
2364
+ const placeholders = sessionIds.map(() => "?").join(", ");
2365
+ const harnessPredicate = harness === undefined ? "" : " AND harness = ?";
2366
+ const protectedRows = cleanupStatement(db, `SELECT session_id
2367
+ FROM pending_session_cleanup
2368
+ WHERE session_id IN (${placeholders})
2369
+ AND harness LIKE '%:rust'${harnessPredicate}`).all(...sessionIds, ...harness === undefined ? [] : [`${harness}:rust`]);
2370
+ const protectedSessionIds = new Set(protectedRows.map((row) => row.session_id));
2371
+ deletableSessionIds = sessionIds.filter((sessionId) => !protectedSessionIds.has(sessionId));
2372
+ }
2373
+ if (deletableSessionIds.length === 0)
2374
+ return 0;
2375
+ const placeholders = deletableSessionIds.map(() => "?").join(", ");
2376
+ const harnessTables = SESSION_SCOPED_TABLES.filter((definition) => definition.harnessScoped);
2377
+ if (options.preserveTagRevisionTombstones) {
2378
+ const owners = cleanupStatement(db, harnessTables.map((definition) => `SELECT session_id, harness FROM ${definition.table} WHERE session_id IN (${placeholders})${definition.extraPredicate ? ` AND ${definition.extraPredicate}` : ""}`).join(" UNION ")).all(...harnessTables.flatMap(() => deletableSessionIds));
2379
+ const record = cleanupStatement(db, "INSERT OR IGNORE INTO schema_migrations_meta (key, value) VALUES (?, ?)");
2380
+ for (const owner of owners)
2381
+ record.run(tagTombstoneOwnerKey(owner.session_id, owner.harness), owner.harness);
2382
+ const fallback = cleanupStatement(db, `INSERT INTO schema_migrations_meta (key, value)
2383
+ SELECT ?, ? WHERE NOT EXISTS (SELECT 1 FROM schema_migrations_meta WHERE key >= ? AND key < ?)`);
2384
+ for (const id of deletableSessionIds)
2385
+ fallback.run(tagTombstoneOwnerKey(id, getHarness2()), getHarness2(), ...tagTombstoneOwnerRange(id));
2386
+ }
2387
+ for (const sessionId of deletableSessionIds)
2388
+ deleteChunkEmbedBackoffForSession2(db, sessionId);
2389
+ for (const definition of SESSION_SCOPED_TABLES) {
2390
+ if (definition.table === "message_history_fts") {
2391
+ cleanupStatement(db, `DELETE FROM message_history_fts
2392
+ WHERE rowid IN (
2393
+ SELECT fts_rowid
2394
+ FROM message_fts_rowid_map
2395
+ WHERE session_id IN (${placeholders})
2396
+ )`).run(...deletableSessionIds);
2397
+ deleteUnmappedMessageFtsRows2(db, deletableSessionIds);
2398
+ continue;
2399
+ }
2400
+ const predicates = [`session_id IN (${placeholders})`];
2401
+ if (definition.extraPredicate)
2402
+ predicates.push(definition.extraPredicate);
2403
+ const bindHarness = harness !== undefined && definition.harnessScoped === true;
2404
+ if (bindHarness)
2405
+ predicates.push("harness = ?");
2406
+ const statement = cleanupStatement(db, `DELETE FROM ${definition.table} WHERE ${predicates.join(" AND ")}`);
2407
+ if (bindHarness)
2408
+ statement.run(...deletableSessionIds, harness);
2409
+ else
2410
+ statement.run(...deletableSessionIds);
2411
+ }
2412
+ deleteSessionActivity(db, deletableSessionIds);
2413
+ if (!options.preserveTagRevisionTombstones) {
2414
+ const retireOwner = cleanupStatement(db, harness === undefined ? "DELETE FROM schema_migrations_meta WHERE key >= ? AND key < ?" : "DELETE FROM schema_migrations_meta WHERE key = ?");
2415
+ const survivingRows = harnessTables.map((definition) => `EXISTS (SELECT 1 FROM ${definition.table} WHERE session_id = ?${definition.extraPredicate ? ` AND ${definition.extraPredicate}` : ""})`).join(" OR ");
2416
+ const retire = cleanupStatement(db, `DELETE FROM schema_migrations_meta WHERE key IN (?, ?)
2417
+ AND NOT (${survivingRows})
2418
+ AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta AS owners WHERE owners.key >= ? AND owners.key < ?)`);
2419
+ for (const id of deletableSessionIds) {
2420
+ if (harness === undefined)
2421
+ retireOwner.run(...tagTombstoneOwnerRange(id));
2422
+ else
2423
+ retireOwner.run(tagTombstoneOwnerKey(id, harness));
2424
+ retire.run(tagIdentityRevisionKey(id), tagRevisionKey(id), ...harnessTables.map(() => id), ...tagTombstoneOwnerRange(id));
2425
+ }
2426
+ }
2427
+ if (!options.deferRecoveryFenceCleanup)
2428
+ for (const sessionId of deletableSessionIds)
2429
+ clearLkgRecoveryFence(sessionId);
2430
+ return deletableSessionIds.length;
2431
+ }
2432
+
1111
2433
  // src/features/magic-context/storage-meta-session.ts
1112
2434
  var SESSION_META_FALLBACK_SELECTS = {
1113
2435
  cache_ttl: "'5m' AS cache_ttl",
@@ -1361,7 +2683,7 @@ function hasOnlySystemHashMaterialization(sessions, sessionId) {
1361
2683
  }
1362
2684
 
1363
2685
  // src/hooks/magic-context/system-prompt-delivery.ts
1364
- var pending2 = new BoundedSessionMap(1000);
2686
+ var pending3 = new BoundedSessionMap(1000);
1365
2687
  var retiredRequests = new WeakSet;
1366
2688
  var heldRequests = new WeakSet;
1367
2689
  var refreshOwners = new BoundedSessionMap(1000);
@@ -1377,11 +2699,11 @@ function recordSystemRefreshOwnership(sessionId, hash, ownsHistoryRefresh, histo
1377
2699
  function preparation(sessionId, request) {
1378
2700
  if (retiredRequests.has(request))
1379
2701
  return;
1380
- const previous = pending2.get(sessionId);
2702
+ const previous = pending3.get(sessionId);
1381
2703
  if (previous?.request === request)
1382
2704
  return previous;
1383
2705
  const next = { request, held: false };
1384
- pending2.set(sessionId, next);
2706
+ pending3.set(sessionId, next);
1385
2707
  return next;
1386
2708
  }
1387
2709
  function recordSystemPromptForRequest(sessionId, request, hash, db, ownsHistoryRefresh, history, materialization) {
@@ -1389,7 +2711,7 @@ function recordSystemPromptForRequest(sessionId, request, hash, db, ownsHistoryR
1389
2711
  return;
1390
2712
  if (ownsHistoryRefresh !== undefined)
1391
2713
  recordSystemRefreshOwnership(sessionId, hash, ownsHistoryRefresh, history, materialization);
1392
- const previous = pending2.get(sessionId);
2714
+ const previous = pending3.get(sessionId);
1393
2715
  if (previous?.request === request && previous.held && previous.hash && previous.hash !== hash) {
1394
2716
  retirePendingSystemPromptDelivery(sessionId);
1395
2717
  return;
@@ -1412,7 +2734,7 @@ function recordHeldHeadForRequest(sessionId, request, deferRefresh) {
1412
2734
  }
1413
2735
  }
1414
2736
  function bindSystemPromptResponse(sessionId, request, response) {
1415
- const saved = pending2.get(sessionId);
2737
+ const saved = pending3.get(sessionId);
1416
2738
  if (!saved || saved.request !== request || request?.kind !== "v2" || !response.responseId || response.responseId === request.previousResponseId || response.modelKey !== request.modelKey || !Number.isFinite(response.createdAt) || response.createdAt <= request.startedAt)
1417
2739
  return;
1418
2740
  if (saved.response && saved.response.id !== response.responseId)
@@ -1420,11 +2742,11 @@ function bindSystemPromptResponse(sessionId, request, response) {
1420
2742
  saved.response = { id: response.responseId, createdAt: response.createdAt };
1421
2743
  }
1422
2744
  function isHeldHeadForRequest(sessionId, request) {
1423
- const saved = pending2.get(sessionId);
2745
+ const saved = pending3.get(sessionId);
1424
2746
  return saved?.request === request && saved?.held === true || request !== undefined && retiredRequests.has(request) && heldRequests.has(request);
1425
2747
  }
1426
2748
  function acknowledgeSystemPromptDelivery(args) {
1427
- const saved = pending2.get(args.sessionId);
2749
+ const saved = pending3.get(args.sessionId);
1428
2750
  if (!saved || saved.request !== args.request || !args.responseId)
1429
2751
  return;
1430
2752
  const request = saved.request;
@@ -1466,10 +2788,10 @@ function clearSystemPromptDelivery(sessionId) {
1466
2788
  refreshOwners.delete(sessionId);
1467
2789
  }
1468
2790
  function retirePendingSystemPromptDelivery(sessionId) {
1469
- const saved = pending2.get(sessionId);
2791
+ const saved = pending3.get(sessionId);
1470
2792
  if (saved)
1471
2793
  retiredRequests.add(saved.request);
1472
- pending2.delete(sessionId);
2794
+ pending3.delete(sessionId);
1473
2795
  }
1474
2796
 
1475
2797
  // src/hooks/magic-context/lkg-measured-request.ts
@@ -1481,7 +2803,7 @@ function lkgProviderInputTotal(tokens) {
1481
2803
  return counts.every((count) => Number.isSafeInteger(count) && count >= 0) ? counts.reduce((sum, count) => sum + count, 0) : Number.NaN;
1482
2804
  }
1483
2805
  function identity(slot) {
1484
- return createHash3("sha256").update(JSON.stringify([
2806
+ return createHash6("sha256").update(JSON.stringify([
1485
2807
  slot.capturedAt,
1486
2808
  slot.captureSequence,
1487
2809
  slot.rowVersion,
@@ -1577,7 +2899,7 @@ function clearCapturedLkgMeasurement(sessionId) {
1577
2899
  }
1578
2900
 
1579
2901
  // src/hooks/magic-context/lkg-persist.ts
1580
- import { createHash as createHash4 } from "node:crypto";
2902
+ import { createHash as createHash7 } from "node:crypto";
1581
2903
  function parseStringArray(value) {
1582
2904
  if (typeof value !== "string")
1583
2905
  return null;
@@ -1691,7 +3013,7 @@ function rememberFingerprint(db, sessionId, fingerprint) {
1691
3013
  saved.set(sessionId, fingerprint);
1692
3014
  }
1693
3015
  function slotFingerprint(slot) {
1694
- return createHash4("sha256").update(JSON.stringify([
3016
+ return createHash7("sha256").update(JSON.stringify([
1695
3017
  slot.jsonPrefix,
1696
3018
  slot.inputIdSeq,
1697
3019
  slot.inputContentDigests,
@@ -2828,7 +4150,7 @@ var DIGEST_CHUNK_BYTES = 64 * 1024;
2828
4150
  var digestChunk;
2829
4151
  function lkgContentDigestFromFields(fields) {
2830
4152
  lkgDigestsComputed += 1;
2831
- const hash = createHash5("sha256");
4153
+ const hash = createHash8("sha256");
2832
4154
  digestChunk ??= Buffer.allocUnsafe(DIGEST_CHUNK_BYTES);
2833
4155
  const chunk = digestChunk;
2834
4156
  let offset = 0;
@@ -2891,7 +4213,7 @@ function legacyLkgDigestFromFields(fields) {
2891
4213
  const value = typeof field === "symbol" ? field.description ?? "" : String(field);
2892
4214
  key += `${typeof field}:${value.length}:${value}\x00`;
2893
4215
  }
2894
- return createHash5("sha256").update(key).digest("base64url");
4216
+ return createHash8("sha256").update(key).digest("base64url");
2895
4217
  }
2896
4218
  function legacyLkgContentDigest(message) {
2897
4219
  const fields = flattenContentFields(withoutEmptyUserDiffSummary(message));
@@ -3461,15 +4783,15 @@ function createPreAdoptionToolSweepResolver(db, sessionId) {
3461
4783
  }
3462
4784
 
3463
4785
  // src/features/magic-context/pi-content-decisions.ts
3464
- var PREFIX = "pi-content-replay-v1:";
4786
+ var PREFIX2 = "pi-content-replay-v1:";
3465
4787
  function encodePiContentDecision(kind, messageId) {
3466
- return PREFIX + JSON.stringify([kind, messageId]);
4788
+ return PREFIX2 + JSON.stringify([kind, messageId]);
3467
4789
  }
3468
4790
  function decodePiContentDecision(value) {
3469
- if (!value.startsWith(PREFIX))
4791
+ if (!value.startsWith(PREFIX2))
3470
4792
  return null;
3471
4793
  try {
3472
- const pair = JSON.parse(value.slice(PREFIX.length));
4794
+ const pair = JSON.parse(value.slice(PREFIX2.length));
3473
4795
  if (Array.isArray(pair) && pair.length === 2 && (pair[0] === "reminder-strip" || pair[0] === "seam-temporal-strip" || pair[0] === "tag-identity-repair-once" || pair[0] === "tag-identity-repair-pending" || pair[0] === "tag-identity-rebuild-failed" || pair[0] === "tag-identity-recurring") && typeof pair[1] === "string" && pair[1].length > 0)
3474
4796
  return [pair[0], pair[1]];
3475
4797
  } catch {}
@@ -4403,7 +5725,7 @@ function addToProjection(projection, messages, withIndexSources) {
4403
5725
  if (isStrictGapHealingMessage2(message))
4404
5726
  projection.nonNarrativeOrdinals.add(message.ordinal);
4405
5727
  if (withIndexSources)
4406
- projection.indexSources.push(toMessageIndexSource2(message));
5728
+ projection.indexSources.push(toMessageIndexSource(message));
4407
5729
  }
4408
5730
  projection.messageCount += messages.length;
4409
5731
  }
@@ -4770,7 +6092,7 @@ function* rebaseSteps(args) {
4770
6092
  outcome.recompPartialRangeRebased = true;
4771
6093
  }
4772
6094
  if (indexNeedsRebuild) {
4773
- clearIndexedMessagesInTransaction2(db, sessionId);
6095
+ clearIndexedMessagesInTransaction(db, sessionId);
4774
6096
  outcome.indexRebuilt = true;
4775
6097
  outcome.compressionDepthRowsDropped = depthRowCount;
4776
6098
  }
@@ -4808,7 +6130,7 @@ function* rebaseSteps(args) {
4808
6130
  if (outcome.indexRebuilt) {
4809
6131
  const sources = projection.indexSources;
4810
6132
  for (let start = 0;start < sources.length; start += INDEX_REBUILD_CHUNK) {
4811
- indexSourcesAfterOrdinal2(db, sessionId, sources.slice(start, start + INDEX_REBUILD_CHUNK), sources.length);
6133
+ indexSourcesAfterOrdinal(db, sessionId, sources.slice(start, start + INDEX_REBUILD_CHUNK), sources.length);
4812
6134
  yield;
4813
6135
  }
4814
6136
  outcome.indexRowsRebuilt = countRows2(db, "SELECT COUNT(*) AS count FROM message_history_source WHERE session_id = ?", sessionId);
@@ -4988,14 +6310,14 @@ class HiddenCompletionRefusal extends Error {
4988
6310
  }
4989
6311
 
4990
6312
  // src/features/magic-context/compaction-marker.ts
4991
- import { createHash as createHash6 } from "node:crypto";
4992
- import { existsSync, statSync as statSync3 } from "node:fs";
6313
+ import { createHash as createHash9 } from "node:crypto";
6314
+ import { existsSync, statSync as statSync4 } from "node:fs";
4993
6315
  var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
4994
6316
  var ID_PREFIX_HEX_LENGTH = 12;
4995
6317
  var ID_SUFFIX_LENGTH = 14;
4996
6318
  var ID_PREFIX_MASK = (1n << BigInt(ID_PREFIX_HEX_LENGTH * 4)) - 1n;
4997
6319
  function deterministicBase62(seed, length) {
4998
- let value = BigInt(`0x${createHash6("sha256").update(seed).digest("hex")}`);
6320
+ let value = BigInt(`0x${createHash9("sha256").update(seed).digest("hex")}`);
4999
6321
  const chars = Array(length);
5000
6322
  for (let index = length - 1;index >= 0; index -= 1) {
5001
6323
  chars[index] = BASE62_CHARS[Number(value % 62n)];
@@ -5061,7 +6383,7 @@ function runMarkerWriteTransaction(db, site, operation) {
5061
6383
  function markerWalPages(db) {
5062
6384
  try {
5063
6385
  const row = db.prepare("PRAGMA page_size").get();
5064
- const bytes = statSync3(`${getOpenCodeDbPath()}-wal`).size;
6386
+ const bytes = statSync4(`${getOpenCodeDbPath()}-wal`).size;
5065
6387
  return Math.max(0, Math.floor((bytes - 32) / (row.page_size + 24)));
5066
6388
  } catch {
5067
6389
  return null;
@@ -5845,7 +7167,7 @@ function parseUserMemoryRow(row) {
5845
7167
  }
5846
7168
  // src/features/magic-context/dreamer/provider-output-failure.ts
5847
7169
  import { AsyncLocalStorage } from "node:async_hooks";
5848
- import { createHash as createHash7 } from "node:crypto";
7170
+ import { createHash as createHash10 } from "node:crypto";
5849
7171
  var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
5850
7172
 
5851
7173
  class DreamerProviderOutputFailureError extends Error {
@@ -5942,12 +7264,12 @@ function providerOutputFailureFromInvalidManifest(messages, responseText, now =
5942
7264
  const resetAt = quotaResetAt(responseText, now);
5943
7265
  if (resetAt === undefined && completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS)
5944
7266
  return null;
5945
- const fingerprint = createHash7("sha256").update(normalized).digest("hex").slice(0, 16);
7267
+ const fingerprint = createHash10("sha256").update(normalized).digest("hex").slice(0, 16);
5946
7268
  return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText, resetAt);
5947
7269
  }
5948
7270
 
5949
7271
  // src/v2/hooks/hidden-child.ts
5950
- import { createHash as createHash8 } from "node:crypto";
7272
+ import { createHash as createHash11 } from "node:crypto";
5951
7273
 
5952
7274
  // src/agents/dreamer.ts
5953
7275
  var DREAMER_AGENT = "dreamer";
@@ -6172,7 +7494,7 @@ function markerCandidates(text) {
6172
7494
  function textDigest(text) {
6173
7495
  return {
6174
7496
  length: text.length,
6175
- sha256: createHash8("sha256").update(text).digest("hex").slice(0, 16)
7497
+ sha256: createHash11("sha256").update(text).digest("hex").slice(0, 16)
6176
7498
  };
6177
7499
  }
6178
7500
  function firstDifference(a, b) {
@@ -7772,9 +9094,9 @@ async function promptAsyncAndWaitForIdle(client, request, options = {}) {
7772
9094
  }
7773
9095
  }
7774
9096
  // src/shared/prompt-surface-runtime.ts
7775
- import { createHash as createHash9 } from "node:crypto";
7776
- import { existsSync as existsSync2, readFileSync as readFileSync3, statSync as statSync4 } from "node:fs";
7777
- import { dirname, isAbsolute, resolve } from "node:path";
9097
+ import { createHash as createHash12 } from "node:crypto";
9098
+ import { existsSync as existsSync2, readFileSync as readFileSync5, statSync as statSync5 } from "node:fs";
9099
+ import { dirname as dirname2, isAbsolute, resolve as resolve2 } from "node:path";
7778
9100
 
7779
9101
  // src/tools/light-descriptions.ts
7780
9102
  var CTX_REDUCE_LIGHT_DESCRIPTION = `Stamp an item as no longer needed for the work ahead. Not a delete: stamping QUEUES it, the item stays readable until Magic Context clears stamped items in one sweep, newest tags are protected, and a cleared item goes to the archive (recent: a [dropped §N§] placeholder; older: removed) recoverable via ctx_expand(tag=N). The question is "does this need to stay on my desk for what comes next?" — a file you keep editing stays, the grep that found it goes. Stamp used reads/searches/outputs, acted-on build/test output, redundant dumps, extracted pasted payloads; keep user messages, your own text, unresolved errors, raw evidence, exact wording that may matter. Look at each tag; never blanket-stamp "1-50". Grammar: "3-5", "1,2,9", "1-5,8,12-15".`;
@@ -7805,22 +9127,22 @@ function promptSurfaceHashMaterial(systemContent, preset = "full") {
7805
9127
  \x00magic-context-prompt-surface:${preset}`;
7806
9128
  }
7807
9129
  function systemPromptFingerprint(systemContent, preset = "full") {
7808
- return createHash9("md5").update(promptSurfaceHashMaterial(systemContent, preset)).digest("hex");
9130
+ return createHash12("md5").update(promptSurfaceHashMaterial(systemContent, preset)).digest("hex");
7809
9131
  }
7810
9132
  var PROMPT_SURFACE_TOOL_ID_SET = new Set(ACTIVE_TOOL_IDS);
7811
9133
  function resolveUserConfigDirectory(options) {
7812
9134
  if (options.userConfigDirectory)
7813
- return resolve(options.userConfigDirectory);
9135
+ return resolve2(options.userConfigDirectory);
7814
9136
  const sharedBase = cortexKitUserConfigBasePath();
7815
9137
  const shared = detectConfigFile(sharedBase);
7816
9138
  if (shared.format !== "none")
7817
- return dirname(shared.path);
9139
+ return dirname2(shared.path);
7818
9140
  if (options.harness) {
7819
9141
  const legacy = resolveLegacyConfigSourcesForHarness(options.directory ?? process.cwd(), options.harness === "omp" ? "pi" : options.harness === "opencode2" ? "opencode" : options.harness).user.find((source) => existsSync2(source.path));
7820
9142
  if (legacy)
7821
- return dirname(legacy.path);
9143
+ return dirname2(legacy.path);
7822
9144
  }
7823
- return dirname(sharedBase);
9145
+ return dirname2(sharedBase);
7824
9146
  }
7825
9147
  function markerCount(content) {
7826
9148
  return content.match(GUIDANCE_MARKER_LINE)?.length ?? 0;
@@ -7837,14 +9159,14 @@ function createPromptSurfaceRuntime(options) {
7837
9159
  const readGuidanceOverride = (configuredPath) => {
7838
9160
  if (!configuredPath)
7839
9161
  return;
7840
- const path = isAbsolute(configuredPath) ? configuredPath : resolve(userConfigDirectory, configuredPath);
9162
+ const path = isAbsolute(configuredPath) ? configuredPath : resolve2(userConfigDirectory, configuredPath);
7841
9163
  let content;
7842
9164
  try {
7843
- if (!statSync4(path).isFile()) {
9165
+ if (!statSync5(path).isFile()) {
7844
9166
  warnOnce(`guidance-not-file:${path}`, `prompt_surface.guidance_override_path (${path}) is not a file; using built-in guidance.`);
7845
9167
  return;
7846
9168
  }
7847
- content = readFileSync3(path, "utf8");
9169
+ content = readFileSync5(path, "utf8");
7848
9170
  } catch (error) {
7849
9171
  const reason = error instanceof Error ? error.message : String(error);
7850
9172
  warnOnce(`guidance-unreadable:${path}:${reason}`, `prompt_surface.guidance_override_path (${path}) could not be read (${reason}); using built-in guidance.`);
@@ -9067,7 +10389,7 @@ function queueDropsForCompartmentalizedMessages(db, sessionId, upToMessageIndex,
9067
10389
 
9068
10390
  // src/hooks/magic-context/compartment-runner-historian.ts
9069
10391
  import { mkdirSync, unlinkSync, writeFileSync } from "node:fs";
9070
- import { join } from "node:path";
10392
+ import { join as join3 } from "node:path";
9071
10393
 
9072
10394
  // src/agents/historian.ts
9073
10395
  var HISTORIAN_AGENT = "historian";
@@ -9703,7 +11025,7 @@ function compareMemorySelectionPriority(left, right) {
9703
11025
  }
9704
11026
 
9705
11027
  // src/features/magic-context/mural/render-trigger.ts
9706
- import { createHash as createHash10 } from "node:crypto";
11028
+ import { createHash as createHash13 } from "node:crypto";
9707
11029
 
9708
11030
  // src/features/magic-context/mural/mural-selection.ts
9709
11031
  var DEFAULT_MURAL_MEMORY_BUDGET = 8000;
@@ -10407,7 +11729,7 @@ function ensureMuralRendered(db, projectIdentity, budgetTokens = DEFAULT_MURAL_M
10407
11729
  return { ...cached.result };
10408
11730
  }
10409
11731
  const plan = planMuralRender(entries);
10410
- const textHash = createHash10("sha256").update(plan.layout.text).digest("hex");
11732
+ const textHash = createHash13("sha256").update(plan.layout.text).digest("hex");
10411
11733
  if (existing && existing.contentHash === textHash && existing.width === plan.width && existing.height === plan.height) {
10412
11734
  return rememberRender(db, projectIdentity, key, existing.image, {
10413
11735
  hasMural: true,
@@ -16003,7 +17325,7 @@ function dumpHistorianResponse(sessionId, directory, label, text) {
16003
17325
  ensureCortexKitArtifactGitignore(directory);
16004
17326
  const safeSessionId = sanitizeDumpName(sessionId);
16005
17327
  const safeLabel = sanitizeDumpName(label);
16006
- const dumpPath = join(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
17328
+ const dumpPath = join3(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
16007
17329
  writeFileSync(dumpPath, text, "utf8");
16008
17330
  sessionLog2(sessionId, "compartment agent: historian response dumped", {
16009
17331
  label,
@@ -16022,6 +17344,60 @@ function sanitizeDumpName(value) {
16022
17344
  return value.replace(/[^a-zA-Z0-9._-]/g, "-");
16023
17345
  }
16024
17346
 
17347
+ // src/hooks/magic-context/historian-history-wait.ts
17348
+ var historyWaits = new Map;
17349
+ function newestMessageId(snapshot) {
17350
+ try {
17351
+ const count = getRawSessionMessageOrdinalCount2(snapshot.sessionId);
17352
+ const ids = readRawSessionMessageIdOrdinalsForRange2(snapshot.sessionId, count, count);
17353
+ const newest = ids.keys().next().value;
17354
+ if (newest)
17355
+ return newest;
17356
+ } catch {}
17357
+ return snapshot.rawLastMessageIdAtTrigger;
17358
+ }
17359
+ function recoveryWindow(snapshot, percentage) {
17360
+ return percentage >= escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage || snapshot.emergencyTailScale !== undefined;
17361
+ }
17362
+ function clearHistorianHistoryWait(sessionId) {
17363
+ historyWaits.delete(sessionId);
17364
+ }
17365
+ function recordHistorianNoProgress(snapshot, emergency = false) {
17366
+ const newest = newestMessageId(snapshot);
17367
+ if (!newest)
17368
+ return;
17369
+ const previous = historyWaits.get(snapshot.sessionId);
17370
+ const sameHistory = previous?.newestMessageId === newest;
17371
+ historyWaits.set(snapshot.sessionId, {
17372
+ newestMessageId: newest,
17373
+ recoveryAttempted: sameHistory && previous.recoveryAttempted || emergency || recoveryWindow(snapshot, snapshot.usagePercentage),
17374
+ floorLiftAttempted: sameHistory && previous.floorLiftAttempted || snapshot.liftLivePromptFloor === true
17375
+ });
17376
+ }
17377
+ function shouldWaitForNewHistorianHistory(snapshot, options = {}) {
17378
+ const wait = historyWaits.get(snapshot.sessionId);
17379
+ if (!wait)
17380
+ return false;
17381
+ const newest = newestMessageId(snapshot);
17382
+ if (newest && newest !== wait.newestMessageId) {
17383
+ try {
17384
+ const order = compareRawSessionMessageOrder2(snapshot.sessionId, newest, wait.newestMessageId);
17385
+ if (order === null || order > 0)
17386
+ return false;
17387
+ } catch {}
17388
+ }
17389
+ const recovery = options.emergency || recoveryWindow(snapshot, options.usagePercentage ?? snapshot.usagePercentage);
17390
+ const floorLift = snapshot.liftLivePromptFloor === true;
17391
+ if (recovery && !wait.recoveryAttempted || floorLift && !wait.floorLiftAttempted) {
17392
+ if (options.claim) {
17393
+ wait.recoveryAttempted ||= recovery;
17394
+ wait.floorLiftAttempted ||= floorLift;
17395
+ }
17396
+ return false;
17397
+ }
17398
+ return true;
17399
+ }
17400
+
16025
17401
  // src/tools/ctx-note/render.ts
16026
17402
  var GLANCE_TITLE_MAX = 80;
16027
17403
  var NUDGE_TITLE_MAX = 60;
@@ -17578,6 +18954,14 @@ async function runCompartmentAgent(deps) {
17578
18954
  sessionLog2(sessionId, `historian prompt fit: sized to ${producerModel ?? "unknown"} (${describeHistorianPromptTrim(promptFit)}; requestedChunkTokens=${historianChunkTokens})`);
17579
18955
  }
17580
18956
  const perRunCap = selectPerRunCap(boundarySnapshot);
18957
+ if (!deps.forceDrainQuota && shouldWaitForNewHistorianHistory(boundarySnapshot, {
18958
+ emergency: getOverflowState(db, sessionId).needsEmergencyRecovery
18959
+ })) {
18960
+ telemetry.status = "noop";
18961
+ telemetry.failureReason = "waiting for new history after no forward progress";
18962
+ sessionLog2(sessionId, "historian no-op: waiting for new history after no forward progress");
18963
+ return;
18964
+ }
17581
18965
  const usable = Math.max(1, Math.round(boundarySnapshot.contextLimit * boundarySnapshot.executeThresholdPercentage / 100));
17582
18966
  const reserve = deps.forceDrainQuota ? { ok: true, reservation: null } : reserveProtectedTailDrainTokens({
17583
18967
  db,
@@ -17684,6 +19068,12 @@ ${chunkText}`,
17684
19068
  const maxExistingSequence = priorCompartments.reduce((max, c) => c.sequence > max ? c.sequence : max, -1);
17685
19069
  const sequenceOffset = priorCompartments.length === 0 ? 0 : maxExistingSequence + 1;
17686
19070
  retainDrainReservationForRetryThrottle = true;
19071
+ if (!deps.forceDrainQuota) {
19072
+ shouldWaitForNewHistorianHistory(boundarySnapshot, {
19073
+ emergency: getOverflowState(db, sessionId).needsEmergencyRecovery,
19074
+ claim: true
19075
+ });
19076
+ }
17687
19077
  const validatedPass = await runValidatedHistorianPass({
17688
19078
  client,
17689
19079
  hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
@@ -17735,7 +19125,11 @@ ${chunkText}`,
17735
19125
  sessionLog2(sessionId, `historian failure: source=no-progress reason="historian returned compartments that did not advance past raw message ${offset - 1}" newCompartmentCount=${newCompartments.length} lastNewEnd=${lastNewEnd} priorEnd=${offset - 1}`);
17736
19126
  sessionLog2(sessionId, "historian output discarded: reason=no_forward_progress");
17737
19127
  const failCount = incrementHistorianFailure(db, sessionId, `no forward progress beyond raw message ${offset - 1}`);
17738
- await notifyHistorianIssue(buildHistorianFailureNotice(failCount, `historian made no forward progress beyond raw message ${offset - 1}`));
19128
+ try {
19129
+ await notifyHistorianIssue(buildHistorianFailureNotice(failCount, `historian made no forward progress beyond raw message ${offset - 1}`));
19130
+ } finally {
19131
+ recordHistorianNoProgress(boundarySnapshot, inEmergency);
19132
+ }
17739
19133
  return;
17740
19134
  }
17741
19135
  retainDrainReservationForRetryThrottle = false;
@@ -17847,6 +19241,7 @@ ${chunkText}`,
17847
19241
  db.exec("COMMIT");
17848
19242
  published = true;
17849
19243
  publishCommitted = true;
19244
+ clearHistorianHistoryWait(sessionId);
17850
19245
  finishHistorianPublishStage(sessionId, "publish-txn", transactionStartedAt, "completed", `compartments=${persistedCompartments.length}`);
17851
19246
  logSlowWriteTransaction("historian-publish", lockAcquiredAt);
17852
19247
  } catch (error) {
@@ -19107,4 +20502,4 @@ ${failure}`;
19107
20502
  }
19108
20503
  }
19109
20504
 
19110
- export { historianRunConfig, dreamerRunConfig, pluginConfigReader, currentPluginConfigReader, withLiveDreamerOutputCap, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, queueM0Mutation, getMaxM0MutationId, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getUncoveredCompartmentEndsThrough, providerResponseFailed, isSuccessfulProviderCompletion, rememberUnpublishedAutoSearchNoHint, getUnpublishedAutoSearchNoHint, forgetUnpublishedAutoSearchNoHint, registerAutoSearchWork, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, clearSession, requestPendingMaterialization, pendingMaterializationOrigin, hasPendingMaterializationOrigin, clearPendingMaterialization, recordSystemPromptForRequest, recordHeldHeadForRequest, bindSystemPromptResponse, isHeldHeadForRequest, deferDeliveredSystemRefresh, retirePendingSystemPromptDelivery, lkgProviderInputTotal, beginV2LkgRequest, claimLkgRequestIdentity, currentLkgRequestIdentity, noteCapturedLkgRequest, noteLkgProviderResponse, measuredLkgPrefix, clearLkgMeasuredRequest, saveLkgSlotToDb, clearPersistedLkgSlotStrict, loadPersistedLkgSlot, drainStaleLkgSlots, resolveLkgModelKeys, createLkgEntryProjector, captureLkgSlot, validateAnthropicReasoningRuns, validateLkgSeam, replayLkg, coldStartRawServedIndex, coldStartUncapturedReplay, noteUncertifiedNormalLkg, hasProcessLocalLkgProof, lkgDirtyRevision, rememberLkgDirtyRevision, readPersistedLkgUntaggedInputIds, persistLkgUntaggedInputIds, noteLkgRecoveryPrefix, readLkgRecoveryPrefix, noteLkgHealthyPrefix, lkgRecoveryReplayUnproven, lkgRecoveryEntryUnproven, beginLkgPass, visitMessageContentFields, contentSnapshotValue, messageContentFields, signatureForFields, exactReusablePrefix, incrementalLkgContentDigests, lkgSlotRejection, captureSlot, getInMemorySlot, getSlot, forgetInMemorySlot, dropSlot, noteEntry, getLkgSlotHeapStats, TOOL_SWEEP_SCOPED_MARKER, useScopedToolSweep, createPreAdoptionToolSweepResolver, copySessionStateForClone, queueMemoryMutation, getMaxMemoryMutationIdForProjects, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, readCoordinateGeneration, rebaseSessionCoordinatesAsync, HiddenCompletionRefusal, getOpenCodeDbPath, compareOpenCodeMessagesByCanonicalOrder, prepareCompactionMarkerCandidates, removeMcOwnedCompactionMarkers, getCompartmentEvents, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, DreamerProviderOutputFailureError, withDreamerModelCooldown, providerOutputFailureFromInvalidManifest, DREAMER_AGENT, DREAMER_RETROSPECTIVE_AGENT, DREAMER_PRIMER_INVESTIGATOR_AGENT, DREAMER_MEMORY_MAPPER_AGENT, DREAMER_CLASSIFIER_AGENT, DREAMER_DOCS_AGENT, DREAMER_REVIEWER_AGENT, HIDDEN_HISTORIAN_AGENT, HIDDEN_DREAMER_AGENT, HIDDEN_CURATE_AGENT, hiddenAgentFor, hiddenToolLoop, HIDDEN_RUN_DISPOSED_REASON, noteChildOfDisposedInstance, hiddenChildPermissions, registerHiddenChildAgents, hiddenToolCallRefusal, HiddenAgentStepLimit, HiddenChildHook, extractLatestAssistantText, hasLengthCappedOutput, parseProviderModel, modelBodyField, toModelEntry, ModelProducedNoOutputError, noteModelActivityMonitored, noteModelOutputReceived, isPromptTimeoutError, getPromptFailureDetail, raceWithSignal, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, annotateSubagentInvocationError, failedInvocationStatus, sumTokensFromChildMessages, recordChildInvocation, createPromptAsyncTransport, CTX_NOTE_LIGHT_DESCRIPTION, ACTIVE_TOOL_IDS, systemPromptFingerprint, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, MARKER_SUMMARY_TEXT, markerUpdateDefinitelyDidNotCut, applyDeferredCompactionMarker, teardownChildSession, runTokenLog, formatRunTokenLog, createChildSessionWithFence, buildMagicContextSection, getMuralIdentity, getMural, modelKeyAcceptsImages, resolveMuralWire, extractM0Block, formatDate, TEMPORAL_MARKER_REPLAY_PATTERN, collectTemporalCandidates, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, selectHiddenMessagesAtCompactionSeam, prepareCompartmentInjection, renderCompartmentInjection, MaterializeContentionError, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, materializeM0, hydrateCachedM0Mural, resetPrefixTrimFallbackState, findHostCompactionWindow, capturePrefixTrimSourceOrder, prepareCachedM0M1Replay, hasCompleteCachedM0M1, injectM0M1, clampProducerAtomChars, producerInputTokenLimit, historianProducerReserve, producerPromptFailureReason, resolveHiddenCompletionExecutor, createV1HiddenCompletionExecutor, EMPTY_READ_REPLY, noteTouchedAt, renderGlance, renderNotesById, formatWriteReply, observeNoteNudgeServe, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, omitIncompleteFileTokenTotals, describeBoundaryDiagnostics, RECOVERY_NO_HEAD_LIMIT, deriveProtectedTailTokenTarget, selectPerRunCap, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, noteTransformPassForExactOrdinalReads, runCompartmentAgent, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, isRecompFailure2, isRecompSkip2, extractRecompReason2, setRecompStarting2, setRecompNote2, setRecompTerminal2, buildRecompDeps2, runManagedRecomp2 };
20505
+ export { historianRunConfig, dreamerRunConfig, pluginConfigReader, currentPluginConfigReader, withLiveDreamerOutputCap, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, queueM0Mutation, getMaxM0MutationId, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getUncoveredCompartmentEndsThrough, providerResponseFailed, isSuccessfulProviderCompletion, LkgRecoveryFenceError, lkgServedArrayDigest, hasCleanLkgRecoveryFence, dirtyLkgRecoveryRevision, ownsLkgDirtyFence, invalidateCleanLkgRecoveryFence, prepareLkgCaptureFence, certifyCommittedLkgCapture, markLkgRecoveryDirty, rememberUnpublishedAutoSearchNoHint, getUnpublishedAutoSearchNoHint, forgetUnpublishedAutoSearchNoHint, registerAutoSearchWork, gaDatabasePath, RAW_MESSAGE_TYPES, V2StoreReaderPool, V2StoreReader, advanceSessionActivity, backfillSessionActivity, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, clearSession, requestPendingMaterialization, pendingMaterializationOrigin, hasPendingMaterializationOrigin, clearPendingMaterialization, recordSystemPromptForRequest, recordHeldHeadForRequest, bindSystemPromptResponse, isHeldHeadForRequest, deferDeliveredSystemRefresh, retirePendingSystemPromptDelivery, lkgProviderInputTotal, beginV2LkgRequest, claimLkgRequestIdentity, currentLkgRequestIdentity, noteCapturedLkgRequest, noteLkgProviderResponse, measuredLkgPrefix, clearLkgMeasuredRequest, saveLkgSlotToDb, clearPersistedLkgSlotStrict, loadPersistedLkgSlot, drainStaleLkgSlots, resolveLkgModelKeys, createLkgEntryProjector, captureLkgSlot, validateAnthropicReasoningRuns, validateLkgSeam, replayLkg, coldStartRawServedIndex, coldStartUncapturedReplay, noteUncertifiedNormalLkg, hasProcessLocalLkgProof, lkgDirtyRevision, rememberLkgDirtyRevision, readPersistedLkgUntaggedInputIds, persistLkgUntaggedInputIds, noteLkgRecoveryPrefix, readLkgRecoveryPrefix, noteLkgHealthyPrefix, lkgRecoveryReplayUnproven, lkgRecoveryEntryUnproven, beginLkgPass, visitMessageContentFields, contentSnapshotValue, messageContentFields, signatureForFields, exactReusablePrefix, incrementalLkgContentDigests, lkgSlotRejection, captureSlot, getInMemorySlot, getSlot, forgetInMemorySlot, dropSlot, noteEntry, getLkgSlotHeapStats, TOOL_SWEEP_SCOPED_MARKER, useScopedToolSweep, createPreAdoptionToolSweepResolver, copySessionStateForClone, queueMemoryMutation, getMaxMemoryMutationIdForProjects, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, readCoordinateGeneration, rebaseSessionCoordinatesAsync, HiddenCompletionRefusal, getOpenCodeDbPath, compareOpenCodeMessagesByCanonicalOrder, prepareCompactionMarkerCandidates, removeMcOwnedCompactionMarkers, getCompartmentEvents, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, DreamerProviderOutputFailureError, withDreamerModelCooldown, providerOutputFailureFromInvalidManifest, DREAMER_AGENT, DREAMER_RETROSPECTIVE_AGENT, DREAMER_PRIMER_INVESTIGATOR_AGENT, DREAMER_MEMORY_MAPPER_AGENT, DREAMER_CLASSIFIER_AGENT, DREAMER_DOCS_AGENT, DREAMER_REVIEWER_AGENT, HIDDEN_HISTORIAN_AGENT, HIDDEN_DREAMER_AGENT, HIDDEN_CURATE_AGENT, hiddenAgentFor, hiddenToolLoop, HIDDEN_RUN_DISPOSED_REASON, noteChildOfDisposedInstance, hiddenChildPermissions, registerHiddenChildAgents, hiddenToolCallRefusal, HiddenAgentStepLimit, HiddenChildHook, extractLatestAssistantText, hasLengthCappedOutput, parseProviderModel, modelBodyField, toModelEntry, ModelProducedNoOutputError, noteModelActivityMonitored, noteModelOutputReceived, isPromptTimeoutError, getPromptFailureDetail, raceWithSignal, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, annotateSubagentInvocationError, failedInvocationStatus, sumTokensFromChildMessages, recordChildInvocation, createPromptAsyncTransport, CTX_NOTE_LIGHT_DESCRIPTION, ACTIVE_TOOL_IDS, systemPromptFingerprint, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, MARKER_SUMMARY_TEXT, markerUpdateDefinitelyDidNotCut, applyDeferredCompactionMarker, teardownChildSession, runTokenLog, formatRunTokenLog, createChildSessionWithFence, buildMagicContextSection, getMuralIdentity, getMural, modelKeyAcceptsImages, resolveMuralWire, extractM0Block, formatDate, TEMPORAL_MARKER_REPLAY_PATTERN, collectTemporalCandidates, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, selectHiddenMessagesAtCompactionSeam, prepareCompartmentInjection, renderCompartmentInjection, MaterializeContentionError, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, materializeM0, hydrateCachedM0Mural, resetPrefixTrimFallbackState, findHostCompactionWindow, capturePrefixTrimSourceOrder, prepareCachedM0M1Replay, hasCompleteCachedM0M1, injectM0M1, clampProducerAtomChars, producerInputTokenLimit, historianProducerReserve, producerPromptFailureReason, resolveHiddenCompletionExecutor, createV1HiddenCompletionExecutor, shouldWaitForNewHistorianHistory, EMPTY_READ_REPLY, noteTouchedAt, renderGlance, renderNotesById, formatWriteReply, observeNoteNudgeServe, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, omitIncompleteFileTokenTotals, describeBoundaryDiagnostics, RECOVERY_NO_HEAD_LIMIT, deriveProtectedTailTokenTarget, selectPerRunCap, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, noteTransformPassForExactOrdinalReads, runCompartmentAgent, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, isRecompFailure2, isRecompSkip2, extractRecompReason2, setRecompStarting2, setRecompNote2, setRecompTerminal2, buildRecompDeps2, runManagedRecomp2 };