@cortexkit/opencode-magic-context 0.41.4 → 0.42.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/README.md +21 -3
  2. package/dist/agents/hidden-agent-registrations.d.ts +1 -3
  3. package/dist/agents/hidden-agent-registrations.d.ts.map +1 -1
  4. package/dist/agents/magic-context-prompt.d.ts +1 -1
  5. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  6. package/dist/agents/permissions.d.ts +1 -22
  7. package/dist/agents/permissions.d.ts.map +1 -1
  8. package/dist/config/agent-disable.d.ts +0 -5
  9. package/dist/config/agent-disable.d.ts.map +1 -1
  10. package/dist/config/index.d.ts +5 -0
  11. package/dist/config/index.d.ts.map +1 -1
  12. package/dist/config/migrate-config-location.d.ts.map +1 -1
  13. package/dist/config/project-security.d.ts +20 -2
  14. package/dist/config/project-security.d.ts.map +1 -1
  15. package/dist/config/removed-agent-config.d.ts +8 -0
  16. package/dist/config/removed-agent-config.d.ts.map +1 -0
  17. package/dist/config/schema/magic-context.d.ts +43 -201
  18. package/dist/config/schema/magic-context.d.ts.map +1 -1
  19. package/dist/{conflict-warning-hook-ejkc9sjn.js → conflict-warning-hook-6p3xqeac.js} +3 -3
  20. package/dist/{derive-budgets-bc366cz8.js → derive-budgets-s2pgnnm4.js} +1 -1
  21. package/dist/features/builtin-commands/commands.d.ts +0 -4
  22. package/dist/features/builtin-commands/commands.d.ts.map +1 -1
  23. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  24. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +15 -4
  25. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  26. package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
  27. package/dist/features/magic-context/context-authority.d.ts +31 -4
  28. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  29. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  30. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  31. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  32. package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
  33. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  34. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts +19 -9
  35. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts.map +1 -1
  36. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  37. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  38. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +4 -0
  39. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  40. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  41. package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
  42. package/dist/features/magic-context/git-commits/sweep-coordinator.d.ts.map +1 -1
  43. package/dist/features/magic-context/index.d.ts +0 -1
  44. package/dist/features/magic-context/index.d.ts.map +1 -1
  45. package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
  46. package/dist/features/magic-context/memory/embedding-local.d.ts +13 -0
  47. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  48. package/dist/features/magic-context/memory/embedding-model-match.d.ts +41 -0
  49. package/dist/features/magic-context/memory/embedding-model-match.d.ts.map +1 -0
  50. package/dist/features/magic-context/memory/embedding-openai.d.ts +7 -20
  51. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  52. package/dist/features/magic-context/memory/embedding-provider.d.ts +2 -2
  53. package/dist/features/magic-context/memory/embedding-provider.d.ts.map +1 -1
  54. package/dist/features/magic-context/memory/embedding-synapse.d.ts +48 -14
  55. package/dist/features/magic-context/memory/embedding-synapse.d.ts.map +1 -1
  56. package/dist/features/magic-context/memory/embedding.d.ts +1 -1
  57. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  58. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  59. package/dist/features/magic-context/memory/project-identity.d.ts +1 -0
  60. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  61. package/dist/features/magic-context/memory/promotion.d.ts +7 -1
  62. package/dist/features/magic-context/memory/promotion.d.ts.map +1 -1
  63. package/dist/features/magic-context/merged-reasoning-decisions.d.ts +6 -0
  64. package/dist/features/magic-context/merged-reasoning-decisions.d.ts.map +1 -0
  65. package/dist/features/magic-context/message-fts-rowid-map.d.ts.map +1 -1
  66. package/dist/features/magic-context/message-index-async.d.ts +12 -0
  67. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  68. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  69. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  70. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  71. package/dist/features/magic-context/mural/render-trigger.d.ts +6 -0
  72. package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
  73. package/dist/features/magic-context/no-content-compartment.d.ts +12 -0
  74. package/dist/features/magic-context/no-content-compartment.d.ts.map +1 -0
  75. package/dist/features/magic-context/pi-content-decisions.d.ts +9 -0
  76. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -0
  77. package/dist/features/magic-context/project-docs-hash.d.ts +4 -0
  78. package/dist/features/magic-context/project-docs-hash.d.ts.map +1 -1
  79. package/dist/features/magic-context/project-embedding-registry.d.ts +13 -4
  80. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  81. package/dist/features/magic-context/protection-window.d.ts +79 -0
  82. package/dist/features/magic-context/protection-window.d.ts.map +1 -0
  83. package/dist/features/magic-context/search.d.ts.map +1 -1
  84. package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
  85. package/dist/features/magic-context/shadow-backfill-state.d.ts +26 -0
  86. package/dist/features/magic-context/shadow-backfill-state.d.ts.map +1 -0
  87. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  88. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +4 -0
  89. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
  90. package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
  91. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  92. package/dist/features/magic-context/storage-db.d.ts +1 -1
  93. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  94. package/dist/features/magic-context/storage-embedding-measurements.d.ts +2 -2
  95. package/dist/features/magic-context/storage-embedding-measurements.d.ts.map +1 -1
  96. package/dist/features/magic-context/storage-historian-runs.d.ts +4 -0
  97. package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
  98. package/dist/features/magic-context/storage-memory-mutation-log.d.ts +1 -0
  99. package/dist/features/magic-context/storage-memory-mutation-log.d.ts.map +1 -1
  100. package/dist/features/magic-context/storage-meta-persisted.d.ts +79 -13
  101. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  102. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  103. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  104. package/dist/features/magic-context/storage-native-replay.d.ts +29 -0
  105. package/dist/features/magic-context/storage-native-replay.d.ts.map +1 -0
  106. package/dist/features/magic-context/storage-notes.d.ts +6 -0
  107. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  108. package/dist/features/magic-context/storage-replay-document.d.ts +33 -0
  109. package/dist/features/magic-context/storage-replay-document.d.ts.map +1 -0
  110. package/dist/features/magic-context/storage-subagent-invocations.d.ts +1 -1
  111. package/dist/features/magic-context/storage-subagent-invocations.d.ts.map +1 -1
  112. package/dist/features/magic-context/storage-tags.d.ts +19 -11
  113. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  114. package/dist/features/magic-context/storage.d.ts +3 -3
  115. package/dist/features/magic-context/storage.d.ts.map +1 -1
  116. package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
  117. package/dist/features/magic-context/tagger.d.ts +13 -0
  118. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  119. package/dist/features/magic-context/tool-owner-backfill.d.ts.map +1 -1
  120. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  121. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  122. package/dist/features/magic-context/workspaces.d.ts.map +1 -1
  123. package/dist/hooks/magic-context/apply-operations.d.ts +11 -5
  124. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  125. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  126. package/dist/hooks/magic-context/cache-busting-signals.d.ts +9 -1
  127. package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
  128. package/dist/hooks/magic-context/caveman-cleanup.d.ts +1 -1
  129. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
  130. package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
  131. package/dist/hooks/magic-context/child-session-spawn.d.ts +3 -3
  132. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
  133. package/dist/hooks/magic-context/command-handler.d.ts +1 -10
  134. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  135. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  136. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +10 -21
  137. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts.map +1 -1
  138. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  139. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  140. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  141. package/dist/hooks/magic-context/compartment-runner-validation.d.ts +1 -1
  142. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  143. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +26 -2
  144. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
  145. package/dist/hooks/magic-context/decay-render.d.ts.map +1 -1
  146. package/dist/hooks/magic-context/dropped-input-guard.d.ts +9 -0
  147. package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -0
  148. package/dist/hooks/magic-context/embed-session-state.d.ts +1 -1
  149. package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
  150. package/dist/hooks/magic-context/emergency-drop.d.ts +6 -1
  151. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  152. package/dist/hooks/magic-context/event-handler.d.ts +0 -1
  153. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  154. package/dist/hooks/magic-context/event-payloads.d.ts +7 -6
  155. package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
  156. package/dist/hooks/magic-context/event-resolvers.d.ts +1 -1
  157. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  158. package/dist/hooks/magic-context/execute-status.d.ts +3 -1
  159. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  160. package/dist/hooks/magic-context/format-embed-failure.d.ts +2 -1
  161. package/dist/hooks/magic-context/format-embed-failure.d.ts.map +1 -1
  162. package/dist/hooks/magic-context/format-embed-status.d.ts.map +1 -1
  163. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +7 -1
  164. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  165. package/dist/hooks/magic-context/hook-handlers.d.ts +3 -1
  166. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  167. package/dist/hooks/magic-context/hook.d.ts +13 -4
  168. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  169. package/dist/hooks/magic-context/inject-compartments.d.ts +14 -1
  170. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  171. package/dist/hooks/magic-context/live-session-state.d.ts +1 -1
  172. package/dist/hooks/magic-context/lkg-slot.d.ts +34 -0
  173. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  174. package/dist/hooks/magic-context/maintenance-authority.d.ts +2 -2
  175. package/dist/hooks/magic-context/maintenance-authority.d.ts.map +1 -1
  176. package/dist/hooks/magic-context/module-state-sync-timing.d.ts +21 -0
  177. package/dist/hooks/magic-context/module-state-sync-timing.d.ts.map +1 -0
  178. package/dist/hooks/magic-context/module-state-sync.d.ts +21 -7
  179. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  180. package/dist/hooks/magic-context/module-transport.d.ts +12 -0
  181. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  182. package/dist/hooks/magic-context/module-wire.d.ts +8 -0
  183. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  184. package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
  185. package/dist/hooks/magic-context/persist-filtered-noise.d.ts +5 -0
  186. package/dist/hooks/magic-context/persist-filtered-noise.d.ts.map +1 -0
  187. package/dist/hooks/magic-context/protected-tail-boundary.d.ts +6 -0
  188. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  189. package/dist/hooks/magic-context/read-session-chunk.d.ts +18 -18
  190. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  191. package/dist/hooks/magic-context/read-session-db.d.ts +22 -12
  192. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  193. package/dist/hooks/magic-context/read-session-formatting.d.ts +8 -0
  194. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  195. package/dist/hooks/magic-context/read-session-raw.d.ts +10 -1
  196. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  197. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  198. package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -1
  199. package/dist/hooks/magic-context/rust-mode-transform.d.ts +74 -9
  200. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  201. package/dist/hooks/magic-context/send-session-notification.d.ts +11 -10
  202. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  203. package/dist/hooks/magic-context/strip-content.d.ts +7 -0
  204. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  205. package/dist/hooks/magic-context/supersession-reclaim.d.ts +13 -0
  206. package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
  207. package/dist/hooks/magic-context/system-prompt-hash.d.ts +2 -3
  208. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  209. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +8 -3
  210. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  211. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  212. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  213. package/dist/hooks/magic-context/transform-context-state.d.ts +7 -1
  214. package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
  215. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +11 -4
  216. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  217. package/dist/hooks/magic-context/transform.d.ts +7 -2
  218. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  219. package/dist/hooks/magic-context/upgrade-reminder.d.ts +7 -9
  220. package/dist/hooks/magic-context/upgrade-reminder.d.ts.map +1 -1
  221. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  222. package/dist/index-1974jvn3.js +783 -0
  223. package/dist/{index-0y2mcg5y.js → index-1q9kay7n.js} +18717 -16197
  224. package/dist/{index-4avmwfp5.js → index-36wd1d6k.js} +6 -29
  225. package/dist/{index-fz104x1j.js → index-jmtjh2d3.js} +3 -3
  226. package/dist/{index-q264erdp.js → index-nqgjwfzn.js} +70 -38
  227. package/dist/{index-mjv9je4e.js → index-xdtge3y2.js} +45 -7
  228. package/dist/index.d.ts.map +1 -1
  229. package/dist/index.js +6457 -5190
  230. package/dist/plugin/conflict-warning-hook.d.ts +5 -6
  231. package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
  232. package/dist/plugin/dream-timer.d.ts +1 -0
  233. package/dist/plugin/dream-timer.d.ts.map +1 -1
  234. package/dist/plugin/embedding-bootstrap-helpers.d.ts.map +1 -1
  235. package/dist/plugin/embedding-routing.d.ts +4 -1
  236. package/dist/plugin/embedding-routing.d.ts.map +1 -1
  237. package/dist/plugin/hooks/create-session-hooks.d.ts +16 -2
  238. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  239. package/dist/plugin/rpc-handlers.d.ts +31 -1
  240. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  241. package/dist/plugin/rust-tool-backends.d.ts +1 -0
  242. package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
  243. package/dist/plugin/tool-registry.d.ts.map +1 -1
  244. package/dist/{recomp-orchestrator-q98r6rga.js → recomp-orchestrator-m33b3rk9.js} +5 -5
  245. package/dist/{send-session-notification-hdh02wy9.js → send-session-notification-1qeqkswb.js} +6 -4
  246. package/dist/shared/child-session-teardown.d.ts +34 -0
  247. package/dist/shared/child-session-teardown.d.ts.map +1 -0
  248. package/dist/shared/keep-subagents.d.ts +1 -1
  249. package/dist/shared/keep-subagents.d.ts.map +1 -1
  250. package/dist/shared/model-suggestion-retry.d.ts +1 -1
  251. package/dist/shared/opencode-db-path.d.ts +24 -0
  252. package/dist/shared/opencode-db-path.d.ts.map +1 -0
  253. package/dist/shared/prompt-surface-runtime.d.ts +10 -5
  254. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  255. package/dist/shared/resolve-fallbacks.d.ts +1 -1
  256. package/dist/shared/rpc-types.d.ts +121 -0
  257. package/dist/shared/rpc-types.d.ts.map +1 -1
  258. package/dist/shared/sqlite.d.ts +42 -0
  259. package/dist/shared/sqlite.d.ts.map +1 -1
  260. package/dist/shared/status-detail-text.d.ts +3 -1
  261. package/dist/shared/status-detail-text.d.ts.map +1 -1
  262. package/dist/shared/status-summary.d.ts +30 -0
  263. package/dist/shared/status-summary.d.ts.map +1 -0
  264. package/dist/shared/subagent-runner.d.ts +17 -10
  265. package/dist/shared/subagent-runner.d.ts.map +1 -1
  266. package/dist/shared/tag-transcript.d.ts.map +1 -1
  267. package/dist/shared/tail-hygiene-status.d.ts +1 -0
  268. package/dist/shared/tail-hygiene-status.d.ts.map +1 -1
  269. package/dist/shared/transcript.d.ts +6 -0
  270. package/dist/shared/transcript.d.ts.map +1 -1
  271. package/dist/shared/user-facing-codes.d.ts +191 -0
  272. package/dist/shared/user-facing-codes.d.ts.map +1 -0
  273. package/dist/shared/window-geometry.d.ts +23 -0
  274. package/dist/shared/window-geometry.d.ts.map +1 -1
  275. package/dist/shared/write-transaction-timing.d.ts +1 -1
  276. package/dist/shared/write-transaction-timing.d.ts.map +1 -1
  277. package/dist/{storage-meta-session-dvwfw778.js → storage-meta-session-e6g0mmec.js} +2 -2
  278. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  279. package/dist/tools/ctx-memory/verification-recording.d.ts.map +1 -1
  280. package/dist/tools/ctx-note/constants.d.ts +1 -1
  281. package/dist/tools/ctx-note/constants.d.ts.map +1 -1
  282. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  283. package/dist/tools/ctx-note/types.d.ts +1 -0
  284. package/dist/tools/ctx-note/types.d.ts.map +1 -1
  285. package/dist/tools/ctx-reduce/tools.d.ts +10 -1
  286. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  287. package/dist/tools/ctx-search/constants.d.ts +1 -1
  288. package/dist/tools/ctx-search/constants.d.ts.map +1 -1
  289. package/dist/tools/light-descriptions.d.ts +2 -2
  290. package/dist/tools/light-descriptions.d.ts.map +1 -1
  291. package/package.json +2 -3
  292. package/src/agents/hidden-agent-registrations.ts +3 -15
  293. package/src/agents/magic-context-prompt.test.ts +7 -5
  294. package/src/agents/magic-context-prompt.ts +22 -30
  295. package/src/agents/permissions.test.ts +1 -42
  296. package/src/agents/permissions.ts +1 -24
  297. package/src/config/agent-disable.ts +5 -22
  298. package/src/config/index.test.ts +126 -15
  299. package/src/config/index.ts +41 -6
  300. package/src/config/latch-permanence-guard.test.ts +4 -0
  301. package/src/config/migrate-config-location.test.ts +39 -6
  302. package/src/config/migrate-config-location.ts +18 -31
  303. package/src/config/profiles.ts +1 -1
  304. package/src/config/project-security.hostile-matrix.test.ts +0 -8
  305. package/src/config/project-security.test.ts +21 -24
  306. package/src/config/project-security.ts +115 -14
  307. package/src/config/protected-tokens.test.ts +235 -0
  308. package/src/config/removed-agent-config.ts +45 -0
  309. package/src/config/removed-agent-source-fence.test.ts +56 -0
  310. package/src/config/schema/magic-context.test.ts +50 -42
  311. package/src/config/schema/magic-context.ts +70 -37
  312. package/src/shared/child-session-teardown.test.ts +218 -0
  313. package/src/shared/child-session-teardown.ts +66 -0
  314. package/src/shared/keep-subagents.ts +9 -14
  315. package/src/shared/model-suggestion-retry.ts +1 -1
  316. package/src/shared/opencode-db-path.test.ts +196 -0
  317. package/src/shared/opencode-db-path.ts +215 -0
  318. package/src/shared/prompt-surface-a1-golden.md +50 -35
  319. package/src/shared/prompt-surface-runtime.test.ts +28 -0
  320. package/src/shared/prompt-surface-runtime.ts +22 -5
  321. package/src/shared/resolve-fallbacks.ts +1 -1
  322. package/src/shared/rpc-types.ts +128 -0
  323. package/src/shared/session-messages-bounded.test.ts +1 -1
  324. package/src/shared/sqlite-import-fence.test.ts +19 -0
  325. package/src/shared/sqlite.test.ts +27 -1
  326. package/src/shared/sqlite.ts +204 -1
  327. package/src/shared/status-detail-text.test.ts +92 -20
  328. package/src/shared/status-detail-text.ts +24 -2
  329. package/src/shared/status-summary.ts +167 -0
  330. package/src/shared/subagent-runner.ts +17 -10
  331. package/src/shared/tag-transcript.ts +33 -21
  332. package/src/shared/tail-hygiene-status.ts +8 -0
  333. package/src/shared/transcript.ts +7 -0
  334. package/src/shared/user-facing-codes.test.ts +140 -0
  335. package/src/shared/user-facing-codes.ts +276 -0
  336. package/src/shared/window-geometry.test.ts +44 -0
  337. package/src/shared/window-geometry.ts +89 -11
  338. package/src/shared/write-transaction-attribution.test.ts +241 -0
  339. package/src/shared/write-transaction-timing.ts +2 -1
  340. package/src/tui/index.tsx +44 -11
  341. package/src/tui/slots/sidebar-content.tsx +12 -7
  342. package/src/tui-compiled/index.tsx +662 -649
  343. package/src/tui-compiled/slots/sidebar-content.tsx +301 -305
  344. package/dist/agents/sidekick.d.ts +0 -2
  345. package/dist/agents/sidekick.d.ts.map +0 -1
  346. package/dist/features/magic-context/defaults.d.ts +0 -2
  347. package/dist/features/magic-context/defaults.d.ts.map +0 -1
  348. package/dist/features/magic-context/sidekick/agent.d.ts +0 -14
  349. package/dist/features/magic-context/sidekick/agent.d.ts.map +0 -1
  350. package/dist/features/magic-context/sidekick/core.d.ts +0 -38
  351. package/dist/features/magic-context/sidekick/core.d.ts.map +0 -1
  352. package/dist/features/magic-context/sidekick/index.d.ts +0 -3
  353. package/dist/features/magic-context/sidekick/index.d.ts.map +0 -1
  354. package/dist/hooks/magic-context/boundary-execution.d.ts +0 -27
  355. package/dist/hooks/magic-context/boundary-execution.d.ts.map +0 -1
  356. package/dist/index-raatkvw5.js +0 -360
  357. package/src/agents/sidekick.ts +0 -1
  358. package/src/features/magic-context/defaults.ts +0 -1
@@ -80,6 +80,34 @@ describe("prompt-surface runtime", () => {
80
80
  expect(changedModel.primaryOverride).toBe(second);
81
81
  });
82
82
 
83
+ it("shares one frozen guidance epoch between the system hook and Rust adapter", () => {
84
+ const directory = tempDir();
85
+ const path = join(directory, "guidance.md");
86
+ const first = "## Magic Context\n\nShared first epoch";
87
+ const second = "## Magic Context\n\nShared second epoch";
88
+ writeFileSync(path, first);
89
+ const runtime = createPromptSurfaceRuntime({
90
+ userConfigDirectory: directory,
91
+ warn: () => undefined,
92
+ });
93
+ const systemEpochs = createPromptSurfaceGuidanceEpochCache(runtime);
94
+ const adapterEpochs = createPromptSurfaceGuidanceEpochCache(runtime);
95
+ const config = {
96
+ default: "full" as const,
97
+ guidance_override_path: "guidance.md",
98
+ };
99
+
100
+ const systemInitial = systemEpochs.resolve("session", config, "provider/model");
101
+ writeFileSync(path, second);
102
+ const adapterDeferred = adapterEpochs.resolve("session", config, "provider/model");
103
+ expect(adapterDeferred).toBe(systemInitial);
104
+ expect(adapterDeferred.primaryOverride).toBe(first);
105
+
106
+ adapterEpochs.clear("session");
107
+ const systemNextEpoch = systemEpochs.resolve("session", config, "provider/model");
108
+ expect(systemNextEpoch.primaryOverride).toBe(second);
109
+ });
110
+
83
111
  it("uses registration default, applies known overrides, and reports invalid IDs", () => {
84
112
  const warnings: string[] = [];
85
113
  const runtime = createPromptSurfaceRuntime({
@@ -230,18 +230,33 @@ interface GuidanceEpoch {
230
230
  selection: PromptSurfaceGuidanceSelection;
231
231
  }
232
232
 
233
- /** Freeze preset selection and materialized override bytes for one model-key epoch. */
234
- export function createPromptSurfaceGuidanceEpochCache(runtime: PromptSurfaceRuntime): {
233
+ export interface PromptSurfaceGuidanceEpochCache {
235
234
  resolve: (
236
235
  sessionId: string,
237
236
  config: PromptSurfaceConfig | undefined,
238
237
  modelKey: string | undefined,
239
238
  ) => PromptSurfaceGuidanceSelection;
240
239
  clear: (sessionId: string) => void;
241
- } {
242
- const epochs = new Map<string, GuidanceEpoch>();
240
+ }
243
241
 
244
- return {
242
+ const guidanceEpochCacheByRuntime = new WeakMap<
243
+ PromptSurfaceRuntime,
244
+ PromptSurfaceGuidanceEpochCache
245
+ >();
246
+
247
+ /**
248
+ * Freeze preset selection and materialized override bytes for one model-key epoch.
249
+ * Every hook using the same runtime also shares this cache, so a file edit cannot
250
+ * make the system hook and Rust adapter observe different bytes within one epoch.
251
+ */
252
+ export function createPromptSurfaceGuidanceEpochCache(
253
+ runtime: PromptSurfaceRuntime,
254
+ ): PromptSurfaceGuidanceEpochCache {
255
+ const shared = guidanceEpochCacheByRuntime.get(runtime);
256
+ if (shared) return shared;
257
+
258
+ const epochs = new Map<string, GuidanceEpoch>();
259
+ const cache: PromptSurfaceGuidanceEpochCache = {
245
260
  resolve(sessionId, config, modelKey) {
246
261
  const canonicalModelKey = modelKey ? piModelRefToCanonical(modelKey) : undefined;
247
262
  const cached = epochs.get(sessionId);
@@ -257,4 +272,6 @@ export function createPromptSurfaceGuidanceEpochCache(runtime: PromptSurfaceRunt
257
272
  epochs.delete(sessionId);
258
273
  },
259
274
  };
275
+ guidanceEpochCacheByRuntime.set(runtime, cache);
276
+ return cache;
260
277
  }
@@ -2,7 +2,7 @@ import type { ModelInput, ResolvedModelEntry } from "./model-resolution";
2
2
 
3
3
  /**
4
4
  * Resolve the fallback model list to attempt for a hidden-agent (historian /
5
- * dreamer / sidekick) call when its configured primary fails.
5
+ * dreamer) call when its configured primary fails.
6
6
  *
7
7
  * Policy: ONLY the user's explicitly-configured `fallback_models` for this
8
8
  * agent. There is NO builtin provider-agnostic chain — a hardcoded chain
@@ -7,12 +7,15 @@ import type {
7
7
  DreamTaskBacklogMap,
8
8
  DreamTaskProgress,
9
9
  } from "../features/magic-context/dreamer/task-registry";
10
+ import type { SynapseLaneDescriptor } from "../features/magic-context/memory/embedding-synapse";
10
11
  import type { ConfigParseFailure } from "./config-diagnostics";
11
12
  import type { LoggerDiagnostics } from "./logger";
12
13
 
13
14
  export interface TailHygieneStatus {
14
15
  /** Tokens in active, non-protected tail content that the agent can reclaim. */
15
16
  u: number;
17
+ /** Spent tool outputs contributing positive tokens to U in this baseline. */
18
+ reclaimableToolOutputCount?: number;
16
19
  /** Tokens in rendered-tail content eligible for hygiene accounting in the same scan. */
17
20
  t: number;
18
21
  /** Reclaimable-to-eligible token ratio, clamped to 0–1 and shared by both nudge mechanisms. */
@@ -54,6 +57,8 @@ export interface SidebarSnapshot {
54
57
  cacheTtl: string;
55
58
  /** Persistent runtime failure shown directly in the sidebar when non-null. */
56
59
  lastTransformError: string | null;
60
+ /** Durable history-compression failure count used to select the stable summary warning. */
61
+ historianFailureCount?: number;
57
62
  lastDreamerRunAt: number | null;
58
63
  projectIdentity: string | null;
59
64
  compartmentTokens: number;
@@ -169,6 +174,8 @@ export interface StatusDetail extends SidebarSnapshot {
169
174
  reserve: number;
170
175
  reserveSource: "output_catalog" | "output_config" | "wall_margin" | "none";
171
176
  geometry: "shared_upfront" | "shared_truncating" | "separate";
177
+ windowSource: "catalog" | "overlay" | "provider" | "detected";
178
+ absoluteWall: number;
172
179
  };
173
180
  };
174
181
  /**
@@ -221,6 +228,12 @@ export interface StatusDetail extends SidebarSnapshot {
221
228
  * (the plugin owns it), so this surface supplies the live DB value; the module
222
229
  * surface supplies the module-store value instead.
223
230
  */
231
+ /** Search-indexing coverage and current command state for the default status summary. */
232
+ embedding?: {
233
+ state: "off" | "running" | "paused" | "stopped" | "ready" | "waiting";
234
+ indexed: number;
235
+ total: number;
236
+ };
224
237
  storage_versions: {
225
238
  /**
226
239
  * Persisted schema version of context.db (MAX of schema_migrations).
@@ -239,12 +252,127 @@ export interface EmbedDetail {
239
252
  enabled: boolean;
240
253
  model: string;
241
254
  provider: string;
255
+ synapseDescriptor?: SynapseLaneDescriptor;
242
256
  session: { embedded: number; total: number };
243
257
  memories: { embedded: number; total: number };
244
258
  commits: { embedded: number; total: number; gitEnabled: boolean };
245
259
  statusText: string;
246
260
  }
247
261
 
262
+ export interface DebugProcessMemoryUsage {
263
+ rss: number;
264
+ heapTotal: number;
265
+ heapUsed: number;
266
+ external: number;
267
+ arrayBuffers: number;
268
+ }
269
+
270
+ export interface DebugSessionHolderCount {
271
+ sessionId: string;
272
+ lkgBytes: number;
273
+ taggerAssignments: number;
274
+ taggerToolAccounting: number;
275
+ wireRawMessages: number;
276
+ wireMessages: number;
277
+ wireContentSnapshots: number;
278
+ wireEstimatedBytes: number;
279
+ }
280
+
281
+ export interface DebugMemoryHolders {
282
+ lkgSlots: {
283
+ count: number;
284
+ totalBytes: number;
285
+ };
286
+ taggerCache: {
287
+ sessionCount: number;
288
+ assignmentEntries: number;
289
+ toolAccountingEntries: number;
290
+ loadSignatureEntries: number;
291
+ };
292
+ wireCache: {
293
+ snapshots: number;
294
+ rawContentSnapshots: number;
295
+ estimatedBytes: number;
296
+ };
297
+ compartmentMirrors: {
298
+ entries: number;
299
+ };
300
+ messageIndexQueue: {
301
+ queueLength: number;
302
+ reconciliationScheduled: number;
303
+ incrementalTimers: number;
304
+ pendingIncremental: number;
305
+ activeSessionLocks: number;
306
+ completedIncrementalKeys: number;
307
+ activeBufferMessages: number;
308
+ activeBufferBytes: number;
309
+ };
310
+ sessions: DebugSessionHolderCount[];
311
+ }
312
+
313
+ export interface DebugSqliteConnectionMemoryStats {
314
+ sequence: number;
315
+ filename: string;
316
+ readonly: boolean;
317
+ pageSize: number | null;
318
+ pageCount: number | null;
319
+ freelistCount: number | null;
320
+ cacheSize: number | null;
321
+ cacheSizeUnit: "pages" | "kib" | null;
322
+ cacheUpperBoundBytes: number | null;
323
+ mmapSizeBytes: number | null;
324
+ walFileBytes: number | null;
325
+ shmFileBytes: number | null;
326
+ fts5TableCount: number | null;
327
+ journalMode: string | null;
328
+ }
329
+
330
+ export interface DebugNativeMemoryUsage {
331
+ sqlite: {
332
+ connectionCount: number;
333
+ cacheUpperBoundBytes: number;
334
+ mmapUpperBoundBytes: number;
335
+ walFileBytes: number;
336
+ shmFileBytes: number;
337
+ sqliteStatusApi: "unavailable";
338
+ connections: DebugSqliteConnectionMemoryStats[];
339
+ };
340
+ tokenizer: {
341
+ loaded: boolean;
342
+ loadAttempted: boolean;
343
+ tableBytes: number | null;
344
+ tablePath: string | null;
345
+ };
346
+ localEmbedding: {
347
+ loaded: boolean;
348
+ providerCount: number;
349
+ models: string[];
350
+ runtimes: Array<"native" | "wasm">;
351
+ modelCacheBytes: number | null;
352
+ rssDeltaAtLoad: number;
353
+ externalDeltaAtLoad: number;
354
+ arrayBuffersDeltaAtLoad: number;
355
+ };
356
+ quickJs: {
357
+ loadAttempted: boolean;
358
+ loaded: boolean;
359
+ };
360
+ }
361
+
362
+ export interface DebugMemoryUsageResponse {
363
+ pid: number;
364
+ bunVersion: string;
365
+ memoryUsage: DebugProcessMemoryUsage;
366
+ native: DebugNativeMemoryUsage;
367
+ holders: DebugMemoryHolders;
368
+ }
369
+
370
+ export interface DebugHeapSnapshotResponse extends DebugMemoryUsageResponse {
371
+ path: string;
372
+ format: "jsc" | "v8";
373
+ snapshotVersion?: number;
374
+ }
375
+
248
376
  export interface RpcNotificationMessage {
249
377
  id: number;
250
378
  type: string;
@@ -6,7 +6,7 @@
6
6
  // huge sessions (10k+ messages) which is exactly when Magic Context shines.
7
7
  //
8
8
  // Background: the plugin only ever needs the latest assistant message of a
9
- // helper subagent (historian / dreamer / sidekick / key-files / user-memory)
9
+ // helper subagent (historian / dreamer / key-files / user-memory)
10
10
  // or a bounded tail of the active session (conflict-warning cleanup). Both
11
11
  // fit comfortably in `limit: 50` with massive headroom.
12
12
  //
@@ -0,0 +1,19 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+
5
+ // `sqlite.ts` is executed directly by Node in CI's `node:sqlite` smoke and by
6
+ // Pi/Desktop hosts. Node's type-stripping loader does not resolve extensionless
7
+ // relative imports, so a static import of any sibling module breaks that path
8
+ // while every Bun-run test stays green (2026-09-12: master CI red for three
9
+ // runs after a logging import landed here). Runtime dependencies must be
10
+ // injected (see registerSlowWriteReporter); only type-only imports may be relative.
11
+ describe("sqlite.ts import fence", () => {
12
+ test("has no runtime-relative imports", () => {
13
+ const source = readFileSync(join(import.meta.dir, "sqlite.ts"), "utf8");
14
+ const relativeRuntimeImports = source
15
+ .split("\n")
16
+ .filter((line) => /^import\s+(?!type\s)[^;]*from\s+["']\.\.?\//.test(line));
17
+ expect(relativeRuntimeImports).toEqual([]);
18
+ });
19
+ });
@@ -1,7 +1,33 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { loadSqliteModule, SqliteRuntimeUnavailableError } from "./sqlite";
2
+ import {
3
+ Database,
4
+ getSqliteMemoryStats,
5
+ loadSqliteModule,
6
+ SqliteRuntimeUnavailableError,
7
+ } from "./sqlite";
3
8
 
4
9
  describe("SQLite runtime selector", () => {
10
+ it("reports live connection PRAGMAs and removes closed handles", () => {
11
+ const before = getSqliteMemoryStats().connectionCount;
12
+ const db = new Database(":memory:");
13
+ try {
14
+ db.exec("PRAGMA cache_size=-1024");
15
+ db.exec("CREATE VIRTUAL TABLE probe_fts USING fts5(content)");
16
+ const during = getSqliteMemoryStats();
17
+ expect(during.connectionCount).toBe(before + 1);
18
+ expect(during.connections.at(-1)).toMatchObject({
19
+ filename: ":memory:",
20
+ cacheSize: -1024,
21
+ cacheSizeUnit: "kib",
22
+ cacheUpperBoundBytes: 1024 * 1024,
23
+ fts5TableCount: 1,
24
+ });
25
+ } finally {
26
+ db.close();
27
+ }
28
+ expect(getSqliteMemoryStats().connectionCount).toBe(before);
29
+ });
30
+
5
31
  it("wraps a missing node:sqlite module with the detected runtime and cause", async () => {
6
32
  const cause = Object.assign(new Error("No such built-in module: node:sqlite"), {
7
33
  code: "ERR_UNKNOWN_BUILTIN_MODULE",
@@ -39,12 +39,28 @@
39
39
  * `run()` → {changes,lastInsertRowid}) is identical and was verified directly.
40
40
  */
41
41
 
42
+ import { statSync } from "node:fs";
42
43
  // Type import only — runtime is loaded dynamically below. @types/better-sqlite3
43
44
  // has the richest definitions and is a structural superset of the API surface
44
45
  // we use, so calls typed against BetterSqlite3 work under bun:sqlite and
45
46
  // node:sqlite at runtime (both expose prepare/run/get/all/exec/close).
46
47
  import type BetterSqlite3 from "better-sqlite3";
47
48
 
49
+ /**
50
+ * Slow-write reporting is injected rather than imported: this module is also
51
+ * executed directly by Node (the `node:sqlite` smoke in CI, Pi, Desktop), and
52
+ * Node's type-stripping loader does not resolve extensionless imports, so any
53
+ * static import of the plugin's logging chain here breaks that path. The
54
+ * storage bootstrap registers the real reporter; until then slow privileged
55
+ * writes are simply not logged.
56
+ */
57
+ type SlowWriteReporter = (site: string, transactionStartedAt: number) => void;
58
+ let reportSlowPrivilegedWrite: SlowWriteReporter | undefined;
59
+
60
+ export function registerSlowWriteReporter(reporter: SlowWriteReporter): void {
61
+ reportSlowPrivilegedWrite = reporter;
62
+ }
63
+
48
64
  export type SqliteRuntime = "Bun" | "Node.js";
49
65
 
50
66
  type SqliteModule = {
@@ -158,6 +174,88 @@ const DatabaseImpl: typeof BetterSqlite3 = isBun
158
174
  ? (sqliteModule.Database as typeof BetterSqlite3)
159
175
  : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
160
176
 
177
+ interface TrackedSqliteConnection {
178
+ sequence: number;
179
+ filename: string;
180
+ readonly: boolean;
181
+ reference: WeakRef<BetterSqlite3.Database>;
182
+ }
183
+
184
+ export interface SqliteConnectionMemoryStats {
185
+ sequence: number;
186
+ filename: string;
187
+ readonly: boolean;
188
+ pageSize: number | null;
189
+ pageCount: number | null;
190
+ freelistCount: number | null;
191
+ cacheSize: number | null;
192
+ cacheSizeUnit: "pages" | "kib" | null;
193
+ cacheUpperBoundBytes: number | null;
194
+ mmapSizeBytes: number | null;
195
+ walFileBytes: number | null;
196
+ shmFileBytes: number | null;
197
+ fts5TableCount: number | null;
198
+ journalMode: string | null;
199
+ }
200
+
201
+ export interface SqliteMemoryStats {
202
+ connectionCount: number;
203
+ cacheUpperBoundBytes: number;
204
+ mmapUpperBoundBytes: number;
205
+ walFileBytes: number;
206
+ shmFileBytes: number;
207
+ sqliteStatusApi: "unavailable";
208
+ connections: SqliteConnectionMemoryStats[];
209
+ }
210
+
211
+ const trackedSqliteConnections = new Map<number, TrackedSqliteConnection>();
212
+ let nextSqliteConnectionSequence = 1;
213
+
214
+ function trackSqliteConnection(
215
+ db: BetterSqlite3.Database,
216
+ filename: unknown,
217
+ options: unknown,
218
+ ): BetterSqlite3.Database {
219
+ const originalClose = db.close.bind(db) as (...args: unknown[]) => unknown;
220
+ const sequence = nextSqliteConnectionSequence++;
221
+ const metadata = {
222
+ sequence,
223
+ filename:
224
+ typeof filename === "string"
225
+ ? filename
226
+ : Buffer.isBuffer(filename)
227
+ ? "<buffer>"
228
+ : ":memory:",
229
+ readonly:
230
+ Boolean(options) &&
231
+ typeof options === "object" &&
232
+ ((options as { readonly?: unknown }).readonly === true ||
233
+ (options as { readOnly?: unknown }).readOnly === true),
234
+ };
235
+ Object.defineProperty(db, "close", {
236
+ configurable: true,
237
+ value: (...args: unknown[]) => {
238
+ try {
239
+ return originalClose(...args);
240
+ } finally {
241
+ trackedSqliteConnections.delete(sequence);
242
+ }
243
+ },
244
+ });
245
+ trackedSqliteConnections.set(sequence, {
246
+ ...metadata,
247
+ reference: new WeakRef(db),
248
+ });
249
+ return db;
250
+ }
251
+
252
+ const TrackedDatabase = new Proxy(DatabaseImpl, {
253
+ construct(target, args) {
254
+ const db = Reflect.construct(target, args, target) as BetterSqlite3.Database;
255
+ return trackSqliteConnection(db, args[0], args[1]);
256
+ },
257
+ }) as typeof BetterSqlite3;
258
+
161
259
  /**
162
260
  * Wrap node:sqlite's `DatabaseSync` so it presents the better-sqlite3/bun
163
261
  * surface the rest of the codebase calls:
@@ -259,7 +357,108 @@ function buildNodeSqliteDatabaseClass(DatabaseSync: any): typeof BetterSqlite3 {
259
357
  return NodeSqliteDatabase as unknown as typeof BetterSqlite3;
260
358
  }
261
359
 
262
- export const Database: typeof BetterSqlite3 = DatabaseImpl;
360
+ export const Database: typeof BetterSqlite3 = TrackedDatabase;
361
+
362
+ function pragmaValue(db: BetterSqlite3.Database, name: string): unknown {
363
+ const row = db.prepare(`PRAGMA ${name}`).get() as Record<string, unknown> | undefined;
364
+ if (!row) return undefined;
365
+ return row[name] ?? Object.values(row)[0];
366
+ }
367
+
368
+ function pragmaNumber(db: BetterSqlite3.Database, name: string): number | null {
369
+ try {
370
+ const value = pragmaValue(db, name);
371
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
372
+ } catch {
373
+ return null;
374
+ }
375
+ }
376
+
377
+ function pragmaString(db: BetterSqlite3.Database, name: string): string | null {
378
+ try {
379
+ const value = pragmaValue(db, name);
380
+ return typeof value === "string" ? value : null;
381
+ } catch {
382
+ return null;
383
+ }
384
+ }
385
+
386
+ function sqliteSidecarBytes(filename: string, suffix: "-wal" | "-shm"): number | null {
387
+ if (filename === ":memory:" || filename === "<buffer>") return 0;
388
+ try {
389
+ return statSync(`${filename}${suffix}`).size;
390
+ } catch (error) {
391
+ return (error as NodeJS.ErrnoException).code === "ENOENT" ? 0 : null;
392
+ }
393
+ }
394
+
395
+ function fts5TableCount(db: BetterSqlite3.Database): number | null {
396
+ try {
397
+ const row = db
398
+ .prepare(
399
+ "SELECT COUNT(*) AS count FROM sqlite_master WHERE type = 'table' AND sql LIKE '%USING fts5%'",
400
+ )
401
+ .get() as { count?: unknown } | undefined;
402
+ return typeof row?.count === "number" ? row.count : null;
403
+ } catch {
404
+ return null;
405
+ }
406
+ }
407
+
408
+ /**
409
+ * Read the SQLite memory bounds that Bun/node:sqlite expose without native FFI.
410
+ * SQLite's sqlite3_status()/sqlite3_db_status() counters are not surfaced by
411
+ * either runtime, so cache and mmap values are configured upper bounds rather
412
+ * than resident-byte measurements.
413
+ */
414
+ export function getSqliteMemoryStats(): SqliteMemoryStats {
415
+ const connections: SqliteConnectionMemoryStats[] = [];
416
+ for (const [sequence, tracked] of trackedSqliteConnections) {
417
+ const db = tracked.reference.deref();
418
+ if (!db) {
419
+ trackedSqliteConnections.delete(sequence);
420
+ continue;
421
+ }
422
+ const pageSize = pragmaNumber(db, "page_size");
423
+ const cacheSize = pragmaNumber(db, "cache_size");
424
+ const cacheSizeUnit = cacheSize === null ? null : cacheSize < 0 ? "kib" : "pages";
425
+ const cacheUpperBoundBytes =
426
+ cacheSize === null
427
+ ? null
428
+ : cacheSize < 0
429
+ ? Math.abs(cacheSize) * 1024
430
+ : pageSize === null
431
+ ? null
432
+ : cacheSize * pageSize;
433
+ connections.push({
434
+ sequence: tracked.sequence,
435
+ filename: tracked.filename,
436
+ readonly: tracked.readonly,
437
+ pageSize,
438
+ pageCount: pragmaNumber(db, "page_count"),
439
+ freelistCount: pragmaNumber(db, "freelist_count"),
440
+ cacheSize,
441
+ cacheSizeUnit,
442
+ cacheUpperBoundBytes,
443
+ mmapSizeBytes: pragmaNumber(db, "mmap_size"),
444
+ walFileBytes: sqliteSidecarBytes(tracked.filename, "-wal"),
445
+ shmFileBytes: sqliteSidecarBytes(tracked.filename, "-shm"),
446
+ fts5TableCount: fts5TableCount(db),
447
+ journalMode: pragmaString(db, "journal_mode"),
448
+ });
449
+ }
450
+ const sumKnown = (select: (connection: SqliteConnectionMemoryStats) => number | null): number =>
451
+ connections.reduce((sum, connection) => sum + (select(connection) ?? 0), 0);
452
+ return {
453
+ connectionCount: connections.length,
454
+ cacheUpperBoundBytes: sumKnown((connection) => connection.cacheUpperBoundBytes),
455
+ mmapUpperBoundBytes: sumKnown((connection) => connection.mmapSizeBytes),
456
+ walFileBytes: sumKnown((connection) => connection.walFileBytes),
457
+ shmFileBytes: sumKnown((connection) => connection.shmFileBytes),
458
+ sqliteStatusApi: "unavailable",
459
+ connections,
460
+ };
461
+ }
263
462
 
264
463
  /** Instance type alias used by helpers and storage modules. */
265
464
  export type Database = BetterSqlite3.Database;
@@ -298,6 +497,7 @@ export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
298
497
  const previousDepth = privilegeDepth.get(db) ?? 0;
299
498
  const nested = isInTransaction(db);
300
499
  const savepoint = "mc_privilege_scope";
500
+ const transactionStartedAt = nested ? undefined : performance.now();
301
501
  if (nested) {
302
502
  db.exec(`SAVEPOINT ${savepoint}`);
303
503
  } else {
@@ -316,6 +516,9 @@ export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
316
516
  db.exec(`RELEASE ${savepoint}`);
317
517
  } else {
318
518
  db.exec("COMMIT");
519
+ if (transactionStartedAt !== undefined) {
520
+ reportSlowPrivilegedWrite?.("privileged_writer", transactionStartedAt);
521
+ }
319
522
  }
320
523
  if (previousDepth > 0) privilegeDepth.set(db, previousDepth);
321
524
  else privilegeDepth.delete(db);