@cortexkit/opencode-magic-context 0.41.4 → 0.42.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 (328) 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 +17 -0
  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 +23 -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 +7 -0
  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/task-executor.d.ts.map +1 -1
  37. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +4 -0
  38. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  39. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  40. package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
  41. package/dist/features/magic-context/git-commits/sweep-coordinator.d.ts.map +1 -1
  42. package/dist/features/magic-context/index.d.ts +0 -1
  43. package/dist/features/magic-context/index.d.ts.map +1 -1
  44. package/dist/features/magic-context/memory/embedding-local.d.ts +13 -0
  45. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  46. package/dist/features/magic-context/memory/embedding-synapse.d.ts +43 -10
  47. package/dist/features/magic-context/memory/embedding-synapse.d.ts.map +1 -1
  48. package/dist/features/magic-context/memory/embedding.d.ts +1 -1
  49. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  50. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  51. package/dist/features/magic-context/memory/project-identity.d.ts +1 -0
  52. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  53. package/dist/features/magic-context/memory/promotion.d.ts +7 -1
  54. package/dist/features/magic-context/memory/promotion.d.ts.map +1 -1
  55. package/dist/features/magic-context/merged-reasoning-decisions.d.ts +6 -0
  56. package/dist/features/magic-context/merged-reasoning-decisions.d.ts.map +1 -0
  57. package/dist/features/magic-context/message-fts-rowid-map.d.ts.map +1 -1
  58. package/dist/features/magic-context/message-index-async.d.ts +12 -0
  59. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  60. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  61. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  62. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  63. package/dist/features/magic-context/mural/render-trigger.d.ts +6 -0
  64. package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
  65. package/dist/features/magic-context/no-content-compartment.d.ts +12 -0
  66. package/dist/features/magic-context/no-content-compartment.d.ts.map +1 -0
  67. package/dist/features/magic-context/pi-content-decisions.d.ts +9 -0
  68. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -0
  69. package/dist/features/magic-context/project-docs-hash.d.ts +4 -0
  70. package/dist/features/magic-context/project-docs-hash.d.ts.map +1 -1
  71. package/dist/features/magic-context/project-embedding-registry.d.ts +13 -4
  72. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  73. package/dist/features/magic-context/protection-window.d.ts +79 -0
  74. package/dist/features/magic-context/protection-window.d.ts.map +1 -0
  75. package/dist/features/magic-context/search.d.ts.map +1 -1
  76. package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
  77. package/dist/features/magic-context/shadow-backfill-state.d.ts +26 -0
  78. package/dist/features/magic-context/shadow-backfill-state.d.ts.map +1 -0
  79. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  80. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +4 -0
  81. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
  82. package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
  83. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  84. package/dist/features/magic-context/storage-db.d.ts +1 -1
  85. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  86. package/dist/features/magic-context/storage-embedding-measurements.d.ts +2 -2
  87. package/dist/features/magic-context/storage-embedding-measurements.d.ts.map +1 -1
  88. package/dist/features/magic-context/storage-historian-runs.d.ts +4 -0
  89. package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
  90. package/dist/features/magic-context/storage-memory-mutation-log.d.ts +1 -0
  91. package/dist/features/magic-context/storage-memory-mutation-log.d.ts.map +1 -1
  92. package/dist/features/magic-context/storage-meta-persisted.d.ts +79 -13
  93. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  94. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  95. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  96. package/dist/features/magic-context/storage-native-replay.d.ts +29 -0
  97. package/dist/features/magic-context/storage-native-replay.d.ts.map +1 -0
  98. package/dist/features/magic-context/storage-notes.d.ts +6 -0
  99. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  100. package/dist/features/magic-context/storage-replay-document.d.ts +33 -0
  101. package/dist/features/magic-context/storage-replay-document.d.ts.map +1 -0
  102. package/dist/features/magic-context/storage-subagent-invocations.d.ts +1 -1
  103. package/dist/features/magic-context/storage-subagent-invocations.d.ts.map +1 -1
  104. package/dist/features/magic-context/storage-tags.d.ts +19 -11
  105. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  106. package/dist/features/magic-context/storage.d.ts +3 -3
  107. package/dist/features/magic-context/storage.d.ts.map +1 -1
  108. package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
  109. package/dist/features/magic-context/tagger.d.ts +13 -0
  110. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  111. package/dist/features/magic-context/tool-owner-backfill.d.ts.map +1 -1
  112. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  113. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  114. package/dist/features/magic-context/workspaces.d.ts.map +1 -1
  115. package/dist/hooks/magic-context/apply-operations.d.ts +11 -5
  116. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  117. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  118. package/dist/hooks/magic-context/cache-busting-signals.d.ts +9 -1
  119. package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
  120. package/dist/hooks/magic-context/caveman-cleanup.d.ts +1 -1
  121. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
  122. package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
  123. package/dist/hooks/magic-context/child-session-spawn.d.ts +3 -3
  124. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
  125. package/dist/hooks/magic-context/command-handler.d.ts +1 -10
  126. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  127. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  128. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +10 -21
  129. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts.map +1 -1
  130. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  131. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  132. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +26 -2
  133. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
  134. package/dist/hooks/magic-context/decay-render.d.ts.map +1 -1
  135. package/dist/hooks/magic-context/dropped-input-guard.d.ts +9 -0
  136. package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -0
  137. package/dist/hooks/magic-context/emergency-drop.d.ts +6 -1
  138. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  139. package/dist/hooks/magic-context/event-handler.d.ts +0 -1
  140. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  141. package/dist/hooks/magic-context/event-payloads.d.ts +7 -6
  142. package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
  143. package/dist/hooks/magic-context/event-resolvers.d.ts +1 -1
  144. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  145. package/dist/hooks/magic-context/execute-status.d.ts +1 -1
  146. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  147. package/dist/hooks/magic-context/format-embed-status.d.ts.map +1 -1
  148. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +7 -1
  149. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  150. package/dist/hooks/magic-context/hook-handlers.d.ts +3 -1
  151. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  152. package/dist/hooks/magic-context/hook.d.ts +13 -4
  153. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  154. package/dist/hooks/magic-context/inject-compartments.d.ts +14 -1
  155. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  156. package/dist/hooks/magic-context/live-session-state.d.ts +1 -1
  157. package/dist/hooks/magic-context/lkg-slot.d.ts +34 -0
  158. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  159. package/dist/hooks/magic-context/module-state-sync-timing.d.ts +21 -0
  160. package/dist/hooks/magic-context/module-state-sync-timing.d.ts.map +1 -0
  161. package/dist/hooks/magic-context/module-state-sync.d.ts +21 -7
  162. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  163. package/dist/hooks/magic-context/module-transport.d.ts +12 -0
  164. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  165. package/dist/hooks/magic-context/module-wire.d.ts +8 -0
  166. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  167. package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
  168. package/dist/hooks/magic-context/persist-filtered-noise.d.ts +5 -0
  169. package/dist/hooks/magic-context/persist-filtered-noise.d.ts.map +1 -0
  170. package/dist/hooks/magic-context/protected-tail-boundary.d.ts +6 -0
  171. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  172. package/dist/hooks/magic-context/read-session-chunk.d.ts +18 -18
  173. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  174. package/dist/hooks/magic-context/read-session-db.d.ts +22 -12
  175. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  176. package/dist/hooks/magic-context/read-session-formatting.d.ts +8 -0
  177. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  178. package/dist/hooks/magic-context/read-session-raw.d.ts +10 -1
  179. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  180. package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -1
  181. package/dist/hooks/magic-context/rust-mode-transform.d.ts +74 -9
  182. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  183. package/dist/hooks/magic-context/send-session-notification.d.ts +11 -10
  184. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  185. package/dist/hooks/magic-context/strip-content.d.ts +7 -0
  186. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  187. package/dist/hooks/magic-context/supersession-reclaim.d.ts +13 -0
  188. package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
  189. package/dist/hooks/magic-context/system-prompt-hash.d.ts +2 -3
  190. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  191. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +8 -3
  192. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  193. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  194. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  195. package/dist/hooks/magic-context/transform-context-state.d.ts +7 -1
  196. package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
  197. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +11 -4
  198. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  199. package/dist/hooks/magic-context/transform.d.ts +7 -2
  200. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  201. package/dist/hooks/magic-context/upgrade-reminder.d.ts +7 -9
  202. package/dist/hooks/magic-context/upgrade-reminder.d.ts.map +1 -1
  203. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  204. package/dist/index-1974jvn3.js +783 -0
  205. package/dist/{index-4avmwfp5.js → index-36wd1d6k.js} +6 -29
  206. package/dist/{index-0y2mcg5y.js → index-c9hamh36.js} +18332 -16226
  207. package/dist/{index-fz104x1j.js → index-jmtjh2d3.js} +3 -3
  208. package/dist/{index-q264erdp.js → index-nqgjwfzn.js} +70 -38
  209. package/dist/{index-mjv9je4e.js → index-xdtge3y2.js} +45 -7
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +6199 -5088
  212. package/dist/plugin/conflict-warning-hook.d.ts +5 -6
  213. package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
  214. package/dist/plugin/dream-timer.d.ts +1 -0
  215. package/dist/plugin/dream-timer.d.ts.map +1 -1
  216. package/dist/plugin/embedding-routing.d.ts +4 -1
  217. package/dist/plugin/embedding-routing.d.ts.map +1 -1
  218. package/dist/plugin/hooks/create-session-hooks.d.ts +16 -2
  219. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  220. package/dist/plugin/rpc-handlers.d.ts +31 -1
  221. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  222. package/dist/plugin/rust-tool-backends.d.ts +1 -0
  223. package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
  224. package/dist/plugin/tool-registry.d.ts.map +1 -1
  225. package/dist/{recomp-orchestrator-q98r6rga.js → recomp-orchestrator-3atsasjy.js} +5 -5
  226. package/dist/{send-session-notification-hdh02wy9.js → send-session-notification-1qeqkswb.js} +6 -4
  227. package/dist/shared/child-session-teardown.d.ts +34 -0
  228. package/dist/shared/child-session-teardown.d.ts.map +1 -0
  229. package/dist/shared/keep-subagents.d.ts +1 -1
  230. package/dist/shared/keep-subagents.d.ts.map +1 -1
  231. package/dist/shared/model-suggestion-retry.d.ts +1 -1
  232. package/dist/shared/opencode-db-path.d.ts +24 -0
  233. package/dist/shared/opencode-db-path.d.ts.map +1 -0
  234. package/dist/shared/prompt-surface-runtime.d.ts +10 -5
  235. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  236. package/dist/shared/resolve-fallbacks.d.ts +1 -1
  237. package/dist/shared/rpc-types.d.ts +111 -0
  238. package/dist/shared/rpc-types.d.ts.map +1 -1
  239. package/dist/shared/sqlite.d.ts +42 -0
  240. package/dist/shared/sqlite.d.ts.map +1 -1
  241. package/dist/shared/status-detail-text.d.ts.map +1 -1
  242. package/dist/shared/subagent-runner.d.ts +17 -10
  243. package/dist/shared/subagent-runner.d.ts.map +1 -1
  244. package/dist/shared/tag-transcript.d.ts.map +1 -1
  245. package/dist/shared/transcript.d.ts +6 -0
  246. package/dist/shared/transcript.d.ts.map +1 -1
  247. package/dist/shared/window-geometry.d.ts +23 -0
  248. package/dist/shared/window-geometry.d.ts.map +1 -1
  249. package/dist/shared/write-transaction-timing.d.ts +1 -1
  250. package/dist/shared/write-transaction-timing.d.ts.map +1 -1
  251. package/dist/{storage-meta-session-dvwfw778.js → storage-meta-session-e6g0mmec.js} +2 -2
  252. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  253. package/dist/tools/ctx-memory/verification-recording.d.ts.map +1 -1
  254. package/dist/tools/ctx-note/constants.d.ts +1 -1
  255. package/dist/tools/ctx-note/constants.d.ts.map +1 -1
  256. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  257. package/dist/tools/ctx-note/types.d.ts +1 -0
  258. package/dist/tools/ctx-note/types.d.ts.map +1 -1
  259. package/dist/tools/ctx-reduce/tools.d.ts +10 -1
  260. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  261. package/dist/tools/ctx-search/constants.d.ts +1 -1
  262. package/dist/tools/ctx-search/constants.d.ts.map +1 -1
  263. package/dist/tools/light-descriptions.d.ts +2 -2
  264. package/dist/tools/light-descriptions.d.ts.map +1 -1
  265. package/package.json +2 -3
  266. package/src/agents/hidden-agent-registrations.ts +3 -15
  267. package/src/agents/magic-context-prompt.test.ts +7 -5
  268. package/src/agents/magic-context-prompt.ts +22 -30
  269. package/src/agents/permissions.test.ts +1 -42
  270. package/src/agents/permissions.ts +1 -24
  271. package/src/config/agent-disable.ts +5 -22
  272. package/src/config/index.test.ts +126 -15
  273. package/src/config/index.ts +41 -6
  274. package/src/config/latch-permanence-guard.test.ts +4 -0
  275. package/src/config/migrate-config-location.test.ts +39 -6
  276. package/src/config/migrate-config-location.ts +18 -31
  277. package/src/config/profiles.ts +1 -1
  278. package/src/config/project-security.hostile-matrix.test.ts +0 -8
  279. package/src/config/project-security.test.ts +11 -22
  280. package/src/config/project-security.ts +103 -9
  281. package/src/config/protected-tokens.test.ts +235 -0
  282. package/src/config/removed-agent-config.ts +45 -0
  283. package/src/config/removed-agent-source-fence.test.ts +56 -0
  284. package/src/config/schema/magic-context.test.ts +21 -42
  285. package/src/config/schema/magic-context.ts +46 -37
  286. package/src/shared/child-session-teardown.test.ts +218 -0
  287. package/src/shared/child-session-teardown.ts +66 -0
  288. package/src/shared/keep-subagents.ts +9 -14
  289. package/src/shared/model-suggestion-retry.ts +1 -1
  290. package/src/shared/opencode-db-path.test.ts +196 -0
  291. package/src/shared/opencode-db-path.ts +215 -0
  292. package/src/shared/prompt-surface-a1-golden.md +50 -35
  293. package/src/shared/prompt-surface-runtime.test.ts +28 -0
  294. package/src/shared/prompt-surface-runtime.ts +22 -5
  295. package/src/shared/resolve-fallbacks.ts +1 -1
  296. package/src/shared/rpc-types.ts +118 -0
  297. package/src/shared/session-messages-bounded.test.ts +1 -1
  298. package/src/shared/sqlite-import-fence.test.ts +19 -0
  299. package/src/shared/sqlite.test.ts +27 -1
  300. package/src/shared/sqlite.ts +204 -1
  301. package/src/shared/status-detail-text.test.ts +6 -3
  302. package/src/shared/status-detail-text.ts +15 -0
  303. package/src/shared/subagent-runner.ts +17 -10
  304. package/src/shared/tag-transcript.ts +33 -21
  305. package/src/shared/transcript.ts +7 -0
  306. package/src/shared/window-geometry.test.ts +44 -0
  307. package/src/shared/window-geometry.ts +89 -11
  308. package/src/shared/write-transaction-attribution.test.ts +241 -0
  309. package/src/shared/write-transaction-timing.ts +2 -1
  310. package/src/tui/index.tsx +3 -3
  311. package/src/tui/slots/sidebar-content.tsx +12 -7
  312. package/src/tui-compiled/index.tsx +3 -3
  313. package/src/tui-compiled/slots/sidebar-content.tsx +301 -305
  314. package/dist/agents/sidekick.d.ts +0 -2
  315. package/dist/agents/sidekick.d.ts.map +0 -1
  316. package/dist/features/magic-context/defaults.d.ts +0 -2
  317. package/dist/features/magic-context/defaults.d.ts.map +0 -1
  318. package/dist/features/magic-context/sidekick/agent.d.ts +0 -14
  319. package/dist/features/magic-context/sidekick/agent.d.ts.map +0 -1
  320. package/dist/features/magic-context/sidekick/core.d.ts +0 -38
  321. package/dist/features/magic-context/sidekick/core.d.ts.map +0 -1
  322. package/dist/features/magic-context/sidekick/index.d.ts +0 -3
  323. package/dist/features/magic-context/sidekick/index.d.ts.map +0 -1
  324. package/dist/hooks/magic-context/boundary-execution.d.ts +0 -27
  325. package/dist/hooks/magic-context/boundary-execution.d.ts.map +0 -1
  326. package/dist/index-raatkvw5.js +0 -360
  327. package/src/agents/sidekick.ts +0 -1
  328. package/src/features/magic-context/defaults.ts +0 -1
@@ -10,7 +10,12 @@ export const PROMPT_WALL_MARGIN = 4_096;
10
10
  export const PI_OUTPUT_FLOOR = 4_096;
11
11
  export const OPENCODE_OUTPUT_CAP = 32_000;
12
12
 
13
- const MIN_PLAUSIBLE_CONTEXT_LIMIT = 1_024;
13
+ /**
14
+ * Smallest context window any served model can plausibly have. Reported or
15
+ * inferred limits below this are placeholders (0, 1) or corrupt state, never a
16
+ * real window, so every denominator check shares this one floor.
17
+ */
18
+ export const MIN_PLAUSIBLE_CONTEXT_LIMIT = 1_024;
14
19
  const OUTPUT_RESERVE_CAP_RATIO = 0.25;
15
20
 
16
21
  export type WindowGeometry = "shared_upfront" | "shared_truncating" | "separate";
@@ -70,11 +75,15 @@ export interface ResolvedWindowOverlayFacts {
70
75
  facts: Record<string, WindowOverlayFact>;
71
76
  }
72
77
 
78
+ export type WindowLimitSource = "catalog" | "overlay" | "provider" | "detected";
79
+
73
80
  export interface WindowDerivation {
74
81
  window: number;
75
82
  reserve: number;
76
83
  reserveSource: WindowReserveSource;
77
84
  geometry: WindowGeometry;
85
+ windowSource: WindowLimitSource;
86
+ absoluteWall: number;
78
87
  }
79
88
 
80
89
  export interface WindowGeometryResult {
@@ -446,20 +455,22 @@ export function deriveWindowGeometry(
446
455
  const catalogContext = isFinitePositive(catalogLimit?.context)
447
456
  ? catalogLimit.context
448
457
  : undefined;
458
+ const providerContext = isFinitePositive(providerLimit?.context)
459
+ ? providerLimit.context
460
+ : undefined;
449
461
  const advertised = numericOverlayFact(options.overlay, "window.advertised");
450
462
  const enforced = numericOverlayFact(options.overlay, "window.enforced");
451
- let softContext = mergePositive(
452
- enforced ?? advertised ?? catalogContext,
453
- providerLimit?.context,
454
- );
455
- let hardContext = mergePositive(enforced ?? softContext, providerLimit?.context);
456
- if (isFinitePositive(options.contextCap)) {
463
+ let softContext = mergePositive(enforced ?? advertised ?? catalogContext, providerContext);
464
+ let hardContext = mergePositive(enforced ?? softContext, providerContext);
465
+ const contextCap = isFinitePositive(options.contextCap) ? options.contextCap : undefined;
466
+ const hasContextCap = contextCap !== undefined;
467
+ if (contextCap !== undefined) {
457
468
  softContext = isFinitePositive(softContext)
458
- ? Math.min(softContext, options.contextCap)
459
- : options.contextCap;
469
+ ? Math.min(softContext, contextCap)
470
+ : contextCap;
460
471
  hardContext = isFinitePositive(hardContext)
461
- ? Math.min(hardContext, options.contextCap)
462
- : options.contextCap;
472
+ ? Math.min(hardContext, contextCap)
473
+ : contextCap;
463
474
  }
464
475
  const input = mergePositive(
465
476
  isFinitePositive(catalogLimit?.input) ? catalogLimit.input : undefined,
@@ -573,6 +584,13 @@ export function deriveWindowGeometry(
573
584
 
574
585
  const hardWindow = hardContext ?? softContext ?? input;
575
586
  if (!isFinitePositive(hardWindow)) return undefined;
587
+ const windowSource: WindowLimitSource = hasContextCap
588
+ ? "detected"
589
+ : providerContext !== undefined
590
+ ? "provider"
591
+ : enforced !== undefined || advertised !== undefined
592
+ ? "overlay"
593
+ : "catalog";
576
594
  let usableHard: number;
577
595
  if (geometry === "separate") {
578
596
  usableHard = hardWindow;
@@ -606,6 +624,66 @@ export function deriveWindowGeometry(
606
624
  reserve: Math.floor(Math.max(0, resolvedWindow - usableSoft)),
607
625
  reserveSource,
608
626
  geometry,
627
+ windowSource,
628
+ absoluteWall: Math.floor(hardWindow),
629
+ },
630
+ };
631
+ }
632
+
633
+ export interface ProvenInputFloorResult {
634
+ geometry: WindowGeometryResult;
635
+ refused?: { reading: number; absoluteWall: number };
636
+ }
637
+
638
+ export function hasTrustedAbsoluteWall(geometry: WindowGeometryResult): boolean {
639
+ return geometry.derivation.windowSource !== "catalog";
640
+ }
641
+
642
+ /**
643
+ * Successful requests can disprove static catalog metadata, but cannot
644
+ * disprove a provider, overlay, or observed-overflow wall. A reading beyond
645
+ * that wall is malformed usage accounting and must not enlarge the geometry.
646
+ */
647
+ export function applyProvenInputFloor(
648
+ geometry: WindowGeometryResult,
649
+ provenInputTokens: number | undefined,
650
+ ): ProvenInputFloorResult {
651
+ if (
652
+ !isFinitePositive(provenInputTokens) ||
653
+ provenInputTokens < MIN_PLAUSIBLE_CONTEXT_LIMIT ||
654
+ provenInputTokens <= geometry.usableSoft
655
+ ) {
656
+ return { geometry };
657
+ }
658
+ if (hasTrustedAbsoluteWall(geometry) && provenInputTokens > geometry.derivation.absoluteWall) {
659
+ return {
660
+ geometry,
661
+ refused: {
662
+ reading: provenInputTokens,
663
+ absoluteWall: geometry.derivation.absoluteWall,
664
+ },
665
+ };
666
+ }
667
+
668
+ const trustedAbsoluteWall = hasTrustedAbsoluteWall(geometry);
669
+ const window = trustedAbsoluteWall
670
+ ? geometry.derivation.window
671
+ : Math.max(geometry.derivation.window, provenInputTokens);
672
+ return {
673
+ geometry: {
674
+ ...geometry,
675
+ usableSoft: provenInputTokens,
676
+ usableHard: trustedAbsoluteWall
677
+ ? geometry.usableHard
678
+ : Math.max(geometry.usableHard, provenInputTokens),
679
+ derivation: {
680
+ ...geometry.derivation,
681
+ window,
682
+ reserve: Math.max(0, window - provenInputTokens),
683
+ absoluteWall: trustedAbsoluteWall
684
+ ? geometry.derivation.absoluteWall
685
+ : Math.max(geometry.derivation.absoluteWall, provenInputTokens),
686
+ },
609
687
  },
610
688
  };
611
689
  }
@@ -0,0 +1,241 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
+ import { mkdtempSync, readFileSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join, resolve } from "node:path";
5
+
6
+ const repoRoot = resolve(import.meta.dir, "../../../../");
7
+ const beginImmediate = /\b(?:[A-Za-z_$][\w$]*\.)?exec\("BEGIN IMMEDIATE"\)/g;
8
+
9
+ const fencedSources: Array<{ path: string; sites: string[] }> = [
10
+ {
11
+ path: "packages/plugin/src/features/magic-context/smart-notes/storage.ts",
12
+ sites: ["smart_note_commit"],
13
+ },
14
+ {
15
+ path: "packages/plugin/src/hooks/magic-context/inject-compartments.ts",
16
+ sites: ["opencode_materialize_cache", "opencode_soft_refresh_cache"],
17
+ },
18
+ {
19
+ path: "packages/plugin/src/features/magic-context/message-index.ts",
20
+ sites: [
21
+ "message_index_incremental",
22
+ "message_index_reconcile",
23
+ "message_index_orphan_sweep",
24
+ ],
25
+ },
26
+ {
27
+ path: "packages/plugin/src/features/magic-context/storage-meta-persisted.ts",
28
+ sites: [
29
+ "storage_meta_wrapup_expiry_cleanup",
30
+ "storage_meta_wrapup_acquire",
31
+ "storage_meta_wrapup_update",
32
+ "storage_meta_wrapup_release",
33
+ ],
34
+ },
35
+ {
36
+ path: "packages/plugin/src/features/magic-context/context-authority.ts",
37
+ sites: ["authority_marker_capture", "authority_capture_check"],
38
+ },
39
+ {
40
+ path: "packages/plugin/src/features/magic-context/compartment-storage.ts",
41
+ sites: ["compartment_state_replace", "recomp_staging_promote"],
42
+ },
43
+ {
44
+ path: "packages/plugin/src/features/magic-context/project-embedding-registry.ts",
45
+ sites: ["embedding_identity_record", "embedding_stale_gc"],
46
+ },
47
+ {
48
+ path: "packages/plugin/src/features/magic-context/workspaces.ts",
49
+ sites: ["workspace_epoch_bump", "workspace_epoch_bump"],
50
+ },
51
+ {
52
+ // The chokepoint cannot import the logging chain (Node executes it
53
+ // directly), so it reports through the injected reporter instead.
54
+ path: "packages/plugin/src/shared/sqlite.ts",
55
+ sites: ["privileged_writer"],
56
+ reporterCall: "reportSlowPrivilegedWrite?.(",
57
+ },
58
+ {
59
+ path: "packages/plugin/src/features/magic-context/git-commits/sweep-coordinator.ts",
60
+ sites: ["git_sweep_lease"],
61
+ },
62
+ {
63
+ path: "packages/plugin/src/features/magic-context/session-project-backfill.ts",
64
+ sites: ["session_project_backfill"],
65
+ },
66
+ {
67
+ path: "packages/plugin/src/tools/ctx-memory/verification-recording.ts",
68
+ sites: ["ctx_memory_mutation"],
69
+ },
70
+ {
71
+ path: "packages/plugin/src/features/magic-context/storage-clone.ts",
72
+ sites: ["storage_clone_copy"],
73
+ },
74
+ {
75
+ path: "packages/plugin/src/hooks/magic-context/compartment-runner-recomp.ts",
76
+ sites: ["historian-publish:recomp"],
77
+ },
78
+ {
79
+ path: "packages/plugin/src/hooks/magic-context/compartment-runner-incremental.ts",
80
+ sites: ["historian-publish"],
81
+ },
82
+ {
83
+ path: "packages/plugin/src/features/magic-context/dreamer/lease.ts",
84
+ sites: ["lease_dynamic_site"],
85
+ },
86
+ {
87
+ path: "packages/pi-plugin/src/inject-compartments-pi.ts",
88
+ sites: ["pi_materialize_cache", "pi_soft_refresh_cache"],
89
+ },
90
+ {
91
+ path: "packages/pi-plugin/src/pi-historian-runner.ts",
92
+ sites: ["pi_historian_publish"],
93
+ },
94
+ {
95
+ path: "packages/pi-plugin/src/context-handler.ts",
96
+ sites: ["pi_compaction_queue"],
97
+ },
98
+ ];
99
+
100
+ const nonBeginCoveredSites: Array<{ path: string; site: string }> = [
101
+ {
102
+ path: "packages/plugin/src/features/magic-context/message-index.ts",
103
+ site: "message_index_clear",
104
+ },
105
+ {
106
+ path: "packages/plugin/src/features/magic-context/message-fts-rowid-map.ts",
107
+ site: "message_fts_rowid_backfill",
108
+ },
109
+ {
110
+ path: "packages/plugin/src/hooks/magic-context/note-nudger.ts",
111
+ site: "note_nudge_trigger",
112
+ },
113
+ {
114
+ path: "packages/plugin/src/features/magic-context/user-memory/storage-user-memory.ts",
115
+ site: "user_memory_candidate_insert",
116
+ },
117
+ ];
118
+
119
+ let scenarioRoot: string | null = null;
120
+ let scenarioLogPath: string | null = null;
121
+
122
+ const newlyCoveredSites = [
123
+ "opencode_materialize_cache",
124
+ "opencode_soft_refresh_cache",
125
+ "message_index_incremental",
126
+ "message_index_reconcile",
127
+ "message_index_orphan_sweep",
128
+ "message_index_clear",
129
+ "message_fts_rowid_backfill",
130
+ "storage_meta_wrapup_expiry_cleanup",
131
+ "storage_meta_wrapup_acquire",
132
+ "storage_meta_wrapup_update",
133
+ "storage_meta_wrapup_release",
134
+ "authority_marker_capture",
135
+ "authority_capture_check",
136
+ "compartment_state_replace",
137
+ "recomp_staging_promote",
138
+ "embedding_identity_record",
139
+ "embedding_stale_gc",
140
+ "workspace_epoch_bump",
141
+ "privileged_writer",
142
+ "git_sweep_lease",
143
+ "session_project_backfill",
144
+ "ctx_memory_mutation",
145
+ "storage_clone_copy",
146
+ "smart_note_commit",
147
+ "pi_materialize_cache",
148
+ "pi_soft_refresh_cache",
149
+ "pi_historian_publish",
150
+ "pi_compaction_queue",
151
+ "note_nudge_trigger",
152
+ "user_memory_candidate_insert",
153
+ ] as const;
154
+
155
+ function sourceFor(relativePath: string): string {
156
+ return readFileSync(resolve(repoRoot, relativePath), "utf8");
157
+ }
158
+
159
+ function assertCoveredBeginImmediate(
160
+ source: string,
161
+ sites: string[],
162
+ reporterCall = "logSlowWriteTransaction(",
163
+ ): void {
164
+ const matches = [...source.matchAll(beginImmediate)];
165
+ expect(matches).toHaveLength(sites.length);
166
+ for (let index = 0; index < matches.length; index += 1) {
167
+ const match = matches[index];
168
+ const nextBegin = matches[index + 1]?.index ?? source.length;
169
+ const transactionRegion = source.slice(match.index, nextBegin);
170
+ expect(transactionRegion).toContain(reporterCall);
171
+ if (sites[index] === "lease_dynamic_site") {
172
+ expect(transactionRegion).toContain("logSlowWriteTransaction(site");
173
+ } else {
174
+ expect(transactionRegion).toContain(`"${sites[index]}"`);
175
+ }
176
+ }
177
+ }
178
+
179
+ describe("write transaction attribution fences", () => {
180
+ beforeAll(async () => {
181
+ scenarioRoot = mkdtempSync(join(tmpdir(), "magic-context-write-attribution-"));
182
+ scenarioLogPath = join(scenarioRoot, "transactions.log");
183
+ const scenario = `
184
+ const timing = await import(${JSON.stringify(new URL("./write-transaction-timing.ts", import.meta.url).href)});
185
+ const logger = await import(${JSON.stringify(new URL("./logger.ts", import.meta.url).href)});
186
+ for (const site of ${JSON.stringify(newlyCoveredSites)}) {
187
+ timing.logSlowWriteTransaction(site, 1_000, 1_000, 2_100);
188
+ timing.logSlowWriteTransaction(site, 2_000, 1_000, 2_100);
189
+ }
190
+ logger.flushLogger();
191
+ `;
192
+ const child = Bun.spawn({
193
+ cmd: ["bun", "--eval", scenario],
194
+ cwd: import.meta.dir,
195
+ env: {
196
+ ...process.env,
197
+ NODE_ENV: "production",
198
+ MAGIC_CONTEXT_LOG_PATH: scenarioLogPath,
199
+ },
200
+ stdout: "pipe",
201
+ stderr: "pipe",
202
+ });
203
+ const [exitCode, stderr] = await Promise.all([
204
+ child.exited,
205
+ new Response(child.stderr).text(),
206
+ ]);
207
+ expect(exitCode, stderr).toBe(0);
208
+ });
209
+
210
+ afterAll(() => {
211
+ if (scenarioRoot) rmSync(scenarioRoot, { recursive: true, force: true });
212
+ scenarioRoot = null;
213
+ scenarioLogPath = null;
214
+ });
215
+
216
+ test("lists every BEGIN IMMEDIATE writer and requires a covered site", () => {
217
+ for (const fencedSource of fencedSources) {
218
+ assertCoveredBeginImmediate(
219
+ sourceFor(fencedSource.path),
220
+ fencedSource.sites,
221
+ "reporterCall" in fencedSource ? fencedSource.reporterCall : undefined,
222
+ );
223
+ }
224
+ for (const coveredSite of nonBeginCoveredSites) {
225
+ expect(sourceFor(coveredSite.path)).toContain(
226
+ `logSlowWriteTransaction("${coveredSite.site}"`,
227
+ );
228
+ }
229
+ });
230
+
231
+ for (const site of newlyCoveredSites) {
232
+ test(`logs a slow and suppresses a sub-threshold transaction at site=${site}`, () => {
233
+ if (!scenarioLogPath) throw new Error("timing scenario did not start");
234
+ const lines = readFileSync(scenarioLogPath, "utf8")
235
+ .split("\n")
236
+ .filter((line) => line.includes(`site=${site}`));
237
+ expect(lines).toHaveLength(1);
238
+ expect(lines[0]).toContain("held=1100.0ms");
239
+ });
240
+ }
241
+ });
@@ -14,9 +14,10 @@ export function logSlowWriteTransaction(
14
14
  site: string,
15
15
  startedAt: number,
16
16
  thresholdMs = SLOW_WRITE_TRANSACTION_THRESHOLD_MS,
17
+ completedAtMs = performance.now(),
17
18
  ): void {
18
19
  try {
19
- const durationMs = performance.now() - startedAt;
20
+ const durationMs = completedAtMs - startedAt;
20
21
  if (durationMs < thresholdMs) return;
21
22
  log(`[magic-context] slow write transaction: site=${site} held=${durationMs.toFixed(1)}ms`);
22
23
  } catch {
package/src/tui/index.tsx CHANGED
@@ -206,7 +206,7 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
206
206
  segs.push({ label: "User Profile", tokens: d.profileTokens, color: COLORS.profile })
207
207
 
208
208
  if (d.conversationTokens > 0)
209
- segs.push({ label: "Conversation*", tokens: d.conversationTokens, color: COLORS.conversation })
209
+ segs.push({ label: "Conversation", tokens: d.conversationTokens, color: COLORS.conversation })
210
210
  if (d.toolCallTokens > 0)
211
211
  segs.push({ label: "Tool Calls", tokens: d.toolCallTokens, color: COLORS.toolCalls })
212
212
  if (d.toolDefinitionTokens > 0)
@@ -279,7 +279,7 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
279
279
  </box>
280
280
  )
281
281
  })}
282
- <text fg={t().textMuted}>* Conversation includes Reasoning; hygiene excludes it</text>
282
+ <text fg={t().textMuted}>Conversation includes reasoning; hygiene excludes it</text>
283
283
  {s().tailHygiene !== undefined && (
284
284
  <R
285
285
  t={t()}
@@ -515,7 +515,7 @@ async function showRecompDialog(api: TuiPluginApi, targetSessionId = getSessionI
515
515
  ? "This session has no compartments yet — recomp will build them from raw history."
516
516
  : `You have ${count} compartments.`,
517
517
  "",
518
- "Recomp will regenerate all compartments and facts from raw history.",
518
+ "Recomp will rebuild the compressed history from raw history. Saved memories are not changed.",
519
519
  "This may take a long time and consume significant tokens.",
520
520
  "",
521
521
  "Proceed?",
@@ -5,7 +5,6 @@ import packageJson from "../../../package.json"
5
5
  import { badgeTextColor } from '../badge-contrast';
6
6
  import { loadSidebarSnapshot, type SidebarSnapshot } from "../data/context-db"
7
7
  import { formatThresholdPercent } from "../../shared/format-threshold"
8
- import { formatTailHygiene } from "../../shared/tail-hygiene-status"
9
8
  import { compactionOffSidebarRows, nativeCompactionContextLabel } from "../compaction-off"
10
9
  import {
11
10
  computeEffectiveOrder,
@@ -106,6 +105,16 @@ function compactTokens(value: number): string {
106
105
  return String(value)
107
106
  }
108
107
 
108
+ /**
109
+ * Sidebar form of the tail-hygiene reading: the reclaimable share and the
110
+ * two masses it is computed from, in the same compact token unit as the
111
+ * breakdown rows so the value fits beside its label at sidebar width. The
112
+ * long, unit-spelled form stays in the status dialog.
113
+ */
114
+ function hygieneValue(status: { severity: number; u: number; t: number }): string {
115
+ return `${(status.severity * 100).toFixed(1)}% · ${compactTokens(status.u)}/${compactTokens(status.t)}`
116
+ }
117
+
109
118
  function relativeTime(ms: number): string {
110
119
  const diff = Date.now() - ms
111
120
  if (diff < 60_000) return "just now"
@@ -240,7 +249,7 @@ const TokenBreakdown = (props: {
240
249
  key: "conv",
241
250
  tokens: s.conversationTokens,
242
251
  color: COLORS.conversation,
243
- label: "Conversation*",
252
+ label: "Conversation",
244
253
  })
245
254
 
246
255
  // Tool Calls = tool_use/tool_result/tool/tool-invocation parts in messages
@@ -321,7 +330,6 @@ const TokenBreakdown = (props: {
321
330
  </box>
322
331
  )
323
332
  })}
324
- <text fg={props.theme.textMuted}>* includes Reasoning; hygiene excludes it</text>
325
333
  </box>
326
334
  )}
327
335
  </box>
@@ -798,14 +806,11 @@ const SidebarContent = (props: {
798
806
  </box>
799
807
  )}
800
808
  <TokenBreakdown theme={props.theme} snapshot={s()!} collapsed={collapsed()} />
801
- {!collapsed() && (
802
- <text fg={props.theme.textMuted}>Conversation includes reasoning estimates; hygiene excludes reasoning.</text>
803
- )}
804
809
  {s()!.tailHygiene !== undefined && (
805
810
  <StatRow
806
811
  theme={props.theme}
807
812
  label="Hygiene"
808
- value={formatTailHygiene(s()!.tailHygiene!)}
813
+ value={hygieneValue(s()!.tailHygiene!)}
809
814
  warning={!s()!.tailHygiene!.evaluable}
810
815
  />
811
816
  )}
@@ -201,7 +201,7 @@ const StatusDialog = props => {
201
201
  color: COLORS.profile
202
202
  });
203
203
  if (d.conversationTokens > 0) segs.push({
204
- label: "Conversation*",
204
+ label: "Conversation",
205
205
  tokens: d.conversationTokens,
206
206
  color: COLORS.conversation
207
207
  });
@@ -384,7 +384,7 @@ const StatusDialog = props => {
384
384
  return _el$35;
385
385
  })();
386
386
  }), _el$15);
387
- _$insertNode(_el$15, _$createTextNode(`* Conversation includes Reasoning; hygiene excludes it`));
387
+ _$insertNode(_el$15, _$createTextNode(`Conversation includes reasoning; hygiene excludes it`));
388
388
  _$insert(_el$14, (() => {
389
389
  var _c$4 = _$memo(() => s().tailHygiene !== undefined);
390
390
  return () => _c$4() && _$createComponent(R, {
@@ -1070,7 +1070,7 @@ async function showRecompDialog(api, targetSessionId = getSessionId(api)) {
1070
1070
  api.ui.dialog.replace(() => _$createComponent(api.ui.DialogConfirm, {
1071
1071
  title: "\u26A0\uFE0F Recomp Confirmation",
1072
1072
  get message() {
1073
- return [count === 0 ? "This session has no compartments yet — recomp will build them from raw history." : `You have ${count} compartments.`, "", "Recomp will regenerate all compartments and facts from raw history.", "This may take a long time and consume significant tokens.", "", "Proceed?"].join("\n");
1073
+ return [count === 0 ? "This session has no compartments yet — recomp will build them from raw history." : `You have ${count} compartments.`, "", "Recomp will rebuild the compressed history from raw history. Saved memories are not changed.", "This may take a long time and consume significant tokens.", "", "Proceed?"].join("\n");
1074
1074
  },
1075
1075
  onConfirm: async () => {
1076
1076
  const requested = await requestRecomp(sessionId);