@cortexkit/opencode-magic-context 0.44.4 → 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 (679) 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-ncwn1jk9.js → derive-budgets-a63zsm5c.js} +3 -3
  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/module-apply.d.ts +4 -25
  40. package/dist/features/magic-context/dreamer/module-apply.d.ts.map +1 -1
  41. package/dist/features/magic-context/dreamer/retrospective-learnings.d.ts.map +1 -1
  42. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +5 -1
  43. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  44. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts +12 -5
  45. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts.map +1 -1
  46. package/dist/features/magic-context/dreamer/task-executor.d.ts +6 -0
  47. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  48. package/dist/features/magic-context/dreamer/task-gates.d.ts +34 -0
  49. package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
  50. package/dist/features/magic-context/dreamer/task-prompts.d.ts +1 -1
  51. package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
  52. package/dist/features/magic-context/dreamer/task-registry.d.ts +7 -5
  53. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  54. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +10 -3
  55. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  56. package/dist/features/magic-context/dreamer/token-budget.d.ts +3 -0
  57. package/dist/features/magic-context/dreamer/token-budget.d.ts.map +1 -1
  58. package/dist/features/magic-context/dreamer/verify.d.ts +2 -2
  59. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  60. package/dist/features/magic-context/git-commits/git-log-reader.d.ts +11 -2
  61. package/dist/features/magic-context/git-commits/git-log-reader.d.ts.map +1 -1
  62. package/dist/features/magic-context/git-commits/indexer.d.ts.map +1 -1
  63. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  64. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts +2 -0
  65. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
  66. package/dist/features/magic-context/legacy-authority-fixture.test-support.d.ts +6 -0
  67. package/dist/features/magic-context/legacy-authority-fixture.test-support.d.ts.map +1 -0
  68. package/dist/features/magic-context/lkg-prefix-chunks.d.ts +53 -0
  69. package/dist/features/magic-context/lkg-prefix-chunks.d.ts.map +1 -0
  70. package/dist/features/magic-context/memory/embedding-backfill.d.ts.map +1 -1
  71. package/dist/features/magic-context/memory/embedding-local.d.ts +8 -0
  72. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  73. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  74. package/dist/features/magic-context/memory/embedding-worker-client.d.ts +27 -0
  75. package/dist/features/magic-context/memory/embedding-worker-client.d.ts.map +1 -0
  76. package/dist/features/magic-context/memory/embedding-worker.d.ts +2 -0
  77. package/dist/features/magic-context/memory/embedding-worker.d.ts.map +1 -0
  78. package/dist/features/magic-context/memory/embedding-worker.fixture.d.ts +2 -0
  79. package/dist/features/magic-context/memory/embedding-worker.fixture.d.ts.map +1 -0
  80. package/dist/features/magic-context/memory/memory-selection.d.ts.map +1 -1
  81. package/dist/features/magic-context/memory/project-identity-cache.d.ts +4 -3
  82. package/dist/features/magic-context/memory/project-identity-cache.d.ts.map +1 -1
  83. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  84. package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
  85. package/dist/features/magic-context/memory/visibility.d.ts +1 -1
  86. package/dist/features/magic-context/memory/visibility.d.ts.map +1 -1
  87. package/dist/features/magic-context/message-fts-rowid-map.d.ts +14 -1
  88. package/dist/features/magic-context/message-fts-rowid-map.d.ts.map +1 -1
  89. package/dist/features/magic-context/message-fts-session-filter.d.ts +14 -0
  90. package/dist/features/magic-context/message-fts-session-filter.d.ts.map +1 -0
  91. package/dist/features/magic-context/message-index.d.ts +1 -7
  92. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  93. package/dist/features/magic-context/message-time-backfill.d.ts.map +1 -1
  94. package/dist/features/magic-context/migration-v94-write-split.d.ts +62 -0
  95. package/dist/features/magic-context/migration-v94-write-split.d.ts.map +1 -0
  96. package/dist/features/magic-context/migration-worker-client.d.ts +23 -0
  97. package/dist/features/magic-context/migration-worker-client.d.ts.map +1 -0
  98. package/dist/features/magic-context/migration-worker-protocol.d.ts +30 -0
  99. package/dist/features/magic-context/migration-worker-protocol.d.ts.map +1 -0
  100. package/dist/features/magic-context/migration-worker.d.ts +2 -0
  101. package/dist/features/magic-context/migration-worker.d.ts.map +1 -0
  102. package/dist/features/magic-context/migrations.d.ts +7 -0
  103. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  104. package/dist/features/magic-context/mural/render-mural.d.ts +24 -2
  105. package/dist/features/magic-context/mural/render-mural.d.ts.map +1 -1
  106. package/dist/features/magic-context/mural/render-trigger.d.ts +1 -1
  107. package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
  108. package/dist/features/magic-context/overflow-detection.d.ts +18 -7
  109. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  110. package/dist/features/magic-context/project-embedding-registry.d.ts +2 -0
  111. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  112. package/dist/features/magic-context/range-parser.d.ts +2 -3
  113. package/dist/features/magic-context/range-parser.d.ts.map +1 -1
  114. package/dist/features/magic-context/resolve-subagent-fallback.d.ts +2 -0
  115. package/dist/features/magic-context/resolve-subagent-fallback.d.ts.map +1 -1
  116. package/dist/features/magic-context/scheduler.d.ts +2 -0
  117. package/dist/features/magic-context/scheduler.d.ts.map +1 -1
  118. package/dist/features/magic-context/search.d.ts +7 -0
  119. package/dist/features/magic-context/search.d.ts.map +1 -1
  120. package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
  121. package/dist/features/magic-context/session-project-storage.d.ts +10 -1
  122. package/dist/features/magic-context/session-project-storage.d.ts.map +1 -1
  123. package/dist/features/magic-context/smart-notes/compiler-prompt.d.ts +1 -1
  124. package/dist/features/magic-context/smart-notes/compiler-prompt.d.ts.map +1 -1
  125. package/dist/features/magic-context/smart-notes/compiler.d.ts +4 -0
  126. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  127. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
  128. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +2 -0
  129. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
  130. package/dist/features/magic-context/smart-notes/ssrf-guard.d.ts +10 -8
  131. package/dist/features/magic-context/smart-notes/ssrf-guard.d.ts.map +1 -1
  132. package/dist/features/magic-context/smart-notes/storage.d.ts +2 -2
  133. package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
  134. package/dist/features/magic-context/smart-notes/types.d.ts +7 -2
  135. package/dist/features/magic-context/smart-notes/types.d.ts.map +1 -1
  136. package/dist/features/magic-context/storage-caveman-rules.d.ts +21 -0
  137. package/dist/features/magic-context/storage-caveman-rules.d.ts.map +1 -0
  138. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  139. package/dist/features/magic-context/storage-compartment-history-version.d.ts +4 -0
  140. package/dist/features/magic-context/storage-compartment-history-version.d.ts.map +1 -0
  141. package/dist/features/magic-context/storage-db.d.ts +62 -2
  142. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  143. package/dist/features/magic-context/storage-identity-merge.d.ts +6 -0
  144. package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
  145. package/dist/features/magic-context/storage-meta-persisted.d.ts +15 -0
  146. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  147. package/dist/features/magic-context/storage-meta-session.d.ts +1 -1
  148. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  149. package/dist/features/magic-context/storage-meta-shared.d.ts +1 -1
  150. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  151. package/dist/features/magic-context/storage-notes.d.ts +2 -2
  152. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  153. package/dist/features/magic-context/storage-reasoning-removal.d.ts +30 -0
  154. package/dist/features/magic-context/storage-reasoning-removal.d.ts.map +1 -0
  155. package/dist/features/magic-context/storage-replay-document.d.ts +42 -5
  156. package/dist/features/magic-context/storage-replay-document.d.ts.map +1 -1
  157. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  158. package/dist/features/magic-context/storage-tags.d.ts +7 -1
  159. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  160. package/dist/features/magic-context/storage.d.ts +1 -1
  161. package/dist/features/magic-context/storage.d.ts.map +1 -1
  162. package/dist/features/magic-context/store-generation-rebase.d.ts.map +1 -1
  163. package/dist/features/magic-context/tag-input.d.ts +4 -0
  164. package/dist/features/magic-context/tag-input.d.ts.map +1 -0
  165. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  166. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  167. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  168. package/dist/ffi-3cx1cxpk.js +78 -0
  169. package/dist/ffi-7bqqe4cd.js +91 -0
  170. package/dist/ffi-7e6gryj5.js +91 -0
  171. package/dist/ffi-bpvkebwr.js +78 -0
  172. package/dist/hooks/magic-context/apply-operations.d.ts +9 -1
  173. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  174. package/dist/hooks/magic-context/auto-search-deadline.d.ts +10 -0
  175. package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -0
  176. package/dist/hooks/magic-context/auto-search-hint.d.ts +3 -0
  177. package/dist/hooks/magic-context/auto-search-hint.d.ts.map +1 -1
  178. package/dist/hooks/magic-context/auto-search-runner.d.ts +3 -0
  179. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  180. package/dist/hooks/magic-context/caveman-cleanup.d.ts +8 -1
  181. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
  182. package/dist/hooks/magic-context/caveman.d.ts +56 -1
  183. package/dist/hooks/magic-context/caveman.d.ts.map +1 -1
  184. package/dist/hooks/magic-context/child-session-spawn.d.ts +2 -0
  185. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
  186. package/dist/hooks/magic-context/command-handler.d.ts +1 -1
  187. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  188. package/dist/hooks/magic-context/compaction-marker-manager.d.ts +1 -1
  189. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  190. package/dist/hooks/magic-context/compartment-parser.d.ts +3 -3
  191. package/dist/hooks/magic-context/compartment-parser.d.ts.map +1 -1
  192. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  193. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +0 -1
  194. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  195. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  196. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  197. package/dist/hooks/magic-context/compartment-runner-types.d.ts +3 -0
  198. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  199. package/dist/hooks/magic-context/compartment-runner-validation.d.ts +6 -0
  200. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  201. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  202. package/dist/hooks/magic-context/degraded-pass-refusal.d.ts +35 -0
  203. package/dist/hooks/magic-context/degraded-pass-refusal.d.ts.map +1 -0
  204. package/dist/hooks/magic-context/derive-budgets.d.ts.map +1 -1
  205. package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -1
  206. package/dist/hooks/magic-context/embed-history-runner.d.ts.map +1 -1
  207. package/dist/hooks/magic-context/emergency-drop.d.ts +15 -0
  208. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  209. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  210. package/dist/hooks/magic-context/execute-status.d.ts +1 -0
  211. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  212. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +17 -0
  213. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  214. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +2 -0
  215. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  216. package/dist/hooks/magic-context/historian-host-runner.d.ts +5 -0
  217. package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
  218. package/dist/hooks/magic-context/historian-prompt-fit.d.ts +116 -0
  219. package/dist/hooks/magic-context/historian-prompt-fit.d.ts.map +1 -0
  220. package/dist/hooks/magic-context/historian-prompt.generated.d.ts +1 -1
  221. package/dist/hooks/magic-context/historian-prompt.generated.d.ts.map +1 -1
  222. package/dist/hooks/magic-context/history-boundary-repair.d.ts +44 -0
  223. package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -0
  224. package/dist/hooks/magic-context/hook.d.ts +4 -0
  225. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  226. package/dist/hooks/magic-context/inject-compartments.d.ts +8 -0
  227. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  228. package/dist/hooks/magic-context/lkg-persist.d.ts +12 -0
  229. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  230. package/dist/hooks/magic-context/lkg-replay-fit.d.ts +104 -0
  231. package/dist/hooks/magic-context/lkg-replay-fit.d.ts.map +1 -0
  232. package/dist/hooks/magic-context/lkg-replay.d.ts +64 -0
  233. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  234. package/dist/hooks/magic-context/module-client.d.ts.map +1 -1
  235. package/dist/hooks/magic-context/module-state-sync-timing.d.ts +1 -1
  236. package/dist/hooks/magic-context/module-state-sync-timing.d.ts.map +1 -1
  237. package/dist/hooks/magic-context/module-state-sync.d.ts +6 -68
  238. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  239. package/dist/hooks/magic-context/module-tool-backends.d.ts +1 -34
  240. package/dist/hooks/magic-context/module-tool-backends.d.ts.map +1 -1
  241. package/dist/hooks/magic-context/module-transport.d.ts +1 -55
  242. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  243. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  244. package/dist/hooks/magic-context/note-nudger.d.ts +2 -0
  245. package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
  246. package/dist/hooks/magic-context/pass-outcome.d.ts +59 -2
  247. package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
  248. package/dist/hooks/magic-context/producer-window-guard.d.ts +6 -0
  249. package/dist/hooks/magic-context/producer-window-guard.d.ts.map +1 -1
  250. package/dist/hooks/magic-context/read-session-chunk.d.ts +13 -2
  251. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  252. package/dist/hooks/magic-context/read-session-formatting.d.ts +11 -0
  253. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  254. package/dist/hooks/magic-context/reasoning-removal.d.ts +60 -0
  255. package/dist/hooks/magic-context/reasoning-removal.d.ts.map +1 -0
  256. package/dist/hooks/magic-context/recomp-orchestrator.d.ts +1 -0
  257. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  258. package/dist/hooks/magic-context/reference-retrieval.d.ts +1 -1
  259. package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -1
  260. package/dist/hooks/magic-context/reply-pages.d.ts +3 -0
  261. package/dist/hooks/magic-context/reply-pages.d.ts.map +1 -0
  262. package/dist/hooks/magic-context/rust-lkg-freeze-registry.d.ts +62 -0
  263. package/dist/hooks/magic-context/rust-lkg-freeze-registry.d.ts.map +1 -0
  264. package/dist/hooks/magic-context/rust-mode-transform.d.ts +17 -85
  265. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  266. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  267. package/dist/hooks/magic-context/sentinel.d.ts +35 -0
  268. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  269. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts +28 -0
  270. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts.map +1 -0
  271. package/dist/hooks/magic-context/single-store-refusal.d.ts +14 -0
  272. package/dist/hooks/magic-context/single-store-refusal.d.ts.map +1 -0
  273. package/dist/hooks/magic-context/storage-busy-refusal.d.ts +7 -0
  274. package/dist/hooks/magic-context/storage-busy-refusal.d.ts.map +1 -1
  275. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  276. package/dist/hooks/magic-context/stripped-command.d.ts +1 -1
  277. package/dist/hooks/magic-context/stripped-command.d.ts.map +1 -1
  278. package/dist/hooks/magic-context/system-injection-stripper.d.ts +7 -0
  279. package/dist/hooks/magic-context/system-injection-stripper.d.ts.map +1 -1
  280. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  281. package/dist/hooks/magic-context/tag-content-primitives.d.ts.map +1 -1
  282. package/dist/hooks/magic-context/tag-id-fallback.d.ts.map +1 -1
  283. package/dist/hooks/magic-context/tag-messages.d.ts +18 -1
  284. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  285. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  286. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  287. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +1 -0
  288. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  289. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +37 -4
  290. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  291. package/dist/hooks/magic-context/transform.d.ts +12 -39
  292. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  293. package/dist/hooks/magic-context/unmanaged-over-window.d.ts +36 -0
  294. package/dist/hooks/magic-context/unmanaged-over-window.d.ts.map +1 -0
  295. package/dist/hooks/magic-context/unresolved-history-boundary.d.ts +15 -0
  296. package/dist/hooks/magic-context/unresolved-history-boundary.d.ts.map +1 -0
  297. package/dist/hooks/magic-context/user-profile-render.d.ts +3 -0
  298. package/dist/hooks/magic-context/user-profile-render.d.ts.map +1 -0
  299. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  300. package/dist/{index-sqp1hz9v.js → index-16ny736w.js} +10190 -25296
  301. package/dist/{index-mrc0twf3.js → index-2aq21j41.js} +1201 -428
  302. package/dist/{index-32b096cc.js → index-2ntg5sd4.js} +6 -2
  303. package/dist/index-4krbw8z9.js +6034 -0
  304. package/dist/{index-33q7s9y2.js → index-75zjgwga.js} +61 -85
  305. package/dist/{index-zx7pmr39.js → index-8fgkmxmy.js} +28 -10
  306. package/dist/index-a4m2b1yv.js +530 -0
  307. package/dist/index-anq4nn6f.js +131 -0
  308. package/dist/index-avwt563y.js +62 -0
  309. package/dist/index-bmzf7zxv.js +445 -0
  310. package/dist/index-e44zzy84.js +10 -0
  311. package/dist/index-en1k8h8m.js +244 -0
  312. package/dist/{index-638hf49n.js → index-f85teqck.js} +15 -6
  313. package/dist/index-fr2z4qy8.js +7810 -0
  314. package/dist/{index-kwe03yde.js → index-fzbvakh0.js} +1 -1
  315. package/dist/{module-asyncify-2EFITU5U-rkqjhjxd.js → index-g20jdh0p.js} +114 -105
  316. package/dist/index-gd5qx1j9.js +398 -0
  317. package/dist/{index-3bygzk2d.js → index-hybnrwq0.js} +169 -4
  318. package/dist/{index-jqcbs2k1.js → index-mc22ayvf.js} +24 -5
  319. package/dist/index-q7yesyk9.js +9118 -0
  320. package/dist/index-remp7e2g.js +214 -0
  321. package/dist/{index-7k55qm8a.js → index-sfpzqvdz.js} +8 -8
  322. package/dist/{index-msqr3x6m.js → index-vvtfyw1z.js} +12 -75
  323. package/dist/index-w9jwmntv.js +202 -0
  324. package/dist/{index-kr5qehbd.js → index-x23gah8c.js} +1 -1
  325. package/dist/{index-jdxxq8cz.js → index-x8a7jmkh.js} +6 -1
  326. package/dist/{index-wprsye9w.js → index-xgt9k6c6.js} +23 -12
  327. package/dist/index-y8v6yerm.js +77 -0
  328. package/dist/index.d.ts.map +1 -1
  329. package/dist/index.js +7519 -8096
  330. package/dist/message-time-backfill-an311pmk.js +124 -0
  331. package/dist/migration-worker.js +53 -0
  332. package/dist/{model-resolution-dxatzjde.js → model-resolution-xhfmyyvy.js} +5 -1
  333. package/dist/module-ES6BEMUI-3cet1pyp.js +12 -0
  334. package/dist/module-asyncify-2EFITU5U-c2razzd9.js +6 -0
  335. package/dist/plugin/boot-deadline.d.ts.map +1 -1
  336. package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
  337. package/dist/plugin/dream-timer-module-client.d.ts +1 -11
  338. package/dist/plugin/dream-timer-module-client.d.ts.map +1 -1
  339. package/dist/plugin/dream-timer.d.ts.map +1 -1
  340. package/dist/plugin/hooks/create-session-hooks.d.ts +8 -0
  341. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  342. package/dist/plugin/messages-transform.d.ts +20 -13
  343. package/dist/plugin/messages-transform.d.ts.map +1 -1
  344. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  345. package/dist/plugin/stale-build-notice.d.ts +16 -0
  346. package/dist/plugin/stale-build-notice.d.ts.map +1 -0
  347. package/dist/{read-session-chunk-339hg90t.js → read-session-chunk-8rxs0tc9.js} +24 -6
  348. package/dist/recomp-orchestrator-nzamtw29.js +39 -0
  349. package/dist/{rpc-notifications-4amf6mf4.js → rpc-notifications-3hed126v.js} +3 -1
  350. package/dist/{safe-notification-target-50gm9c58.js → safe-notification-target-43r8jsxw.js} +3 -3
  351. package/dist/send-session-notification-nqpv7cne.js +28 -0
  352. package/dist/shared/assistant-message-extractor.d.ts +4 -0
  353. package/dist/shared/assistant-message-extractor.d.ts.map +1 -1
  354. package/dist/shared/background-batch-drain.d.ts +8 -0
  355. package/dist/shared/background-batch-drain.d.ts.map +1 -0
  356. package/dist/{features/builtin-commands/commands.d.ts → shared/builtin-commands.d.ts} +1 -1
  357. package/dist/shared/builtin-commands.d.ts.map +1 -0
  358. package/dist/shared/embedding-activity.d.ts +13 -0
  359. package/dist/shared/embedding-activity.d.ts.map +1 -0
  360. package/dist/shared/historian-tool-expansions.d.ts +5 -0
  361. package/dist/shared/historian-tool-expansions.d.ts.map +1 -0
  362. package/dist/shared/historian-tool-template.d.ts +5 -0
  363. package/dist/shared/historian-tool-template.d.ts.map +1 -0
  364. package/dist/shared/historian-transient-error.d.ts +2 -0
  365. package/dist/shared/historian-transient-error.d.ts.map +1 -0
  366. package/dist/shared/jsonc-edit.d.ts.map +1 -1
  367. package/dist/shared/logger.d.ts +7 -0
  368. package/dist/shared/logger.d.ts.map +1 -1
  369. package/dist/shared/model-suggestion-retry.d.ts +2 -1
  370. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  371. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  372. package/dist/shared/off-thread-migration-clock.d.ts +38 -0
  373. package/dist/shared/off-thread-migration-clock.d.ts.map +1 -0
  374. package/dist/shared/plugin-package-version.d.ts +14 -0
  375. package/dist/shared/plugin-package-version.d.ts.map +1 -0
  376. package/dist/shared/project-directory-key.d.ts +26 -0
  377. package/dist/shared/project-directory-key.d.ts.map +1 -0
  378. package/dist/shared/prompt-async-transport.d.ts +4 -0
  379. package/dist/shared/prompt-async-transport.d.ts.map +1 -1
  380. package/dist/shared/prompt-surface-runtime.d.ts +3 -3
  381. package/dist/shared/provider-response-completion.d.ts +12 -0
  382. package/dist/shared/provider-response-completion.d.ts.map +1 -0
  383. package/dist/shared/redaction.d.ts.map +1 -1
  384. package/dist/shared/rpc-client.d.ts +23 -2
  385. package/dist/shared/rpc-client.d.ts.map +1 -1
  386. package/dist/shared/rpc-types.d.ts +19 -0
  387. package/dist/shared/rpc-types.d.ts.map +1 -1
  388. package/dist/shared/rpc-utils.d.ts +34 -0
  389. package/dist/shared/rpc-utils.d.ts.map +1 -1
  390. package/dist/shared/sqlite.d.ts +13 -2
  391. package/dist/shared/sqlite.d.ts.map +1 -1
  392. package/dist/shared/stale-plugin-build.d.ts +21 -0
  393. package/dist/shared/stale-plugin-build.d.ts.map +1 -0
  394. package/dist/shared/status-summary.d.ts +29 -0
  395. package/dist/shared/status-summary.d.ts.map +1 -1
  396. package/dist/shared/status-view-check.d.ts +124 -0
  397. package/dist/shared/status-view-check.d.ts.map +1 -0
  398. package/dist/shared/status-view.d.ts +38 -2
  399. package/dist/shared/status-view.d.ts.map +1 -1
  400. package/dist/shared/tag-owner-id.d.ts +19 -0
  401. package/dist/shared/tag-owner-id.d.ts.map +1 -0
  402. package/dist/shared/tag-transcript.d.ts +2 -1
  403. package/dist/shared/tag-transcript.d.ts.map +1 -1
  404. package/dist/shared/test-temp-dir.d.ts +8 -2
  405. package/dist/shared/test-temp-dir.d.ts.map +1 -1
  406. package/dist/shared/user-facing-codes.d.ts +41 -6
  407. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  408. package/dist/shared/xml-unescape.d.ts +9 -0
  409. package/dist/shared/xml-unescape.d.ts.map +1 -0
  410. package/dist/task-config-v81k8jvk.js +17 -0
  411. package/dist/tools/ctx-expand/constants.d.ts +1 -1
  412. package/dist/tools/ctx-expand/constants.d.ts.map +1 -1
  413. package/dist/tools/ctx-expand/mode.d.ts +4 -0
  414. package/dist/tools/ctx-expand/mode.d.ts.map +1 -1
  415. package/dist/tools/ctx-expand/render.d.ts +5 -1
  416. package/dist/tools/ctx-expand/render.d.ts.map +1 -1
  417. package/dist/tools/ctx-expand/tools.d.ts +2 -0
  418. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  419. package/dist/tools/ctx-expand/types.d.ts +1 -0
  420. package/dist/tools/ctx-expand/types.d.ts.map +1 -1
  421. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  422. package/dist/tools/ctx-note/render.d.ts +2 -0
  423. package/dist/tools/ctx-note/render.d.ts.map +1 -1
  424. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  425. package/dist/tools/ctx-reduce/constants.d.ts +1 -1
  426. package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
  427. package/dist/tools/ctx-search/constants.d.ts +1 -1
  428. package/dist/tools/ctx-search/constants.d.ts.map +1 -1
  429. package/dist/tools/light-descriptions.d.ts +3 -3
  430. package/dist/tools/light-descriptions.d.ts.map +1 -1
  431. package/dist/tools/parameter-descriptions.d.ts +14 -14
  432. package/dist/transform-postprocess-phase-414phndq.js +61 -0
  433. package/dist/tui/data/context-db.d.ts +34 -10
  434. package/dist/tui/data/context-db.d.ts.map +1 -1
  435. package/dist/tui/data/notification-socket.d.ts +6 -0
  436. package/dist/tui/data/notification-socket.d.ts.map +1 -1
  437. package/dist/tui/data/session-directory.d.ts +16 -0
  438. package/dist/tui/data/session-directory.d.ts.map +1 -0
  439. package/dist/tui-compiled/data/context-db.d.ts +34 -10
  440. package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
  441. package/dist/tui-compiled/data/notification-socket.d.ts +6 -0
  442. package/dist/tui-compiled/data/notification-socket.d.ts.map +1 -1
  443. package/dist/tui-compiled/data/session-directory.d.ts +16 -0
  444. package/dist/tui-compiled/data/session-directory.d.ts.map +1 -0
  445. package/dist/v2/derive-budgets-v0krf3t7.js +18 -0
  446. package/dist/v2/embedding-worker.js +47 -0
  447. package/dist/v2/emscripten-module-0g8f45e6.js +602 -0
  448. package/dist/v2/emscripten-module-0pekdjxz.js +1532 -0
  449. package/dist/v2/emscripten-module-e67xwsp3.js +503 -0
  450. package/dist/v2/emscripten-module-pj1vyb44.js +4559 -0
  451. package/dist/v2/ffi-3cx1cxpk.js +78 -0
  452. package/dist/v2/ffi-7bqqe4cd.js +91 -0
  453. package/dist/v2/ffi-7e6gryj5.js +91 -0
  454. package/dist/v2/ffi-bpvkebwr.js +78 -0
  455. package/dist/v2/fold/boundary.d.ts.map +1 -1
  456. package/dist/v2/fork-inheritance.d.ts +101 -0
  457. package/dist/v2/fork-inheritance.d.ts.map +1 -0
  458. package/dist/v2/hidden-child-cleanup.d.ts +11 -0
  459. package/dist/v2/hidden-child-cleanup.d.ts.map +1 -0
  460. package/dist/v2/hidden-child-native.d.ts +29 -0
  461. package/dist/v2/hidden-child-native.d.ts.map +1 -0
  462. package/dist/v2/hidden-child-record.d.ts +135 -0
  463. package/dist/v2/hidden-child-record.d.ts.map +1 -0
  464. package/dist/v2/hidden-completion.d.ts +12 -97
  465. package/dist/v2/hidden-completion.d.ts.map +1 -1
  466. package/dist/v2/hooks/context.d.ts +20 -8
  467. package/dist/v2/hooks/context.d.ts.map +1 -1
  468. package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
  469. package/dist/v2/hooks/dream-trigger.d.ts +5 -0
  470. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  471. package/dist/v2/hooks/generate.d.ts +10 -0
  472. package/dist/v2/hooks/generate.d.ts.map +1 -0
  473. package/dist/v2/hooks/hidden-child.d.ts +33 -2
  474. package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
  475. package/dist/v2/hooks/payload.d.ts +3 -0
  476. package/dist/v2/hooks/payload.d.ts.map +1 -1
  477. package/dist/v2/hooks/session-api-gate.d.ts +4 -0
  478. package/dist/v2/hooks/session-api-gate.d.ts.map +1 -0
  479. package/dist/v2/hooks/storage-gate.d.ts +3 -1
  480. package/dist/v2/hooks/storage-gate.d.ts.map +1 -1
  481. package/dist/v2/hooks/tools.d.ts.map +1 -1
  482. package/dist/v2/hooks/types.d.ts +10 -0
  483. package/dist/v2/hooks/types.d.ts.map +1 -1
  484. package/dist/v2/hooks/update-check.d.ts.map +1 -1
  485. package/dist/v2/hooks/usage-persist.d.ts.map +1 -1
  486. package/dist/v2/hooks/usage-reading.d.ts +4 -0
  487. package/dist/v2/hooks/usage-reading.d.ts.map +1 -1
  488. package/dist/v2/index-6e4mwffh.js +5662 -0
  489. package/dist/v2/index-en1k8h8m.js +244 -0
  490. package/dist/{message-time-backfill-q374fxc5.js → v2/message-time-backfill-0n93vrd7.js} +19 -5
  491. package/dist/v2/migration-worker.js +52 -0
  492. package/dist/v2/model-resolution-xhfmyyvy.js +16 -0
  493. package/dist/v2/module-ES6BEMUI-3cet1pyp.js +12 -0
  494. package/dist/v2/module-asyncify-2EFITU5U-c2razzd9.js +6 -0
  495. package/dist/v2/prompt-context-5y5ms8f9.js +6 -0
  496. package/dist/v2/read-session-chunk-hjza38hr.js +83 -0
  497. package/dist/v2/recomp-orchestrator-1aq7h44c.js +36 -0
  498. package/dist/v2/retrospective-raw-provider.d.ts +21 -0
  499. package/dist/v2/retrospective-raw-provider.d.ts.map +1 -0
  500. package/dist/v2/rpc-notifications-3hed126v.js +16 -0
  501. package/dist/v2/safe-notification-target-wtj0bbc2.js +9 -0
  502. package/dist/{send-session-notification-04hvd54c.js → v2/send-session-notification-mq9frrtm.js} +10 -5
  503. package/dist/v2/server-0jqw05sa.js +803 -0
  504. package/dist/v2/server-5317ykaf.js +40 -0
  505. package/dist/v2/server-a4m2b1yv.js +530 -0
  506. package/dist/v2/server-avwt563y.js +62 -0
  507. package/dist/v2/server-c4g2y1z8.js +28824 -0
  508. package/dist/v2/server-ckpc8pxy.js +662 -0
  509. package/dist/v2/server-e36nf2p1.js +7702 -0
  510. package/dist/v2/server-e44zzy84.js +10 -0
  511. package/dist/v2/server-fgmxwrgy.js +16 -0
  512. package/dist/v2/server-fmsr7v69.js +75 -0
  513. package/dist/v2/server-g20jdh0p.js +1273 -0
  514. package/dist/{index-qm36k34q.js → v2/server-hfjfbg59.js} +796 -737
  515. package/dist/v2/server-n96ag4rk.js +633 -0
  516. package/dist/v2/server-qdjnb2z1.js +181 -0
  517. package/dist/v2/server-qpg6wf72.js +187 -0
  518. package/dist/v2/server-r7cmye3k.js +131 -0
  519. package/dist/v2/server-remp7e2g.js +214 -0
  520. package/dist/v2/server-rhdgxp1t.js +398 -0
  521. package/dist/v2/server-sfpzqvdz.js +137 -0
  522. package/dist/v2/server-syahy8j8.js +50 -0
  523. package/dist/v2/server-v5xgft5v.js +9116 -0
  524. package/dist/v2/server-w99cyt6a.js +361 -0
  525. package/dist/v2/server-x8a7jmkh.js +104 -0
  526. package/dist/v2/server-y8v6yerm.js +77 -0
  527. package/dist/v2/server-z19x7eqz.js +423 -0
  528. package/dist/v2/server.d.ts.map +1 -1
  529. package/dist/v2/server.js +8796 -107376
  530. package/dist/v2/store-reader.d.ts +50 -0
  531. package/dist/v2/store-reader.d.ts.map +1 -1
  532. package/dist/v2/task-config-tbndqyny.js +17 -0
  533. package/dist/v2/transformers-node-wasm.js +26768 -0
  534. package/dist/v2/transformers-web.js +25670 -0
  535. package/dist/v2/transformers.node-hj754h7s.js +29997 -0
  536. package/dist/v2/tui/index.d.ts +10 -1
  537. package/dist/v2/tui/index.d.ts.map +1 -1
  538. package/dist/v2/tui/sidebar-mount.d.ts +6 -0
  539. package/dist/v2/tui/sidebar-mount.d.ts.map +1 -1
  540. package/dist/v2/tui/status-dialog-mount.d.ts +7 -4
  541. package/dist/v2/tui/status-dialog-mount.d.ts.map +1 -1
  542. package/dist/v2/tui/types.d.ts +12 -0
  543. package/dist/v2/tui/types.d.ts.map +1 -1
  544. package/dist/v2/wrapup-orchestrator-tbyx78dz.js +425 -0
  545. package/dist/wrapup-orchestrator-h28bqsy6.js +26 -0
  546. package/package.json +8 -8
  547. package/src/agents/hidden-agent-registrations.ts +24 -16
  548. package/src/agents/magic-context-prompt.test.ts +41 -0
  549. package/src/agents/magic-context-prompt.ts +8 -5
  550. package/src/agents/permissions.test.ts +31 -49
  551. package/src/agents/permissions.ts +8 -28
  552. package/src/config/index.test.ts +60 -20
  553. package/src/config/index.ts +53 -1
  554. package/src/config/live-run-config.test.ts +5 -5
  555. package/src/config/live-snapshot.test.ts +4 -4
  556. package/src/config/migrate-config-location.test.ts +3 -10
  557. package/src/config/project-config-trust-boundary.test.ts +207 -0
  558. package/src/config/project-security.hostile-matrix.test.ts +4 -4
  559. package/src/config/project-security.ts +218 -1
  560. package/src/config/protected-tokens.test.ts +14 -9
  561. package/src/config/raw-loader.test.ts +31 -3
  562. package/src/config/raw-loader.ts +8 -3
  563. package/src/config/schema/magic-context.ts +20 -3
  564. package/src/config/variable.test.ts +3 -2
  565. package/src/features/magic-context/dreamer/cron.ts +30 -9
  566. package/src/features/magic-context/dreamer/task-registry.ts +7 -5
  567. package/src/shared/announcement.test.ts +2 -1
  568. package/src/shared/assistant-message-extractor.test.ts +27 -1
  569. package/src/shared/assistant-message-extractor.ts +27 -0
  570. package/src/shared/background-batch-drain.test.ts +38 -0
  571. package/src/shared/background-batch-drain.ts +29 -0
  572. package/src/shared/builtin-commands.ts +50 -0
  573. package/src/shared/console-diagnostics-fence.test.ts +145 -0
  574. package/src/shared/data-path.test.ts +6 -5
  575. package/src/shared/embedding-activity.test.ts +21 -0
  576. package/src/shared/embedding-activity.ts +36 -0
  577. package/src/shared/historian-tool-defaults.json +13 -0
  578. package/src/shared/historian-tool-expansions.ts +18 -0
  579. package/src/shared/historian-tool-template.ts +248 -0
  580. package/src/shared/historian-transient-error.test.ts +36 -0
  581. package/src/shared/historian-transient-error.ts +22 -0
  582. package/src/shared/jsonc-edit.ts +20 -1
  583. package/src/shared/logger.test.ts +3 -2
  584. package/src/shared/logger.ts +40 -1
  585. package/src/shared/model-suggestion-retry.test.ts +46 -0
  586. package/src/shared/model-suggestion-retry.ts +16 -1
  587. package/src/shared/models-dev-cache.test.ts +74 -2
  588. package/src/shared/models-dev-cache.ts +5 -1
  589. package/src/shared/off-thread-migration-clock.test.ts +55 -0
  590. package/src/shared/off-thread-migration-clock.ts +124 -0
  591. package/src/shared/opencode-db-path.test.ts +3 -2
  592. package/src/shared/plugin-package-version.ts +52 -0
  593. package/src/shared/project-directory-key.test.ts +111 -0
  594. package/src/shared/project-directory-key.ts +54 -0
  595. package/src/shared/prompt-async-transport.test.ts +249 -72
  596. package/src/shared/prompt-async-transport.ts +131 -24
  597. package/src/shared/prompt-surface-a1-golden.md +41 -25
  598. package/src/shared/prompt-surface-runtime.test.ts +3 -3
  599. package/src/shared/provider-response-completion.ts +23 -0
  600. package/src/shared/redaction.test.ts +51 -1
  601. package/src/shared/redaction.ts +33 -0
  602. package/src/shared/rpc-async-probes.test.ts +32 -2
  603. package/src/shared/rpc-client.test.ts +3 -2
  604. package/src/shared/rpc-client.ts +76 -18
  605. package/src/shared/rpc-types.ts +15 -0
  606. package/src/shared/rpc-utils.test.ts +164 -10
  607. package/src/shared/rpc-utils.ts +144 -15
  608. package/src/shared/sqlite-acquisition-routing.test.ts +46 -3
  609. package/src/shared/sqlite-pass-scope.test.ts +3 -2
  610. package/src/shared/sqlite-transaction-mode-guard.test.ts +4 -0
  611. package/src/shared/sqlite-writer-diagnostics.test.ts +134 -0
  612. package/src/shared/sqlite.ts +225 -41
  613. package/src/shared/stale-plugin-build.test.ts +129 -0
  614. package/src/shared/stale-plugin-build.ts +151 -0
  615. package/src/shared/status-summary.ts +40 -13
  616. package/src/shared/status-view-check.test.ts +253 -0
  617. package/src/shared/status-view-check.ts +536 -0
  618. package/src/shared/status-view.test.ts +6 -1
  619. package/src/shared/status-view.ts +176 -4
  620. package/src/shared/storage-busy.test.ts +3 -2
  621. package/src/shared/tag-owner-id.test.ts +33 -0
  622. package/src/shared/tag-owner-id.ts +29 -0
  623. package/src/shared/tag-transcript.ts +13 -2
  624. package/src/shared/test-temp-dir-policy.test.ts +33 -0
  625. package/src/shared/test-temp-dir.test.ts +27 -0
  626. package/src/shared/test-temp-dir.ts +36 -12
  627. package/src/shared/tui-config.test.ts +6 -5
  628. package/src/shared/tui-preferences.test.ts +3 -2
  629. package/src/shared/user-facing-codes.ts +52 -6
  630. package/src/shared/window-geometry.test.ts +3 -2
  631. package/src/shared/write-transaction-attribution.test.ts +11 -7
  632. package/src/shared/write-transaction-hold-clock.test.ts +160 -0
  633. package/src/shared/xml-unescape.ts +19 -0
  634. package/src/tui/data/context-db.test.ts +92 -4
  635. package/src/tui/data/context-db.ts +184 -18
  636. package/src/tui/data/notification-socket.test.ts +49 -2
  637. package/src/tui/data/notification-socket.ts +47 -9
  638. package/src/tui/data/session-directory.ts +19 -0
  639. package/src/tui/dialogs/status-dialog-render.test.ts +284 -0
  640. package/src/tui/dialogs/status-dialog.tsx +41 -38
  641. package/src/tui/index.tsx +30 -18
  642. package/src/tui/slots/sidebar-content.tsx +9 -2
  643. package/src/tui-compiled/data/context-db.ts +184 -18
  644. package/src/tui-compiled/data/notification-socket.ts +47 -9
  645. package/src/tui-compiled/data/session-directory.ts +19 -0
  646. package/src/tui-compiled/dialogs/status-dialog.tsx +38 -29
  647. package/src/tui-compiled/index.tsx +29 -16
  648. package/src/tui-compiled/slots/sidebar-content.tsx +3 -2
  649. package/src/v2/tui/host-contract.test.ts +9 -10
  650. package/src/v2/tui/index.ts +78 -23
  651. package/src/v2/tui/load-compiled-sidebar.d.mts +5 -1
  652. package/src/v2/tui/load-compiled-status-dialog.d.mts +3 -2
  653. package/src/v2/tui/session-directory.test.ts +53 -0
  654. package/src/v2/tui/sidebar-mount.ts +19 -1
  655. package/src/v2/tui/status-dialog-mount.ts +10 -7
  656. package/src/v2/tui/types.ts +10 -0
  657. package/dist/features/builtin-commands/commands.d.ts.map +0 -1
  658. package/dist/features/builtin-commands/types.d.ts +0 -3
  659. package/dist/features/builtin-commands/types.d.ts.map +0 -1
  660. package/dist/features/magic-context/context-authority.d.ts +0 -272
  661. package/dist/features/magic-context/context-authority.d.ts.map +0 -1
  662. package/dist/features/magic-context/memory/mirror-reembed.d.ts +0 -22
  663. package/dist/features/magic-context/memory/mirror-reembed.d.ts.map +0 -1
  664. package/dist/hooks/magic-context/historian-state-file.d.ts +0 -43
  665. package/dist/hooks/magic-context/historian-state-file.d.ts.map +0 -1
  666. package/dist/index-4an2p8qa.js +0 -1056
  667. package/dist/index-rn7gafjr.js +0 -8
  668. package/dist/index-v6t0tg85.js +0 -13
  669. package/dist/plugin/memory-id-translation.d.ts +0 -109
  670. package/dist/plugin/memory-id-translation.d.ts.map +0 -1
  671. package/dist/plugin/rust-note-backend.d.ts +0 -84
  672. package/dist/plugin/rust-note-backend.d.ts.map +0 -1
  673. package/dist/recomp-orchestrator-0ers6smx.js +0 -22
  674. package/dist/task-config-2bm68628.js +0 -9
  675. package/dist/transform-postprocess-phase-ttdkrm6r.js +0 -36
  676. package/dist/v2/host-service.d.ts +0 -66
  677. package/dist/v2/host-service.d.ts.map +0 -1
  678. package/dist/wrapup-orchestrator-x0jvvrqn.js +0 -19
  679. /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-sqp1hz9v.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,33 +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,
179
187
  toolPartHasUserAnswer,
180
188
  isEditTool,
189
+ modelAcceptsEmptyContent,
190
+ neutralizeDroppedReasoningPart,
191
+ restoreNeutralizedReasoningPart,
192
+ isNeutralizedReasoningPart,
193
+ makeSentinel,
194
+ makeWholeMessageSentinel,
195
+ isSentinel,
196
+ replaySentinelByMessageIds,
181
197
  SKELETON_REAL_INPUT_MAX_BYTES,
182
198
  partHasCompletedResult,
183
199
  extractToolCallObservation,
184
200
  ToolMutationBatch,
185
201
  createToolDropTarget
186
- } from "./index-qm36k34q.js";
202
+ } from "./index-4krbw8z9.js";
187
203
  import {
188
- canonicalModelIdentity
189
- } from "./index-msqr3x6m.js";
204
+ openCodeDbExists,
205
+ withReadOnlySessionDb,
206
+ getMessageTimesFromOpenCodeDb
207
+ } from "./index-bmzf7zxv.js";
208
+ import {
209
+ stableStringify
210
+ } from "./index-anq4nn6f.js";
190
211
  import {
191
212
  getErrorMessage
192
- } from "./index-33q7s9y2.js";
213
+ } from "./index-y8v6yerm.js";
193
214
  import {
194
215
  logSlowWriteTransaction
195
- } 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
+ }
196
289
 
197
290
  // src/hooks/magic-context/apply-operations.ts
198
291
  var RECENT_TOOL_SKELETON_WINDOW = 20;
@@ -240,8 +333,8 @@ function foldChangesServedPrefix(before, after) {
240
333
  function foldBustsServedPrefix(reason, before, after) {
241
334
  return CACHE_LOSING_FOLD_REASONS.has(reason ?? "") || foldChangesServedPrefix(before, after);
242
335
  }
243
- function convertLegacyToolSkeletons(db, sessionId, targets) {
244
- 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
245
338
  FROM tags
246
339
  WHERE session_id = ? AND type = 'tool' AND status = 'dropped'
247
340
  AND drop_mode IN ('truncated', 'full')
@@ -254,6 +347,8 @@ function convertLegacyToolSkeletons(db, sessionId, targets) {
254
347
  const cannotRemove = target.cannotRemove?.() === true || target.requiresToolArcSkeleton === true || target.wouldStrandConversationEnd?.() === true;
255
348
  let mode;
256
349
  if (row.dropMode === "full") {
350
+ if (options.keepFullDrop?.(row.callId) === true)
351
+ continue;
257
352
  if (target.cannotRemove?.() !== true)
258
353
  continue;
259
354
  mode = "skeleton_real";
@@ -421,7 +516,7 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
421
516
  }
422
517
  function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
423
518
  let didMutateMessage = false;
424
- const tags = preloadedTags ?? getTagsBySession(db, sessionId);
519
+ const tags = preloadedTags ?? getDroppedTagsByNumbers(db, sessionId, [...targets.keys()]);
425
520
  for (const tag of tags) {
426
521
  if (tag.status === "dropped") {
427
522
  const target = targets.get(tag.tagNumber);
@@ -473,6 +568,7 @@ var GIT_TIMEOUT_MS = 1e4;
473
568
  var DEFAULT_MAX_COMMITS = 5000;
474
569
  var RECORD_SEPARATOR = "\x1E";
475
570
  var FIELD_SEPARATOR = "\x1F";
571
+ var FULL_OBJECT_NAME = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;
476
572
  function classifyGitLogFailure(message) {
477
573
  if (message.includes("not a git repository"))
478
574
  return "not_a_repo";
@@ -487,9 +583,11 @@ async function readGitCommitsResult(directory, options = {}) {
487
583
  throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
488
584
  }
489
585
  const projectLabel = options.projectIdentity ?? "<project>";
586
+ const exclusion = options.excludeReachableFrom && FULL_OBJECT_NAME.test(options.excludeReachableFrom) ? options.excludeReachableFrom : null;
490
587
  const args = [
491
588
  "log",
492
589
  revision,
590
+ ...exclusion ? [`^${exclusion}`] : [],
493
591
  "--no-merges",
494
592
  `--max-count=${options.maxCommits ?? DEFAULT_MAX_COMMITS}`,
495
593
  `--format=%H${FIELD_SEPARATOR}%s${FIELD_SEPARATOR}%ae${FIELD_SEPARATOR}%ct${FIELD_SEPARATOR}%b${RECORD_SEPARATOR}`
@@ -498,6 +596,7 @@ async function readGitCommitsResult(directory, options = {}) {
498
596
  const iso = new Date(options.sinceMs).toISOString();
499
597
  args.push(`--since=${iso}`);
500
598
  }
599
+ args.push("--");
501
600
  let stdout;
502
601
  try {
503
602
  const result = await execFileAsync("git", args, {
@@ -510,6 +609,10 @@ async function readGitCommitsResult(directory, options = {}) {
510
609
  stdout = result.stdout;
511
610
  } catch (error) {
512
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
+ }
513
616
  const failure = classifyGitLogFailure(message);
514
617
  if (failure === "transient") {
515
618
  log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
@@ -547,7 +650,7 @@ function parseGitLogOutput(stdout) {
547
650
  const author = fields[2].trim();
548
651
  const timeSec = Number.parseInt(fields[3].trim(), 10);
549
652
  const body = fields[4].trim();
550
- if (sha.length !== 40 || !Number.isFinite(timeSec) || timeSec <= 0) {
653
+ if (!FULL_OBJECT_NAME.test(sha) || !Number.isFinite(timeSec) || timeSec <= 0) {
551
654
  continue;
552
655
  }
553
656
  const message = body.length > 0 ? `${subject}
@@ -585,12 +688,13 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
585
688
  }
586
689
  indexInProgress.add(projectPath);
587
690
  try {
588
- const latestIndexed = getLatestIndexedCommitTimeMs(db, projectPath);
589
- 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;
590
693
  const read = await readGitCommitsResult(directory, {
591
694
  sinceMs,
592
695
  maxCommits: options.maxCommits,
593
- projectIdentity: projectPath
696
+ projectIdentity: projectPath,
697
+ excludeReachableFrom: latestIndexed ?? undefined
594
698
  });
595
699
  const commits = read.commits;
596
700
  result.scanned = commits.length;
@@ -600,10 +704,10 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
600
704
  }
601
705
  if (commits.length === 0) {
602
706
  result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
603
- 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})`);
604
708
  return result;
605
709
  }
606
- 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"})`);
607
711
  const upsert = upsertCommits(db, projectPath, commits);
608
712
  result.inserted = upsert.inserted;
609
713
  result.updated = upsert.updated;
@@ -710,6 +814,9 @@ function getFtsStatement(db, dated = false) {
710
814
  }
711
815
  return stmt;
712
816
  }
817
+ function escapeLikePattern(text) {
818
+ return text.replace(/[\\%_]/g, (char) => `\\${char}`);
819
+ }
713
820
  function getLikeFallbackStatement(db, dated = false) {
714
821
  const statements = dated ? datedFtsPlainStatements : ftsPlainStatements;
715
822
  let stmt = statements.get(db);
@@ -718,7 +825,7 @@ function getLikeFallbackStatement(db, dated = false) {
718
825
  FROM git_commits
719
826
  WHERE project_path = ?
720
827
  ${dated ? "AND committed_at BETWEEN ? AND ?" : ""}
721
- AND lower(message) LIKE '%' || lower(?) || '%'
828
+ AND lower(message) LIKE '%' || lower(?) || '%' ESCAPE '\\'
722
829
  ORDER BY committed_at DESC LIMIT ?`);
723
830
  statements.set(db, stmt);
724
831
  }
@@ -765,7 +872,7 @@ function searchGitCommitsSync(db, projectPath, query, options) {
765
872
  }
766
873
  }
767
874
  if (ftsCandidates.length === 0) {
768
- 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)) {
769
876
  ftsCandidates.push(rowToCommit(row));
770
877
  }
771
878
  }
@@ -875,6 +982,61 @@ function containsProbeVerbatim(text, probes) {
875
982
  return probes.some((probe) => haystack.includes(probe.toLowerCase()));
876
983
  }
877
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
+
878
1040
  // src/features/magic-context/search-measurement.ts
879
1041
  import { createHash } from "node:crypto";
880
1042
  function resultId(result) {
@@ -968,6 +1130,7 @@ function sha256(value) {
968
1130
 
969
1131
  // src/features/magic-context/search.ts
970
1132
  var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
1133
+ var MAX_UNIFIED_SEARCH_LIMIT = 25;
971
1134
  var FTS_SEMANTIC_CANDIDATE_LIMIT = 50;
972
1135
  var SEMANTIC_WEIGHT = 0.7;
973
1136
  var FTS_WEIGHT = 0.3;
@@ -978,9 +1141,12 @@ var MESSAGE_SOURCE_BOOST = 1.275;
978
1141
  var GIT_COMMIT_SOURCE_BOOST = 1.2;
979
1142
  var PRIMER_SOURCE_BOOST = 1.25;
980
1143
  var messageSearchStatements = new WeakMap;
1144
+ var sessionFirstMessageSearchStatements = new WeakMap;
981
1145
  var messageSearchStatementsWithCutoff = new WeakMap;
1146
+ var sessionFirstMessageSearchStatementsWithCutoff = new WeakMap;
982
1147
  var messageSearchStatementsWithDateRange = new WeakMap;
983
1148
  var messageSearchDiagnosticStatements = new WeakMap;
1149
+ var sessionFirstMessageSearchDiagnosticStatements = new WeakMap;
984
1150
  var messageSearchDiagnosticStatementsWithDateRange = new WeakMap;
985
1151
  var batchedMessageSearchStatements = new WeakMap;
986
1152
  var batchedFtsCountStatements = new WeakMap;
@@ -995,7 +1161,7 @@ function normalizeLimit(limit) {
995
1161
  if (typeof limit !== "number" || !Number.isFinite(limit)) {
996
1162
  return DEFAULT_UNIFIED_SEARCH_LIMIT;
997
1163
  }
998
- return Math.max(1, Math.floor(limit));
1164
+ return Math.min(MAX_UNIFIED_SEARCH_LIMIT, Math.max(1, Math.floor(limit)));
999
1165
  }
1000
1166
  function normalizeDateRange(from, to) {
1001
1167
  if (from === undefined && to === undefined)
@@ -1076,19 +1242,21 @@ function sourceNamesForSearchMemories(args) {
1076
1242
  }
1077
1243
  return sourceNames.size > 0 ? sourceNames : undefined;
1078
1244
  }
1079
- function getMessageSearchStatement(db) {
1080
- let stmt = messageSearchStatements.get(db);
1245
+ function getMessageSearchStatement(db, sessionFirst) {
1246
+ const statements = sessionFirst ? sessionFirstMessageSearchStatements : messageSearchStatements;
1247
+ let stmt = statements.get(db);
1081
1248
  if (!stmt) {
1082
- 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 ?");
1083
- 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);
1084
1251
  }
1085
1252
  return stmt;
1086
1253
  }
1087
- function getMessageSearchStatementWithCutoff(db) {
1088
- let stmt = messageSearchStatementsWithCutoff.get(db);
1254
+ function getMessageSearchStatementWithCutoff(db, sessionFirst) {
1255
+ const statements = sessionFirst ? sessionFirstMessageSearchStatementsWithCutoff : messageSearchStatementsWithCutoff;
1256
+ let stmt = statements.get(db);
1089
1257
  if (!stmt) {
1090
- 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 ?");
1091
- 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);
1092
1260
  }
1093
1261
  return stmt;
1094
1262
  }
@@ -1109,9 +1277,9 @@ function getMessageSearchStatementWithDateRange(db, withCutoff) {
1109
1277
  JOIN message_fts_rowid_map AS map
1110
1278
  ON map.session_id = message_history_fts.session_id
1111
1279
  AND map.fts_rowid = message_history_fts.rowid
1112
- WHERE message_history_fts.session_id = ?
1113
- AND message_history_fts MATCH ?
1114
- 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 ?
1115
1283
  ${withCutoff ? "AND CAST(message_history_fts.message_ordinal AS INTEGER) <= ?" : ""}
1116
1284
  ORDER BY bm25(message_history_fts),
1117
1285
  CAST(message_history_fts.message_ordinal AS INTEGER) ASC
@@ -1120,8 +1288,9 @@ function getMessageSearchStatementWithDateRange(db, withCutoff) {
1120
1288
  }
1121
1289
  return statement;
1122
1290
  }
1123
- function getMessageSearchDiagnosticStatement(db) {
1124
- let stmt = messageSearchDiagnosticStatements.get(db);
1291
+ function getMessageSearchDiagnosticStatement(db, sessionFirst) {
1292
+ const statements = sessionFirst ? sessionFirstMessageSearchDiagnosticStatements : messageSearchDiagnosticStatements;
1293
+ let stmt = statements.get(db);
1125
1294
  if (!stmt) {
1126
1295
  stmt = db.prepare(`
1127
1296
  WITH matches AS MATERIALIZED (
@@ -1133,7 +1302,7 @@ function getMessageSearchDiagnosticStatement(db) {
1133
1302
  CAST(message_ordinal AS INTEGER) AS ordinalValue,
1134
1303
  bm25(message_history_fts) AS ftsRank
1135
1304
  FROM message_history_fts
1136
- WHERE session_id = ? AND message_history_fts MATCH ?
1305
+ WHERE ${sessionFirst ? MESSAGE_FTS_SESSION_FILTER_SQL : ""}session_id = ?1 AND message_history_fts MATCH ?
1137
1306
  ),
1138
1307
  eligible AS (
1139
1308
  SELECT * FROM matches
@@ -1161,7 +1330,7 @@ function getMessageSearchDiagnosticStatement(db) {
1161
1330
  WHERE NOT EXISTS (SELECT 1 FROM eligible)
1162
1331
  ORDER BY summaryOnly ASC, ftsRank ASC, messageOrdinal ASC
1163
1332
  `);
1164
- messageSearchDiagnosticStatements.set(db, stmt);
1333
+ statements.set(db, stmt);
1165
1334
  }
1166
1335
  return stmt;
1167
1336
  }
@@ -1181,9 +1350,9 @@ function getMessageSearchDiagnosticStatementWithDateRange(db) {
1181
1350
  JOIN message_fts_rowid_map AS map
1182
1351
  ON map.session_id = message_history_fts.session_id
1183
1352
  AND map.fts_rowid = message_history_fts.rowid
1184
- WHERE message_history_fts.session_id = ?
1185
- AND message_history_fts MATCH ?
1186
- 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 ?
1187
1356
  ),
1188
1357
  eligible AS (
1189
1358
  SELECT * FROM matches
@@ -1215,13 +1384,13 @@ function getMessageSearchDiagnosticStatementWithDateRange(db) {
1215
1384
  }
1216
1385
  return statement;
1217
1386
  }
1218
- function getBatchedFtsCountStatement(db, queryCount, cutoff, dateRange) {
1387
+ function getBatchedFtsCountStatement(db, queryCount, cutoff, dateRange, sessionFirst) {
1219
1388
  let statements = batchedFtsCountStatements.get(db);
1220
1389
  if (!statements) {
1221
1390
  statements = new Map;
1222
1391
  batchedFtsCountStatements.set(db, statements);
1223
1392
  }
1224
- 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}`;
1225
1394
  let statement = statements.get(key);
1226
1395
  if (!statement) {
1227
1396
  const cutoffSql = cutoff === null ? "" : " AND CAST(message_history_fts.message_ordinal AS INTEGER) <= ?";
@@ -1231,27 +1400,30 @@ function getBatchedFtsCountStatement(db, queryCount, cutoff, dateRange) {
1231
1400
  const dateSql = dateRange === null ? "" : " AND map.message_time_ms BETWEEN ? AND ?";
1232
1401
  statement = db.prepare(Array.from({ length: queryCount }, (_, index) => `SELECT ${index} AS queryIndex, COUNT(*) AS count
1233
1402
  FROM message_history_fts${joinSql}
1234
- WHERE message_history_fts.session_id = ?
1235
- 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(`
1236
1405
  UNION ALL
1237
1406
  `));
1238
1407
  statements.set(key, statement);
1239
1408
  }
1240
1409
  return statement;
1241
1410
  }
1242
- 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) {
1243
1415
  if (ftsQueries.length === 0)
1244
1416
  return [];
1245
1417
  const bindings = [];
1246
1418
  for (const query of ftsQueries) {
1247
- bindings.push(sessionId, query);
1419
+ bindings.push(sessionId, contentOnlyMessageQuery(query));
1248
1420
  if (dateRange !== null)
1249
1421
  bindings.push(dateRange.from, dateRange.to);
1250
1422
  if (cutoff !== null)
1251
1423
  bindings.push(cutoff);
1252
1424
  }
1253
1425
  try {
1254
- const rows = getBatchedFtsCountStatement(db, ftsQueries.length, cutoff, dateRange).all(...bindings);
1426
+ const rows = getBatchedFtsCountStatement(db, ftsQueries.length, cutoff, dateRange, sessionFirst).all(...bindings);
1255
1427
  const counts = Array.from({ length: ftsQueries.length }, () => 0);
1256
1428
  for (const row of rows) {
1257
1429
  if (typeof row.queryIndex === "number" && row.queryIndex >= 0 && row.queryIndex < counts.length && typeof row.count === "number") {
@@ -1348,10 +1520,8 @@ function selectSemanticCandidates(args) {
1348
1520
  if (args.queryModelId && args.queryModelId !== "off") {
1349
1521
  const embeddingProjects = args.workspace?.isWorkspaced ? args.workspace.identities : [args.projectPath];
1350
1522
  for (const projectPath of embeddingProjects) {
1351
- const cachedEmbeddings = peekProjectEmbeddings(projectPath, args.queryModelId);
1352
- if (!cachedEmbeddings)
1353
- continue;
1354
- for (const memoryId of cachedEmbeddings.keys()) {
1523
+ const storedEmbeddings = getProjectEmbeddings(args.db, projectPath, args.queryModelId);
1524
+ for (const memoryId of storedEmbeddings.keys()) {
1355
1525
  candidateIds.add(memoryId);
1356
1526
  }
1357
1527
  }
@@ -1428,6 +1598,7 @@ async function searchMemories(args) {
1428
1598
  });
1429
1599
  const ftsScores = getFtsScores(ftsMatches);
1430
1600
  const semanticCandidates = selectSemanticCandidates({
1601
+ db: args.db,
1431
1602
  memories,
1432
1603
  projectPath: args.projectPath,
1433
1604
  ftsMatches,
@@ -1482,18 +1653,19 @@ function normalizeMessageSearchRow(row, cutoff) {
1482
1653
  content: row.content
1483
1654
  };
1484
1655
  }
1485
- function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff, dateRange) {
1656
+ function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff, dateRange, sessionFirst) {
1486
1657
  if (ftsQuery.length === 0)
1487
1658
  return [];
1488
1659
  let rawRows;
1660
+ const matchQuery = contentOnlyMessageQuery(ftsQuery);
1489
1661
  if (dateRange !== null) {
1490
- const bindings = [sessionId, ftsQuery, dateRange.from, dateRange.to];
1662
+ const bindings = [sessionId, matchQuery, dateRange.from, dateRange.to];
1491
1663
  if (cutoff !== null)
1492
1664
  bindings.push(cutoff);
1493
1665
  bindings.push(fetchLimit);
1494
1666
  rawRows = getMessageSearchStatementWithDateRange(db, cutoff !== null).all(...bindings);
1495
1667
  } else {
1496
- 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);
1497
1669
  }
1498
1670
  const rows = rawRows.map((row) => row);
1499
1671
  const result = [];
@@ -1507,7 +1679,8 @@ function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff, dateRan
1507
1679
  function runMessageFtsQueryWithDiagnostics(args) {
1508
1680
  if (args.ftsQuery.length === 0)
1509
1681
  return { rows: [], suppressedCount: 0 };
1510
- 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);
1511
1684
  const suppressedCount = rawRows[0]?.suppressedCount ?? 0;
1512
1685
  const rows = [];
1513
1686
  for (const row of rawRows) {
@@ -1519,13 +1692,13 @@ function runMessageFtsQueryWithDiagnostics(args) {
1519
1692
  }
1520
1693
  return { rows, suppressedCount };
1521
1694
  }
1522
- function getBatchedMessageSearchStatement(db, queryCount, cutoff, dateRange) {
1695
+ function getBatchedMessageSearchStatement(db, queryCount, cutoff, dateRange, sessionFirst) {
1523
1696
  let statements = batchedMessageSearchStatements.get(db);
1524
1697
  if (!statements) {
1525
1698
  statements = new Map;
1526
1699
  batchedMessageSearchStatements.set(db, statements);
1527
1700
  }
1528
- 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}`;
1529
1702
  let statement = statements.get(key);
1530
1703
  if (!statement) {
1531
1704
  const cutoffSql = cutoff === null ? "" : " AND CAST(message_history_fts.message_ordinal AS INTEGER) <= ?";
@@ -1541,8 +1714,8 @@ function getBatchedMessageSearchStatement(db, queryCount, cutoff, dateRange) {
1541
1714
  message_history_fts.content AS content,
1542
1715
  bm25(message_history_fts) AS ftsRank
1543
1716
  FROM message_history_fts${joinSql}
1544
- WHERE message_history_fts.session_id = ?
1545
- 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}
1546
1719
  ORDER BY ftsRank
1547
1720
  LIMIT ?
1548
1721
  )`);
@@ -1554,19 +1727,19 @@ ORDER BY queryIndex ASC, ftsRank ASC`);
1554
1727
  }
1555
1728
  return statement;
1556
1729
  }
1557
- function runMessageFtsQueriesBatch(db, sessionId, ftsQueries, fetchLimit, cutoff, dateRange) {
1730
+ function runMessageFtsQueriesBatch(db, sessionId, ftsQueries, fetchLimit, cutoff, dateRange, sessionFirst) {
1558
1731
  if (ftsQueries.length === 0)
1559
1732
  return [];
1560
1733
  const bindings = [];
1561
1734
  for (const query of ftsQueries) {
1562
- bindings.push(sessionId, query);
1735
+ bindings.push(sessionId, contentOnlyMessageQuery(query));
1563
1736
  if (dateRange !== null)
1564
1737
  bindings.push(dateRange.from, dateRange.to);
1565
1738
  if (cutoff !== null)
1566
1739
  bindings.push(cutoff);
1567
1740
  bindings.push(fetchLimit);
1568
1741
  }
1569
- const rows = getBatchedMessageSearchStatement(db, ftsQueries.length, cutoff, dateRange).all(...bindings);
1742
+ const rows = getBatchedMessageSearchStatement(db, ftsQueries.length, cutoff, dateRange, sessionFirst).all(...bindings);
1570
1743
  const result = Array.from({ length: ftsQueries.length }, () => []);
1571
1744
  for (const row of rows) {
1572
1745
  if (typeof row.queryIndex !== "number" || row.queryIndex < 0 || row.queryIndex >= result.length) {
@@ -1587,6 +1760,9 @@ function probeDiscriminationWeight(df, corpusSize) {
1587
1760
  return 1 / (1 + IDF_FALLOFF * df / corpusSize);
1588
1761
  }
1589
1762
  function searchMessages(args) {
1763
+ return withMessageFtsSessionFilter(args.db, args.sessionId, (sessionFirst) => searchMessagesInSnapshot(args, sessionFirst));
1764
+ }
1765
+ function searchMessagesInSnapshot(args, sessionFirst) {
1590
1766
  const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
1591
1767
  const fetchLimit = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.limit * 3 : args.limit;
1592
1768
  const baseQuery = sanitizeFtsQuery(args.query.trim());
@@ -1598,15 +1774,16 @@ function searchMessages(args) {
1598
1774
  ftsQuery: baseQuery,
1599
1775
  fetchLimit,
1600
1776
  cutoff,
1601
- dateRange: args.dateRange
1777
+ dateRange: args.dateRange,
1778
+ sessionFirst
1602
1779
  }) : {
1603
- rows: runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff, args.dateRange),
1780
+ rows: runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff, args.dateRange, sessionFirst),
1604
1781
  suppressedCount: 0
1605
1782
  };
1606
1783
  if (args.diagnostics) {
1607
1784
  args.diagnostics.suppressedLiveMessageMatches = outcome.suppressedCount;
1608
1785
  }
1609
- 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);
1610
1787
  const filtered = rows.slice(0, args.limit);
1611
1788
  return filtered.map((row, rank) => ({
1612
1789
  source: "message",
@@ -1619,7 +1796,7 @@ function searchMessages(args) {
1619
1796
  }
1620
1797
  const sanitizedProbes = probes.map((probe) => ({ probe, query: sanitizeFtsQuery(probe) })).filter((entry) => entry.query.length > 0);
1621
1798
  const corpusSize = getIndexedMessageCorpusSize(args.db, args.sessionId, cutoff);
1622
- 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);
1623
1800
  const collectBaseDiagnostics = args.diagnostics !== undefined && cutoff !== null;
1624
1801
  const baseOutcome = collectBaseDiagnostics && baseQuery.length > 0 ? runMessageFtsQueryWithDiagnostics({
1625
1802
  db: args.db,
@@ -1627,7 +1804,8 @@ function searchMessages(args) {
1627
1804
  ftsQuery: baseQuery,
1628
1805
  fetchLimit,
1629
1806
  cutoff,
1630
- dateRange: args.dateRange
1807
+ dateRange: args.dateRange,
1808
+ sessionFirst
1631
1809
  }) : null;
1632
1810
  if (args.diagnostics) {
1633
1811
  args.diagnostics.suppressedLiveMessageMatches = baseOutcome?.suppressedCount ?? 0;
@@ -1636,7 +1814,7 @@ function searchMessages(args) {
1636
1814
  ...!collectBaseDiagnostics && baseQuery.length > 0 ? [baseQuery] : [],
1637
1815
  ...sanitizedProbes.map((entry) => entry.query)
1638
1816
  ];
1639
- 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);
1640
1818
  const queryLists = [];
1641
1819
  let queryIndex = 0;
1642
1820
  if (baseQuery.length > 0) {
@@ -2078,7 +2256,7 @@ function resolveMemoriesByIdsForSearch(args) {
2078
2256
  async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
2079
2257
  const trimmedQuery = query.trim();
2080
2258
  const measurementStartedAt = Date.now();
2081
- if (trimmedQuery.length === 0) {
2259
+ if (trimmedQuery.length === 0 || options.signal?.aborted) {
2082
2260
  return [];
2083
2261
  }
2084
2262
  const limit = normalizeLimit(options.limit);
@@ -2110,6 +2288,8 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
2110
2288
  return null;
2111
2289
  }) : Promise.resolve(null);
2112
2290
  await Promise.resolve();
2291
+ if (options.signal?.aborted)
2292
+ return [];
2113
2293
  const messageProbes = options.explicitSearch ? extractLiteralProbes(trimmedQuery) : [];
2114
2294
  const messageResults = runMessages ? searchMessages({
2115
2295
  db,
@@ -2123,6 +2303,8 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
2123
2303
  dateRange
2124
2304
  }) : [];
2125
2305
  const capturedQuery = await queryEmbeddingPromise;
2306
+ if (options.signal?.aborted)
2307
+ return [];
2126
2308
  const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
2127
2309
  const queryContract = capturedQuery instanceof Float32Array || capturedQuery === null ? null : capturedQuery;
2128
2310
  const generationIsCurrent = queryContract === null || embeddingSnapshot !== null && embeddingSnapshot.generation === queryContract.generation;
@@ -2349,34 +2531,169 @@ ${bodyParts.join(`
2349
2531
  `)}`;
2350
2532
  }
2351
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
+
2352
2570
  // src/hooks/magic-context/caveman.ts
2353
- var PRESERVATION_PATTERNS = [
2571
+ var PRESERVATION_PATTERNS_BEFORE_PATHS = [
2354
2572
  /```[\s\S]*?```/g,
2355
2573
  /`[^`\n]+`/g,
2356
2574
  /https?:\/\/\S+/g,
2357
- /§\d+§/g,
2358
- /\b(?:msg|ses|toolu)_[A-Za-z0-9]+/g,
2359
- /(?:\.{1,2}\/)?(?:[\w.-]+\/)+[\w.-]+\.\w{1,6}/g,
2360
- /(?<![a-z0-9])[0-9a-f]{7,40}(?![a-z0-9])/gi
2575
+ /§\d+§/g
2361
2576
  ];
2362
- 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) {
2363
2633
  const preserved = [];
2634
+ const placeholderFor = (original) => {
2635
+ const placeholder = `\x00MC_PRES_${preserved.length}\x00`;
2636
+ preserved.push({ placeholder, original });
2637
+ return placeholder;
2638
+ };
2364
2639
  let working = text;
2365
- for (const pattern of PRESERVATION_PATTERNS) {
2366
- working = working.replace(pattern, (match) => {
2367
- const placeholder = `\x00MC_PRES_${preserved.length}\x00`;
2368
- preserved.push({ placeholder, original: match });
2369
- return placeholder;
2370
- });
2640
+ for (const pattern of PRESERVATION_PATTERNS_BEFORE_PATHS) {
2641
+ working = working.replace(pattern, (match) => placeholderFor(match));
2371
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));
2372
2655
  return { text: working, preserved };
2373
2656
  }
2374
- function restoreRegions(text, preserved) {
2375
- let working = text;
2376
- for (let i = preserved.length - 1;i >= 0; i--) {
2377
- 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;
2378
2666
  }
2379
- 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);
2380
2697
  }
2381
2698
  var FILLER_WORDS = [
2382
2699
  "just",
@@ -2473,7 +2790,7 @@ var ULTRA_ABBREVIATIONS = {
2473
2790
  };
2474
2791
  function buildPhraseDropRegex(phrases) {
2475
2792
  const escaped = phrases.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
2476
- return new RegExp(`(\\s+)?\\b(?:${escaped.join("|")})\\b`, "gi");
2793
+ return new RegExp(`(?:(?<!\\s)\\s+)?\\b(?:${escaped.join("|")})\\b`, "gi");
2477
2794
  }
2478
2795
  function dropPhrases(text, phrases) {
2479
2796
  return text.replace(buildPhraseDropRegex(phrases), "");
@@ -2486,7 +2803,7 @@ function dropArticles(text) {
2486
2803
  function dropAuxiliaries(text) {
2487
2804
  const sorted = [...AUXILIARIES].sort((a, b) => b.length - a.length);
2488
2805
  const escaped = sorted.map((a) => a.replace(/\s+/g, "\\s+"));
2489
- 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");
2490
2807
  let working = text.replace(pattern, " ");
2491
2808
  working = working.replace(/ +/g, " ");
2492
2809
  return working;
@@ -2554,10 +2871,125 @@ function normalizeWhitespace(text) {
2554
2871
 
2555
2872
  `);
2556
2873
  }
2557
- 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") {
2558
2965
  if (text.length === 0)
2559
2966
  return text;
2560
- 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);
2561
2993
  const transformed = transformPreservingUserLines(protectedText, (chunk) => {
2562
2994
  let working = chunk;
2563
2995
  working = dropPhrases(working, FILLER_WORDS);
@@ -2574,7 +3006,7 @@ function cavemanCompress(text, level) {
2574
3006
  }
2575
3007
  return working;
2576
3008
  });
2577
- const restored = restoreRegions(transformed, preserved);
3009
+ const restored = restoreRegions(transformed, preserved, text.includes("\x00"));
2578
3010
  return normalizeWhitespace(restored).trim();
2579
3011
  }
2580
3012
 
@@ -2608,10 +3040,10 @@ function formatAge(committedAtMs) {
2608
3040
  const years = Math.floor(days / 365);
2609
3041
  return years === 1 ? "1y ago" : `${years}y ago`;
2610
3042
  }
2611
- function renderFragment(result, charCap) {
3043
+ function renderFragment(result, charCap, wordRules) {
2612
3044
  switch (result.source) {
2613
3045
  case "memory": {
2614
- const compressed = cavemanCompress(result.content, "ultra");
3046
+ const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2615
3047
  return truncate(compressed, charCap);
2616
3048
  }
2617
3049
  case "git_commit": {
@@ -2620,20 +3052,20 @@ function renderFragment(result, charCap) {
2620
3052
  return `commit ${result.shortSha} ${formatAge(result.committedAtMs)}: ${body}`;
2621
3053
  }
2622
3054
  case "message": {
2623
- const compressed = cavemanCompress(result.content, "ultra");
3055
+ const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2624
3056
  return truncate(compressed, charCap);
2625
3057
  }
2626
3058
  case "compartment": {
2627
3059
  const source = result.snippet ?? result.title;
2628
- const compressed = cavemanCompress(source, "ultra");
3060
+ const compressed = cavemanCompress(source, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2629
3061
  return truncate(compressed, charCap);
2630
3062
  }
2631
3063
  case "primer": {
2632
- const compressed = cavemanCompress(result.content, "ultra");
3064
+ const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2633
3065
  return truncate(compressed, charCap);
2634
3066
  }
2635
3067
  case "note": {
2636
- const compressed = cavemanCompress(result.content, "ultra");
3068
+ const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
2637
3069
  return truncate(compressed, charCap);
2638
3070
  }
2639
3071
  }
@@ -2644,7 +3076,7 @@ function buildAutoSearchHint(results, options = {}) {
2644
3076
  const picks = results.slice(0, maxFragments);
2645
3077
  const lines = [];
2646
3078
  for (const result of picks) {
2647
- const fragment = renderFragment(result, fragmentCharCap);
3079
+ const fragment = renderFragment(result, fragmentCharCap, options.wordRules ?? "english");
2648
3080
  if (fragment.length === 0)
2649
3081
  continue;
2650
3082
  lines.push(`- ${fragment}`);
@@ -2763,30 +3195,6 @@ function appendReminderToUserMessage(message, reminder) {
2763
3195
  }
2764
3196
 
2765
3197
  // src/hooks/magic-context/auto-search-runner.ts
2766
- var AUTO_SEARCH_TIMEOUT_MS = 3000;
2767
- async function unifiedSearchWithTimeout(db, sessionId, projectPath, prompt, options, timeoutMs) {
2768
- const controller = new AbortController;
2769
- let timer;
2770
- const timeoutPromise = new Promise((resolve) => {
2771
- timer = setTimeout(() => {
2772
- controller.abort();
2773
- resolve(null);
2774
- }, timeoutMs);
2775
- });
2776
- try {
2777
- return await Promise.race([
2778
- unifiedSearch(db, sessionId, projectPath, prompt, {
2779
- ...options,
2780
- signal: controller.signal,
2781
- countRetrievals: false
2782
- }),
2783
- timeoutPromise
2784
- ]);
2785
- } finally {
2786
- if (timer !== undefined)
2787
- clearTimeout(timer);
2788
- }
2789
- }
2790
3198
  var AUTO_SEARCH_OK = { ok: true };
2791
3199
  function collectUserPromptParts(message) {
2792
3200
  let collected = "";
@@ -2847,6 +3255,7 @@ function findLatestMeaningfulUserMessage(messages) {
2847
3255
  return null;
2848
3256
  }
2849
3257
  async function runAutoSearchHint(args) {
3258
+ const startedAt = performance.now();
2850
3259
  const { sessionId, db, messages, options } = args;
2851
3260
  if (!options.enabled)
2852
3261
  return AUTO_SEARCH_OK;
@@ -2889,27 +3298,36 @@ async function runAutoSearchHint(args) {
2889
3298
  }
2890
3299
  let results;
2891
3300
  try {
2892
- if (options.directory) {
2893
- await options.ensureProjectRegistered?.(options.directory, db);
2894
- }
2895
- const embeddingSnapshot = getProjectEmbeddingSnapshot(options.projectPath);
2896
- const memoryEnabled = embeddingSnapshot?.features.memoryEnabled ?? options.memoryEnabled;
2897
- const embeddingEnabled = embeddingSnapshot ? embeddingSnapshot.historyEnabled : options.embeddingEnabled;
2898
- const gitCommitsEnabled = embeddingSnapshot?.gitCommitEnabled ?? options.gitCommitsEnabled ?? false;
2899
- const searchOptions = {
2900
- limit: 10,
2901
- memoryEnabled,
2902
- embeddingEnabled,
2903
- gitCommitsEnabled,
2904
- embedQuery: async (text, signal) => {
2905
- const result = await embedTextForProject(options.projectPath, text, signal, "query");
2906
- return result;
2907
- },
2908
- isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
2909
- visibleMemoryIds: options.visibleMemoryIds ?? null,
2910
- sources: ["memory", "message", "git_commit"]
2911
- };
2912
- 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);
2913
3331
  } catch (error) {
2914
3332
  log(`[auto-search] unified search failed for session ${sessionId} (will retry next pass): ${error instanceof Error ? error.message : String(error)}`);
2915
3333
  return { ok: false, kind: "search-failure" };
@@ -2925,7 +3343,7 @@ async function runAutoSearchHint(args) {
2925
3343
  sessionLog(sessionId, `auto-search: top score ${results[0].score.toFixed(3)} below threshold ${options.scoreThreshold}`);
2926
3344
  return writeNoHintAndReconcile("below-threshold");
2927
3345
  }
2928
- const hintText = buildAutoSearchHint(results);
3346
+ const hintText = buildAutoSearchHint(results, { wordRules: options.wordRules });
2929
3347
  if (!hintText) {
2930
3348
  return writeNoHintAndReconcile("empty");
2931
3349
  }
@@ -3245,90 +3663,29 @@ function resolveTodowriteAvailability(sessionId) {
3245
3663
  return resolveToolAvailability(sessionId, TODOWRITE_TOOL);
3246
3664
  }
3247
3665
 
3248
- // src/hooks/magic-context/sentinel.ts
3249
- var WHOLE_MESSAGE_PLACEHOLDER_TEXT = "[dropped]";
3250
- function modelAcceptsEmptyContent(providerID) {
3251
- return providerID === "anthropic";
3252
- }
3253
- var VARIANT_CACHE_PRESERVING_MODELS = {
3254
- "anthropic/claude-fable-5-1": "2026-09-02",
3255
- "openai/gpt-6-astra": "2026-09-05",
3256
- "anthropic/claude-opus-5-5": "2026-09-23"
3257
- };
3258
- function canonicalVariantModelIdentity(providerID, modelID) {
3259
- const normalizedProviderID = providerID.toLowerCase();
3260
- const isAnthropicFamily = normalizedProviderID === "anthropic" || normalizedProviderID === "google-vertex-anthropic" || normalizedProviderID.includes("bedrock");
3261
- if (isAnthropicFamily && isFable51ThinkingBindingModel("anthropic", modelID)) {
3262
- return "anthropic/claude-fable-5-1";
3263
- }
3264
- return canonicalModelIdentity(`${providerID}/${modelID}`).toLowerCase();
3265
- }
3266
- function variantChangeBustsProviderCache(providerID, modelID) {
3267
- if (!providerID || !modelID)
3268
- return false;
3269
- const identity = canonicalVariantModelIdentity(providerID, modelID);
3270
- if (Object.hasOwn(VARIANT_CACHE_PRESERVING_MODELS, identity))
3271
- return false;
3272
- const normalizedProviderID = providerID.toLowerCase();
3273
- return normalizedProviderID === "anthropic" || normalizedProviderID === "google-vertex-anthropic" || normalizedProviderID.includes("bedrock");
3274
- }
3275
- function makeSentinel(originalPart) {
3276
- const sentinel = {
3277
- type: "text",
3278
- text: ""
3279
- };
3280
- if (isRecord(originalPart)) {
3281
- if (originalPart.cache_control !== undefined) {
3282
- sentinel.cache_control = originalPart.cache_control;
3283
- }
3284
- if (originalPart.cacheControl !== undefined) {
3285
- sentinel.cacheControl = originalPart.cacheControl;
3286
- }
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;
3287
3681
  }
3288
- return sentinel;
3289
3682
  }
3290
- function makeWholeMessageSentinel(providerID) {
3291
- return {
3292
- type: "text",
3293
- text: modelAcceptsEmptyContent(providerID) ? "" : WHOLE_MESSAGE_PLACEHOLDER_TEXT
3294
- };
3295
- }
3296
- function isSentinel(part) {
3297
- if (!isRecord(part))
3298
- return false;
3299
- if (part.type !== "text")
3300
- return false;
3301
- if (typeof part.text !== "string")
3302
- return false;
3303
- return part.text === "" || part.text === WHOLE_MESSAGE_PLACEHOLDER_TEXT;
3304
- }
3305
- function replaySentinelByMessageIds(messages, ids, providerID, hiddenSeamIds = new Set) {
3306
- if (ids.size === 0)
3307
- return { replayed: 0, missingIds: [] };
3308
- const seen = new Set;
3309
- let replayed = 0;
3310
- for (let index = messages.length - 1;index >= 0; index -= 1) {
3311
- const msg = messages[index];
3312
- const id = msg.info.id;
3313
- if (!id || !ids.has(id))
3314
- continue;
3315
- seen.add(id);
3316
- if (!modelAcceptsEmptyContent(providerID) && hiddenSeamIds.has(id)) {
3317
- messages.splice(index, 1);
3318
- replayed += 1;
3319
- continue;
3320
- }
3321
- if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
3322
- continue;
3323
- msg.parts.length = 0;
3324
- msg.parts.push(makeWholeMessageSentinel(providerID));
3325
- replayed += 1;
3326
- }
3327
- const missingIds = [];
3328
- for (const id of ids)
3329
- if (!seen.has(id))
3330
- missingIds.push(id);
3331
- 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 });
3332
3689
  }
3333
3690
 
3334
3691
  // src/hooks/magic-context/drop-stale-reduce-calls.ts
@@ -3475,11 +3832,69 @@ function estimateDroppedTokensFromTagReductions(db, sessionId, reductions) {
3475
3832
  return Math.max(0, Math.round(total));
3476
3833
  }
3477
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
+
3478
3846
  // src/hooks/magic-context/fold-execution-gate.ts
3479
3847
  function foldExecutesThisPass(foldDue, materialized) {
3480
3848
  return foldDue && materialized;
3481
3849
  }
3482
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
+
3483
3898
  // src/hooks/magic-context/caveman-cleanup.ts
3484
3899
  var DEPTH_UNTOUCHED = 0;
3485
3900
  var DEPTH_LITE = 1;
@@ -3512,10 +3927,16 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
3512
3927
  };
3513
3928
  if (!config.enabled)
3514
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
+ };
3515
3938
  const protectedCutoff = config.protectedCutoff;
3516
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);
3517
- if (eligible.length === 0)
3518
- return result;
3519
3940
  const tagsNeedingCompression = eligible.filter((tag, index) => {
3520
3941
  const target = targets.get(tag.tagNumber);
3521
3942
  if (!target?.getContent || !target.setContent)
@@ -3523,7 +3944,31 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
3523
3944
  const targetDepth = computeTargetDepth(index, eligible.length);
3524
3945
  return targetDepth > tag.cavemanDepth;
3525
3946
  });
3526
- 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)
3527
3972
  return result;
3528
3973
  const originalByTag = getSourceContents(db, sessionId, tagsNeedingCompression.map((t) => t.tagNumber));
3529
3974
  const positionByTag = new Map;
@@ -3542,20 +3987,15 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
3542
3987
  const level = DEPTH_TO_LEVEL[targetDepth];
3543
3988
  if (!level)
3544
3989
  continue;
3545
- const compressed = cavemanCompress(originalText, level);
3546
- if (compressed.length === 0)
3990
+ if (cavemanCompress(originalText, level, rulesFor(state), wordRulesFor(state)).length === 0) {
3547
3991
  continue;
3992
+ }
3548
3993
  const target = targets.get(tag.tagNumber);
3549
3994
  if (!target)
3550
3995
  continue;
3551
- const priorContent = target.getContent?.();
3552
- const didMutate = target.setContent(compressed);
3553
- if (didMutate) {
3554
- result.mutatedTextTags += 1;
3555
- result.textReductions.push({
3556
- tagNumber: tag.tagNumber,
3557
- removedCharacters: Math.max(0, (priorContent?.length ?? originalText.length) - compressed.length)
3558
- });
3996
+ const priorContent = target.getContent?.() ?? originalText;
3997
+ if (applyCompressedText(target, tag.tagNumber, originalText, targetDepth, state)) {
3998
+ recordRewrite(tag.tagNumber, target, priorContent);
3559
3999
  }
3560
4000
  updateCavemanDepth(db, sessionId, tag.tagNumber, targetDepth);
3561
4001
  if (targetDepth === DEPTH_LITE)
@@ -3572,79 +4012,62 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
3572
4012
  }
3573
4013
  return result;
3574
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
+ }
3575
4039
  function replayCavemanCompression(sessionId, db, targets, tags) {
3576
4040
  const compressedTags = tags.filter((tag) => tag.type === "message" && tag.status === "active" && tag.cavemanDepth > 0 && targets.has(tag.tagNumber));
3577
4041
  if (compressedTags.length === 0)
3578
4042
  return 0;
3579
4043
  const originalByTag = getSourceContents(db, sessionId, compressedTags.map((t) => t.tagNumber));
4044
+ const state = getCavemanReplayState(db, sessionId);
3580
4045
  let replayed = 0;
3581
4046
  for (const tag of compressedTags) {
3582
4047
  const originalText = originalByTag.get(tag.tagNumber);
3583
4048
  if (typeof originalText !== "string" || originalText.length === 0)
3584
4049
  continue;
3585
- const level = DEPTH_TO_LEVEL[tag.cavemanDepth];
3586
- if (!level)
3587
- continue;
3588
- const compressed = cavemanCompress(originalText, level);
3589
- if (compressed.length === 0)
3590
- continue;
3591
4050
  const target = targets.get(tag.tagNumber);
3592
4051
  if (!target)
3593
4052
  continue;
3594
- if (target.setContent(compressed)) {
4053
+ if (applyCompressedText(target, tag.tagNumber, originalText, tag.cavemanDepth, state)) {
3595
4054
  replayed += 1;
3596
4055
  }
3597
4056
  }
3598
4057
  return replayed;
3599
4058
  }
3600
4059
 
3601
- // src/hooks/magic-context/system-injection-stripper.ts
3602
- var SYSTEM_INJECTION_MARKERS = [
3603
- "<!-- OMO_INTERNAL_INITIATOR -->",
3604
- "[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
3605
- "[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
3606
- "[Category+Skill Reminder]",
3607
- "[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
3608
- "[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
3609
- "[EMERGENCY CONTEXT WINDOW WARNING]",
3610
- "Unstable background agent appears idle",
3611
- "**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
3612
- ];
3613
- var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
3614
- var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
3615
- function stripSystemInjection(text) {
3616
- let hasInjection = false;
3617
- for (const marker of SYSTEM_INJECTION_MARKERS) {
3618
- if (text.includes(marker)) {
3619
- hasInjection = true;
3620
- break;
3621
- }
3622
- }
3623
- if (SYSTEM_REMINDER_REGEX.test(text))
3624
- hasInjection = true;
3625
- SYSTEM_REMINDER_REGEX.lastIndex = 0;
3626
- if (!hasInjection)
3627
- return null;
3628
- let cleaned = text;
3629
- cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
3630
- cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
3631
- cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
3632
- for (const marker of SYSTEM_INJECTION_MARKERS) {
3633
- if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
3634
- continue;
3635
- const idx = cleaned.indexOf(marker);
3636
- if (idx === -1)
3637
- continue;
3638
- const blockEnd = cleaned.indexOf(`
3639
-
3640
- `, idx + marker.length);
3641
- cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
3642
- }
3643
- return cleaned.trim();
3644
- }
3645
-
3646
4060
  // src/hooks/magic-context/heuristic-cleanup.ts
3647
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",
3648
4071
  "mcp_grep",
3649
4072
  "mcp_read",
3650
4073
  "mcp_glob",
@@ -3685,7 +4108,8 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3685
4108
  ceilingTokens: emergency.ceilingTokens,
3686
4109
  usagePercentage: emergency.usagePercentage,
3687
4110
  priorInputSample,
3688
- hasPriorDrop: priorInputSample > 0
4111
+ hasPriorDrop: priorInputSample > 0,
4112
+ passAlreadyPriced: emergency.passAlreadyPriced === true
3689
4113
  });
3690
4114
  if (plan.shouldDrop) {
3691
4115
  const toDrop = new Set(plan.tagNumbers);
@@ -3760,7 +4184,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3760
4184
  }
3761
4185
  }
3762
4186
  } else {
3763
- const didSet = target.setContent(stripped);
4187
+ const didSet = target.setContent(stripped, { keepReasoning: true });
3764
4188
  if (didSet) {
3765
4189
  replaceSourceContent(db, sessionId, tag.tagNumber, strippedSource);
3766
4190
  droppedInjections++;
@@ -3787,7 +4211,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3787
4211
  const fingerprintGroups = new Map;
3788
4212
  for (const [compositeKey, fingerprint] of toolFingerprints) {
3789
4213
  const tag = tagsByCompositeKey.get(compositeKey);
3790
- if (!tag || config.protectedTagNumbers.has(tag.tagNumber))
4214
+ if (!tag)
3791
4215
  continue;
3792
4216
  const group = fingerprintGroups.get(fingerprint) ?? [];
3793
4217
  group.push(tag);
@@ -3800,6 +4224,8 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3800
4224
  group.sort((a, b) => a.tagNumber - b.tagNumber);
3801
4225
  for (let i = 0;i < group.length - 1; i++) {
3802
4226
  const tag = group[i];
4227
+ if (config.protectedTagNumbers.has(tag.tagNumber))
4228
+ continue;
3803
4229
  const target = targets.get(tag.tagNumber);
3804
4230
  if (target?.canDrop?.() === false)
3805
4231
  continue;
@@ -3828,6 +4254,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
3828
4254
  const cavemanResult = applyCavemanCleanup(sessionId, db, targets, tags, {
3829
4255
  enabled: true,
3830
4256
  minChars: config.caveman.minChars,
4257
+ wordRules: config.caveman.wordRules,
3831
4258
  protectedCutoff: config.protectedCutoff
3832
4259
  });
3833
4260
  compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
@@ -4142,6 +4569,8 @@ function replayClearedReasoning(messages, reasoningByMessage, messageTagNumbers,
4142
4569
  if (!parts)
4143
4570
  continue;
4144
4571
  for (const tp of parts) {
4572
+ if (tp.type === "text")
4573
+ continue;
4145
4574
  if (tp.thinking !== undefined && tp.thinking !== "[cleared]") {
4146
4575
  tp.thinking = "[cleared]";
4147
4576
  cleared++;
@@ -4192,6 +4621,8 @@ function clearOldReasoning(messages, reasoningByMessage, messageTagNumbers, clea
4192
4621
  if (!parts)
4193
4622
  continue;
4194
4623
  for (const tp of parts) {
4624
+ if (tp.type === "text")
4625
+ continue;
4195
4626
  if (tp.thinking !== undefined && tp.thinking !== "[cleared]") {
4196
4627
  tp.thinking = "[cleared]";
4197
4628
  cleared++;
@@ -4483,8 +4914,9 @@ function applyFrozenTrailingBlankDecisions(messages, frozenDecisions) {
4483
4914
  return mutations;
4484
4915
  }
4485
4916
  function stripReasoningFromAssistantIds(messages, providerID, messageIds) {
4486
- if (providerID !== "anthropic" || messageIds.size === 0)
4917
+ if (messageIds.size === 0)
4487
4918
  return 0;
4919
+ const emptySentinels = modelAcceptsEmptyContent(providerID);
4488
4920
  let stripped = 0;
4489
4921
  for (const message of messages) {
4490
4922
  const id = message.info.id;
@@ -4494,9 +4926,16 @@ function stripReasoningFromAssistantIds(messages, providerID, messageIds) {
4494
4926
  const part = message.parts[index];
4495
4927
  if (!isRecord(part) || !REASONING_PART_TYPES.has(String(part.type)))
4496
4928
  continue;
4497
- 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
+ }
4498
4935
  stripped += 1;
4499
4936
  }
4937
+ if (message.parts.length === 0)
4938
+ message.parts.push(makeWholeMessageSentinel(providerID));
4500
4939
  }
4501
4940
  return stripped;
4502
4941
  }
@@ -4594,6 +5033,135 @@ function stripProcessedImages(messages, frozenIds, options) {
4594
5033
  return { stripped, newlyStrippedIds };
4595
5034
  }
4596
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
+
4597
5165
  // src/hooks/magic-context/supersession-reclaim.ts
4598
5166
  var TODOWRITE_KEEP = 1;
4599
5167
  var SUPERSESSION_RECENT_MESSAGE_WINDOW = 20;
@@ -5146,6 +5714,7 @@ function createExistingTagResolver(sessionId, tagger, db) {
5146
5714
  let cachedAssignmentSize = -1;
5147
5715
  let cachedScopedAssignments = null;
5148
5716
  const usedTagNumbers = new Set;
5717
+ const claimedContentIds = new Set;
5149
5718
  function getScopedAssignments() {
5150
5719
  if (!cachedScopedAssignments || cachedAssignmentSize !== assignments.size) {
5151
5720
  cachedScopedAssignments = createScopedAssignments(assignments);
@@ -5156,13 +5725,14 @@ function createExistingTagResolver(sessionId, tagger, db) {
5156
5725
  return {
5157
5726
  resolve(messageId, type, currentContentId, ordinal, options) {
5158
5727
  const accept = options?.accept ?? (() => true);
5728
+ claimedContentIds.add(currentContentId);
5159
5729
  const exactTagId = assignments.get(currentContentId);
5160
5730
  if (exactTagId !== undefined && accept(exactTagId)) {
5161
5731
  usedTagNumbers.add(exactTagId);
5162
5732
  return exactTagId;
5163
5733
  }
5164
5734
  const fallback = getScopedAssignments().get(messageId)?.[type][ordinal];
5165
- if (!fallback || usedTagNumbers.has(fallback.tagNumber) || !accept(fallback.tagNumber)) {
5735
+ if (!fallback || usedTagNumbers.has(fallback.tagNumber) || claimedContentIds.has(fallback.contentId) || !accept(fallback.tagNumber)) {
5166
5736
  return;
5167
5737
  }
5168
5738
  updateTagMessageId(db, sessionId, fallback.tagNumber, currentContentId);
@@ -5184,20 +5754,22 @@ function logTransformTiming(sessionId, stage, startMs, extra) {
5184
5754
  // src/hooks/magic-context/tag-messages.ts
5185
5755
  var TOOL_OWNER_CACHE_KEY_SEP = "\x00";
5186
5756
  var inertWhitespaceCache = new WeakMap;
5187
- 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);
5188
5760
  const tagsVersion = tagger.getLoadedTagsVersion?.(sessionId, db);
5189
5761
  if (tagsVersion === undefined)
5190
- return getInertWhitespaceAssistantTags(db, sessionId);
5762
+ return getInertWhitespaceAssistantTags(db, sessionId, messageIds);
5191
5763
  let bySession = inertWhitespaceCache.get(db);
5192
5764
  if (!bySession) {
5193
5765
  bySession = new Map;
5194
5766
  inertWhitespaceCache.set(db, bySession);
5195
5767
  }
5196
5768
  const cached = bySession.get(sessionId);
5197
- if (cached?.tagsVersion === tagsVersion)
5769
+ if (cached?.tagsVersion === tagsVersion && cached.ownersKey === ownersKey)
5198
5770
  return cached.tags;
5199
- const tags = getInertWhitespaceAssistantTags(db, sessionId);
5200
- bySession.set(sessionId, { tagsVersion, tags });
5771
+ const tags = getInertWhitespaceAssistantTags(db, sessionId, messageIds);
5772
+ bySession.set(sessionId, { tagsVersion, ownersKey, tags });
5201
5773
  return tags;
5202
5774
  }
5203
5775
  function makeToolOwnerCacheKey(sessionId, callId) {
@@ -5374,7 +5946,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5374
5946
  const tInertWhitespace = performance.now();
5375
5947
  const inertWhitespaceTagNumbers = new Set;
5376
5948
  const inertWhitespaceTagsByMessage = new Map;
5377
- for (const tag of getCachedInertWhitespaceAssistantTags(db, sessionId, tagger)) {
5949
+ for (const tag of getCachedInertWhitespaceAssistantTags(db, sessionId, tagger, messages)) {
5378
5950
  inertWhitespaceTagNumbers.add(tag.tagNumber);
5379
5951
  tagger.bindTag(sessionId, tag.contentId, tag.tagNumber);
5380
5952
  const scoped = /^(.*):p(\d+)$/.exec(tag.contentId);
@@ -5393,6 +5965,22 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5393
5965
  const tGetSourceContents = performance.now();
5394
5966
  const sourceContents = getSourceContents(db, sessionId, collectRelevantSourceTagIds(messages, assignments));
5395
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;
5396
5984
  let precedingThinkingParts = [];
5397
5985
  let lastReduceMessageIndex = -1;
5398
5986
  const RECENT_REDUCE_LOOKBACK = 10;
@@ -5546,15 +6134,20 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5546
6134
  }
5547
6135
  targets.set(tagId, {
5548
6136
  message,
5549
- setContent: (content) => {
6137
+ textPrefix: skipPrefixInjection ? "" : prependTag(tagId, ""),
6138
+ setContent: (content, options) => {
5550
6139
  if (textPart.text === content)
5551
6140
  return false;
6141
+ const partialEnd = messageId ? getPartialEnds().get(messageId) : undefined;
6142
+ if (partialEnd !== undefined && partIndex > partialEnd)
6143
+ return false;
5552
6144
  textPart.text = content;
6145
+ if (options?.keepReasoning === true)
6146
+ return true;
5553
6147
  for (const tp of thinkingParts) {
5554
- if (tp.thinking !== undefined)
5555
- tp.thinking = "[cleared]";
5556
- if (tp.text !== undefined)
5557
- tp.text = "[cleared]";
6148
+ if (partialEnd !== undefined && message.parts.indexOf(tp) > partialEnd)
6149
+ continue;
6150
+ neutralizeDroppedReasoningPart(tp);
5558
6151
  }
5559
6152
  return true;
5560
6153
  },
@@ -5626,6 +6219,11 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5626
6219
  const prevText = typeof prev === "object" && prev !== null && "text" in prev ? prev.text : "";
5627
6220
  if (prevText === content)
5628
6221
  return false;
6222
+ if (messageId) {
6223
+ const partialEnd = getPartialEnds().get(messageId);
6224
+ if (partialEnd !== undefined && partIndex > partialEnd)
6225
+ return false;
6226
+ }
5629
6227
  messageParts[partIndex] = {
5630
6228
  type: "text",
5631
6229
  text: content
@@ -5646,7 +6244,18 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5646
6244
  logTransformTiming(sessionId, "tag.assignTag", performance.now() - accAssignTag);
5647
6245
  logTransformTiming(sessionId, "tag.assignToolTag", performance.now() - accAssignToolTag);
5648
6246
  logTransformTiming(sessionId, "tag.saveSource", performance.now() - accSaveSource);
6247
+ const partialEnds = toolTagByCallId.size > 0 ? loadPartialEnds().last : new Map;
5649
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;
5650
6259
  const thinkingParts = toolThinkingByCallId.get(compositeKey) ?? [];
5651
6260
  targets.set(tagId, createToolDropTarget(compositeKey, thinkingParts, toolCallIndex, batch, tagId));
5652
6261
  }
@@ -5733,7 +6342,7 @@ function removeSyntheticTodoParts(messages) {
5733
6342
  }
5734
6343
  }
5735
6344
  }
5736
- async function applyTodoSynthesis(args) {
6345
+ async function applyTodoSynthesis2(args) {
5737
6346
  if (!args.fullFeatureMode || args.compactionOff)
5738
6347
  return 0;
5739
6348
  const persistedAnchor = args.replaySnapshot ? args.replaySnapshot.todoSyntheticAnchor : getPersistedTodoSyntheticAnchor(args.db, args.sessionId);
@@ -5798,7 +6407,10 @@ function freezeAllReasoningForBindingRecovery(args) {
5798
6407
  args.recoveredMessageIds.add(id);
5799
6408
  return { flagTarget: args.flagTarget, messageIds };
5800
6409
  }
5801
- function freezeReasoningOnBustingPass(args) {
6410
+ function countAutoSearchHints(db, sessionId) {
6411
+ return getAutoSearchHintDecisions(db, sessionId).filter((decision) => decision.decision === "hint").length;
6412
+ }
6413
+ function freezeReasoningOnBustingPass2(args) {
5802
6414
  const messageIds = findReasoningBearingAssistantIds(args.messages).filter((id) => !args.alreadyFrozen.has(id));
5803
6415
  if (messageIds.length === 0)
5804
6416
  return { strip: null, persistenceFailed: false };
@@ -5823,7 +6435,7 @@ function proactiveStripStartIndex(args) {
5823
6435
  return null;
5824
6436
  if (!lastServed.messages)
5825
6437
  return 0;
5826
- const divergence = firstServedDivergenceIndex(args.messages, lastServed.messages, {
6438
+ const divergence = firstServedDivergenceIndex2(args.messages, lastServed.messages, {
5827
6439
  providerID: args.resolvedProviderID
5828
6440
  });
5829
6441
  if (lastServed.proven)
@@ -5849,7 +6461,7 @@ function servedMessageKey(message, providerID) {
5849
6461
  }));
5850
6462
  return stableStringify(plain);
5851
6463
  }
5852
- function firstServedDivergenceIndex(messages, lastServed, options = {}) {
6464
+ function firstServedDivergenceIndex2(messages, lastServed, options = {}) {
5853
6465
  const shared = Math.min(messages.length, lastServed.length);
5854
6466
  for (let index = 0;index < shared; index += 1) {
5855
6467
  if (servedMessageKey(messages[index], options.providerID) !== servedMessageKey(lastServed[index], options.providerID)) {
@@ -5858,9 +6470,26 @@ function firstServedDivergenceIndex(messages, lastServed, options = {}) {
5858
6470
  }
5859
6471
  return null;
5860
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
+ }
5861
6492
  function replayRustModeBindingMismatchStrips2(args) {
5862
- if (!modelAcceptsEmptyContent(args.resolvedProviderID))
5863
- return;
5864
6493
  const recoveryMessageIds = new Set;
5865
6494
  for (const id of getMergedReasoningStrippedIds(args.db, args.sessionId)) {
5866
6495
  if (!id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX))
@@ -5871,7 +6500,7 @@ function replayRustModeBindingMismatchStrips2(args) {
5871
6500
  }
5872
6501
  stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, recoveryMessageIds);
5873
6502
  }
5874
- 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";
5875
6504
  function isSqliteLockContentionError(error) {
5876
6505
  if (!error || typeof error !== "object")
5877
6506
  return false;
@@ -5915,7 +6544,7 @@ function applyRustModeDeferredCompactionMarker2(args) {
5915
6544
  } catch (error) {
5916
6545
  if (!isSqliteLockContentionError(error))
5917
6546
  throw error;
5918
- 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)}`);
5919
6548
  return;
5920
6549
  }
5921
6550
  }
@@ -5958,13 +6587,70 @@ function clearRustModeBoundaryRecord2(db, sessionId) {
5958
6587
  setPersistedCompactionMarkerState(db, sessionId, null);
5959
6588
  return true;
5960
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
+ }
5961
6639
  function runRustModePostprocess2(args) {
5962
- if (!args.fullFeatureMode || args.compactionOff) {
6640
+ if (args.compactionOff) {
5963
6641
  return { thinkingBindingRecovery: null, proactiveThinkingStrip: null, markerAt: null };
5964
6642
  }
5965
6643
  if (args.messages.some((message) => !message || typeof message !== "object" || !isRecord(message.info))) {
5966
6644
  return { thinkingBindingRecovery: null, proactiveThinkingStrip: null, markerAt: null };
5967
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();
5968
6654
  applyRustModeDeferredCompactionMarker2({
5969
6655
  ...args.compactionMarkerStrategy ? { applyDeferred: args.compactionMarkerStrategy.applyDeferred } : {},
5970
6656
  db: args.db,
@@ -5972,7 +6658,7 @@ function runRustModePostprocess2(args) {
5972
6658
  boundary: args.materializedBoundary,
5973
6659
  sessionDirectory: args.sessionDirectory
5974
6660
  });
5975
- (args.compactionMarkerStrategy?.reconcile ?? reconcileMarkerRepresentation)(args.messages, getPersistedCompactionMarkerState(args.db, args.sessionId), {
6661
+ (args.compactionMarkerStrategy?.reconcile ?? reconcileMarkerRepresentation2)(args.messages, getPersistedCompactionMarkerState(args.db, args.sessionId), {
5976
6662
  db: args.db,
5977
6663
  sessionId: args.sessionId,
5978
6664
  tagger: args.tagger,
@@ -6016,6 +6702,7 @@ function runRustModePostprocess2(args) {
6016
6702
  }
6017
6703
  const absorbingStripDecisions = new Map([...trailingBlankDecisions].filter(([, decision]) => decision === "strip"));
6018
6704
  applyFrozenTrailingBlankDecisions(args.messages, absorbingStripDecisions);
6705
+ let noteNudgeAppended = false;
6019
6706
  const currentUserMessageId = findLastUserMessageId(args.messages);
6020
6707
  const noteReadStillVisible = hasVisibleNoteReadCall(args.messages);
6021
6708
  const deferredNoteText = peekNoteNudgeText(args.db, args.sessionId, currentUserMessageId, args.projectPath, noteReadStillVisible);
@@ -6027,55 +6714,12 @@ function runRustModePostprocess2(args) {
6027
6714
  const outcome = markNoteNudgeDelivered(args.db, args.sessionId, instruction, anchoredMessageId);
6028
6715
  if (anchoredMessageId && outcome.ok) {
6029
6716
  appendReminderToUserMessageById(args.messages, anchoredMessageId, instruction);
6717
+ noteNudgeAppended = true;
6030
6718
  } else if (anchoredMessageId && !outcome.ok) {
6031
6719
  sessionLog(args.sessionId, `rust note-nudge delivery skipped wire append: ${outcome.kind}`);
6032
6720
  }
6033
6721
  }
6034
- const recoveryMessageIds = new Set;
6035
- let thinkingBindingRecovery = null;
6036
- let proactiveThinkingStrip = null;
6037
- if (modelAcceptsEmptyContent(args.resolvedProviderID)) {
6038
- try {
6039
- for (const id of getMergedReasoningStrippedIds(args.db, args.sessionId)) {
6040
- if (!id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX))
6041
- continue;
6042
- const messageId = id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length);
6043
- if (messageId.length > 0)
6044
- recoveryMessageIds.add(messageId);
6045
- }
6046
- const flagTarget = args.thinkingBindingRecoveryEnabledForModel ? getThinkingBindingRecoveryTarget(args.db, args.sessionId) : null;
6047
- if (flagTarget) {
6048
- thinkingBindingRecovery = freezeAllReasoningForBindingRecovery({
6049
- db: args.db,
6050
- sessionId: args.sessionId,
6051
- messages: args.messages,
6052
- flagTarget,
6053
- recoveredMessageIds: recoveryMessageIds
6054
- });
6055
- if (!thinkingBindingRecovery) {
6056
- sessionLog(args.sessionId, "rust thinking binding recovery: persistence failed; leaving the bound blocks intact");
6057
- }
6058
- }
6059
- } catch (error) {
6060
- sessionLog(args.sessionId, "rust thinking binding recovery failed:", error);
6061
- }
6062
- stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, recoveryMessageIds);
6063
- const stripFrom = args.thinkingBindingRecoveryEnabledForModel === true ? proactiveStripStartIndex(args) : null;
6064
- if (stripFrom !== null) {
6065
- const outcome = freezeReasoningOnBustingPass({
6066
- db: args.db,
6067
- sessionId: args.sessionId,
6068
- messages: args.messages.slice(stripFrom),
6069
- alreadyFrozen: recoveryMessageIds
6070
- });
6071
- if (outcome.strip) {
6072
- proactiveThinkingStrip = outcome.strip;
6073
- for (const id of outcome.strip.messageIds)
6074
- recoveryMessageIds.add(id);
6075
- stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, new Set(outcome.strip.messageIds));
6076
- }
6077
- }
6078
- }
6722
+ const { thinkingBindingRecovery, proactiveThinkingStrip } = applyRustModeThinkingStrips(args, noteNudgeAppended || servedMarkerRecord() !== servedMarkerBefore);
6079
6723
  const marker = getPersistedCompactionMarkerState(args.db, args.sessionId);
6080
6724
  return {
6081
6725
  thinkingBindingRecovery,
@@ -6088,7 +6732,7 @@ function dropMarkerSummaryTag(db, sessionId, summaryMessageId) {
6088
6732
  if (tagNumber !== null)
6089
6733
  updateTagStatus(db, sessionId, tagNumber, "dropped");
6090
6734
  }
6091
- function reconcileMarkerRepresentation(messages, persistedMarkerState, options) {
6735
+ function reconcileMarkerRepresentation2(messages, persistedMarkerState, options) {
6092
6736
  if (persistedMarkerState === null) {
6093
6737
  if (options.isCacheBustingPass === true) {
6094
6738
  retireDeferredClearedCompactionMarkerState(options.db, options.sessionId);
@@ -6171,7 +6815,7 @@ function sourceAlreadyReflectsCoveringMarker(sessionId, sourceOrder, marker, pen
6171
6815
  return false;
6172
6816
  return sourceOrder.messageIds.includes(marker.summaryMessageId) && !sourceOrder.messageIds.includes(pending.endMessageId);
6173
6817
  }
6174
- function clearPendingCompactionMarkerAfterSuccessfulDrain(args) {
6818
+ function clearPendingCompactionMarkerAfterSuccessfulDrain2(args) {
6175
6819
  if (clearPendingCompactionMarkerStateIf(args.db, args.sessionId, args.pending)) {
6176
6820
  return "cleared";
6177
6821
  }
@@ -6186,7 +6830,7 @@ function clearPendingCompactionMarkerAfterSuccessfulDrain(args) {
6186
6830
  }
6187
6831
  var defaultCompactionMarkerStrategy2 = {
6188
6832
  applyDeferred: applyDeferredCompactionMarker,
6189
- reconcile: reconcileMarkerRepresentation
6833
+ reconcile: reconcileMarkerRepresentation2
6190
6834
  };
6191
6835
  async function abortSessionFailClosed2(client, sessionId) {
6192
6836
  if (typeof client?.session?.abort !== "function") {
@@ -6219,7 +6863,7 @@ function evaluateEmergencyFailClosed2(input) {
6219
6863
  reason: shouldAbort ? "provider-overflow-abort" : "proceed"
6220
6864
  };
6221
6865
  }
6222
- function finalizeMessageRepresentation(messages, resolvedProviderID, options) {
6866
+ function finalizeMessageRepresentation2(messages, resolvedProviderID, options) {
6223
6867
  let clearedParts = 0;
6224
6868
  if (modelAcceptsEmptyContent(resolvedProviderID)) {
6225
6869
  const prependedMessageCount = Math.min(messages.length, Math.max(0, options?.prependedMessageCount ?? 0));
@@ -6250,6 +6894,13 @@ function finalizeMessageRepresentation(messages, resolvedProviderID, options) {
6250
6894
  async function runPostTransformPhase2(args) {
6251
6895
  const tPostprocessSetup = performance.now();
6252
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
+ };
6253
6904
  const trailingBlankSourceDecisions = args.trailingBlankSourceDecisions ?? snapshotTrailingBlankSourceDecisions(args.messages);
6254
6905
  let trailingBlankNewestAssistant;
6255
6906
  for (let index = args.messages.length - 1;index >= 0; index -= 1) {
@@ -6282,7 +6933,8 @@ async function runPostTransformPhase2(args) {
6282
6933
  const deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
6283
6934
  const materializationRequested = isExplicitFlush || deferredMaterialize;
6284
6935
  const m0M1EnabledForFold = args.m0M1 !== undefined && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory) && (args.fullFeatureMode || compactionOff);
6285
- const foldDueDecision = m0M1EnabledForFold && args.m0M1 ? mustMaterialize({
6936
+ const freezeM0M1 = args.freezeM0M1 === true;
6937
+ const foldDueDecision = m0M1EnabledForFold && args.m0M1 && !freezeM0M1 ? mustMaterialize({
6286
6938
  db: args.db,
6287
6939
  sessionId: args.sessionId,
6288
6940
  state: args.sessionMeta,
@@ -6297,7 +6949,7 @@ async function runPostTransformPhase2(args) {
6297
6949
  hardSignals: args.m0M1.hardSignals
6298
6950
  }) : { value: false, reason: null };
6299
6951
  let preparedPrefix;
6300
- const shouldCaptureCachedPrefix = (foldDueDecision.value || args.schedulerDecision === "execute") && m0M1EnabledForFold && !emergencyDropEligible;
6952
+ const shouldCaptureCachedPrefix = (foldDueDecision.value || args.schedulerDecision === "execute") && m0M1EnabledForFold && !emergencyDropEligible && !freezeM0M1;
6301
6953
  const cachedPrefixBeforePreflight = shouldCaptureCachedPrefix ? prepareCachedM0M1Replay(args.db, args.sessionId) : undefined;
6302
6954
  const completeCachedPrefixAvailable = args.sessionMeta.cachedM0Bytes != null && args.sessionMeta.cachedM1Bytes != null || cachedPrefixBeforePreflight !== undefined || m0M1EnabledForFold && !shouldCaptureCachedPrefix && hasCompleteCachedM0M1(args.db, args.sessionId);
6303
6955
  const firstRenderBust = m0M1EnabledForFold && !completeCachedPrefixAvailable;
@@ -6305,7 +6957,7 @@ async function runPostTransformPhase2(args) {
6305
6957
  let foldBustsServedPrefixThisPass = false;
6306
6958
  let publishedM1RefreshedThisPass = false;
6307
6959
  let prefixPreflightFailed = false;
6308
- const softRefreshOpportunity = args.schedulerDecision === "execute" || deferredMaterialize;
6960
+ const softRefreshOpportunity = !freezeM0M1 && (args.schedulerDecision === "execute" || deferredMaterialize);
6309
6961
  let m0RematerializedThisPass = false;
6310
6962
  const m0CoverageBeforeFold = args.sessionMeta.cachedM0Bytes === null ? -1 : args.sessionMeta.cachedM0MaxCompartmentSeq;
6311
6963
  let m0MaterializeReason = null;
@@ -6378,7 +7030,7 @@ async function runPostTransformPhase2(args) {
6378
7030
  } catch (error) {
6379
7031
  preparedPrefix = cachedPrefixBeforePreflight;
6380
7032
  prefixPreflightFailed = true;
6381
- args.passOutcome?.record("m0-m1-fold-preexecution-degradation");
7033
+ failPass("m0-m1-fold-preexecution-degradation", error);
6382
7034
  sessionLog(args.sessionId, "transform: m[0] HARD fold pre-execution failed:", getErrorMessage(error));
6383
7035
  }
6384
7036
  sessionLog(args.sessionId, `m[0] HARD fold decision: reason=${foldDueDecision.reason ?? "unknown"} executed=${foldExecutedThisPass} bustsServedPrefix=${foldBustsServedPrefixThisPass}`);
@@ -6390,8 +7042,9 @@ async function runPostTransformPhase2(args) {
6390
7042
  const depth = getPendingOpsCount(args.db, args.sessionId);
6391
7043
  return depth === null ? "not loaded (deferred pass)" : String(depth);
6392
7044
  };
7045
+ const idleExpiryRebuild = !freezeM0M1 && args.m0M1?.hardSignals?.cacheExpired === true;
6393
7046
  const rideSignals = {
6394
- hardFold: foldBustsServedPrefixThisPass || firstRenderBust,
7047
+ hardFold: foldBustsServedPrefixThisPass || firstRenderBust || idleExpiryRebuild,
6395
7048
  force: emergencyDropEligible && (args.contextUsage.percentage >= 95 || getEmergencyInputSample(args.db, args.sessionId) === 0),
6396
7049
  explicitFlush: isExplicitFlush || deferredMaterialize && !prefixPreflightFailed,
6397
7050
  publishedHistory: publishedM1RefreshedThisPass || !m0M1EnabledForFold && (args.pendingCompartmentInjection?.compartmentCount ?? 0) > 0 && (args.historyRebuiltThisPass || args.rebuiltHistoryFromInitialPrepare || args.canConsumeDeferredLate && args.deferredHistoryWasPendingAtPassStart)
@@ -6412,6 +7065,25 @@ async function runPostTransformPhase2(args) {
6412
7065
  }
6413
7066
  }
6414
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
+ }
6415
7087
  if (shouldRunHeuristics) {
6416
7088
  const subagentRerun = !args.fullFeatureMode && alreadyRanThisTurn && args.schedulerDecision === "execute" && !isExplicitFlush && !forceMaterialization;
6417
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})`;
@@ -6432,6 +7104,7 @@ async function runPostTransformPhase2(args) {
6432
7104
  let deferredMaterializedSuccessfully = false;
6433
7105
  let pendingOpsDidMutate = false;
6434
7106
  let heuristicOrReasoningDidMutate = false;
7107
+ let heuristicOrReasoningEditBesidesTrim = false;
6435
7108
  let droppedCount = 0;
6436
7109
  let droppedTokens = 0;
6437
7110
  const droppedTokenReductions = [];
@@ -6482,21 +7155,23 @@ async function runPostTransformPhase2(args) {
6482
7155
  const t5 = performance.now();
6483
7156
  const cavemanConfig = args.cavemanTextCompression?.enabled ? {
6484
7157
  enabled: true,
6485
- minChars: args.cavemanTextCompression.minChars
7158
+ minChars: args.cavemanTextCompression.minChars,
7159
+ wordRules: args.cavemanTextCompression.wordRules
6486
7160
  } : undefined;
6487
7161
  const heuristicTags = shouldApplyPendingOps ? getActiveTagsBySession(args.db, args.sessionId) : args.tags;
6488
- const independentMutationBeforeHeuristics = pendingOpsDidMutate || args.didMutateFromFlushedStatuses || foldBustsServedPrefixThisPass || args.historyRebuiltThisPass || args.compartmentInjectionRebuiltFromDb || args.rebuiltHistoryFromInitialPrepare;
6489
- 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) {
6490
7164
  clearEmergencyDropSample(args.db, args.sessionId);
6491
7165
  }
6492
- 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;
6493
7167
  let cleanup = applyHeuristicCleanup(args.sessionId, args.db, args.targets, args.messageTagNumbers, {
6494
7168
  protectedTagNumbers: args.protectedTagNumbers,
6495
7169
  protectedCutoff: args.protectedCutoff,
6496
7170
  emergency: emergencyDropEligible && args.emergencyCeilingTokens !== undefined && args.emergencyCeilingTokens > 0 ? {
6497
7171
  currentTotalInputTokens: args.contextUsage.inputTokens,
6498
7172
  ceilingTokens: args.emergencyCeilingTokens,
6499
- usagePercentage: args.contextUsage.percentage
7173
+ usagePercentage: args.contextUsage.percentage,
7174
+ passAlreadyPriced: emergencyRewriteAlreadyPriced
6500
7175
  } : undefined,
6501
7176
  routine: routineCleanupApplied,
6502
7177
  caveman: cavemanConfig
@@ -6533,11 +7208,63 @@ async function runPostTransformPhase2(args) {
6533
7208
  emergencyReclaimedTokens += cleanup.emergencyReclaimedTokens;
6534
7209
  droppedTokenReductions.push(...cleanup.droppedTokenReductions);
6535
7210
  const t7 = performance.now();
6536
- 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;
6537
7213
  if (routineCleanupApplied && canUseEmptySentinels) {
6538
7214
  stripClearedReasoning(args.messages);
6539
7215
  }
6540
- 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
+ }
6541
7268
  if (clearedReasoning > 0 || strippedInline > 0) {
6542
7269
  let maxTag = 0;
6543
7270
  for (const tag of args.messageTagNumbers.values()) {
@@ -6557,18 +7284,16 @@ async function runPostTransformPhase2(args) {
6557
7284
  }
6558
7285
  }
6559
7286
  logTransformTiming(args.sessionId, "clearOldReasoning", t7);
6560
- heuristicOrReasoningDidMutate = heuristicMutationCount + clearedReasoning + strippedInline > 0;
6561
- droppedCount += clearedReasoning + strippedInline;
6562
- if (pendingMaterializationAtPassStart) {
7287
+ heuristicOrReasoningDidMutate = heuristicMutationCount + clearedReasoning + strippedInline + removedReasoningMessages > 0;
7288
+ heuristicOrReasoningEditBesidesTrim = heuristicMutationCount + clearedReasoning + strippedInline > 0;
7289
+ droppedCount += clearedReasoning + strippedInline + removedReasoningMessages;
7290
+ if (pendingMaterializationAtPassStart && !freezeM0M1) {
6563
7291
  args.pendingMaterializationSessions.delete(args.sessionId);
6564
7292
  }
6565
7293
  if (args.currentTurnId) {
6566
7294
  args.lastHeuristicsTurnId.set(args.sessionId, args.currentTurnId);
6567
7295
  }
6568
7296
  }
6569
- if (args.schedulerDecision === "execute" && !materializationRequested) {
6570
- updateSessionMeta(args.db, args.sessionId, { lastResponseTime: Date.now() });
6571
- }
6572
7297
  if (emergencyDropEligible && (pendingOpsDidMutate || heuristicOrReasoningDidMutate)) {
6573
7298
  setEmergencyDropSample(args.db, args.sessionId, args.contextUsage.inputTokens);
6574
7299
  }
@@ -6645,15 +7370,15 @@ async function runPostTransformPhase2(args) {
6645
7370
  if (args.sessionMeta.lastTransformError !== null) {
6646
7371
  updateSessionMeta(args.db, args.sessionId, { lastTransformError: null });
6647
7372
  }
6648
- if (shouldRunHeuristics) {
7373
+ if (shouldRunHeuristics && !freezeM0M1) {
6649
7374
  if (isExplicitFlush)
6650
7375
  explicitMaterializedSuccessfully = true;
6651
7376
  if (deferredMaterialize)
6652
7377
  deferredMaterializedSuccessfully = true;
6653
7378
  }
6654
7379
  } catch (error) {
6655
- args.passOutcome?.record("pending-operation-failure");
6656
7380
  sessionLog(args.sessionId, "transform failed applying pending operations:", error);
7381
+ failPass("pending-operation-failure", error);
6657
7382
  updateSessionMeta(args.db, args.sessionId, { lastTransformError: getErrorMessage(error) });
6658
7383
  }
6659
7384
  if (isCacheBustingPass) {
@@ -6676,7 +7401,7 @@ async function runPostTransformPhase2(args) {
6676
7401
  }
6677
7402
  logTransformTiming(args.sessionId, "dropStaleReduceCalls", t8);
6678
7403
  } catch (error) {
6679
- args.passOutcome?.record("stale-reduce-strip-exception");
7404
+ failPass("stale-reduce-strip-exception", error);
6680
7405
  sessionLog(args.sessionId, "transform failed dropping stale ctx_reduce calls:", error);
6681
7406
  }
6682
7407
  }
@@ -6694,12 +7419,15 @@ async function runPostTransformPhase2(args) {
6694
7419
  }
6695
7420
  logTransformTiming(args.sessionId, "stripProcessedImages", tImg);
6696
7421
  } catch (error) {
6697
- args.passOutcome?.record("image-strip-exception");
7422
+ failPass("image-strip-exception", error);
6698
7423
  sessionLog(args.sessionId, "transform failed stripping processed images:", error);
6699
7424
  }
6700
7425
  }
6701
7426
  const m0M1Enabled = m0M1EnabledForFold;
6702
7427
  if (m0M1Enabled && args.m0M1) {
7428
+ if (freezeM0M1 && !preparedPrefix) {
7429
+ preparedPrefix = prepareCachedM0M1Replay(args.db, args.sessionId);
7430
+ }
6703
7431
  const tInjectM0M1 = performance.now();
6704
7432
  try {
6705
7433
  const result = injectM0M1({
@@ -6715,7 +7443,7 @@ async function runPostTransformPhase2(args) {
6715
7443
  historyBudgetTokens: args.m0M1.historyBudgetTokens,
6716
7444
  historyBudgetPolicyIdentity: args.m0M1.historyBudgetPolicyIdentity,
6717
7445
  temporalAwareness: args.m0M1.temporalAwareness,
6718
- isCacheBustingPass,
7446
+ isCacheBustingPass: isCacheBustingPass && !freezeM0M1,
6719
7447
  preparedPrefix,
6720
7448
  prefixTrimSourceOrder: args.prefixTrimSourceOrder,
6721
7449
  allowFreshContentionFallback: forceMaterialization || emergencyDropEligible,
@@ -6735,7 +7463,8 @@ async function runPostTransformPhase2(args) {
6735
7463
  sessionLog(args.sessionId, `transform: injected m[0]/m[1] (rematerialized=${result.m0RematerializedThisPass}, reason=${result.decision.reason ?? "cache_hit"})`);
6736
7464
  }
6737
7465
  } catch (error) {
6738
- args.passOutcome?.record("m0-m1-injection-degradation");
7466
+ clearInjectionCache(args.sessionId);
7467
+ failPass("m0-m1-injection-degradation", error);
6739
7468
  sessionLog(args.sessionId, "transform: m[0]/m[1] injection failed:", getErrorMessage(error));
6740
7469
  if (args.pendingCompartmentInjection) {
6741
7470
  try {
@@ -6747,7 +7476,6 @@ async function runPostTransformPhase2(args) {
6747
7476
  sessionLog(args.sessionId, "transform: legacy fallback injection also failed:", getErrorMessage(fallbackError));
6748
7477
  }
6749
7478
  }
6750
- clearInjectionCache(args.sessionId);
6751
7479
  }
6752
7480
  logTransformTiming(args.sessionId, "pp.injectM0M1", tInjectM0M1);
6753
7481
  } else if (args.fullFeatureMode && !compactionOff && args.pendingCompartmentInjection) {
@@ -6840,7 +7568,7 @@ async function runPostTransformPhase2(args) {
6840
7568
  case "already-current":
6841
7569
  case "stale-skip":
6842
7570
  persistedCompactionMarkerState = getPersistedCompactionMarkerState(args.db, args.sessionId);
6843
- if (clearPendingCompactionMarkerAfterSuccessfulDrain({
7571
+ if (clearPendingCompactionMarkerAfterSuccessfulDrain2({
6844
7572
  db: args.db,
6845
7573
  sessionId: args.sessionId,
6846
7574
  pending,
@@ -6850,7 +7578,7 @@ async function runPostTransformPhase2(args) {
6850
7578
  }
6851
7579
  break;
6852
7580
  case "retryable-failure":
6853
- args.passOutcome?.record("compaction-marker-drain-failure");
7581
+ failPass("compaction-marker-drain-failure", outcome.error);
6854
7582
  sessionLog(args.sessionId, "compaction-marker drain: retryable failure; preserving deferred history refresh signal", outcome.error);
6855
7583
  suppressV12HistoryDrain = true;
6856
7584
  break;
@@ -6858,6 +7586,7 @@ async function runPostTransformPhase2(args) {
6858
7586
  }
6859
7587
  }
6860
7588
  }
7589
+ const deferredClearedMarkerRetires = !compactionOff && isCacheBustingPass && persistedCompactionMarkerState === null && getDeferredClearedCompactionMarkerState(args.db, args.sessionId) !== null;
6861
7590
  if (!compactionOff) {
6862
7591
  (args.compactionMarkerStrategy ?? defaultCompactionMarkerStrategy2).reconcile(args.messages, persistedCompactionMarkerState, {
6863
7592
  db: args.db,
@@ -6877,6 +7606,7 @@ async function runPostTransformPhase2(args) {
6877
7606
  logTransformTiming(args.sessionId, "pp.markerReconcile", tMarker);
6878
7607
  const tNoteAndTodo = performance.now();
6879
7608
  const noteReadStillVisible = args.fullFeatureMode ? hasVisibleNoteReadCall(args.messages) : false;
7609
+ let noteNudgeAppendedThisPass = false;
6880
7610
  const deferredNoteText = args.fullFeatureMode ? peekNoteNudgeText(args.db, args.sessionId, args.currentTurnId, args.projectPath, noteReadStillVisible) : null;
6881
7611
  if (deferredNoteText) {
6882
7612
  const noteInstruction = `
@@ -6886,13 +7616,16 @@ async function runPostTransformPhase2(args) {
6886
7616
  const outcome = markNoteNudgeDelivered(args.db, args.sessionId, noteInstruction, anchoredMessageId);
6887
7617
  if (anchoredMessageId && outcome.ok) {
6888
7618
  appendReminderToUserMessageById(args.messages, anchoredMessageId, noteInstruction);
7619
+ noteNudgeAppendedThisPass = true;
6889
7620
  } else if (anchoredMessageId && !outcome.ok) {
6890
7621
  args.passOutcome?.record("note-nudge-cas-failure");
6891
7622
  sessionLog(args.sessionId, `note-nudge delivery skipped wire append: ${outcome.kind}`);
6892
7623
  }
6893
7624
  }
7625
+ let todoAnchorMovedThisPass = false;
6894
7626
  if (args.fullFeatureMode && !compactionOff) {
6895
- prependedMessageCount += await applyTodoSynthesis({
7627
+ const todoAnchorBefore = replaySnapshot ? replaySnapshot.todoSyntheticAnchor : getPersistedTodoSyntheticAnchor(args.db, args.sessionId);
7628
+ prependedMessageCount += await applyTodoSynthesis2({
6896
7629
  db: args.db,
6897
7630
  sessionId: args.sessionId,
6898
7631
  messages: args.messages,
@@ -6905,6 +7638,10 @@ async function runPostTransformPhase2(args) {
6905
7638
  activeAgent: args.activeAgent,
6906
7639
  replaySnapshot
6907
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
+ }
6908
7645
  }
6909
7646
  logTransformTiming(args.sessionId, "pp.noteAndTodoSynthesis", tNoteAndTodo);
6910
7647
  if (args.compartmentInjectionRebuiltFromDb && args.pendingCompartmentInjection) {
@@ -6919,7 +7656,7 @@ async function runPostTransformPhase2(args) {
6919
7656
  }
6920
7657
  }
6921
7658
  if (args.fullFeatureMode && isCacheBustingPass && args.m0M1 && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory)) {
6922
- checkM0MutationDriftAndSignal({
7659
+ checkM0MutationDriftAndSignal2({
6923
7660
  db: args.db,
6924
7661
  sessionId: args.sessionId,
6925
7662
  cachedM0MaxMutationId: args.sessionMeta.cachedM0MaxMutationId,
@@ -6927,9 +7664,12 @@ async function runPostTransformPhase2(args) {
6927
7664
  historyRefreshSessions: args.historyRefreshSessions
6928
7665
  });
6929
7666
  }
7667
+ let autoSearchHintsBefore = 0;
7668
+ let autoSearchHintAppendedThisPass = false;
6930
7669
  if (args.fullFeatureMode && args.autoSearch?.enabled && args.projectPath) {
6931
7670
  const tAutoSearch = performance.now();
6932
7671
  const visibleMemoryIds = getVisibleMemoryIds(args.db, args.sessionId) ?? undefined;
7672
+ autoSearchHintsBefore = countAutoSearchHints(args.db, args.sessionId);
6933
7673
  try {
6934
7674
  const autoSearchOutcome = await runAutoSearchHint({
6935
7675
  sessionId: args.sessionId,
@@ -6942,7 +7682,8 @@ async function runPostTransformPhase2(args) {
6942
7682
  directory: args.autoSearch.directory ?? args.sessionDirectory,
6943
7683
  projectPath: args.projectPath,
6944
7684
  ensureProjectRegistered: args.autoSearch.ensureProjectRegistered,
6945
- visibleMemoryIds
7685
+ visibleMemoryIds,
7686
+ wordRules: args.autoSearch.wordRules
6946
7687
  }
6947
7688
  });
6948
7689
  if (!autoSearchOutcome.ok) {
@@ -6952,6 +7693,7 @@ async function runPostTransformPhase2(args) {
6952
7693
  args.passOutcome?.record("auto-search-internal-failure");
6953
7694
  sessionLog(args.sessionId, "auto-search runner failed:", error);
6954
7695
  }
7696
+ autoSearchHintAppendedThisPass = countAutoSearchHints(args.db, args.sessionId) !== autoSearchHintsBefore;
6955
7697
  logTransformTiming(args.sessionId, "pp.autoSearchHint", tAutoSearch);
6956
7698
  }
6957
7699
  if (args.fullFeatureMode && isCacheBustingPass) {
@@ -6988,9 +7730,10 @@ async function runPostTransformPhase2(args) {
6988
7730
  }
6989
7731
  }
6990
7732
  const mergedReasoningStrippedIds = new Set(replaySnapshot?.mergedReasoningStrippedIds ?? []);
7733
+ let lateEditBeforeNewestThinking = false;
6991
7734
  const thinkingBindingRecoveryMessageIds = new Set;
6992
7735
  let thinkingBindingRecovery = null;
6993
- if (canUseEmptySentinels && !compactionOff) {
7736
+ if (!compactionOff) {
6994
7737
  try {
6995
7738
  for (const id of mergedReasoningStrippedIds) {
6996
7739
  if (id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX)) {
@@ -7012,14 +7755,16 @@ async function runPostTransformPhase2(args) {
7012
7755
  for (const messageId of thinkingBindingRecovery.messageIds) {
7013
7756
  mergedReasoningStrippedIds.add(thinkingBindingRecoveryFrozenId(messageId));
7014
7757
  }
7015
- if (thinkingBindingRecovery.messageIds.length > 0)
7758
+ if (thinkingBindingRecovery.messageIds.length > 0) {
7016
7759
  bustedThisPass = true;
7760
+ lateEditBeforeNewestThinking = true;
7761
+ }
7017
7762
  } else {
7018
- args.passOutcome?.record("thinking-binding-recovery-persistence-failure");
7763
+ failPass("thinking-binding-recovery-persistence-failure");
7019
7764
  sessionLog(args.sessionId, "thinking binding recovery: persistence failed; leaving the bound blocks intact");
7020
7765
  }
7021
7766
  }
7022
- if (isCacheBustingPass) {
7767
+ if (canUseEmptySentinels && isCacheBustingPass) {
7023
7768
  const candidates = findMergedReasoningStripDecisions(args.messages, args.resolvedProviderID, mergedReasoningStrippedIds, { mutationExemptMessage: reasoningMutationExemptMessage });
7024
7769
  const newlyDetectedIds = candidates.filter((id) => !mergedReasoningStrippedIds.has(id));
7025
7770
  if (newlyDetectedIds.length > 0) {
@@ -7030,14 +7775,15 @@ async function runPostTransformPhase2(args) {
7030
7775
  mergedReasoningStrippedIds.add(id);
7031
7776
  }
7032
7777
  bustedThisPass = true;
7778
+ lateEditBeforeNewestThinking = true;
7033
7779
  } else {
7034
- args.passOutcome?.record("merged-reasoning-strip-persistence-failure");
7780
+ failPass("merged-reasoning-strip-persistence-failure");
7035
7781
  sessionLog(args.sessionId, "merged reasoning strip: persistence failed; leaving newly detected assistants intact");
7036
7782
  }
7037
7783
  }
7038
7784
  }
7039
7785
  } catch (error) {
7040
- args.passOutcome?.record("merged-reasoning-strip-exception");
7786
+ failPass("merged-reasoning-strip-exception", error);
7041
7787
  sessionLog(args.sessionId, "transform failed freezing merged reasoning strip:", error);
7042
7788
  }
7043
7789
  }
@@ -7058,17 +7804,18 @@ async function runPostTransformPhase2(args) {
7058
7804
  try {
7059
7805
  const demotedIds = demoteTrailingBlankKeepDecisions(args.db, args.sessionId, poisonedKeepIds);
7060
7806
  if (demotedIds === null) {
7061
- args.passOutcome?.record("trailing-blank-heal-persistence-failure");
7807
+ failPass("trailing-blank-heal-persistence-failure");
7062
7808
  sessionLog(args.sessionId, "trailing blank heal: persistence failed; retaining frozen keep decisions");
7063
7809
  } else {
7064
7810
  for (const id of demotedIds) {
7065
7811
  trailingBlankDecisions.set(id, "strip");
7066
7812
  bustedThisPass = true;
7813
+ lateEditBeforeNewestThinking = true;
7067
7814
  sessionLog(args.sessionId, `trailing blank heal: demoted message ${id} from keep to strip because its source has no trailing blank`);
7068
7815
  }
7069
7816
  }
7070
7817
  } catch (error) {
7071
- args.passOutcome?.record("trailing-blank-heal-exception");
7818
+ failPass("trailing-blank-heal-exception", error);
7072
7819
  sessionLog(args.sessionId, "transform failed healing trailing blank decisions:", error);
7073
7820
  }
7074
7821
  }
@@ -7085,7 +7832,7 @@ async function runPostTransformPhase2(args) {
7085
7832
  overwriteMessageId: newestAssistantId
7086
7833
  });
7087
7834
  if (persisted) {
7088
- const committed = getTrailingBlankDecisions(args.db, args.sessionId);
7835
+ const committed = getTrailingBlankDecisions(args.db, args.sessionId, candidates.map(([id]) => id));
7089
7836
  for (const [id] of candidates) {
7090
7837
  const decision = committed.get(id);
7091
7838
  if (decision)
@@ -7093,12 +7840,15 @@ async function runPostTransformPhase2(args) {
7093
7840
  }
7094
7841
  if (isCacheBustingPass)
7095
7842
  bustedThisPass = true;
7843
+ if (isCacheBustingPass && candidates.some(([id]) => id !== newestAssistantId)) {
7844
+ lateEditBeforeNewestThinking = true;
7845
+ }
7096
7846
  } else {
7097
- args.passOutcome?.record("trailing-blank-decision-persistence-failure");
7847
+ failPass("trailing-blank-decision-persistence-failure");
7098
7848
  sessionLog(args.sessionId, "trailing blank decision: persistence failed; serving the frozen decisions");
7099
7849
  }
7100
7850
  } catch (error) {
7101
- args.passOutcome?.record("trailing-blank-decision-exception");
7851
+ failPass("trailing-blank-decision-exception", error);
7102
7852
  sessionLog(args.sessionId, "transform failed freezing trailing blank decision:", error);
7103
7853
  }
7104
7854
  }
@@ -7114,9 +7864,11 @@ async function runPostTransformPhase2(args) {
7114
7864
  skipMergedReasoningStrip: compactionOff,
7115
7865
  skipTrailingWhitespaceStrip: compactionOff
7116
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;
7117
7869
  let proactiveThinkingStrip = null;
7118
- if (canUseEmptySentinels && !compactionOff && args.fullFeatureMode && args.thinkingBindingRecoveryEnabledForModel === true && proactiveThinkingStripPermitted) {
7119
- const outcome = freezeReasoningOnBustingPass({
7870
+ if (!compactionOff && args.thinkingBindingRecoveryEnabledForModel === true && proactiveThinkingStripPermitted && prefixEditBesidesReasoningTrim) {
7871
+ const outcome = freezeReasoningOnBustingPass2({
7120
7872
  db: args.db,
7121
7873
  sessionId: args.sessionId,
7122
7874
  messages: args.messages,
@@ -7130,12 +7882,32 @@ async function runPostTransformPhase2(args) {
7130
7882
  }
7131
7883
  bustedThisPass = true;
7132
7884
  } else if (outcome.persistenceFailed) {
7133
- 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
+ }
7134
7904
  }
7905
+ settledDroppedReasoning = settleDroppedReasoningParts(args.messages, mode);
7135
7906
  }
7136
7907
  const tFinalRepresentation = performance.now();
7137
- const finalRepresentation = finalizeMessageRepresentation(args.messages, args.resolvedProviderID, finalizeOptions);
7138
- 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}`);
7139
7911
  logTransformTiming(args.sessionId, "finalizeMessageRepresentation", tFinalRepresentation, `clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
7140
7912
  const tTailBaseline = performance.now();
7141
7913
  let assertedBaseline;
@@ -7247,11 +8019,12 @@ async function runPostTransformPhase2(args) {
7247
8019
  droppedCount,
7248
8020
  emergency,
7249
8021
  bustedThisPass,
8022
+ prefixTrimStatus: deliveredPrefix?.prefixTrimStatus ?? null,
7250
8023
  thinkingBindingRecovery,
7251
8024
  proactiveThinkingStrip
7252
8025
  };
7253
8026
  }
7254
- function checkM0MutationDriftAndSignal(args) {
8027
+ function checkM0MutationDriftAndSignal2(args) {
7255
8028
  const currentMaxMutationId = getMaxM0MutationId(args.db, args.sessionId) ?? 0;
7256
8029
  const cachedMaxMutationId = args.cachedM0MaxMutationId ?? 0;
7257
8030
  if (currentMaxMutationId !== cachedMaxMutationId) {
@@ -7263,4 +8036,4 @@ function checkM0MutationDriftAndSignal(args) {
7263
8036
  return false;
7264
8037
  }
7265
8038
 
7266
- 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 };