@cortexkit/opencode-magic-context 0.44.3 → 0.45.0

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 (701) hide show
  1. package/dist/agents/hidden-agent-registrations.d.ts +3 -2
  2. package/dist/agents/hidden-agent-registrations.d.ts.map +1 -1
  3. package/dist/agents/magic-context-prompt.d.ts +1 -0
  4. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  5. package/dist/agents/permissions.d.ts +8 -28
  6. package/dist/agents/permissions.d.ts.map +1 -1
  7. package/dist/{announcement-n8hs7kjw.js → announcement-f75t58v9.js} +4 -2
  8. package/dist/config/index.d.ts.map +1 -1
  9. package/dist/config/project-security.d.ts +48 -0
  10. package/dist/config/project-security.d.ts.map +1 -1
  11. package/dist/config/raw-loader.d.ts.map +1 -1
  12. package/dist/config/schema/magic-context.d.ts +10 -7
  13. package/dist/config/schema/magic-context.d.ts.map +1 -1
  14. package/dist/{conflict-warning-hook-hmpzxep6.js → conflict-warning-hook-5yrz2r24.js} +10 -6
  15. package/dist/{derive-budgets-vjmvh6pz.js → derive-budgets-a63zsm5c.js} +4 -4
  16. package/dist/embedding-worker.js +49 -0
  17. package/dist/emscripten-module-0g8f45e6.js +602 -0
  18. package/dist/emscripten-module-0pekdjxz.js +1532 -0
  19. package/dist/emscripten-module-e67xwsp3.js +503 -0
  20. package/dist/emscripten-module-pj1vyb44.js +4559 -0
  21. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +23 -3
  22. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  23. package/dist/features/magic-context/compartment-embedding.d.ts.map +1 -1
  24. package/dist/features/magic-context/compartment-storage.d.ts +14 -3
  25. package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
  26. package/dist/features/magic-context/context-store-uuid.d.ts +7 -0
  27. package/dist/features/magic-context/context-store-uuid.d.ts.map +1 -0
  28. package/dist/features/magic-context/dreamer/classify.d.ts +1 -3
  29. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  30. package/dist/features/magic-context/dreamer/cron.d.ts +5 -4
  31. package/dist/features/magic-context/dreamer/cron.d.ts.map +1 -1
  32. package/dist/features/magic-context/dreamer/docs-proposals.d.ts.map +1 -1
  33. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  34. package/dist/features/magic-context/dreamer/expire-memories.d.ts.map +1 -1
  35. package/dist/features/magic-context/dreamer/idle-schedule-prune.d.ts +24 -0
  36. package/dist/features/magic-context/dreamer/idle-schedule-prune.d.ts.map +1 -0
  37. package/dist/features/magic-context/dreamer/manual-summary.d.ts.map +1 -1
  38. package/dist/features/magic-context/dreamer/map-memories.d.ts +5 -5
  39. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  40. package/dist/features/magic-context/dreamer/module-apply.d.ts +4 -25
  41. package/dist/features/magic-context/dreamer/module-apply.d.ts.map +1 -1
  42. package/dist/features/magic-context/dreamer/retrospective-learnings.d.ts.map +1 -1
  43. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +5 -1
  44. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  45. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts +12 -5
  46. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts.map +1 -1
  47. package/dist/features/magic-context/dreamer/task-executor.d.ts +6 -0
  48. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  49. package/dist/features/magic-context/dreamer/task-gates.d.ts +34 -0
  50. package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
  51. package/dist/features/magic-context/dreamer/task-prompts.d.ts +1 -1
  52. package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
  53. package/dist/features/magic-context/dreamer/task-registry.d.ts +7 -5
  54. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  55. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +10 -3
  56. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  57. package/dist/features/magic-context/dreamer/token-budget.d.ts +3 -0
  58. package/dist/features/magic-context/dreamer/token-budget.d.ts.map +1 -1
  59. package/dist/features/magic-context/dreamer/verify.d.ts +2 -2
  60. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  61. package/dist/features/magic-context/git-commits/git-log-reader.d.ts +11 -2
  62. package/dist/features/magic-context/git-commits/git-log-reader.d.ts.map +1 -1
  63. package/dist/features/magic-context/git-commits/indexer.d.ts.map +1 -1
  64. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  65. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts +2 -0
  66. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
  67. package/dist/features/magic-context/legacy-authority-fixture.test-support.d.ts +6 -0
  68. package/dist/features/magic-context/legacy-authority-fixture.test-support.d.ts.map +1 -0
  69. package/dist/features/magic-context/lkg-prefix-chunks.d.ts +53 -0
  70. package/dist/features/magic-context/lkg-prefix-chunks.d.ts.map +1 -0
  71. package/dist/features/magic-context/memory/embedding-backfill.d.ts.map +1 -1
  72. package/dist/features/magic-context/memory/embedding-local.d.ts +8 -0
  73. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  74. package/dist/features/magic-context/memory/embedding-openai.d.ts +1 -0
  75. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  76. package/dist/features/magic-context/memory/embedding-worker-client.d.ts +27 -0
  77. package/dist/features/magic-context/memory/embedding-worker-client.d.ts.map +1 -0
  78. package/dist/features/magic-context/memory/embedding-worker.d.ts +2 -0
  79. package/dist/features/magic-context/memory/embedding-worker.d.ts.map +1 -0
  80. package/dist/features/magic-context/memory/embedding-worker.fixture.d.ts +2 -0
  81. package/dist/features/magic-context/memory/embedding-worker.fixture.d.ts.map +1 -0
  82. package/dist/features/magic-context/memory/memory-selection.d.ts.map +1 -1
  83. package/dist/features/magic-context/memory/project-identity-cache.d.ts +4 -3
  84. package/dist/features/magic-context/memory/project-identity-cache.d.ts.map +1 -1
  85. package/dist/features/magic-context/memory/project-identity.d.ts +5 -4
  86. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  87. package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
  88. package/dist/features/magic-context/memory/visibility.d.ts +1 -1
  89. package/dist/features/magic-context/memory/visibility.d.ts.map +1 -1
  90. package/dist/features/magic-context/message-fts-rowid-map.d.ts +14 -1
  91. package/dist/features/magic-context/message-fts-rowid-map.d.ts.map +1 -1
  92. package/dist/features/magic-context/message-fts-session-filter.d.ts +14 -0
  93. package/dist/features/magic-context/message-fts-session-filter.d.ts.map +1 -0
  94. package/dist/features/magic-context/message-index.d.ts +1 -7
  95. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  96. package/dist/features/magic-context/message-time-backfill.d.ts.map +1 -1
  97. package/dist/features/magic-context/migration-v94-write-split.d.ts +62 -0
  98. package/dist/features/magic-context/migration-v94-write-split.d.ts.map +1 -0
  99. package/dist/features/magic-context/migration-worker-client.d.ts +23 -0
  100. package/dist/features/magic-context/migration-worker-client.d.ts.map +1 -0
  101. package/dist/features/magic-context/migration-worker-protocol.d.ts +30 -0
  102. package/dist/features/magic-context/migration-worker-protocol.d.ts.map +1 -0
  103. package/dist/features/magic-context/migration-worker.d.ts +2 -0
  104. package/dist/features/magic-context/migration-worker.d.ts.map +1 -0
  105. package/dist/features/magic-context/migrations.d.ts +7 -0
  106. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  107. package/dist/features/magic-context/mural/render-mural.d.ts +24 -2
  108. package/dist/features/magic-context/mural/render-mural.d.ts.map +1 -1
  109. package/dist/features/magic-context/mural/render-trigger.d.ts +1 -1
  110. package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
  111. package/dist/features/magic-context/overflow-detection.d.ts +18 -7
  112. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  113. package/dist/features/magic-context/project-embedding-registry.d.ts +2 -0
  114. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  115. package/dist/features/magic-context/range-parser.d.ts +2 -3
  116. package/dist/features/magic-context/range-parser.d.ts.map +1 -1
  117. package/dist/features/magic-context/resolve-subagent-fallback.d.ts +2 -0
  118. package/dist/features/magic-context/resolve-subagent-fallback.d.ts.map +1 -1
  119. package/dist/features/magic-context/scheduler.d.ts +2 -0
  120. package/dist/features/magic-context/scheduler.d.ts.map +1 -1
  121. package/dist/features/magic-context/search.d.ts +7 -0
  122. package/dist/features/magic-context/search.d.ts.map +1 -1
  123. package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
  124. package/dist/features/magic-context/session-project-storage.d.ts +10 -1
  125. package/dist/features/magic-context/session-project-storage.d.ts.map +1 -1
  126. package/dist/features/magic-context/smart-notes/compiler-prompt.d.ts +1 -1
  127. package/dist/features/magic-context/smart-notes/compiler-prompt.d.ts.map +1 -1
  128. package/dist/features/magic-context/smart-notes/compiler.d.ts +4 -0
  129. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  130. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
  131. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +2 -0
  132. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
  133. package/dist/features/magic-context/smart-notes/ssrf-guard.d.ts +10 -8
  134. package/dist/features/magic-context/smart-notes/ssrf-guard.d.ts.map +1 -1
  135. package/dist/features/magic-context/smart-notes/storage.d.ts +2 -2
  136. package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
  137. package/dist/features/magic-context/smart-notes/types.d.ts +7 -2
  138. package/dist/features/magic-context/smart-notes/types.d.ts.map +1 -1
  139. package/dist/features/magic-context/storage-caveman-rules.d.ts +21 -0
  140. package/dist/features/magic-context/storage-caveman-rules.d.ts.map +1 -0
  141. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  142. package/dist/features/magic-context/storage-compartment-history-version.d.ts +4 -0
  143. package/dist/features/magic-context/storage-compartment-history-version.d.ts.map +1 -0
  144. package/dist/features/magic-context/storage-db.d.ts +68 -3
  145. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  146. package/dist/features/magic-context/storage-identity-merge.d.ts +6 -0
  147. package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
  148. package/dist/features/magic-context/storage-meta-persisted.d.ts +15 -0
  149. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  150. package/dist/features/magic-context/storage-meta-session.d.ts +1 -1
  151. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  152. package/dist/features/magic-context/storage-meta-shared.d.ts +1 -1
  153. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  154. package/dist/features/magic-context/storage-notes.d.ts +2 -2
  155. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  156. package/dist/features/magic-context/storage-reasoning-removal.d.ts +30 -0
  157. package/dist/features/magic-context/storage-reasoning-removal.d.ts.map +1 -0
  158. package/dist/features/magic-context/storage-replay-document.d.ts +42 -5
  159. package/dist/features/magic-context/storage-replay-document.d.ts.map +1 -1
  160. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  161. package/dist/features/magic-context/storage-tags.d.ts +7 -1
  162. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  163. package/dist/features/magic-context/storage.d.ts +1 -1
  164. package/dist/features/magic-context/storage.d.ts.map +1 -1
  165. package/dist/features/magic-context/store-generation-rebase.d.ts.map +1 -1
  166. package/dist/features/magic-context/tag-input.d.ts +4 -0
  167. package/dist/features/magic-context/tag-input.d.ts.map +1 -0
  168. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  169. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  170. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  171. package/dist/features/magic-context/v22-deferred-backfill.d.ts.map +1 -1
  172. package/dist/ffi-3cx1cxpk.js +78 -0
  173. package/dist/ffi-7bqqe4cd.js +91 -0
  174. package/dist/ffi-7e6gryj5.js +91 -0
  175. package/dist/ffi-bpvkebwr.js +78 -0
  176. package/dist/hooks/magic-context/apply-operations.d.ts +9 -1
  177. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  178. package/dist/hooks/magic-context/auto-search-deadline.d.ts +10 -0
  179. package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -0
  180. package/dist/hooks/magic-context/auto-search-hint.d.ts +3 -0
  181. package/dist/hooks/magic-context/auto-search-hint.d.ts.map +1 -1
  182. package/dist/hooks/magic-context/auto-search-runner.d.ts +3 -0
  183. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  184. package/dist/hooks/magic-context/caveman-cleanup.d.ts +8 -1
  185. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
  186. package/dist/hooks/magic-context/caveman.d.ts +56 -1
  187. package/dist/hooks/magic-context/caveman.d.ts.map +1 -1
  188. package/dist/hooks/magic-context/child-session-spawn.d.ts +2 -0
  189. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
  190. package/dist/hooks/magic-context/command-handler.d.ts +1 -1
  191. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  192. package/dist/hooks/magic-context/compaction-marker-manager.d.ts +1 -1
  193. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  194. package/dist/hooks/magic-context/compartment-parser.d.ts +3 -3
  195. package/dist/hooks/magic-context/compartment-parser.d.ts.map +1 -1
  196. package/dist/hooks/magic-context/compartment-render-epoch.d.ts +12 -1
  197. package/dist/hooks/magic-context/compartment-render-epoch.d.ts.map +1 -1
  198. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  199. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +0 -1
  200. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  201. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  202. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  203. package/dist/hooks/magic-context/compartment-runner-types.d.ts +3 -0
  204. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  205. package/dist/hooks/magic-context/compartment-runner-validation.d.ts +6 -0
  206. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  207. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  208. package/dist/hooks/magic-context/degraded-pass-refusal.d.ts +35 -0
  209. package/dist/hooks/magic-context/degraded-pass-refusal.d.ts.map +1 -0
  210. package/dist/hooks/magic-context/derive-budgets.d.ts.map +1 -1
  211. package/dist/hooks/magic-context/drop-stale-reduce-calls.d.ts.map +1 -1
  212. package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -1
  213. package/dist/hooks/magic-context/embed-history-runner.d.ts.map +1 -1
  214. package/dist/hooks/magic-context/emergency-drop.d.ts +15 -0
  215. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  216. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  217. package/dist/hooks/magic-context/event-resolvers.d.ts +7 -0
  218. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  219. package/dist/hooks/magic-context/execute-status.d.ts +1 -0
  220. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  221. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +17 -0
  222. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  223. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +2 -0
  224. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  225. package/dist/hooks/magic-context/historian-host-runner.d.ts +5 -0
  226. package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
  227. package/dist/hooks/magic-context/historian-prompt-fit.d.ts +116 -0
  228. package/dist/hooks/magic-context/historian-prompt-fit.d.ts.map +1 -0
  229. package/dist/hooks/magic-context/historian-prompt.generated.d.ts +1 -1
  230. package/dist/hooks/magic-context/historian-prompt.generated.d.ts.map +1 -1
  231. package/dist/hooks/magic-context/history-boundary-repair.d.ts +44 -0
  232. package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -0
  233. package/dist/hooks/magic-context/hook.d.ts +4 -0
  234. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  235. package/dist/hooks/magic-context/inject-compartments.d.ts +13 -0
  236. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  237. package/dist/hooks/magic-context/lkg-persist.d.ts +12 -0
  238. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  239. package/dist/hooks/magic-context/lkg-replay-fit.d.ts +104 -0
  240. package/dist/hooks/magic-context/lkg-replay-fit.d.ts.map +1 -0
  241. package/dist/hooks/magic-context/lkg-replay.d.ts +64 -0
  242. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  243. package/dist/hooks/magic-context/module-client.d.ts.map +1 -1
  244. package/dist/hooks/magic-context/module-state-sync-timing.d.ts +1 -1
  245. package/dist/hooks/magic-context/module-state-sync-timing.d.ts.map +1 -1
  246. package/dist/hooks/magic-context/module-state-sync.d.ts +6 -68
  247. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  248. package/dist/hooks/magic-context/module-tool-backends.d.ts +1 -34
  249. package/dist/hooks/magic-context/module-tool-backends.d.ts.map +1 -1
  250. package/dist/hooks/magic-context/module-transport.d.ts +1 -55
  251. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  252. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  253. package/dist/hooks/magic-context/note-nudger.d.ts +2 -0
  254. package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
  255. package/dist/hooks/magic-context/pass-outcome.d.ts +59 -2
  256. package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
  257. package/dist/hooks/magic-context/producer-window-guard.d.ts +6 -0
  258. package/dist/hooks/magic-context/producer-window-guard.d.ts.map +1 -1
  259. package/dist/hooks/magic-context/read-session-chunk.d.ts +17 -4
  260. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  261. package/dist/hooks/magic-context/read-session-formatting.d.ts +11 -0
  262. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  263. package/dist/hooks/magic-context/read-session-raw.d.ts +2 -2
  264. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  265. package/dist/hooks/magic-context/reasoning-removal.d.ts +60 -0
  266. package/dist/hooks/magic-context/reasoning-removal.d.ts.map +1 -0
  267. package/dist/hooks/magic-context/recomp-orchestrator.d.ts +1 -0
  268. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  269. package/dist/hooks/magic-context/reference-retrieval.d.ts +1 -1
  270. package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -1
  271. package/dist/hooks/magic-context/reply-pages.d.ts +3 -0
  272. package/dist/hooks/magic-context/reply-pages.d.ts.map +1 -0
  273. package/dist/hooks/magic-context/rust-lkg-freeze-registry.d.ts +62 -0
  274. package/dist/hooks/magic-context/rust-lkg-freeze-registry.d.ts.map +1 -0
  275. package/dist/hooks/magic-context/rust-mode-transform.d.ts +17 -85
  276. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  277. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  278. package/dist/hooks/magic-context/sentinel.d.ts +35 -0
  279. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  280. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts +28 -0
  281. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts.map +1 -0
  282. package/dist/hooks/magic-context/single-store-refusal.d.ts +14 -0
  283. package/dist/hooks/magic-context/single-store-refusal.d.ts.map +1 -0
  284. package/dist/hooks/magic-context/storage-busy-refusal.d.ts +7 -0
  285. package/dist/hooks/magic-context/storage-busy-refusal.d.ts.map +1 -1
  286. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  287. package/dist/hooks/magic-context/stripped-command.d.ts +1 -1
  288. package/dist/hooks/magic-context/stripped-command.d.ts.map +1 -1
  289. package/dist/hooks/magic-context/system-injection-stripper.d.ts +7 -0
  290. package/dist/hooks/magic-context/system-injection-stripper.d.ts.map +1 -1
  291. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  292. package/dist/hooks/magic-context/tag-content-primitives.d.ts.map +1 -1
  293. package/dist/hooks/magic-context/tag-id-fallback.d.ts.map +1 -1
  294. package/dist/hooks/magic-context/tag-messages.d.ts +18 -1
  295. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  296. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  297. package/dist/hooks/magic-context/tokenizer-calibration.d.ts +1 -1
  298. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  299. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +1 -0
  300. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  301. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +38 -4
  302. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  303. package/dist/hooks/magic-context/transform.d.ts +12 -39
  304. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  305. package/dist/hooks/magic-context/unmanaged-over-window.d.ts +36 -0
  306. package/dist/hooks/magic-context/unmanaged-over-window.d.ts.map +1 -0
  307. package/dist/hooks/magic-context/unresolved-history-boundary.d.ts +15 -0
  308. package/dist/hooks/magic-context/unresolved-history-boundary.d.ts.map +1 -0
  309. package/dist/hooks/magic-context/user-profile-render.d.ts +3 -0
  310. package/dist/hooks/magic-context/user-profile-render.d.ts.map +1 -0
  311. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  312. package/dist/{index-yhm60r53.js → index-16ny736w.js} +13622 -28584
  313. package/dist/{index-q5p1aqvv.js → index-2aq21j41.js} +1208 -429
  314. package/dist/{index-32b096cc.js → index-2ntg5sd4.js} +6 -2
  315. package/dist/index-4krbw8z9.js +6034 -0
  316. package/dist/{index-33q7s9y2.js → index-75zjgwga.js} +61 -85
  317. package/dist/{index-nf9sk8sh.js → index-8fgkmxmy.js} +28 -10
  318. package/dist/index-a4m2b1yv.js +530 -0
  319. package/dist/index-anq4nn6f.js +131 -0
  320. package/dist/index-avwt563y.js +62 -0
  321. package/dist/index-bmzf7zxv.js +445 -0
  322. package/dist/index-e44zzy84.js +10 -0
  323. package/dist/index-en1k8h8m.js +244 -0
  324. package/dist/{index-638hf49n.js → index-f85teqck.js} +15 -6
  325. package/dist/index-fr2z4qy8.js +7810 -0
  326. package/dist/{index-kwe03yde.js → index-fzbvakh0.js} +1 -1
  327. package/dist/{module-asyncify-2EFITU5U-rkqjhjxd.js → index-g20jdh0p.js} +114 -105
  328. package/dist/index-gd5qx1j9.js +398 -0
  329. package/dist/{index-3bygzk2d.js → index-hybnrwq0.js} +169 -4
  330. package/dist/{index-jqcbs2k1.js → index-mc22ayvf.js} +24 -5
  331. package/dist/{index-y5145x8k.js → index-n96ag4rk.js} +15 -1
  332. package/dist/index-q7yesyk9.js +9118 -0
  333. package/dist/index-remp7e2g.js +214 -0
  334. package/dist/{index-7k55qm8a.js → index-sfpzqvdz.js} +8 -8
  335. package/dist/{index-9y5p0d50.js → index-vvtfyw1z.js} +13 -76
  336. package/dist/index-w9jwmntv.js +202 -0
  337. package/dist/{index-kr5qehbd.js → index-x23gah8c.js} +1 -1
  338. package/dist/{index-jdxxq8cz.js → index-x8a7jmkh.js} +6 -1
  339. package/dist/{index-rdsaxnf2.js → index-xgt9k6c6.js} +23 -12
  340. package/dist/index-y8v6yerm.js +77 -0
  341. package/dist/index.d.ts.map +1 -1
  342. package/dist/index.js +7560 -8084
  343. package/dist/message-time-backfill-an311pmk.js +124 -0
  344. package/dist/migration-worker.js +53 -0
  345. package/dist/{model-resolution-dxatzjde.js → model-resolution-xhfmyyvy.js} +5 -1
  346. package/dist/module-ES6BEMUI-3cet1pyp.js +12 -0
  347. package/dist/module-asyncify-2EFITU5U-c2razzd9.js +6 -0
  348. package/dist/plugin/boot-deadline.d.ts.map +1 -1
  349. package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
  350. package/dist/plugin/dream-timer-module-client.d.ts +1 -11
  351. package/dist/plugin/dream-timer-module-client.d.ts.map +1 -1
  352. package/dist/plugin/dream-timer.d.ts.map +1 -1
  353. package/dist/plugin/hooks/create-session-hooks.d.ts +8 -0
  354. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  355. package/dist/plugin/messages-transform.d.ts +20 -13
  356. package/dist/plugin/messages-transform.d.ts.map +1 -1
  357. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  358. package/dist/plugin/stale-build-notice.d.ts +16 -0
  359. package/dist/plugin/stale-build-notice.d.ts.map +1 -0
  360. package/dist/read-session-chunk-8rxs0tc9.js +84 -0
  361. package/dist/recomp-orchestrator-nzamtw29.js +39 -0
  362. package/dist/{rpc-notifications-4amf6mf4.js → rpc-notifications-3hed126v.js} +3 -1
  363. package/dist/{safe-notification-target-50gm9c58.js → safe-notification-target-43r8jsxw.js} +3 -3
  364. package/dist/send-session-notification-nqpv7cne.js +28 -0
  365. package/dist/shared/assistant-message-extractor.d.ts +4 -0
  366. package/dist/shared/assistant-message-extractor.d.ts.map +1 -1
  367. package/dist/shared/background-batch-drain.d.ts +8 -0
  368. package/dist/shared/background-batch-drain.d.ts.map +1 -0
  369. package/dist/{features/builtin-commands/commands.d.ts → shared/builtin-commands.d.ts} +1 -1
  370. package/dist/shared/builtin-commands.d.ts.map +1 -0
  371. package/dist/shared/embedding-activity.d.ts +13 -0
  372. package/dist/shared/embedding-activity.d.ts.map +1 -0
  373. package/dist/shared/historian-tool-expansions.d.ts +5 -0
  374. package/dist/shared/historian-tool-expansions.d.ts.map +1 -0
  375. package/dist/shared/historian-tool-template.d.ts +5 -0
  376. package/dist/shared/historian-tool-template.d.ts.map +1 -0
  377. package/dist/shared/historian-transient-error.d.ts +2 -0
  378. package/dist/shared/historian-transient-error.d.ts.map +1 -0
  379. package/dist/shared/jsonc-edit.d.ts.map +1 -1
  380. package/dist/shared/logger.d.ts +7 -0
  381. package/dist/shared/logger.d.ts.map +1 -1
  382. package/dist/shared/model-suggestion-retry.d.ts +2 -1
  383. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  384. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  385. package/dist/shared/off-thread-migration-clock.d.ts +38 -0
  386. package/dist/shared/off-thread-migration-clock.d.ts.map +1 -0
  387. package/dist/shared/plugin-package-version.d.ts +14 -0
  388. package/dist/shared/plugin-package-version.d.ts.map +1 -0
  389. package/dist/shared/project-directory-key.d.ts +26 -0
  390. package/dist/shared/project-directory-key.d.ts.map +1 -0
  391. package/dist/shared/prompt-async-transport.d.ts +4 -0
  392. package/dist/shared/prompt-async-transport.d.ts.map +1 -1
  393. package/dist/shared/prompt-surface-runtime.d.ts +3 -3
  394. package/dist/shared/provider-response-completion.d.ts +12 -0
  395. package/dist/shared/provider-response-completion.d.ts.map +1 -0
  396. package/dist/shared/redaction.d.ts.map +1 -1
  397. package/dist/shared/rpc-client.d.ts +23 -2
  398. package/dist/shared/rpc-client.d.ts.map +1 -1
  399. package/dist/shared/rpc-types.d.ts +19 -0
  400. package/dist/shared/rpc-types.d.ts.map +1 -1
  401. package/dist/shared/rpc-utils.d.ts +41 -0
  402. package/dist/shared/rpc-utils.d.ts.map +1 -1
  403. package/dist/shared/sqlite.d.ts +13 -2
  404. package/dist/shared/sqlite.d.ts.map +1 -1
  405. package/dist/shared/stale-plugin-build.d.ts +21 -0
  406. package/dist/shared/stale-plugin-build.d.ts.map +1 -0
  407. package/dist/shared/status-summary.d.ts +29 -0
  408. package/dist/shared/status-summary.d.ts.map +1 -1
  409. package/dist/shared/status-view-check.d.ts +124 -0
  410. package/dist/shared/status-view-check.d.ts.map +1 -0
  411. package/dist/shared/status-view.d.ts +38 -2
  412. package/dist/shared/status-view.d.ts.map +1 -1
  413. package/dist/shared/tag-owner-id.d.ts +19 -0
  414. package/dist/shared/tag-owner-id.d.ts.map +1 -0
  415. package/dist/shared/tag-transcript.d.ts +2 -1
  416. package/dist/shared/tag-transcript.d.ts.map +1 -1
  417. package/dist/shared/test-temp-dir.d.ts +8 -2
  418. package/dist/shared/test-temp-dir.d.ts.map +1 -1
  419. package/dist/shared/transcript.d.ts +2 -0
  420. package/dist/shared/transcript.d.ts.map +1 -1
  421. package/dist/shared/user-answer.d.ts +4 -0
  422. package/dist/shared/user-answer.d.ts.map +1 -0
  423. package/dist/shared/user-facing-codes.d.ts +41 -6
  424. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  425. package/dist/shared/xml-unescape.d.ts +9 -0
  426. package/dist/shared/xml-unescape.d.ts.map +1 -0
  427. package/dist/task-config-v81k8jvk.js +17 -0
  428. package/dist/tools/ctx-expand/constants.d.ts +1 -1
  429. package/dist/tools/ctx-expand/constants.d.ts.map +1 -1
  430. package/dist/tools/ctx-expand/mode.d.ts +4 -0
  431. package/dist/tools/ctx-expand/mode.d.ts.map +1 -1
  432. package/dist/tools/ctx-expand/render.d.ts +5 -1
  433. package/dist/tools/ctx-expand/render.d.ts.map +1 -1
  434. package/dist/tools/ctx-expand/tools.d.ts +2 -0
  435. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  436. package/dist/tools/ctx-expand/types.d.ts +1 -0
  437. package/dist/tools/ctx-expand/types.d.ts.map +1 -1
  438. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  439. package/dist/tools/ctx-note/render.d.ts +2 -0
  440. package/dist/tools/ctx-note/render.d.ts.map +1 -1
  441. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  442. package/dist/tools/ctx-reduce/constants.d.ts +1 -1
  443. package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
  444. package/dist/tools/ctx-search/constants.d.ts +1 -1
  445. package/dist/tools/ctx-search/constants.d.ts.map +1 -1
  446. package/dist/tools/light-descriptions.d.ts +3 -3
  447. package/dist/tools/light-descriptions.d.ts.map +1 -1
  448. package/dist/tools/parameter-descriptions.d.ts +14 -14
  449. package/dist/transform-postprocess-phase-414phndq.js +61 -0
  450. package/dist/tui/data/context-db.d.ts +34 -10
  451. package/dist/tui/data/context-db.d.ts.map +1 -1
  452. package/dist/tui/data/notification-socket.d.ts +6 -0
  453. package/dist/tui/data/notification-socket.d.ts.map +1 -1
  454. package/dist/tui/data/session-directory.d.ts +16 -0
  455. package/dist/tui/data/session-directory.d.ts.map +1 -0
  456. package/dist/tui-compiled/data/context-db.d.ts +34 -10
  457. package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
  458. package/dist/tui-compiled/data/notification-socket.d.ts +6 -0
  459. package/dist/tui-compiled/data/notification-socket.d.ts.map +1 -1
  460. package/dist/tui-compiled/data/session-directory.d.ts +16 -0
  461. package/dist/tui-compiled/data/session-directory.d.ts.map +1 -0
  462. package/dist/v2/derive-budgets-v0krf3t7.js +18 -0
  463. package/dist/v2/embedding-worker.js +47 -0
  464. package/dist/v2/emscripten-module-0g8f45e6.js +602 -0
  465. package/dist/v2/emscripten-module-0pekdjxz.js +1532 -0
  466. package/dist/v2/emscripten-module-e67xwsp3.js +503 -0
  467. package/dist/v2/emscripten-module-pj1vyb44.js +4559 -0
  468. package/dist/v2/ffi-3cx1cxpk.js +78 -0
  469. package/dist/v2/ffi-7bqqe4cd.js +91 -0
  470. package/dist/v2/ffi-7e6gryj5.js +91 -0
  471. package/dist/v2/ffi-bpvkebwr.js +78 -0
  472. package/dist/v2/fold/boundary.d.ts.map +1 -1
  473. package/dist/v2/fork-inheritance.d.ts +101 -0
  474. package/dist/v2/fork-inheritance.d.ts.map +1 -0
  475. package/dist/v2/hidden-child-cleanup.d.ts +11 -0
  476. package/dist/v2/hidden-child-cleanup.d.ts.map +1 -0
  477. package/dist/v2/hidden-child-native.d.ts +29 -0
  478. package/dist/v2/hidden-child-native.d.ts.map +1 -0
  479. package/dist/v2/hidden-child-record.d.ts +135 -0
  480. package/dist/v2/hidden-child-record.d.ts.map +1 -0
  481. package/dist/v2/hidden-completion.d.ts +12 -97
  482. package/dist/v2/hidden-completion.d.ts.map +1 -1
  483. package/dist/v2/hooks/context.d.ts +20 -8
  484. package/dist/v2/hooks/context.d.ts.map +1 -1
  485. package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
  486. package/dist/v2/hooks/dream-trigger.d.ts +5 -0
  487. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  488. package/dist/v2/hooks/generate.d.ts +10 -0
  489. package/dist/v2/hooks/generate.d.ts.map +1 -0
  490. package/dist/v2/hooks/hidden-child.d.ts +33 -2
  491. package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
  492. package/dist/v2/hooks/payload.d.ts +3 -0
  493. package/dist/v2/hooks/payload.d.ts.map +1 -1
  494. package/dist/v2/hooks/session-api-gate.d.ts +4 -0
  495. package/dist/v2/hooks/session-api-gate.d.ts.map +1 -0
  496. package/dist/v2/hooks/storage-gate.d.ts +3 -1
  497. package/dist/v2/hooks/storage-gate.d.ts.map +1 -1
  498. package/dist/v2/hooks/store.d.ts +1 -1
  499. package/dist/v2/hooks/store.d.ts.map +1 -1
  500. package/dist/v2/hooks/tools.d.ts.map +1 -1
  501. package/dist/v2/hooks/types.d.ts +10 -0
  502. package/dist/v2/hooks/types.d.ts.map +1 -1
  503. package/dist/v2/hooks/update-check.d.ts.map +1 -1
  504. package/dist/v2/hooks/usage-persist.d.ts.map +1 -1
  505. package/dist/v2/hooks/usage-reading.d.ts +4 -0
  506. package/dist/v2/hooks/usage-reading.d.ts.map +1 -1
  507. package/dist/v2/index-6e4mwffh.js +5662 -0
  508. package/dist/v2/index-en1k8h8m.js +244 -0
  509. package/dist/{message-time-backfill-q374fxc5.js → v2/message-time-backfill-0n93vrd7.js} +19 -5
  510. package/dist/v2/migration-worker.js +52 -0
  511. package/dist/v2/model-resolution-xhfmyyvy.js +16 -0
  512. package/dist/v2/module-ES6BEMUI-3cet1pyp.js +12 -0
  513. package/dist/v2/module-asyncify-2EFITU5U-c2razzd9.js +6 -0
  514. package/dist/v2/prompt-context-5y5ms8f9.js +6 -0
  515. package/dist/{read-session-chunk-n072mcq4.js → v2/read-session-chunk-hjza38hr.js} +24 -7
  516. package/dist/v2/recomp-orchestrator-1aq7h44c.js +36 -0
  517. package/dist/v2/retrospective-raw-provider.d.ts +21 -0
  518. package/dist/v2/retrospective-raw-provider.d.ts.map +1 -0
  519. package/dist/v2/rpc-notifications-3hed126v.js +16 -0
  520. package/dist/v2/safe-notification-target-wtj0bbc2.js +9 -0
  521. package/dist/{send-session-notification-04hvd54c.js → v2/send-session-notification-mq9frrtm.js} +10 -5
  522. package/dist/v2/server-0jqw05sa.js +803 -0
  523. package/dist/v2/server-5317ykaf.js +40 -0
  524. package/dist/v2/server-a4m2b1yv.js +530 -0
  525. package/dist/v2/server-avwt563y.js +62 -0
  526. package/dist/v2/server-c4g2y1z8.js +28824 -0
  527. package/dist/v2/server-ckpc8pxy.js +662 -0
  528. package/dist/v2/server-e36nf2p1.js +7702 -0
  529. package/dist/v2/server-e44zzy84.js +10 -0
  530. package/dist/v2/server-fgmxwrgy.js +16 -0
  531. package/dist/v2/server-fmsr7v69.js +75 -0
  532. package/dist/v2/server-g20jdh0p.js +1273 -0
  533. package/dist/{index-dgg5y7er.js → v2/server-hfjfbg59.js} +849 -747
  534. package/dist/v2/server-n96ag4rk.js +633 -0
  535. package/dist/v2/server-qdjnb2z1.js +181 -0
  536. package/dist/v2/server-qpg6wf72.js +187 -0
  537. package/dist/v2/server-r7cmye3k.js +131 -0
  538. package/dist/v2/server-remp7e2g.js +214 -0
  539. package/dist/v2/server-rhdgxp1t.js +398 -0
  540. package/dist/v2/server-sfpzqvdz.js +137 -0
  541. package/dist/v2/server-syahy8j8.js +50 -0
  542. package/dist/v2/server-v5xgft5v.js +9116 -0
  543. package/dist/v2/server-w99cyt6a.js +361 -0
  544. package/dist/v2/server-x8a7jmkh.js +104 -0
  545. package/dist/v2/server-y8v6yerm.js +77 -0
  546. package/dist/v2/server-z19x7eqz.js +423 -0
  547. package/dist/v2/server.d.ts.map +1 -1
  548. package/dist/v2/server.js +8868 -107184
  549. package/dist/v2/store-reader.d.ts +52 -1
  550. package/dist/v2/store-reader.d.ts.map +1 -1
  551. package/dist/v2/task-config-tbndqyny.js +17 -0
  552. package/dist/v2/transformers-node-wasm.js +26768 -0
  553. package/dist/v2/transformers-web.js +25670 -0
  554. package/dist/v2/transformers.node-hj754h7s.js +29997 -0
  555. package/dist/v2/tui/index.d.ts +10 -1
  556. package/dist/v2/tui/index.d.ts.map +1 -1
  557. package/dist/v2/tui/sidebar-mount.d.ts +6 -0
  558. package/dist/v2/tui/sidebar-mount.d.ts.map +1 -1
  559. package/dist/v2/tui/status-dialog-mount.d.ts +7 -4
  560. package/dist/v2/tui/status-dialog-mount.d.ts.map +1 -1
  561. package/dist/v2/tui/types.d.ts +12 -0
  562. package/dist/v2/tui/types.d.ts.map +1 -1
  563. package/dist/v2/wrapup-orchestrator-tbyx78dz.js +425 -0
  564. package/dist/wrapup-orchestrator-h28bqsy6.js +26 -0
  565. package/package.json +8 -8
  566. package/src/agents/hidden-agent-registrations.ts +24 -16
  567. package/src/agents/magic-context-prompt.test.ts +41 -0
  568. package/src/agents/magic-context-prompt.ts +8 -5
  569. package/src/agents/permissions.test.ts +31 -49
  570. package/src/agents/permissions.ts +8 -28
  571. package/src/config/index.test.ts +60 -20
  572. package/src/config/index.ts +53 -1
  573. package/src/config/live-run-config.test.ts +5 -5
  574. package/src/config/live-snapshot.test.ts +4 -4
  575. package/src/config/migrate-config-location.test.ts +3 -10
  576. package/src/config/project-config-trust-boundary.test.ts +207 -0
  577. package/src/config/project-security.hostile-matrix.test.ts +4 -4
  578. package/src/config/project-security.ts +218 -1
  579. package/src/config/protected-tokens.test.ts +14 -9
  580. package/src/config/raw-loader.test.ts +31 -3
  581. package/src/config/raw-loader.ts +8 -3
  582. package/src/config/schema/magic-context.ts +20 -3
  583. package/src/config/variable.test.ts +3 -2
  584. package/src/features/magic-context/dreamer/cron.ts +30 -9
  585. package/src/features/magic-context/dreamer/task-registry.ts +7 -5
  586. package/src/shared/announcement.test.ts +2 -1
  587. package/src/shared/assistant-message-extractor.test.ts +27 -1
  588. package/src/shared/assistant-message-extractor.ts +27 -0
  589. package/src/shared/background-batch-drain.test.ts +38 -0
  590. package/src/shared/background-batch-drain.ts +29 -0
  591. package/src/shared/builtin-commands.ts +50 -0
  592. package/src/shared/console-diagnostics-fence.test.ts +145 -0
  593. package/src/shared/data-path.test.ts +6 -5
  594. package/src/shared/embedding-activity.test.ts +21 -0
  595. package/src/shared/embedding-activity.ts +36 -0
  596. package/src/shared/historian-tool-defaults.json +13 -0
  597. package/src/shared/historian-tool-expansions.ts +18 -0
  598. package/src/shared/historian-tool-template.ts +248 -0
  599. package/src/shared/historian-transient-error.test.ts +36 -0
  600. package/src/shared/historian-transient-error.ts +22 -0
  601. package/src/shared/jsonc-edit.ts +20 -1
  602. package/src/shared/logger.test.ts +3 -2
  603. package/src/shared/logger.ts +40 -1
  604. package/src/shared/model-suggestion-retry.test.ts +46 -0
  605. package/src/shared/model-suggestion-retry.ts +16 -1
  606. package/src/shared/models-dev-cache.test.ts +74 -2
  607. package/src/shared/models-dev-cache.ts +5 -1
  608. package/src/shared/off-thread-migration-clock.test.ts +55 -0
  609. package/src/shared/off-thread-migration-clock.ts +124 -0
  610. package/src/shared/opencode-db-path.test.ts +3 -2
  611. package/src/shared/plugin-package-version.ts +52 -0
  612. package/src/shared/project-directory-key.test.ts +111 -0
  613. package/src/shared/project-directory-key.ts +54 -0
  614. package/src/shared/prompt-async-transport.test.ts +249 -72
  615. package/src/shared/prompt-async-transport.ts +131 -24
  616. package/src/shared/prompt-surface-a1-golden.md +41 -25
  617. package/src/shared/prompt-surface-runtime.test.ts +3 -3
  618. package/src/shared/provider-response-completion.ts +23 -0
  619. package/src/shared/redaction.test.ts +51 -1
  620. package/src/shared/redaction.ts +33 -0
  621. package/src/shared/rpc-async-probes.test.ts +32 -2
  622. package/src/shared/rpc-client.test.ts +3 -2
  623. package/src/shared/rpc-client.ts +76 -18
  624. package/src/shared/rpc-types.ts +15 -0
  625. package/src/shared/rpc-utils.test.ts +191 -12
  626. package/src/shared/rpc-utils.ts +184 -26
  627. package/src/shared/sqlite-acquisition-routing.test.ts +46 -3
  628. package/src/shared/sqlite-pass-scope.test.ts +3 -2
  629. package/src/shared/sqlite-transaction-mode-guard.test.ts +4 -0
  630. package/src/shared/sqlite-writer-diagnostics.test.ts +134 -0
  631. package/src/shared/sqlite.ts +225 -41
  632. package/src/shared/stale-plugin-build.test.ts +129 -0
  633. package/src/shared/stale-plugin-build.ts +151 -0
  634. package/src/shared/status-summary.ts +40 -13
  635. package/src/shared/status-view-check.test.ts +253 -0
  636. package/src/shared/status-view-check.ts +536 -0
  637. package/src/shared/status-view.test.ts +6 -1
  638. package/src/shared/status-view.ts +176 -4
  639. package/src/shared/storage-busy.test.ts +3 -2
  640. package/src/shared/tag-owner-id.test.ts +33 -0
  641. package/src/shared/tag-owner-id.ts +29 -0
  642. package/src/shared/tag-transcript.ts +17 -3
  643. package/src/shared/test-temp-dir-policy.test.ts +33 -0
  644. package/src/shared/test-temp-dir.test.ts +27 -0
  645. package/src/shared/test-temp-dir.ts +36 -12
  646. package/src/shared/transcript.ts +3 -0
  647. package/src/shared/tui-config.test.ts +6 -5
  648. package/src/shared/tui-preferences.test.ts +3 -2
  649. package/src/shared/user-answer.test.ts +40 -0
  650. package/src/shared/user-answer.ts +17 -0
  651. package/src/shared/user-facing-codes.ts +52 -6
  652. package/src/shared/window-geometry.test.ts +3 -2
  653. package/src/shared/write-transaction-attribution.test.ts +11 -7
  654. package/src/shared/write-transaction-hold-clock.test.ts +160 -0
  655. package/src/shared/xml-unescape.ts +19 -0
  656. package/src/tui/data/context-db.test.ts +92 -4
  657. package/src/tui/data/context-db.ts +184 -18
  658. package/src/tui/data/notification-socket.test.ts +49 -2
  659. package/src/tui/data/notification-socket.ts +47 -9
  660. package/src/tui/data/session-directory.ts +19 -0
  661. package/src/tui/dialogs/status-dialog-render.test.ts +284 -0
  662. package/src/tui/dialogs/status-dialog.tsx +41 -38
  663. package/src/tui/index.tsx +30 -18
  664. package/src/tui/slots/sidebar-content.tsx +9 -2
  665. package/src/tui-compiled/data/context-db.ts +184 -18
  666. package/src/tui-compiled/data/notification-socket.ts +47 -9
  667. package/src/tui-compiled/data/session-directory.ts +19 -0
  668. package/src/tui-compiled/dialogs/status-dialog.tsx +38 -29
  669. package/src/tui-compiled/index.tsx +29 -16
  670. package/src/tui-compiled/slots/sidebar-content.tsx +3 -2
  671. package/src/v2/tui/host-contract.test.ts +9 -10
  672. package/src/v2/tui/index.ts +78 -23
  673. package/src/v2/tui/load-compiled-sidebar.d.mts +5 -1
  674. package/src/v2/tui/load-compiled-status-dialog.d.mts +3 -2
  675. package/src/v2/tui/session-directory.test.ts +53 -0
  676. package/src/v2/tui/sidebar-mount.ts +19 -1
  677. package/src/v2/tui/status-dialog-mount.ts +10 -7
  678. package/src/v2/tui/types.ts +10 -0
  679. package/dist/features/builtin-commands/commands.d.ts.map +0 -1
  680. package/dist/features/builtin-commands/types.d.ts +0 -3
  681. package/dist/features/builtin-commands/types.d.ts.map +0 -1
  682. package/dist/features/magic-context/context-authority.d.ts +0 -272
  683. package/dist/features/magic-context/context-authority.d.ts.map +0 -1
  684. package/dist/features/magic-context/memory/mirror-reembed.d.ts +0 -22
  685. package/dist/features/magic-context/memory/mirror-reembed.d.ts.map +0 -1
  686. package/dist/hooks/magic-context/historian-state-file.d.ts +0 -43
  687. package/dist/hooks/magic-context/historian-state-file.d.ts.map +0 -1
  688. package/dist/index-4an2p8qa.js +0 -1056
  689. package/dist/index-rn7gafjr.js +0 -8
  690. package/dist/index-v6t0tg85.js +0 -13
  691. package/dist/plugin/memory-id-translation.d.ts +0 -109
  692. package/dist/plugin/memory-id-translation.d.ts.map +0 -1
  693. package/dist/plugin/rust-note-backend.d.ts +0 -84
  694. package/dist/plugin/rust-note-backend.d.ts.map +0 -1
  695. package/dist/recomp-orchestrator-19tr6zya.js +0 -22
  696. package/dist/task-config-2bm68628.js +0 -9
  697. package/dist/transform-postprocess-phase-z2mfc5w1.js +0 -36
  698. package/dist/v2/host-service.d.ts +0 -66
  699. package/dist/v2/host-service.d.ts.map +0 -1
  700. package/dist/wrapup-orchestrator-sy4m56a7.js +0 -19
  701. /package/dist/{index-s70wtd8k.js → index-q6hef7fh.js} +0 -0
@@ -1,23 +1,18 @@
1
1
  import {
2
2
  getHarness
3
- } from "./index-s70wtd8k.js";
3
+ } from "./index-q6hef7fh.js";
4
4
  import {
5
5
  log,
6
6
  sessionLog
7
- } from "./index-3bygzk2d.js";
7
+ } from "./index-hybnrwq0.js";
8
8
  import {
9
- openCodeDbExists,
10
- withReadOnlySessionDb,
11
- getMessageTimesFromOpenCodeDb
12
- } from "./index-4an2p8qa.js";
9
+ isTransientSqliteError
10
+ } from "./index-a4m2b1yv.js";
13
11
  import {
14
12
  BoundedSessionMap,
15
- resolveWorkspaceShareCategories,
16
- resolveWorkspaceIdentitySet,
17
- expandWorkspaceIdentitySetWithAliases,
18
- resolveStoredPathWorkspaceIdentity,
19
- sourceNameForMemory,
13
+ renderUserFacingFailure,
20
14
  loadCompartmentChunkEmbeddingsForSearch,
15
+ getMaxM0MutationId,
21
16
  getIndexedMessageCorpusSize,
22
17
  escalationBands,
23
18
  MERGED_REASONING_PARTS_PREFIX,
@@ -25,6 +20,9 @@ import {
25
20
  HYGIENE_PROVIDER_UNITS_VERSION,
26
21
  sessionDecisionCalibration,
27
22
  transitionSessionHygieneUnits,
23
+ ReplayDocumentError,
24
+ readReplayEnvelope,
25
+ updateReplayDocument,
28
26
  getEmergencyInputSample,
29
27
  setEmergencyDropSample,
30
28
  clearEmergencyDropSample,
@@ -62,7 +60,6 @@ import {
62
60
  replacePendingCompactionMarkerStateIf,
63
61
  clearPendingCompactionMarkerStateIf,
64
62
  recordEmbeddingMeasurement,
65
- getMaxM0MutationId,
66
63
  updateSessionMeta,
67
64
  advanceToolReclaimWatermark,
68
65
  getNotes,
@@ -73,17 +70,15 @@ import {
73
70
  saveSourceContent,
74
71
  replaceSourceContent,
75
72
  getSourceContents,
76
- isFable51ThinkingBindingModel,
77
73
  cosineSimilarity,
78
74
  saveCommitEmbedding,
79
75
  loadProjectCommitEmbeddings,
80
76
  loadUnembeddedCommits,
81
77
  countEmbeddedCommits,
82
78
  upsertCommits,
83
- getLatestIndexedCommitTimeMs,
79
+ getLatestIndexedCommitSha,
84
80
  enforceProjectCap,
85
81
  getProjectEmbeddings,
86
- peekProjectEmbeddings,
87
82
  contentSha256,
88
83
  getShadowEmbeddingMeasurementCohort,
89
84
  getPrimaryEmbeddingMeasurementCohort,
@@ -117,12 +112,23 @@ import {
117
112
  peekNoteNudgeText,
118
113
  markNoteNudgeDelivered,
119
114
  getActiveCompartmentRun
120
- } from "./index-yhm60r53.js";
115
+ } from "./index-16ny736w.js";
121
116
  import {
122
117
  textMentionsRecentCommit,
123
118
  hasMeaningfulUserText2,
124
- estimateTokens,
125
- stableStringify,
119
+ estimateTokens
120
+ } from "./index-gd5qx1j9.js";
121
+ import {
122
+ isValidLanguageCode
123
+ } from "./index-q7yesyk9.js";
124
+ import {
125
+ resolveWorkspaceShareCategories,
126
+ resolveWorkspaceIdentitySet,
127
+ expandWorkspaceIdentitySetWithAliases,
128
+ resolveStoredPathWorkspaceIdentity,
129
+ sourceNameForMemory
130
+ } from "./index-fr2z4qy8.js";
131
+ import {
126
132
  CTX_REDUCE_KEEP,
127
133
  newestCtxReduceTagNumbers,
128
134
  stripWellFormedLeadingTagPrefix,
@@ -166,32 +172,120 @@ import {
166
172
  getTagsBySession,
167
173
  getActiveTagsBySession,
168
174
  getTailHygieneTags,
175
+ getDroppedTagsByNumbers,
169
176
  getTagById,
170
177
  getToolTagNumberByOwner,
171
178
  getNullOwnerToolTag,
172
179
  adoptNullOwnerToolTag,
173
180
  getCandidateToolOwners,
174
181
  pickNearestPriorOwner,
182
+ stripSystemInjection,
175
183
  isTextPart,
176
184
  isToolPartWithOutput,
177
185
  isFilePart,
178
186
  buildFileSourceContent,
187
+ toolPartHasUserAnswer,
179
188
  isEditTool,
189
+ modelAcceptsEmptyContent,
190
+ neutralizeDroppedReasoningPart,
191
+ restoreNeutralizedReasoningPart,
192
+ isNeutralizedReasoningPart,
193
+ makeSentinel,
194
+ makeWholeMessageSentinel,
195
+ isSentinel,
196
+ replaySentinelByMessageIds,
180
197
  SKELETON_REAL_INPUT_MAX_BYTES,
181
198
  partHasCompletedResult,
182
199
  extractToolCallObservation,
183
200
  ToolMutationBatch,
184
201
  createToolDropTarget
185
- } from "./index-dgg5y7er.js";
202
+ } from "./index-4krbw8z9.js";
186
203
  import {
187
- canonicalModelIdentity
188
- } from "./index-9y5p0d50.js";
204
+ openCodeDbExists,
205
+ withReadOnlySessionDb,
206
+ getMessageTimesFromOpenCodeDb
207
+ } from "./index-bmzf7zxv.js";
208
+ import {
209
+ stableStringify
210
+ } from "./index-anq4nn6f.js";
189
211
  import {
190
212
  getErrorMessage
191
- } from "./index-33q7s9y2.js";
213
+ } from "./index-y8v6yerm.js";
192
214
  import {
193
215
  logSlowWriteTransaction
194
- } from "./index-kr5qehbd.js";
216
+ } from "./index-x23gah8c.js";
217
+
218
+ // src/features/magic-context/storage-reasoning-removal.ts
219
+ var NAMESPACE = "reasoningRemoval";
220
+ var BACKUP_NAMESPACE = "reasoningRemovalBackup";
221
+ function invalidState(sessionId) {
222
+ return new Error(`invalid persisted reasoning removal state for session ${sessionId}`);
223
+ }
224
+ function parseState(doc, sessionId, namespace = NAMESPACE) {
225
+ const lane = doc[namespace];
226
+ if (lane === undefined)
227
+ return { messageIds: new Set, dropLeavesReasoning: false };
228
+ if (!isRecord(lane) || !Array.isArray(lane.messageIds))
229
+ throw invalidState(sessionId);
230
+ const ids = new Set;
231
+ for (const id of lane.messageIds) {
232
+ if (typeof id !== "string" || id.length === 0)
233
+ throw invalidState(sessionId);
234
+ ids.add(id);
235
+ }
236
+ if (lane.dropLeavesReasoning !== undefined && typeof lane.dropLeavesReasoning !== "boolean") {
237
+ throw invalidState(sessionId);
238
+ }
239
+ return { messageIds: ids, dropLeavesReasoning: lane.dropLeavesReasoning === true };
240
+ }
241
+ function writeState(doc, state) {
242
+ doc.version = 2;
243
+ const lane = {
244
+ messageIds: [...state.messageIds],
245
+ ...state.dropLeavesReasoning ? { dropLeavesReasoning: true } : {}
246
+ };
247
+ doc[NAMESPACE] = lane;
248
+ doc[BACKUP_NAMESPACE] = { ...lane, messageIds: [...lane.messageIds] };
249
+ }
250
+ function getReasoningRemovalState(db, sessionId) {
251
+ const doc = readReplayEnvelope(db, sessionId);
252
+ try {
253
+ return parseState(doc, sessionId);
254
+ } catch (error) {
255
+ if (doc[BACKUP_NAMESPACE] === undefined)
256
+ throw error;
257
+ return parseState(doc, sessionId, BACKUP_NAMESPACE);
258
+ }
259
+ }
260
+ function addRemovedReasoningIds(db, sessionId, ids) {
261
+ const requested = [...ids].filter((id) => typeof id === "string" && id.length > 0);
262
+ if (requested.length === 0)
263
+ return true;
264
+ return updateReplayDocument(db, sessionId, (doc) => {
265
+ const current = parseState(doc, sessionId);
266
+ let changed = false;
267
+ for (const id of requested) {
268
+ if (current.messageIds.has(id))
269
+ continue;
270
+ current.messageIds.add(id);
271
+ changed = true;
272
+ }
273
+ if (!changed)
274
+ return false;
275
+ writeState(doc, current);
276
+ return true;
277
+ });
278
+ }
279
+ function markDropLeavesReasoning(db, sessionId) {
280
+ return updateReplayDocument(db, sessionId, (doc) => {
281
+ const current = parseState(doc, sessionId);
282
+ if (current.dropLeavesReasoning)
283
+ return false;
284
+ current.dropLeavesReasoning = true;
285
+ writeState(doc, current);
286
+ return true;
287
+ });
288
+ }
195
289
 
196
290
  // src/hooks/magic-context/apply-operations.ts
197
291
  var RECENT_TOOL_SKELETON_WINDOW = 20;
@@ -239,8 +333,8 @@ function foldChangesServedPrefix(before, after) {
239
333
  function foldBustsServedPrefix(reason, before, after) {
240
334
  return CACHE_LOSING_FOLD_REASONS.has(reason ?? "") || foldChangesServedPrefix(before, after);
241
335
  }
242
- function convertLegacyToolSkeletons(db, sessionId, targets) {
243
- const rows = db.prepare(`SELECT tag_number AS tagNumber, drop_mode AS dropMode
336
+ function convertLegacyToolSkeletons(db, sessionId, targets, options = {}) {
337
+ const rows = db.prepare(`SELECT tag_number AS tagNumber, drop_mode AS dropMode, message_id AS callId
244
338
  FROM tags
245
339
  WHERE session_id = ? AND type = 'tool' AND status = 'dropped'
246
340
  AND drop_mode IN ('truncated', 'full')
@@ -253,6 +347,8 @@ function convertLegacyToolSkeletons(db, sessionId, targets) {
253
347
  const cannotRemove = target.cannotRemove?.() === true || target.requiresToolArcSkeleton === true || target.wouldStrandConversationEnd?.() === true;
254
348
  let mode;
255
349
  if (row.dropMode === "full") {
350
+ if (options.keepFullDrop?.(row.callId) === true)
351
+ continue;
256
352
  if (target.cannotRemove?.() !== true)
257
353
  continue;
258
354
  mode = "skeleton_real";
@@ -420,7 +516,7 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
420
516
  }
421
517
  function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
422
518
  let didMutateMessage = false;
423
- const tags = preloadedTags ?? getTagsBySession(db, sessionId);
519
+ const tags = preloadedTags ?? getDroppedTagsByNumbers(db, sessionId, [...targets.keys()]);
424
520
  for (const tag of tags) {
425
521
  if (tag.status === "dropped") {
426
522
  const target = targets.get(tag.tagNumber);
@@ -472,6 +568,7 @@ var GIT_TIMEOUT_MS = 1e4;
472
568
  var DEFAULT_MAX_COMMITS = 5000;
473
569
  var RECORD_SEPARATOR = "\x1E";
474
570
  var FIELD_SEPARATOR = "\x1F";
571
+ var FULL_OBJECT_NAME = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;
475
572
  function classifyGitLogFailure(message) {
476
573
  if (message.includes("not a git repository"))
477
574
  return "not_a_repo";
@@ -486,9 +583,11 @@ async function readGitCommitsResult(directory, options = {}) {
486
583
  throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
487
584
  }
488
585
  const projectLabel = options.projectIdentity ?? "<project>";
586
+ const exclusion = options.excludeReachableFrom && FULL_OBJECT_NAME.test(options.excludeReachableFrom) ? options.excludeReachableFrom : null;
489
587
  const args = [
490
588
  "log",
491
589
  revision,
590
+ ...exclusion ? [`^${exclusion}`] : [],
492
591
  "--no-merges",
493
592
  `--max-count=${options.maxCommits ?? DEFAULT_MAX_COMMITS}`,
494
593
  `--format=%H${FIELD_SEPARATOR}%s${FIELD_SEPARATOR}%ae${FIELD_SEPARATOR}%ct${FIELD_SEPARATOR}%b${RECORD_SEPARATOR}`
@@ -497,6 +596,7 @@ async function readGitCommitsResult(directory, options = {}) {
497
596
  const iso = new Date(options.sinceMs).toISOString();
498
597
  args.push(`--since=${iso}`);
499
598
  }
599
+ args.push("--");
500
600
  let stdout;
501
601
  try {
502
602
  const result = await execFileAsync("git", args, {
@@ -509,6 +609,10 @@ async function readGitCommitsResult(directory, options = {}) {
509
609
  stdout = result.stdout;
510
610
  } catch (error) {
511
611
  const message = error instanceof Error ? error.message : String(error);
612
+ if (exclusion && message.includes("bad object")) {
613
+ log(`[git-commits] indexed tip ${exclusion.slice(0, 7)} is missing for ${projectLabel}; reading the full window`);
614
+ return readGitCommitsResult(directory, { ...options, excludeReachableFrom: undefined });
615
+ }
512
616
  const failure = classifyGitLogFailure(message);
513
617
  if (failure === "transient") {
514
618
  log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
@@ -546,7 +650,7 @@ function parseGitLogOutput(stdout) {
546
650
  const author = fields[2].trim();
547
651
  const timeSec = Number.parseInt(fields[3].trim(), 10);
548
652
  const body = fields[4].trim();
549
- if (sha.length !== 40 || !Number.isFinite(timeSec) || timeSec <= 0) {
653
+ if (!FULL_OBJECT_NAME.test(sha) || !Number.isFinite(timeSec) || timeSec <= 0) {
550
654
  continue;
551
655
  }
552
656
  const message = body.length > 0 ? `${subject}
@@ -584,12 +688,13 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
584
688
  }
585
689
  indexInProgress.add(projectPath);
586
690
  try {
587
- const latestIndexed = getLatestIndexedCommitTimeMs(db, projectPath);
588
- const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
691
+ const latestIndexed = getLatestIndexedCommitSha(db, projectPath);
692
+ const sinceMs = Date.now() - options.sinceDays * MS_PER_DAY;
589
693
  const read = await readGitCommitsResult(directory, {
590
694
  sinceMs,
591
695
  maxCommits: options.maxCommits,
592
- projectIdentity: projectPath
696
+ projectIdentity: projectPath,
697
+ excludeReachableFrom: latestIndexed ?? undefined
593
698
  });
594
699
  const commits = read.commits;
595
700
  result.scanned = commits.length;
@@ -599,10 +704,10 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
599
704
  }
600
705
  if (commits.length === 0) {
601
706
  result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
602
- log(`[git-commits] no new commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed ?? "none"} evicted=${result.evicted})`);
707
+ log(`[git-commits] no new commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed?.slice(0, 7) ?? "none"} evicted=${result.evicted})`);
603
708
  return result;
604
709
  }
605
- log(`[git-commits] read ${commits.length} commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed ?? "none"})`);
710
+ log(`[git-commits] read ${commits.length} commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed?.slice(0, 7) ?? "none"})`);
606
711
  const upsert = upsertCommits(db, projectPath, commits);
607
712
  result.inserted = upsert.inserted;
608
713
  result.updated = upsert.updated;
@@ -709,6 +814,9 @@ function getFtsStatement(db, dated = false) {
709
814
  }
710
815
  return stmt;
711
816
  }
817
+ function escapeLikePattern(text) {
818
+ return text.replace(/[\\%_]/g, (char) => `\\${char}`);
819
+ }
712
820
  function getLikeFallbackStatement(db, dated = false) {
713
821
  const statements = dated ? datedFtsPlainStatements : ftsPlainStatements;
714
822
  let stmt = statements.get(db);
@@ -717,7 +825,7 @@ function getLikeFallbackStatement(db, dated = false) {
717
825
  FROM git_commits
718
826
  WHERE project_path = ?
719
827
  ${dated ? "AND committed_at BETWEEN ? AND ?" : ""}
720
- AND lower(message) LIKE '%' || lower(?) || '%'
828
+ AND lower(message) LIKE '%' || lower(?) || '%' ESCAPE '\\'
721
829
  ORDER BY committed_at DESC LIMIT ?`);
722
830
  statements.set(db, stmt);
723
831
  }
@@ -764,7 +872,7 @@ function searchGitCommitsSync(db, projectPath, query, options) {
764
872
  }
765
873
  }
766
874
  if (ftsCandidates.length === 0) {
767
- for (const row of getLikeFallbackStatement(db, dated).all(projectPath, ...dated ? [from, to] : [], trimmed, fetchLimit)) {
875
+ for (const row of getLikeFallbackStatement(db, dated).all(projectPath, ...dated ? [from, to] : [], escapeLikePattern(trimmed), fetchLimit)) {
768
876
  ftsCandidates.push(rowToCommit(row));
769
877
  }
770
878
  }
@@ -874,6 +982,61 @@ function containsProbeVerbatim(text, probes) {
874
982
  return probes.some((probe) => haystack.includes(probe.toLowerCase()));
875
983
  }
876
984
 
985
+ // src/features/magic-context/message-fts-session-filter.ts
986
+ var MESSAGE_FTS_SESSION_FILTER_SQL = `+message_history_fts.rowid IN (
987
+ SELECT fts_rowid FROM message_fts_rowid_map WHERE session_id = ?1
988
+ ) AND `;
989
+ var coverageCaches = new WeakMap;
990
+ function getCoverageCache(db) {
991
+ let cache = coverageCaches.get(db);
992
+ if (!cache) {
993
+ cache = {
994
+ pin: db.prepare("SELECT fts_rowid FROM message_fts_rowid_map LIMIT 1"),
995
+ stamp: db.prepare("SELECT total_changes() AS changes, data_version AS version FROM pragma_data_version"),
996
+ missing: db.prepare(`SELECT DISTINCT session_id AS sessionId
997
+ FROM message_history_fts WHERE rowid IN (
998
+ SELECT id FROM message_history_fts_docsize
999
+ EXCEPT SELECT fts_rowid FROM message_fts_rowid_map
1000
+ )`)
1001
+ };
1002
+ coverageCaches.set(db, cache);
1003
+ }
1004
+ return cache;
1005
+ }
1006
+ function withMessageFtsSessionFilter(db, sessionId, read) {
1007
+ let cacheable = false;
1008
+ try {
1009
+ const transaction = db;
1010
+ cacheable = transaction.inTransaction === false || transaction.isTransaction === false;
1011
+ if (!cacheable)
1012
+ coverageCaches.delete(db);
1013
+ } catch {
1014
+ coverageCaches.delete(db);
1015
+ }
1016
+ return db.transaction(() => {
1017
+ let sessionFirst = false;
1018
+ try {
1019
+ const cache = getCoverageCache(db);
1020
+ cache.pin.get();
1021
+ const stamp = cache.stamp.get();
1022
+ let incomplete = cache.incompleteSessions;
1023
+ if (!cacheable || !incomplete || cache.version !== stamp.version || cache.changes !== stamp.changes) {
1024
+ const rows = cache.missing.all();
1025
+ incomplete = new Set(rows.map((row) => row.sessionId));
1026
+ if (cacheable) {
1027
+ cache.version = stamp.version;
1028
+ cache.changes = stamp.changes;
1029
+ cache.incompleteSessions = incomplete;
1030
+ }
1031
+ }
1032
+ sessionFirst = !incomplete.has(sessionId);
1033
+ } catch {
1034
+ coverageCaches.delete(db);
1035
+ }
1036
+ return read(sessionFirst);
1037
+ }).deferred();
1038
+ }
1039
+
877
1040
  // src/features/magic-context/search-measurement.ts
878
1041
  import { createHash } from "node:crypto";
879
1042
  function resultId(result) {
@@ -967,6 +1130,7 @@ function sha256(value) {
967
1130
 
968
1131
  // src/features/magic-context/search.ts
969
1132
  var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
1133
+ var MAX_UNIFIED_SEARCH_LIMIT = 25;
970
1134
  var FTS_SEMANTIC_CANDIDATE_LIMIT = 50;
971
1135
  var SEMANTIC_WEIGHT = 0.7;
972
1136
  var FTS_WEIGHT = 0.3;
@@ -977,9 +1141,12 @@ var MESSAGE_SOURCE_BOOST = 1.275;
977
1141
  var GIT_COMMIT_SOURCE_BOOST = 1.2;
978
1142
  var PRIMER_SOURCE_BOOST = 1.25;
979
1143
  var messageSearchStatements = new WeakMap;
1144
+ var sessionFirstMessageSearchStatements = new WeakMap;
980
1145
  var messageSearchStatementsWithCutoff = new WeakMap;
1146
+ var sessionFirstMessageSearchStatementsWithCutoff = new WeakMap;
981
1147
  var messageSearchStatementsWithDateRange = new WeakMap;
982
1148
  var messageSearchDiagnosticStatements = new WeakMap;
1149
+ var sessionFirstMessageSearchDiagnosticStatements = new WeakMap;
983
1150
  var messageSearchDiagnosticStatementsWithDateRange = new WeakMap;
984
1151
  var batchedMessageSearchStatements = new WeakMap;
985
1152
  var batchedFtsCountStatements = new WeakMap;
@@ -994,7 +1161,7 @@ function normalizeLimit(limit) {
994
1161
  if (typeof limit !== "number" || !Number.isFinite(limit)) {
995
1162
  return DEFAULT_UNIFIED_SEARCH_LIMIT;
996
1163
  }
997
- return Math.max(1, Math.floor(limit));
1164
+ return Math.min(MAX_UNIFIED_SEARCH_LIMIT, Math.max(1, Math.floor(limit)));
998
1165
  }
999
1166
  function normalizeDateRange(from, to) {
1000
1167
  if (from === undefined && to === undefined)
@@ -1075,19 +1242,21 @@ function sourceNamesForSearchMemories(args) {
1075
1242
  }
1076
1243
  return sourceNames.size > 0 ? sourceNames : undefined;
1077
1244
  }
1078
- function getMessageSearchStatement(db) {
1079
- let stmt = messageSearchStatements.get(db);
1245
+ function getMessageSearchStatement(db, sessionFirst) {
1246
+ const statements = sessionFirst ? sessionFirstMessageSearchStatements : messageSearchStatements;
1247
+ let stmt = statements.get(db);
1080
1248
  if (!stmt) {
1081
- stmt = db.prepare("SELECT message_ordinal AS messageOrdinal, message_id AS messageId, role, content FROM message_history_fts WHERE session_id = ? AND message_history_fts MATCH ? ORDER BY bm25(message_history_fts), CAST(message_ordinal AS INTEGER) ASC LIMIT ?");
1082
- messageSearchStatements.set(db, stmt);
1249
+ stmt = db.prepare(`SELECT message_ordinal AS messageOrdinal, message_id AS messageId, role, content FROM message_history_fts WHERE ${sessionFirst ? MESSAGE_FTS_SESSION_FILTER_SQL : ""}session_id = ?1 AND message_history_fts MATCH ? ORDER BY bm25(message_history_fts), CAST(message_ordinal AS INTEGER) ASC LIMIT ?`);
1250
+ statements.set(db, stmt);
1083
1251
  }
1084
1252
  return stmt;
1085
1253
  }
1086
- function getMessageSearchStatementWithCutoff(db) {
1087
- let stmt = messageSearchStatementsWithCutoff.get(db);
1254
+ function getMessageSearchStatementWithCutoff(db, sessionFirst) {
1255
+ const statements = sessionFirst ? sessionFirstMessageSearchStatementsWithCutoff : messageSearchStatementsWithCutoff;
1256
+ let stmt = statements.get(db);
1088
1257
  if (!stmt) {
1089
- stmt = db.prepare("SELECT message_ordinal AS messageOrdinal, message_id AS messageId, role, content FROM message_history_fts WHERE session_id = ? AND message_history_fts MATCH ? AND CAST(message_ordinal AS INTEGER) <= ? ORDER BY bm25(message_history_fts), CAST(message_ordinal AS INTEGER) ASC LIMIT ?");
1090
- messageSearchStatementsWithCutoff.set(db, stmt);
1258
+ stmt = db.prepare(`SELECT message_ordinal AS messageOrdinal, message_id AS messageId, role, content FROM message_history_fts WHERE ${sessionFirst ? MESSAGE_FTS_SESSION_FILTER_SQL : ""}session_id = ?1 AND message_history_fts MATCH ? AND CAST(message_ordinal AS INTEGER) <= ? ORDER BY bm25(message_history_fts), CAST(message_ordinal AS INTEGER) ASC LIMIT ?`);
1259
+ statements.set(db, stmt);
1091
1260
  }
1092
1261
  return stmt;
1093
1262
  }
@@ -1108,9 +1277,9 @@ function getMessageSearchStatementWithDateRange(db, withCutoff) {
1108
1277
  JOIN message_fts_rowid_map AS map
1109
1278
  ON map.session_id = message_history_fts.session_id
1110
1279
  AND map.fts_rowid = message_history_fts.rowid
1111
- WHERE message_history_fts.session_id = ?
1112
- AND message_history_fts MATCH ?
1113
- AND map.message_time_ms BETWEEN ? AND ?
1280
+ WHERE ${MESSAGE_FTS_SESSION_FILTER_SQL}message_history_fts.session_id = ?1
1281
+ AND message_history_fts MATCH ?
1282
+ AND map.message_time_ms BETWEEN ? AND ?
1114
1283
  ${withCutoff ? "AND CAST(message_history_fts.message_ordinal AS INTEGER) <= ?" : ""}
1115
1284
  ORDER BY bm25(message_history_fts),
1116
1285
  CAST(message_history_fts.message_ordinal AS INTEGER) ASC
@@ -1119,8 +1288,9 @@ function getMessageSearchStatementWithDateRange(db, withCutoff) {
1119
1288
  }
1120
1289
  return statement;
1121
1290
  }
1122
- function getMessageSearchDiagnosticStatement(db) {
1123
- let stmt = messageSearchDiagnosticStatements.get(db);
1291
+ function getMessageSearchDiagnosticStatement(db, sessionFirst) {
1292
+ const statements = sessionFirst ? sessionFirstMessageSearchDiagnosticStatements : messageSearchDiagnosticStatements;
1293
+ let stmt = statements.get(db);
1124
1294
  if (!stmt) {
1125
1295
  stmt = db.prepare(`
1126
1296
  WITH matches AS MATERIALIZED (
@@ -1132,7 +1302,7 @@ function getMessageSearchDiagnosticStatement(db) {
1132
1302
  CAST(message_ordinal AS INTEGER) AS ordinalValue,
1133
1303
  bm25(message_history_fts) AS ftsRank
1134
1304
  FROM message_history_fts
1135
- WHERE session_id = ? AND message_history_fts MATCH ?
1305
+ WHERE ${sessionFirst ? MESSAGE_FTS_SESSION_FILTER_SQL : ""}session_id = ?1 AND message_history_fts MATCH ?
1136
1306
  ),
1137
1307
  eligible AS (
1138
1308
  SELECT * FROM matches
@@ -1160,7 +1330,7 @@ function getMessageSearchDiagnosticStatement(db) {
1160
1330
  WHERE NOT EXISTS (SELECT 1 FROM eligible)
1161
1331
  ORDER BY summaryOnly ASC, ftsRank ASC, messageOrdinal ASC
1162
1332
  `);
1163
- messageSearchDiagnosticStatements.set(db, stmt);
1333
+ statements.set(db, stmt);
1164
1334
  }
1165
1335
  return stmt;
1166
1336
  }
@@ -1180,9 +1350,9 @@ function getMessageSearchDiagnosticStatementWithDateRange(db) {
1180
1350
  JOIN message_fts_rowid_map AS map
1181
1351
  ON map.session_id = message_history_fts.session_id
1182
1352
  AND map.fts_rowid = message_history_fts.rowid
1183
- WHERE message_history_fts.session_id = ?
1184
- AND message_history_fts MATCH ?
1185
- AND map.message_time_ms BETWEEN ? AND ?
1353
+ WHERE ${MESSAGE_FTS_SESSION_FILTER_SQL}message_history_fts.session_id = ?1
1354
+ AND message_history_fts MATCH ?
1355
+ AND map.message_time_ms BETWEEN ? AND ?
1186
1356
  ),
1187
1357
  eligible AS (
1188
1358
  SELECT * FROM matches
@@ -1214,13 +1384,13 @@ function getMessageSearchDiagnosticStatementWithDateRange(db) {
1214
1384
  }
1215
1385
  return statement;
1216
1386
  }
1217
- function getBatchedFtsCountStatement(db, queryCount, cutoff, dateRange) {
1387
+ function getBatchedFtsCountStatement(db, queryCount, cutoff, dateRange, sessionFirst) {
1218
1388
  let statements = batchedFtsCountStatements.get(db);
1219
1389
  if (!statements) {
1220
1390
  statements = new Map;
1221
1391
  batchedFtsCountStatements.set(db, statements);
1222
1392
  }
1223
- const key = `${queryCount}:${cutoff === null ? "all" : "cutoff"}:${dateRange === null ? "all-dates" : "dated"}`;
1393
+ const key = `${queryCount}:${cutoff === null ? "all" : "cutoff"}:${dateRange === null ? "all-dates" : "dated"}:${sessionFirst}`;
1224
1394
  let statement = statements.get(key);
1225
1395
  if (!statement) {
1226
1396
  const cutoffSql = cutoff === null ? "" : " AND CAST(message_history_fts.message_ordinal AS INTEGER) <= ?";
@@ -1230,27 +1400,30 @@ function getBatchedFtsCountStatement(db, queryCount, cutoff, dateRange) {
1230
1400
  const dateSql = dateRange === null ? "" : " AND map.message_time_ms BETWEEN ? AND ?";
1231
1401
  statement = db.prepare(Array.from({ length: queryCount }, (_, index) => `SELECT ${index} AS queryIndex, COUNT(*) AS count
1232
1402
  FROM message_history_fts${joinSql}
1233
- WHERE message_history_fts.session_id = ?
1234
- AND message_history_fts MATCH ?${dateSql}${cutoffSql}`).join(`
1403
+ WHERE ${sessionFirst || dateRange !== null ? MESSAGE_FTS_SESSION_FILTER_SQL : ""}message_history_fts.session_id = ${index === 0 ? "?1" : "?"}
1404
+ AND message_history_fts MATCH ?${dateSql}${cutoffSql}`).join(`
1235
1405
  UNION ALL
1236
1406
  `));
1237
1407
  statements.set(key, statement);
1238
1408
  }
1239
1409
  return statement;
1240
1410
  }
1241
- function countSessionFtsMatchesBatch(db, sessionId, ftsQueries, cutoff, dateRange) {
1411
+ function contentOnlyMessageQuery(ftsQuery) {
1412
+ return ftsQuery.length === 0 ? "" : `content : (${ftsQuery})`;
1413
+ }
1414
+ function countSessionFtsMatchesBatch(db, sessionId, ftsQueries, cutoff, dateRange, sessionFirst) {
1242
1415
  if (ftsQueries.length === 0)
1243
1416
  return [];
1244
1417
  const bindings = [];
1245
1418
  for (const query of ftsQueries) {
1246
- bindings.push(sessionId, query);
1419
+ bindings.push(sessionId, contentOnlyMessageQuery(query));
1247
1420
  if (dateRange !== null)
1248
1421
  bindings.push(dateRange.from, dateRange.to);
1249
1422
  if (cutoff !== null)
1250
1423
  bindings.push(cutoff);
1251
1424
  }
1252
1425
  try {
1253
- const rows = getBatchedFtsCountStatement(db, ftsQueries.length, cutoff, dateRange).all(...bindings);
1426
+ const rows = getBatchedFtsCountStatement(db, ftsQueries.length, cutoff, dateRange, sessionFirst).all(...bindings);
1254
1427
  const counts = Array.from({ length: ftsQueries.length }, () => 0);
1255
1428
  for (const row of rows) {
1256
1429
  if (typeof row.queryIndex === "number" && row.queryIndex >= 0 && row.queryIndex < counts.length && typeof row.count === "number") {
@@ -1347,10 +1520,8 @@ function selectSemanticCandidates(args) {
1347
1520
  if (args.queryModelId && args.queryModelId !== "off") {
1348
1521
  const embeddingProjects = args.workspace?.isWorkspaced ? args.workspace.identities : [args.projectPath];
1349
1522
  for (const projectPath of embeddingProjects) {
1350
- const cachedEmbeddings = peekProjectEmbeddings(projectPath, args.queryModelId);
1351
- if (!cachedEmbeddings)
1352
- continue;
1353
- for (const memoryId of cachedEmbeddings.keys()) {
1523
+ const storedEmbeddings = getProjectEmbeddings(args.db, projectPath, args.queryModelId);
1524
+ for (const memoryId of storedEmbeddings.keys()) {
1354
1525
  candidateIds.add(memoryId);
1355
1526
  }
1356
1527
  }
@@ -1427,6 +1598,7 @@ async function searchMemories(args) {
1427
1598
  });
1428
1599
  const ftsScores = getFtsScores(ftsMatches);
1429
1600
  const semanticCandidates = selectSemanticCandidates({
1601
+ db: args.db,
1430
1602
  memories,
1431
1603
  projectPath: args.projectPath,
1432
1604
  ftsMatches,
@@ -1481,18 +1653,19 @@ function normalizeMessageSearchRow(row, cutoff) {
1481
1653
  content: row.content
1482
1654
  };
1483
1655
  }
1484
- function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff, dateRange) {
1656
+ function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff, dateRange, sessionFirst) {
1485
1657
  if (ftsQuery.length === 0)
1486
1658
  return [];
1487
1659
  let rawRows;
1660
+ const matchQuery = contentOnlyMessageQuery(ftsQuery);
1488
1661
  if (dateRange !== null) {
1489
- const bindings = [sessionId, ftsQuery, dateRange.from, dateRange.to];
1662
+ const bindings = [sessionId, matchQuery, dateRange.from, dateRange.to];
1490
1663
  if (cutoff !== null)
1491
1664
  bindings.push(cutoff);
1492
1665
  bindings.push(fetchLimit);
1493
1666
  rawRows = getMessageSearchStatementWithDateRange(db, cutoff !== null).all(...bindings);
1494
1667
  } else {
1495
- rawRows = cutoff !== null ? getMessageSearchStatementWithCutoff(db).all(sessionId, ftsQuery, cutoff, fetchLimit) : getMessageSearchStatement(db).all(sessionId, ftsQuery, fetchLimit);
1668
+ rawRows = cutoff !== null ? getMessageSearchStatementWithCutoff(db, sessionFirst).all(sessionId, matchQuery, cutoff, fetchLimit) : getMessageSearchStatement(db, sessionFirst).all(sessionId, matchQuery, fetchLimit);
1496
1669
  }
1497
1670
  const rows = rawRows.map((row) => row);
1498
1671
  const result = [];
@@ -1506,7 +1679,8 @@ function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff, dateRan
1506
1679
  function runMessageFtsQueryWithDiagnostics(args) {
1507
1680
  if (args.ftsQuery.length === 0)
1508
1681
  return { rows: [], suppressedCount: 0 };
1509
- const rawRows = (args.dateRange === null ? getMessageSearchDiagnosticStatement(args.db).all(args.sessionId, args.ftsQuery, args.cutoff, args.fetchLimit, args.cutoff) : getMessageSearchDiagnosticStatementWithDateRange(args.db).all(args.sessionId, args.ftsQuery, args.dateRange.from, args.dateRange.to, args.cutoff, args.fetchLimit, args.cutoff)).map((row) => row);
1682
+ const matchQuery = contentOnlyMessageQuery(args.ftsQuery);
1683
+ const rawRows = (args.dateRange === null ? getMessageSearchDiagnosticStatement(args.db, args.sessionFirst).all(args.sessionId, matchQuery, args.cutoff, args.fetchLimit, args.cutoff) : getMessageSearchDiagnosticStatementWithDateRange(args.db).all(args.sessionId, matchQuery, args.dateRange.from, args.dateRange.to, args.cutoff, args.fetchLimit, args.cutoff)).map((row) => row);
1510
1684
  const suppressedCount = rawRows[0]?.suppressedCount ?? 0;
1511
1685
  const rows = [];
1512
1686
  for (const row of rawRows) {
@@ -1518,13 +1692,13 @@ function runMessageFtsQueryWithDiagnostics(args) {
1518
1692
  }
1519
1693
  return { rows, suppressedCount };
1520
1694
  }
1521
- function getBatchedMessageSearchStatement(db, queryCount, cutoff, dateRange) {
1695
+ function getBatchedMessageSearchStatement(db, queryCount, cutoff, dateRange, sessionFirst) {
1522
1696
  let statements = batchedMessageSearchStatements.get(db);
1523
1697
  if (!statements) {
1524
1698
  statements = new Map;
1525
1699
  batchedMessageSearchStatements.set(db, statements);
1526
1700
  }
1527
- const key = `${queryCount}:${cutoff === null ? "all" : "cutoff"}:${dateRange === null ? "all-dates" : "dated"}`;
1701
+ const key = `${queryCount}:${cutoff === null ? "all" : "cutoff"}:${dateRange === null ? "all-dates" : "dated"}:${sessionFirst}`;
1528
1702
  let statement = statements.get(key);
1529
1703
  if (!statement) {
1530
1704
  const cutoffSql = cutoff === null ? "" : " AND CAST(message_history_fts.message_ordinal AS INTEGER) <= ?";
@@ -1540,8 +1714,8 @@ function getBatchedMessageSearchStatement(db, queryCount, cutoff, dateRange) {
1540
1714
  message_history_fts.content AS content,
1541
1715
  bm25(message_history_fts) AS ftsRank
1542
1716
  FROM message_history_fts${joinSql}
1543
- WHERE message_history_fts.session_id = ?
1544
- AND message_history_fts MATCH ?${dateSql}${cutoffSql}
1717
+ WHERE ${sessionFirst || dateRange !== null ? MESSAGE_FTS_SESSION_FILTER_SQL : ""}message_history_fts.session_id = ${index === 0 ? "?1" : "?"}
1718
+ AND message_history_fts MATCH ?${dateSql}${cutoffSql}
1545
1719
  ORDER BY ftsRank
1546
1720
  LIMIT ?
1547
1721
  )`);
@@ -1553,19 +1727,19 @@ ORDER BY queryIndex ASC, ftsRank ASC`);
1553
1727
  }
1554
1728
  return statement;
1555
1729
  }
1556
- function runMessageFtsQueriesBatch(db, sessionId, ftsQueries, fetchLimit, cutoff, dateRange) {
1730
+ function runMessageFtsQueriesBatch(db, sessionId, ftsQueries, fetchLimit, cutoff, dateRange, sessionFirst) {
1557
1731
  if (ftsQueries.length === 0)
1558
1732
  return [];
1559
1733
  const bindings = [];
1560
1734
  for (const query of ftsQueries) {
1561
- bindings.push(sessionId, query);
1735
+ bindings.push(sessionId, contentOnlyMessageQuery(query));
1562
1736
  if (dateRange !== null)
1563
1737
  bindings.push(dateRange.from, dateRange.to);
1564
1738
  if (cutoff !== null)
1565
1739
  bindings.push(cutoff);
1566
1740
  bindings.push(fetchLimit);
1567
1741
  }
1568
- const rows = getBatchedMessageSearchStatement(db, ftsQueries.length, cutoff, dateRange).all(...bindings);
1742
+ const rows = getBatchedMessageSearchStatement(db, ftsQueries.length, cutoff, dateRange, sessionFirst).all(...bindings);
1569
1743
  const result = Array.from({ length: ftsQueries.length }, () => []);
1570
1744
  for (const row of rows) {
1571
1745
  if (typeof row.queryIndex !== "number" || row.queryIndex < 0 || row.queryIndex >= result.length) {
@@ -1586,6 +1760,9 @@ function probeDiscriminationWeight(df, corpusSize) {
1586
1760
  return 1 / (1 + IDF_FALLOFF * df / corpusSize);
1587
1761
  }
1588
1762
  function searchMessages(args) {
1763
+ return withMessageFtsSessionFilter(args.db, args.sessionId, (sessionFirst) => searchMessagesInSnapshot(args, sessionFirst));
1764
+ }
1765
+ function searchMessagesInSnapshot(args, sessionFirst) {
1589
1766
  const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
1590
1767
  const fetchLimit = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.limit * 3 : args.limit;
1591
1768
  const baseQuery = sanitizeFtsQuery(args.query.trim());
@@ -1597,15 +1774,16 @@ function searchMessages(args) {
1597
1774
  ftsQuery: baseQuery,
1598
1775
  fetchLimit,
1599
1776
  cutoff,
1600
- dateRange: args.dateRange
1777
+ dateRange: args.dateRange,
1778
+ sessionFirst
1601
1779
  }) : {
1602
- rows: runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff, args.dateRange),
1780
+ rows: runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff, args.dateRange, sessionFirst),
1603
1781
  suppressedCount: 0
1604
1782
  };
1605
1783
  if (args.diagnostics) {
1606
1784
  args.diagnostics.suppressedLiveMessageMatches = outcome.suppressedCount;
1607
1785
  }
1608
- const rows = outcome.rows.length > 0 || !args.relaxedRecall ? outcome.rows : runMessageFtsQuery(args.db, args.sessionId, relaxedFtsQuery(args.query), fetchLimit, cutoff, args.dateRange);
1786
+ const rows = outcome.rows.length > 0 || !args.relaxedRecall ? outcome.rows : runMessageFtsQuery(args.db, args.sessionId, relaxedFtsQuery(args.query), fetchLimit, cutoff, args.dateRange, sessionFirst);
1609
1787
  const filtered = rows.slice(0, args.limit);
1610
1788
  return filtered.map((row, rank) => ({
1611
1789
  source: "message",
@@ -1618,7 +1796,7 @@ function searchMessages(args) {
1618
1796
  }
1619
1797
  const sanitizedProbes = probes.map((probe) => ({ probe, query: sanitizeFtsQuery(probe) })).filter((entry) => entry.query.length > 0);
1620
1798
  const corpusSize = getIndexedMessageCorpusSize(args.db, args.sessionId, cutoff);
1621
- const probeCounts = countSessionFtsMatchesBatch(args.db, args.sessionId, sanitizedProbes.map((entry) => entry.query), cutoff, args.dateRange);
1799
+ const probeCounts = countSessionFtsMatchesBatch(args.db, args.sessionId, sanitizedProbes.map((entry) => entry.query), cutoff, args.dateRange, sessionFirst);
1622
1800
  const collectBaseDiagnostics = args.diagnostics !== undefined && cutoff !== null;
1623
1801
  const baseOutcome = collectBaseDiagnostics && baseQuery.length > 0 ? runMessageFtsQueryWithDiagnostics({
1624
1802
  db: args.db,
@@ -1626,7 +1804,8 @@ function searchMessages(args) {
1626
1804
  ftsQuery: baseQuery,
1627
1805
  fetchLimit,
1628
1806
  cutoff,
1629
- dateRange: args.dateRange
1807
+ dateRange: args.dateRange,
1808
+ sessionFirst
1630
1809
  }) : null;
1631
1810
  if (args.diagnostics) {
1632
1811
  args.diagnostics.suppressedLiveMessageMatches = baseOutcome?.suppressedCount ?? 0;
@@ -1635,7 +1814,7 @@ function searchMessages(args) {
1635
1814
  ...!collectBaseDiagnostics && baseQuery.length > 0 ? [baseQuery] : [],
1636
1815
  ...sanitizedProbes.map((entry) => entry.query)
1637
1816
  ];
1638
- const rowsByQuery = runMessageFtsQueriesBatch(args.db, args.sessionId, searchQueries, fetchLimit, cutoff, args.dateRange);
1817
+ const rowsByQuery = runMessageFtsQueriesBatch(args.db, args.sessionId, searchQueries, fetchLimit, cutoff, args.dateRange, sessionFirst);
1639
1818
  const queryLists = [];
1640
1819
  let queryIndex = 0;
1641
1820
  if (baseQuery.length > 0) {
@@ -2077,7 +2256,7 @@ function resolveMemoriesByIdsForSearch(args) {
2077
2256
  async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
2078
2257
  const trimmedQuery = query.trim();
2079
2258
  const measurementStartedAt = Date.now();
2080
- if (trimmedQuery.length === 0) {
2259
+ if (trimmedQuery.length === 0 || options.signal?.aborted) {
2081
2260
  return [];
2082
2261
  }
2083
2262
  const limit = normalizeLimit(options.limit);
@@ -2109,6 +2288,8 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
2109
2288
  return null;
2110
2289
  }) : Promise.resolve(null);
2111
2290
  await Promise.resolve();
2291
+ if (options.signal?.aborted)
2292
+ return [];
2112
2293
  const messageProbes = options.explicitSearch ? extractLiteralProbes(trimmedQuery) : [];
2113
2294
  const messageResults = runMessages ? searchMessages({
2114
2295
  db,
@@ -2122,6 +2303,8 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
2122
2303
  dateRange
2123
2304
  }) : [];
2124
2305
  const capturedQuery = await queryEmbeddingPromise;
2306
+ if (options.signal?.aborted)
2307
+ return [];
2125
2308
  const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
2126
2309
  const queryContract = capturedQuery instanceof Float32Array || capturedQuery === null ? null : capturedQuery;
2127
2310
  const generationIsCurrent = queryContract === null || embeddingSnapshot !== null && embeddingSnapshot.generation === queryContract.generation;
@@ -2348,34 +2531,169 @@ ${bodyParts.join(`
2348
2531
  `)}`;
2349
2532
  }
2350
2533
 
2534
+ // src/hooks/magic-context/auto-search-deadline.ts
2535
+ var AUTO_SEARCH_TIMEOUT_MS = 3000;
2536
+ async function withAutoSearchDeadline(operation, startedAt = performance.now()) {
2537
+ const deadline = startedAt + AUTO_SEARCH_TIMEOUT_MS;
2538
+ const remaining = deadline - performance.now();
2539
+ if (remaining <= 0)
2540
+ return null;
2541
+ const controller = new AbortController;
2542
+ const checkDeadline = () => {
2543
+ if (!controller.signal.aborted && performance.now() >= deadline)
2544
+ controller.abort();
2545
+ return controller.signal.aborted;
2546
+ };
2547
+ let timer;
2548
+ const timeout = new Promise((resolve) => {
2549
+ timer = setTimeout(() => {
2550
+ resolve(null);
2551
+ controller.abort();
2552
+ }, remaining);
2553
+ });
2554
+ try {
2555
+ return await Promise.race([
2556
+ Promise.resolve().then(() => operation(controller.signal, checkDeadline)).then((result) => {
2557
+ if (checkDeadline()) {
2558
+ return null;
2559
+ }
2560
+ return result;
2561
+ }),
2562
+ timeout
2563
+ ]);
2564
+ } finally {
2565
+ if (timer !== undefined)
2566
+ clearTimeout(timer);
2567
+ }
2568
+ }
2569
+
2351
2570
  // src/hooks/magic-context/caveman.ts
2352
- var PRESERVATION_PATTERNS = [
2571
+ var PRESERVATION_PATTERNS_BEFORE_PATHS = [
2353
2572
  /```[\s\S]*?```/g,
2354
2573
  /`[^`\n]+`/g,
2355
2574
  /https?:\/\/\S+/g,
2356
- /§\d+§/g,
2357
- /\b(?:msg|ses|toolu)_[A-Za-z0-9]+/g,
2358
- /(?:\.{1,2}\/)?(?:[\w.-]+\/)+[\w.-]+\.\w{1,6}/g,
2359
- /(?<![a-z0-9])[0-9a-f]{7,40}(?![a-z0-9])/gi
2575
+ /§\d+§/g
2360
2576
  ];
2361
- function protectRegions(text) {
2577
+ var ASCII_IDENTIFIER_PATTERN = /\b(?:msg|ses|toolu)_[A-Za-z0-9]+/g;
2578
+ var COMMIT_HASH_PATTERN = /(?<![a-z0-9])[0-9a-f]{7,40}(?![a-z0-9])/gi;
2579
+ var PLACEHOLDER_OPEN = "\x00MC_PRES_";
2580
+ function isPathSegmentCode(code) {
2581
+ return isAsciiWordCode(code) || code === 46 || code === 45;
2582
+ }
2583
+ function isAsciiWordCode(code) {
2584
+ return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 95;
2585
+ }
2586
+ function fileNameTailEnd(text, start, end) {
2587
+ for (let dot = end - 2;dot > start; dot -= 1) {
2588
+ if (text.charCodeAt(dot) !== 46 || !isAsciiWordCode(text.charCodeAt(dot + 1)))
2589
+ continue;
2590
+ let tailEnd = dot + 1;
2591
+ while (tailEnd < end && tailEnd - dot <= 6 && isAsciiWordCode(text.charCodeAt(tailEnd))) {
2592
+ tailEnd += 1;
2593
+ }
2594
+ return tailEnd;
2595
+ }
2596
+ return -1;
2597
+ }
2598
+ function findFilePathMatches(text) {
2599
+ const matches = [];
2600
+ const length = text.length;
2601
+ let position = 0;
2602
+ while (position < length) {
2603
+ if (!isPathSegmentCode(text.charCodeAt(position))) {
2604
+ position += 1;
2605
+ continue;
2606
+ }
2607
+ const segments = [];
2608
+ let segmentStart = position;
2609
+ for (;; ) {
2610
+ let segmentEnd = segmentStart;
2611
+ while (segmentEnd < length && isPathSegmentCode(text.charCodeAt(segmentEnd))) {
2612
+ segmentEnd += 1;
2613
+ }
2614
+ segments.push([segmentStart, segmentEnd]);
2615
+ if (segmentEnd + 1 < length && text.charCodeAt(segmentEnd) === 47 && isPathSegmentCode(text.charCodeAt(segmentEnd + 1))) {
2616
+ segmentStart = segmentEnd + 1;
2617
+ continue;
2618
+ }
2619
+ break;
2620
+ }
2621
+ for (let index = segments.length - 1;index >= 1; index -= 1) {
2622
+ const tailEnd = fileNameTailEnd(text, segments[index][0], segments[index][1]);
2623
+ if (tailEnd >= 0) {
2624
+ matches.push([position, tailEnd]);
2625
+ break;
2626
+ }
2627
+ }
2628
+ position = segments[segments.length - 1][1];
2629
+ }
2630
+ return matches;
2631
+ }
2632
+ function protectRegions(text, identifierPattern) {
2362
2633
  const preserved = [];
2634
+ const placeholderFor = (original) => {
2635
+ const placeholder = `\x00MC_PRES_${preserved.length}\x00`;
2636
+ preserved.push({ placeholder, original });
2637
+ return placeholder;
2638
+ };
2363
2639
  let working = text;
2364
- for (const pattern of PRESERVATION_PATTERNS) {
2365
- working = working.replace(pattern, (match) => {
2366
- const placeholder = `\x00MC_PRES_${preserved.length}\x00`;
2367
- preserved.push({ placeholder, original: match });
2368
- return placeholder;
2369
- });
2640
+ for (const pattern of PRESERVATION_PATTERNS_BEFORE_PATHS) {
2641
+ working = working.replace(pattern, (match) => placeholderFor(match));
2370
2642
  }
2643
+ working = working.replace(identifierPattern, (match) => placeholderFor(match));
2644
+ const pathMatches = findFilePathMatches(working);
2645
+ if (pathMatches.length > 0) {
2646
+ let rebuilt = "";
2647
+ let cursor = 0;
2648
+ for (const [start, end] of pathMatches) {
2649
+ rebuilt += working.slice(cursor, start) + placeholderFor(working.slice(start, end));
2650
+ cursor = end;
2651
+ }
2652
+ working = rebuilt + working.slice(cursor);
2653
+ }
2654
+ working = working.replace(COMMIT_HASH_PATTERN, (match) => placeholderFor(match));
2371
2655
  return { text: working, preserved };
2372
2656
  }
2373
- function restoreRegions(text, preserved) {
2374
- let working = text;
2375
- for (let i = preserved.length - 1;i >= 0; i--) {
2376
- working = working.split(preserved[i].placeholder).join(preserved[i].original);
2657
+ function restoreRegions(text, preserved, sourceHasNul) {
2658
+ if (preserved.length === 0)
2659
+ return text;
2660
+ if (sourceHasNul) {
2661
+ let working = text;
2662
+ for (let i = preserved.length - 1;i >= 0; i--) {
2663
+ working = working.split(preserved[i].placeholder).join(preserved[i].original);
2664
+ }
2665
+ return working;
2377
2666
  }
2378
- return working;
2667
+ const expanded = new Map;
2668
+ const expand = (value) => {
2669
+ let output = "";
2670
+ let cursor = 0;
2671
+ for (;; ) {
2672
+ const start = value.indexOf(PLACEHOLDER_OPEN, cursor);
2673
+ if (start < 0)
2674
+ break;
2675
+ let end = start + PLACEHOLDER_OPEN.length;
2676
+ while (end < value.length && value.charCodeAt(end) >= 48 && value.charCodeAt(end) <= 57) {
2677
+ end += 1;
2678
+ }
2679
+ const regionIndex = Number(value.slice(start + PLACEHOLDER_OPEN.length, end));
2680
+ const region = preserved[regionIndex];
2681
+ if (end === start + PLACEHOLDER_OPEN.length || value.charCodeAt(end) !== 0 || !region) {
2682
+ output += value.slice(cursor, start + 1);
2683
+ cursor = start + 1;
2684
+ continue;
2685
+ }
2686
+ let restored = expanded.get(regionIndex);
2687
+ if (restored === undefined) {
2688
+ restored = expand(region.original);
2689
+ expanded.set(regionIndex, restored);
2690
+ }
2691
+ output += value.slice(cursor, start) + restored;
2692
+ cursor = end + 1;
2693
+ }
2694
+ return output + value.slice(cursor);
2695
+ };
2696
+ return expand(text);
2379
2697
  }
2380
2698
  var FILLER_WORDS = [
2381
2699
  "just",
@@ -2472,7 +2790,7 @@ var ULTRA_ABBREVIATIONS = {
2472
2790
  };
2473
2791
  function buildPhraseDropRegex(phrases) {
2474
2792
  const escaped = phrases.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
2475
- return new RegExp(`(\\s+)?\\b(?:${escaped.join("|")})\\b`, "gi");
2793
+ return new RegExp(`(?:(?<!\\s)\\s+)?\\b(?:${escaped.join("|")})\\b`, "gi");
2476
2794
  }
2477
2795
  function dropPhrases(text, phrases) {
2478
2796
  return text.replace(buildPhraseDropRegex(phrases), "");
@@ -2485,7 +2803,7 @@ function dropArticles(text) {
2485
2803
  function dropAuxiliaries(text) {
2486
2804
  const sorted = [...AUXILIARIES].sort((a, b) => b.length - a.length);
2487
2805
  const escaped = sorted.map((a) => a.replace(/\s+/g, "\\s+"));
2488
- const pattern = new RegExp(`\\s+\\b(?:${escaped.join("|")})\\b\\s+(?=\\w+(?:ed|en|ing|ized|ised)\\b)`, "gi");
2806
+ const pattern = new RegExp(`(?<!\\s)\\s+\\b(?:${escaped.join("|")})\\b\\s+(?=\\w+(?:ed|en|ing|ized|ised)\\b)`, "gi");
2489
2807
  let working = text.replace(pattern, " ");
2490
2808
  working = working.replace(/ +/g, " ");
2491
2809
  return working;
@@ -2553,10 +2871,125 @@ function normalizeWhitespace(text) {
2553
2871
 
2554
2872
  `);
2555
2873
  }
2556
- function cavemanCompress(text, level) {
2874
+ var WORD_CHARS = "\\p{L}\\p{M}\\p{N}_";
2875
+ var NOT_AFTER_WORD = `(?<![${WORD_CHARS}])`;
2876
+ var NOT_BEFORE_WORD = `(?![${WORD_CHARS}])`;
2877
+ var HORIZONTAL_SPACE = "[^\\S\\n]";
2878
+ function escapeRegex(literal) {
2879
+ return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2880
+ }
2881
+ function asciiCaseInsensitive(literal, separator) {
2882
+ let pattern = "";
2883
+ for (const ch of literal) {
2884
+ if (separator !== undefined && ch === " ")
2885
+ pattern += separator;
2886
+ else if (/[a-z]/i.test(ch))
2887
+ pattern += `[${ch.toLowerCase()}${ch.toUpperCase()}]`;
2888
+ else
2889
+ pattern += escapeRegex(ch);
2890
+ }
2891
+ return pattern;
2892
+ }
2893
+ function unicodeWordPattern(words, separator) {
2894
+ const alternation = words.map((word) => asciiCaseInsensitive(word, separator)).join("|");
2895
+ return `${NOT_AFTER_WORD}(?:${alternation})${NOT_BEFORE_WORD}`;
2896
+ }
2897
+ var UNICODE_IDENTIFIER_PATTERN = new RegExp(`${NOT_AFTER_WORD}(?:msg|ses|toolu)_[A-Za-z0-9]+`, "gu");
2898
+ function buildUnicodePhraseDropRegex(phrases) {
2899
+ const phrase = unicodeWordPattern(phrases);
2900
+ return new RegExp(`(?<=^|\\n)(${HORIZONTAL_SPACE}*)(?:${phrase}${HORIZONTAL_SPACE}*)+` + `|(?<!${HORIZONTAL_SPACE})${HORIZONTAL_SPACE}+${phrase}` + `|${phrase}`, "gu");
2901
+ }
2902
+ var UNICODE_FILLER_DROP = buildUnicodePhraseDropRegex(FILLER_WORDS);
2903
+ var UNICODE_HEDGING_DROP = buildUnicodePhraseDropRegex(HEDGING_PHRASES);
2904
+ var UNICODE_PLEASANTRY_DROP = buildUnicodePhraseDropRegex(PLEASANTRIES);
2905
+ function dropPhrasesUnicode(text, pattern) {
2906
+ return text.replace(pattern, (_match, indentation) => indentation ?? "");
2907
+ }
2908
+ var UNICODE_ARTICLE_DROP = new RegExp(`${unicodeWordPattern(["the", "a", "an"])}${HORIZONTAL_SPACE}+`, "gu");
2909
+ function dropArticlesUnicode(text) {
2910
+ return text.replace(UNICODE_ARTICLE_DROP, "").replace(/ +/g, " ");
2911
+ }
2912
+ var UNICODE_AUXILIARY_DROP = new RegExp(`(?<!${HORIZONTAL_SPACE})${HORIZONTAL_SPACE}+` + unicodeWordPattern([...AUXILIARIES].sort((a, b) => b.length - a.length), `${HORIZONTAL_SPACE}+`) + `${HORIZONTAL_SPACE}+(?=[${WORD_CHARS}]+(?:${["ed", "en", "ing", "ized", "ised"].map((suffix) => asciiCaseInsensitive(suffix)).join("|")})${NOT_BEFORE_WORD})`, "gu");
2913
+ function dropAuxiliariesUnicode(text) {
2914
+ return text.replace(UNICODE_AUXILIARY_DROP, " ").replace(/ +/g, " ");
2915
+ }
2916
+ var UNICODE_PHRASE_SHORTENINGS = [
2917
+ ["in order to", "to"],
2918
+ ["due to the fact that", "because"],
2919
+ ["at this point in time", "now"],
2920
+ ["at the moment", "now"],
2921
+ ["in the event that", "if"],
2922
+ ["for the purpose of", "for"],
2923
+ ["with regard to", "about"],
2924
+ ["in spite of the fact that", "though"],
2925
+ ["on the grounds that", "because"],
2926
+ ["for the reason that", "because"]
2927
+ ].map(([phrase, replacement]) => [new RegExp(unicodeWordPattern([phrase]), "gu"), replacement]);
2928
+ var UNICODE_ULTRA_CONNECTIVES = [
2929
+ [new RegExp(unicodeWordPattern(["and then", "then after", "afterwards"]), "gu"), "→"],
2930
+ [new RegExp(unicodeWordPattern(["because of"]), "gu"), "//"],
2931
+ [new RegExp(unicodeWordPattern(["therefore"]), "gu"), "→"],
2932
+ [new RegExp(unicodeWordPattern(["because"]), "gu"), "//"],
2933
+ [new RegExp(unicodeWordPattern(["however"]), "gu"), "but"],
2934
+ [new RegExp(unicodeWordPattern(["furthermore"]), "gu"), "+"],
2935
+ [new RegExp(unicodeWordPattern(["additionally"]), "gu"), "+"],
2936
+ [new RegExp(unicodeWordPattern(["as well as"]), "gu"), "+"],
2937
+ [new RegExp(` ${asciiCaseInsensitive("and")} `, "gu"), " + "],
2938
+ [new RegExp(` ${asciiCaseInsensitive("or")} `, "gu"), " | "]
2939
+ ];
2940
+ var UNICODE_ULTRA_ABBREVIATIONS = Object.entries(ULTRA_ABBREVIATIONS).map(([term, abbreviation]) => [new RegExp(unicodeWordPattern([term]), "gu"), abbreviation]);
2941
+ function applyReplacements(text, replacements) {
2942
+ let working = text;
2943
+ for (const [pattern, replacement] of replacements) {
2944
+ working = working.replace(pattern, replacement);
2945
+ }
2946
+ return working;
2947
+ }
2948
+ function applyUltraAbbreviationsUnicode(text) {
2949
+ let working = text;
2950
+ for (const [pattern, abbreviation] of UNICODE_ULTRA_ABBREVIATIONS) {
2951
+ if ((working.match(pattern)?.length ?? 0) < 3)
2952
+ continue;
2953
+ working = working.replace(pattern, (match) => match[0] === match[0].toUpperCase() ? abbreviation[0].toUpperCase() + abbreviation.slice(1) : abbreviation);
2954
+ }
2955
+ return working;
2956
+ }
2957
+ var CURRENT_CAVEMAN_RULES = "unicode-v2";
2958
+ function cavemanWordRulesForLanguage(language) {
2959
+ const code = typeof language === "string" ? language.trim().toLowerCase() : "";
2960
+ if (code === "en" || code.startsWith("en-"))
2961
+ return "english";
2962
+ return isValidLanguageCode(code) ? "none" : "english";
2963
+ }
2964
+ function cavemanCompress(text, level, rules = CURRENT_CAVEMAN_RULES, wordRules = "english") {
2557
2965
  if (text.length === 0)
2558
2966
  return text;
2559
- const { text: protectedText, preserved } = protectRegions(text);
2967
+ if (rules === "ascii-v1")
2968
+ return cavemanCompressAsciiV1(text, level);
2969
+ const { text: protectedText, preserved } = protectRegions(text, UNICODE_IDENTIFIER_PATTERN);
2970
+ const transformed = transformPreservingUserLines(protectedText, (chunk) => {
2971
+ let working = chunk;
2972
+ if (wordRules === "none")
2973
+ return working;
2974
+ working = dropPhrasesUnicode(working, UNICODE_FILLER_DROP);
2975
+ working = dropPhrasesUnicode(working, UNICODE_HEDGING_DROP);
2976
+ working = dropPhrasesUnicode(working, UNICODE_PLEASANTRY_DROP);
2977
+ working = applyReplacements(working, UNICODE_PHRASE_SHORTENINGS);
2978
+ if (level === "full" || level === "ultra") {
2979
+ working = dropAuxiliariesUnicode(working);
2980
+ working = dropArticlesUnicode(working);
2981
+ }
2982
+ if (level === "ultra") {
2983
+ working = applyReplacements(working, UNICODE_ULTRA_CONNECTIVES);
2984
+ working = applyUltraAbbreviationsUnicode(working);
2985
+ }
2986
+ return working;
2987
+ });
2988
+ const normalized = normalizeWhitespace(transformed).trim();
2989
+ return restoreRegions(normalized, preserved, text.includes("\x00"));
2990
+ }
2991
+ function cavemanCompressAsciiV1(text, level) {
2992
+ const { text: protectedText, preserved } = protectRegions(text, ASCII_IDENTIFIER_PATTERN);
2560
2993
  const transformed = transformPreservingUserLines(protectedText, (chunk) => {
2561
2994
  let working = chunk;
2562
2995
  working = dropPhrases(working, FILLER_WORDS);
@@ -2573,7 +3006,7 @@ function cavemanCompress(text, level) {
2573
3006
  }
2574
3007
  return working;
2575
3008
  });
2576
- const restored = restoreRegions(transformed, preserved);
3009
+ const restored = restoreRegions(transformed, preserved, text.includes("\x00"));
2577
3010
  return normalizeWhitespace(restored).trim();
2578
3011
  }
2579
3012
 
@@ -2607,10 +3040,10 @@ function formatAge(committedAtMs) {
2607
3040
  const years = Math.floor(days / 365);
2608
3041
  return years === 1 ? "1y ago" : `${years}y ago`;
2609
3042
  }
2610
- function renderFragment(result, charCap) {
3043
+ function renderFragment(result, charCap, wordRules) {
2611
3044
  switch (result.source) {
2612
3045
  case "memory": {
2613
- const compressed = cavemanCompress(result.content, "ultra");
3046
+ const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2614
3047
  return truncate(compressed, charCap);
2615
3048
  }
2616
3049
  case "git_commit": {
@@ -2619,20 +3052,20 @@ function renderFragment(result, charCap) {
2619
3052
  return `commit ${result.shortSha} ${formatAge(result.committedAtMs)}: ${body}`;
2620
3053
  }
2621
3054
  case "message": {
2622
- const compressed = cavemanCompress(result.content, "ultra");
3055
+ const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2623
3056
  return truncate(compressed, charCap);
2624
3057
  }
2625
3058
  case "compartment": {
2626
3059
  const source = result.snippet ?? result.title;
2627
- const compressed = cavemanCompress(source, "ultra");
3060
+ const compressed = cavemanCompress(source, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2628
3061
  return truncate(compressed, charCap);
2629
3062
  }
2630
3063
  case "primer": {
2631
- const compressed = cavemanCompress(result.content, "ultra");
3064
+ const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2632
3065
  return truncate(compressed, charCap);
2633
3066
  }
2634
3067
  case "note": {
2635
- const compressed = cavemanCompress(result.content, "ultra");
3068
+ const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2636
3069
  return truncate(compressed, charCap);
2637
3070
  }
2638
3071
  }
@@ -2643,7 +3076,7 @@ function buildAutoSearchHint(results, options = {}) {
2643
3076
  const picks = results.slice(0, maxFragments);
2644
3077
  const lines = [];
2645
3078
  for (const result of picks) {
2646
- const fragment = renderFragment(result, fragmentCharCap);
3079
+ const fragment = renderFragment(result, fragmentCharCap, options.wordRules ?? "english");
2647
3080
  if (fragment.length === 0)
2648
3081
  continue;
2649
3082
  lines.push(`- ${fragment}`);
@@ -2762,30 +3195,6 @@ function appendReminderToUserMessage(message, reminder) {
2762
3195
  }
2763
3196
 
2764
3197
  // src/hooks/magic-context/auto-search-runner.ts
2765
- var AUTO_SEARCH_TIMEOUT_MS = 3000;
2766
- async function unifiedSearchWithTimeout(db, sessionId, projectPath, prompt, options, timeoutMs) {
2767
- const controller = new AbortController;
2768
- let timer;
2769
- const timeoutPromise = new Promise((resolve) => {
2770
- timer = setTimeout(() => {
2771
- controller.abort();
2772
- resolve(null);
2773
- }, timeoutMs);
2774
- });
2775
- try {
2776
- return await Promise.race([
2777
- unifiedSearch(db, sessionId, projectPath, prompt, {
2778
- ...options,
2779
- signal: controller.signal,
2780
- countRetrievals: false
2781
- }),
2782
- timeoutPromise
2783
- ]);
2784
- } finally {
2785
- if (timer !== undefined)
2786
- clearTimeout(timer);
2787
- }
2788
- }
2789
3198
  var AUTO_SEARCH_OK = { ok: true };
2790
3199
  function collectUserPromptParts(message) {
2791
3200
  let collected = "";
@@ -2846,6 +3255,7 @@ function findLatestMeaningfulUserMessage(messages) {
2846
3255
  return null;
2847
3256
  }
2848
3257
  async function runAutoSearchHint(args) {
3258
+ const startedAt = performance.now();
2849
3259
  const { sessionId, db, messages, options } = args;
2850
3260
  if (!options.enabled)
2851
3261
  return AUTO_SEARCH_OK;
@@ -2888,27 +3298,36 @@ async function runAutoSearchHint(args) {
2888
3298
  }
2889
3299
  let results;
2890
3300
  try {
2891
- if (options.directory) {
2892
- await options.ensureProjectRegistered?.(options.directory, db);
2893
- }
2894
- const embeddingSnapshot = getProjectEmbeddingSnapshot(options.projectPath);
2895
- const memoryEnabled = embeddingSnapshot?.features.memoryEnabled ?? options.memoryEnabled;
2896
- const embeddingEnabled = embeddingSnapshot ? embeddingSnapshot.historyEnabled : options.embeddingEnabled;
2897
- const gitCommitsEnabled = embeddingSnapshot?.gitCommitEnabled ?? options.gitCommitsEnabled ?? false;
2898
- const searchOptions = {
2899
- limit: 10,
2900
- memoryEnabled,
2901
- embeddingEnabled,
2902
- gitCommitsEnabled,
2903
- embedQuery: async (text, signal) => {
2904
- const result = await embedTextForProject(options.projectPath, text, signal, "query");
2905
- return result;
2906
- },
2907
- isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
2908
- visibleMemoryIds: options.visibleMemoryIds ?? null,
2909
- sources: ["memory", "message", "git_commit"]
2910
- };
2911
- results = await unifiedSearchWithTimeout(db, sessionId, options.projectPath, rawPrompt, searchOptions, AUTO_SEARCH_TIMEOUT_MS);
3301
+ results = await withAutoSearchDeadline(async (signal, checkDeadline) => {
3302
+ if (options.directory) {
3303
+ await options.ensureProjectRegistered?.(options.directory, db);
3304
+ }
3305
+ if (checkDeadline())
3306
+ return null;
3307
+ const embeddingSnapshot = getProjectEmbeddingSnapshot(options.projectPath);
3308
+ const memoryEnabled = embeddingSnapshot?.features.memoryEnabled ?? options.memoryEnabled;
3309
+ const embeddingEnabled = embeddingSnapshot ? embeddingSnapshot.historyEnabled : options.embeddingEnabled;
3310
+ const gitCommitsEnabled = embeddingSnapshot?.gitCommitEnabled ?? options.gitCommitsEnabled ?? false;
3311
+ const searchOptions = {
3312
+ limit: 10,
3313
+ memoryEnabled,
3314
+ embeddingEnabled,
3315
+ gitCommitsEnabled,
3316
+ embedQuery: async (text, signal) => {
3317
+ const result = await embedTextForProject(options.projectPath, text, signal, "query");
3318
+ checkDeadline();
3319
+ return result;
3320
+ },
3321
+ isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
3322
+ visibleMemoryIds: options.visibleMemoryIds ?? null,
3323
+ sources: ["memory", "message", "git_commit"]
3324
+ };
3325
+ return unifiedSearch(db, sessionId, options.projectPath, rawPrompt, {
3326
+ ...searchOptions,
3327
+ signal,
3328
+ countRetrievals: false
3329
+ });
3330
+ }, startedAt);
2912
3331
  } catch (error) {
2913
3332
  log(`[auto-search] unified search failed for session ${sessionId} (will retry next pass): ${error instanceof Error ? error.message : String(error)}`);
2914
3333
  return { ok: false, kind: "search-failure" };
@@ -2924,7 +3343,7 @@ async function runAutoSearchHint(args) {
2924
3343
  sessionLog(sessionId, `auto-search: top score ${results[0].score.toFixed(3)} below threshold ${options.scoreThreshold}`);
2925
3344
  return writeNoHintAndReconcile("below-threshold");
2926
3345
  }
2927
- const hintText = buildAutoSearchHint(results);
3346
+ const hintText = buildAutoSearchHint(results, { wordRules: options.wordRules });
2928
3347
  if (!hintText) {
2929
3348
  return writeNoHintAndReconcile("empty");
2930
3349
  }
@@ -3244,90 +3663,29 @@ function resolveTodowriteAvailability(sessionId) {
3244
3663
  return resolveToolAvailability(sessionId, TODOWRITE_TOOL);
3245
3664
  }
3246
3665
 
3247
- // src/hooks/magic-context/sentinel.ts
3248
- var WHOLE_MESSAGE_PLACEHOLDER_TEXT = "[dropped]";
3249
- function modelAcceptsEmptyContent(providerID) {
3250
- return providerID === "anthropic";
3251
- }
3252
- var VARIANT_CACHE_PRESERVING_MODELS = {
3253
- "anthropic/claude-fable-5-1": "2026-09-02",
3254
- "openai/gpt-6-astra": "2026-09-05",
3255
- "anthropic/claude-opus-5-5": "2026-09-23"
3256
- };
3257
- function canonicalVariantModelIdentity(providerID, modelID) {
3258
- const normalizedProviderID = providerID.toLowerCase();
3259
- const isAnthropicFamily = normalizedProviderID === "anthropic" || normalizedProviderID === "google-vertex-anthropic" || normalizedProviderID.includes("bedrock");
3260
- if (isAnthropicFamily && isFable51ThinkingBindingModel("anthropic", modelID)) {
3261
- return "anthropic/claude-fable-5-1";
3262
- }
3263
- return canonicalModelIdentity(`${providerID}/${modelID}`).toLowerCase();
3264
- }
3265
- function variantChangeBustsProviderCache(providerID, modelID) {
3266
- if (!providerID || !modelID)
3267
- return false;
3268
- const identity = canonicalVariantModelIdentity(providerID, modelID);
3269
- if (Object.hasOwn(VARIANT_CACHE_PRESERVING_MODELS, identity))
3270
- return false;
3271
- const normalizedProviderID = providerID.toLowerCase();
3272
- return normalizedProviderID === "anthropic" || normalizedProviderID === "google-vertex-anthropic" || normalizedProviderID.includes("bedrock");
3273
- }
3274
- function makeSentinel(originalPart) {
3275
- const sentinel = {
3276
- type: "text",
3277
- text: ""
3278
- };
3279
- if (isRecord(originalPart)) {
3280
- if (originalPart.cache_control !== undefined) {
3281
- sentinel.cache_control = originalPart.cache_control;
3282
- }
3283
- if (originalPart.cacheControl !== undefined) {
3284
- sentinel.cacheControl = originalPart.cacheControl;
3285
- }
3666
+ // src/hooks/magic-context/degraded-pass-refusal.ts
3667
+ class DegradedPassRefusalError extends Error {
3668
+ site;
3669
+ code = "DEGRADED_PASS_REFUSAL";
3670
+ recoverable = true;
3671
+ estimatedTokens;
3672
+ contextLimitTokens;
3673
+ constructor(site, options) {
3674
+ super(renderUserFacingFailure("transform_pass_degraded", "plain"), {
3675
+ cause: options?.cause
3676
+ });
3677
+ this.site = site;
3678
+ this.name = "DegradedPassRefusalError";
3679
+ this.estimatedTokens = options?.estimatedTokens;
3680
+ this.contextLimitTokens = options?.contextLimitTokens;
3286
3681
  }
3287
- return sentinel;
3288
3682
  }
3289
- function makeWholeMessageSentinel(providerID) {
3290
- return {
3291
- type: "text",
3292
- text: modelAcceptsEmptyContent(providerID) ? "" : WHOLE_MESSAGE_PLACEHOLDER_TEXT
3293
- };
3294
- }
3295
- function isSentinel(part) {
3296
- if (!isRecord(part))
3297
- return false;
3298
- if (part.type !== "text")
3299
- return false;
3300
- if (typeof part.text !== "string")
3301
- return false;
3302
- return part.text === "" || part.text === WHOLE_MESSAGE_PLACEHOLDER_TEXT;
3303
- }
3304
- function replaySentinelByMessageIds(messages, ids, providerID, hiddenSeamIds = new Set) {
3305
- if (ids.size === 0)
3306
- return { replayed: 0, missingIds: [] };
3307
- const seen = new Set;
3308
- let replayed = 0;
3309
- for (let index = messages.length - 1;index >= 0; index -= 1) {
3310
- const msg = messages[index];
3311
- const id = msg.info.id;
3312
- if (!id || !ids.has(id))
3313
- continue;
3314
- seen.add(id);
3315
- if (!modelAcceptsEmptyContent(providerID) && hiddenSeamIds.has(id)) {
3316
- messages.splice(index, 1);
3317
- replayed += 1;
3318
- continue;
3319
- }
3320
- if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
3321
- continue;
3322
- msg.parts.length = 0;
3323
- msg.parts.push(makeWholeMessageSentinel(providerID));
3324
- replayed += 1;
3325
- }
3326
- const missingIds = [];
3327
- for (const id of ids)
3328
- if (!seen.has(id))
3329
- missingIds.push(id);
3330
- return { replayed, missingIds };
3683
+ function degradedPassError(site, error) {
3684
+ if (error instanceof DegradedPassRefusalError)
3685
+ return error;
3686
+ if (isTransientSqliteError(error) && error instanceof Error)
3687
+ return error;
3688
+ return new DegradedPassRefusalError(site, { cause: error });
3331
3689
  }
3332
3690
 
3333
3691
  // src/hooks/magic-context/drop-stale-reduce-calls.ts
@@ -3394,7 +3752,7 @@ function dropStaleReduceCalls(messages, frozenIds, options = {}) {
3394
3752
  const message = messages[i];
3395
3753
  const id = typeof message.info.id === "string" ? message.info.id : undefined;
3396
3754
  const inFrozen = id !== undefined && frozenIds.has(id);
3397
- const isNewDetection = !inFrozen && detect && i < protectedStart && id !== undefined && messageHasReducePart(message);
3755
+ const isNewDetection = !inFrozen && detect && i < protectedStart && id !== undefined && messageHasReducePart(message) && !message.parts.some(toolPartHasUserAnswer);
3398
3756
  if (!inFrozen && !isNewDetection)
3399
3757
  continue;
3400
3758
  const touched = sentinelizeReduceParts(message);
@@ -3474,11 +3832,69 @@ function estimateDroppedTokensFromTagReductions(db, sessionId, reductions) {
3474
3832
  return Math.max(0, Math.round(total));
3475
3833
  }
3476
3834
 
3835
+ // src/hooks/magic-context/emergency-fail-closed.ts
3836
+ var ENGINE_RECONNECTING_USER_MESSAGE = "Magic Context's engine is reconnecting. Send your message again in a few seconds.";
3837
+
3838
+ class EmergencyFailClosedError extends Error {
3839
+ code = "EMERGENCY_FAIL_CLOSED";
3840
+ constructor(message, options) {
3841
+ super(message, options);
3842
+ this.name = "EmergencyFailClosedError";
3843
+ }
3844
+ }
3845
+
3477
3846
  // src/hooks/magic-context/fold-execution-gate.ts
3478
3847
  function foldExecutesThisPass(foldDue, materialized) {
3479
3848
  return foldDue && materialized;
3480
3849
  }
3481
3850
 
3851
+ // src/features/magic-context/storage-caveman-rules.ts
3852
+ var NAMESPACE2 = "caveman";
3853
+ var CURRENT_RULES_VERSION = 2;
3854
+ var ORIGINAL_RULES = {
3855
+ currentRules: false,
3856
+ englishWordRules: true,
3857
+ legacyReasoningTags: new Set
3858
+ };
3859
+ function parseState2(lane) {
3860
+ if (!isRecord(lane) || lane.rules !== CURRENT_RULES_VERSION)
3861
+ return ORIGINAL_RULES;
3862
+ const tags = Array.isArray(lane.legacyReasoningTags) ? lane.legacyReasoningTags : [];
3863
+ return {
3864
+ currentRules: true,
3865
+ englishWordRules: lane.englishWordRules !== false,
3866
+ legacyReasoningTags: new Set(tags.filter((tag) => Number.isSafeInteger(tag) && tag > 0))
3867
+ };
3868
+ }
3869
+ function getCavemanReplayState(db, sessionId) {
3870
+ try {
3871
+ return parseState2(readReplayEnvelope(db, sessionId)[NAMESPACE2]);
3872
+ } catch (error) {
3873
+ if (error instanceof ReplayDocumentError)
3874
+ return ORIGINAL_RULES;
3875
+ throw error;
3876
+ }
3877
+ }
3878
+ function recordCavemanCurrentRules(db, sessionId, englishWordRules, legacyReasoningTags) {
3879
+ const tags = [...new Set(legacyReasoningTags)].sort((a, b) => a - b);
3880
+ const persisted = updateReplayDocument(db, sessionId, (doc) => {
3881
+ const current = parseState2(doc[NAMESPACE2]);
3882
+ if (current.currentRules && current.englishWordRules === englishWordRules)
3883
+ return false;
3884
+ doc.version = 2;
3885
+ doc[NAMESPACE2] = {
3886
+ rules: CURRENT_RULES_VERSION,
3887
+ legacyReasoningTags: current.currentRules ? [...current.legacyReasoningTags].sort((a, b) => a - b) : tags,
3888
+ ...englishWordRules ? {} : { englishWordRules: false }
3889
+ };
3890
+ return true;
3891
+ });
3892
+ if (!persisted)
3893
+ return null;
3894
+ const state = getCavemanReplayState(db, sessionId);
3895
+ return state.currentRules && state.englishWordRules === englishWordRules ? state : null;
3896
+ }
3897
+
3482
3898
  // src/hooks/magic-context/caveman-cleanup.ts
3483
3899
  var DEPTH_UNTOUCHED = 0;
3484
3900
  var DEPTH_LITE = 1;
@@ -3511,10 +3927,16 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
3511
3927
  };
3512
3928
  if (!config.enabled)
3513
3929
  return result;
3930
+ const recordRewrite = (tagNumber, target, before) => {
3931
+ result.mutatedTextTags += 1;
3932
+ const after = target.getContent?.() ?? "";
3933
+ result.textReductions.push({
3934
+ tagNumber,
3935
+ removedCharacters: Math.max(0, (before?.length ?? 0) - after.length)
3936
+ });
3937
+ };
3514
3938
  const protectedCutoff = config.protectedCutoff;
3515
3939
  const eligible = tags.filter((tag) => tag.type === "message" && tag.status === "active" && (protectedCutoff === null || tag.tagNumber < protectedCutoff) && tag.byteSize >= config.minChars).sort((a, b) => a.tagNumber - b.tagNumber);
3516
- if (eligible.length === 0)
3517
- return result;
3518
3940
  const tagsNeedingCompression = eligible.filter((tag, index) => {
3519
3941
  const target = targets.get(tag.tagNumber);
3520
3942
  if (!target?.getContent || !target.setContent)
@@ -3522,7 +3944,31 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
3522
3944
  const targetDepth = computeTargetDepth(index, eligible.length);
3523
3945
  return targetDepth > tag.cavemanDepth;
3524
3946
  });
3525
- if (tagsNeedingCompression.length === 0)
3947
+ const englishWordRules = (config.wordRules ?? "english") === "english";
3948
+ let state = getCavemanReplayState(db, sessionId);
3949
+ if (!state.currentRules || state.englishWordRules !== englishWordRules) {
3950
+ const compressedBefore = tags.filter((tag) => tag.type === "message" && tag.status === "active" && tag.cavemanDepth > 0);
3951
+ const switched = recordCavemanCurrentRules(db, sessionId, englishWordRules, compressedBefore.map((tag) => tag.tagNumber));
3952
+ if (switched) {
3953
+ state = switched;
3954
+ const deepened = new Set(tagsNeedingCompression.map((tag) => tag.tagNumber));
3955
+ const rewrites = compressedBefore.filter((tag) => targets.has(tag.tagNumber) && !deepened.has(tag.tagNumber));
3956
+ const originals = getSourceContents(db, sessionId, rewrites.map((tag) => tag.tagNumber));
3957
+ for (const tag of rewrites) {
3958
+ const target = targets.get(tag.tagNumber);
3959
+ const originalText = originals.get(tag.tagNumber);
3960
+ if (!target || typeof originalText !== "string" || originalText.length === 0) {
3961
+ continue;
3962
+ }
3963
+ const before = target.getContent?.() ?? null;
3964
+ if (applyCompressedText(target, tag.tagNumber, originalText, tag.cavemanDepth, state)) {
3965
+ recordRewrite(tag.tagNumber, target, before);
3966
+ }
3967
+ }
3968
+ sessionLog(sessionId, `caveman cleanup: switched to current rules (${englishWordRules ? "English" : "language-neutral"} word rules), rewrote ${rewrites.length} compressed text tags`);
3969
+ }
3970
+ }
3971
+ if (eligible.length === 0 || tagsNeedingCompression.length === 0)
3526
3972
  return result;
3527
3973
  const originalByTag = getSourceContents(db, sessionId, tagsNeedingCompression.map((t) => t.tagNumber));
3528
3974
  const positionByTag = new Map;
@@ -3541,20 +3987,15 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
3541
3987
  const level = DEPTH_TO_LEVEL[targetDepth];
3542
3988
  if (!level)
3543
3989
  continue;
3544
- const compressed = cavemanCompress(originalText, level);
3545
- if (compressed.length === 0)
3990
+ if (cavemanCompress(originalText, level, rulesFor(state), wordRulesFor(state)).length === 0) {
3546
3991
  continue;
3992
+ }
3547
3993
  const target = targets.get(tag.tagNumber);
3548
3994
  if (!target)
3549
3995
  continue;
3550
- const priorContent = target.getContent?.();
3551
- const didMutate = target.setContent(compressed);
3552
- if (didMutate) {
3553
- result.mutatedTextTags += 1;
3554
- result.textReductions.push({
3555
- tagNumber: tag.tagNumber,
3556
- removedCharacters: Math.max(0, (priorContent?.length ?? originalText.length) - compressed.length)
3557
- });
3996
+ const priorContent = target.getContent?.() ?? originalText;
3997
+ if (applyCompressedText(target, tag.tagNumber, originalText, targetDepth, state)) {
3998
+ recordRewrite(tag.tagNumber, target, priorContent);
3558
3999
  }
3559
4000
  updateCavemanDepth(db, sessionId, tag.tagNumber, targetDepth);
3560
4001
  if (targetDepth === DEPTH_LITE)
@@ -3571,79 +4012,62 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
3571
4012
  }
3572
4013
  return result;
3573
4014
  }
4015
+ function rulesFor(state) {
4016
+ return state.currentRules ? CURRENT_CAVEMAN_RULES : "ascii-v1";
4017
+ }
4018
+ function wordRulesFor(state) {
4019
+ return state.englishWordRules ? "english" : "none";
4020
+ }
4021
+ function applyCompressedText(target, tagNumber, originalText, depth, state) {
4022
+ const level = DEPTH_TO_LEVEL[depth];
4023
+ if (!level)
4024
+ return false;
4025
+ const before = target.getContent?.();
4026
+ if (!state.currentRules || state.legacyReasoningTags.has(tagNumber)) {
4027
+ const legacy = cavemanCompress(originalText, level, "ascii-v1");
4028
+ if (!state.currentRules)
4029
+ return legacy.length > 0 && target.setContent(legacy);
4030
+ if (legacy.length > 0)
4031
+ target.setContent(legacy);
4032
+ }
4033
+ const compressed = cavemanCompress(originalText, level, CURRENT_CAVEMAN_RULES, wordRulesFor(state));
4034
+ if (compressed.length === 0)
4035
+ return false;
4036
+ target.setContent(`${target.textPrefix ?? ""}${compressed}`, { keepReasoning: true });
4037
+ return target.getContent ? target.getContent() !== before : true;
4038
+ }
3574
4039
  function replayCavemanCompression(sessionId, db, targets, tags) {
3575
4040
  const compressedTags = tags.filter((tag) => tag.type === "message" && tag.status === "active" && tag.cavemanDepth > 0 && targets.has(tag.tagNumber));
3576
4041
  if (compressedTags.length === 0)
3577
4042
  return 0;
3578
4043
  const originalByTag = getSourceContents(db, sessionId, compressedTags.map((t) => t.tagNumber));
4044
+ const state = getCavemanReplayState(db, sessionId);
3579
4045
  let replayed = 0;
3580
4046
  for (const tag of compressedTags) {
3581
4047
  const originalText = originalByTag.get(tag.tagNumber);
3582
4048
  if (typeof originalText !== "string" || originalText.length === 0)
3583
4049
  continue;
3584
- const level = DEPTH_TO_LEVEL[tag.cavemanDepth];
3585
- if (!level)
3586
- continue;
3587
- const compressed = cavemanCompress(originalText, level);
3588
- if (compressed.length === 0)
3589
- continue;
3590
4050
  const target = targets.get(tag.tagNumber);
3591
4051
  if (!target)
3592
4052
  continue;
3593
- if (target.setContent(compressed)) {
4053
+ if (applyCompressedText(target, tag.tagNumber, originalText, tag.cavemanDepth, state)) {
3594
4054
  replayed += 1;
3595
4055
  }
3596
4056
  }
3597
4057
  return replayed;
3598
4058
  }
3599
4059
 
3600
- // src/hooks/magic-context/system-injection-stripper.ts
3601
- var SYSTEM_INJECTION_MARKERS = [
3602
- "<!-- OMO_INTERNAL_INITIATOR -->",
3603
- "[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
3604
- "[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
3605
- "[Category+Skill Reminder]",
3606
- "[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
3607
- "[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
3608
- "[EMERGENCY CONTEXT WINDOW WARNING]",
3609
- "Unstable background agent appears idle",
3610
- "**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
3611
- ];
3612
- var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
3613
- var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
3614
- function stripSystemInjection(text) {
3615
- let hasInjection = false;
3616
- for (const marker of SYSTEM_INJECTION_MARKERS) {
3617
- if (text.includes(marker)) {
3618
- hasInjection = true;
3619
- break;
3620
- }
3621
- }
3622
- if (SYSTEM_REMINDER_REGEX.test(text))
3623
- hasInjection = true;
3624
- SYSTEM_REMINDER_REGEX.lastIndex = 0;
3625
- if (!hasInjection)
3626
- return null;
3627
- let cleaned = text;
3628
- cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
3629
- cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
3630
- cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
3631
- for (const marker of SYSTEM_INJECTION_MARKERS) {
3632
- if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
3633
- continue;
3634
- const idx = cleaned.indexOf(marker);
3635
- if (idx === -1)
3636
- continue;
3637
- const blockEnd = cleaned.indexOf(`
3638
-
3639
- `, idx + marker.length);
3640
- cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
3641
- }
3642
- return cleaned.trim();
3643
- }
3644
-
3645
4060
  // src/hooks/magic-context/heuristic-cleanup.ts
3646
4061
  var DEDUP_SAFE_TOOLS = new Set([
4062
+ "grep",
4063
+ "read",
4064
+ "glob",
4065
+ "ast_grep_search",
4066
+ "lsp_diagnostics",
4067
+ "lsp_symbols",
4068
+ "lsp_find_references",
4069
+ "lsp_goto_definition",
4070
+ "lsp_prepare_rename",
3647
4071
  "mcp_grep",
3648
4072
  "mcp_read",
3649
4073
  "mcp_glob",
@@ -3684,7 +4108,8 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3684
4108
  ceilingTokens: emergency.ceilingTokens,
3685
4109
  usagePercentage: emergency.usagePercentage,
3686
4110
  priorInputSample,
3687
- hasPriorDrop: priorInputSample > 0
4111
+ hasPriorDrop: priorInputSample > 0,
4112
+ passAlreadyPriced: emergency.passAlreadyPriced === true
3688
4113
  });
3689
4114
  if (plan.shouldDrop) {
3690
4115
  const toDrop = new Set(plan.tagNumbers);
@@ -3759,7 +4184,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3759
4184
  }
3760
4185
  }
3761
4186
  } else {
3762
- const didSet = target.setContent(stripped);
4187
+ const didSet = target.setContent(stripped, { keepReasoning: true });
3763
4188
  if (didSet) {
3764
4189
  replaceSourceContent(db, sessionId, tag.tagNumber, strippedSource);
3765
4190
  droppedInjections++;
@@ -3786,7 +4211,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3786
4211
  const fingerprintGroups = new Map;
3787
4212
  for (const [compositeKey, fingerprint] of toolFingerprints) {
3788
4213
  const tag = tagsByCompositeKey.get(compositeKey);
3789
- if (!tag || config.protectedTagNumbers.has(tag.tagNumber))
4214
+ if (!tag)
3790
4215
  continue;
3791
4216
  const group = fingerprintGroups.get(fingerprint) ?? [];
3792
4217
  group.push(tag);
@@ -3799,7 +4224,11 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3799
4224
  group.sort((a, b) => a.tagNumber - b.tagNumber);
3800
4225
  for (let i = 0;i < group.length - 1; i++) {
3801
4226
  const tag = group[i];
4227
+ if (config.protectedTagNumbers.has(tag.tagNumber))
4228
+ continue;
3802
4229
  const target = targets.get(tag.tagNumber);
4230
+ if (target?.canDrop?.() === false)
4231
+ continue;
3803
4232
  const { result, mode } = applyNewToolDrop(target, { inWindow: false });
3804
4233
  if (result === "incomplete")
3805
4234
  continue;
@@ -3825,6 +4254,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3825
4254
  const cavemanResult = applyCavemanCleanup(sessionId, db, targets, tags, {
3826
4255
  enabled: true,
3827
4256
  minChars: config.caveman.minChars,
4257
+ wordRules: config.caveman.wordRules,
3828
4258
  protectedCutoff: config.protectedCutoff
3829
4259
  });
3830
4260
  compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
@@ -4139,6 +4569,8 @@ function replayClearedReasoning(messages, reasoningByMessage, messageTagNumbers,
4139
4569
  if (!parts)
4140
4570
  continue;
4141
4571
  for (const tp of parts) {
4572
+ if (tp.type === "text")
4573
+ continue;
4142
4574
  if (tp.thinking !== undefined && tp.thinking !== "[cleared]") {
4143
4575
  tp.thinking = "[cleared]";
4144
4576
  cleared++;
@@ -4189,6 +4621,8 @@ function clearOldReasoning(messages, reasoningByMessage, messageTagNumbers, clea
4189
4621
  if (!parts)
4190
4622
  continue;
4191
4623
  for (const tp of parts) {
4624
+ if (tp.type === "text")
4625
+ continue;
4192
4626
  if (tp.thinking !== undefined && tp.thinking !== "[cleared]") {
4193
4627
  tp.thinking = "[cleared]";
4194
4628
  cleared++;
@@ -4480,8 +4914,9 @@ function applyFrozenTrailingBlankDecisions(messages, frozenDecisions) {
4480
4914
  return mutations;
4481
4915
  }
4482
4916
  function stripReasoningFromAssistantIds(messages, providerID, messageIds) {
4483
- if (providerID !== "anthropic" || messageIds.size === 0)
4917
+ if (messageIds.size === 0)
4484
4918
  return 0;
4919
+ const emptySentinels = modelAcceptsEmptyContent(providerID);
4485
4920
  let stripped = 0;
4486
4921
  for (const message of messages) {
4487
4922
  const id = message.info.id;
@@ -4491,9 +4926,16 @@ function stripReasoningFromAssistantIds(messages, providerID, messageIds) {
4491
4926
  const part = message.parts[index];
4492
4927
  if (!isRecord(part) || !REASONING_PART_TYPES.has(String(part.type)))
4493
4928
  continue;
4494
- message.parts[index] = makeSentinel(part);
4929
+ if (emptySentinels) {
4930
+ message.parts[index] = makeSentinel(part);
4931
+ } else {
4932
+ message.parts.splice(index, 1);
4933
+ index -= 1;
4934
+ }
4495
4935
  stripped += 1;
4496
4936
  }
4937
+ if (message.parts.length === 0)
4938
+ message.parts.push(makeWholeMessageSentinel(providerID));
4497
4939
  }
4498
4940
  return stripped;
4499
4941
  }
@@ -4591,6 +5033,135 @@ function stripProcessedImages(messages, frozenIds, options) {
4591
5033
  return { stripped, newlyStrippedIds };
4592
5034
  }
4593
5035
 
5036
+ // src/hooks/magic-context/reasoning-removal.ts
5037
+ var REMOVABLE_REASONING_TYPES = new Set(["reasoning", "thinking", "redacted_thinking"]);
5038
+ function isReasoningPart(part) {
5039
+ return isRecord(part) && REMOVABLE_REASONING_TYPES.has(String(part.type));
5040
+ }
5041
+ function isReasoningOrNeutralized(part) {
5042
+ return isReasoningPart(part) || isNeutralizedReasoningPart(part);
5043
+ }
5044
+ function hasWireContentBesideReasoning(message) {
5045
+ return message.parts.some((part) => {
5046
+ if (!isRecord(part) || part.ignored === true)
5047
+ return false;
5048
+ if (part.type === "tool" || part.type === "file")
5049
+ return true;
5050
+ return part.type === "text" && typeof part.text === "string" && part.text.trim() !== "";
5051
+ });
5052
+ }
5053
+ function newestAssistant(messages) {
5054
+ for (let index = messages.length - 1;index >= 0; index -= 1) {
5055
+ if (messages[index].info.role === "assistant")
5056
+ return messages[index];
5057
+ }
5058
+ return;
5059
+ }
5060
+ function openRouterReasoningDetails(part) {
5061
+ if (!isRecord(part) || !isRecord(part.metadata))
5062
+ return;
5063
+ const openrouter = part.metadata.openrouter;
5064
+ if (!isRecord(openrouter) || !Array.isArray(openrouter.reasoning_details))
5065
+ return;
5066
+ return openrouter.reasoning_details;
5067
+ }
5068
+ function isProtectedReasoningDetail(detail) {
5069
+ if (!isRecord(detail))
5070
+ return true;
5071
+ if (typeof detail.format !== "string")
5072
+ return true;
5073
+ return detail.format.startsWith("google-gemini");
5074
+ }
5075
+ function reasoningPayloadLeavesWithParts(message) {
5076
+ for (const part of message.parts) {
5077
+ const details = openRouterReasoningDetails(part);
5078
+ if (details?.some(isProtectedReasoningDetail))
5079
+ return false;
5080
+ }
5081
+ return true;
5082
+ }
5083
+ function stripOpenRouterReasoningDetails(message) {
5084
+ let stripped = 0;
5085
+ for (const part of message.parts) {
5086
+ if (!openRouterReasoningDetails(part))
5087
+ continue;
5088
+ const metadata = part.metadata;
5089
+ const { reasoning_details: _removed, ...rest } = metadata.openrouter;
5090
+ metadata.openrouter = rest;
5091
+ stripped += 1;
5092
+ }
5093
+ return stripped;
5094
+ }
5095
+ function selectReasoningRemovals(args) {
5096
+ let maxTag = 0;
5097
+ for (const tag of args.messageTagNumbers.values())
5098
+ if (tag > maxTag)
5099
+ maxTag = tag;
5100
+ const cutoff = maxTag - args.clearReasoningAge;
5101
+ if (maxTag === 0 || cutoff <= 0)
5102
+ return [];
5103
+ const newest = newestAssistant(args.messages);
5104
+ const exempt = findLatestAssistantReasoningMutationExemptMessage(args.messages);
5105
+ const selected = [];
5106
+ for (const message of args.messages) {
5107
+ if (message.info.role !== "assistant")
5108
+ continue;
5109
+ if (!message.parts.some(isReasoningOrNeutralized))
5110
+ continue;
5111
+ const id = typeof message.info.id === "string" && message.info.id.length > 0 ? message.info.id : undefined;
5112
+ if (id !== undefined && (args.alreadyRemoved.has(id) || args.prefixBound && args.alsoGone?.has(id)))
5113
+ continue;
5114
+ const tag = args.messageTagNumbers.get(message) ?? 0;
5115
+ const removable = id !== undefined && message !== newest && message !== exempt && tag > 0 && tag <= cutoff && hasWireContentBesideReasoning(message) && reasoningPayloadLeavesWithParts(message);
5116
+ if (removable && id !== undefined)
5117
+ selected.push(id);
5118
+ else if (args.prefixBound)
5119
+ break;
5120
+ }
5121
+ return selected;
5122
+ }
5123
+ function removeReasoningParts(messages, ids, providerID) {
5124
+ if (ids.size === 0)
5125
+ return 0;
5126
+ const exempt = findLatestAssistantReasoningMutationExemptMessage(messages);
5127
+ let removed = 0;
5128
+ for (const message of messages) {
5129
+ if (message.info.role !== "assistant" || message === exempt)
5130
+ continue;
5131
+ const id = message.info.id;
5132
+ if (typeof id !== "string" || !ids.has(id))
5133
+ continue;
5134
+ if (!reasoningPayloadLeavesWithParts(message))
5135
+ continue;
5136
+ const before = message.parts.length;
5137
+ const kept = message.parts.filter((part) => !isReasoningOrNeutralized(part));
5138
+ if (kept.length === before)
5139
+ continue;
5140
+ removed += before - kept.length;
5141
+ message.parts.length = 0;
5142
+ message.parts.push(...kept);
5143
+ stripOpenRouterReasoningDetails(message);
5144
+ if (!hasWireContentBesideReasoning(message)) {
5145
+ message.parts.push(makeWholeMessageSentinel(providerID));
5146
+ }
5147
+ }
5148
+ return removed;
5149
+ }
5150
+ function settleDroppedReasoningParts(messages, mode) {
5151
+ let settled = 0;
5152
+ for (const message of messages) {
5153
+ if (message.info.role !== "assistant")
5154
+ continue;
5155
+ for (const part of message.parts) {
5156
+ if (!isNeutralizedReasoningPart(part))
5157
+ continue;
5158
+ if (restoreNeutralizedReasoningPart(part, mode === "legacy"))
5159
+ settled += 1;
5160
+ }
5161
+ }
5162
+ return settled;
5163
+ }
5164
+
4594
5165
  // src/hooks/magic-context/supersession-reclaim.ts
4595
5166
  var TODOWRITE_KEEP = 1;
4596
5167
  var SUPERSESSION_RECENT_MESSAGE_WINDOW = 20;
@@ -5143,6 +5714,7 @@ function createExistingTagResolver(sessionId, tagger, db) {
5143
5714
  let cachedAssignmentSize = -1;
5144
5715
  let cachedScopedAssignments = null;
5145
5716
  const usedTagNumbers = new Set;
5717
+ const claimedContentIds = new Set;
5146
5718
  function getScopedAssignments() {
5147
5719
  if (!cachedScopedAssignments || cachedAssignmentSize !== assignments.size) {
5148
5720
  cachedScopedAssignments = createScopedAssignments(assignments);
@@ -5153,13 +5725,14 @@ function createExistingTagResolver(sessionId, tagger, db) {
5153
5725
  return {
5154
5726
  resolve(messageId, type, currentContentId, ordinal, options) {
5155
5727
  const accept = options?.accept ?? (() => true);
5728
+ claimedContentIds.add(currentContentId);
5156
5729
  const exactTagId = assignments.get(currentContentId);
5157
5730
  if (exactTagId !== undefined && accept(exactTagId)) {
5158
5731
  usedTagNumbers.add(exactTagId);
5159
5732
  return exactTagId;
5160
5733
  }
5161
5734
  const fallback = getScopedAssignments().get(messageId)?.[type][ordinal];
5162
- if (!fallback || usedTagNumbers.has(fallback.tagNumber) || !accept(fallback.tagNumber)) {
5735
+ if (!fallback || usedTagNumbers.has(fallback.tagNumber) || claimedContentIds.has(fallback.contentId) || !accept(fallback.tagNumber)) {
5163
5736
  return;
5164
5737
  }
5165
5738
  updateTagMessageId(db, sessionId, fallback.tagNumber, currentContentId);
@@ -5181,20 +5754,22 @@ function logTransformTiming(sessionId, stage, startMs, extra) {
5181
5754
  // src/hooks/magic-context/tag-messages.ts
5182
5755
  var TOOL_OWNER_CACHE_KEY_SEP = "\x00";
5183
5756
  var inertWhitespaceCache = new WeakMap;
5184
- function getCachedInertWhitespaceAssistantTags(db, sessionId, tagger) {
5757
+ function getCachedInertWhitespaceAssistantTags(db, sessionId, tagger, messages) {
5758
+ const messageIds = messages.flatMap((message) => typeof message.info.id === "string" ? [message.info.id] : []);
5759
+ const ownersKey = JSON.stringify(messageIds);
5185
5760
  const tagsVersion = tagger.getLoadedTagsVersion?.(sessionId, db);
5186
5761
  if (tagsVersion === undefined)
5187
- return getInertWhitespaceAssistantTags(db, sessionId);
5762
+ return getInertWhitespaceAssistantTags(db, sessionId, messageIds);
5188
5763
  let bySession = inertWhitespaceCache.get(db);
5189
5764
  if (!bySession) {
5190
5765
  bySession = new Map;
5191
5766
  inertWhitespaceCache.set(db, bySession);
5192
5767
  }
5193
5768
  const cached = bySession.get(sessionId);
5194
- if (cached?.tagsVersion === tagsVersion)
5769
+ if (cached?.tagsVersion === tagsVersion && cached.ownersKey === ownersKey)
5195
5770
  return cached.tags;
5196
- const tags = getInertWhitespaceAssistantTags(db, sessionId);
5197
- bySession.set(sessionId, { tagsVersion, tags });
5771
+ const tags = getInertWhitespaceAssistantTags(db, sessionId, messageIds);
5772
+ bySession.set(sessionId, { tagsVersion, ownersKey, tags });
5198
5773
  return tags;
5199
5774
  }
5200
5775
  function makeToolOwnerCacheKey(sessionId, callId) {
@@ -5371,7 +5946,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5371
5946
  const tInertWhitespace = performance.now();
5372
5947
  const inertWhitespaceTagNumbers = new Set;
5373
5948
  const inertWhitespaceTagsByMessage = new Map;
5374
- for (const tag of getCachedInertWhitespaceAssistantTags(db, sessionId, tagger)) {
5949
+ for (const tag of getCachedInertWhitespaceAssistantTags(db, sessionId, tagger, messages)) {
5375
5950
  inertWhitespaceTagNumbers.add(tag.tagNumber);
5376
5951
  tagger.bindTag(sessionId, tag.contentId, tag.tagNumber);
5377
5952
  const scoped = /^(.*):p(\d+)$/.exec(tag.contentId);
@@ -5390,6 +5965,22 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5390
5965
  const tGetSourceContents = performance.now();
5391
5966
  const sourceContents = getSourceContents(db, sessionId, collectRelevantSourceTagIds(messages, assignments));
5392
5967
  logTransformTiming(sessionId, "tag.getSourceContents", tGetSourceContents);
5968
+ let partialEndsCache;
5969
+ const loadPartialEnds = () => {
5970
+ if (partialEndsCache)
5971
+ return partialEndsCache;
5972
+ const first = new Map;
5973
+ const last = new Map;
5974
+ const rows = db.prepare("SELECT end_message_id, end_block_index FROM compartments WHERE session_id=? AND end_block_index IS NOT NULL ORDER BY rowid").all(sessionId);
5975
+ for (const row of rows) {
5976
+ if (!first.has(row.end_message_id))
5977
+ first.set(row.end_message_id, row.end_block_index);
5978
+ last.set(row.end_message_id, row.end_block_index);
5979
+ }
5980
+ partialEndsCache = { first, last };
5981
+ return partialEndsCache;
5982
+ };
5983
+ const getPartialEnds = () => loadPartialEnds().first;
5393
5984
  let precedingThinkingParts = [];
5394
5985
  let lastReduceMessageIndex = -1;
5395
5986
  const RECENT_REDUCE_LOOKBACK = 10;
@@ -5543,15 +6134,20 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5543
6134
  }
5544
6135
  targets.set(tagId, {
5545
6136
  message,
5546
- setContent: (content) => {
6137
+ textPrefix: skipPrefixInjection ? "" : prependTag(tagId, ""),
6138
+ setContent: (content, options) => {
5547
6139
  if (textPart.text === content)
5548
6140
  return false;
6141
+ const partialEnd = messageId ? getPartialEnds().get(messageId) : undefined;
6142
+ if (partialEnd !== undefined && partIndex > partialEnd)
6143
+ return false;
5549
6144
  textPart.text = content;
6145
+ if (options?.keepReasoning === true)
6146
+ return true;
5550
6147
  for (const tp of thinkingParts) {
5551
- if (tp.thinking !== undefined)
5552
- tp.thinking = "[cleared]";
5553
- if (tp.text !== undefined)
5554
- tp.text = "[cleared]";
6148
+ if (partialEnd !== undefined && message.parts.indexOf(tp) > partialEnd)
6149
+ continue;
6150
+ neutralizeDroppedReasoningPart(tp);
5555
6151
  }
5556
6152
  return true;
5557
6153
  },
@@ -5623,6 +6219,11 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5623
6219
  const prevText = typeof prev === "object" && prev !== null && "text" in prev ? prev.text : "";
5624
6220
  if (prevText === content)
5625
6221
  return false;
6222
+ if (messageId) {
6223
+ const partialEnd = getPartialEnds().get(messageId);
6224
+ if (partialEnd !== undefined && partIndex > partialEnd)
6225
+ return false;
6226
+ }
5626
6227
  messageParts[partIndex] = {
5627
6228
  type: "text",
5628
6229
  text: content
@@ -5643,7 +6244,18 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5643
6244
  logTransformTiming(sessionId, "tag.assignTag", performance.now() - accAssignTag);
5644
6245
  logTransformTiming(sessionId, "tag.assignToolTag", performance.now() - accAssignToolTag);
5645
6246
  logTransformTiming(sessionId, "tag.saveSource", performance.now() - accSaveSource);
6247
+ const partialEnds = toolTagByCallId.size > 0 ? loadPartialEnds().last : new Map;
5646
6248
  for (const [compositeKey, tagId] of toolTagByCallId) {
6249
+ const occurrences = toolCallIndex.get(compositeKey)?.occurrences ?? [];
6250
+ const touchesUncoveredPart = occurrences.some(({ message, part }) => {
6251
+ const messageId = message.info.id;
6252
+ if (typeof messageId !== "string")
6253
+ return false;
6254
+ const partialEnd = partialEnds.get(messageId);
6255
+ return partialEnd !== undefined && message.parts.indexOf(part) > partialEnd;
6256
+ });
6257
+ if (touchesUncoveredPart)
6258
+ continue;
5647
6259
  const thinkingParts = toolThinkingByCallId.get(compositeKey) ?? [];
5648
6260
  targets.set(tagId, createToolDropTarget(compositeKey, thinkingParts, toolCallIndex, batch, tagId));
5649
6261
  }
@@ -5730,7 +6342,7 @@ function removeSyntheticTodoParts(messages) {
5730
6342
  }
5731
6343
  }
5732
6344
  }
5733
- async function applyTodoSynthesis(args) {
6345
+ async function applyTodoSynthesis2(args) {
5734
6346
  if (!args.fullFeatureMode || args.compactionOff)
5735
6347
  return 0;
5736
6348
  const persistedAnchor = args.replaySnapshot ? args.replaySnapshot.todoSyntheticAnchor : getPersistedTodoSyntheticAnchor(args.db, args.sessionId);
@@ -5795,7 +6407,10 @@ function freezeAllReasoningForBindingRecovery(args) {
5795
6407
  args.recoveredMessageIds.add(id);
5796
6408
  return { flagTarget: args.flagTarget, messageIds };
5797
6409
  }
5798
- function freezeReasoningOnBustingPass(args) {
6410
+ function countAutoSearchHints(db, sessionId) {
6411
+ return getAutoSearchHintDecisions(db, sessionId).filter((decision) => decision.decision === "hint").length;
6412
+ }
6413
+ function freezeReasoningOnBustingPass2(args) {
5799
6414
  const messageIds = findReasoningBearingAssistantIds(args.messages).filter((id) => !args.alreadyFrozen.has(id));
5800
6415
  if (messageIds.length === 0)
5801
6416
  return { strip: null, persistenceFailed: false };
@@ -5820,7 +6435,7 @@ function proactiveStripStartIndex(args) {
5820
6435
  return null;
5821
6436
  if (!lastServed.messages)
5822
6437
  return 0;
5823
- const divergence = firstServedDivergenceIndex(args.messages, lastServed.messages, {
6438
+ const divergence = firstServedDivergenceIndex2(args.messages, lastServed.messages, {
5824
6439
  providerID: args.resolvedProviderID
5825
6440
  });
5826
6441
  if (lastServed.proven)
@@ -5846,7 +6461,7 @@ function servedMessageKey(message, providerID) {
5846
6461
  }));
5847
6462
  return stableStringify(plain);
5848
6463
  }
5849
- function firstServedDivergenceIndex(messages, lastServed, options = {}) {
6464
+ function firstServedDivergenceIndex2(messages, lastServed, options = {}) {
5850
6465
  const shared = Math.min(messages.length, lastServed.length);
5851
6466
  for (let index = 0;index < shared; index += 1) {
5852
6467
  if (servedMessageKey(messages[index], options.providerID) !== servedMessageKey(lastServed[index], options.providerID)) {
@@ -5855,9 +6470,26 @@ function firstServedDivergenceIndex(messages, lastServed, options = {}) {
5855
6470
  }
5856
6471
  return null;
5857
6472
  }
6473
+ function rustModeServedKeyAfterPersistedStrips2(args) {
6474
+ const recoveryMessageIds = new Set;
6475
+ for (const id of getMergedReasoningStrippedIds(args.db, args.sessionId)) {
6476
+ if (!id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX))
6477
+ continue;
6478
+ const messageId = id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length);
6479
+ if (messageId.length > 0)
6480
+ recoveryMessageIds.add(messageId);
6481
+ }
6482
+ return (message) => {
6483
+ const id = isRecord(message) && isRecord(message.info) ? message.info.id : undefined;
6484
+ if (typeof id !== "string" || !recoveryMessageIds.has(id)) {
6485
+ return servedMessageKey(message, args.resolvedProviderID);
6486
+ }
6487
+ const copy = [structuredClone(message)];
6488
+ stripReasoningFromAssistantIds(copy, args.resolvedProviderID, recoveryMessageIds);
6489
+ return servedMessageKey(copy[0], args.resolvedProviderID);
6490
+ };
6491
+ }
5858
6492
  function replayRustModeBindingMismatchStrips2(args) {
5859
- if (!modelAcceptsEmptyContent(args.resolvedProviderID))
5860
- return;
5861
6493
  const recoveryMessageIds = new Set;
5862
6494
  for (const id of getMergedReasoningStrippedIds(args.db, args.sessionId)) {
5863
6495
  if (!id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX))
@@ -5868,7 +6500,7 @@ function replayRustModeBindingMismatchStrips2(args) {
5868
6500
  }
5869
6501
  stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, recoveryMessageIds);
5870
6502
  }
5871
- var RUST_MARKER_LOCK_SKIP_LOG = "rust compaction-marker: pending target write skipped on lock contention; next pass retries";
6503
+ var RUST_MARKER_LOCK_SKIP_LOG2 = "rust compaction-marker: pending target write skipped on lock contention; next pass retries";
5872
6504
  function isSqliteLockContentionError(error) {
5873
6505
  if (!error || typeof error !== "object")
5874
6506
  return false;
@@ -5912,7 +6544,7 @@ function applyRustModeDeferredCompactionMarker2(args) {
5912
6544
  } catch (error) {
5913
6545
  if (!isSqliteLockContentionError(error))
5914
6546
  throw error;
5915
- sessionLog(args.sessionId, `${RUST_MARKER_LOCK_SKIP_LOG}: ${error instanceof Error ? error.message : String(error)}`);
6547
+ sessionLog(args.sessionId, `${RUST_MARKER_LOCK_SKIP_LOG2}: ${error instanceof Error ? error.message : String(error)}`);
5916
6548
  return;
5917
6549
  }
5918
6550
  }
@@ -5955,13 +6587,70 @@ function clearRustModeBoundaryRecord2(db, sessionId) {
5955
6587
  setPersistedCompactionMarkerState(db, sessionId, null);
5956
6588
  return true;
5957
6589
  }
6590
+ function applyRustModeThinkingStrips(args, hostEditBeforeNewestThinking) {
6591
+ const recoveryMessageIds = new Set;
6592
+ let thinkingBindingRecovery = null;
6593
+ let proactiveThinkingStrip = null;
6594
+ {
6595
+ try {
6596
+ for (const id of getMergedReasoningStrippedIds(args.db, args.sessionId)) {
6597
+ if (!id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX))
6598
+ continue;
6599
+ const messageId = id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length);
6600
+ if (messageId.length > 0)
6601
+ recoveryMessageIds.add(messageId);
6602
+ }
6603
+ const flagTarget = args.thinkingBindingRecoveryEnabledForModel ? getThinkingBindingRecoveryTarget(args.db, args.sessionId) : null;
6604
+ if (flagTarget) {
6605
+ thinkingBindingRecovery = freezeAllReasoningForBindingRecovery({
6606
+ db: args.db,
6607
+ sessionId: args.sessionId,
6608
+ messages: args.messages,
6609
+ flagTarget,
6610
+ recoveredMessageIds: recoveryMessageIds
6611
+ });
6612
+ if (!thinkingBindingRecovery) {
6613
+ sessionLog(args.sessionId, "rust thinking binding recovery: persistence failed; leaving the bound blocks intact");
6614
+ }
6615
+ }
6616
+ } catch (error) {
6617
+ sessionLog(args.sessionId, "rust thinking binding recovery failed:", error);
6618
+ }
6619
+ stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, recoveryMessageIds);
6620
+ const moduleBustStrips = args.cacheBustingPass === true && (args.moduleReasoningTrimOnly !== true || hostEditBeforeNewestThinking);
6621
+ const stripFrom = args.thinkingBindingRecoveryEnabledForModel === true ? proactiveStripStartIndex({ ...args, cacheBustingPass: moduleBustStrips }) : null;
6622
+ if (stripFrom !== null) {
6623
+ const outcome = freezeReasoningOnBustingPass2({
6624
+ db: args.db,
6625
+ sessionId: args.sessionId,
6626
+ messages: args.messages.slice(stripFrom),
6627
+ alreadyFrozen: recoveryMessageIds
6628
+ });
6629
+ if (outcome.strip) {
6630
+ proactiveThinkingStrip = outcome.strip;
6631
+ for (const id of outcome.strip.messageIds)
6632
+ recoveryMessageIds.add(id);
6633
+ stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, new Set(outcome.strip.messageIds));
6634
+ }
6635
+ }
6636
+ }
6637
+ return { thinkingBindingRecovery, proactiveThinkingStrip };
6638
+ }
5958
6639
  function runRustModePostprocess2(args) {
5959
- if (!args.fullFeatureMode || args.compactionOff) {
6640
+ if (args.compactionOff) {
5960
6641
  return { thinkingBindingRecovery: null, proactiveThinkingStrip: null, markerAt: null };
5961
6642
  }
5962
6643
  if (args.messages.some((message) => !message || typeof message !== "object" || !isRecord(message.info))) {
5963
6644
  return { thinkingBindingRecovery: null, proactiveThinkingStrip: null, markerAt: null };
5964
6645
  }
6646
+ if (!args.fullFeatureMode) {
6647
+ return { ...applyRustModeThinkingStrips(args, false), markerAt: null };
6648
+ }
6649
+ const servedMarkerRecord = () => JSON.stringify([
6650
+ getPersistedCompactionMarkerState(args.db, args.sessionId),
6651
+ getDeferredClearedCompactionMarkerState(args.db, args.sessionId)
6652
+ ]);
6653
+ const servedMarkerBefore = servedMarkerRecord();
5965
6654
  applyRustModeDeferredCompactionMarker2({
5966
6655
  ...args.compactionMarkerStrategy ? { applyDeferred: args.compactionMarkerStrategy.applyDeferred } : {},
5967
6656
  db: args.db,
@@ -5969,7 +6658,7 @@ function runRustModePostprocess2(args) {
5969
6658
  boundary: args.materializedBoundary,
5970
6659
  sessionDirectory: args.sessionDirectory
5971
6660
  });
5972
- (args.compactionMarkerStrategy?.reconcile ?? reconcileMarkerRepresentation)(args.messages, getPersistedCompactionMarkerState(args.db, args.sessionId), {
6661
+ (args.compactionMarkerStrategy?.reconcile ?? reconcileMarkerRepresentation2)(args.messages, getPersistedCompactionMarkerState(args.db, args.sessionId), {
5973
6662
  db: args.db,
5974
6663
  sessionId: args.sessionId,
5975
6664
  tagger: args.tagger,
@@ -6013,6 +6702,7 @@ function runRustModePostprocess2(args) {
6013
6702
  }
6014
6703
  const absorbingStripDecisions = new Map([...trailingBlankDecisions].filter(([, decision]) => decision === "strip"));
6015
6704
  applyFrozenTrailingBlankDecisions(args.messages, absorbingStripDecisions);
6705
+ let noteNudgeAppended = false;
6016
6706
  const currentUserMessageId = findLastUserMessageId(args.messages);
6017
6707
  const noteReadStillVisible = hasVisibleNoteReadCall(args.messages);
6018
6708
  const deferredNoteText = peekNoteNudgeText(args.db, args.sessionId, currentUserMessageId, args.projectPath, noteReadStillVisible);
@@ -6024,55 +6714,12 @@ function runRustModePostprocess2(args) {
6024
6714
  const outcome = markNoteNudgeDelivered(args.db, args.sessionId, instruction, anchoredMessageId);
6025
6715
  if (anchoredMessageId && outcome.ok) {
6026
6716
  appendReminderToUserMessageById(args.messages, anchoredMessageId, instruction);
6717
+ noteNudgeAppended = true;
6027
6718
  } else if (anchoredMessageId && !outcome.ok) {
6028
6719
  sessionLog(args.sessionId, `rust note-nudge delivery skipped wire append: ${outcome.kind}`);
6029
6720
  }
6030
6721
  }
6031
- const recoveryMessageIds = new Set;
6032
- let thinkingBindingRecovery = null;
6033
- let proactiveThinkingStrip = null;
6034
- if (modelAcceptsEmptyContent(args.resolvedProviderID)) {
6035
- try {
6036
- for (const id of getMergedReasoningStrippedIds(args.db, args.sessionId)) {
6037
- if (!id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX))
6038
- continue;
6039
- const messageId = id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length);
6040
- if (messageId.length > 0)
6041
- recoveryMessageIds.add(messageId);
6042
- }
6043
- const flagTarget = args.thinkingBindingRecoveryEnabledForModel ? getThinkingBindingRecoveryTarget(args.db, args.sessionId) : null;
6044
- if (flagTarget) {
6045
- thinkingBindingRecovery = freezeAllReasoningForBindingRecovery({
6046
- db: args.db,
6047
- sessionId: args.sessionId,
6048
- messages: args.messages,
6049
- flagTarget,
6050
- recoveredMessageIds: recoveryMessageIds
6051
- });
6052
- if (!thinkingBindingRecovery) {
6053
- sessionLog(args.sessionId, "rust thinking binding recovery: persistence failed; leaving the bound blocks intact");
6054
- }
6055
- }
6056
- } catch (error) {
6057
- sessionLog(args.sessionId, "rust thinking binding recovery failed:", error);
6058
- }
6059
- stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, recoveryMessageIds);
6060
- const stripFrom = args.thinkingBindingRecoveryEnabledForModel === true ? proactiveStripStartIndex(args) : null;
6061
- if (stripFrom !== null) {
6062
- const outcome = freezeReasoningOnBustingPass({
6063
- db: args.db,
6064
- sessionId: args.sessionId,
6065
- messages: args.messages.slice(stripFrom),
6066
- alreadyFrozen: recoveryMessageIds
6067
- });
6068
- if (outcome.strip) {
6069
- proactiveThinkingStrip = outcome.strip;
6070
- for (const id of outcome.strip.messageIds)
6071
- recoveryMessageIds.add(id);
6072
- stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, new Set(outcome.strip.messageIds));
6073
- }
6074
- }
6075
- }
6722
+ const { thinkingBindingRecovery, proactiveThinkingStrip } = applyRustModeThinkingStrips(args, noteNudgeAppended || servedMarkerRecord() !== servedMarkerBefore);
6076
6723
  const marker = getPersistedCompactionMarkerState(args.db, args.sessionId);
6077
6724
  return {
6078
6725
  thinkingBindingRecovery,
@@ -6085,7 +6732,7 @@ function dropMarkerSummaryTag(db, sessionId, summaryMessageId) {
6085
6732
  if (tagNumber !== null)
6086
6733
  updateTagStatus(db, sessionId, tagNumber, "dropped");
6087
6734
  }
6088
- function reconcileMarkerRepresentation(messages, persistedMarkerState, options) {
6735
+ function reconcileMarkerRepresentation2(messages, persistedMarkerState, options) {
6089
6736
  if (persistedMarkerState === null) {
6090
6737
  if (options.isCacheBustingPass === true) {
6091
6738
  retireDeferredClearedCompactionMarkerState(options.db, options.sessionId);
@@ -6168,7 +6815,7 @@ function sourceAlreadyReflectsCoveringMarker(sessionId, sourceOrder, marker, pen
6168
6815
  return false;
6169
6816
  return sourceOrder.messageIds.includes(marker.summaryMessageId) && !sourceOrder.messageIds.includes(pending.endMessageId);
6170
6817
  }
6171
- function clearPendingCompactionMarkerAfterSuccessfulDrain(args) {
6818
+ function clearPendingCompactionMarkerAfterSuccessfulDrain2(args) {
6172
6819
  if (clearPendingCompactionMarkerStateIf(args.db, args.sessionId, args.pending)) {
6173
6820
  return "cleared";
6174
6821
  }
@@ -6183,7 +6830,7 @@ function clearPendingCompactionMarkerAfterSuccessfulDrain(args) {
6183
6830
  }
6184
6831
  var defaultCompactionMarkerStrategy2 = {
6185
6832
  applyDeferred: applyDeferredCompactionMarker,
6186
- reconcile: reconcileMarkerRepresentation
6833
+ reconcile: reconcileMarkerRepresentation2
6187
6834
  };
6188
6835
  async function abortSessionFailClosed2(client, sessionId) {
6189
6836
  if (typeof client?.session?.abort !== "function") {
@@ -6216,7 +6863,7 @@ function evaluateEmergencyFailClosed2(input) {
6216
6863
  reason: shouldAbort ? "provider-overflow-abort" : "proceed"
6217
6864
  };
6218
6865
  }
6219
- function finalizeMessageRepresentation(messages, resolvedProviderID, options) {
6866
+ function finalizeMessageRepresentation2(messages, resolvedProviderID, options) {
6220
6867
  let clearedParts = 0;
6221
6868
  if (modelAcceptsEmptyContent(resolvedProviderID)) {
6222
6869
  const prependedMessageCount = Math.min(messages.length, Math.max(0, options?.prependedMessageCount ?? 0));
@@ -6247,6 +6894,13 @@ function finalizeMessageRepresentation(messages, resolvedProviderID, options) {
6247
6894
  async function runPostTransformPhase2(args) {
6248
6895
  const tPostprocessSetup = performance.now();
6249
6896
  const compactionOff = args.compactionOff === true;
6897
+ const failPass = (site, error = new Error(`Could not complete ${site}`), kind) => {
6898
+ args.passOutcome?.record(site, kind);
6899
+ if (!compactionOff) {
6900
+ sessionLog(args.sessionId, `transform refused degraded pass site=${site}:`, error);
6901
+ throw degradedPassError(site, error);
6902
+ }
6903
+ };
6250
6904
  const trailingBlankSourceDecisions = args.trailingBlankSourceDecisions ?? snapshotTrailingBlankSourceDecisions(args.messages);
6251
6905
  let trailingBlankNewestAssistant;
6252
6906
  for (let index = args.messages.length - 1;index >= 0; index -= 1) {
@@ -6279,7 +6933,8 @@ async function runPostTransformPhase2(args) {
6279
6933
  const deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
6280
6934
  const materializationRequested = isExplicitFlush || deferredMaterialize;
6281
6935
  const m0M1EnabledForFold = args.m0M1 !== undefined && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory) && (args.fullFeatureMode || compactionOff);
6282
- const foldDueDecision = m0M1EnabledForFold && args.m0M1 ? mustMaterialize({
6936
+ const freezeM0M1 = args.freezeM0M1 === true;
6937
+ const foldDueDecision = m0M1EnabledForFold && args.m0M1 && !freezeM0M1 ? mustMaterialize({
6283
6938
  db: args.db,
6284
6939
  sessionId: args.sessionId,
6285
6940
  state: args.sessionMeta,
@@ -6290,10 +6945,11 @@ async function runPostTransformPhase2(args) {
6290
6945
  muralEnabled: args.m0M1.muralEnabled,
6291
6946
  memoryInjectionBudgetTokens: args.m0M1.memoryInjectionBudgetTokens,
6292
6947
  historyBudgetTokens: args.m0M1.historyBudgetTokens,
6948
+ historyBudgetPolicyIdentity: args.m0M1.historyBudgetPolicyIdentity,
6293
6949
  hardSignals: args.m0M1.hardSignals
6294
6950
  }) : { value: false, reason: null };
6295
6951
  let preparedPrefix;
6296
- const shouldCaptureCachedPrefix = (foldDueDecision.value || args.schedulerDecision === "execute") && m0M1EnabledForFold && !emergencyDropEligible;
6952
+ const shouldCaptureCachedPrefix = (foldDueDecision.value || args.schedulerDecision === "execute") && m0M1EnabledForFold && !emergencyDropEligible && !freezeM0M1;
6297
6953
  const cachedPrefixBeforePreflight = shouldCaptureCachedPrefix ? prepareCachedM0M1Replay(args.db, args.sessionId) : undefined;
6298
6954
  const completeCachedPrefixAvailable = args.sessionMeta.cachedM0Bytes != null && args.sessionMeta.cachedM1Bytes != null || cachedPrefixBeforePreflight !== undefined || m0M1EnabledForFold && !shouldCaptureCachedPrefix && hasCompleteCachedM0M1(args.db, args.sessionId);
6299
6955
  const firstRenderBust = m0M1EnabledForFold && !completeCachedPrefixAvailable;
@@ -6301,7 +6957,7 @@ async function runPostTransformPhase2(args) {
6301
6957
  let foldBustsServedPrefixThisPass = false;
6302
6958
  let publishedM1RefreshedThisPass = false;
6303
6959
  let prefixPreflightFailed = false;
6304
- const softRefreshOpportunity = args.schedulerDecision === "execute" || deferredMaterialize;
6960
+ const softRefreshOpportunity = !freezeM0M1 && (args.schedulerDecision === "execute" || deferredMaterialize);
6305
6961
  let m0RematerializedThisPass = false;
6306
6962
  const m0CoverageBeforeFold = args.sessionMeta.cachedM0Bytes === null ? -1 : args.sessionMeta.cachedM0MaxCompartmentSeq;
6307
6963
  let m0MaterializeReason = null;
@@ -6328,6 +6984,7 @@ async function runPostTransformPhase2(args) {
6328
6984
  memoryEnabled: args.m0M1.memoryEnabled,
6329
6985
  memoryInjectionBudgetTokens: args.m0M1.memoryInjectionBudgetTokens,
6330
6986
  historyBudgetTokens: args.m0M1.historyBudgetTokens,
6987
+ historyBudgetPolicyIdentity: args.m0M1.historyBudgetPolicyIdentity,
6331
6988
  temporalAwareness: args.m0M1.temporalAwareness,
6332
6989
  isCacheBustingPass: true,
6333
6990
  contentionFallbackPrefix: cachedPrefixBeforePreflight,
@@ -6373,7 +7030,7 @@ async function runPostTransformPhase2(args) {
6373
7030
  } catch (error) {
6374
7031
  preparedPrefix = cachedPrefixBeforePreflight;
6375
7032
  prefixPreflightFailed = true;
6376
- args.passOutcome?.record("m0-m1-fold-preexecution-degradation");
7033
+ failPass("m0-m1-fold-preexecution-degradation", error);
6377
7034
  sessionLog(args.sessionId, "transform: m[0] HARD fold pre-execution failed:", getErrorMessage(error));
6378
7035
  }
6379
7036
  sessionLog(args.sessionId, `m[0] HARD fold decision: reason=${foldDueDecision.reason ?? "unknown"} executed=${foldExecutedThisPass} bustsServedPrefix=${foldBustsServedPrefixThisPass}`);
@@ -6385,8 +7042,9 @@ async function runPostTransformPhase2(args) {
6385
7042
  const depth = getPendingOpsCount(args.db, args.sessionId);
6386
7043
  return depth === null ? "not loaded (deferred pass)" : String(depth);
6387
7044
  };
7045
+ const idleExpiryRebuild = !freezeM0M1 && args.m0M1?.hardSignals?.cacheExpired === true;
6388
7046
  const rideSignals = {
6389
- hardFold: foldBustsServedPrefixThisPass || firstRenderBust,
7047
+ hardFold: foldBustsServedPrefixThisPass || firstRenderBust || idleExpiryRebuild,
6390
7048
  force: emergencyDropEligible && (args.contextUsage.percentage >= 95 || getEmergencyInputSample(args.db, args.sessionId) === 0),
6391
7049
  explicitFlush: isExplicitFlush || deferredMaterialize && !prefixPreflightFailed,
6392
7050
  publishedHistory: publishedM1RefreshedThisPass || !m0M1EnabledForFold && (args.pendingCompartmentInjection?.compartmentCount ?? 0) > 0 && (args.historyRebuiltThisPass || args.rebuiltHistoryFromInitialPrepare || args.canConsumeDeferredLate && args.deferredHistoryWasPendingAtPassStart)
@@ -6407,6 +7065,25 @@ async function runPostTransformPhase2(args) {
6407
7065
  }
6408
7066
  }
6409
7067
  const canUseEmptySentinels = modelAcceptsEmptyContent(args.resolvedProviderID);
7068
+ const prefixBoundModel = args.thinkingBindingRecoveryEnabledForModel === true;
7069
+ const reasoningRemovalEnabled = (!canUseEmptySentinels || prefixBoundModel) && !compactionOff;
7070
+ const reasoningRemovalSelectable = reasoningRemovalEnabled && typeof args.resolvedProviderID === "string";
7071
+ const removedReasoningIds = new Set;
7072
+ let dropLeavesReasoning = false;
7073
+ let reasoningRemovalReadable = false;
7074
+ if (reasoningRemovalEnabled) {
7075
+ try {
7076
+ const state = getReasoningRemovalState(args.db, args.sessionId);
7077
+ for (const id of state.messageIds)
7078
+ removedReasoningIds.add(id);
7079
+ dropLeavesReasoning = state.dropLeavesReasoning;
7080
+ reasoningRemovalReadable = true;
7081
+ } catch (error) {
7082
+ args.passOutcome?.record("reasoning-removal-read-failure");
7083
+ sessionLog(args.sessionId, "reasoning removal: persisted state and backup unreadable; failing the pass closed:", error);
7084
+ throw new EmergencyFailClosedError("Magic Context could not read its saved reasoning-removal state for this session", { cause: error });
7085
+ }
7086
+ }
6410
7087
  if (shouldRunHeuristics) {
6411
7088
  const subagentRerun = !args.fullFeatureMode && alreadyRanThisTurn && args.schedulerDecision === "execute" && !isExplicitFlush && !forceMaterialization;
6412
7089
  const reason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : foldBustsServedPrefixThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : subagentRerun ? `${reclaimRideLabel(rideSignals)} subagent_rerun (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})` : `${reclaimRideLabel(rideSignals)} (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
@@ -6427,6 +7104,7 @@ async function runPostTransformPhase2(args) {
6427
7104
  let deferredMaterializedSuccessfully = false;
6428
7105
  let pendingOpsDidMutate = false;
6429
7106
  let heuristicOrReasoningDidMutate = false;
7107
+ let heuristicOrReasoningEditBesidesTrim = false;
6430
7108
  let droppedCount = 0;
6431
7109
  let droppedTokens = 0;
6432
7110
  const droppedTokenReductions = [];
@@ -6477,21 +7155,23 @@ async function runPostTransformPhase2(args) {
6477
7155
  const t5 = performance.now();
6478
7156
  const cavemanConfig = args.cavemanTextCompression?.enabled ? {
6479
7157
  enabled: true,
6480
- minChars: args.cavemanTextCompression.minChars
7158
+ minChars: args.cavemanTextCompression.minChars,
7159
+ wordRules: args.cavemanTextCompression.wordRules
6481
7160
  } : undefined;
6482
7161
  const heuristicTags = shouldApplyPendingOps ? getActiveTagsBySession(args.db, args.sessionId) : args.tags;
6483
- const independentMutationBeforeHeuristics = pendingOpsDidMutate || args.didMutateFromFlushedStatuses || foldBustsServedPrefixThisPass || args.historyRebuiltThisPass || args.compartmentInjectionRebuiltFromDb || args.rebuiltHistoryFromInitialPrepare;
6484
- if (emergencyDropEligible && independentMutationBeforeHeuristics && getEmergencyInputSample(args.db, args.sessionId) > 0) {
7162
+ const emergencyRewriteAlreadyPriced = pendingOpsDidMutate || foldBustsServedPrefixThisPass || args.historyRebuiltThisPass || args.compartmentInjectionRebuiltFromDb || args.rebuiltHistoryFromInitialPrepare;
7163
+ if (emergencyDropEligible && emergencyRewriteAlreadyPriced && getEmergencyInputSample(args.db, args.sessionId) > 0) {
6485
7164
  clearEmergencyDropSample(args.db, args.sessionId);
6486
7165
  }
6487
- let routineCleanupApplied = (emergencyDropEligible ? args.contextUsage.percentage >= 95 || getEmergencyInputSample(args.db, args.sessionId) === 0 : !args.fullFeatureMode || !routinePressureAlreadyApplied) || materializationRequested || independentMutationBeforeHeuristics;
7166
+ let routineCleanupApplied = (emergencyDropEligible ? args.contextUsage.percentage >= 95 || getEmergencyInputSample(args.db, args.sessionId) === 0 : !args.fullFeatureMode || !routinePressureAlreadyApplied) || materializationRequested || emergencyRewriteAlreadyPriced;
6488
7167
  let cleanup = applyHeuristicCleanup(args.sessionId, args.db, args.targets, args.messageTagNumbers, {
6489
7168
  protectedTagNumbers: args.protectedTagNumbers,
6490
7169
  protectedCutoff: args.protectedCutoff,
6491
7170
  emergency: emergencyDropEligible && args.emergencyCeilingTokens !== undefined && args.emergencyCeilingTokens > 0 ? {
6492
7171
  currentTotalInputTokens: args.contextUsage.inputTokens,
6493
7172
  ceilingTokens: args.emergencyCeilingTokens,
6494
- usagePercentage: args.contextUsage.percentage
7173
+ usagePercentage: args.contextUsage.percentage,
7174
+ passAlreadyPriced: emergencyRewriteAlreadyPriced
6495
7175
  } : undefined,
6496
7176
  routine: routineCleanupApplied,
6497
7177
  caveman: cavemanConfig
@@ -6528,11 +7208,63 @@ async function runPostTransformPhase2(args) {
6528
7208
  emergencyReclaimedTokens += cleanup.emergencyReclaimedTokens;
6529
7209
  droppedTokenReductions.push(...cleanup.droppedTokenReductions);
6530
7210
  const t7 = performance.now();
6531
- const clearedReasoning = routineCleanupApplied && canUseEmptySentinels ? clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge) : 0;
7211
+ const ageLaneAllowed = !prefixBoundModel;
7212
+ const clearedReasoning = routineCleanupApplied && canUseEmptySentinels && ageLaneAllowed ? clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge) : 0;
6532
7213
  if (routineCleanupApplied && canUseEmptySentinels) {
6533
7214
  stripClearedReasoning(args.messages);
6534
7215
  }
6535
- const strippedInline = routineCleanupApplied ? stripInlineThinking(args.messages, args.messageTagNumbers, args.clearReasoningAge) : 0;
7216
+ const strippedInline = routineCleanupApplied && ageLaneAllowed ? stripInlineThinking(args.messages, args.messageTagNumbers, args.clearReasoningAge) : 0;
7217
+ const persistedInlineWatermark = args.sessionMeta?.clearedReasoningThroughTag ?? 0;
7218
+ if (routineCleanupApplied && persistedInlineWatermark > 0 && !compactionOff) {
7219
+ replayStrippedInlineThinking(args.messages, args.messageTagNumbers, persistedInlineWatermark);
7220
+ }
7221
+ let removedReasoningMessages = 0;
7222
+ if (routineCleanupApplied && reasoningRemovalSelectable && reasoningRemovalReadable) {
7223
+ const bindingStrippedIds = new Set;
7224
+ if (prefixBoundModel) {
7225
+ for (const id of getMergedReasoningStrippedIds(args.db, args.sessionId)) {
7226
+ if (!id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX))
7227
+ continue;
7228
+ const messageId = id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length);
7229
+ if (messageId.length > 0)
7230
+ bindingStrippedIds.add(messageId);
7231
+ }
7232
+ }
7233
+ const newIds = selectReasoningRemovals({
7234
+ messages: args.messages,
7235
+ messageTagNumbers: args.messageTagNumbers,
7236
+ clearReasoningAge: args.clearReasoningAge,
7237
+ alreadyRemoved: removedReasoningIds,
7238
+ prefixBound: prefixBoundModel,
7239
+ alsoGone: bindingStrippedIds
7240
+ });
7241
+ if (newIds.length > 0) {
7242
+ let persisted = false;
7243
+ try {
7244
+ persisted = addRemovedReasoningIds(args.db, args.sessionId, newIds);
7245
+ } catch (error) {
7246
+ sessionLog(args.sessionId, "reasoning removal: persistence threw:", error);
7247
+ failPass("reasoning-removal-persistence-failure", error);
7248
+ }
7249
+ if (persisted) {
7250
+ for (const id of newIds)
7251
+ removedReasoningIds.add(id);
7252
+ try {
7253
+ const committed = getReasoningRemovalState(args.db, args.sessionId);
7254
+ for (const id of committed.messageIds)
7255
+ removedReasoningIds.add(id);
7256
+ } catch (error) {
7257
+ sessionLog(args.sessionId, "reasoning removal: committed set re-read failed:", error);
7258
+ failPass("reasoning-removal-read-failure", error);
7259
+ }
7260
+ removedReasoningMessages = newIds.length;
7261
+ sessionLog(args.sessionId, `reasoning removal: froze ${newIds.length} assistant(s), total=${removedReasoningIds.size}`);
7262
+ } else {
7263
+ failPass("reasoning-removal-persistence-failure");
7264
+ sessionLog(args.sessionId, "reasoning removal: persistence failed; serving the earlier set only");
7265
+ }
7266
+ }
7267
+ }
6536
7268
  if (clearedReasoning > 0 || strippedInline > 0) {
6537
7269
  let maxTag = 0;
6538
7270
  for (const tag of args.messageTagNumbers.values()) {
@@ -6552,18 +7284,16 @@ async function runPostTransformPhase2(args) {
6552
7284
  }
6553
7285
  }
6554
7286
  logTransformTiming(args.sessionId, "clearOldReasoning", t7);
6555
- heuristicOrReasoningDidMutate = heuristicMutationCount + clearedReasoning + strippedInline > 0;
6556
- droppedCount += clearedReasoning + strippedInline;
6557
- if (pendingMaterializationAtPassStart) {
7287
+ heuristicOrReasoningDidMutate = heuristicMutationCount + clearedReasoning + strippedInline + removedReasoningMessages > 0;
7288
+ heuristicOrReasoningEditBesidesTrim = heuristicMutationCount + clearedReasoning + strippedInline > 0;
7289
+ droppedCount += clearedReasoning + strippedInline + removedReasoningMessages;
7290
+ if (pendingMaterializationAtPassStart && !freezeM0M1) {
6558
7291
  args.pendingMaterializationSessions.delete(args.sessionId);
6559
7292
  }
6560
7293
  if (args.currentTurnId) {
6561
7294
  args.lastHeuristicsTurnId.set(args.sessionId, args.currentTurnId);
6562
7295
  }
6563
7296
  }
6564
- if (args.schedulerDecision === "execute" && !materializationRequested) {
6565
- updateSessionMeta(args.db, args.sessionId, { lastResponseTime: Date.now() });
6566
- }
6567
7297
  if (emergencyDropEligible && (pendingOpsDidMutate || heuristicOrReasoningDidMutate)) {
6568
7298
  setEmergencyDropSample(args.db, args.sessionId, args.contextUsage.inputTokens);
6569
7299
  }
@@ -6640,15 +7370,15 @@ async function runPostTransformPhase2(args) {
6640
7370
  if (args.sessionMeta.lastTransformError !== null) {
6641
7371
  updateSessionMeta(args.db, args.sessionId, { lastTransformError: null });
6642
7372
  }
6643
- if (shouldRunHeuristics) {
7373
+ if (shouldRunHeuristics && !freezeM0M1) {
6644
7374
  if (isExplicitFlush)
6645
7375
  explicitMaterializedSuccessfully = true;
6646
7376
  if (deferredMaterialize)
6647
7377
  deferredMaterializedSuccessfully = true;
6648
7378
  }
6649
7379
  } catch (error) {
6650
- args.passOutcome?.record("pending-operation-failure");
6651
7380
  sessionLog(args.sessionId, "transform failed applying pending operations:", error);
7381
+ failPass("pending-operation-failure", error);
6652
7382
  updateSessionMeta(args.db, args.sessionId, { lastTransformError: getErrorMessage(error) });
6653
7383
  }
6654
7384
  if (isCacheBustingPass) {
@@ -6671,7 +7401,7 @@ async function runPostTransformPhase2(args) {
6671
7401
  }
6672
7402
  logTransformTiming(args.sessionId, "dropStaleReduceCalls", t8);
6673
7403
  } catch (error) {
6674
- args.passOutcome?.record("stale-reduce-strip-exception");
7404
+ failPass("stale-reduce-strip-exception", error);
6675
7405
  sessionLog(args.sessionId, "transform failed dropping stale ctx_reduce calls:", error);
6676
7406
  }
6677
7407
  }
@@ -6689,12 +7419,15 @@ async function runPostTransformPhase2(args) {
6689
7419
  }
6690
7420
  logTransformTiming(args.sessionId, "stripProcessedImages", tImg);
6691
7421
  } catch (error) {
6692
- args.passOutcome?.record("image-strip-exception");
7422
+ failPass("image-strip-exception", error);
6693
7423
  sessionLog(args.sessionId, "transform failed stripping processed images:", error);
6694
7424
  }
6695
7425
  }
6696
7426
  const m0M1Enabled = m0M1EnabledForFold;
6697
7427
  if (m0M1Enabled && args.m0M1) {
7428
+ if (freezeM0M1 && !preparedPrefix) {
7429
+ preparedPrefix = prepareCachedM0M1Replay(args.db, args.sessionId);
7430
+ }
6698
7431
  const tInjectM0M1 = performance.now();
6699
7432
  try {
6700
7433
  const result = injectM0M1({
@@ -6708,8 +7441,9 @@ async function runPostTransformPhase2(args) {
6708
7441
  memoryEnabled: args.m0M1.memoryEnabled,
6709
7442
  memoryInjectionBudgetTokens: args.m0M1.memoryInjectionBudgetTokens,
6710
7443
  historyBudgetTokens: args.m0M1.historyBudgetTokens,
7444
+ historyBudgetPolicyIdentity: args.m0M1.historyBudgetPolicyIdentity,
6711
7445
  temporalAwareness: args.m0M1.temporalAwareness,
6712
- isCacheBustingPass,
7446
+ isCacheBustingPass: isCacheBustingPass && !freezeM0M1,
6713
7447
  preparedPrefix,
6714
7448
  prefixTrimSourceOrder: args.prefixTrimSourceOrder,
6715
7449
  allowFreshContentionFallback: forceMaterialization || emergencyDropEligible,
@@ -6729,7 +7463,8 @@ async function runPostTransformPhase2(args) {
6729
7463
  sessionLog(args.sessionId, `transform: injected m[0]/m[1] (rematerialized=${result.m0RematerializedThisPass}, reason=${result.decision.reason ?? "cache_hit"})`);
6730
7464
  }
6731
7465
  } catch (error) {
6732
- args.passOutcome?.record("m0-m1-injection-degradation");
7466
+ clearInjectionCache(args.sessionId);
7467
+ failPass("m0-m1-injection-degradation", error);
6733
7468
  sessionLog(args.sessionId, "transform: m[0]/m[1] injection failed:", getErrorMessage(error));
6734
7469
  if (args.pendingCompartmentInjection) {
6735
7470
  try {
@@ -6741,7 +7476,6 @@ async function runPostTransformPhase2(args) {
6741
7476
  sessionLog(args.sessionId, "transform: legacy fallback injection also failed:", getErrorMessage(fallbackError));
6742
7477
  }
6743
7478
  }
6744
- clearInjectionCache(args.sessionId);
6745
7479
  }
6746
7480
  logTransformTiming(args.sessionId, "pp.injectM0M1", tInjectM0M1);
6747
7481
  } else if (args.fullFeatureMode && !compactionOff && args.pendingCompartmentInjection) {
@@ -6834,7 +7568,7 @@ async function runPostTransformPhase2(args) {
6834
7568
  case "already-current":
6835
7569
  case "stale-skip":
6836
7570
  persistedCompactionMarkerState = getPersistedCompactionMarkerState(args.db, args.sessionId);
6837
- if (clearPendingCompactionMarkerAfterSuccessfulDrain({
7571
+ if (clearPendingCompactionMarkerAfterSuccessfulDrain2({
6838
7572
  db: args.db,
6839
7573
  sessionId: args.sessionId,
6840
7574
  pending,
@@ -6844,7 +7578,7 @@ async function runPostTransformPhase2(args) {
6844
7578
  }
6845
7579
  break;
6846
7580
  case "retryable-failure":
6847
- args.passOutcome?.record("compaction-marker-drain-failure");
7581
+ failPass("compaction-marker-drain-failure", outcome.error);
6848
7582
  sessionLog(args.sessionId, "compaction-marker drain: retryable failure; preserving deferred history refresh signal", outcome.error);
6849
7583
  suppressV12HistoryDrain = true;
6850
7584
  break;
@@ -6852,6 +7586,7 @@ async function runPostTransformPhase2(args) {
6852
7586
  }
6853
7587
  }
6854
7588
  }
7589
+ const deferredClearedMarkerRetires = !compactionOff && isCacheBustingPass && persistedCompactionMarkerState === null && getDeferredClearedCompactionMarkerState(args.db, args.sessionId) !== null;
6855
7590
  if (!compactionOff) {
6856
7591
  (args.compactionMarkerStrategy ?? defaultCompactionMarkerStrategy2).reconcile(args.messages, persistedCompactionMarkerState, {
6857
7592
  db: args.db,
@@ -6871,6 +7606,7 @@ async function runPostTransformPhase2(args) {
6871
7606
  logTransformTiming(args.sessionId, "pp.markerReconcile", tMarker);
6872
7607
  const tNoteAndTodo = performance.now();
6873
7608
  const noteReadStillVisible = args.fullFeatureMode ? hasVisibleNoteReadCall(args.messages) : false;
7609
+ let noteNudgeAppendedThisPass = false;
6874
7610
  const deferredNoteText = args.fullFeatureMode ? peekNoteNudgeText(args.db, args.sessionId, args.currentTurnId, args.projectPath, noteReadStillVisible) : null;
6875
7611
  if (deferredNoteText) {
6876
7612
  const noteInstruction = `
@@ -6880,13 +7616,16 @@ async function runPostTransformPhase2(args) {
6880
7616
  const outcome = markNoteNudgeDelivered(args.db, args.sessionId, noteInstruction, anchoredMessageId);
6881
7617
  if (anchoredMessageId && outcome.ok) {
6882
7618
  appendReminderToUserMessageById(args.messages, anchoredMessageId, noteInstruction);
7619
+ noteNudgeAppendedThisPass = true;
6883
7620
  } else if (anchoredMessageId && !outcome.ok) {
6884
7621
  args.passOutcome?.record("note-nudge-cas-failure");
6885
7622
  sessionLog(args.sessionId, `note-nudge delivery skipped wire append: ${outcome.kind}`);
6886
7623
  }
6887
7624
  }
7625
+ let todoAnchorMovedThisPass = false;
6888
7626
  if (args.fullFeatureMode && !compactionOff) {
6889
- prependedMessageCount += await applyTodoSynthesis({
7627
+ const todoAnchorBefore = replaySnapshot ? replaySnapshot.todoSyntheticAnchor : getPersistedTodoSyntheticAnchor(args.db, args.sessionId);
7628
+ prependedMessageCount += await applyTodoSynthesis2({
6890
7629
  db: args.db,
6891
7630
  sessionId: args.sessionId,
6892
7631
  messages: args.messages,
@@ -6899,6 +7638,10 @@ async function runPostTransformPhase2(args) {
6899
7638
  activeAgent: args.activeAgent,
6900
7639
  replaySnapshot
6901
7640
  });
7641
+ if (isCacheBustingPass) {
7642
+ const todoAnchorAfter = getPersistedTodoSyntheticAnchor(args.db, args.sessionId);
7643
+ todoAnchorMovedThisPass = (todoAnchorBefore?.callId ?? null) !== (todoAnchorAfter?.callId ?? null) || (todoAnchorBefore?.messageId ?? null) !== (todoAnchorAfter?.messageId ?? null);
7644
+ }
6902
7645
  }
6903
7646
  logTransformTiming(args.sessionId, "pp.noteAndTodoSynthesis", tNoteAndTodo);
6904
7647
  if (args.compartmentInjectionRebuiltFromDb && args.pendingCompartmentInjection) {
@@ -6913,7 +7656,7 @@ async function runPostTransformPhase2(args) {
6913
7656
  }
6914
7657
  }
6915
7658
  if (args.fullFeatureMode && isCacheBustingPass && args.m0M1 && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory)) {
6916
- checkM0MutationDriftAndSignal({
7659
+ checkM0MutationDriftAndSignal2({
6917
7660
  db: args.db,
6918
7661
  sessionId: args.sessionId,
6919
7662
  cachedM0MaxMutationId: args.sessionMeta.cachedM0MaxMutationId,
@@ -6921,9 +7664,12 @@ async function runPostTransformPhase2(args) {
6921
7664
  historyRefreshSessions: args.historyRefreshSessions
6922
7665
  });
6923
7666
  }
7667
+ let autoSearchHintsBefore = 0;
7668
+ let autoSearchHintAppendedThisPass = false;
6924
7669
  if (args.fullFeatureMode && args.autoSearch?.enabled && args.projectPath) {
6925
7670
  const tAutoSearch = performance.now();
6926
7671
  const visibleMemoryIds = getVisibleMemoryIds(args.db, args.sessionId) ?? undefined;
7672
+ autoSearchHintsBefore = countAutoSearchHints(args.db, args.sessionId);
6927
7673
  try {
6928
7674
  const autoSearchOutcome = await runAutoSearchHint({
6929
7675
  sessionId: args.sessionId,
@@ -6936,7 +7682,8 @@ async function runPostTransformPhase2(args) {
6936
7682
  directory: args.autoSearch.directory ?? args.sessionDirectory,
6937
7683
  projectPath: args.projectPath,
6938
7684
  ensureProjectRegistered: args.autoSearch.ensureProjectRegistered,
6939
- visibleMemoryIds
7685
+ visibleMemoryIds,
7686
+ wordRules: args.autoSearch.wordRules
6940
7687
  }
6941
7688
  });
6942
7689
  if (!autoSearchOutcome.ok) {
@@ -6946,6 +7693,7 @@ async function runPostTransformPhase2(args) {
6946
7693
  args.passOutcome?.record("auto-search-internal-failure");
6947
7694
  sessionLog(args.sessionId, "auto-search runner failed:", error);
6948
7695
  }
7696
+ autoSearchHintAppendedThisPass = countAutoSearchHints(args.db, args.sessionId) !== autoSearchHintsBefore;
6949
7697
  logTransformTiming(args.sessionId, "pp.autoSearchHint", tAutoSearch);
6950
7698
  }
6951
7699
  if (args.fullFeatureMode && isCacheBustingPass) {
@@ -6982,9 +7730,10 @@ async function runPostTransformPhase2(args) {
6982
7730
  }
6983
7731
  }
6984
7732
  const mergedReasoningStrippedIds = new Set(replaySnapshot?.mergedReasoningStrippedIds ?? []);
7733
+ let lateEditBeforeNewestThinking = false;
6985
7734
  const thinkingBindingRecoveryMessageIds = new Set;
6986
7735
  let thinkingBindingRecovery = null;
6987
- if (canUseEmptySentinels && !compactionOff) {
7736
+ if (!compactionOff) {
6988
7737
  try {
6989
7738
  for (const id of mergedReasoningStrippedIds) {
6990
7739
  if (id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX)) {
@@ -7006,14 +7755,16 @@ async function runPostTransformPhase2(args) {
7006
7755
  for (const messageId of thinkingBindingRecovery.messageIds) {
7007
7756
  mergedReasoningStrippedIds.add(thinkingBindingRecoveryFrozenId(messageId));
7008
7757
  }
7009
- if (thinkingBindingRecovery.messageIds.length > 0)
7758
+ if (thinkingBindingRecovery.messageIds.length > 0) {
7010
7759
  bustedThisPass = true;
7760
+ lateEditBeforeNewestThinking = true;
7761
+ }
7011
7762
  } else {
7012
- args.passOutcome?.record("thinking-binding-recovery-persistence-failure");
7763
+ failPass("thinking-binding-recovery-persistence-failure");
7013
7764
  sessionLog(args.sessionId, "thinking binding recovery: persistence failed; leaving the bound blocks intact");
7014
7765
  }
7015
7766
  }
7016
- if (isCacheBustingPass) {
7767
+ if (canUseEmptySentinels && isCacheBustingPass) {
7017
7768
  const candidates = findMergedReasoningStripDecisions(args.messages, args.resolvedProviderID, mergedReasoningStrippedIds, { mutationExemptMessage: reasoningMutationExemptMessage });
7018
7769
  const newlyDetectedIds = candidates.filter((id) => !mergedReasoningStrippedIds.has(id));
7019
7770
  if (newlyDetectedIds.length > 0) {
@@ -7024,14 +7775,15 @@ async function runPostTransformPhase2(args) {
7024
7775
  mergedReasoningStrippedIds.add(id);
7025
7776
  }
7026
7777
  bustedThisPass = true;
7778
+ lateEditBeforeNewestThinking = true;
7027
7779
  } else {
7028
- args.passOutcome?.record("merged-reasoning-strip-persistence-failure");
7780
+ failPass("merged-reasoning-strip-persistence-failure");
7029
7781
  sessionLog(args.sessionId, "merged reasoning strip: persistence failed; leaving newly detected assistants intact");
7030
7782
  }
7031
7783
  }
7032
7784
  }
7033
7785
  } catch (error) {
7034
- args.passOutcome?.record("merged-reasoning-strip-exception");
7786
+ failPass("merged-reasoning-strip-exception", error);
7035
7787
  sessionLog(args.sessionId, "transform failed freezing merged reasoning strip:", error);
7036
7788
  }
7037
7789
  }
@@ -7052,17 +7804,18 @@ async function runPostTransformPhase2(args) {
7052
7804
  try {
7053
7805
  const demotedIds = demoteTrailingBlankKeepDecisions(args.db, args.sessionId, poisonedKeepIds);
7054
7806
  if (demotedIds === null) {
7055
- args.passOutcome?.record("trailing-blank-heal-persistence-failure");
7807
+ failPass("trailing-blank-heal-persistence-failure");
7056
7808
  sessionLog(args.sessionId, "trailing blank heal: persistence failed; retaining frozen keep decisions");
7057
7809
  } else {
7058
7810
  for (const id of demotedIds) {
7059
7811
  trailingBlankDecisions.set(id, "strip");
7060
7812
  bustedThisPass = true;
7813
+ lateEditBeforeNewestThinking = true;
7061
7814
  sessionLog(args.sessionId, `trailing blank heal: demoted message ${id} from keep to strip because its source has no trailing blank`);
7062
7815
  }
7063
7816
  }
7064
7817
  } catch (error) {
7065
- args.passOutcome?.record("trailing-blank-heal-exception");
7818
+ failPass("trailing-blank-heal-exception", error);
7066
7819
  sessionLog(args.sessionId, "transform failed healing trailing blank decisions:", error);
7067
7820
  }
7068
7821
  }
@@ -7079,7 +7832,7 @@ async function runPostTransformPhase2(args) {
7079
7832
  overwriteMessageId: newestAssistantId
7080
7833
  });
7081
7834
  if (persisted) {
7082
- const committed = getTrailingBlankDecisions(args.db, args.sessionId);
7835
+ const committed = getTrailingBlankDecisions(args.db, args.sessionId, candidates.map(([id]) => id));
7083
7836
  for (const [id] of candidates) {
7084
7837
  const decision = committed.get(id);
7085
7838
  if (decision)
@@ -7087,12 +7840,15 @@ async function runPostTransformPhase2(args) {
7087
7840
  }
7088
7841
  if (isCacheBustingPass)
7089
7842
  bustedThisPass = true;
7843
+ if (isCacheBustingPass && candidates.some(([id]) => id !== newestAssistantId)) {
7844
+ lateEditBeforeNewestThinking = true;
7845
+ }
7090
7846
  } else {
7091
- args.passOutcome?.record("trailing-blank-decision-persistence-failure");
7847
+ failPass("trailing-blank-decision-persistence-failure");
7092
7848
  sessionLog(args.sessionId, "trailing blank decision: persistence failed; serving the frozen decisions");
7093
7849
  }
7094
7850
  } catch (error) {
7095
- args.passOutcome?.record("trailing-blank-decision-exception");
7851
+ failPass("trailing-blank-decision-exception", error);
7096
7852
  sessionLog(args.sessionId, "transform failed freezing trailing blank decision:", error);
7097
7853
  }
7098
7854
  }
@@ -7108,9 +7864,11 @@ async function runPostTransformPhase2(args) {
7108
7864
  skipMergedReasoningStrip: compactionOff,
7109
7865
  skipTrailingWhitespaceStrip: compactionOff
7110
7866
  };
7867
+ const dropModeSwitchesThisPass = !canUseEmptySentinels && !dropLeavesReasoning && typeof args.resolvedProviderID === "string" && isCacheBustingPass && reasoningRemovalReadable && args.messages.some((message) => message.info.role === "assistant" && message.parts.some((part) => isNeutralizedReasoningPart(part)));
7868
+ const prefixEditBesidesReasoningTrim = firstRenderBust || materializationRequested || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully || foldBustsServedPrefixThisPass || publishedM1RefreshedThisPass || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass || pendingOpsDidMutate || heuristicOrReasoningEditBesidesTrim || emergency || autoReclaimDidMutateThisPass || convertedToolSkeletonsDidMutate || deferredClearedMarkerRetires || noteNudgeAppendedThisPass || todoAnchorMovedThisPass || autoSearchHintAppendedThisPass || dropModeSwitchesThisPass || lateEditBeforeNewestThinking;
7111
7869
  let proactiveThinkingStrip = null;
7112
- if (canUseEmptySentinels && !compactionOff && args.fullFeatureMode && args.thinkingBindingRecoveryEnabledForModel === true && proactiveThinkingStripPermitted) {
7113
- const outcome = freezeReasoningOnBustingPass({
7870
+ if (!compactionOff && args.thinkingBindingRecoveryEnabledForModel === true && proactiveThinkingStripPermitted && prefixEditBesidesReasoningTrim) {
7871
+ const outcome = freezeReasoningOnBustingPass2({
7114
7872
  db: args.db,
7115
7873
  sessionId: args.sessionId,
7116
7874
  messages: args.messages,
@@ -7124,12 +7882,32 @@ async function runPostTransformPhase2(args) {
7124
7882
  }
7125
7883
  bustedThisPass = true;
7126
7884
  } else if (outcome.persistenceFailed) {
7127
- args.passOutcome?.record("proactive-thinking-strip-persistence-failure");
7885
+ failPass("proactive-thinking-strip-persistence-failure");
7886
+ }
7887
+ }
7888
+ let settledDroppedReasoning = 0;
7889
+ if (!canUseEmptySentinels) {
7890
+ let mode = "legacy";
7891
+ if (dropLeavesReasoning) {
7892
+ mode = "restore";
7893
+ } else if (typeof args.resolvedProviderID === "string") {
7894
+ if (isCacheBustingPass && reasoningRemovalReadable) {
7895
+ try {
7896
+ if (markDropLeavesReasoning(args.db, args.sessionId)) {
7897
+ dropLeavesReasoning = true;
7898
+ mode = "restore";
7899
+ }
7900
+ } catch (error) {
7901
+ sessionLog(args.sessionId, "reasoning removal: drop mode write failed:", error);
7902
+ }
7903
+ }
7128
7904
  }
7905
+ settledDroppedReasoning = settleDroppedReasoningParts(args.messages, mode);
7129
7906
  }
7130
7907
  const tFinalRepresentation = performance.now();
7131
- const finalRepresentation = finalizeMessageRepresentation(args.messages, args.resolvedProviderID, finalizeOptions);
7132
- sessionLog(args.sessionId, `final representation: clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
7908
+ const finalRepresentation = finalizeMessageRepresentation2(args.messages, args.resolvedProviderID, finalizeOptions);
7909
+ const removedReasoningParts = reasoningRemovalEnabled ? removeReasoningParts(args.messages, removedReasoningIds, args.resolvedProviderID) : 0;
7910
+ sessionLog(args.sessionId, `final representation: clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts} removedReasoningParts=${removedReasoningParts} settledDroppedReasoning=${settledDroppedReasoning}`);
7133
7911
  logTransformTiming(args.sessionId, "finalizeMessageRepresentation", tFinalRepresentation, `clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
7134
7912
  const tTailBaseline = performance.now();
7135
7913
  let assertedBaseline;
@@ -7241,11 +8019,12 @@ async function runPostTransformPhase2(args) {
7241
8019
  droppedCount,
7242
8020
  emergency,
7243
8021
  bustedThisPass,
8022
+ prefixTrimStatus: deliveredPrefix?.prefixTrimStatus ?? null,
7244
8023
  thinkingBindingRecovery,
7245
8024
  proactiveThinkingStrip
7246
8025
  };
7247
8026
  }
7248
- function checkM0MutationDriftAndSignal(args) {
8027
+ function checkM0MutationDriftAndSignal2(args) {
7249
8028
  const currentMaxMutationId = getMaxM0MutationId(args.db, args.sessionId) ?? 0;
7250
8029
  const cachedMaxMutationId = args.cachedM0MaxMutationId ?? 0;
7251
8030
  if (currentMaxMutationId !== cachedMaxMutationId) {
@@ -7257,4 +8036,4 @@ function checkM0MutationDriftAndSignal(args) {
7257
8036
  return false;
7258
8037
  }
7259
8038
 
7260
- export { indexCommitsForProject, embedUnembeddedCommits, createTagger, createUnifiedSearchDiagnostics, parseIdShapedQuery, resolveMemoriesByIdsForSearch, unifiedSearch, formatSearchResults, findSessionId, findLastUserMessageId, clearAutoSearchForSession, setCtxReduceRegisteredGlobally, resolveCtxReduceAvailabilityFromMessages, resolveCtxReduceAvailability, primeCtxReduceSpawnPermission, ctxReduceSpawnPermissionReadNeeded, spawnAgentFromMessages, spawnAgentFromOpenCodeDb, todowritePermissionDenied, cachedToolPermissionDenied, clearToolPermissionDenied, resolveTodowriteAvailabilityFromMessages, resolveTodowriteAvailability, modelAcceptsEmptyContent, variantChangeBustsProviderCache, canConsumeDeferredOnThisPass, hasReclaimRide, reclaimRideLabel, replayCavemanCompression, replayClearedReasoning, replayStrippedInlineThinking, stripClearedReasoning, snapshotTrailingBlankSourceDecisions, applyFlushedStatuses, stripStructuralNoise, logTransformTiming, hasRecentAssistantCommit, tagMessages, resetDegradedCacheCount2, isSyntheticHeadMessage2, replayRustModeBindingMismatchStrips2, applyRustModeDeferredCompactionMarker2, clearRustModeBoundaryRecord2, runRustModePostprocess2, defaultCompactionMarkerStrategy2, abortSessionFailClosed2, evaluateEmergencyFailClosed2, runPostTransformPhase2 };
8039
+ export { indexCommitsForProject, embedUnembeddedCommits, createTagger, createUnifiedSearchDiagnostics, parseIdShapedQuery, resolveMemoriesByIdsForSearch, unifiedSearch, formatSearchResults, cavemanWordRulesForLanguage, findSessionId, findLastUserMessageId, clearAutoSearchForSession, setCtxReduceRegisteredGlobally, resolveCtxReduceAvailabilityFromMessages, resolveCtxReduceAvailability, primeCtxReduceSpawnPermission, ctxReduceSpawnPermissionReadNeeded, spawnAgentFromMessages, spawnAgentFromOpenCodeDb, todowritePermissionDenied, cachedToolPermissionDenied, clearToolPermissionDenied, resolveTodowriteAvailabilityFromMessages, resolveTodowriteAvailability, canConsumeDeferredOnThisPass, hasReclaimRide, reclaimRideLabel, replayCavemanCompression, DegradedPassRefusalError, degradedPassError, ENGINE_RECONNECTING_USER_MESSAGE, EmergencyFailClosedError, replayClearedReasoning, replayStrippedInlineThinking, stripClearedReasoning, snapshotTrailingBlankSourceDecisions, applyFlushedStatuses, stripStructuralNoise, logTransformTiming, hasRecentAssistantCommit, tagMessages, resetDegradedCacheCount2, isSyntheticHeadMessage2, applyTodoSynthesis2, freezeReasoningOnBustingPass2, firstServedDivergenceIndex2, rustModeServedKeyAfterPersistedStrips2, replayRustModeBindingMismatchStrips2, RUST_MARKER_LOCK_SKIP_LOG2, applyRustModeDeferredCompactionMarker2, clearRustModeBoundaryRecord2, runRustModePostprocess2, reconcileMarkerRepresentation2, clearPendingCompactionMarkerAfterSuccessfulDrain2, defaultCompactionMarkerStrategy2, abortSessionFailClosed2, evaluateEmergencyFailClosed2, finalizeMessageRepresentation2, runPostTransformPhase2, checkM0MutationDriftAndSignal2 };