@cortexkit/opencode-magic-context 0.49.6 → 0.49.8

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 (255) hide show
  1. package/dist/auto-search-worker.js +10 -7
  2. package/dist/compaction-marker-candidates-worker.js +2 -2
  3. package/dist/{compaction-marker-candidates-cz72pm1t.js → compaction-marker-candidates-xxz35vwp.js} +3 -3
  4. package/dist/{conflict-warning-hook-1jq1rxx7.js → conflict-warning-hook-w3crzrar.js} +8 -8
  5. package/dist/{context-ae3gxdye.js → context-x0ccfv0f.js} +88 -53
  6. package/dist/{derive-budgets-j4ry8j8n.js → derive-budgets-3nbxsyss.js} +2 -2
  7. package/dist/embedding-backfill-3h2m5n0q.js +21 -0
  8. package/dist/embedding-worker-process.js +6 -2
  9. package/dist/embedding-worker.js +6 -5
  10. package/dist/features/magic-context/compaction-marker-candidates.d.ts.map +1 -1
  11. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  12. package/dist/features/magic-context/dreamer/cron.d.ts +2 -0
  13. package/dist/features/magic-context/dreamer/cron.d.ts.map +1 -1
  14. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts +6 -3
  15. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -1
  16. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +7 -1
  17. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
  18. package/dist/features/magic-context/dreamer/map-memories.d.ts +2 -2
  19. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/primer-seed.d.ts +2 -0
  21. package/dist/features/magic-context/dreamer/primer-seed.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/provider-output-failure.d.ts +1 -0
  23. package/dist/features/magic-context/dreamer/provider-output-failure.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +2 -2
  25. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  26. package/dist/features/magic-context/memory/embedding-worker-client.d.ts.map +1 -1
  27. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  28. package/dist/features/magic-context/migration-worker-client.d.ts.map +1 -1
  29. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  30. package/dist/features/magic-context/smart-notes/wake-plane.d.ts.map +1 -1
  31. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  32. package/dist/features/magic-context/storage-meta-persisted.d.ts +10 -3
  33. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  34. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  35. package/dist/features/magic-context/storage-replay-document.d.ts +4 -0
  36. package/dist/features/magic-context/storage-replay-document.d.ts.map +1 -1
  37. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  38. package/dist/history-owner-ty29fz0f.js +244 -0
  39. package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
  40. package/dist/hooks/magic-context/apply-operations.d.ts +7 -0
  41. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  42. package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
  43. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  44. package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
  45. package/dist/hooks/magic-context/edit-marker.d.ts +2 -0
  46. package/dist/hooks/magic-context/edit-marker.d.ts.map +1 -1
  47. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  48. package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -1
  49. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  50. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  51. package/dist/hooks/magic-context/module-transport.d.ts +1 -0
  52. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  53. package/dist/hooks/magic-context/note-nudger.d.ts +5 -3
  54. package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/postprocess-read-cache.d.ts.map +1 -1
  56. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/read-session-chunk.d.ts +15 -4
  58. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  59. package/dist/hooks/magic-context/replay-committed-drops.d.ts +9 -0
  60. package/dist/hooks/magic-context/replay-committed-drops.d.ts.map +1 -0
  61. package/dist/hooks/magic-context/rust-lkg-freeze-registry.d.ts +2 -2
  62. package/dist/hooks/magic-context/rust-lkg-freeze-registry.d.ts.map +1 -1
  63. package/dist/hooks/magic-context/rust-mode-transform.d.ts +4 -0
  64. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  65. package/dist/hooks/magic-context/rust-refusal-recovery.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/rust-served-raw.d.ts +29 -0
  67. package/dist/hooks/magic-context/rust-served-raw.d.ts.map +1 -0
  68. package/dist/hooks/magic-context/strip-content.d.ts +23 -24
  69. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/tag-messages.d.ts +2 -0
  71. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/tool-drop-target.d.ts +2 -0
  73. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  74. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  75. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/unresolved-history-boundary.d.ts +5 -1
  77. package/dist/hooks/magic-context/unresolved-history-boundary.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  79. package/dist/{index-g9exahnx.js → index-0jz47061.js} +6 -3
  80. package/dist/{index-4mjhqadz.js → index-150zz6fh.js} +1 -1
  81. package/dist/{index-ch08qwgd.js → index-2rw244rh.js} +88 -81
  82. package/dist/{index-6q5h70h2.js → index-4hb8nt93.js} +3 -3
  83. package/dist/{index-j55vn694.js → index-7bjgyaj1.js} +4 -4
  84. package/dist/{index-h2wc01qk.js → index-8kk7yh6m.js} +2 -2
  85. package/dist/{index-vztbgcdk.js → index-9g1c4bt9.js} +304 -92
  86. package/dist/{index-7q1m1qjk.js → index-a43xq1pg.js} +5 -5
  87. package/dist/{index-tqf7yg27.js → index-a4b0gbyg.js} +1 -1
  88. package/dist/{index-vnjhmkwk.js → index-angx1s0k.js} +4 -3
  89. package/dist/{index-1xaw2pq8.js → index-b4gcb3rk.js} +8 -8
  90. package/dist/{index-z1tjp257.js → index-b64n4d0h.js} +1 -1
  91. package/dist/{index-1bt88epp.js → index-bd9cjab3.js} +1 -1
  92. package/dist/{index-gbmqa9x9.js → index-bmwfzz28.js} +9 -6
  93. package/dist/{index-qx53vezw.js → index-gjvjh960.js} +1 -1
  94. package/dist/{index-zgzdm6dg.js → index-gzg9ekc1.js} +155 -103
  95. package/dist/{index-vh3e2mvr.js → index-hxrvx6cy.js} +121 -51
  96. package/dist/{index-w23dh319.js → index-jw4gbfkv.js} +1 -1
  97. package/dist/index-knvkbfvh.js +25 -0
  98. package/dist/{index-vkbqdnkj.js → index-kvw6xew3.js} +6 -3
  99. package/dist/{index-bg5qqene.js → index-mp2kghkv.js} +3 -27
  100. package/dist/{index-nsjyysj0.js → index-mvvephtj.js} +5 -1
  101. package/dist/{index-cm4hmxyk.js → index-n78avt2p.js} +1 -1
  102. package/dist/{index-hr64sth2.js → index-pgy3h49n.js} +4 -4
  103. package/dist/{index-a796ct3s.js → index-pjgzdezw.js} +13 -9
  104. package/dist/{index-9m7bn21d.js → index-q28hsbpg.js} +15 -3
  105. package/dist/{index-ab3bgm2m.js → index-q76br5zn.js} +3 -3
  106. package/dist/{index-xqyj5c85.js → index-qgp5vnt4.js} +5 -5
  107. package/dist/{index-9s58tq95.js → index-rg1cezmj.js} +22 -22
  108. package/dist/{index-f3dnvnw6.js → index-s178h9z8.js} +4 -3
  109. package/dist/{index-mj1fgfrk.js → index-w1ejb9qr.js} +939 -160
  110. package/dist/{index-k6xvbj2e.js → index-w28y7d0z.js} +2 -0
  111. package/dist/{index-0nnd4bry.js → index-wafzvyhg.js} +63 -19
  112. package/dist/{index-ck6y3td2.js → index-xf6k8szp.js} +4 -4
  113. package/dist/{index-1j8jcjpa.js → index-xpn05jxq.js} +4 -4
  114. package/dist/{index-s0gsmthp.js → index-ydjgz36f.js} +7 -7
  115. package/dist/{index-besxhcsh.js → index-zf9nydbd.js} +50 -39
  116. package/dist/index.js +53 -52
  117. package/dist/{logger-ewak5q1s.js → logger-wn328tfg.js} +1 -1
  118. package/dist/{message-index-bounded-630j53ps.js → message-index-bounded-hxjp56qk.js} +16 -16
  119. package/dist/{message-index-c84wm2g0.js → message-index-zs882h8e.js} +16 -16
  120. package/dist/{message-time-backfill-8kj57qe3.js → message-time-backfill-nb5hhnrt.js} +3 -3
  121. package/dist/migration-worker.js +11 -11
  122. package/dist/plugin/boot-quiet.d.ts.map +1 -1
  123. package/dist/plugin/dream-timer.d.ts.map +1 -1
  124. package/dist/plugin/messages-transform.d.ts.map +1 -1
  125. package/dist/plugin/rpc-handlers.d.ts +2 -0
  126. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  127. package/dist/{project-embedding-registry-vv59t7ah.js → project-embedding-registry-vy7sv9jt.js} +11 -11
  128. package/dist/raw-ordinal-warmup-worker.js +17 -15
  129. package/dist/{read-session-chunk-t3vjd0h0.js → read-session-chunk-t9r7r0sg.js} +13 -11
  130. package/dist/{read-session-raw-gf7eytnm.js → read-session-raw-gm6xj30v.js} +3 -3
  131. package/dist/recomp-orchestrator-gr36zvd2.js +60 -0
  132. package/dist/{safe-notification-target-q0cyrx3x.js → safe-notification-target-jdynm677.js} +2 -2
  133. package/dist/{search-kth2p6cc.js → search-qjen1pmz.js} +24 -24
  134. package/dist/{send-session-notification-3j6krd4w.js → send-session-notification-q8ngbap3.js} +6 -6
  135. package/dist/shared/history-owner.d.ts +12 -0
  136. package/dist/shared/history-owner.d.ts.map +1 -0
  137. package/dist/shared/off-thread-migration-clock.d.ts +8 -1
  138. package/dist/shared/off-thread-migration-clock.d.ts.map +1 -1
  139. package/dist/shared/processed-image-eligibility.d.ts +22 -0
  140. package/dist/shared/processed-image-eligibility.d.ts.map +1 -0
  141. package/dist/shared/recovery-reasoning-prefix.d.ts +9 -0
  142. package/dist/shared/recovery-reasoning-prefix.d.ts.map +1 -0
  143. package/dist/shared/redaction.d.ts.map +1 -1
  144. package/dist/shared/rpc-server.d.ts.map +1 -1
  145. package/dist/shared/sqlite.d.ts +3 -1
  146. package/dist/shared/sqlite.d.ts.map +1 -1
  147. package/dist/shared/tag-transcript.d.ts +9 -0
  148. package/dist/shared/tag-transcript.d.ts.map +1 -1
  149. package/dist/shared/user-facing-codes.d.ts +2 -2
  150. package/dist/{sqlite-d7edbk1s.js → sqlite-4pqyynrs.js} +3 -1
  151. package/dist/{storage-memory-af5zdz98.js → storage-memory-j3v3hc83.js} +2 -2
  152. package/dist/{storage-tags-dyj7mmbq.js → storage-tags-a513rkj3.js} +5 -5
  153. package/dist/tools/ctx-expand/search-archive.d.ts +4 -0
  154. package/dist/tools/ctx-expand/search-archive.d.ts.map +1 -0
  155. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  156. package/dist/{transform-postprocess-phase-bv3kb5s1.js → transform-postprocess-phase-yv463b7y.js} +30 -30
  157. package/dist/v2/auto-search-worker.js +10 -7
  158. package/dist/v2/{compaction-marker-candidates-6gqp5wrc.js → compaction-marker-candidates-a15w3mqh.js} +3 -3
  159. package/dist/v2/compaction-marker-candidates-worker.js +2 -2
  160. package/dist/v2/{context-p8f2shp1.js → context-wd82v9z6.js} +1133 -278
  161. package/dist/v2/{derive-budgets-enckmg7y.js → derive-budgets-0rmpmxjw.js} +3 -3
  162. package/dist/v2/embedding-backfill-vr7wdtrf.js +20 -0
  163. package/dist/v2/embedding-worker-process.js +6 -2
  164. package/dist/v2/embedding-worker.js +6 -5
  165. package/dist/v2/hidden-completion.d.ts.map +1 -1
  166. package/dist/v2/history-owner-2cr9py37.js +243 -0
  167. package/dist/v2/hooks/context.d.ts.map +1 -1
  168. package/dist/v2/hooks/payload.d.ts.map +1 -1
  169. package/dist/v2/hooks/store.d.ts +1 -0
  170. package/dist/v2/hooks/store.d.ts.map +1 -1
  171. package/dist/v2/{logger-pj02s7sr.js → logger-te6e1j72.js} +1 -1
  172. package/dist/v2/{message-index-bounded-yzxmf6vp.js → message-index-bounded-madg2kfr.js} +16 -16
  173. package/dist/v2/{message-index-3ws17x1g.js → message-index-yd94vt9n.js} +16 -16
  174. package/dist/v2/{message-time-backfill-5nf10c65.js → message-time-backfill-rz1pnpaj.js} +3 -3
  175. package/dist/v2/migration-worker.js +11 -11
  176. package/dist/v2/{project-embedding-registry-rsnf2263.js → project-embedding-registry-ja23aygk.js} +11 -11
  177. package/dist/v2/raw-ordinal-warmup-worker.js +17 -15
  178. package/dist/v2/{read-session-chunk-vtb0w2kd.js → read-session-chunk-7qs791f3.js} +13 -11
  179. package/dist/v2/{read-session-raw-gpcddemt.js → read-session-raw-h4azh85b.js} +3 -3
  180. package/dist/v2/recomp-orchestrator-ee91r9s6.js +59 -0
  181. package/dist/v2/{safe-notification-target-y3p1hce9.js → safe-notification-target-936374xx.js} +2 -2
  182. package/dist/v2/search-pn15rr52.js +46 -0
  183. package/dist/v2/{send-session-notification-5aj2j7vf.js → send-session-notification-6n7chhyp.js} +6 -6
  184. package/dist/v2/{server-09g9pkvx.js → server-08k4zkfk.js} +50 -39
  185. package/dist/v2/{server-ras2sxnc.js → server-44ryn9rb.js} +9 -6
  186. package/dist/v2/{server-158ehmk2.js → server-4easnf78.js} +19 -19
  187. package/dist/v2/{server-ww9nr8pe.js → server-4gz0xkrc.js} +5 -5
  188. package/dist/v2/{server-d6g4whc2.js → server-4qr18rfg.js} +3 -3
  189. package/dist/v2/{server-f9py7s7a.js → server-4rs8sm06.js} +5 -5
  190. package/dist/v2/{server-yezz0cp2.js → server-63ha7f0f.js} +3 -27
  191. package/dist/v2/{server-3t0q2cqx.js → server-7dv9wt9r.js} +1 -1
  192. package/dist/v2/{server-cw6521wn.js → server-7e087rvk.js} +2 -0
  193. package/dist/v2/{server-hb6xhh9q.js → server-988cqjme.js} +6 -3
  194. package/dist/v2/{server-keswwkvv.js → server-9a6bwc12.js} +4 -4
  195. package/dist/v2/{server-t4k4qexw.js → server-9e5r8y60.js} +5 -1
  196. package/dist/v2/{server-7ekna9zs.js → server-adfte03x.js} +2 -2
  197. package/dist/v2/{server-9zqewm6g.js → server-ak7w74j9.js} +4 -4
  198. package/dist/v2/{server-387vkhjq.js → server-bx59ezg6.js} +4 -3
  199. package/dist/v2/{server-676xw7at.js → server-ckrb5rm8.js} +1 -1
  200. package/dist/v2/{server-wrem2nmz.js → server-cxsr0ng6.js} +15 -3
  201. package/dist/v2/{server-t528t8qm.js → server-hn9fb3v0.js} +2 -2
  202. package/dist/v2/{server-qn23p4h7.js → server-j3dm74ey.js} +9 -9
  203. package/dist/v2/{server-yd01snxq.js → server-jjsf29aq.js} +4 -4
  204. package/dist/v2/server-knvkbfvh.js +25 -0
  205. package/dist/v2/{server-cm4hmxyk.js → server-n78avt2p.js} +1 -1
  206. package/dist/v2/{server-btgnsv7w.js → server-njnx39q2.js} +6 -3
  207. package/dist/v2/{server-6a9mxnb2.js → server-npm52h2q.js} +4 -3
  208. package/dist/v2/{server-vb7pbd9p.js → server-nveratm5.js} +1 -1
  209. package/dist/v2/{server-7skbfb81.js → server-q360kdb8.js} +121 -51
  210. package/dist/v2/{server-kzns2hbz.js → server-s6jqh8bj.js} +1 -1
  211. package/dist/v2/{server-6byqfbqf.js → server-shme41gj.js} +1 -1
  212. package/dist/v2/{server-0nnd4bry.js → server-wafzvyhg.js} +63 -19
  213. package/dist/v2/{server-fby0cxbq.js → server-xj4mewze.js} +304 -92
  214. package/dist/v2/{server-aa9w15cs.js → server-y5g32dhq.js} +88 -81
  215. package/dist/v2/{server-x2r63c0x.js → server-yak3sxya.js} +7 -7
  216. package/dist/v2/{server-4tn95znb.js → server-zrwaj29a.js} +2 -2
  217. package/dist/v2/server.js +9 -8
  218. package/dist/v2/{sqlite-d7edbk1s.js → sqlite-4pqyynrs.js} +3 -1
  219. package/dist/v2/{storage-memory-af5zdz98.js → storage-memory-j3v3hc83.js} +2 -2
  220. package/dist/v2/{storage-tags-d47bpaqa.js → storage-tags-spa92sgj.js} +5 -5
  221. package/dist/v2/store-reader.d.ts.map +1 -1
  222. package/dist/v2/{wrapup-orchestrator-cahk37n7.js → wrapup-orchestrator-5wxy1ggv.js} +38 -35
  223. package/dist/wrapup-orchestrator-gv08c6f9.js +47 -0
  224. package/package.json +3 -3
  225. package/src/config/compaction-accessor-guard.test.ts +3 -0
  226. package/src/features/magic-context/dreamer/cron.ts +8 -0
  227. package/src/shared/history-owner.test.ts +60 -0
  228. package/src/shared/history-owner.ts +43 -0
  229. package/src/shared/host-stall-profiler-node.ts +3 -1
  230. package/src/shared/host-stall-profiler.ts +3 -1
  231. package/src/shared/off-thread-migration-clock.test.ts +80 -10
  232. package/src/shared/off-thread-migration-clock.ts +37 -13
  233. package/src/shared/processed-image-eligibility.test.ts +68 -0
  234. package/src/shared/processed-image-eligibility.ts +41 -0
  235. package/src/shared/processed-image-position-review.json +20 -0
  236. package/src/shared/processed-image-position-review.test.ts +19 -0
  237. package/src/shared/recovery-reasoning-prefix.test.ts +34 -0
  238. package/src/shared/recovery-reasoning-prefix.ts +35 -0
  239. package/src/shared/redaction.test.ts +16 -0
  240. package/src/shared/redaction.ts +8 -1
  241. package/src/shared/root-async-context.probe.mjs +36 -0
  242. package/src/shared/root-async-context.test.ts +49 -0
  243. package/src/shared/rpc-server.ts +27 -23
  244. package/src/shared/sqlite-busy-budget-review.test.ts +291 -0
  245. package/src/shared/sqlite-foreground-wait.test.ts +253 -1
  246. package/src/shared/sqlite-writer-diagnostics.test.ts +31 -0
  247. package/src/shared/sqlite.ts +112 -30
  248. package/src/shared/tag-transcript.ts +118 -0
  249. package/src/shared/user-facing-codes.ts +2 -2
  250. package/dist/embedding-backfill-dtjmyktb.js +0 -21
  251. package/dist/recomp-orchestrator-1d08g57a.js +0 -60
  252. package/dist/v2/embedding-backfill-cg4rv90f.js +0 -20
  253. package/dist/v2/recomp-orchestrator-v64r4s4r.js +0 -59
  254. package/dist/v2/search-bpa4fxq1.js +0 -46
  255. package/dist/wrapup-orchestrator-mqp0v195.js +0 -47
@@ -9,7 +9,7 @@ import {
9
9
  resolveLegacyConfigSources,
10
10
  getProtectedTokensTierOverrides,
11
11
  loadPluginConfigDetailed
12
- } from "./server-d6g4whc2.js";
12
+ } from "./server-4qr18rfg.js";
13
13
  import {
14
14
  getHarness2,
15
15
  harnessOwnsOpenCodeStore2
@@ -24,7 +24,7 @@ import {
24
24
  log2,
25
25
  sessionLog2,
26
26
  getLoggerDiagnostics2
27
- } from "./server-t4k4qexw.js";
27
+ } from "./server-9e5r8y60.js";
28
28
  import {
29
29
  hasTrustedAbsoluteWall,
30
30
  applyProvenInputFloor,
@@ -36,7 +36,7 @@ import {
36
36
  getSdkContextLimit,
37
37
  getSdkOutputLimit,
38
38
  getModelsDevCacheState
39
- } from "./server-vb7pbd9p.js";
39
+ } from "./server-nveratm5.js";
40
40
  import {
41
41
  withContentLanguageDirective,
42
42
  parseCron,
@@ -48,7 +48,7 @@ import {
48
48
  DEFAULT_HISTORIAN_TIMEOUT_MS,
49
49
  DEFAULT_LOCAL_EMBEDDING_MODEL,
50
50
  DREAM_TASK_PROMOTION_DEFAULTS
51
- } from "./server-cw6521wn.js";
51
+ } from "./server-7e087rvk.js";
52
52
  import {
53
53
  historianRunConfig,
54
54
  dreamerRunConfig,
@@ -109,6 +109,8 @@ import {
109
109
  resolveLkgModelKeys,
110
110
  createLkgEntryProjector,
111
111
  captureLkgSlot,
112
+ validateAnthropicReasoningRuns,
113
+ validateLkgSeam,
112
114
  replayLkg,
113
115
  coldStartRawServedIndex,
114
116
  coldStartUncapturedReplay,
@@ -263,7 +265,7 @@ import {
263
265
  startCompartmentAgent,
264
266
  setRecompStarting2,
265
267
  setRecompTerminal2
266
- } from "./server-7skbfb81.js";
268
+ } from "./server-q360kdb8.js";
267
269
  import {
268
270
  CANONICAL_DREAM_TASKS,
269
271
  DREAM_TASK_CAPABILITIES,
@@ -301,7 +303,7 @@ import {
301
303
  openDatabaseAsync,
302
304
  isDatabasePersisted,
303
305
  getDatabasePersistenceError
304
- } from "./server-09g9pkvx.js";
306
+ } from "./server-08k4zkfk.js";
305
307
  import {
306
308
  setHomeProjectPermission,
307
309
  shouldSkipHomeProjectMemory,
@@ -317,7 +319,7 @@ import {
317
319
  storedPathBelongsToIdentity,
318
320
  beginBootQuietPeriod,
319
321
  scheduleAfterBootQuiet
320
- } from "./server-btgnsv7w.js";
322
+ } from "./server-njnx39q2.js";
321
323
  import {
322
324
  detectLatestTurnThinkingMismatch,
323
325
  isPrefixBoundThinkingModel,
@@ -346,6 +348,8 @@ import {
346
348
  sessionDecisionCalibration,
347
349
  transitionSessionHygieneUnits,
348
350
  getProtectionWindowForSession,
351
+ withReplayEnvelopeSnapshot,
352
+ invalidateReplayEnvelopeSnapshot,
349
353
  isRustMarkerAdmissionFenced,
350
354
  setRustMarkerAdmissionFence,
351
355
  ReplayDocumentError,
@@ -415,6 +419,7 @@ import {
415
419
  getStaleReduceStrippedIds,
416
420
  addStaleReduceStrippedIds,
417
421
  getProcessedImageStrippedIds,
422
+ getProcessedImageMarkers,
418
423
  addProcessedImageStrippedIds,
419
424
  getPendingCompactionMarkerState,
420
425
  getCompactionMarkerHealth,
@@ -424,6 +429,7 @@ import {
424
429
  clearPendingCompactionMarkerStateIf,
425
430
  getPendingPiCompactionMarkerState,
426
431
  clearPendingPiCompactionMarkerStateIf,
432
+ logPiCompactionMarkerClear,
427
433
  setSessionWorkMetrics,
428
434
  getObservedEpochFloor,
429
435
  resolveEpochFloorForPass,
@@ -458,6 +464,7 @@ import {
458
464
  stripReasoningFromAssistantIds,
459
465
  findMergedReasoningStripDecisions,
460
466
  stripReasoningFromMergedAssistants,
467
+ getEmptyImageParts,
461
468
  stripProcessedImages,
462
469
  projectOpencodeReasoningBudgetCutoff,
463
470
  DEFAULT_KEEP_REASONING_TOKENS,
@@ -483,6 +490,7 @@ import {
483
490
  withRawSessionMessageCache2,
484
491
  readRawSessionMessages2,
485
492
  visitRawSessionMessages2,
493
+ visitRawSessionMessagesAsync2,
486
494
  prepareRawSessionOrdinals2,
487
495
  primeTailRawMessageCache2,
488
496
  primeInMemoryTailRawMessageCache2,
@@ -491,11 +499,12 @@ import {
491
499
  readRawSessionMessageIdOrdinalsForRange2,
492
500
  readRawSessionMessagePartsById2,
493
501
  readRawSessionBoundaryEndpoints2,
502
+ hasRawSessionMessageById2,
494
503
  readRawSessionMessageOrdinalById2,
495
504
  readRawSessionMessageById2,
496
505
  readSessionChunk2,
497
506
  readRawSessionSeedTail2
498
- } from "./server-fby0cxbq.js";
507
+ } from "./server-xj4mewze.js";
499
508
  import {
500
509
  textMentionsRecentCommit,
501
510
  hasMeaningfulUserText2,
@@ -506,7 +515,7 @@ import {
506
515
  estimateTokens,
507
516
  estimateFixedPromptTokens,
508
517
  normalizeText
509
- } from "./server-kzns2hbz.js";
518
+ } from "./server-s6jqh8bj.js";
510
519
  import {
511
520
  SubcClient,
512
521
  connectionFileExists,
@@ -514,8 +523,9 @@ import {
514
523
  toSynapseLaneDescriptor,
515
524
  formatSynapseLaneDescriptor,
516
525
  SynapseEmbeddingProvider
517
- } from "./server-hb6xhh9q.js";
526
+ } from "./server-988cqjme.js";
518
527
  import {
528
+ inRootAsyncContext2,
519
529
  getTagIdentityWriteGeneration2,
520
530
  Database2,
521
531
  getSqliteDatabasePath2,
@@ -527,21 +537,18 @@ import {
527
537
  isTransientSqliteError2,
528
538
  SqliteAcquisitionBusyError2,
529
539
  withAsyncPrivilegedWriter2
530
- } from "./server-0nnd4bry.js";
531
- import {
532
- sameProjectDirectory,
533
- canonicalProjectDirectory
534
- } from "./server-yezz0cp2.js";
540
+ } from "./server-wafzvyhg.js";
541
+ import"./server-63ha7f0f.js";
535
542
  import {
536
543
  deleteChunkEmbedBackoffForSession
537
- } from "./server-keswwkvv.js";
544
+ } from "./server-9a6bwc12.js";
538
545
  import {
539
546
  registerOwnRpcServerInstance,
540
547
  rpcPortDir,
541
548
  rpcPortFilePath,
542
549
  parseRpcPortFile,
543
550
  inspectProcessesAsync
544
- } from "./server-wrem2nmz.js";
551
+ } from "./server-cxsr0ng6.js";
545
552
  import {
546
553
  BoundedSessionMap,
547
554
  LkgRecoveryFenceError,
@@ -560,14 +567,14 @@ import {
560
567
  isMessageIndexReconciledThrough2,
561
568
  indexMessagesAfterOrdinal2,
562
569
  sweepOrphanedOpenCodeMessageIndexes2
563
- } from "./server-qn23p4h7.js";
570
+ } from "./server-j3dm74ey.js";
564
571
  import {
565
572
  stableStringify,
566
573
  getTemporalDecisions,
567
574
  observeTemporalDecisions,
568
575
  freezeTemporalDecisions,
569
576
  tagIdentityRevisionKey
570
- } from "./server-6byqfbqf.js";
577
+ } from "./server-shme41gj.js";
571
578
  import {
572
579
  resolveModelCalibration,
573
580
  calibrateBuckets,
@@ -659,14 +666,14 @@ import {
659
666
  adoptNullOwnerToolTag2,
660
667
  getCandidateToolOwners2,
661
668
  pickNearestPriorOwner2
662
- } from "./server-yd01snxq.js";
669
+ } from "./server-jjsf29aq.js";
663
670
  import"./server-51779zs2.js";
664
671
  import {
665
672
  isRawCompactionSummaryInfo2,
666
673
  extractInMemoryMessageViews2,
667
674
  buildInMemoryTailRawMessages2,
668
675
  runSessionWarmupWorker
669
- } from "./server-387vkhjq.js";
676
+ } from "./server-bx59ezg6.js";
670
677
  import {
671
678
  resolveOpenCodeDbPath,
672
679
  assertOpenCodeStoreGeneration,
@@ -682,12 +689,12 @@ import {
682
689
  latestRealUserTurnIdFromOpenCodeDb,
683
690
  getMessageTimesFromOpenCodeDb,
684
691
  findLastAssistantModelFromOpenCodeDb
685
- } from "./server-4tn95znb.js";
692
+ } from "./server-zrwaj29a.js";
686
693
  import {
687
694
  getCurrentToolSetHash,
688
695
  recordToolDefinition,
689
696
  getMeasuredToolDefinitionTokens
690
- } from "./server-7ekna9zs.js";
697
+ } from "./server-adfte03x.js";
691
698
  import {
692
699
  V2_MEMORY_CATEGORIES,
693
700
  CATEGORY_PRIORITY
@@ -700,7 +707,7 @@ import {
700
707
  resolveStoredPathWorkspaceIdentity,
701
708
  storedPathBelongsToWorkspace,
702
709
  computeWorkspaceEpochFingerprint
703
- } from "./server-ww9nr8pe.js";
710
+ } from "./server-4gz0xkrc.js";
704
711
  import {
705
712
  GIT_SWEEP_LEASE_RENEWAL_MS,
706
713
  acquireGitSweepLease,
@@ -727,7 +734,7 @@ import {
727
734
  drainCommitBacklogForProject2,
728
735
  embedSessionCompartmentChunks2,
729
736
  getEmbeddingCoverageStatus2
730
- } from "./server-158ehmk2.js";
737
+ } from "./server-4easnf78.js";
731
738
  import"./server-fb3zxn06.js";
732
739
  import {
733
740
  SESSION_NOTE_CONDITION_ERROR,
@@ -771,15 +778,15 @@ import {
771
778
  readGitFileChangeTimesSince,
772
779
  verificationFileExists,
773
780
  normalizeVerificationFiles
774
- } from "./server-x2r63c0x.js";
781
+ } from "./server-yak3sxya.js";
775
782
  import {
776
783
  deriveTriggerBudget2,
777
784
  deriveHistorianChunkTokens2,
778
785
  resolveKnownHistorianContextLimit2,
779
786
  resolveHistorianProducerLimits2,
780
787
  resolveHistorianContextLimit2
781
- } from "./server-t528t8qm.js";
782
- import"./server-6a9mxnb2.js";
788
+ } from "./server-hn9fb3v0.js";
789
+ import"./server-npm52h2q.js";
783
790
  import {
784
791
  isEmbeddingHostBusy2
785
792
  } from "./server-qt1qqasc.js";
@@ -790,10 +797,10 @@ import {
790
797
  } from "./server-4dhv7mqz.js";
791
798
  import {
792
799
  getLocalEmbeddingNativeMemoryStats
793
- } from "./server-ras2sxnc.js";
800
+ } from "./server-44ryn9rb.js";
794
801
  import {
795
802
  cosineSimilarity
796
- } from "./server-f9py7s7a.js";
803
+ } from "./server-4rs8sm06.js";
797
804
  import {
798
805
  computeCueContentHash,
799
806
  hasMuralCueColumns,
@@ -818,7 +825,7 @@ import {
818
825
  mergeMemoryStats2,
819
826
  archiveMemory2,
820
827
  getMemoryCountsByStatus2
821
- } from "./server-cm4hmxyk.js";
828
+ } from "./server-n78avt2p.js";
822
829
  import {
823
830
  registerNotificationSink2,
824
831
  pushNotification2,
@@ -826,11 +833,11 @@ import {
826
833
  drainNotifications2,
827
834
  isTuiConnected2
828
835
  } from "./server-x8a7jmkh.js";
829
- import"./server-676xw7at.js";
836
+ import"./server-ckrb5rm8.js";
830
837
  import {
831
838
  flushIgnoredMessages2,
832
839
  sendStatusNotification2
833
- } from "./server-9zqewm6g.js";
840
+ } from "./server-ak7w74j9.js";
834
841
  import {
835
842
  renderSingleStoreMigrationRequiredRefusal,
836
843
  SingleStoreMigrationRequiredError,
@@ -845,12 +852,13 @@ import {
845
852
  SubcModuleTransport,
846
853
  indexCommitsForProject,
847
854
  embedUnembeddedCommits,
855
+ withMessageFtsSessionFilter,
848
856
  createUnifiedSearchDiagnostics2,
849
857
  parseIdShapedQuery2,
850
858
  resolveMemoriesByIdsForSearch2,
851
859
  unifiedSearch2,
852
860
  formatSearchResults2
853
- } from "./server-aa9w15cs.js";
861
+ } from "./server-y5g32dhq.js";
854
862
  import {
855
863
  resolvePromptContext2
856
864
  } from "./server-fmsr7v69.js";
@@ -864,6 +872,10 @@ import {
864
872
  import {
865
873
  computeNormalizedHash
866
874
  } from "./server-2bvekkfy.js";
875
+ import {
876
+ sameProjectDirectory,
877
+ canonicalProjectDirectory
878
+ } from "./server-knvkbfvh.js";
867
879
  import {
868
880
  getErrorMessage,
869
881
  describeError
@@ -890,7 +902,7 @@ import {
890
902
  } from "./server-8ajstryz.js";
891
903
  import {
892
904
  logSlowWriteTransaction
893
- } from "./server-3t0q2cqx.js";
905
+ } from "./server-7dv9wt9r.js";
894
906
 
895
907
  // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/external.js
896
908
  var exports_external = {};
@@ -2782,6 +2794,7 @@ function forgetCachedPrefix(sessionId) {
2782
2794
  function dropCompartmentsAfter(db, sessionId, anchor, holderId, activeBranch = false, onRetire) {
2783
2795
  db.exec("BEGIN IMMEDIATE");
2784
2796
  let finished = false;
2797
+ let clearedMarker = null;
2785
2798
  try {
2786
2799
  if (!isCompartmentLeaseHeld(db, sessionId, holderId)) {
2787
2800
  db.exec("ROLLBACK");
@@ -2798,14 +2811,16 @@ function dropCompartmentsAfter(db, sessionId, anchor, holderId, activeBranch = f
2798
2811
  if (activeBranch) {
2799
2812
  db.prepare("UPDATE session_meta SET prior_boundary_ordinal = ? WHERE session_id = ?").run((anchor?.endMessage ?? 0) + 1, sessionId);
2800
2813
  const marker = getPendingPiCompactionMarkerState(db, sessionId);
2801
- if (marker)
2802
- clearPendingPiCompactionMarkerStateIf(db, sessionId, marker);
2814
+ if (marker && clearPendingPiCompactionMarkerStateIf(db, sessionId, marker, null))
2815
+ clearedMarker = marker;
2803
2816
  }
2804
2817
  deleteChunkEmbedBackoffForSession(db, sessionId);
2805
2818
  queueM0Mutation(db, { sessionId, mutationType: "recomp_boundary_change" });
2806
2819
  clearCachedM0M1(db, sessionId);
2807
2820
  db.exec("COMMIT");
2808
2821
  finished = true;
2822
+ if (clearedMarker)
2823
+ logPiCompactionMarkerClear(sessionId, clearedMarker, "active-branch-retired");
2809
2824
  return dropped.map((row) => row.sequence);
2810
2825
  } finally {
2811
2826
  if (!finished) {
@@ -2956,10 +2971,10 @@ async function sourceReady(source, sessionId) {
2956
2971
  function defer(fn) {
2957
2972
  const immediate = globalThis.setImmediate;
2958
2973
  if (typeof immediate === "function") {
2959
- immediate(fn);
2974
+ inRootAsyncContext2(() => immediate(fn));
2960
2975
  return;
2961
2976
  }
2962
- setTimeout(fn, 0);
2977
+ inRootAsyncContext2(() => setTimeout(fn, 0));
2963
2978
  }
2964
2979
  function yieldToEventLoop() {
2965
2980
  return new Promise((resolve) => defer(resolve));
@@ -3043,14 +3058,14 @@ function scheduleReconciliation(db, sessionId, readMessages) {
3043
3058
  reconcileSessionIndex(db, sessionId, readMessages).then((ran) => {
3044
3059
  if (ran)
3045
3060
  return;
3046
- setTimeout(() => {
3061
+ inRootAsyncContext2(() => setTimeout(() => {
3047
3062
  heapHolder.reconciliationScheduledSessions.delete(sessionId);
3048
3063
  scheduleReconciliation(db, sessionId, readMessages);
3049
- }, PREPARE_RETRY_MS).unref?.();
3064
+ }, PREPARE_RETRY_MS)).unref?.();
3050
3065
  }).catch((error) => {
3051
3066
  logIndexingError(sessionId, "reconciliation", error);
3052
3067
  if (isDatabaseLockedError(error))
3053
- setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000).unref();
3068
+ inRootAsyncContext2(() => setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000)).unref();
3054
3069
  }).finally(() => {
3055
3070
  heapHolder.reconciliationScheduledSessions.delete(sessionId);
3056
3071
  });
@@ -3860,7 +3875,7 @@ function queueAutoSearchBackfill(db, sessionId, projectPath, query) {
3860
3875
  pending.delete(key);
3861
3876
  resolve();
3862
3877
  };
3863
- const queued = setTimeout(() => {
3878
+ const queued = inRootAsyncContext2(() => setTimeout(() => {
3864
3879
  lifecycle.signal.removeEventListener("abort", cancel);
3865
3880
  if (lifecycle.signal.aborted)
3866
3881
  return done();
@@ -3871,7 +3886,7 @@ function queueAutoSearchBackfill(db, sessionId, projectPath, query) {
3871
3886
  clearTimeout(timeout);
3872
3887
  done();
3873
3888
  });
3874
- }, 0);
3889
+ }, 0));
3875
3890
  const cancel = () => {
3876
3891
  clearTimeout(queued);
3877
3892
  done();
@@ -3918,7 +3933,7 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
3918
3933
  deadlineUnixMs: autoSearchDeadlineUnixMs(deadlineSignal)
3919
3934
  };
3920
3935
  return new Promise((resolve, reject) => {
3921
- const worker = new Worker(entry, { workerData: input });
3936
+ const worker = inRootAsyncContext2(() => new Worker(entry, { workerData: input }));
3922
3937
  let settled = false;
3923
3938
  const finish = (results, error) => {
3924
3939
  if (settled)
@@ -4030,7 +4045,7 @@ function searchMessageHistoryOffThread(db, request, entry = defaultAutoSearchWor
4030
4045
  deadline.unref?.();
4031
4046
  };
4032
4047
  try {
4033
- worker = new Worker(entry, { workerData: input });
4048
+ worker = inRootAsyncContext2(() => new Worker(entry, { workerData: input }));
4034
4049
  } catch (error) {
4035
4050
  finish(null, "start-failed", error);
4036
4051
  return;
@@ -6483,21 +6498,40 @@ function buildReplacementContent(tagId) {
6483
6498
  return `[dropped §${tagId}§]`;
6484
6499
  }
6485
6500
  function applyNewToolDrop(target, options) {
6486
- if (!target)
6501
+ if (options.persist && (target?.prepareDrop?.() ?? target?.canDrop?.()) === false) {
6502
+ return { result: "incomplete", mode: "full" };
6503
+ }
6504
+ if (!target) {
6505
+ options.persist?.("full");
6487
6506
  return { result: "absent", mode: "full" };
6488
- if (options.inWindow && hasSmallToolInput(target) || options.keepSkeleton === true || target.cannotRemove?.() === true) {
6507
+ }
6508
+ if (options.inWindow && hasSmallToolInput(target) || options.keepSkeleton === true || target.cannotRemove?.() === true || target.wouldStrandConversationEnd?.() === true) {
6489
6509
  const strip = target.hasAttachments?.() === true;
6510
+ options.persist?.(strip ? "skeleton_stripped" : "skeleton_real");
6490
6511
  return {
6491
6512
  result: (strip ? target.skeletonStripped?.() : target.skeletonReal?.()) ?? "absent",
6492
6513
  mode: strip ? "skeleton_stripped" : "skeleton_real"
6493
6514
  };
6494
6515
  }
6516
+ options.persist?.("full");
6495
6517
  const result = target.drop?.() ?? "absent";
6496
6518
  if (result === "truncated" && target.hasAttachments?.() === true) {
6497
6519
  return { result: target.skeletonStripped?.() ?? "absent", mode: "skeleton_stripped" };
6498
6520
  }
6499
6521
  return { result, mode: result === "truncated" ? "skeleton_real" : "full" };
6500
6522
  }
6523
+ function applyPersistedToolDrop(db, sessionId, tagNumber, target, options, afterWrite) {
6524
+ return applyNewToolDrop(target, {
6525
+ ...options,
6526
+ persist: (mode) => {
6527
+ db.transaction(() => {
6528
+ updateTagDropMode2(db, sessionId, tagNumber, mode);
6529
+ updateTagStatus2(db, sessionId, tagNumber, "dropped");
6530
+ afterWrite?.();
6531
+ }).immediate();
6532
+ }
6533
+ });
6534
+ }
6501
6535
  function hasSmallToolInput(target) {
6502
6536
  const bytes = target?.inputStringBytes?.() ?? null;
6503
6537
  return bytes !== null && bytes <= SKELETON_REAL_INPUT_MAX_BYTES;
@@ -6577,11 +6611,11 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
6577
6611
  diagnostics.reasons[reason] = (diagnostics.reasons[reason] ?? 0) + 1;
6578
6612
  };
6579
6613
  let admitted = false;
6580
- let startedAt = 0;
6581
6614
  try {
6582
6615
  db.transaction(() => {
6583
6616
  admitted = true;
6584
- startedAt = performance.now();
6617
+ }).immediate();
6618
+ {
6585
6619
  const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
6586
6620
  const tags = preloadedTags ?? getTagsByNumbers2(db, sessionId, [
6587
6621
  ...new Set([
@@ -6633,10 +6667,31 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
6633
6667
  continue;
6634
6668
  }
6635
6669
  }
6670
+ const persistDrop = (mode) => {
6671
+ let startedAt = 0;
6672
+ try {
6673
+ db.transaction(() => {
6674
+ startedAt = performance.now();
6675
+ if (mode)
6676
+ updateTagDropMode2(db, sessionId, pendingOp.tagId, mode);
6677
+ updateTagStatus2(db, sessionId, pendingOp.tagId, "dropped");
6678
+ if (!synthetic)
6679
+ removePendingOp(db, sessionId, pendingOp.tagId);
6680
+ }).immediate();
6681
+ } finally {
6682
+ if (startedAt)
6683
+ logSlowWriteTransaction("apply_pending_operation", startedAt);
6684
+ }
6685
+ };
6636
6686
  let shouldPersistDrop = false;
6637
6687
  if (isToolTag) {
6638
6688
  if (editMarkerTagIds.has(pendingOp.tagId)) {
6639
6689
  const strip = target?.hasAttachments?.() === true;
6690
+ if (target?.canDrop?.() === false || target?.prepareDrop?.() === false || !target) {
6691
+ reject("edit_marker_incomplete");
6692
+ continue;
6693
+ }
6694
+ persistDrop(strip ? "edit_marker_stripped" : "edit_marker");
6640
6695
  const markResult = (strip ? target?.editMarkerStripped?.() : target?.editMarker?.()) ?? "absent";
6641
6696
  if (markResult === "incomplete" || markResult === "absent") {
6642
6697
  reject(`edit_marker_${markResult}`);
@@ -6645,11 +6700,11 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
6645
6700
  didMutateMessage = true;
6646
6701
  operationMutated = true;
6647
6702
  onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "edit_marker" });
6648
- updateTagDropMode2(db, sessionId, pendingOp.tagId, strip ? "edit_marker_stripped" : "edit_marker");
6649
6703
  shouldPersistDrop = true;
6650
6704
  } else {
6651
6705
  const { result: dropResult, mode: appliedMode } = applyNewToolDrop(target, {
6652
- inWindow: skeletonWindow.has(pendingOp.tagId)
6706
+ inWindow: skeletonWindow.has(pendingOp.tagId),
6707
+ persist: persistDrop
6653
6708
  });
6654
6709
  if (dropResult === "incomplete" || synthetic && dropResult !== "removed" && dropResult !== "truncated") {
6655
6710
  reject(`drop_${dropResult}`);
@@ -6665,12 +6720,12 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
6665
6720
  } else {
6666
6721
  reject(`drop_${dropResult}`);
6667
6722
  }
6668
- updateTagDropMode2(db, sessionId, pendingOp.tagId, appliedMode);
6669
6723
  shouldPersistDrop = true;
6670
6724
  }
6671
6725
  } else if (target) {
6672
6726
  const replacement = buildReplacementContent(pendingOp.tagId);
6673
6727
  const priorContent = target.getContent?.();
6728
+ persistDrop();
6674
6729
  const changed = target.setContent(replacement);
6675
6730
  if (changed) {
6676
6731
  didMutateMessage = true;
@@ -6687,30 +6742,25 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
6687
6742
  shouldPersistDrop = true;
6688
6743
  } else if (!synthetic) {
6689
6744
  reject("target_absent");
6745
+ persistDrop();
6690
6746
  shouldPersistDrop = true;
6691
6747
  }
6692
6748
  if (!shouldPersistDrop) {
6693
6749
  reject("not_persisted");
6694
6750
  continue;
6695
6751
  }
6696
- updateTagStatus2(db, sessionId, pendingOp.tagId, "dropped");
6697
- if (!synthetic)
6698
- removePendingOp(db, sessionId, pendingOp.tagId);
6699
6752
  if (operationMutated)
6700
6753
  diagnostics.mutated += 1;
6701
6754
  else
6702
6755
  diagnostics.persistedWithoutMutation += 1;
6703
6756
  }
6704
- }).immediate();
6757
+ }
6705
6758
  } catch (error) {
6706
6759
  if (!admitted && /database (?:table )?is locked|sqlite_(busy|locked)/i.test(String(error))) {
6707
6760
  sessionLog2(sessionId, "pending operations write admission busy; retaining prior bytes for retry");
6708
6761
  return false;
6709
6762
  }
6710
6763
  throw error;
6711
- } finally {
6712
- if (admitted)
6713
- logSlowWriteTransaction("apply_pending_operations", startedAt);
6714
6764
  }
6715
6765
  if (diagnostics) {
6716
6766
  onBatchComplete?.(diagnostics);
@@ -7208,31 +7258,27 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
7208
7258
  if (plan.shouldDrop) {
7209
7259
  const toDrop = new Set(plan.tagNumbers);
7210
7260
  const newestEmergencyTags = recentTags;
7211
- db.transaction(() => {
7212
- for (const tag of tags) {
7213
- if (!toDrop.has(tag.tagNumber))
7214
- continue;
7215
- if (tag.status !== "active" || tag.type !== "tool")
7216
- continue;
7217
- const target = targets.get(tag.tagNumber);
7218
- const recent = (emergency.usagePercentage ?? 0) < 95 && newestEmergencyTags.has(tag.tagNumber);
7219
- const { result, mode } = applyNewToolDrop(target, {
7220
- inWindow: recent,
7221
- keepSkeleton: target?.requiresToolArcSkeleton === true
7261
+ for (const tag of tags) {
7262
+ if (!toDrop.has(tag.tagNumber))
7263
+ continue;
7264
+ if (tag.status !== "active" || tag.type !== "tool")
7265
+ continue;
7266
+ const target = targets.get(tag.tagNumber);
7267
+ const recent = (emergency.usagePercentage ?? 0) < 95 && newestEmergencyTags.has(tag.tagNumber);
7268
+ const { result } = applyPersistedToolDrop(db, sessionId, tag.tagNumber, target, {
7269
+ inWindow: recent,
7270
+ keepSkeleton: target?.requiresToolArcSkeleton === true
7271
+ });
7272
+ if (result === "removed" || result === "truncated") {
7273
+ droppedTools++;
7274
+ emergencyDroppedTools++;
7275
+ droppedTokenReductions.push({
7276
+ tagNumber: tag.tagNumber,
7277
+ mode: result === "removed" ? "full" : "truncated"
7222
7278
  });
7223
- if (result === "removed" || result === "truncated") {
7224
- updateTagStatus2(db, sessionId, tag.tagNumber, "dropped");
7225
- updateTagDropMode2(db, sessionId, tag.tagNumber, mode);
7226
- droppedTools++;
7227
- emergencyDroppedTools++;
7228
- droppedTokenReductions.push({
7229
- tagNumber: tag.tagNumber,
7230
- mode: result === "removed" ? "full" : "truncated"
7231
- });
7232
- emergencyReclaimedTokens += estimateEmergencyDropReclaimTokens(measuredByTag.get(tag.tagNumber) ?? tag);
7233
- }
7279
+ emergencyReclaimedTokens += estimateEmergencyDropReclaimTokens(measuredByTag.get(tag.tagNumber) ?? tag);
7234
7280
  }
7235
- }).immediate();
7281
+ }
7236
7282
  sessionLog2(sessionId, `emergency tiered drop: ${plan.reason}`);
7237
7283
  } else {
7238
7284
  sessionLog2(sessionId, `emergency tiered drop skipped: ${plan.reason}`);
@@ -7313,35 +7359,33 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
7313
7359
  group.push(tag);
7314
7360
  fingerprintGroups.set(fingerprint, group);
7315
7361
  }
7316
- db.transaction(() => {
7317
- for (const [, group] of fingerprintGroups) {
7318
- if (group.length <= 1)
7362
+ for (const [, group] of fingerprintGroups) {
7363
+ if (group.length <= 1)
7364
+ continue;
7365
+ group.sort((a, b) => a.tagNumber - b.tagNumber);
7366
+ for (let i = 0;i < group.length - 1; i++) {
7367
+ const tag = group[i];
7368
+ if (config.protectedTagNumbers.has(tag.tagNumber))
7319
7369
  continue;
7320
- group.sort((a, b) => a.tagNumber - b.tagNumber);
7321
- for (let i = 0;i < group.length - 1; i++) {
7322
- const tag = group[i];
7323
- if (config.protectedTagNumbers.has(tag.tagNumber))
7324
- continue;
7325
- const target = targets.get(tag.tagNumber);
7326
- if (protectedTools.has(tag.tagNumber))
7327
- continue;
7328
- if (target?.canDrop?.() === false)
7329
- continue;
7330
- const { result, mode } = applyNewToolDrop(target, { inWindow: false });
7331
- if (result === "incomplete")
7332
- continue;
7333
- updateTagDropMode2(db, sessionId, tag.tagNumber, mode);
7334
- updateTagStatus2(db, sessionId, tag.tagNumber, "dropped");
7335
- if (result === "removed" || result === "truncated") {
7336
- deduplicatedTools++;
7337
- droppedTokenReductions.push({
7338
- tagNumber: tag.tagNumber,
7339
- mode: result === "removed" ? "full" : "truncated"
7340
- });
7341
- }
7370
+ const target = targets.get(tag.tagNumber);
7371
+ if (protectedTools.has(tag.tagNumber))
7372
+ continue;
7373
+ if (target?.canDrop?.() === false)
7374
+ continue;
7375
+ const { result } = applyPersistedToolDrop(db, sessionId, tag.tagNumber, target, {
7376
+ inWindow: false
7377
+ });
7378
+ if (result === "incomplete")
7379
+ continue;
7380
+ if (result === "removed" || result === "truncated") {
7381
+ deduplicatedTools++;
7382
+ droppedTokenReductions.push({
7383
+ tagNumber: tag.tagNumber,
7384
+ mode: result === "removed" ? "full" : "truncated"
7385
+ });
7342
7386
  }
7343
7387
  }
7344
- }).immediate();
7388
+ }
7345
7389
  }
7346
7390
  if (droppedTools > 0 || deduplicatedTools > 0 || droppedInjections > 0) {
7347
7391
  sessionLog2(sessionId, `heuristic cleanup: dropped ${droppedTools} tool tags, deduplicated ${deduplicatedTools} tool calls, dropped ${droppedInjections} system injections`);
@@ -7515,6 +7559,7 @@ function postprocessReplaySnapshot(db, sessionId) {
7515
7559
  ...replay,
7516
7560
  staleReduceStrippedIds: new Set(replay.staleReduceStrippedIds),
7517
7561
  processedImageStrippedIds: new Set(replay.processedImageStrippedIds),
7562
+ processedImageMarkers: new Map(replay.processedImageMarkers),
7518
7563
  strippedPlaceholderIds: new Set(replay.strippedPlaceholderIds),
7519
7564
  hiddenSeamPlaceholderIds: new Set(replay.hiddenSeamPlaceholderIds),
7520
7565
  mergedReasoningStrippedIds: new Set(replay.mergedReasoningStrippedIds),
@@ -8820,11 +8865,6 @@ function runRustModePostprocess(args) {
8820
8865
  for (const anchor of getNoteNudgeAnchors(args.db, args.sessionId)) {
8821
8866
  appendReminderToUserMessageById(args.messages, anchor.messageId, anchor.text);
8822
8867
  }
8823
- for (const decision of getAutoSearchHintDecisions(args.db, args.sessionId)) {
8824
- if (decision.decision === "hint" && getUnpublishedAutoSearchNoHint(args.sessionId, decision.messageId) === undefined) {
8825
- appendReminderToUserMessageById(args.messages, decision.messageId, decision.text);
8826
- }
8827
- }
8828
8868
  const trailingBlankDecisions = new Map;
8829
8869
  const visibleAssistantIds = args.messages.filter((message) => message.info.role === "assistant").map((message) => message.info.id).filter((id) => typeof id === "string");
8830
8870
  if (modelAcceptsEmptyContent(args.resolvedProviderID)) {
@@ -8862,7 +8902,7 @@ function runRustModePostprocess(args) {
8862
8902
  userMessageIds: args.messages.filter((m) => m.info.role === "user" && typeof m.info.id === "string").map((m) => m.info.id),
8863
8903
  anchorMessageId: currentUserMessageId,
8864
8904
  isLiveTail: args.messages.at(-1)?.info.id === currentUserMessageId,
8865
- isCacheBustingPass: args.cacheBustingPass === true
8905
+ prefixRewriteCoversAnchor: false
8866
8906
  });
8867
8907
  const noteReadStillVisible = hasVisibleNoteReadCall(args.messages);
8868
8908
  const deferredNoteText = peekNoteNudgeText(args.db, args.sessionId, currentUserMessageId, args.projectPath, noteReadStillVisible, eligibility);
@@ -8879,6 +8919,11 @@ function runRustModePostprocess(args) {
8879
8919
  sessionLog2(args.sessionId, `rust note-nudge delivery skipped wire append: ${outcome.kind}`);
8880
8920
  }
8881
8921
  }
8922
+ for (const decision of getAutoSearchHintDecisions(args.db, args.sessionId)) {
8923
+ if (decision.decision === "hint" && getUnpublishedAutoSearchNoHint(args.sessionId, decision.messageId) === undefined) {
8924
+ appendReminderToUserMessageById(args.messages, decision.messageId, decision.text);
8925
+ }
8926
+ }
8882
8927
  const { thinkingBindingRecovery, proactiveThinkingStrip } = applyRustModeThinkingStrips(args, noteNudgeAppended || servedMarkerRecord() !== servedMarkerBefore);
8883
8928
  const marker = getPersistedCompactionMarkerState(args.db, args.sessionId);
8884
8929
  return {
@@ -9737,15 +9782,32 @@ async function runPostTransformPhase(args) {
9737
9782
  sessionLog2(args.sessionId, "transform failed dropping stale ctx_reduce calls:", error);
9738
9783
  }
9739
9784
  }
9740
- if (canUseEmptySentinels && !compactionOff && replaySnapshot) {
9785
+ if (!compactionOff && replaySnapshot) {
9741
9786
  try {
9742
9787
  const tImg = performance.now();
9788
+ const imageWatermark = canEditWholePrefix ? Math.max(args.watermark, getMaxDroppedTagNumber2(args.db, args.sessionId)) : args.watermark;
9743
9789
  const frozenImageIds = replaySnapshot.processedImageStrippedIds;
9790
+ const frozenMarkers = replaySnapshot.processedImageMarkers;
9791
+ const replacementText = canUseEmptySentinels ? "" : "[image stripped]";
9744
9792
  stripProcessedImages(args.messages, frozenImageIds, {
9745
- detect: canEditWholePrefix && args.watermark > 0,
9746
- watermark: args.watermark,
9793
+ detect: canEditWholePrefix && imageWatermark > 0,
9794
+ watermark: imageWatermark,
9747
9795
  messageTagNumbers: args.messageTagNumbers,
9748
- persistNewIds: (ids) => addProcessedImageStrippedIds(args.db, args.sessionId, ids),
9796
+ protectedCutoff: args.protectedCutoff,
9797
+ contextPercentage: args.contextUsage.percentage,
9798
+ replacementText,
9799
+ frozenMarkers,
9800
+ protectedMessageIds: new Set([
9801
+ ...args.tags.filter((tag) => protectedToolTags.has(tag.tagNumber)).map((tag) => tag.toolOwnerMessageId ?? tag.messageId)
9802
+ ]),
9803
+ persistNewIds: (ids, markers) => {
9804
+ if (!addProcessedImageStrippedIds(args.db, args.sessionId, ids, markers))
9805
+ return false;
9806
+ const committed = getProcessedImageMarkers(args.db, args.sessionId);
9807
+ for (const id of ids)
9808
+ frozenMarkers.set(id, committed.get(id) ?? replacementText);
9809
+ return true;
9810
+ },
9749
9811
  onFirstApplication: recordFirstApplicationAt
9750
9812
  });
9751
9813
  logTransformTiming(args.sessionId, "stripProcessedImages", tImg);
@@ -9873,16 +9935,6 @@ async function runPostTransformPhase(args) {
9873
9935
  logTransformTiming(args.sessionId, "pp.placeholderNeutralize", tPlaceholder);
9874
9936
  }
9875
9937
  const tNudgeBlock = performance.now();
9876
- if (args.fullFeatureMode && !compactionOff && replaySnapshot) {
9877
- for (const anchor of replaySnapshot.noteNudgeAnchors) {
9878
- appendReminderToUserMessageById(args.messages, anchor.messageId, anchor.text);
9879
- }
9880
- for (const decision of replaySnapshot.autoSearchHintDecisions) {
9881
- if (decision.decision === "hint") {
9882
- appendReminderToUserMessageById(args.messages, decision.messageId, decision.text);
9883
- }
9884
- }
9885
- }
9886
9938
  logTransformTiming(args.sessionId, "pp.nudgeAndSticky", tNudgeBlock);
9887
9939
  const tMarker = performance.now();
9888
9940
  const explicitRebuildHappened = args.historyRefreshExplicitBeforePrepare && args.rebuiltHistoryFromInitialPrepare;
@@ -9958,13 +10010,15 @@ async function runPostTransformPhase(args) {
9958
10010
  const noteReadStillVisible = args.fullFeatureMode ? hasVisibleNoteReadCall(args.messages) : false;
9959
10011
  let noteNudgeAppendedThisPass = false;
9960
10012
  const noteNudgeUserMessageId = findNoteNudgeUserMessageId(args.messages);
10013
+ const lastServedForNote = canEditWholePrefix && (m0RematerializedThisPass || historyWasConsumedThisPass) ? args.readLastServedMessages?.() : null;
10014
+ const rewrittenHeadCoversNote = !!lastServedForNote && args.messages.slice(0, prependedMessageCount).some((message, index) => isSyntheticHeadMessage(message) && index < lastServedForNote.length && servedMessageKey(message, args.resolvedProviderID) !== servedMessageKey(lastServedForNote[index], args.resolvedProviderID));
9961
10015
  const noteNudgeEligibility = args.fullFeatureMode ? observeNoteNudgeServe({
9962
10016
  db: args.db,
9963
10017
  sessionId: args.sessionId,
9964
10018
  userMessageIds: args.messages.filter((m) => m.info.role === "user" && typeof m.info.id === "string").map((m) => m.info.id),
9965
10019
  anchorMessageId: noteNudgeUserMessageId,
9966
10020
  isLiveTail: args.messages.at(-1)?.info.id === noteNudgeUserMessageId,
9967
- isCacheBustingPass
10021
+ prefixRewriteCoversAnchor: canEditWholePrefix && rewrittenHeadCoversNote
9968
10022
  }) : undefined;
9969
10023
  const deferredNoteText = args.fullFeatureMode ? peekNoteNudgeText(args.db, args.sessionId, noteNudgeUserMessageId, args.projectPath, noteReadStillVisible, noteNudgeEligibility) : null;
9970
10024
  if (deferredNoteText) {
@@ -9981,6 +10035,16 @@ async function runPostTransformPhase(args) {
9981
10035
  sessionLog2(args.sessionId, `note-nudge delivery skipped wire append: ${outcome.kind}`);
9982
10036
  }
9983
10037
  }
10038
+ if (args.fullFeatureMode && !compactionOff && replaySnapshot) {
10039
+ for (const anchor of replaySnapshot.noteNudgeAnchors) {
10040
+ appendReminderToUserMessageById(args.messages, anchor.messageId, anchor.text);
10041
+ }
10042
+ for (const decision of replaySnapshot.autoSearchHintDecisions) {
10043
+ if (decision.decision === "hint") {
10044
+ appendReminderToUserMessageById(args.messages, decision.messageId, decision.text);
10045
+ }
10046
+ }
10047
+ }
9984
10048
  let todoAnchorMovedThisPass = false;
9985
10049
  if (args.fullFeatureMode && !compactionOff) {
9986
10050
  const todoAnchorBefore = replaySnapshot ? replaySnapshot.todoSyntheticAnchor : getPersistedTodoSyntheticAnchor(args.db, args.sessionId);
@@ -11180,7 +11244,7 @@ function createPassOutcome() {
11180
11244
  }
11181
11245
 
11182
11246
  // src/hooks/magic-context/rust-mode-transform.ts
11183
- import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
11247
+ import { createHash as createHash5, randomUUID as randomUUID2 } from "node:crypto";
11184
11248
 
11185
11249
  // src/features/magic-context/memory/single-store-embedding-drain.ts
11186
11250
  function isWatermarkRow(row) {
@@ -13627,13 +13691,235 @@ function resolveRustLkgReplayParticipant(sessionId) {
13627
13691
  return latest;
13628
13692
  return alive.length === 1 ? alive[0] : undefined;
13629
13693
  }
13630
- function noteExternalLkgReplay(participant, sessionId, inputCount) {
13694
+ function noteExternalLkgReplay(participant, sessionId, inputMessages, servedMessages) {
13631
13695
  if (!participant)
13632
13696
  return;
13633
- participant.enterFreezeFromExternalServe(sessionId, inputCount);
13697
+ participant.enterFreezeFromExternalServe(sessionId, inputMessages, servedMessages);
13634
13698
  sessionLog2(sessionId, "lkg_external_replay_froze_rust_adapter");
13635
13699
  }
13636
13700
 
13701
+ // src/hooks/magic-context/rust-served-raw.ts
13702
+ import { createHash as createHash4 } from "node:crypto";
13703
+ class RustServedRawConflict extends EmergencyFailClosedError {
13704
+ reason;
13705
+ messageIds;
13706
+ firstBlockId;
13707
+ constructor(reason, messageIds, firstBlockId) {
13708
+ super(`Rust served-raw conflict: ${reason} at ${firstBlockId}`);
13709
+ this.reason = reason;
13710
+ this.messageIds = messageIds;
13711
+ this.firstBlockId = firstBlockId;
13712
+ }
13713
+ }
13714
+ function partDigest(part) {
13715
+ const serialized = JSON.stringify(part);
13716
+ return createHash4("sha256").update(stableStringify(serialized === undefined ? undefined : JSON.parse(serialized))).digest("hex");
13717
+ }
13718
+ function records(doc) {
13719
+ if (doc.rustServedRaw === undefined)
13720
+ return [];
13721
+ if (!Array.isArray(doc.rustServedRaw))
13722
+ throw new EmergencyFailClosedError("Invalid Rust served-raw evidence");
13723
+ for (const row of doc.rustServedRaw) {
13724
+ if (!row || typeof row.messageId !== "string" || !Number.isSafeInteger(row.index) || row.index < 0 || row.partId !== undefined && typeof row.partId !== "string" || typeof row.digest !== "string" || !/^[a-f0-9]{64}$/.test(row.digest) || !Array.isArray(row.blockIds) || !row.blockIds.every((id) => typeof id === "string")) {
13725
+ throw new EmergencyFailClosedError("Invalid Rust served-raw part");
13726
+ }
13727
+ }
13728
+ return doc.rustServedRaw;
13729
+ }
13730
+ function rustRawRebuild(db, sessionId) {
13731
+ const value = readReplayEnvelope(db, sessionId).rustRawRebuild;
13732
+ if (value === undefined)
13733
+ return;
13734
+ if (!value || typeof value.identity !== "string" || !/^[a-f0-9]{64}$/.test(value.identity) || !["source_removed", "source_changed", "candidate_loss", "candidate_conflict"].includes(value.reason) || !Array.isArray(value.messageIds) || !value.messageIds.every((id) => typeof id === "string") || typeof value.firstBlockId !== "string" || typeof value.pending !== "boolean") {
13735
+ throw new EmergencyFailClosedError("Invalid Rust raw-rebuild request");
13736
+ }
13737
+ return value;
13738
+ }
13739
+ function servedRawBlockIds(db, sessionId) {
13740
+ return records(readReplayEnvelope(db, sessionId)).flatMap((row) => row.blockIds);
13741
+ }
13742
+ function sourcePart(row, message) {
13743
+ return row.partId === undefined ? message?.parts[row.index] : message?.parts.find((part) => part?.id === row.partId);
13744
+ }
13745
+ function conflict(row, reason) {
13746
+ return new RustServedRawConflict(reason, [row.messageId], row.blockIds[0] ?? `${row.messageId}#0`);
13747
+ }
13748
+ function checkRustServedRawIngress(db, sessionId, input) {
13749
+ const rows = records(readReplayEnvelope(db, sessionId));
13750
+ if (!rows.length)
13751
+ return;
13752
+ const byId = new Map(input.map((message) => [message.info.id, message]));
13753
+ const changed = rows.filter((row) => partDigest(sourcePart(row, byId.get(row.messageId))) !== row.digest);
13754
+ const first = changed[0];
13755
+ if (!first)
13756
+ return;
13757
+ throw new RustServedRawConflict(sourcePart(first, byId.get(first.messageId)) === undefined ? "source_removed" : "source_changed", [...new Set(changed.map((row) => row.messageId))], first.blockIds[0] ?? `${first.messageId}#0`);
13758
+ }
13759
+ function requestRustRawRebuild(db, sessionId, error) {
13760
+ if (!updateReplayDocument(db, sessionId, (doc) => {
13761
+ const previous = doc.rustRawRebuild;
13762
+ if (previous?.pending && previous.reason === error.reason && previous.firstBlockId === error.firstBlockId && error.messageIds.every((id) => previous.messageIds.includes(id)))
13763
+ return false;
13764
+ const messageIds = [
13765
+ ...new Set([
13766
+ ...previous?.pending ? previous.messageIds : [],
13767
+ ...error.messageIds
13768
+ ])
13769
+ ];
13770
+ const identity = partDigest([
13771
+ previous?.identity ?? "",
13772
+ error.reason,
13773
+ messageIds,
13774
+ error.firstBlockId
13775
+ ]);
13776
+ doc.version = 2;
13777
+ doc.rustRawRebuild = {
13778
+ identity,
13779
+ reason: error.reason,
13780
+ messageIds,
13781
+ firstBlockId: error.firstBlockId,
13782
+ pending: true
13783
+ };
13784
+ return true;
13785
+ }))
13786
+ throw new EmergencyFailClosedError("Cannot persist Rust raw-rebuild request");
13787
+ }
13788
+ function noteRustServedRaw(db, sessionId, input, served) {
13789
+ const additions = [];
13790
+ const byId = new Map(served.filter((message) => typeof message?.info?.id === "string").map((message) => [message.info.id, message]));
13791
+ for (const message of input) {
13792
+ const visible = byId.get(message.info.id);
13793
+ if (!visible)
13794
+ continue;
13795
+ let offset = 0;
13796
+ for (const [index, value] of message.parts.entries()) {
13797
+ if (!value || typeof value !== "object")
13798
+ continue;
13799
+ const part = value;
13800
+ const count = encodeOpenCodeMessagesToCk([{ ...message, parts: [part] }])[0].ck.content.length;
13801
+ const actual = typeof part.id === "string" ? visible.parts.find((candidate) => candidate?.id === part.id) : visible.parts[index];
13802
+ const status = part.state?.status;
13803
+ const reachesProvider = !(part.type === "text" && part.ignored === true) && ![
13804
+ "compaction",
13805
+ "step-start",
13806
+ "step-finish",
13807
+ "snapshot",
13808
+ "patch",
13809
+ "agent",
13810
+ "retry"
13811
+ ].includes(String(part.type)) && (part.type !== "tool" || status === "completed" || status === "error");
13812
+ if (reachesProvider && count > 0) {
13813
+ const digest = partDigest(part);
13814
+ if (actual === part || partDigest(actual) === digest) {
13815
+ additions.push({
13816
+ messageId: message.info.id,
13817
+ index,
13818
+ ...typeof part.id === "string" ? { partId: part.id } : {},
13819
+ digest,
13820
+ blockIds: Array.from({ length: count }, (_, i) => `${message.info.id}#${offset + i}`)
13821
+ });
13822
+ }
13823
+ }
13824
+ offset += count;
13825
+ }
13826
+ }
13827
+ if (!additions.length)
13828
+ return;
13829
+ if (!updateReplayDocument(db, sessionId, (doc) => {
13830
+ const rows = records(doc);
13831
+ const key = (row) => stableStringify([row.messageId, row.partId ?? row.index]);
13832
+ const merged = new Map(rows.map((row) => [key(row), row]));
13833
+ for (const row of additions)
13834
+ merged.set(key(row), row);
13835
+ const next = [...merged.values()];
13836
+ if (stableStringify(rows) === stableStringify(next))
13837
+ return false;
13838
+ doc.version = 2;
13839
+ doc.rustServedRaw = next;
13840
+ return true;
13841
+ }))
13842
+ throw new EmergencyFailClosedError("Cannot persist Rust served-raw evidence");
13843
+ }
13844
+ function preserveRustServedRaw(db, sessionId, output, input = output, reconstruct = new Set, covered = new Set) {
13845
+ const rows = records(readReplayEnvelope(db, sessionId));
13846
+ if (!rows.length)
13847
+ return false;
13848
+ const sources = new Map(input.map((message) => [message.info.id, message]));
13849
+ const byId = new Map(output.map((message) => [message.info.id, message]));
13850
+ let repaired = false;
13851
+ for (const row of rows) {
13852
+ if (covered.has(row.messageId))
13853
+ continue;
13854
+ const original = sources.get(row.messageId);
13855
+ const source = sourcePart(row, original);
13856
+ if (!original || !source)
13857
+ throw conflict(row, "source_removed");
13858
+ if (partDigest(source) !== row.digest)
13859
+ throw conflict(row, "source_changed");
13860
+ let message = byId.get(row.messageId);
13861
+ if (!message) {
13862
+ if (!reconstruct.has(row.messageId))
13863
+ throw conflict(row, "candidate_loss");
13864
+ const sourceIndex = input.indexOf(original);
13865
+ const next = output.findIndex((candidate) => input.findIndex((entry) => entry.info.id === candidate.info.id) > sourceIndex);
13866
+ message = structuredClone(original);
13867
+ output.splice(next < 0 ? output.length : next, 0, message);
13868
+ byId.set(row.messageId, message);
13869
+ repaired = true;
13870
+ }
13871
+ const parts = message.parts;
13872
+ if (row.partId === undefined) {
13873
+ const candidate = parts[row.index];
13874
+ if (partDigest(candidate) === row.digest)
13875
+ continue;
13876
+ const reversibleTag = source.type === "text" && typeof source.text === "string" && typeof candidate?.text === "string" && /^§\d+§ /.test(candidate.text) && candidate.text.replace(/^§\d+§ /, "") === source.text && partDigest({ ...candidate, text: source.text }) === row.digest;
13877
+ if (!reversibleTag) {
13878
+ if (!reconstruct.has(row.messageId))
13879
+ throw conflict(row, "candidate_conflict");
13880
+ message.parts = structuredClone(original.parts);
13881
+ repaired = true;
13882
+ continue;
13883
+ }
13884
+ parts[row.index] = structuredClone(source);
13885
+ continue;
13886
+ }
13887
+ const matches = parts.flatMap((part, i) => part.id === row.partId ? [i] : []);
13888
+ if (matches.length > 1)
13889
+ throw conflict(row, "candidate_conflict");
13890
+ const index = matches[0];
13891
+ if (index !== undefined) {
13892
+ if (partDigest(parts[index]) !== row.digest)
13893
+ parts[index] = structuredClone(source);
13894
+ } else if (["reasoning", "thinking", "redacted_thinking"].includes(String(source.type)) || reconstruct.has(row.messageId)) {
13895
+ parts.splice(row.index, 0, structuredClone(source));
13896
+ repaired = true;
13897
+ } else
13898
+ throw conflict(row, "candidate_loss");
13899
+ }
13900
+ return repaired;
13901
+ }
13902
+ function releaseRustServedRaw(db, sessionId, output, rebuiltIdentity) {
13903
+ const snapshot = readReplayEnvelope(db, sessionId);
13904
+ if (!records(snapshot).length && !snapshot.rustRawRebuild?.pending)
13905
+ return;
13906
+ const byId = new Map(output.map((message) => [message.info.id, message]));
13907
+ if (!updateReplayDocument(db, sessionId, (doc) => {
13908
+ const rows = records(doc);
13909
+ const kept = rows.filter((row) => partDigest(sourcePart(row, byId.get(row.messageId))) === row.digest);
13910
+ const recovery = doc.rustRawRebuild;
13911
+ const acknowledged = recovery?.pending && recovery.identity === rebuiltIdentity;
13912
+ if (kept.length === rows.length && !acknowledged)
13913
+ return false;
13914
+ doc.version = 2;
13915
+ doc.rustServedRaw = kept;
13916
+ if (acknowledged)
13917
+ doc.rustRawRebuild = { ...recovery, pending: false };
13918
+ return true;
13919
+ }))
13920
+ throw new EmergencyFailClosedError("Cannot release Rust served-raw evidence");
13921
+ }
13922
+
13637
13923
  // src/hooks/magic-context/transform-context-state.ts
13638
13924
  function loadPersistedUsageWatermark(db, sessionId) {
13639
13925
  const result = db.prepare("SELECT last_response_time FROM session_meta WHERE session_id = ?").get(sessionId);
@@ -13876,16 +14162,19 @@ function rustCaptureDigests(inputs, prior, acceptedInputs) {
13876
14162
  } : undefined);
13877
14163
  return { ...incremental, inputContentSignatures };
13878
14164
  }
14165
+ var contentSnapshotFieldVisitObserverForTests;
13879
14166
  function messageMatchesContentSnapshot(message, snapshot) {
13880
14167
  let fieldIndex = 0;
13881
14168
  const matched = visitMessageContentFields(contentSnapshotValue(message), {
13882
14169
  field(value) {
14170
+ contentSnapshotFieldVisitObserverForTests?.();
13883
14171
  if (!Object.is(value, snapshot.fields[fieldIndex]))
13884
14172
  return false;
13885
14173
  fieldIndex += 1;
13886
14174
  return true;
13887
14175
  },
13888
14176
  beginObject() {
14177
+ contentSnapshotFieldVisitObserverForTests?.();
13889
14178
  const expectedCount = snapshot.fields[fieldIndex];
13890
14179
  if (typeof expectedCount !== "number")
13891
14180
  return;
@@ -13912,10 +14201,10 @@ function messageCacheSignature(message) {
13912
14201
  const parts = Array.isArray(message.parts) ? message.parts : [];
13913
14202
  const serializedParts = JSON.stringify(parts) ?? "null";
13914
14203
  const serializedMessage = JSON.stringify(message) ?? "null";
13915
- return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash4("sha256").update(serializedMessage).digest("hex")}`;
14204
+ return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash5("sha256").update(serializedMessage).digest("hex")}`;
13916
14205
  }
13917
14206
  function advanceWireFingerprint(previous, encoded) {
13918
- return createHash4("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
14207
+ return createHash5("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
13919
14208
  }
13920
14209
  function buildWireFingerprint(encoded) {
13921
14210
  let fingerprint = "rust-wire-v1";
@@ -14445,7 +14734,8 @@ function buildTransformBody(args) {
14445
14734
  args.providerId ? `provider:${args.providerId}` : "",
14446
14735
  args.modelKey ? `model:${args.modelKey}` : "",
14447
14736
  args.variant ? `variant:${args.variant}` : "",
14448
- args.systemPromptHash ? `system:${args.systemPromptHash}` : ""
14737
+ args.systemPromptHash ? `system:${args.systemPromptHash}` : "",
14738
+ args.rawRebuild ? `raw_replay:${args.rawRebuild.identity}` : ""
14449
14739
  ].filter(Boolean).join("|"),
14450
14740
  system_prompt_hash: args.systemPromptHash,
14451
14741
  adopted_system_prompt_hash: args.passInputs.adopted_system_prompt_hash,
@@ -14453,6 +14743,14 @@ function buildTransformBody(args) {
14453
14743
  is_subagent: args.passInputs.is_subagent === true,
14454
14744
  messages: args.input,
14455
14745
  native_messages: args.nativeMessages,
14746
+ served_raw_block_ids: args.servedRawBlockIds ?? [],
14747
+ ...args.rawRebuild?.pending ? {
14748
+ raw_replay_rebuild: {
14749
+ identity: args.rawRebuild.identity,
14750
+ reason: args.rawRebuild.reason,
14751
+ message_ids: args.rawRebuild.messageIds
14752
+ }
14753
+ } : {},
14456
14754
  tool_input_key_orders: args.toolInputKeyOrders ?? toolInputKeyOrders(args.input),
14457
14755
  ...args.fullArrayFingerprint ? { full_array_fingerprint: args.fullArrayFingerprint } : {},
14458
14756
  ...args.tailDelta ? {
@@ -14643,6 +14941,7 @@ function createRustModeTransform(deps, options) {
14643
14941
  throw error;
14644
14942
  } finally {
14645
14943
  clock.clearTimeout(timer);
14944
+ invalidateReplayEnvelopeSnapshot(deps.db, args.sessionId);
14646
14945
  }
14647
14946
  };
14648
14947
  const callTransformWithStallProbe = async (args, attemptTimeoutMs) => {
@@ -14751,6 +15050,24 @@ function createRustModeTransform(deps, options) {
14751
15050
  logTransformTiming(sessionId, "rust.ordinal_rebuild", startedAt, detail);
14752
15051
  }
14753
15052
  };
15053
+ const recordRawConflict = (sessionId, error) => {
15054
+ requestRustRawRebuild(deps.db, sessionId, error);
15055
+ dropSlot(sessionId, `raw_replay_${error.reason}`);
15056
+ const state = ensureState(states, sessionId);
15057
+ state.forceFullWire = true;
15058
+ state.parked = false;
15059
+ sessionLog2(sessionId, `raw_replay_rebuild_requested reason=${error.reason} first_changed=${error.firstBlockId}`);
15060
+ };
15061
+ const observeRawReplay = (sessionId, input, served) => {
15062
+ try {
15063
+ checkRustServedRawIngress(deps.db, sessionId, input);
15064
+ noteRustServedRaw(deps.db, sessionId, input, served);
15065
+ } catch (error) {
15066
+ if (error instanceof RustServedRawConflict)
15067
+ recordRawConflict(sessionId, error);
15068
+ throw error;
15069
+ }
15070
+ };
14754
15071
  const replayLastGood = (sessionId, currentMessages, output, systemPromptTokens) => {
14755
15072
  try {
14756
15073
  if (states.get(sessionId)?.markerAdmissionFenced || isRustMarkerAdmissionFenced(deps.db, sessionId))
@@ -14837,6 +15154,7 @@ function createRustModeTransform(deps, options) {
14837
15154
  ownDirtyRevision: lkgDirtyRevision(sessionId)
14838
15155
  }));
14839
15156
  const replayInputCount = currentMessages.length;
15157
+ observeRawReplay(sessionId, currentMessages, replay.messages);
14840
15158
  replaceMessagesInPlace(output, replay.messages);
14841
15159
  ensureState(states, sessionId).lkgLatestServedDigest = lkgServedArrayDigest(JSON.stringify(replay.messages));
14842
15160
  enterLkgReplayFreeze(ensureState(states, sessionId), replayInputCount);
@@ -14900,7 +15218,10 @@ function createRustModeTransform(deps, options) {
14900
15218
  const passStampBySession = new Map;
14901
15219
  const replayParticipant = {
14902
15220
  lastPassStamp: (sessionId) => states.has(sessionId) ? passStampBySession.get(sessionId) : undefined,
14903
- enterFreezeFromExternalServe: (sessionId, inputCount) => enterLkgReplayFreeze(ensureState(states, sessionId), inputCount),
15221
+ enterFreezeFromExternalServe: (sessionId, inputMessages, servedMessages) => {
15222
+ observeRawReplay(sessionId, inputMessages, servedMessages);
15223
+ enterLkgReplayFreeze(ensureState(states, sessionId), inputMessages.length);
15224
+ },
14904
15225
  replayFits: (sessionId, messages, inputMessages) => {
14905
15226
  try {
14906
15227
  const fit = lkgReplayFits({
@@ -15046,6 +15367,24 @@ function createRustModeTransform(deps, options) {
15046
15367
  bindSystemDateRequest(output, dateRequest);
15047
15368
  const passObservedAtMs = Date.now();
15048
15369
  const state = ensureState(states, sessionId);
15370
+ let rawRebuild;
15371
+ let rawReadError;
15372
+ try {
15373
+ rawRebuild = rustRawRebuild(deps.db, sessionId);
15374
+ try {
15375
+ checkRustServedRawIngress(deps.db, sessionId, messages);
15376
+ } catch (error) {
15377
+ if (!(error instanceof RustServedRawConflict) || !rawRebuild?.pending)
15378
+ throw error;
15379
+ requestRustRawRebuild(deps.db, sessionId, error);
15380
+ rawRebuild = rustRawRebuild(deps.db, sessionId);
15381
+ }
15382
+ } catch (error) {
15383
+ if (error instanceof RustServedRawConflict)
15384
+ throw error;
15385
+ rawReadError = error;
15386
+ }
15387
+ const reconstructRaw = new Set(rawRebuild?.messageIds ?? []);
15049
15388
  let entrySlot = getSlot(sessionId);
15050
15389
  try {
15051
15390
  entrySlot = loadPersistedLkgSlot(deps.db, sessionId, true) ?? entrySlot;
@@ -15084,6 +15423,7 @@ function createRustModeTransform(deps, options) {
15084
15423
  let decision = "error";
15085
15424
  let materializeReason = "none";
15086
15425
  let frozenReleaseReason = null;
15426
+ let frozenReleaseFirstChanged = "unknown";
15087
15427
  let schedulerDecision;
15088
15428
  let responseCommitted;
15089
15429
  let responsePrefixBustPermitted;
@@ -15109,7 +15449,7 @@ function createRustModeTransform(deps, options) {
15109
15449
  let recoveryProjectRoot = options.projectRoot ?? deps.directory ?? "";
15110
15450
  const passUsageSnapshot = loadContextUsage(deps.contextUsageMap, deps.db, sessionId);
15111
15451
  requestInputTokens = Math.max(0, Math.floor(passUsageSnapshot.inputTokens));
15112
- let preflightError;
15452
+ let preflightError = rawReadError;
15113
15453
  let markerAdmissionRecovery = state.markerAdmissionFenced;
15114
15454
  try {
15115
15455
  markerAdmissionRecovery ||= isRustMarkerAdmissionFenced(deps.db, sessionId);
@@ -15303,7 +15643,7 @@ function createRustModeTransform(deps, options) {
15303
15643
  decision,
15304
15644
  committed: responseCommitted,
15305
15645
  prefixBustPermitted: responsePrefixBustPermitted,
15306
- reason: materializeReason,
15646
+ reason: applied && served && frozenReleaseReason ? `lkg_frozen_release:${frozenReleaseReason};first_changed=${frozenReleaseFirstChanged};materialize_reason=${materializeReason}` : materializeReason,
15307
15647
  schedulerDecision,
15308
15648
  schedulerDeferReason,
15309
15649
  historianNoFire,
@@ -15325,7 +15665,7 @@ function createRustModeTransform(deps, options) {
15325
15665
  materializeReason: materializeReason === "none" ? null : materializeReason,
15326
15666
  inputTokens: requestInputTokens,
15327
15667
  tsMs: passObservedAtMs,
15328
- lkgFrozenReleaseReason: applied && served ? frozenReleaseReason ?? undefined : undefined
15668
+ lkgFrozenReleaseReason: applied && served && frozenReleaseReason ? `${frozenReleaseReason};first_changed=${frozenReleaseFirstChanged}` : undefined
15329
15669
  });
15330
15670
  }
15331
15671
  };
@@ -15360,7 +15700,7 @@ function createRustModeTransform(deps, options) {
15360
15700
  sessionLog2(sessionId, `rust module stages (slow pass): ${detail}`);
15361
15701
  }
15362
15702
  };
15363
- if (state.parked) {
15703
+ if (state.parked && !preflightError) {
15364
15704
  state.passesSincePark += 1;
15365
15705
  if (!emergencyFailClosed && passUsageSnapshot.percentage < RUST_PARK_PROBE_PRESSURE_BYPASS_PCT && state.passCount % RUST_PARK_RETRY_INTERVAL !== 0) {
15366
15706
  decision = "parked";
@@ -15645,7 +15985,7 @@ function createRustModeTransform(deps, options) {
15645
15985
  const id = messageIdOf(message) ?? `index:${todoStart + offset}`;
15646
15986
  const parts = message.parts?.filter((part) => isRecord4(part) && part.type === "tool" && part.tool === "todowrite");
15647
15987
  if (parts?.length) {
15648
- todoCalls.set(id, createHash4("sha256").update(JSON.stringify(parts)).digest("hex"));
15988
+ todoCalls.set(id, createHash5("sha256").update(JSON.stringify(parts)).digest("hex"));
15649
15989
  } else {
15650
15990
  todoCalls.delete(id);
15651
15991
  }
@@ -15791,6 +16131,8 @@ function createRustModeTransform(deps, options) {
15791
16131
  };
15792
16132
  let body = buildTransformBody({
15793
16133
  sessionId,
16134
+ rawRebuild,
16135
+ servedRawBlockIds: servedRawBlockIds(deps.db, sessionId),
15794
16136
  input: encodedInput,
15795
16137
  nativeMessages: wireDelta ? messages.slice(wireDelta.rawStart) : messages,
15796
16138
  toolInputKeyOrders: toolInputKeyOrders(encodedInput),
@@ -15990,6 +16332,8 @@ function createRustModeTransform(deps, options) {
15990
16332
  const retryWireBuildStartedAt = performance.now();
15991
16333
  body = buildTransformBody({
15992
16334
  sessionId,
16335
+ rawRebuild,
16336
+ servedRawBlockIds: servedRawBlockIds(deps.db, sessionId),
15993
16337
  input: retryEncodedInput,
15994
16338
  nativeMessages: messages,
15995
16339
  toolInputKeyOrders: toolInputKeyOrders(retryEncodedInput),
@@ -16049,6 +16393,13 @@ function createRustModeTransform(deps, options) {
16049
16393
  sessionLog2(sessionId, `signed thinking reset fence: ${fenced.length} assistant(s) [${fenced.join(",")}]`);
16050
16394
  }
16051
16395
  const cacheBustingPass = moduleDecisionBusts;
16396
+ if (rawRebuild?.pending && !moduleDecisionBusts) {
16397
+ throw new EmergencyFailClosedError("Rust raw-rebuild request was not authorized by the module");
16398
+ }
16399
+ if (rawRebuild?.pending) {
16400
+ frozenReleaseReason = `raw_replay_${rawRebuild.reason}`;
16401
+ frozenReleaseFirstChanged = rawRebuild.firstBlockId;
16402
+ }
16052
16403
  let frozenReplayReleased = false;
16053
16404
  if (markerAdmissionRecovery && !moduleDecisionBusts)
16054
16405
  throw new RustTransformProtocolError("rust marker admission recovery: supported prefix_bust_permitted=true required; upgrade ck-mc if unsupported");
@@ -16080,6 +16431,7 @@ function createRustModeTransform(deps, options) {
16080
16431
  let appliedMessages = moduleMessages;
16081
16432
  let markerStrategyFailure;
16082
16433
  let replayedFrozenRepresentation = false;
16434
+ let reconstructedRaw = false;
16083
16435
  const boundaryId = response.boundary_id;
16084
16436
  if (typeof boundaryId === "string" && boundaryId.length > 0) {
16085
16437
  assertNativeBoundary(moduleMessages, sessionId, boundaryId);
@@ -16124,7 +16476,7 @@ function createRustModeTransform(deps, options) {
16124
16476
  }
16125
16477
  if (recoveryFenceRebuild) {
16126
16478
  frozenReplayReleased = true;
16127
- frozenReleaseReason = "lkg_recovery_fence_unproven";
16479
+ frozenReleaseReason ??= "lkg_recovery_fence_unproven";
16128
16480
  frozenReleaseLastServed = { messages: null, proven: false };
16129
16481
  }
16130
16482
  if (state.lkgRepresentationFrozen && !shouldAdoptModuleAfterFreeze(moduleDecisionBusts, frozenReplayReleased)) {
@@ -16189,6 +16541,10 @@ function createRustModeTransform(deps, options) {
16189
16541
  if (!replayedFrozenRepresentation) {
16190
16542
  const outputCloneStartedAt = performance.now();
16191
16543
  appliedMessages = cloneModuleNativeOutput(moduleMessages);
16544
+ if (!moduleDecisionBusts || rawRebuild?.pending && rawRebuild.reason.startsWith("candidate")) {
16545
+ const covered = moduleDecisionBusts && typeof response.coverage_ordinal === "number" ? new Set([...state.idOrdinalMemo].filter(([, ordinal]) => ordinal <= Number(response.coverage_ordinal)).map(([id]) => id)) : new Set;
16546
+ reconstructedRaw = preserveRustServedRaw(deps.db, sessionId, appliedMessages, messages, reconstructRaw, covered);
16547
+ }
16192
16548
  timings.outputClone += performance.now() - outputCloneStartedAt;
16193
16549
  }
16194
16550
  pendingWireCache.nativeOutput = moduleMessages;
@@ -16247,7 +16603,7 @@ function createRustModeTransform(deps, options) {
16247
16603
  prefixPermissionSupported: permissionSupported,
16248
16604
  moduleReasoningTrimOnly: response.reasoning_trim_only === true,
16249
16605
  moduleSignedThinkingReset: response.signed_thinking_reset === true,
16250
- ...permissionSupported && (passStartedFrozen || frozenReleaseReason || coldStartLastServed) ? { frozenReleaseLastServed } : {},
16606
+ ...moduleDecisionBusts && (passStartedFrozen || frozenReleaseReason || coldStartLastServed) ? { frozenReleaseLastServed } : {},
16251
16607
  trailingBlankSourceDecisions,
16252
16608
  trailingBlankNewestAssistantId: typeof trailingBlankNewestAssistantId === "string" ? trailingBlankNewestAssistantId : undefined,
16253
16609
  tagger: deps.tagger,
@@ -16258,6 +16614,23 @@ function createRustModeTransform(deps, options) {
16258
16614
  if (markerStrategyFailure)
16259
16615
  throw markerStrategyFailure;
16260
16616
  }
16617
+ if (!moduleDecisionBusts && !replayedFrozenRepresentation) {
16618
+ reconstructedRaw = preserveRustServedRaw(deps.db, sessionId, appliedMessages, messages, reconstructRaw) || reconstructedRaw;
16619
+ replayRustModeBindingMismatchStrips({
16620
+ db: deps.db,
16621
+ sessionId,
16622
+ messages: appliedMessages,
16623
+ resolvedProviderID: model?.providerID
16624
+ });
16625
+ if (servedRawBlockIds(deps.db, sessionId).length > 0 && (!validateLkgSeam([], appliedMessages, model?.providerID ?? null) || model?.providerID === "anthropic" && !validateAnthropicReasoningRuns(appliedMessages.map((message) => ({
16626
+ ...message,
16627
+ parts: message.parts.filter((part) => !isRecord4(part) || !["text", "reasoning"].includes(String(part.type)) || part.text !== "")
16628
+ }))))) {
16629
+ throw new RustServedRawConflict("candidate_conflict", [
16630
+ ...new Set(servedRawBlockIds(deps.db, sessionId).map((id) => id.replace(/#\d+$/, "")))
16631
+ ], servedRawBlockIds(deps.db, sessionId)[0] ?? "unknown");
16632
+ }
16633
+ }
16261
16634
  if (typeof boundaryId === "string" && boundaryId.length > 0) {
16262
16635
  assertNativeBoundary(appliedMessages, sessionId, boundaryId);
16263
16636
  }
@@ -16293,6 +16666,24 @@ function createRustModeTransform(deps, options) {
16293
16666
  }
16294
16667
  }
16295
16668
  logStage(sessionId, "apply", applyStartedAt, timings);
16669
+ if (frozenReleaseReason && frozenReleaseLastServed.messages && [...frozenReleaseLastServed.messages, ...appliedMessages].every((message) => isRecord4(message) && isRecord4(message.info) && Array.isArray(message.parts))) {
16670
+ frozenReleaseFirstChanged = "none";
16671
+ const byId = new Map(appliedMessages.map((message) => [message.info.id, message]));
16672
+ for (const before of frozenReleaseLastServed.messages) {
16673
+ const after = byId.get(before.info.id);
16674
+ const index = before.parts.findIndex((part, i) => JSON.stringify(part) !== JSON.stringify(after?.parts[i]));
16675
+ if (!after || index >= 0) {
16676
+ const blockIndex = index > 0 ? encodeOpenCodeMessagesToCk([
16677
+ { ...before, parts: before.parts.slice(0, index) }
16678
+ ])[0].ck.content.length : 0;
16679
+ frozenReleaseFirstChanged = `${before.info.id}#${blockIndex}`;
16680
+ break;
16681
+ }
16682
+ }
16683
+ }
16684
+ if (replayedFrozenRepresentation || reconstructedRaw) {
16685
+ noteRustServedRaw(deps.db, sessionId, messages, appliedMessages);
16686
+ }
16296
16687
  const lkgInputIds = messages.map((message) => message.info.id);
16297
16688
  const lkgInputKeys = resolveLkgModelKeys(messages);
16298
16689
  const applyReplaceStartedAt = performance.now();
@@ -16550,6 +16941,9 @@ function createRustModeTransform(deps, options) {
16550
16941
  }
16551
16942
  }
16552
16943
  }
16944
+ if (moduleDecisionBusts) {
16945
+ releaseRustServedRaw(deps.db, sessionId, output.messages, rawRebuild?.identity);
16946
+ }
16553
16947
  } catch (error) {
16554
16948
  if (markerDefinitelyNoCut) {
16555
16949
  try {
@@ -16687,7 +17081,12 @@ function createRustModeTransform(deps, options) {
16687
17081
  const adapter = {
16688
17082
  run: async (sessionId, messages, output, sessionMeta) => {
16689
17083
  try {
16690
- await withSqliteTransformPass2(() => run(sessionId, messages, output, sessionMeta));
17084
+ await withReplayEnvelopeSnapshot(deps.db, sessionId, () => withSqliteTransformPass2(() => run(sessionId, messages, output, sessionMeta)));
17085
+ } catch (error) {
17086
+ if (error instanceof RustServedRawConflict) {
17087
+ recordRawConflict(sessionId, error);
17088
+ }
17089
+ throw error;
16691
17090
  } finally {
16692
17091
  try {
16693
17092
  withoutSqliteTransformPass2(() => resolveHostRunner()?.pump(sessionId));
@@ -17111,15 +17510,27 @@ class UnmanagedOverWindowError extends Error {
17111
17510
  }
17112
17511
 
17113
17512
  // src/hooks/magic-context/unresolved-history-boundary.ts
17513
+ function storedHistoryBoundaryPresence(db, sessionId) {
17514
+ try {
17515
+ const row = db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id = ?").get(sessionId);
17516
+ return row?.id ? hasRawSessionMessageById2(sessionId, row.id) : undefined;
17517
+ } catch {
17518
+ return;
17519
+ }
17520
+ }
17521
+
17114
17522
  class UnresolvedHistoryBoundaryError extends Error {
17115
17523
  estimatedTokens;
17116
17524
  contextLimitTokens;
17525
+ boundaryPresent;
17117
17526
  code = "UNRESOLVED_HISTORY_BOUNDARY";
17118
17527
  recoverable = true;
17119
- constructor(estimatedTokens, contextLimitTokens) {
17120
- super(renderUserFacingFailure("history_boundary_unresolved", "plain"));
17528
+ constructor(estimatedTokens, contextLimitTokens, boundaryPresent) {
17529
+ const reason = boundaryPresent === true ? "The boundary row is present in the host store but out of order relative to the loaded history. " : boundaryPresent === false ? "The boundary row is missing from the host store. " : "";
17530
+ super(reason + renderUserFacingFailure("history_boundary_unresolved", "plain"));
17121
17531
  this.estimatedTokens = estimatedTokens;
17122
17532
  this.contextLimitTokens = contextLimitTokens;
17533
+ this.boundaryPresent = boundaryPresent;
17123
17534
  this.name = "UnresolvedHistoryBoundaryError";
17124
17535
  }
17125
17536
  }
@@ -18276,7 +18687,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
18276
18687
  });
18277
18688
  if (untrimmed.tokens > boundaryContextLimit) {
18278
18689
  sessionLog2(sessionId, `history boundary unresolved: prefix trim refused and the untrimmed request estimate ${untrimmed.tokens} (trusted=${untrimmed.trusted}) exceeds the context limit ${boundaryContextLimit}; not sending it`);
18279
- throw new UnresolvedHistoryBoundaryError(untrimmed.tokens, boundaryContextLimit);
18690
+ throw new UnresolvedHistoryBoundaryError(untrimmed.tokens, boundaryContextLimit, storedHistoryBoundaryPresence(db, sessionId));
18280
18691
  }
18281
18692
  }
18282
18693
  if (unmanagedOverWindowPass) {
@@ -18603,6 +19014,114 @@ function resolveHistoryBudgetTokens(historyBudgetPercentage, contextUsage, execu
18603
19014
  }) / 100) * historyBudgetPercentage);
18604
19015
  }
18605
19016
 
19017
+ // src/shared/recovery-reasoning-prefix.ts
19018
+ function recoveryReasoningPrefixes(messages, partsKey) {
19019
+ const prefixes = [];
19020
+ for (let index = 0;index < messages.length; index++) {
19021
+ const message = messages[index];
19022
+ const parts = message?.[partsKey];
19023
+ if (!Array.isArray(parts))
19024
+ continue;
19025
+ for (let p = 0;p < parts.length; p++) {
19026
+ const type = parts[p]?.type;
19027
+ if (type !== "thinking" && type !== "reasoning" && type !== "redactedThinking" && type !== "redacted_thinking")
19028
+ continue;
19029
+ prefixes.push(JSON.stringify([
19030
+ ...messages.slice(0, index),
19031
+ { ...message, [partsKey]: parts.slice(0, p + 1) }
19032
+ ]));
19033
+ }
19034
+ }
19035
+ return prefixes;
19036
+ }
19037
+
19038
+ // src/hooks/magic-context/replay-committed-drops.ts
19039
+ function replayCommittedDrops(db, sessionId, messages) {
19040
+ const original = messages;
19041
+ const reasoningPrefixes = recoveryReasoningPrefixes(messages, "parts");
19042
+ if (reasoningPrefixes.length)
19043
+ messages = structuredClone(messages);
19044
+ const tags = getTagsBySession2(db, sessionId).filter((tag) => tag.status === "dropped");
19045
+ const toolTags = new Map(tags.filter((tag) => tag.type === "tool").map((tag) => [makeToolCompositeKey(tag.toolOwnerMessageId ?? "", tag.messageId), tag]));
19046
+ const textTags = new Map(tags.filter((tag) => tag.type !== "tool").map((tag) => [tag.messageId, tag]));
19047
+ const byNumber = new Map(tags.map((tag) => [tag.tagNumber, tag]));
19048
+ const index = new Map;
19049
+ const owners = new Map;
19050
+ const resolvedOwners = new Map;
19051
+ const ambiguousCalls = new Set;
19052
+ const targets = new Map;
19053
+ let precedingThinking = [];
19054
+ const toolThinking = new Map;
19055
+ const batch = new ToolMutationBatch(messages);
19056
+ for (const message of messages) {
19057
+ if (message.info.role === "user")
19058
+ precedingThinking = [];
19059
+ const thinking = message.parts.filter(isThinkingPart);
19060
+ for (let p = 0;p < message.parts.length; p++) {
19061
+ const part = message.parts[p];
19062
+ const observation = extractToolCallObservation(part);
19063
+ if (observation) {
19064
+ const { callId, kind } = observation;
19065
+ const pending = owners.get(callId) ?? [];
19066
+ if (pending.length > 1)
19067
+ ambiguousCalls.add(callId);
19068
+ const hostingKey = makeToolCompositeKey(message.info.id ?? "", callId);
19069
+ const owner = kind === "invocation" || part.type === "tool" || toolTags.has(hostingKey) ? message.info.id ?? "" : pending.shift() ?? resolvedOwners.get(callId) ?? message.info.id ?? "";
19070
+ if (kind === "invocation")
19071
+ pending.push(owner);
19072
+ else
19073
+ resolvedOwners.set(callId, owner);
19074
+ owners.set(callId, pending);
19075
+ const key = makeToolCompositeKey(owner, callId);
19076
+ if (message.info.role === "tool" && !toolThinking.has(key))
19077
+ toolThinking.set(key, precedingThinking);
19078
+ const entry = index.get(key) ?? { occurrences: [], hasResult: false };
19079
+ entry.occurrences.push({ message, part, kind });
19080
+ entry.hasResult ||= kind === "result" && partHasCompletedResult(part);
19081
+ index.set(key, entry);
19082
+ } else {
19083
+ const prefix = isTextPart(part) ? /^§(\d+)§\s/.exec(part.text) : null;
19084
+ const tag = (prefix ? byNumber.get(Number(prefix[1])) : undefined) ?? textTags.get(`${message.info.id}:p${p}`) ?? textTags.get(`${message.info.id}:file${p}`);
19085
+ if (tag && tag.type !== "tool")
19086
+ targets.set(tag.tagNumber, {
19087
+ message,
19088
+ setContent(content) {
19089
+ if (isTextPart(part)) {
19090
+ if (part.text === content)
19091
+ return false;
19092
+ part.text = content;
19093
+ } else
19094
+ message.parts[p] = { type: "text", text: content };
19095
+ return true;
19096
+ }
19097
+ });
19098
+ }
19099
+ }
19100
+ if (message.info.role === "assistant" && !message.parts.some(isTextPart))
19101
+ precedingThinking = thinking;
19102
+ }
19103
+ const arcsByCall = new Map;
19104
+ for (const entry of index.values()) {
19105
+ const callId = extractToolCallObservation(entry.occurrences[0]?.part)?.callId ?? "";
19106
+ arcsByCall.set(callId, (arcsByCall.get(callId) ?? 0) + 1);
19107
+ }
19108
+ for (const [key, entry] of index) {
19109
+ const callId = extractToolCallObservation(entry.occurrences[0]?.part)?.callId ?? "";
19110
+ if (ambiguousCalls.has(callId))
19111
+ continue;
19112
+ const tag = toolTags.get(key) ?? (arcsByCall.get(callId) === 1 ? toolTags.get(makeToolCompositeKey("", callId)) : undefined);
19113
+ if (tag)
19114
+ targets.set(tag.tagNumber, createToolDropTarget(key, toolThinking.get(key) ?? [], index, batch, tag.tagNumber));
19115
+ }
19116
+ applyFlushedStatuses(sessionId, db, targets, tags);
19117
+ batch.finalize();
19118
+ if (JSON.stringify(recoveryReasoningPrefixes(messages, "parts")) !== JSON.stringify(reasoningPrefixes))
19119
+ return false;
19120
+ if (messages !== original)
19121
+ original.splice(0, original.length, ...messages);
19122
+ return true;
19123
+ }
19124
+
18606
19125
  // src/plugin/messages-transform.ts
18607
19126
  var ASSISTANT_TERMINAL_RETRY_MESSAGE = "The conversation ends with a completed assistant response and cannot be resubmitted as-is — send a new message to continue.";
18608
19127
 
@@ -18745,7 +19264,6 @@ function tryMessagesTransformLkgReplay(args) {
18745
19264
  sessionLog2(sessionId, "lkg_emergency_armed");
18746
19265
  } else {
18747
19266
  const inputMessages = output.messages;
18748
- const inputCount = inputMessages.length;
18749
19267
  const keys = resolveLkgModelKeys(inputMessages);
18750
19268
  const replay = replayLkg({
18751
19269
  sessionId,
@@ -18764,6 +19282,10 @@ function tryMessagesTransformLkgReplay(args) {
18764
19282
  sessionLog2(sessionId, "lkg_restart_rebuild_required");
18765
19283
  return false;
18766
19284
  }
19285
+ if (replay.ok && !rust && !replayCommittedDrops(db, sessionId, replay.messages)) {
19286
+ sessionLog2(sessionId, "lkg_reasoning_prefix_changed");
19287
+ return false;
19288
+ }
18767
19289
  let tsFit = true;
18768
19290
  if (replay.ok && !rust && keys.providerKey && keys.modelKey) {
18769
19291
  const model = {
@@ -18813,8 +19335,8 @@ function tryMessagesTransformLkgReplay(args) {
18813
19335
  return false;
18814
19336
  retirePendingSystemPromptDelivery(sessionId);
18815
19337
  args.onLkgReplay?.();
19338
+ noteExternalLkgReplay(rust, sessionId, inputMessages, replay.messages);
18816
19339
  replaceMessagesInPlace2(output, replay.messages);
18817
- noteExternalLkgReplay(rust, sessionId, inputCount);
18818
19340
  sessionLog2(sessionId, "lkg_replay_served");
18819
19341
  return true;
18820
19342
  } else {
@@ -20124,7 +20646,7 @@ function computeOpenCodeWorkMetricsIncremental(openCodeDb, sessionId, carry) {
20124
20646
  import { readFileSync, statSync } from "node:fs";
20125
20647
 
20126
20648
  // src/plugin/embedding-bootstrap-helpers.ts
20127
- import { createHash as createHash5 } from "node:crypto";
20649
+ import { createHash as createHash6 } from "node:crypto";
20128
20650
  var EMBEDDING_AFFECTING_KEYS = new Set([
20129
20651
  "embedding.api_key",
20130
20652
  "embedding.endpoint",
@@ -20172,7 +20694,7 @@ var EMBEDDING_WARNING_TERMS = [
20172
20694
  ];
20173
20695
  var loggedFailureSignatures = new Map;
20174
20696
  function sha256Prefix(value, length = 16) {
20175
- return createHash5("sha256").update(value).digest("hex").slice(0, length);
20697
+ return createHash6("sha256").update(value).digest("hex").slice(0, length);
20176
20698
  }
20177
20699
  function warningLooksEmbeddingRelated(message) {
20178
20700
  const lower = message.toLowerCase();
@@ -21555,7 +22077,7 @@ function registerRpcHandlers(rpcServer, args) {
21555
22077
  const sessionId = String(params.sessionId ?? "");
21556
22078
  if (!sessionId)
21557
22079
  return { owner: false };
21558
- const sessionDirectory = liveSessionState.sessionDirectoryBySession.get(sessionId) ?? await readHostSessionDirectory(args.client, sessionId);
22080
+ const sessionDirectory = args.readSessionDirectory ? await args.readSessionDirectory(sessionId) : await readHostSessionDirectory(args.client, sessionId) ?? liveSessionState.sessionDirectoryBySession.get(sessionId);
21559
22081
  if (!sessionDirectory)
21560
22082
  return { owner: false };
21561
22083
  return {
@@ -21626,7 +22148,7 @@ function registerRpcHandlers(rpcServer, args) {
21626
22148
  return { count: buildCompartmentCount(db, sessionId, moduleStatus) };
21627
22149
  });
21628
22150
  const buildManagedCtx = async (db) => {
21629
- const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await importPluginModule(() => import("./derive-budgets-enckmg7y.js"));
22151
+ const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await importPluginModule(() => import("./derive-budgets-0rmpmxjw.js"));
21630
22152
  const { resolveHistorianModel } = await importPluginModule(() => import("./model-resolution-nx97z3x7.js"));
21631
22153
  const { userMemoryCollectionEnabled } = await importPluginModule(() => import("./task-config-x0hq3qfd.js"));
21632
22154
  const DEFAULT_HISTORIAN_TIMEOUT_MS = 10 * 60 * 1000;
@@ -21641,6 +22163,7 @@ function registerRpcHandlers(rpcServer, args) {
21641
22163
  directory,
21642
22164
  historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(historianModel.primary?.model)),
21643
22165
  historianTimeoutMs: runConfig.historian_timeout_ms ?? DEFAULT_HISTORIAN_TIMEOUT_MS,
22166
+ historianMaxOutputTokens: runConfig.historian?.maxTokens,
21644
22167
  memoryEnabled: config.memory?.enabled ?? true,
21645
22168
  autoPromote: runConfig.memory?.auto_promote ?? true,
21646
22169
  historianModel: historianModel.primary,
@@ -21655,6 +22178,20 @@ function registerRpcHandlers(rpcServer, args) {
21655
22178
  const sessionId = String(params.sessionId ?? "");
21656
22179
  if (!sessionId)
21657
22180
  return { ok: false, error: "no session" };
22181
+ const readDirectory = args.readSessionDirectory;
22182
+ if (readDirectory) {
22183
+ const { handoffHistoryWork } = await import("./history-owner-2cr9py37.js");
22184
+ const handed = await handoffHistoryWork({
22185
+ storageDir: args.storageDir ?? getMagicContextStorageDir(),
22186
+ directory,
22187
+ sessionId,
22188
+ method: "recomp",
22189
+ params,
22190
+ readDirectory: () => readDirectory(sessionId)
22191
+ });
22192
+ if (handed)
22193
+ return handed;
22194
+ }
21658
22195
  const dir = String(params.directory ?? directory);
21659
22196
  if (config.transform_mode === "rust") {
21660
22197
  return executeRustRecompRpc(rustModeModuleClient, sessionId, dir);
@@ -21662,8 +22199,8 @@ function registerRpcHandlers(rpcServer, args) {
21662
22199
  const db = readDatabase();
21663
22200
  if (!db)
21664
22201
  return { ok: false, error: "db unavailable" };
21665
- const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-v64r4s4r.js"));
21666
- const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-5aj2j7vf.js"));
22202
+ const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-ee91r9s6.js"));
22203
+ const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-6n7chhyp.js"));
21667
22204
  log2(`[rpc] recomp requested for session ${sessionId}`);
21668
22205
  if (!args.client && !args.hiddenCompletionExecutor) {
21669
22206
  return {
@@ -21719,6 +22256,21 @@ function registerRpcHandlers(rpcServer, args) {
21719
22256
  return { ok: true, message };
21720
22257
  });
21721
22258
  rpcServer.handle("wrapup", async (params) => {
22259
+ const readDirectory = args.readSessionDirectory;
22260
+ if (readDirectory && params.sessionId) {
22261
+ const { handoffHistoryWork } = await import("./history-owner-2cr9py37.js");
22262
+ const sessionId = String(params.sessionId);
22263
+ const handed = await handoffHistoryWork({
22264
+ storageDir: args.storageDir ?? getMagicContextStorageDir(),
22265
+ directory,
22266
+ sessionId,
22267
+ method: "wrapup",
22268
+ params,
22269
+ readDirectory: () => readDirectory(sessionId)
22270
+ });
22271
+ if (handed)
22272
+ return handed;
22273
+ }
21722
22274
  const sessionId = String(params.sessionId ?? "");
21723
22275
  if (!sessionId)
21724
22276
  return { ok: false, error: "no session" };
@@ -21732,7 +22284,7 @@ function registerRpcHandlers(rpcServer, args) {
21732
22284
  const db = readDatabase();
21733
22285
  if (!db)
21734
22286
  return { ok: false, error: "db unavailable" };
21735
- const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-cahk37n7.js"));
22287
+ const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-5wxy1ggv.js"));
21736
22288
  const model = liveSessionState.liveModelBySession.get(sessionId);
21737
22289
  const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
21738
22290
  const ctx = {
@@ -22157,7 +22709,7 @@ class MagicContextRpcServer {
22157
22709
  }
22158
22710
  this.startedAt = Date.now();
22159
22711
  const self = this;
22160
- const server = Bun.serve({
22712
+ const server = inRootAsyncContext2(() => Bun.serve({
22161
22713
  port: 0,
22162
22714
  hostname: "127.0.0.1",
22163
22715
  fetch(req, srv) {
@@ -22180,7 +22732,7 @@ class MagicContextRpcServer {
22180
22732
  self.sockets.delete(ws);
22181
22733
  }
22182
22734
  }
22183
- });
22735
+ }));
22184
22736
  this.server = server;
22185
22737
  this.port = server.port ?? 0;
22186
22738
  try {
@@ -22721,8 +23273,8 @@ function hostMediaFromEncoded(value) {
22721
23273
  import { randomUUID as randomUUID4 } from "node:crypto";
22722
23274
 
22723
23275
  // src/v2/fold/owner.ts
22724
- import { createHash as createHash6 } from "node:crypto";
22725
- var foldDigest = (value) => createHash6("sha256").update(value).digest("hex");
23276
+ import { createHash as createHash7 } from "node:crypto";
23277
+ var foldDigest = (value) => createHash7("sha256").update(value).digest("hex");
22726
23278
 
22727
23279
  class FoldOwner {
22728
23280
  storage;
@@ -23063,12 +23615,12 @@ function placeCacheHint(content, hint) {
23063
23615
  const index = lastText >= 0 ? lastText : content.length - 1;
23064
23616
  content[index] = { ...content[index], cache: hint };
23065
23617
  }
23066
- function removeEmptyTextParts(content, rendered) {
23618
+ function removeEmptyTextParts(content, rendered, mayRemove) {
23067
23619
  let hint;
23068
23620
  let removed = 0;
23069
23621
  for (let index = content.length - 1;index >= 0; index -= 1) {
23070
23622
  const part = content[index];
23071
- if (part?.type !== "text" || part.text !== "")
23623
+ if (part?.type !== "text" || part.text !== "" || !mayRemove(part))
23072
23624
  continue;
23073
23625
  if (hint === undefined)
23074
23626
  hint = part.cache;
@@ -23144,12 +23696,14 @@ function contentValueAttachments(value) {
23144
23696
  ...typeof item.name === "string" ? { filename: item.name } : {}
23145
23697
  }));
23146
23698
  }
23147
- function rebuildFileContent(value, output) {
23699
+ function rebuildFileContent(value, output, attachments) {
23148
23700
  if (isDroppedToolOutput(output))
23149
23701
  return { type: "text", value: output };
23150
23702
  const rebuilt = [];
23151
23703
  let placed = false;
23152
23704
  for (const item of value) {
23705
+ if (item?.type === "file" && Array.isArray(attachments) && !attachments.some((attachment) => attachment?.url === item.uri && attachment?.mime === item.mime))
23706
+ continue;
23153
23707
  if (item?.type !== "text") {
23154
23708
  rebuilt.push(item);
23155
23709
  continue;
@@ -23292,14 +23846,16 @@ function adaptPayload(draft, admittedIDs = new Set) {
23292
23846
  let head = 0;
23293
23847
  const rendered = [];
23294
23848
  const emptyTextGuard = modelAcceptsEmptyContent(draft.model.providerID);
23849
+ const imageOmissions = getEmptyImageParts(messages);
23295
23850
  let omitted = 0;
23296
23851
  let emptyTextParts = 0;
23297
23852
  for (const message of messages) {
23298
23853
  const original = originals.get(message) ?? (typeof message.info.id === "string" ? originalsByID.get(message.info.id) : undefined);
23299
23854
  const id = message.info.syntheticHead ? HEAD_IDS[head++] : original?.id;
23300
23855
  const content = [];
23856
+ const emptyImages = new Set;
23301
23857
  const following = [];
23302
- for (const candidate of message.parts) {
23858
+ for (const [partIndex, candidate] of message.parts.entries()) {
23303
23859
  const part = candidate;
23304
23860
  const bridge = bridges.get(part) ?? (part.type === "tool" && typeof part.callID === "string" ? bridgesFor(message)?.get(part.callID) : undefined);
23305
23861
  if (!bridge) {
@@ -23355,7 +23911,10 @@ function adaptPayload(draft, admittedIDs = new Set) {
23355
23911
  }
23356
23912
  const { synthetic: _synthetic, ...clean } = part;
23357
23913
  const original = hostPartTypes.has(clean.type) && !containsHostInstance(clean) ? hostParts.get(contentKey(clean)) : undefined;
23358
- content.push(original ?? clean);
23914
+ const projected = original ?? clean;
23915
+ if (imageOmissions.get(message.info.id ?? "")?.has(partIndex))
23916
+ emptyImages.add(projected);
23917
+ content.push(projected);
23359
23918
  continue;
23360
23919
  }
23361
23920
  const state = part.state;
@@ -23387,7 +23946,7 @@ function adaptPayload(draft, admittedIDs = new Set) {
23387
23946
  if (bridge.result && bridge.resultMessage) {
23388
23947
  const result = {
23389
23948
  ...bridge.result,
23390
- result: state.output === bridge.output ? bridge.result.result : bridge.files && typeof state.output === "string" ? rebuildFileContent(bridge.files, state.output) : {
23949
+ result: state.output === bridge.output ? bridge.result.result : bridge.files && typeof state.output === "string" ? rebuildFileContent(bridge.files, state.output, state.attachments) : {
23391
23950
  type: state.status === "error" ? "error" : "text",
23392
23951
  value: state.output
23393
23952
  }
@@ -23398,7 +23957,7 @@ function adaptPayload(draft, admittedIDs = new Set) {
23398
23957
  following.push({ ...bridge.resultMessage, content: [result] });
23399
23958
  }
23400
23959
  }
23401
- const guarded = emptyTextGuard ? removeEmptyTextParts(content, rendered) : 0;
23960
+ const guarded = removeEmptyTextParts(content, rendered, (part) => emptyTextGuard || emptyImages.has(part));
23402
23961
  if (content.length || !original?.content.length && guarded === 0) {
23403
23962
  const value = {
23404
23963
  ...original,
@@ -23408,7 +23967,7 @@ function adaptPayload(draft, admittedIDs = new Set) {
23408
23967
  };
23409
23968
  const existing = id ? existingHeads.get(id) : undefined;
23410
23969
  rendered.push(existing ? Object.assign(existing, { content }) : value);
23411
- } else if (emptyTextGuard) {
23970
+ } else if (emptyTextGuard || guarded > 0) {
23412
23971
  omitted += 1;
23413
23972
  }
23414
23973
  emptyTextParts += guarded;
@@ -23416,7 +23975,7 @@ function adaptPayload(draft, admittedIDs = new Set) {
23416
23975
  }
23417
23976
  if (omitted + emptyTextParts > 0 && !emptyTextOmissionLogged.has(draft.sessionID)) {
23418
23977
  emptyTextOmissionLogged.add(draft.sessionID);
23419
- sessionLog2(draft.sessionID, `v2 payload: left out ${omitted} emptied messages and ${emptyTextParts} empty text parts, because Anthropic rejects an empty text block (logged once per session)`);
23978
+ sessionLog2(draft.sessionID, `v2 payload: left out ${omitted} emptied messages and ${emptyTextParts} empty text parts, ${emptyTextGuard ? "because Anthropic rejects an empty text block" : "to replay frozen image omissions"} (logged once per session)`);
23420
23979
  }
23421
23980
  draft.messages.splice(0, draft.messages.length, ...rendered);
23422
23981
  }
@@ -24306,7 +24865,7 @@ function createNativeHiddenChildren(host, removeSession, options) {
24306
24865
  }
24307
24866
  const directory = stored.location?.directory;
24308
24867
  if (options.directory !== undefined && directory !== undefined && !sameProjectDirectory(directory, options.directory)) {
24309
- throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", `hidden child ${sessionID} is bound to ${directory}, not to this instance's ${options.directory}`, true);
24868
+ throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", `hidden child ${sessionID} is bound to ${directory}, not to this instance's ${options.directory}. Reopen the parent session in ${directory}, then run /ctx-recomp so its owning instance can rebuild history.`, true);
24310
24869
  }
24311
24870
  if (stored.parentID === parentID || parentDroppedNoted)
24312
24871
  return;
@@ -24933,7 +25492,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
24933
25492
  budgetReject = reject;
24934
25493
  });
24935
25494
  if (budget) {
24936
- budgetPoll = setInterval(() => {
25495
+ budgetPoll = inRootAsyncContext2(() => setInterval(() => {
24937
25496
  try {
24938
25497
  const fresh = withReader(options.openReader, (reader) => reader.assistantSince?.(run.child.id, usageSeq) ?? (() => {
24939
25498
  const latest = reader.latestAssistant(run.child.id);
@@ -24947,7 +25506,10 @@ async function createV2HiddenCompletionExecutor(host, options) {
24947
25506
  const decision = budget.charge(Math.max(0, tokens?.input ?? 0), Math.max(0, tokens?.cache?.read ?? 0), Math.max(0, tokens?.cache?.write ?? 0), row.data.finish === "stop" && !(row.data.content ?? []).some((part) => part.type === "tool-call"), false);
24948
25507
  const onBudgetUpdate = run.identity.metadata?.onBudgetUpdate;
24949
25508
  if (typeof onBudgetUpdate === "function")
24950
- onBudgetUpdate({ ...budget.snapshot(), sessionId: run.child.id });
25509
+ onBudgetUpdate({
25510
+ ...budget.snapshot(),
25511
+ sessionId: run.child.id
25512
+ });
24951
25513
  if (decision !== "continue") {
24952
25514
  if (budgetPoll)
24953
25515
  clearInterval(budgetPoll);
@@ -24961,7 +25523,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
24961
25523
  clearInterval(budgetPoll);
24962
25524
  budgetReject(error instanceof Error ? error : new Error(String(error)));
24963
25525
  }
24964
- }, POLL_INTERVAL_MS);
25526
+ }, POLL_INTERVAL_MS));
24965
25527
  }
24966
25528
  let abortReject;
24967
25529
  const aborted = new Promise((_resolve, reject) => {
@@ -25316,11 +25878,11 @@ class DeletedSessionTombstones {
25316
25878
  }
25317
25879
 
25318
25880
  // src/features/magic-context/dreamer/task-executor.ts
25319
- import { createHash as createHash13 } from "node:crypto";
25881
+ import { createHash as createHash14 } from "node:crypto";
25320
25882
  import { existsSync as existsSync7, readFileSync as readFileSync8 } from "node:fs";
25321
25883
 
25322
25884
  // src/features/magic-context/mural/compress-cues.ts
25323
- import { createHash as createHash7 } from "node:crypto";
25885
+ import { createHash as createHash8 } from "node:crypto";
25324
25886
 
25325
25887
  // src/features/magic-context/dreamer/storage-dream-state.ts
25326
25888
  var getDreamStateStatements = new WeakMap;
@@ -25523,7 +26085,7 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalOrAcquisiti
25523
26085
  }
25524
26086
  };
25525
26087
  beat();
25526
- const timer = lost ? undefined : setInterval(() => withSqliteBackgroundWriter2(beat), intervalMs);
26088
+ const timer = lost ? undefined : inRootAsyncContext2(() => setInterval(() => withSqliteBackgroundWriter2(beat), intervalMs));
25527
26089
  return {
25528
26090
  stop: () => {
25529
26091
  if (timer)
@@ -26050,7 +26612,7 @@ async function applyCuesThroughModule(args, chunk, manifestText, signal) {
26050
26612
  log2(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason}; rejection ${rejectionCount}/${CUE_REJECTION_LATCH_THRESHOLD})`);
26051
26613
  }
26052
26614
  }
26053
- const commandId = `mural-cues:${route.moduleCommandId}:${createHash7("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
26615
+ const commandId = `mural-cues:${route.moduleCommandId}:${createHash8("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
26054
26616
  let response;
26055
26617
  try {
26056
26618
  response = await route.moduleClient.call({
@@ -26149,6 +26711,25 @@ async function runHiddenSingleShotPrompt(args) {
26149
26711
  });
26150
26712
  promptSettled = true;
26151
26713
  return { validated: run.validated, completion: run.output, childSessionId: handle.id };
26714
+ } catch (error) {
26715
+ if (args.onFailureOutput) {
26716
+ let timer;
26717
+ try {
26718
+ const completion = await Promise.race([
26719
+ args.executor.collect(handle, 200),
26720
+ new Promise((resolve) => {
26721
+ timer = setTimeout(() => resolve(null), 5000);
26722
+ })
26723
+ ]);
26724
+ if (completion)
26725
+ args.onFailureOutput(completion);
26726
+ } catch (readError) {
26727
+ log2(`${args.callContext}: failed to collect interrupted output: ${String(readError)}`);
26728
+ } finally {
26729
+ clearTimeout(timer);
26730
+ }
26731
+ }
26732
+ throw error;
26152
26733
  } finally {
26153
26734
  await args.executor.close(handle, {
26154
26735
  promptSettled,
@@ -26619,7 +27200,7 @@ function applyReviewVerdict(args, leaseKey, parsed, result) {
26619
27200
  }
26620
27201
 
26621
27202
  // src/features/magic-context/dreamer/classify.ts
26622
- import { createHash as createHash8 } from "node:crypto";
27203
+ import { createHash as createHash9 } from "node:crypto";
26623
27204
 
26624
27205
  // src/plugin/rust-tool-backends.ts
26625
27206
  function isRustAuthorityDrainingError(error) {
@@ -27056,7 +27637,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal, runOnHost)
27056
27637
  if (entry.qualifier)
27057
27638
  modelVariants[entry.model] = entry.qualifier;
27058
27639
  }
27059
- const commandId = `classify:${args.moduleCommandId ?? Date.now()}:${createHash8("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`;
27640
+ const commandId = `classify:${args.moduleCommandId ?? Date.now()}:${createHash9("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`;
27060
27641
  const runTask = (hostCompletion) => args.moduleClient?.call({
27061
27642
  sessionId: args.moduleSessionId,
27062
27643
  projectRoot: args.moduleProjectRoot,
@@ -27331,7 +27912,7 @@ function takeCurateSafetyRefusalCount(sessionId) {
27331
27912
 
27332
27913
  // src/features/magic-context/dreamer/docs-proposals.ts
27333
27914
  import { execFileSync } from "node:child_process";
27334
- import { createHash as createHash9 } from "node:crypto";
27915
+ import { createHash as createHash10 } from "node:crypto";
27335
27916
  import {
27336
27917
  existsSync as existsSync4,
27337
27918
  mkdirSync,
@@ -27346,7 +27927,7 @@ import {
27346
27927
  import { tmpdir } from "node:os";
27347
27928
  import { join as join7 } from "node:path";
27348
27929
  var FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
27349
- var hash = (text) => createHash9("sha256").update(text).digest("hex");
27930
+ var hash = (text) => createHash10("sha256").update(text).digest("hex");
27350
27931
  var proposalDir = (projectDir) => join7(projectDir, ".cortexkit/magic-context/docs-update-proposals");
27351
27932
  function docsBaseHashes(projectDir) {
27352
27933
  return Object.fromEntries(FILES.map((name) => [
@@ -27882,7 +28463,7 @@ function throwIfAborted2(signal) {
27882
28463
  }
27883
28464
 
27884
28465
  // src/features/magic-context/smart-notes/compiler.ts
27885
- import { createHash as createHash10 } from "node:crypto";
28466
+ import { createHash as createHash11 } from "node:crypto";
27886
28467
 
27887
28468
  // src/features/magic-context/smart-notes/compiler-prompt.ts
27888
28469
  var SMART_NOTE_COMPILER_SYSTEM_PROMPT = `You are the Magic Context smart-note compiler for the magic-context system.
@@ -28213,7 +28794,7 @@ function manifestAdvisoryWarnings(code, manifest) {
28213
28794
  return warnings;
28214
28795
  }
28215
28796
  function hashCheck(surfaceCondition, compiledCheck, manifest, checkCron) {
28216
- return createHash10("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
28797
+ return createHash11("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
28217
28798
  }
28218
28799
  function extractJsonObject(output) {
28219
28800
  const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
@@ -28307,10 +28888,10 @@ async function probeWakePlaneCatalog() {
28307
28888
  if (!await connectionFileExists(file)) {
28308
28889
  throw new Error("subc connection is not configured");
28309
28890
  }
28310
- const client = await SubcClient.connect({
28891
+ const client = await inRootAsyncContext2(() => SubcClient.connect({
28311
28892
  connectionFile: file,
28312
28893
  handshakeTimeoutMs: WAKE_PLANE_HANDSHAKE_TIMEOUT_MS
28313
- });
28894
+ }));
28314
28895
  try {
28315
28896
  return await client.catalogList();
28316
28897
  } finally {
@@ -28979,34 +29560,36 @@ function snapshotMaintainDocsFiles(docsDir) {
28979
29560
  }
28980
29561
 
28981
29562
  // src/features/magic-context/dreamer/map-memories.ts
28982
- import { createHash as createHash11 } from "node:crypto";
29563
+ import { createHash as createHash12 } from "node:crypto";
28983
29564
 
28984
29565
  // src/features/magic-context/dreamer/map-memories-prompt.ts
29566
+ import { execFile as execFile2 } from "node:child_process";
28985
29567
  import { existsSync as existsSync6, statSync as statSync3 } from "node:fs";
28986
29568
  import path4 from "node:path";
29569
+ import { promisify as promisify2 } from "node:util";
28987
29570
  var MAP_MEMORIES_SYSTEM_PROMPT = `You are a memory mapper for the magic-context system. You map project memories to the repository files that back them.
28988
29571
 
28989
29572
  A memory's BACKING FILES are the file(s) whose code the memory makes a claim about — the files you would open to check whether the memory is accurate. You do NOT judge accuracy, rewrite, or remove anything. You only LOCATE backing files.
28990
29573
 
28991
- Tools (read-only): read, grep, glob. Request line ranges rather than full files; use offset/limit for longer files. Each memory may come with "Likely files" already named in it and confirmed to exist — confirm those FIRST (cheap) instead of searching. Use search/grep to FIND code only when no likely files are given. Do not guess — confirm a file exists and genuinely backs the memory before listing it. Keep reads minimal: you do not need to read a whole file to confirm it backs a one-line claim.
29574
+ Tools (read-only): read, grep, glob. Use at most 3 tool calls per memory, including searches and reads. Never read the same file twice in a batch; reuse what you already learned. Never repeat an identical search or use broad searches such as "fn " or ".*". Request one useful line range, not repeated slices. Each memory may come with "Likely files" from paths it names or a literal identifier search, confirmed to exist — confirm those FIRST (cheap) instead of searching. Use search/grep to FIND code only when no likely files are given. Do not guess — confirm a file exists and genuinely backs the memory before listing it. You are locating code, not exhaustively verifying the claim. If the call budget runs out before you can decide, leave that id unmapped and move on; uncertainty is not evidence of file-independence.
28992
29575
 
28993
29576
  For each memory decide ONE of:
28994
- - Backing files found → the COMPLETE set of repo-relative paths whose code the memory is about.
29577
+ - Backing files found → the specific repo-relative paths whose code the memory is about; do not chase every caller or related implementation.
28995
29578
  - File-independent → the memory describes EXTERNAL behavior (a provider / API / platform / protocol limit, e.g. "Anthropic returns 400 on empty content"), or a pure process / workflow / philosophy rule, with NO specific local file that backs it. A BEHAVIORAL claim (when to act, how to work, who decides, or tool-usage discipline) is file-independent even when it cites file paths or commands as examples: a named file is not the file backing the rule.
28996
29579
 
28997
- Output ONE XML manifest at the very end and NOTHING else — no narration, no per-memory commentary, no reasoning:
29580
+ Output ONE XML manifest and NOTHING else — no narration, no per-memory commentary, no reasoning. Open <mappings> before investigating. Emit each <memory> element as soon as you decide its mapping, before investigating the next memory, so an interruption cannot lose completed work. Close </mappings> when finished:
28998
29581
  <mappings>
28999
29582
  <memory id="N" files="path/a.ts,path/b.ts"/>
29000
29583
  <memory id="M" independent="true"/>
29001
29584
  </mappings>
29002
29585
 
29003
29586
  Rules:
29004
- - Every input memory id MUST appear exactly once.
29587
+ - Every decided input memory id MUST appear exactly once. Omit uncertain ids rather than inventing backing files or declaring them independent.
29005
29588
  - files: repo-relative, comma-separated, no spaces inside a path. Only files that actually exist and genuinely back the memory.
29006
29589
  - A BACKING FILE is CODE that implements or handles the claim — not a file that merely mentions it. A path named inside a process directive is an action target or example, not evidence that the file backs the directive. A markdown doc (.md), a PARITY/notes file, or a test that only DESCRIBES an external fact is NOT a backing file. If the only place a memory's fact appears is prose/docs/a test (no code implements or handles it), mark it independent="true".
29007
29590
  - Many CONSTRAINTS are HYBRID: "external system does X, and OUR code handles it here." Map those to the HANDLING code (you can verify the handling, even though you can't verify the external behavior). Only mark independent when there is NO local code that implements or handles the fact.
29008
29591
  - Prefer the most specific file(s); do not pad with tangential files. Most memories map to one file; some to a few.
29009
- - When you genuinely cannot find any local backing and it is not clearly external, still emit the memory with independent="true" (do not drop it).`;
29592
+ - Mark independent="true" only for the file-independent cases above; an investigation that runs out of calls stays unmapped.`;
29010
29593
  var MAX_SEED_PATHS_PER_MEMORY = 3;
29011
29594
  var PATH_PATTERN = "`?((?:[\\w.-]+\\/)+[\\w.-]+\\.(?:ts|tsx|js|jsx|mjs|cjs|rs|go|py|json|jsonc|sql|toml|sh))`?";
29012
29595
  function extractMemoryCandidatePaths(content, repoDir) {
@@ -29028,10 +29611,65 @@ function extractMemoryCandidatePaths(content, repoDir) {
29028
29611
  }
29029
29612
  return [...found];
29030
29613
  }
29614
+ var execFileAsync2 = promisify2(execFile2);
29615
+ async function seedIdentifierCandidates(memories, repoDir) {
29616
+ const identifiers = new Map(memories.filter((memory) => memory.candidates.length === 0).map((memory) => [
29617
+ memory.id,
29618
+ [
29619
+ ...new Set(memory.content.match(/\b(?:[A-Z][A-Za-z0-9_]{3,}|[a-z][a-z0-9]*[A-Z][A-Za-z0-9_]*|[a-z][a-z0-9]*_[A-Za-z0-9_]{2,})\b/g) ?? [])
29620
+ ].slice(0, 3)
29621
+ ]));
29622
+ const terms = [...new Set([...identifiers.values()].flat())];
29623
+ if (terms.length === 0)
29624
+ return memories;
29625
+ let stdout;
29626
+ try {
29627
+ const result = await execFileAsync2("git", [
29628
+ "-c",
29629
+ "core.quotePath=false",
29630
+ "grep",
29631
+ "--no-color",
29632
+ "-n",
29633
+ "-I",
29634
+ "-F",
29635
+ ...terms.flatMap((term) => ["-e", term]),
29636
+ "--",
29637
+ ...["ts", "tsx", "js", "jsx", "mjs", "cjs", "rs", "go", "py", "sql", "sh"].map((extension) => `*.${extension}`)
29638
+ ], {
29639
+ cwd: repoDir,
29640
+ encoding: "utf8",
29641
+ timeout: 2000,
29642
+ maxBuffer: 256 * 1024,
29643
+ windowsHide: true,
29644
+ killSignal: "SIGKILL"
29645
+ });
29646
+ stdout = result.stdout;
29647
+ } catch {
29648
+ return memories;
29649
+ }
29650
+ const matches = stdout.split(`
29651
+ `).flatMap((line) => {
29652
+ const match = line.match(/^([^:]+):\d+:(.*)$/);
29653
+ return match ? [{ file: match[1], text: match[2] }] : [];
29654
+ });
29655
+ return memories.map((memory) => {
29656
+ const names = identifiers.get(memory.id);
29657
+ if (!names?.length)
29658
+ return memory;
29659
+ const files = new Map;
29660
+ for (const match of matches) {
29661
+ const score = names.filter((name) => match.text.includes(name)).length;
29662
+ if (score)
29663
+ files.set(match.file, Math.max(files.get(match.file) ?? 0, score));
29664
+ }
29665
+ const candidates = [...files].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_SEED_PATHS_PER_MEMORY).map(([file]) => file);
29666
+ return candidates.length ? { ...memory, candidates } : memory;
29667
+ });
29668
+ }
29031
29669
  function buildMapMemoriesPrompt(projectPath, memories) {
29032
29670
  const list = memories.map((m) => {
29033
29671
  const seed = m.candidates.length ? `
29034
- Likely files (named in the memory, confirmed to exist): ${m.candidates.join(", ")}` : "";
29672
+ Likely files (candidate paths, confirmed to exist): ${m.candidates.join(", ")}` : "";
29035
29673
  return `[${m.id}] ${m.category}
29036
29674
  ${m.content}${seed}`;
29037
29675
  }).join(`
@@ -29041,13 +29679,13 @@ ${m.content}${seed}`;
29041
29679
 
29042
29680
  Project: ${projectPath}
29043
29681
 
29044
- For each memory below, find the repo file(s) it makes a claim about, or mark it file-independent. Behavioral process/workflow directives stay file-independent even when they name files. When "Likely files" are listed, those paths are named in the memory and confirmed to exist — START there only for code claims: confirm each actually backs the claim (a quick read/outline), drop any that don't, add others only if genuinely needed. Search from scratch only when no likely files are given. Then output ONE <mappings> manifest covering every id.
29682
+ For each memory below, find the repo file(s) it makes a claim about, or mark it file-independent. Behavioral process/workflow directives stay file-independent even when they name files. When "Likely files" are listed, those paths either occur in the memory or match its identifiers in a bounded literal source search — START there only for code claims: confirm each actually backs the claim (a quick read/outline), drop any that don't, add others only if genuinely needed. Search from scratch only when no likely files are given. Use at most 3 tool calls per memory, reuse prior reads, and emit each decided mapping immediately in ONE <mappings> manifest. Leave uncertain ids unmapped and move on.
29045
29683
 
29046
29684
  <memories>
29047
29685
  ${list}
29048
29686
  </memories>`;
29049
29687
  }
29050
- var MEMORY_ELEMENT_PATTERN = "<memory\\b([^>]*)(?:\\/>|>([\\s\\S]*?)<\\/memory>)";
29688
+ var MEMORY_ELEMENT_PATTERN = "<memory\\b([^<>]*)(?:\\/>|>([\\s\\S]*?)<\\/memory>)";
29051
29689
  var NESTED_FILE_PATTERN = "<file\\b([^>]*)\\/?>";
29052
29690
  function extractNestedFilePaths(inner) {
29053
29691
  const files = [];
@@ -29105,12 +29743,78 @@ function validateMapMemoriesManifest(text, expectedIds) {
29105
29743
  assertNoDuplicateManifestIds(parsed.filter((entry) => expectedIds.has(entry.id)).map((entry) => entry.id), "mappings");
29106
29744
  return parsed;
29107
29745
  }
29746
+ function parsePartialMapMemoriesManifest(text, expectedIds) {
29747
+ const start = text.indexOf("<mappings>");
29748
+ if (start < 0)
29749
+ return [];
29750
+ const entries = new Map;
29751
+ const conflicts = new Set;
29752
+ for (const match of text.slice(start).matchAll(new RegExp(MEMORY_ELEMENT_PATTERN, "gi"))) {
29753
+ try {
29754
+ const entry = parseMapMemoriesManifest(`<mappings>${match[0]}</mappings>`)[0];
29755
+ if (!entry || !expectedIds.has(entry.id) || conflicts.has(entry.id))
29756
+ continue;
29757
+ const previous = entries.get(entry.id);
29758
+ if (previous && JSON.stringify(previous) !== JSON.stringify(entry)) {
29759
+ entries.delete(entry.id);
29760
+ conflicts.add(entry.id);
29761
+ } else {
29762
+ entries.set(entry.id, entry);
29763
+ }
29764
+ } catch {}
29765
+ }
29766
+ return [...entries.values()];
29767
+ }
29108
29768
 
29109
29769
  // src/features/magic-context/dreamer/map-memories.ts
29110
- var MAP_BATCH_SIZE = 20;
29770
+ var MAP_BATCH_SIZE = 5;
29111
29771
  var MAP_BATCH_FLOOR_MS = 240000;
29112
29772
  var CONSECUTIVE_TIMEOUT_LIMIT2 = 2;
29113
29773
  var MAX_INDEPENDENT_REQUEUE_PER_RUN = MAP_BATCH_SIZE;
29774
+ function retryKey(project) {
29775
+ return `map-memories:retry:${project}`;
29776
+ }
29777
+ function readRetries(db, project) {
29778
+ try {
29779
+ const parsed = JSON.parse(getDreamState(db, retryKey(project)) ?? "{}");
29780
+ if (!isRecord(parsed))
29781
+ return {};
29782
+ const retries = {};
29783
+ for (const [id, value] of Object.entries(parsed)) {
29784
+ if (isRecord(value) && typeof value.content === "string" && typeof value.failures === "number" && typeof value.deferUntil === "number") {
29785
+ retries[id] = {
29786
+ content: value.content,
29787
+ failures: value.failures,
29788
+ deferUntil: value.deferUntil
29789
+ };
29790
+ }
29791
+ }
29792
+ return retries;
29793
+ } catch {
29794
+ return {};
29795
+ }
29796
+ }
29797
+ function contentKey2(memory) {
29798
+ return createHash12("sha256").update(`${memory.category}
29799
+ ${memory.content}`).digest("hex");
29800
+ }
29801
+ function isDeferred(memory, retries) {
29802
+ const retry = retries[memory.id];
29803
+ return !!retry && retry.content === contentKey2(memory) && retry.deferUntil > Date.now();
29804
+ }
29805
+ function assistantText2(messages) {
29806
+ return messages.filter((message) => isRecord(message) && (message.role === "assistant" || isRecord(message.info) && message.info.role === "assistant")).map((message) => extractLatestAssistantText([message]) ?? (isRecord(message) && Array.isArray(message.content) ? message.content.filter(isRecord).filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join(`
29807
+ `) : "")).join(`
29808
+ `);
29809
+ }
29810
+ function currentManifest(text) {
29811
+ const start = text.lastIndexOf("<mappings>");
29812
+ return start < 0 ? text : text.slice(start);
29813
+ }
29814
+ function logBatchUsage(messages, committed, startedAt) {
29815
+ const steps = messages.filter((message) => isRecord(message) && (message.role === "assistant" || isRecord(message.info) && message.info.role === "assistant")).length;
29816
+ log2(`[dreamer] map-memories batch: steps=${steps} committed=${committed} steps_per_memory=${committed ? (steps / committed).toFixed(2) : "n/a"} elapsed_ms=${Date.now() - startedAt}`);
29817
+ }
29114
29818
  function computeMapBatchSliceMs(remainingMs, batchesRemaining) {
29115
29819
  return Math.min(remainingMs, Math.max(MAP_BATCH_FLOOR_MS, Math.floor(remainingMs / batchesRemaining)));
29116
29820
  }
@@ -29132,7 +29836,7 @@ function toMapInput(memory, repoDir) {
29132
29836
  candidates: extractMemoryCandidatePaths(memory.content, repoDir)
29133
29837
  };
29134
29838
  }
29135
- function selectMapMemoryInputs(db, projectIdentity, repoDir) {
29839
+ function selectMapMemoryInputs(db, projectIdentity, repoDir, includeDeferred = false) {
29136
29840
  const active = getMemoriesByProject2(db, projectIdentity);
29137
29841
  const activeIds = active.map((m) => m.id);
29138
29842
  const unmapped = new Set(getUnmappedMemoryIds(db, activeIds));
@@ -29151,7 +29855,8 @@ function selectMapMemoryInputs(db, projectIdentity, repoDir) {
29151
29855
  if (requeue.length >= MAX_INDEPENDENT_REQUEUE_PER_RUN)
29152
29856
  break;
29153
29857
  }
29154
- return [...unmappedInputs, ...requeue];
29858
+ const retries = readRetries(db, projectIdentity);
29859
+ return [...unmappedInputs, ...requeue].filter((memory) => includeDeferred || !isDeferred(memory, retries));
29155
29860
  }
29156
29861
  async function mapMemories(args) {
29157
29862
  const result = {
@@ -29161,14 +29866,21 @@ async function mapMemories(args) {
29161
29866
  remaining: 0,
29162
29867
  complete: true
29163
29868
  };
29164
- const inputs = selectMapMemoryInputs(args.db, args.projectIdentity, args.sessionDirectory);
29869
+ const allInputs = selectMapMemoryInputs(args.db, args.projectIdentity, args.sessionDirectory, true);
29870
+ const retries = readRetries(args.db, args.projectIdentity);
29871
+ const activeIds = new Set(allInputs.map((memory) => String(memory.id)));
29872
+ for (const id of Object.keys(retries))
29873
+ if (!activeIds.has(id))
29874
+ delete retries[id];
29875
+ const inputs = allInputs.filter((memory) => !isDeferred(memory, retries));
29876
+ result.remaining = allInputs.length;
29877
+ result.complete = result.remaining === 0;
29165
29878
  if (inputs.length === 0)
29166
29879
  return result;
29167
29880
  const batches = [];
29168
29881
  for (let i = 0;i < inputs.length; i += MAP_BATCH_SIZE) {
29169
29882
  batches.push({ inputs: inputs.slice(i, i + MAP_BATCH_SIZE), isOmissionRetry: false });
29170
29883
  }
29171
- result.remaining = inputs.length;
29172
29884
  const abortController = new AbortController;
29173
29885
  const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, (reason) => abortController.abort(new Error(reason)), args.leaseAcquisition);
29174
29886
  try {
@@ -29191,6 +29903,24 @@ async function mapMemories(args) {
29191
29903
  break;
29192
29904
  const outcome = await mapOneBatch(args, batch.inputs, sliceMs, abortController.signal);
29193
29905
  const committed = outcome.mapped + outcome.independent;
29906
+ runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
29907
+ const committedIds = new Set(outcome.committedIds);
29908
+ for (const memory of batch.inputs) {
29909
+ if (committedIds.has(memory.id)) {
29910
+ delete retries[memory.id];
29911
+ continue;
29912
+ }
29913
+ const content = contentKey2(memory);
29914
+ const prior = retries[memory.id];
29915
+ const failures = (prior?.content === content ? prior.failures : 0) + 1;
29916
+ retries[memory.id] = {
29917
+ content,
29918
+ failures,
29919
+ deferUntil: failures < 2 ? 0 : Date.now() + Math.min(24, 2 ** (failures - 2)) * 3600000
29920
+ };
29921
+ }
29922
+ setDreamState(args.db, retryKey(args.projectIdentity), JSON.stringify(retries));
29923
+ });
29194
29924
  result.mapped += outcome.mapped;
29195
29925
  result.independent += outcome.independent;
29196
29926
  result.remaining -= committed;
@@ -29200,8 +29930,8 @@ async function mapMemories(args) {
29200
29930
  }
29201
29931
  if (outcome.requeue?.length) {
29202
29932
  if (!batch.isOmissionRetry) {
29203
- batches.splice(i + 1, 0, {
29204
- inputs: outcome.requeue,
29933
+ batches.push({
29934
+ inputs: outcome.requeue.filter((memory) => !isDeferred(memory, retries)),
29205
29935
  isOmissionRetry: true
29206
29936
  });
29207
29937
  log2(`[dreamer] map-memories: committed ${committed}/${batch.inputs.length} mapping(s); requeueing ${outcome.requeue.length} omitted id(s) in a targeted retry`);
@@ -29209,12 +29939,12 @@ async function mapMemories(args) {
29209
29939
  log2(`[dreamer] map-memories: targeted retry still omitted ${outcome.requeue.length} id(s); leaving them unmapped for the next run`);
29210
29940
  }
29211
29941
  }
29212
- if (outcome.failure?.class === "timeout") {
29942
+ if (outcome.failure?.class === "timeout" && committed === 0) {
29213
29943
  consecutiveTimeouts += 1;
29214
29944
  timeoutStreakElapsedMs.push(outcome.failure.elapsedMs);
29215
29945
  if (consecutiveTimeouts >= CONSECUTIVE_TIMEOUT_LIMIT2) {
29216
29946
  result.stopReason = "timeout-circuit-breaker";
29217
- log2(`[dreamer] map-memories starvation: circuit breaker tripped after ${consecutiveTimeouts} consecutive batch timeouts (model too slow for its time slice); per-batch elapsed [${timeoutStreakElapsedMs.join("ms, ")}ms] vs ${sliceMs}ms slice; stopping with ${result.remaining} mapping(s) remaining`);
29947
+ log2(`[dreamer] map-memories starvation: circuit breaker tripped after ${consecutiveTimeouts} consecutive batch timeouts with no committed mappings (investigation made no durable progress); per-batch elapsed [${timeoutStreakElapsedMs.join("ms, ")}ms] vs ${sliceMs}ms slice; stopping with ${result.remaining} mapping(s) remaining`);
29218
29948
  break;
29219
29949
  }
29220
29950
  } else {
@@ -29234,12 +29964,13 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
29234
29964
  let promptSettled = false;
29235
29965
  const startedAt = Date.now();
29236
29966
  let budgetFinalized = false;
29967
+ let failedCompletion;
29237
29968
  const onBudgetUpdate = (state) => {
29238
29969
  budgetFinalized ||= state.finalizeFired;
29239
29970
  args.onBudgetUpdate?.(state);
29240
29971
  };
29241
29972
  try {
29242
- const prompt = buildMapMemoriesPrompt(args.projectIdentity, batch);
29973
+ const prompt = buildMapMemoriesPrompt(args.projectIdentity, await seedIdentifierCandidates(batch, args.sessionDirectory));
29243
29974
  if (args.hiddenCompletionExecutor) {
29244
29975
  const run = await runHiddenSingleShotPrompt({
29245
29976
  executor: args.hiddenCompletionExecutor,
@@ -29255,14 +29986,18 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
29255
29986
  fallbackModels: args.fallbackModels,
29256
29987
  timeoutMs: sliceMs,
29257
29988
  signal,
29258
- parse: (text) => validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)))
29989
+ onFailureOutput: (completion) => {
29990
+ failedCompletion = completion;
29991
+ },
29992
+ parse: (text, completion) => validateMapMemoriesManifest(currentManifest(assistantText2(completion.messages ?? []) || text), new Set(batch.map((memory) => memory.id)))
29259
29993
  });
29260
29994
  recordInvocation2(args, startedAt, {
29261
29995
  status: "completed",
29262
29996
  messages: run.completion.messages ?? []
29263
29997
  });
29264
- const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized);
29265
- const returnedIds = new Set(run.validated.map((entry) => entry.id));
29998
+ const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
29999
+ logBatchUsage(run.completion.messages ?? [], outcome.mapped + outcome.independent, startedAt);
30000
+ const returnedIds = new Set(outcome.committedIds);
29266
30001
  return {
29267
30002
  ...outcome,
29268
30003
  requeue: budgetFinalized ? [] : batch.filter((memory) => !returnedIds.has(memory.id))
@@ -29305,7 +30040,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
29305
30040
  fetchOutput: async () => {
29306
30041
  const messagesResponse = await client.session.messages({
29307
30042
  path: { id: agentSessionId },
29308
- query: { directory: args.sessionDirectory, limit: 100 }
30043
+ query: { directory: args.sessionDirectory, limit: 200 }
29309
30044
  });
29310
30045
  return normalizeSDKResponse(messagesResponse, [], {
29311
30046
  preferResponseOnMissingData: true
@@ -29315,7 +30050,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
29315
30050
  if (hasLengthCappedOutput(messages)) {
29316
30051
  throw new Error("map-memories returned length-capped output");
29317
30052
  }
29318
- const text = extractLatestAssistantText(messages);
30053
+ const text = currentManifest(assistantText2(messages));
29319
30054
  if (!text)
29320
30055
  throw new Error("map-memories returned no output");
29321
30056
  return validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
@@ -29323,8 +30058,9 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
29323
30058
  });
29324
30059
  promptSettled = true;
29325
30060
  recordInvocation2(args, startedAt, { status: "completed", messages: run.output });
29326
- const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized);
29327
- const returnedIds = new Set(run.validated.filter((entry) => batch.some((memory) => memory.id === entry.id)).map((entry) => entry.id));
30061
+ const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
30062
+ logBatchUsage(run.output, outcome.mapped + outcome.independent, startedAt);
30063
+ const returnedIds = new Set(outcome.committedIds);
29328
30064
  return {
29329
30065
  ...outcome,
29330
30066
  requeue: budgetFinalized ? [] : batch.filter((memory) => !returnedIds.has(memory.id))
@@ -29332,18 +30068,23 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
29332
30068
  } catch (error) {
29333
30069
  const desc = describeError(error);
29334
30070
  log2(`[dreamer] map-memories batch failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
30071
+ const messages = failedCompletion?.messages ?? await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory) ?? [];
29335
30072
  recordInvocation2(args, startedAt, {
29336
30073
  status: failedInvocationStatus(error),
29337
30074
  error,
29338
- messages: await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory)
30075
+ messages
29339
30076
  });
29340
- if (error instanceof DreamerModuleFailureError || error instanceof DreamTokenBudgetExceeded)
30077
+ if (error instanceof DreamerModuleFailureError)
29341
30078
  throw error;
29342
30079
  if (signal.aborted)
29343
30080
  throw error;
30081
+ const recovered = parsePartialMapMemoriesManifest(assistantText2(messages) || failedCompletion?.text || "", new Set(batch.map((memory) => memory.id)));
30082
+ const outcome = await applyParsedBatchMappings(args, batch, recovered, budgetFinalized, true);
30083
+ logBatchUsage(messages, outcome.mapped + outcome.independent, startedAt);
30084
+ if (error instanceof DreamTokenBudgetExceeded)
30085
+ throw error;
29344
30086
  return {
29345
- mapped: 0,
29346
- independent: 0,
30087
+ ...outcome,
29347
30088
  failure: {
29348
30089
  class: isTimeoutClassError2(error) ? "timeout" : "other",
29349
30090
  elapsedMs: Date.now() - startedAt
@@ -29362,7 +30103,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
29362
30103
  });
29363
30104
  }
29364
30105
  }
29365
- async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = false) {
30106
+ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = false, allowPartial = false) {
29366
30107
  const batchIds = new Set(batch.map((memory) => memory.id));
29367
30108
  const valid = parsed.filter((entry) => batchIds.has(entry.id));
29368
30109
  const unknown = parsed.filter((entry) => !batchIds.has(entry.id));
@@ -29370,14 +30111,14 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
29370
30111
  log2(`[dreamer] map-memories warning: dropping ${unknown.length} unknown mapping entr${unknown.length === 1 ? "y" : "ies"} outside the current batch (${unknown.map((entry) => entry.id).join(", ")})`);
29371
30112
  }
29372
30113
  assertNoDuplicateManifestIds(valid.map((entry) => entry.id), "mappings");
29373
- if (!budgetFinalized && valid.length * 2 < batch.length) {
30114
+ if (!allowPartial && !budgetFinalized && valid.length * 2 < batch.length) {
29374
30115
  throw new Error(`mappings manifest covers ${valid.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
29375
30116
  }
29376
30117
  if (budgetFinalized && valid.length < batch.length) {
29377
30118
  log2(`[dreamer] map-memories: accepted partial manifest after token budget: ${valid.length}/${batch.length}`);
29378
30119
  }
29379
30120
  if (valid.length === 0)
29380
- return { mapped: 0, independent: 0 };
30121
+ return { mapped: 0, independent: 0, committedIds: [] };
29381
30122
  const planned = [];
29382
30123
  const batchById = new Map(batch.map((memory) => [memory.id, memory]));
29383
30124
  for (const p of valid) {
@@ -29426,9 +30167,10 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
29426
30167
  });
29427
30168
  }
29428
30169
  if (planned.length === 0)
29429
- return { mapped: 0, independent: 0 };
30170
+ return { mapped: 0, independent: 0, committedIds: [] };
29430
30171
  let mapped = 0;
29431
30172
  let independent = 0;
30173
+ const committedIds = [];
29432
30174
  if (args.moduleRoute) {
29433
30175
  const identities = getModuleMemoryIdentities(args.db, args.projectIdentity, planned.map((item) => item.id));
29434
30176
  const rows = planned.map((item) => {
@@ -29452,7 +30194,7 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
29452
30194
  name: "memory.set_mapping",
29453
30195
  arguments: {
29454
30196
  memory_project: args.projectIdentity,
29455
- command_id: `${args.moduleRoute.moduleCommandId}:${createHash11("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
30197
+ command_id: `${args.moduleRoute.moduleCommandId}:${createHash12("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
29456
30198
  rows
29457
30199
  }
29458
30200
  }
@@ -29466,19 +30208,22 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
29466
30208
  const accepted = new Set(result.accepted.filter((id) => typeof id === "number"));
29467
30209
  for (const item of planned) {
29468
30210
  const identity = identities.get(item.id);
29469
- if (identity && accepted.has(identity.moduleId))
30211
+ if (identity && accepted.has(identity.moduleId)) {
29470
30212
  item.independent ? independent += 1 : mapped += 1;
30213
+ committedIds.push(item.id);
30214
+ }
29471
30215
  }
29472
- return { mapped, independent };
30216
+ return { mapped, independent, committedIds };
29473
30217
  }
29474
30218
  const now = Date.now();
29475
30219
  runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
29476
30220
  for (const item of planned) {
29477
30221
  recordMemoryMapping(args.db, item.id, item.files, now, item.mappingOrigin);
29478
30222
  item.independent ? independent += 1 : mapped += 1;
30223
+ committedIds.push(item.id);
29479
30224
  }
29480
30225
  });
29481
- return { mapped, independent };
30226
+ return { mapped, independent, committedIds };
29482
30227
  }
29483
30228
  function recordInvocation2(args, startedAt, params) {
29484
30229
  if (!args.parentSessionId)
@@ -29746,32 +30491,41 @@ async function promotePrimers(args) {
29746
30491
  // src/features/magic-context/dreamer/primer-seed.ts
29747
30492
  var PRIMER_SEED_CAP_TOKENS = 4000;
29748
30493
  function renderUserAndToolOrientation(sessionId, startOrdinal, endOrdinal, capTokens) {
30494
+ const renderer = orientationRenderer(capTokens);
30495
+ visitRawSessionMessages2(sessionId, startOrdinal, endOrdinal, renderer.visit, {
30496
+ summary: true
30497
+ });
30498
+ return renderer.result();
30499
+ }
30500
+ function orientationRenderer(capTokens) {
29749
30501
  const lines = [];
29750
30502
  let tokens = 0;
29751
30503
  let sawMessage = false;
29752
- visitRawSessionMessages2(sessionId, startOrdinal, endOrdinal, (msg) => {
29753
- sawMessage = true;
29754
- const out = [];
29755
- if (msg.role === "user" && hasMeaningfulUserText2(msg.parts)) {
29756
- const text = extractTexts2(msg.parts).map((t) => cleanUserText2(t)).map(normalizeText).filter((t) => t.length > 0).join(" / ");
29757
- if (text)
29758
- out.push(`U: ${text}`);
29759
- }
29760
- for (const tc of extractToolCallSummaries(msg.parts))
29761
- out.push(tc);
29762
- for (const line of out) {
29763
- const lineTokens = estimateTokens(line);
29764
- if (tokens + lineTokens > capTokens && lines.length > 0) {
29765
- lines.push("… (orientation truncated; investigate the current source directly)");
29766
- return false;
30504
+ return {
30505
+ visit: (msg) => {
30506
+ sawMessage = true;
30507
+ const out = [];
30508
+ if (msg.role === "user" && hasMeaningfulUserText2(msg.parts)) {
30509
+ const text = extractTexts2(msg.parts).map((t) => cleanUserText2(t)).map(normalizeText).filter((t) => t.length > 0).join(" / ");
30510
+ if (text)
30511
+ out.push(`U: ${text}`);
30512
+ }
30513
+ for (const tc of extractToolCallSummaries(msg.parts))
30514
+ out.push(tc);
30515
+ for (const line of out) {
30516
+ const lineTokens = estimateTokens(line);
30517
+ if (tokens + lineTokens > capTokens && lines.length > 0) {
30518
+ lines.push("… (orientation truncated; investigate the current source directly)");
30519
+ return false;
30520
+ }
30521
+ lines.push(line);
30522
+ tokens += lineTokens;
29767
30523
  }
29768
- lines.push(line);
29769
- tokens += lineTokens;
29770
- }
29771
- return true;
29772
- }, { summary: true });
29773
- return sawMessage ? lines.join(`
29774
- `) : null;
30524
+ return true;
30525
+ },
30526
+ result: () => sawMessage ? lines.join(`
30527
+ `) : null
30528
+ };
29775
30529
  }
29776
30530
  function selectPrimerOriginCandidate(db, primer) {
29777
30531
  return getPrimerCandidatesByIds(db, primer.sourceCandidateIds).filter((candidate) => candidate.projectPath === primer.projectPath).sort((a, b) => b.sourceMessageTime - a.sourceMessageTime || b.id - a.id)[0];
@@ -29805,16 +30559,37 @@ function closedBookOriginP1(db, sessionId, originStartMessage) {
29805
30559
  return { orientation, sessionId };
29806
30560
  }
29807
30561
  function buildPrimerSeed(db, primer) {
30562
+ return buildPrimerSeedUsing(db, selectPrimerOriginCandidate(db, primer), renderUserAndToolOrientation);
30563
+ }
30564
+ async function buildPrimerSeedAsync(db, primer) {
29808
30565
  const mostRecent = selectPrimerOriginCandidate(db, primer);
30566
+ let orientation = null;
30567
+ if (mostRecent && typeof mostRecent.sourceCompartmentStart === "number" && typeof mostRecent.sourceCompartmentEnd === "number") {
30568
+ try {
30569
+ const renderer = orientationRenderer(PRIMER_SEED_CAP_TOKENS);
30570
+ await visitRawSessionMessagesAsync2(mostRecent.sessionId, mostRecent.sourceCompartmentStart, mostRecent.sourceCompartmentEnd, renderer.visit, { summary: true });
30571
+ orientation = renderer.result();
30572
+ } catch {
30573
+ orientation = null;
30574
+ }
30575
+ }
30576
+ return buildPrimerSeedUsing(db, mostRecent, () => orientation);
30577
+ }
30578
+ function buildPrimerSeedUsing(db, mostRecent, render) {
29809
30579
  if (!mostRecent || typeof mostRecent.sourceCompartmentStart !== "number" || typeof mostRecent.sourceCompartmentEnd !== "number") {
29810
- return { kind: "closed-book", orientation: "", prePost: "", sessionId: null };
30580
+ return {
30581
+ kind: "closed-book",
30582
+ orientation: "",
30583
+ prePost: "",
30584
+ sessionId: null
30585
+ };
29811
30586
  }
29812
30587
  const sessionId = mostRecent.sessionId;
29813
30588
  const start = mostRecent.sourceCompartmentStart;
29814
30589
  const end = mostRecent.sourceCompartmentEnd;
29815
30590
  let orientation = null;
29816
30591
  try {
29817
- orientation = renderUserAndToolOrientation(sessionId, start, end, PRIMER_SEED_CAP_TOKENS);
30592
+ orientation = render(sessionId, start, end, PRIMER_SEED_CAP_TOKENS);
29818
30593
  } catch {
29819
30594
  orientation = null;
29820
30595
  }
@@ -29945,14 +30720,14 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
29945
30720
  provider = null;
29946
30721
  }
29947
30722
  }
29948
- const seed = withRawSessionMessageCache2(() => {
30723
+ const seed = await (async () => {
29949
30724
  const unregister = provider && originSessionId ? setRawMessageProvider2(originSessionId, provider) : null;
29950
30725
  try {
29951
- return buildPrimerSeed(args.db, primer);
30726
+ return provider?.iterateMessageRangeAsync ? await buildPrimerSeedAsync(args.db, primer) : withRawSessionMessageCache2(() => buildPrimerSeed(args.db, primer));
29952
30727
  } finally {
29953
30728
  unregister?.();
29954
30729
  }
29955
- });
30730
+ })();
29956
30731
  let agentSessionId = null;
29957
30732
  let promptSettled = false;
29958
30733
  const startedAt = Date.now();
@@ -29968,7 +30743,10 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
29968
30743
  prompt,
29969
30744
  title: "magic-context-dream-refresh-primers",
29970
30745
  callContext: "dreamer:refresh-primers",
29971
- metadata: { tokenBudget: args.tokenBudget, onBudgetUpdate: args.onBudgetUpdate },
30746
+ metadata: {
30747
+ tokenBudget: args.tokenBudget,
30748
+ onBudgetUpdate: args.onBudgetUpdate
30749
+ },
29972
30750
  model: args.model,
29973
30751
  fallbackModels: args.fallbackModels,
29974
30752
  language: args.language,
@@ -30034,7 +30812,10 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
30034
30812
  validateOutput: (messages) => parseAnswer(messages, primer.answer)
30035
30813
  });
30036
30814
  promptSettled = true;
30037
- recordInvocation3(args, startedAt, { status: "completed", messages: run.output });
30815
+ recordInvocation3(args, startedAt, {
30816
+ status: "completed",
30817
+ messages: run.output
30818
+ });
30038
30819
  const answer = run.validated.trim();
30039
30820
  if (!answer)
30040
30821
  return false;
@@ -30049,7 +30830,10 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
30049
30830
  } catch (error) {
30050
30831
  const desc = describeError(error);
30051
30832
  log2(`[dreamer] refresh-primers failed (primer #${primer.id}): ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
30052
- recordInvocation3(args, startedAt, { status: failedInvocationStatus(error), error });
30833
+ recordInvocation3(args, startedAt, {
30834
+ status: failedInvocationStatus(error),
30835
+ error
30836
+ });
30053
30837
  throw error;
30054
30838
  } finally {
30055
30839
  if (agentSessionId && args.client)
@@ -30687,12 +31471,12 @@ function insertDreamRun(db, run) {
30687
31471
  }
30688
31472
 
30689
31473
  // src/features/magic-context/dreamer/verify.ts
30690
- import { createHash as createHash12 } from "node:crypto";
31474
+ import { createHash as createHash13 } from "node:crypto";
30691
31475
 
30692
31476
  // src/features/magic-context/dreamer/verify-diff.ts
30693
- import { execFile as execFile2 } from "node:child_process";
30694
- import { promisify as promisify2 } from "node:util";
30695
- var exec = promisify2(execFile2);
31477
+ import { execFile as execFile3 } from "node:child_process";
31478
+ import { promisify as promisify3 } from "node:util";
31479
+ var exec = promisify3(execFile3);
30696
31480
  var VERIFY_DIFF_BUDGET_TOKENS = 12000;
30697
31481
  var MAX_DIFF_BYTES = 4 * 1024 * 1024;
30698
31482
  async function git2(root, args) {
@@ -31431,7 +32215,7 @@ async function applyParsedVerifyManifest(args, batch, parsed, headAtPrompt, budg
31431
32215
  name: "memory.set_verification",
31432
32216
  arguments: {
31433
32217
  memory_project: args.projectIdentity,
31434
- command_id: `${args.moduleRoute.moduleCommandId}:${createHash12("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
32218
+ command_id: `${args.moduleRoute.moduleCommandId}:${createHash13("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
31435
32219
  rows
31436
32220
  }
31437
32221
  }
@@ -32237,7 +33021,7 @@ function parseFrictionGateVerdict(verdict) {
32237
33021
  }
32238
33022
  function computeRetrospectiveWindowKey(flagged) {
32239
33023
  const anchors = flagged.map((message) => `${message.sessionId}:${message.ts}`).sort().join("|");
32240
- return createHash13("sha256").update(anchors).digest("hex").slice(0, 32);
33024
+ return createHash14("sha256").update(anchors).digest("hex").slice(0, 32);
32241
33025
  }
32242
33026
  function renderFrictionWindow(messages, flaggedOrdinals, radius = 2) {
32243
33027
  const flagged = new Set(flaggedOrdinals);
@@ -33625,7 +34409,7 @@ async function startDreamScheduleTimer(args) {
33625
34409
  startupTickTimer = null;
33626
34410
  runTick("startup");
33627
34411
  });
33628
- const timer = setInterval(() => runTick("interval"), DREAM_TIMER_INTERVAL_MS);
34412
+ const timer = inRootAsyncContext2(() => setInterval(() => runTick("interval"), DREAM_TIMER_INTERVAL_MS));
33629
34413
  if (typeof timer === "object" && "unref" in timer) {
33630
34414
  timer.unref();
33631
34415
  }
@@ -33921,7 +34705,7 @@ async function runCompiledSmartNoteSweep(reg, db) {
33921
34705
  }
33922
34706
  }
33923
34707
  function startGitSweepLeaseRenewal(db, projectIdentity, holderId) {
33924
- const timer = setInterval(() => {
34708
+ const timer = inRootAsyncContext2(() => setInterval(() => {
33925
34709
  try {
33926
34710
  if (!renewGitSweepLease(db, projectIdentity, holderId)) {
33927
34711
  log2(`[git-commits] sweep lease renewal failed for ${projectIdentity}`);
@@ -33929,7 +34713,7 @@ function startGitSweepLeaseRenewal(db, projectIdentity, holderId) {
33929
34713
  } catch (error) {
33930
34714
  log2(`[git-commits] sweep lease renewal errored for ${projectIdentity}: ${error instanceof Error ? error.message : String(error)}`);
33931
34715
  }
33932
- }, GIT_SWEEP_LEASE_RENEWAL_MS);
34716
+ }, GIT_SWEEP_LEASE_RENEWAL_MS));
33933
34717
  timer.unref?.();
33934
34718
  return () => clearInterval(timer);
33935
34719
  }
@@ -34191,9 +34975,9 @@ function hiddenTerminalError(event) {
34191
34975
  }
34192
34976
 
34193
34977
  // src/v2/hooks/lkg-system.ts
34194
- import { createHash as createHash14 } from "node:crypto";
34978
+ import { createHash as createHash15 } from "node:crypto";
34195
34979
  function identity(slot) {
34196
- return createHash14("sha256").update(JSON.stringify({
34980
+ return createHash15("sha256").update(JSON.stringify({
34197
34981
  capturedAt: slot.capturedAt,
34198
34982
  captureSequence: slot.captureSequence,
34199
34983
  rowVersion: slot.rowVersion,
@@ -34468,12 +35252,12 @@ function createRustRefusalRecovery(options) {
34468
35252
  watchers.delete(sessionId);
34469
35253
  };
34470
35254
  const schedule = (sessionId, watcher) => {
34471
- watcher.timer = setTimeout(() => void poll(sessionId, watcher), pollIntervalMs);
35255
+ watcher.timer = inRootAsyncContext2(() => setTimeout(() => void poll(sessionId, watcher), pollIntervalMs));
34472
35256
  };
34473
35257
  const probe = async (watcher, sessionId) => {
34474
35258
  const controller = new AbortController;
34475
35259
  const timeoutError = new Error("rust refusal recovery probe timed out");
34476
- const timer = setTimeout(() => controller.abort(timeoutError), probeTimeoutMs);
35260
+ const timer = inRootAsyncContext2(() => setTimeout(() => controller.abort(timeoutError), probeTimeoutMs));
34477
35261
  try {
34478
35262
  await Promise.race([
34479
35263
  options.moduleClient.call({
@@ -35155,6 +35939,14 @@ function createV2RawMessageReader(openReader) {
35155
35939
  reader.close();
35156
35940
  }
35157
35941
  },
35942
+ orderOf: (sessionID, messageID) => {
35943
+ const reader = openReader();
35944
+ try {
35945
+ return reader.sequenceForId(sessionID, messageID) ?? null;
35946
+ } finally {
35947
+ reader.close();
35948
+ }
35949
+ },
35158
35950
  ordinalMapForRange: (sessionID, fromOrdinal, toOrdinal) => {
35159
35951
  const reader = openReader();
35160
35952
  try {
@@ -35212,6 +36004,9 @@ function createV2RawMessageProvider(reader, sessionID) {
35212
36004
  readMessagePartsById: (messageID) => reader.findPartsById(sessionID, messageID),
35213
36005
  hasMessageById: (messageID) => reader.hasById(sessionID, messageID),
35214
36006
  readMessageOrdinalById: (messageID) => reader.ordinalOf(sessionID, messageID),
36007
+ ...reader.orderOf ? {
36008
+ readMessageOrderById: (messageID) => reader.orderOf?.(sessionID, messageID) ?? null
36009
+ } : {},
35215
36010
  readMessageIdOrdinalsForRange: (fromOrdinal, toOrdinal) => reader.ordinalMapForRange(sessionID, fromOrdinal, toOrdinal),
35216
36011
  readMessageOrdinalPage: (after, limit) => reader.readOrdinalPage(sessionID, after, limit),
35217
36012
  getMessageCount: () => reader.getCount(sessionID),
@@ -47010,7 +47805,7 @@ function resolveCtxExpandMode(args, domain) {
47010
47805
  }
47011
47806
 
47012
47807
  // src/tools/ctx-expand/render.ts
47013
- import { createHash as createHash15 } from "node:crypto";
47808
+ import { createHash as createHash16 } from "node:crypto";
47014
47809
  function isRecord6(value) {
47015
47810
  return value !== null && typeof value === "object" && !Array.isArray(value);
47016
47811
  }
@@ -47234,11 +48029,61 @@ function renderItemByTag(db, sessionId, number, textIndexDomain = "part") {
47234
48029
  const index = scoped ? Number(scoped[2]) : 0;
47235
48030
  const piText = message.parts.filter((part) => isRecord6(part) && part.type === "text");
47236
48031
  const part = message.parts[index];
47237
- const matching = derived ? piText.filter((part) => isRecord6(part) && typeof part.text === "string" && createHash15("sha256").update(part.text).digest("hex") === derived[3]) : [];
48032
+ const matching = derived ? piText.filter((part) => isRecord6(part) && typeof part.text === "string" && createHash16("sha256").update(part.text).digest("hex") === derived[3]) : [];
47238
48033
  const selected = derived ? matching[Number(derived[4])] : textIndexDomain === "text" ? piText[index] : part;
47239
48034
  return selected ? renderPartFull(selected) ?? "" : `Tag ${number}'s original text part is no longer in stored history.`;
47240
48035
  }
47241
48036
 
48037
+ // src/tools/ctx-expand/search-archive.ts
48038
+ function renderSearchArchive(db, sessionId, start, end, tokenBudget, archiveOnly = false) {
48039
+ return withMessageFtsSessionFilter(db, sessionId, (sessionFirst) => {
48040
+ let rawIds;
48041
+ const rows = db.prepare(sessionFirst ? `SELECT f.message_ordinal AS ordinal, f.message_id AS id, f.role, f.content
48042
+ FROM message_fts_rowid_map AS m
48043
+ JOIN message_history_fts AS f ON f.rowid = m.fts_rowid
48044
+ WHERE m.session_id = ?1 AND m.message_ordinal BETWEEN ?2 AND ?3
48045
+ AND f.session_id = ?1 AND f.message_ordinal BETWEEN ?2 AND ?3
48046
+ ORDER BY m.message_ordinal` : `SELECT message_ordinal AS ordinal, message_id AS id, role, content
48047
+ FROM message_history_fts
48048
+ WHERE session_id = ?1 AND message_ordinal BETWEEN ?2 AND ?3
48049
+ ORDER BY CAST(message_ordinal AS INTEGER)`);
48050
+ const blocks = [];
48051
+ let tokens = 0;
48052
+ let lastOrdinal = start - 1;
48053
+ let truncated = false;
48054
+ for (const row of rows.iterate(sessionId, start, end)) {
48055
+ if (!row.content)
48056
+ continue;
48057
+ if (!archiveOnly) {
48058
+ rawIds ??= readRawSessionMessageIdOrdinalsForRange2(sessionId, start, end);
48059
+ if (rawIds.get(row.id) === row.ordinal)
48060
+ continue;
48061
+ }
48062
+ const block = `[${row.ordinal}] ${row.role === "user" ? "U" : "A"}: ${row.content}`;
48063
+ const cost = estimateTokens(block);
48064
+ if (blocks.length > 0 && tokens + cost > tokenBudget) {
48065
+ truncated = true;
48066
+ break;
48067
+ }
48068
+ blocks.push(block);
48069
+ tokens += cost;
48070
+ lastOrdinal = row.ordinal;
48071
+ }
48072
+ if (blocks.length === 0)
48073
+ return null;
48074
+ const text = [
48075
+ "From the search archive: indexed text only; no surrounding messages or tool output.",
48076
+ "",
48077
+ ...blocks
48078
+ ];
48079
+ if (truncated) {
48080
+ text.push("", `Truncated at message ${lastOrdinal} (budget: ~${tokenBudget} tokens). Call ctx_expand(start=${lastOrdinal + 1}, end=${end}) for more archived text.`);
48081
+ }
48082
+ return text.join(`
48083
+ `);
48084
+ });
48085
+ }
48086
+
47242
48087
  // src/tools/ctx-expand/tools.ts
47243
48088
  var ctxExpandArgsShape = {
47244
48089
  tag: tool.schema.union([tool.schema.number(), tool.schema.string()]).optional().describe("Tag number from a §N§ tag or a [dropped §N§] placeholder, not a message ordinal. Returns that one item in full. Use alone."),
@@ -47272,7 +48117,7 @@ function createCtxExpandTool(deps) {
47272
48117
  return renderItemByTag(deps.db, sessionId, mode.tag);
47273
48118
  }
47274
48119
  if (mode.kind === "message") {
47275
- return renderMessageByOrdinal(sessionId, mode.message);
48120
+ return renderSearchArchive(deps.db, sessionId, mode.message, mode.message, CTX_EXPAND_TOKEN_BUDGET) ?? renderMessageByOrdinal(sessionId, mode.message);
47276
48121
  }
47277
48122
  const { start, end, verbose } = mode;
47278
48123
  const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
@@ -47280,6 +48125,9 @@ function createCtxExpandTool(deps) {
47280
48125
  return `Range ${start}-${end} is entirely within the live tail (after the last compacted message ${lastCompartmentEnd}); those messages are already visible in context.`;
47281
48126
  }
47282
48127
  const effectiveEnd = lastCompartmentEnd >= 0 ? Math.min(end, lastCompartmentEnd) : end;
48128
+ const archived = renderSearchArchive(deps.db, sessionId, start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET);
48129
+ if (archived)
48130
+ return archived;
47283
48131
  if (verbose) {
47284
48132
  const v = renderVerboseRange(sessionId, start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET, deps.expandTools);
47285
48133
  if (!v.text) {
@@ -48106,9 +48954,9 @@ function isMissingError(error) {
48106
48954
  }
48107
48955
 
48108
48956
  // ../retina-local-fs/src/provider.ts
48109
- import { execFile as execFile3 } from "node:child_process";
48110
- import { promisify as promisify3 } from "node:util";
48111
- var execFileAsync2 = promisify3(execFile3);
48957
+ import { execFile as execFile4 } from "node:child_process";
48958
+ import { promisify as promisify4 } from "node:util";
48959
+ var execFileAsync3 = promisify4(execFile4);
48112
48960
  function parseSemver(value) {
48113
48961
  const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value);
48114
48962
  if (!match) {
@@ -48757,7 +49605,7 @@ function formatCtxReduceReply(stampedCount, selfStampCount = 0) {
48757
49605
  return parts.join(" ");
48758
49606
  }
48759
49607
  // src/tools/ctx-reduce/tools.ts
48760
- import { createHash as createHash16 } from "node:crypto";
49608
+ import { createHash as createHash17 } from "node:crypto";
48761
49609
 
48762
49610
  // src/features/magic-context/range-parser.ts
48763
49611
  function parseRangeString(input) {
@@ -48820,11 +49668,11 @@ function createCtxReduceTool(deps) {
48820
49668
  const stableId = `oc-${sessionId}-${callId}`;
48821
49669
  if (Buffer.byteLength(stableId) <= 128)
48822
49670
  return stableId;
48823
- return `oc-${createHash16("sha256").update(stableId).digest("hex")}`;
49671
+ return `oc-${createHash17("sha256").update(stableId).digest("hex")}`;
48824
49672
  }
48825
49673
  fallbackCommandSequence += 1;
48826
49674
  const monotonicId = `oc-${sessionId}-${fallbackCommandSequence}`;
48827
- return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash16("sha256").update(monotonicId).digest("hex")}`;
49675
+ return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash17("sha256").update(monotonicId).digest("hex")}`;
48828
49676
  };
48829
49677
  return tool({
48830
49678
  description: CTX_REDUCE_DESCRIPTION,
@@ -50540,6 +51388,13 @@ ${baseline}
50540
51388
  hiddenCompletionExecutor: storageOpenedAtBoot ? hiddenCompletionExecutor : lateHiddenExecutor,
50541
51389
  compactionMarkerStrategy: v2CompactionMarkerStrategy,
50542
51390
  prepareHistorySession,
51391
+ readSessionDirectory: async (sessionID) => {
51392
+ try {
51393
+ return (await context.session.get({ sessionID })).location?.directory ?? null;
51394
+ } catch {
51395
+ return null;
51396
+ }
51397
+ },
50543
51398
  storageDir
50544
51399
  });
50545
51400
  rpcServer.handle("dream", async (params) => {
@@ -50607,11 +51462,11 @@ ${baseline}
50607
51462
  directory,
50608
51463
  compactionEnabled: !compactionOff
50609
51464
  });
50610
- setTimeout(() => {
51465
+ inRootAsyncContext2(() => setTimeout(() => {
50611
51466
  if (rpcStopped)
50612
51467
  return;
50613
51468
  rpcServer.start().catch((error) => log2("[magic-context] v2 RPC server failed to start", error));
50614
- }, 0);
51469
+ }, 0));
50615
51470
  return {
50616
51471
  async dispose() {
50617
51472
  rpcStopped = true;