@cortexkit/opencode-magic-context 0.49.0 → 0.49.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/dist/{announcement-fp14dw0n.js → announcement-hdbkt8v5.js} +1 -1
  2. package/dist/auto-search-worker.js +3 -3
  3. package/dist/config/{mural-model-deprecation.d.ts → deprecated-config.d.ts} +4 -1
  4. package/dist/config/deprecated-config.d.ts.map +1 -0
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/project-security.d.ts +2 -2
  7. package/dist/config/schema/magic-context.d.ts +4 -4
  8. package/dist/config/schema/magic-context.d.ts.map +1 -1
  9. package/dist/{conflict-warning-hook-kzx4dmk1.js → conflict-warning-hook-asnt6hfc.js} +3 -3
  10. package/dist/{context-nj5f293n.js → context-tfyhtdcs.js} +111 -45
  11. package/dist/{derive-budgets-qz5rrr08.js → derive-budgets-j4ry8j8n.js} +1 -1
  12. package/dist/{embedding-backfill-aetxv1vt.js → embedding-backfill-wyc3ykyf.js} +7 -7
  13. package/dist/embedding-worker-process.js +30 -0
  14. package/dist/embedding-worker.js +5 -5
  15. package/dist/features/magic-context/dreamer/task-registry.d.ts +2 -3
  16. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  17. package/dist/features/magic-context/memory/embedding-worker-client.d.ts +8 -1
  18. package/dist/features/magic-context/memory/embedding-worker-client.d.ts.map +1 -1
  19. package/dist/features/magic-context/memory/embedding-worker-process.d.ts +2 -0
  20. package/dist/features/magic-context/memory/embedding-worker-process.d.ts.map +1 -0
  21. package/dist/features/magic-context/memory/onnx-telemetry.d.ts +3 -0
  22. package/dist/features/magic-context/memory/onnx-telemetry.d.ts.map +1 -0
  23. package/dist/features/magic-context/overflow-detection.d.ts +1 -2
  24. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  25. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  26. package/dist/features/magic-context/transform-decision-log.d.ts +1 -1
  27. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  28. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +1 -0
  29. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  30. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +1 -0
  32. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/hook.d.ts +1 -0
  35. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/lkg-measured-request.d.ts +3 -1
  38. package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/lkg-persist.d.ts +8 -14
  40. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  41. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +62 -0
  42. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -0
  43. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +38 -0
  44. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -0
  45. package/dist/hooks/magic-context/lkg-replay.d.ts +3 -1
  46. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  47. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  48. package/dist/hooks/magic-context/opaque-thinking.d.ts +12 -0
  49. package/dist/hooks/magic-context/opaque-thinking.d.ts.map +1 -0
  50. package/dist/hooks/magic-context/pass-outcome.d.ts +2 -2
  51. package/dist/hooks/magic-context/pending-materialization.d.ts +8 -0
  52. package/dist/hooks/magic-context/pending-materialization.d.ts.map +1 -0
  53. package/dist/hooks/magic-context/read-session-db.d.ts +3 -0
  54. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  56. package/dist/hooks/magic-context/rust-mode-transform.d.ts +1 -0
  57. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  58. package/dist/hooks/magic-context/strip-content.d.ts +5 -2
  59. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  60. package/dist/hooks/magic-context/system-date-refresh.d.ts +29 -0
  61. package/dist/hooks/magic-context/system-date-refresh.d.ts.map +1 -0
  62. package/dist/hooks/magic-context/system-prompt-dates.d.ts +6 -0
  63. package/dist/hooks/magic-context/system-prompt-dates.d.ts.map +1 -0
  64. package/dist/hooks/magic-context/system-prompt-delivery.d.ts +47 -0
  65. package/dist/hooks/magic-context/system-prompt-delivery.d.ts.map +1 -0
  66. package/dist/hooks/magic-context/system-prompt-hash.d.ts +4 -0
  67. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
  69. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +2 -0
  71. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/transform.d.ts +6 -0
  73. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  74. package/dist/{index-9qjqq45k.js → index-0pjvpfkf.js} +21 -1
  75. package/dist/index-6m7rdv7y.js +733 -0
  76. package/dist/{index-1r0k9js3.js → index-6tfxmc4n.js} +10 -10
  77. package/dist/{index-gzcmtmar.js → index-7w18gg78.js} +25 -1
  78. package/dist/{index-nm6a8xpd.js → index-att4bfan.js} +1 -1
  79. package/dist/{index-ezmszwbd.js → index-eypn4ba6.js} +7 -4
  80. package/dist/{index-ha87j7a8.js → index-fdtkt5r1.js} +6 -6
  81. package/dist/{index-kp5qe690.js → index-fg00p1cg.js} +38 -36
  82. package/dist/{index-1bc61ans.js → index-fvnzcnww.js} +44 -1
  83. package/dist/index-gbmqa9x9.js +1170 -0
  84. package/dist/{index-pxwp2hjk.js → index-gzky5rva.js} +30 -53
  85. package/dist/{index-kq57tdf0.js → index-k6xvbj2e.js} +255 -1075
  86. package/dist/{index-0w56v4fm.js → index-mw7c950g.js} +1 -1
  87. package/dist/{index-1g30axtz.js → index-p0n5ryq8.js} +82 -900
  88. package/dist/{index-b7mv1jx3.js → index-p1hnwfd8.js} +1 -1
  89. package/dist/{index-peshmj6h.js → index-r2zcs71c.js} +6 -4
  90. package/dist/{index-kmpvemph.js → index-rafsaxac.js} +2 -2
  91. package/dist/{index-stbr4ce6.js → index-s7fc0fkn.js} +1 -1
  92. package/dist/{index-hj2q50k0.js → index-sfhndpcb.js} +463 -6
  93. package/dist/index-sv0bb7vg.js +6972 -0
  94. package/dist/{index-57mrqed8.js → index-w23dh319.js} +17 -258
  95. package/dist/{index-9rt53q79.js → index-xgrwmj82.js} +1 -1
  96. package/dist/{index-h2py7207.js → index-xnanvj3w.js} +765 -1255
  97. package/dist/{index-2jcbj7r1.js → index-zfzdpeq2.js} +2269 -3802
  98. package/dist/{index-s4j7t92z.js → index-zg8yq4ya.js} +29 -744
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +209 -61
  101. package/dist/{message-index-bounded-h0mrd4pr.js → message-index-bounded-hqktkhdy.js} +7 -6
  102. package/dist/migration-worker.js +6 -5
  103. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -1
  104. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  105. package/dist/plugin/messages-transform.d.ts.map +1 -1
  106. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  107. package/dist/{project-embedding-registry-rtt0djyb.js → project-embedding-registry-0gv3h6y8.js} +6 -6
  108. package/dist/raw-ordinal-warmup-worker.js +1 -1
  109. package/dist/{read-session-chunk-ty89v75e.js → read-session-chunk-5mh0bh8y.js} +5 -4
  110. package/dist/{recomp-orchestrator-4f1yyd1q.js → recomp-orchestrator-kpkhkjhq.js} +20 -19
  111. package/dist/{search-pz4f4wge.js → search-p9w39qv4.js} +15 -14
  112. package/dist/{send-session-notification-38cd5dqt.js → send-session-notification-xffh3bbe.js} +2 -2
  113. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  114. package/dist/shared/storage-file-mutex.d.ts +9 -0
  115. package/dist/shared/storage-file-mutex.d.ts.map +1 -0
  116. package/dist/shared/storage-permissions.d.ts +6 -0
  117. package/dist/shared/storage-permissions.d.ts.map +1 -1
  118. package/dist/shared/window-geometry.d.ts +9 -66
  119. package/dist/shared/window-geometry.d.ts.map +1 -1
  120. package/dist/standalone-plugin-marker.d.ts +8 -0
  121. package/dist/standalone-plugin-marker.d.ts.map +1 -0
  122. package/dist/tools/ctx-reduce/constants.d.ts +1 -2
  123. package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
  124. package/dist/tools/ctx-reduce/tools.d.ts +1 -1
  125. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  126. package/dist/{transform-postprocess-phase-tck4g20s.js → transform-postprocess-phase-481j5a7z.js} +20 -19
  127. package/dist/v2/auto-search-worker.js +3 -3
  128. package/dist/v2/{context-crbt6p1y.js → context-gsdtha5v.js} +873 -2122
  129. package/dist/v2/{derive-budgets-fgej9j46.js → derive-budgets-enckmg7y.js} +2 -2
  130. package/dist/v2/{embedding-backfill-ph1qfyn3.js → embedding-backfill-dbvjbcmm.js} +8 -9
  131. package/dist/v2/embedding-worker-process.js +29 -0
  132. package/dist/v2/embedding-worker.js +3 -4
  133. package/dist/v2/hooks/context.d.ts.map +1 -1
  134. package/dist/v2/hooks/copied-tag-notation.d.ts +19 -0
  135. package/dist/v2/hooks/copied-tag-notation.d.ts.map +1 -0
  136. package/dist/v2/hooks/payload.d.ts.map +1 -1
  137. package/dist/v2/hooks/system-prompt-response.d.ts +5 -0
  138. package/dist/v2/hooks/system-prompt-response.d.ts.map +1 -0
  139. package/dist/v2/{message-index-bounded-xwqdywxg.js → message-index-bounded-p6v0n8qh.js} +8 -7
  140. package/dist/v2/migration-worker.js +6 -5
  141. package/dist/v2/{project-embedding-registry-d6m7tyxr.js → project-embedding-registry-nyq7z8y6.js} +7 -8
  142. package/dist/v2/raw-ordinal-warmup-worker.js +2 -2
  143. package/dist/v2/{read-session-chunk-8p5mdryx.js → read-session-chunk-fhyfe4qa.js} +6 -5
  144. package/dist/v2/{recomp-orchestrator-ckfgt6wq.js → recomp-orchestrator-5xy7w136.js} +22 -22
  145. package/dist/v2/{search-ym8rehhz.js → search-j7bakcwa.js} +17 -17
  146. package/dist/v2/{send-session-notification-5m0yapqx.js → send-session-notification-f6v698r5.js} +2 -2
  147. package/dist/v2/{server-jvxzm1jy.js → server-1fszbabv.js} +28 -28
  148. package/dist/v2/{server-3j4d00kf.js → server-2htmbqbv.js} +25 -1
  149. package/dist/v2/{server-c5rrgrcd.js → server-4c7jt8gq.js} +25 -1
  150. package/dist/v2/{server-ycw9qqcy.js → server-4enr7s6x.js} +1 -1
  151. package/dist/v2/{server-v4mewb78.js → server-6tcrjfw8.js} +1 -1
  152. package/dist/v2/{server-x4hscabv.js → server-7spkq1y6.js} +2257 -3746
  153. package/dist/v2/{server-sa8jvrfc.js → server-7vkj6zhb.js} +29 -744
  154. package/dist/v2/{server-xwz4dqh9.js → server-8xmq9h3f.js} +30 -53
  155. package/dist/v2/{server-1tk82krw.js → server-bgzy0phk.js} +463 -6
  156. package/dist/v2/server-c7n2ftng.js +6860 -0
  157. package/dist/v2/server-cvgn49tr.js +733 -0
  158. package/dist/v2/{server-zm570tr2.js → server-cw6521wn.js} +232 -7
  159. package/dist/v2/{server-pj4pjv02.js → server-czb2rkpk.js} +21 -1
  160. package/dist/v2/{server-19zjmn02.js → server-d6g4whc2.js} +20 -14
  161. package/dist/v2/{server-1bc61ans.js → server-fvnzcnww.js} +44 -1
  162. package/dist/v2/{server-w32kmdez.js → server-kh958yj8.js} +3 -3
  163. package/dist/v2/{server-q4ph9bwn.js → server-mqvtz7wz.js} +7 -7
  164. package/dist/v2/{server-2s6ayq3t.js → server-ras2sxnc.js} +133 -13
  165. package/dist/v2/{server-ss95ky04.js → server-s2st631p.js} +1 -1
  166. package/dist/v2/{server-2s9qz6n7.js → server-t528t8qm.js} +1 -1
  167. package/dist/v2/{server-8k2agx29.js → server-vb7pbd9p.js} +17 -258
  168. package/dist/v2/{server-zp53y8js.js → server-zbxjj2mz.js} +2 -2
  169. package/dist/v2/server.d.ts.map +1 -1
  170. package/dist/v2/server.js +149 -5
  171. package/dist/v2/{storage-tags-8vw924zn.js → storage-tags-5yxrvkaf.js} +1 -1
  172. package/dist/v2/{wrapup-orchestrator-a7efxaax.js → wrapup-orchestrator-yem5422s.js} +28 -28
  173. package/dist/{wrapup-orchestrator-barbc6h9.js → wrapup-orchestrator-xvrr27ws.js} +21 -20
  174. package/package.json +4 -4
  175. package/src/config/{mural-model-deprecation.ts → deprecated-config.ts} +19 -0
  176. package/src/config/index.test.ts +15 -37
  177. package/src/config/index.ts +2 -3
  178. package/src/config/project-security.ts +3 -3
  179. package/src/config/schema/magic-context.ts +11 -7
  180. package/src/features/magic-context/dreamer/task-registry.ts +2 -3
  181. package/src/shared/models-dev-cache.ts +1 -7
  182. package/src/shared/sqlite-640-review.test.ts +5 -1
  183. package/src/shared/storage-file-mutex-review.test.ts +162 -0
  184. package/src/shared/storage-file-mutex.ts +130 -0
  185. package/src/shared/storage-permissions.ts +46 -0
  186. package/src/shared/window-geometry.test.ts +102 -236
  187. package/src/shared/window-geometry.ts +23 -413
  188. package/dist/config/mural-model-deprecation.d.ts.map +0 -1
  189. package/dist/index-2jgwttpt.js +0 -3269
  190. package/dist/index-mfkzp7qj.js +0 -229
  191. package/dist/v2/server-4ez8mntn.js +0 -3213
  192. package/dist/v2/server-mfkzp7qj.js +0 -229
  193. package/src/shared/__fixtures__/window-overlay.v1.json +0 -337
  194. /package/dist/{index-2pp04pmg.js → index-69vas84q.js} +0 -0
  195. /package/dist/v2/{index-2pp04pmg.js → index-69vas84q.js} +0 -0
@@ -6,6 +6,9 @@ import {
6
6
  hasMeaningfulUserText2,
7
7
  extractTexts2
8
8
  } from "./server-kzns2hbz.js";
9
+ import {
10
+ getMagicContextStorageDir
11
+ } from "./server-t4k4qexw.js";
9
12
  import {
10
13
  withSqliteBackgroundWriter2,
11
14
  withoutSqliteTransformPass2
@@ -20,16 +23,27 @@ import {
20
23
  } from "./server-6byqfbqf.js";
21
24
  import {
22
25
  cleanUserText2
23
- } from "./server-4ez8mntn.js";
26
+ } from "./server-c7n2ftng.js";
24
27
  import {
25
28
  recordMessageFtsRowid,
26
29
  recordIndexedMessageTime,
27
30
  messageFtsOrdinalRangeIsMapped,
28
31
  deleteUnmappedMessageFtsRows
29
- } from "./server-3j4d00kf.js";
32
+ } from "./server-2htmbqbv.js";
33
+ import {
34
+ isPidAlive,
35
+ readProcessStartTime
36
+ } from "./server-cvgn49tr.js";
30
37
  import {
31
38
  deleteChunkEmbedBackoffForSession
32
- } from "./server-ss95ky04.js";
39
+ } from "./server-s2st631p.js";
40
+ import {
41
+ ensurePrivateStorageDirectorySync,
42
+ writeStorageFileSync,
43
+ writeStorageFileAtomicSync,
44
+ syncStorageDirectorySync,
45
+ writeStorageFileDurableAtomicSync
46
+ } from "./server-fvnzcnww.js";
33
47
  import {
34
48
  closeQuietly
35
49
  } from "./server-8ajstryz.js";
@@ -37,6 +51,51 @@ import {
37
51
  logSlowWriteTransaction
38
52
  } from "./server-3t0q2cqx.js";
39
53
 
54
+ // src/shared/bounded-session-map.ts
55
+ class BoundedSessionMap {
56
+ maxEntries;
57
+ store = new Map;
58
+ constructor(maxEntries) {
59
+ if (!Number.isFinite(maxEntries) || maxEntries < 1) {
60
+ throw new Error(`BoundedSessionMap: maxEntries must be >= 1, got ${maxEntries}`);
61
+ }
62
+ this.maxEntries = maxEntries;
63
+ }
64
+ get(sessionId) {
65
+ const value = this.store.get(sessionId);
66
+ if (value === undefined)
67
+ return;
68
+ this.store.delete(sessionId);
69
+ this.store.set(sessionId, value);
70
+ return value;
71
+ }
72
+ peek(sessionId) {
73
+ return this.store.get(sessionId);
74
+ }
75
+ has(sessionId) {
76
+ return this.store.has(sessionId);
77
+ }
78
+ set(sessionId, value) {
79
+ if (this.store.has(sessionId)) {
80
+ this.store.delete(sessionId);
81
+ } else if (this.store.size >= this.maxEntries) {
82
+ const oldest = this.store.keys().next().value;
83
+ if (oldest !== undefined)
84
+ this.store.delete(oldest);
85
+ }
86
+ this.store.set(sessionId, value);
87
+ }
88
+ delete(sessionId) {
89
+ return this.store.delete(sessionId);
90
+ }
91
+ clear() {
92
+ this.store.clear();
93
+ }
94
+ get size() {
95
+ return this.store.size;
96
+ }
97
+ }
98
+
40
99
  // src/features/magic-context/compression-depth-storage.ts
41
100
  var incrementDepthStatements = new WeakMap;
42
101
  var totalDepthStatements = new WeakMap;
@@ -61,7 +120,403 @@ function clearCompressionDepthRange(db, sessionId, startOrdinal, endOrdinal) {
61
120
  }
62
121
 
63
122
  // src/features/magic-context/message-index.ts
64
- import { createHash } from "node:crypto";
123
+ import { createHash as createHash3 } from "node:crypto";
124
+
125
+ // src/hooks/magic-context/lkg-recovery-fence.ts
126
+ import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
127
+ import { lstatSync, readdirSync as readdirSync2, readFileSync as readFileSync2, rmSync as rmSync2 } from "node:fs";
128
+ import { basename, dirname, join as join2 } from "node:path";
129
+
130
+ // src/shared/storage-file-mutex.ts
131
+ import { execFileSync } from "node:child_process";
132
+ import { createHash, randomUUID } from "node:crypto";
133
+ import { readdirSync, readFileSync, rmSync } from "node:fs";
134
+ import { join } from "node:path";
135
+ var ticketChecksum = (name, ticket) => createHash("sha256").update(JSON.stringify([name, ticket.choosing, ticket.number, ticket.birth])).digest("hex");
136
+ function processBirth(pid) {
137
+ if (process.platform === "linux") {
138
+ try {
139
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
140
+ const ticks = stat.slice(stat.lastIndexOf(")") + 2).trim().split(/\s+/)[19];
141
+ if (!ticks || !/^\d+$/.test(ticks))
142
+ return null;
143
+ return `${readFileSync("/proc/sys/kernel/random/boot_id", "utf8").trim()}:${ticks}`;
144
+ } catch {
145
+ return null;
146
+ }
147
+ }
148
+ if (process.platform === "darwin") {
149
+ try {
150
+ return execFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
151
+ encoding: "utf8",
152
+ timeout: 1000,
153
+ windowsHide: true,
154
+ env: { ...process.env, TZ: "UTC", LC_ALL: "C" },
155
+ stdio: ["ignore", "pipe", "pipe"]
156
+ }).trim() || null;
157
+ } catch {
158
+ return null;
159
+ }
160
+ }
161
+ const start = readProcessStartTime(pid);
162
+ return start === null ? null : String(start);
163
+ }
164
+ var pause = new Int32Array(new SharedArrayBuffer(4));
165
+ function withStorageFileMutex(directory, work, timeoutMs = 1000) {
166
+ ensurePrivateStorageDirectorySync(directory);
167
+ const name = `${process.pid}-${randomUUID()}.lock`;
168
+ const ownPath = join(directory, name);
169
+ const birth = processBirth(process.pid);
170
+ const ticket = { choosing: true, number: 0, birth, checksum: "" };
171
+ const encodedTicket = () => JSON.stringify({ ...ticket, checksum: ticketChecksum(name, ticket) });
172
+ writeStorageFileSync(ownPath, encodedTicket(), { flag: "wx", forcePrivate: true });
173
+ const deadline = performance.now() + timeoutMs;
174
+ const peers = () => {
175
+ const found = [];
176
+ for (const other of readdirSync(directory)) {
177
+ if (other === name || !/^\d+-[\da-f-]+\.lock$/.test(other))
178
+ continue;
179
+ const pid = Number(other.split("-")[0]);
180
+ const otherPath = join(directory, other);
181
+ let value = null;
182
+ try {
183
+ const parsed = JSON.parse(readFileSync(otherPath, "utf8"));
184
+ if (typeof parsed.choosing === "boolean" && Number.isSafeInteger(parsed.number) && parsed.number >= 0 && (parsed.birth === null || typeof parsed.birth === "string") && parsed.checksum === ticketChecksum(other, parsed))
185
+ value = parsed;
186
+ } catch (error) {
187
+ if (error.code === "ENOENT")
188
+ continue;
189
+ }
190
+ const alive = isPidAlive(pid);
191
+ const actualBirth = alive === "alive" && value?.birth ? processBirth(pid) : null;
192
+ if (alive === "dead" || actualBirth !== null && value?.birth && actualBirth !== value.birth) {
193
+ rmSync(otherPath, { force: true });
194
+ continue;
195
+ }
196
+ found.push([other, value]);
197
+ }
198
+ return found;
199
+ };
200
+ try {
201
+ ticket.number = 1 + Math.max(0, ...peers().map(([, value]) => value?.number ?? 0));
202
+ ticket.choosing = false;
203
+ writeStorageFileAtomicSync(ownPath, encodedTicket(), true);
204
+ while (peers().some(([other, value]) => !value || value.choosing || value.number < ticket.number || value.number === ticket.number && other < name)) {
205
+ if (performance.now() >= deadline)
206
+ throw new Error("Storage safety publication lock is unavailable");
207
+ Atomics.wait(pause, 0, 0, 10);
208
+ }
209
+ const result = work();
210
+ if (result && typeof result.then === "function")
211
+ throw new TypeError("Storage publication mutex requires synchronous work");
212
+ return result;
213
+ } finally {
214
+ rmSync(ownPath, { force: true });
215
+ }
216
+ }
217
+
218
+ // src/hooks/magic-context/lkg-recovery-fence.ts
219
+ class LkgRecoveryFenceError extends Error {
220
+ constructor(message) {
221
+ super(message);
222
+ this.name = "LkgRecoveryFenceError";
223
+ }
224
+ }
225
+ var platform = process.platform;
226
+ var observer;
227
+ var knownFences = new BoundedSessionMap(1000);
228
+ var ioObserver;
229
+ var cacheKey = (sessionId) => `${getMagicContextStorageDir()}\x00${getHarness2()}\x00${sessionId}`;
230
+ function remember(sessionId, value) {
231
+ knownFences.set(cacheKey(sessionId), value);
232
+ return value;
233
+ }
234
+ function known(sessionId) {
235
+ const prior = knownFences.get(cacheKey(sessionId));
236
+ if (prior)
237
+ return prior;
238
+ const record = read(sessionId);
239
+ if (record)
240
+ return remember(sessionId, { state: record.state, record });
241
+ try {
242
+ lstatSync(lkgRecoveryFencePath(sessionId));
243
+ } catch (error) {
244
+ if (error.code === "ENOENT")
245
+ return remember(sessionId, { state: "clean", record: null });
246
+ }
247
+ return remember(sessionId, { state: "invalid", record: null });
248
+ }
249
+ function clearLkgFenceProcessState(sessionId) {
250
+ if (sessionId)
251
+ knownFences.delete(cacheKey(sessionId));
252
+ else
253
+ knownFences.clear();
254
+ }
255
+ var durableFencesSupported = () => platform !== "win32";
256
+ var hash = (value) => createHash2("sha256").update(value).digest("hex");
257
+ var lkgServedArrayDigest = hash;
258
+ function lkgRecoveryFencePath(sessionId) {
259
+ return join2(getMagicContextStorageDir(), "lkg-recovery-fences", `${hash(sessionId)}.json`);
260
+ }
261
+ function metadata(slot) {
262
+ return [
263
+ slot.inputIdSeq,
264
+ slot.inputContentDigests,
265
+ slot.inputContentSignatures ?? null,
266
+ slot.piOutputEntryIds ?? null,
267
+ slot.lastInputMessageId,
268
+ slot.modelKey,
269
+ slot.providerKey
270
+ ];
271
+ }
272
+ function representationKey(slot) {
273
+ return createHash2("sha256").update(slot.jsonPrefix).update(JSON.stringify(metadata(slot))).digest("hex");
274
+ }
275
+ function lkgRecoverySlotKey(slot) {
276
+ return hash(JSON.stringify([
277
+ representationKey(slot),
278
+ slot.capturedAt,
279
+ slot.rowVersion ?? null,
280
+ slot.captureSequence ?? null
281
+ ]));
282
+ }
283
+ function payload(record) {
284
+ return [
285
+ record.version,
286
+ record.sessionId,
287
+ record.host,
288
+ record.modelKey,
289
+ record.providerKey,
290
+ record.slotKey,
291
+ record.servedDigest,
292
+ record.revision,
293
+ record.state
294
+ ];
295
+ }
296
+ function publishRecord(record) {
297
+ ioObserver?.("write");
298
+ try {
299
+ if (record.state === "clean")
300
+ observer?.("clean");
301
+ writeStorageFileDurableAtomicSync(lkgRecoveryFencePath(record.sessionId), JSON.stringify({ ...record, checksum: hash(JSON.stringify(payload(record))) }), () => observer?.("temp-synced"));
302
+ if (record.state === "dirty")
303
+ observer?.("dirty");
304
+ remember(record.sessionId, {
305
+ state: record.state,
306
+ record: { ...record, checksum: hash(JSON.stringify(payload(record))) }
307
+ });
308
+ } catch (error) {
309
+ const visible = read(record.sessionId);
310
+ if (record.state === "clean" && visible?.state === "clean" && visible.revision === record.revision && visible.slotKey === record.slotKey) {
311
+ const dirty = { ...record, state: "dirty" };
312
+ writeStorageFileDurableAtomicSync(lkgRecoveryFencePath(record.sessionId), JSON.stringify({ ...dirty, checksum: hash(JSON.stringify(payload(dirty))) }));
313
+ }
314
+ remember(record.sessionId, { state: "invalid", record: null });
315
+ throw error;
316
+ }
317
+ }
318
+ function read(sessionId) {
319
+ ioObserver?.("read");
320
+ try {
321
+ const path = lkgRecoveryFencePath(sessionId);
322
+ const stat = lstatSync(path);
323
+ const directory = lstatSync(dirname(path));
324
+ 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()))
325
+ return null;
326
+ const value = JSON.parse(readFileSync2(path, "utf8"));
327
+ 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))))
328
+ return null;
329
+ return value;
330
+ } catch {
331
+ return null;
332
+ }
333
+ }
334
+ function publish(sessionId, slot, state, revision) {
335
+ const record = {
336
+ version: 1,
337
+ sessionId,
338
+ host: getHarness2(),
339
+ modelKey: slot.modelKey,
340
+ providerKey: slot.providerKey,
341
+ slotKey: lkgRecoverySlotKey(slot),
342
+ servedDigest: hash(slot.jsonPrefix),
343
+ revision,
344
+ state
345
+ };
346
+ publishRecord(record);
347
+ }
348
+ function locked(sessionId, work) {
349
+ ioObserver?.("mutex");
350
+ return withStorageFileMutex(`${lkgRecoveryFencePath(sessionId)}.locks`, () => {
351
+ const path = lkgRecoveryFencePath(sessionId);
352
+ for (const name of readdirSync2(dirname(path))) {
353
+ if (name.startsWith(`${basename(path)}.`) && name.endsWith(".tmp"))
354
+ rmSync2(join2(dirname(path), name), { force: true });
355
+ }
356
+ return work();
357
+ });
358
+ }
359
+ function hasCleanLkgRecoveryFence(sessionId, _slot) {
360
+ if (!durableFencesSupported())
361
+ return false;
362
+ const state = known(sessionId);
363
+ return state.state === "clean";
364
+ }
365
+ function lkgFenceRequiresRebuild(sessionId, slot, processLocalProof) {
366
+ return !processLocalProof && (durableFencesSupported() ? !hasCleanLkgRecoveryFence(sessionId, slot) : true);
367
+ }
368
+ function lkgRecoveryFenceUnclean(sessionId) {
369
+ return durableFencesSupported() && known(sessionId).state !== "clean";
370
+ }
371
+ function dirtyLkgRecoveryRevision(sessionId, _slot) {
372
+ if (!durableFencesSupported())
373
+ return;
374
+ const record = known(sessionId).record;
375
+ return record?.state === "dirty" ? record.revision : undefined;
376
+ }
377
+ function ownsLkgDirtyFence(sessionId, revision) {
378
+ if (!durableFencesSupported())
379
+ return revision === "process-local";
380
+ const record = known(sessionId).record;
381
+ return revision !== undefined && record?.state === "dirty" && record.revision === revision;
382
+ }
383
+ function invalidateCleanLkgRecoveryFence(sessionId, load, ownRevision) {
384
+ if (!durableFencesSupported())
385
+ return "process-local";
386
+ const prior = known(sessionId);
387
+ if (prior.state === "dirty")
388
+ return prior.record?.revision === ownRevision ? ownRevision : undefined;
389
+ return locked(sessionId, () => {
390
+ const slot = load() ?? {
391
+ jsonPrefix: "",
392
+ inputIdSeq: [],
393
+ inputContentDigests: [],
394
+ lastInputMessageId: "",
395
+ modelKey: null,
396
+ providerKey: null,
397
+ capturedAt: 0
398
+ };
399
+ const record = read(sessionId);
400
+ if (record?.state !== "dirty") {
401
+ const revision = randomUUID2();
402
+ publish(sessionId, slot, "dirty", revision);
403
+ return revision;
404
+ }
405
+ return record?.state === "dirty" && record.revision === ownRevision ? ownRevision : undefined;
406
+ });
407
+ }
408
+ function prepareLkgCaptureFence(args) {
409
+ if (!durableFencesSupported())
410
+ return "process-local";
411
+ return locked(args.sessionId, () => {
412
+ const before = read(args.sessionId);
413
+ const owns = before?.state === "dirty" && before.revision === args.ownDirtyRevision;
414
+ const unchangedBytes = before?.state === "clean" && before.servedDigest === hash(args.slot.jsonPrefix);
415
+ if (!args.rebuild && before && !owns && !unchangedBytes && before.state !== "clean")
416
+ throw new LkgRecoveryFenceError(`A concurrent recovery requires a declared prefix rebuild (state=${before?.state}, owned=${owns}, previous=${!!args.previousSlot}, bytes=${unchangedBytes})`);
417
+ const revision = randomUUID2();
418
+ if (before)
419
+ publishRecord({ ...before, state: "dirty", revision });
420
+ else
421
+ publish(args.sessionId, args.previousSlot ?? args.slot, "dirty", revision);
422
+ return revision;
423
+ });
424
+ }
425
+ function certifyCommittedLkgCapture(args) {
426
+ if (!durableFencesSupported())
427
+ return false;
428
+ const state = known(args.sessionId);
429
+ if (state.state !== "dirty" || state.record?.revision !== args.revision)
430
+ return false;
431
+ return locked(args.sessionId, () => {
432
+ const before = read(args.sessionId);
433
+ if (before?.state !== "dirty" || before.revision !== args.revision)
434
+ return false;
435
+ const saved = args.load();
436
+ if (!saved || representationKey(saved) !== representationKey(args.slot) || hash(saved.jsonPrefix) !== args.latestServedDigest)
437
+ return false;
438
+ publish(args.sessionId, saved, "clean", args.revision);
439
+ return true;
440
+ });
441
+ }
442
+ function markLkgRecoveryDirty(args) {
443
+ if (!durableFencesSupported()) {
444
+ if (!args.processLocalProof)
445
+ throw new LkgRecoveryFenceError("Restart replay requires a healthy rebuild on Windows");
446
+ return "process-local";
447
+ }
448
+ const state = known(args.sessionId);
449
+ if (state.state === "dirty" && args.processLocalProof && state.record && state.record.revision === args.ownDirtyRevision)
450
+ return state.record.revision;
451
+ if (state.state === "invalid")
452
+ throw new LkgRecoveryFenceError("No clean durable recovery certificate");
453
+ return locked(args.sessionId, () => {
454
+ const slot = args.slot;
455
+ const before = read(args.sessionId);
456
+ if (before?.state === "dirty") {
457
+ if (!args.processLocalProof || before.revision !== args.ownDirtyRevision)
458
+ throw new LkgRecoveryFenceError(`Recovery superseded this process's last-good request (local=${args.processLocalProof}, owned=${before.revision === args.ownDirtyRevision})`);
459
+ return before.revision;
460
+ }
461
+ if (before && before.state !== "clean")
462
+ throw new LkgRecoveryFenceError("No clean durable recovery certificate");
463
+ const revision = randomUUID2();
464
+ publish(args.sessionId, slot, "dirty", revision);
465
+ return revision;
466
+ });
467
+ }
468
+ function commitLkgWithRecoveryFence(args) {
469
+ if (!durableFencesSupported())
470
+ return args.commit();
471
+ const state = known(args.sessionId);
472
+ if (state.state === "clean" && !args.requiredRevision && !args.retainDirtyRevision) {
473
+ const committed = args.commit();
474
+ if (committed) {
475
+ observer?.("committed");
476
+ remember(args.sessionId, { state: "clean", record: null });
477
+ }
478
+ return committed;
479
+ }
480
+ if (state.state === "invalid" && !args.rebuild)
481
+ throw new LkgRecoveryFenceError("Unproven prior request requires a prefix rebuild");
482
+ return locked(args.sessionId, () => {
483
+ const before = read(args.sessionId);
484
+ if (args.requiredRevision && before?.revision !== args.requiredRevision)
485
+ throw new LkgRecoveryFenceError("A later publisher superseded the rollback snapshot");
486
+ const ownsDirty = before?.state === "dirty" && (before.revision === args.retainDirtyRevision || before.revision === args.ownDirtyRevision);
487
+ if (before?.state === "dirty" && !ownsDirty && !args.rebuild)
488
+ throw new LkgRecoveryFenceError("A concurrent recovery requires a declared prefix rebuild");
489
+ if (before?.state !== "dirty" && state.state === "invalid")
490
+ publish(args.sessionId, args.load() ?? args.slot, "dirty", randomUUID2());
491
+ if (!args.commit())
492
+ return false;
493
+ observer?.("committed");
494
+ const saved = args.load();
495
+ if (!saved || representationKey(saved) !== representationKey(args.slot))
496
+ throw new LkgRecoveryFenceError("Last-good commit did not match its certificate");
497
+ if (args.retainDirtyRevision || args.cleanDigest !== undefined && hash(saved.jsonPrefix) !== args.cleanDigest)
498
+ return true;
499
+ const dirty = read(args.sessionId);
500
+ if (dirty?.state === "dirty")
501
+ publish(args.sessionId, saved, "clean", dirty.revision);
502
+ else
503
+ remember(args.sessionId, { state: "clean", record: null });
504
+ return true;
505
+ });
506
+ }
507
+ function clearLkgRecoveryFence(sessionId, remove, shouldClear) {
508
+ if (!durableFencesSupported())
509
+ return remove?.();
510
+ return locked(sessionId, () => {
511
+ const result = remove?.();
512
+ if (shouldClear && !shouldClear(result))
513
+ return result;
514
+ rmSync2(lkgRecoveryFencePath(sessionId), { force: true });
515
+ syncStorageDirectorySync(dirname(lkgRecoveryFencePath(sessionId)));
516
+ clearLkgFenceProcessState(sessionId);
517
+ return result;
518
+ });
519
+ }
65
520
 
66
521
  // src/features/magic-context/session-activity.ts
67
522
  var PREFIX = "retrospective_activity:";
@@ -224,6 +679,8 @@ function deleteSessionScopedRows(db, sessionIds, harness, options = {}) {
224
679
  retire.run(tagIdentityRevisionKey(id), tagRevisionKey(id), ...harnessTables.map(() => id), ...tagTombstoneOwnerRange(id));
225
680
  }
226
681
  }
682
+ for (const sessionId of deletableSessionIds)
683
+ clearLkgRecoveryFence(sessionId);
227
684
  return deletableSessionIds.length;
228
685
  }
229
686
 
@@ -456,7 +913,7 @@ function toMessageIndexSource(message) {
456
913
  role: message.role,
457
914
  createdAt: message.createdAt,
458
915
  sourceVersion: normalizeSourceVersion(message.version),
459
- contentHash: createHash("sha256").update(content).digest("hex"),
916
+ contentHash: createHash3("sha256").update(content).digest("hex"),
460
917
  content
461
918
  };
462
919
  }
@@ -793,4 +1250,4 @@ function sweepOrphanedOpenCodeMessageIndexes(db, openReadableOpenCodeDb, options
793
1250
  return withoutSqliteTransformPass2(() => withSqliteBackgroundWriter2(() => sweepOrphanedOpenCodeMessageIndexesInBackground(db, openReadableOpenCodeDb, options)));
794
1251
  }
795
1252
 
796
- export { clearCompressionDepth, clearCompressionDepthRange, advanceSessionActivity, backfillSessionActivity, deleteSessionScopedRows, MESSAGE_INDEX_MAX_FTS_BYTES, messageIndexSkipKey, toMessageIndexSource, getLastIndexedOrdinal, getIndexedMessageCorpusSize, markMessageIndexDirty, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, clearIndexedMessagesInTransaction, getIndexableContent, indexSingleMessage, indexMessagesAfterOrdinal, indexSourcesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes };
1253
+ export { BoundedSessionMap, clearCompressionDepth, clearCompressionDepthRange, LkgRecoveryFenceError, clearLkgFenceProcessState, lkgServedArrayDigest, hasCleanLkgRecoveryFence, lkgFenceRequiresRebuild, lkgRecoveryFenceUnclean, dirtyLkgRecoveryRevision, ownsLkgDirtyFence, invalidateCleanLkgRecoveryFence, prepareLkgCaptureFence, certifyCommittedLkgCapture, markLkgRecoveryDirty, commitLkgWithRecoveryFence, clearLkgRecoveryFence, advanceSessionActivity, backfillSessionActivity, deleteSessionScopedRows, MESSAGE_INDEX_MAX_FTS_BYTES, messageIndexSkipKey, toMessageIndexSource, getLastIndexedOrdinal, getIndexedMessageCorpusSize, markMessageIndexDirty, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, clearIndexedMessagesInTransaction, getIndexableContent, indexSingleMessage, indexMessagesAfterOrdinal, indexSourcesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes };