@bastani/atomic 0.9.8 → 0.9.9-alpha.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 (348) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/builtin/cursor/CHANGELOG.md +6 -0
  3. package/dist/builtin/cursor/package.json +2 -2
  4. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  5. package/dist/builtin/intercom/package.json +1 -1
  6. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  7. package/dist/builtin/mcp/package.json +1 -1
  8. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  9. package/dist/builtin/subagents/package.json +1 -1
  10. package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +2 -0
  11. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +7 -1
  12. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +2 -0
  13. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +8 -2
  14. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +2 -0
  15. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +2 -0
  16. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +2 -1
  17. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +2 -0
  18. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +2 -0
  19. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +2 -0
  20. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +2 -0
  21. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +6 -0
  22. package/dist/builtin/subagents/src/shared/types-config.ts +4 -0
  23. package/dist/builtin/subagents/src/shared/types-depth.ts +29 -2
  24. package/dist/builtin/web-access/CHANGELOG.md +6 -0
  25. package/dist/builtin/web-access/package.json +1 -1
  26. package/dist/builtin/workflows/CHANGELOG.md +22 -0
  27. package/dist/builtin/workflows/README.md +17 -8
  28. package/dist/builtin/workflows/builtin/goal-prompts.ts +8 -2
  29. package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +26 -9
  30. package/dist/builtin/workflows/builtin/ralph-forked-prompts.ts +1 -1
  31. package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +8 -3
  32. package/dist/builtin/workflows/builtin/ralph-runner.ts +2 -0
  33. package/dist/builtin/workflows/builtin/shared-prompts.ts +24 -1
  34. package/dist/builtin/workflows/package.json +1 -1
  35. package/dist/builtin/workflows/src/durable/backend.ts +53 -15
  36. package/dist/builtin/workflows/src/durable/completed-catalog.ts +245 -0
  37. package/dist/builtin/workflows/src/durable/completed-inspection.ts +213 -0
  38. package/dist/builtin/workflows/src/durable/dbos-backend.ts +120 -170
  39. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +84 -8
  40. package/dist/builtin/workflows/src/durable/dbos-metadata.ts +98 -0
  41. package/dist/builtin/workflows/src/durable/dbos-tombstone.ts +27 -0
  42. package/dist/builtin/workflows/src/durable/factory.ts +1 -1
  43. package/dist/builtin/workflows/src/durable/file-backend.ts +247 -241
  44. package/dist/builtin/workflows/src/durable/file-lock.ts +153 -0
  45. package/dist/builtin/workflows/src/durable/file-state.ts +104 -0
  46. package/dist/builtin/workflows/src/durable/format-version.ts +12 -0
  47. package/dist/builtin/workflows/src/durable/index.ts +12 -0
  48. package/dist/builtin/workflows/src/durable/resume-catalog.ts +16 -27
  49. package/dist/builtin/workflows/src/durable/resume-eligibility.ts +20 -0
  50. package/dist/builtin/workflows/src/durable/resume-runtime.ts +29 -29
  51. package/dist/builtin/workflows/src/durable/scoped-backend.ts +20 -3
  52. package/dist/builtin/workflows/src/durable/stage-primitive.ts +29 -8
  53. package/dist/builtin/workflows/src/durable/types.ts +3 -0
  54. package/dist/builtin/workflows/src/engine/primitives/task.ts +1 -0
  55. package/dist/builtin/workflows/src/engine/run.ts +14 -14
  56. package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +39 -9
  57. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +10 -0
  58. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +133 -0
  59. package/dist/builtin/workflows/src/extension/runtime.ts +15 -40
  60. package/dist/builtin/workflows/src/extension/wiring.ts +9 -6
  61. package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +226 -0
  62. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +1 -0
  63. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +66 -112
  64. package/dist/builtin/workflows/src/extension/workflow-schema.ts +5 -5
  65. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +16 -1
  66. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +50 -43
  67. package/dist/builtin/workflows/src/runs/foreground/executor-direct-output.ts +91 -0
  68. package/dist/builtin/workflows/src/runs/foreground/executor-direct.ts +95 -46
  69. package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +3 -1
  70. package/dist/builtin/workflows/src/runs/foreground/executor-task-prompts.ts +1 -1
  71. package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +3 -0
  72. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +1 -1
  73. package/dist/builtin/workflows/src/runs/foreground/stage-runner-options.ts +36 -7
  74. package/dist/builtin/workflows/src/runs/shared/worktree-cache-lifecycle.ts +25 -0
  75. package/dist/builtin/workflows/src/runs/shared/worktree-cwd.ts +103 -0
  76. package/dist/builtin/workflows/src/runs/shared/worktree-generation.ts +57 -0
  77. package/dist/builtin/workflows/src/runs/shared/worktree-git.ts +134 -8
  78. package/dist/builtin/workflows/src/runs/shared/worktree.ts +2 -0
  79. package/dist/builtin/workflows/src/shared/resumable-workflow-notices.ts +43 -0
  80. package/dist/builtin/workflows/src/shared/timing.ts +4 -0
  81. package/dist/builtin/workflows/src/shared/types.ts +5 -3
  82. package/dist/builtin/workflows/src/tui/graph-view-constants.ts +1 -0
  83. package/dist/builtin/workflows/src/tui/graph-view-input.ts +24 -14
  84. package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +43 -13
  85. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  86. package/dist/core/agent-session-auto-compaction.js +5 -7
  87. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  88. package/dist/core/agent-session-compaction.d.ts +6 -34
  89. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  90. package/dist/core/agent-session-compaction.js +95 -233
  91. package/dist/core/agent-session-compaction.js.map +1 -1
  92. package/dist/core/agent-session-message-queue.d.ts +0 -4
  93. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  94. package/dist/core/agent-session-message-queue.js +1 -5
  95. package/dist/core/agent-session-message-queue.js.map +1 -1
  96. package/dist/core/agent-session-methods.d.ts +5 -6
  97. package/dist/core/agent-session-methods.d.ts.map +1 -1
  98. package/dist/core/agent-session-methods.js.map +1 -1
  99. package/dist/core/agent-session-types.d.ts +2 -12
  100. package/dist/core/agent-session-types.d.ts.map +1 -1
  101. package/dist/core/agent-session-types.js.map +1 -1
  102. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  103. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  104. package/dist/core/compaction/branch-summarization.js +1 -2
  105. package/dist/core/compaction/branch-summarization.js.map +1 -1
  106. package/dist/core/compaction/compaction-boundary.d.ts +9 -0
  107. package/dist/core/compaction/compaction-boundary.d.ts.map +1 -0
  108. package/dist/core/compaction/compaction-boundary.js +115 -0
  109. package/dist/core/compaction/compaction-boundary.js.map +1 -0
  110. package/dist/core/compaction/compaction-parameters.d.ts +5 -0
  111. package/dist/core/compaction/compaction-parameters.d.ts.map +1 -0
  112. package/dist/core/compaction/compaction-parameters.js +27 -0
  113. package/dist/core/compaction/compaction-parameters.js.map +1 -0
  114. package/dist/core/compaction/compaction-runner.d.ts +14 -0
  115. package/dist/core/compaction/compaction-runner.d.ts.map +1 -0
  116. package/dist/core/compaction/compaction-runner.js +29 -0
  117. package/dist/core/compaction/compaction-runner.js.map +1 -0
  118. package/dist/core/compaction/compaction-types.d.ts +79 -0
  119. package/dist/core/compaction/compaction-types.d.ts.map +1 -0
  120. package/dist/core/compaction/compaction-types.js +6 -0
  121. package/dist/core/compaction/compaction-types.js.map +1 -0
  122. package/dist/core/compaction/deleted-ranges.d.ts +6 -0
  123. package/dist/core/compaction/deleted-ranges.d.ts.map +1 -0
  124. package/dist/core/compaction/deleted-ranges.js +134 -0
  125. package/dist/core/compaction/deleted-ranges.js.map +1 -0
  126. package/dist/core/compaction/index.d.ts +7 -1
  127. package/dist/core/compaction/index.d.ts.map +1 -1
  128. package/dist/core/compaction/index.js +7 -1
  129. package/dist/core/compaction/index.js.map +1 -1
  130. package/dist/core/compaction/range-planner.d.ts +21 -0
  131. package/dist/core/compaction/range-planner.d.ts.map +1 -0
  132. package/dist/core/compaction/range-planner.js +145 -0
  133. package/dist/core/compaction/range-planner.js.map +1 -0
  134. package/dist/core/compaction/transcript-serialization.d.ts +11 -0
  135. package/dist/core/compaction/transcript-serialization.d.ts.map +1 -0
  136. package/dist/core/compaction/transcript-serialization.js +104 -0
  137. package/dist/core/compaction/transcript-serialization.js.map +1 -0
  138. package/dist/core/extensions/context-types.d.ts +2 -2
  139. package/dist/core/extensions/context-types.d.ts.map +1 -1
  140. package/dist/core/extensions/context-types.js.map +1 -1
  141. package/dist/core/extensions/event-results.d.ts +2 -2
  142. package/dist/core/extensions/event-results.d.ts.map +1 -1
  143. package/dist/core/extensions/event-results.js.map +1 -1
  144. package/dist/core/extensions/session-events.d.ts +7 -7
  145. package/dist/core/extensions/session-events.d.ts.map +1 -1
  146. package/dist/core/extensions/session-events.js.map +1 -1
  147. package/dist/core/index.d.ts +1 -1
  148. package/dist/core/index.d.ts.map +1 -1
  149. package/dist/core/index.js.map +1 -1
  150. package/dist/core/messages.d.ts +4 -0
  151. package/dist/core/messages.d.ts.map +1 -1
  152. package/dist/core/messages.js +11 -0
  153. package/dist/core/messages.js.map +1 -1
  154. package/dist/core/provider-context-usage.d.ts.map +1 -1
  155. package/dist/core/provider-context-usage.js +1 -2
  156. package/dist/core/provider-context-usage.js.map +1 -1
  157. package/dist/core/session-manager-archive.d.ts +2 -1
  158. package/dist/core/session-manager-archive.d.ts.map +1 -1
  159. package/dist/core/session-manager-archive.js +2 -2
  160. package/dist/core/session-manager-archive.js.map +1 -1
  161. package/dist/core/session-manager-classification.d.ts +9 -0
  162. package/dist/core/session-manager-classification.d.ts.map +1 -0
  163. package/dist/core/session-manager-classification.js +37 -0
  164. package/dist/core/session-manager-classification.js.map +1 -0
  165. package/dist/core/session-manager-core.d.ts +4 -4
  166. package/dist/core/session-manager-core.d.ts.map +1 -1
  167. package/dist/core/session-manager-core.js +13 -8
  168. package/dist/core/session-manager-core.js.map +1 -1
  169. package/dist/core/session-manager-entries.d.ts +4 -3
  170. package/dist/core/session-manager-entries.d.ts.map +1 -1
  171. package/dist/core/session-manager-entries.js +12 -10
  172. package/dist/core/session-manager-entries.js.map +1 -1
  173. package/dist/core/session-manager-history.d.ts +6 -23
  174. package/dist/core/session-manager-history.d.ts.map +1 -1
  175. package/dist/core/session-manager-history.js +23 -256
  176. package/dist/core/session-manager-history.js.map +1 -1
  177. package/dist/core/session-manager-list.d.ts.map +1 -1
  178. package/dist/core/session-manager-list.js +3 -3
  179. package/dist/core/session-manager-list.js.map +1 -1
  180. package/dist/core/session-manager-storage.d.ts +1 -1
  181. package/dist/core/session-manager-storage.d.ts.map +1 -1
  182. package/dist/core/session-manager-storage.js +3 -2
  183. package/dist/core/session-manager-storage.js.map +1 -1
  184. package/dist/core/session-manager-types.d.ts +14 -15
  185. package/dist/core/session-manager-types.d.ts.map +1 -1
  186. package/dist/core/session-manager-types.js.map +1 -1
  187. package/dist/core/session-manager.d.ts +3 -2
  188. package/dist/core/session-manager.d.ts.map +1 -1
  189. package/dist/core/session-manager.js +1 -1
  190. package/dist/core/session-manager.js.map +1 -1
  191. package/dist/core/slash-commands.d.ts.map +1 -1
  192. package/dist/core/slash-commands.js +1 -1
  193. package/dist/core/slash-commands.js.map +1 -1
  194. package/dist/index.d.ts +3 -2
  195. package/dist/index.d.ts.map +1 -1
  196. package/dist/index.js +2 -1
  197. package/dist/index.js.map +1 -1
  198. package/dist/main-session.d.ts +1 -0
  199. package/dist/main-session.d.ts.map +1 -1
  200. package/dist/main-session.js +7 -0
  201. package/dist/main-session.js.map +1 -1
  202. package/dist/main.d.ts.map +1 -1
  203. package/dist/main.js +2 -2
  204. package/dist/main.js.map +1 -1
  205. package/dist/modes/interactive/components/chat-message-renderer.d.ts +4 -1
  206. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  207. package/dist/modes/interactive/components/chat-message-renderer.js +12 -22
  208. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  209. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  210. package/dist/modes/interactive/components/chat-session-host-events.js +5 -11
  211. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  212. package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
  213. package/dist/modes/interactive/components/chat-session-host-rendering.js +3 -0
  214. package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
  215. package/dist/modes/interactive/components/chat-session-host-state.d.ts +1 -0
  216. package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
  217. package/dist/modes/interactive/components/chat-session-host-state.js +1 -0
  218. package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
  219. package/dist/modes/interactive/components/chat-session-host-utils.d.ts.map +1 -1
  220. package/dist/modes/interactive/components/chat-session-host-utils.js +1 -1
  221. package/dist/modes/interactive/components/chat-session-host-utils.js.map +1 -1
  222. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  223. package/dist/modes/interactive/components/chat-session-host.js +1 -0
  224. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  225. package/dist/modes/interactive/components/compaction-boundary-message.d.ts +20 -0
  226. package/dist/modes/interactive/components/compaction-boundary-message.d.ts.map +1 -0
  227. package/dist/modes/interactive/components/compaction-boundary-message.js +48 -0
  228. package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -0
  229. package/dist/modes/interactive/components/index.d.ts +1 -1
  230. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  231. package/dist/modes/interactive/components/index.js +1 -1
  232. package/dist/modes/interactive/components/index.js.map +1 -1
  233. package/dist/modes/interactive/components/session-selector-list.d.ts.map +1 -1
  234. package/dist/modes/interactive/components/session-selector-list.js +3 -0
  235. package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
  236. package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
  237. package/dist/modes/interactive/interactive-agent-events.js +3 -47
  238. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  239. package/dist/modes/interactive/interactive-mode-deps.d.ts +2 -2
  240. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  241. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  242. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  243. package/dist/modes/interactive/interactive-mode-surface.d.ts +5 -3
  244. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  245. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  246. package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
  247. package/dist/modes/interactive/interactive-render-chat.js +21 -12
  248. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  249. package/dist/modes/rpc/rpc-client.d.ts +3 -5
  250. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  251. package/dist/modes/rpc/rpc-client.js +1 -6
  252. package/dist/modes/rpc/rpc-client.js.map +1 -1
  253. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  254. package/dist/modes/rpc/rpc-command-handler.js +0 -4
  255. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  256. package/dist/modes/rpc/rpc-types.d.ts +2 -11
  257. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  258. package/dist/modes/rpc/rpc-types.js.map +1 -1
  259. package/docs/compaction.md +97 -772
  260. package/docs/extensions.md +25 -29
  261. package/docs/json.md +2 -2
  262. package/docs/rpc.md +32 -24
  263. package/docs/sdk.md +3 -3
  264. package/docs/session-format.md +49 -30
  265. package/docs/sessions.md +5 -3
  266. package/docs/settings.md +14 -4
  267. package/docs/usage.md +1 -1
  268. package/docs/workflows.md +30 -15
  269. package/examples/extensions/custom-compaction.ts +14 -58
  270. package/examples/extensions/handoff.ts +2 -3
  271. package/npm-shrinkwrap.json +23 -23
  272. package/package.json +2 -2
  273. package/dist/core/compaction/context-assistant-turns.d.ts +0 -42
  274. package/dist/core/compaction/context-assistant-turns.d.ts.map +0 -1
  275. package/dist/core/compaction/context-assistant-turns.js +0 -87
  276. package/dist/core/compaction/context-assistant-turns.js.map +0 -1
  277. package/dist/core/compaction/context-compaction-critical.d.ts +0 -15
  278. package/dist/core/compaction/context-compaction-critical.d.ts.map +0 -1
  279. package/dist/core/compaction/context-compaction-critical.js +0 -57
  280. package/dist/core/compaction/context-compaction-critical.js.map +0 -1
  281. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts +0 -18
  282. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts.map +0 -1
  283. package/dist/core/compaction/context-compaction-eviction-alternates.js +0 -186
  284. package/dist/core/compaction/context-compaction-eviction-alternates.js.map +0 -1
  285. package/dist/core/compaction/context-compaction-eviction.d.ts +0 -12
  286. package/dist/core/compaction/context-compaction-eviction.d.ts.map +0 -1
  287. package/dist/core/compaction/context-compaction-eviction.js +0 -222
  288. package/dist/core/compaction/context-compaction-eviction.js.map +0 -1
  289. package/dist/core/compaction/context-compaction-metrics.d.ts +0 -28
  290. package/dist/core/compaction/context-compaction-metrics.d.ts.map +0 -1
  291. package/dist/core/compaction/context-compaction-metrics.js +0 -107
  292. package/dist/core/compaction/context-compaction-metrics.js.map +0 -1
  293. package/dist/core/compaction/context-compaction-prompt.d.ts +0 -9
  294. package/dist/core/compaction/context-compaction-prompt.d.ts.map +0 -1
  295. package/dist/core/compaction/context-compaction-prompt.js +0 -163
  296. package/dist/core/compaction/context-compaction-prompt.js.map +0 -1
  297. package/dist/core/compaction/context-compaction-runner.d.ts +0 -11
  298. package/dist/core/compaction/context-compaction-runner.d.ts.map +0 -1
  299. package/dist/core/compaction/context-compaction-runner.js +0 -273
  300. package/dist/core/compaction/context-compaction-runner.js.map +0 -1
  301. package/dist/core/compaction/context-compaction-strategy.d.ts +0 -5
  302. package/dist/core/compaction/context-compaction-strategy.d.ts.map +0 -1
  303. package/dist/core/compaction/context-compaction-strategy.js +0 -27
  304. package/dist/core/compaction/context-compaction-strategy.js.map +0 -1
  305. package/dist/core/compaction/context-compaction-types.d.ts +0 -75
  306. package/dist/core/compaction/context-compaction-types.d.ts.map +0 -1
  307. package/dist/core/compaction/context-compaction-types.js +0 -6
  308. package/dist/core/compaction/context-compaction-types.js.map +0 -1
  309. package/dist/core/compaction/context-compaction.d.ts +0 -10
  310. package/dist/core/compaction/context-compaction.d.ts.map +0 -1
  311. package/dist/core/compaction/context-compaction.js +0 -8
  312. package/dist/core/compaction/context-compaction.js.map +0 -1
  313. package/dist/core/compaction/context-deletion-application.d.ts +0 -14
  314. package/dist/core/compaction/context-deletion-application.d.ts.map +0 -1
  315. package/dist/core/compaction/context-deletion-application.js +0 -261
  316. package/dist/core/compaction/context-deletion-application.js.map +0 -1
  317. package/dist/core/compaction/context-deletion-store.d.ts +0 -78
  318. package/dist/core/compaction/context-deletion-store.d.ts.map +0 -1
  319. package/dist/core/compaction/context-deletion-store.js +0 -162
  320. package/dist/core/compaction/context-deletion-store.js.map +0 -1
  321. package/dist/core/compaction/context-deletion-targets.d.ts +0 -43
  322. package/dist/core/compaction/context-deletion-targets.d.ts.map +0 -1
  323. package/dist/core/compaction/context-deletion-targets.js +0 -292
  324. package/dist/core/compaction/context-deletion-targets.js.map +0 -1
  325. package/dist/core/compaction/context-deletion-tool-definitions.d.ts +0 -193
  326. package/dist/core/compaction/context-deletion-tool-definitions.d.ts.map +0 -1
  327. package/dist/core/compaction/context-deletion-tool-definitions.js +0 -98
  328. package/dist/core/compaction/context-deletion-tool-definitions.js.map +0 -1
  329. package/dist/core/compaction/context-deletion-tool-helpers.d.ts +0 -19
  330. package/dist/core/compaction/context-deletion-tool-helpers.d.ts.map +0 -1
  331. package/dist/core/compaction/context-deletion-tool-helpers.js +0 -210
  332. package/dist/core/compaction/context-deletion-tool-helpers.js.map +0 -1
  333. package/dist/core/compaction/context-deletion-tools.d.ts +0 -4
  334. package/dist/core/compaction/context-deletion-tools.d.ts.map +0 -1
  335. package/dist/core/compaction/context-deletion-tools.js +0 -403
  336. package/dist/core/compaction/context-deletion-tools.js.map +0 -1
  337. package/dist/core/compaction/context-transcript-analysis.d.ts +0 -11
  338. package/dist/core/compaction/context-transcript-analysis.d.ts.map +0 -1
  339. package/dist/core/compaction/context-transcript-analysis.js +0 -228
  340. package/dist/core/compaction/context-transcript-analysis.js.map +0 -1
  341. package/dist/core/session-manager-tool-dependencies.d.ts +0 -10
  342. package/dist/core/session-manager-tool-dependencies.d.ts.map +0 -1
  343. package/dist/core/session-manager-tool-dependencies.js +0 -133
  344. package/dist/core/session-manager-tool-dependencies.js.map +0 -1
  345. package/dist/modes/interactive/components/context-compaction-summary-message.d.ts +0 -17
  346. package/dist/modes/interactive/components/context-compaction-summary-message.d.ts.map +0 -1
  347. package/dist/modes/interactive/components/context-compaction-summary-message.js +0 -83
  348. package/dist/modes/interactive/components/context-compaction-summary-message.js.map +0 -1
@@ -1,772 +1,161 @@
1
1
  # Compaction & Branch Summarization
2
2
 
3
- LLMs have limited context windows. When conversations grow too long, Atomic's compaction behavior uses **Verbatim Compaction**: it deletes safe older transcript objects while preserving every retained object exactly as it was recorded. This page covers default auto/manual compaction, how it compares to the retired legacy summary compaction, and branch summarization.
3
+ LLMs have finite context windows. Atomic reduces older context with **verbatim line compaction** while preserving recent logical turns as ordinary messages. Branch summarization is a separate, intentionally lossy feature used only when navigating away from a branch.
4
4
 
5
- Atomic's compaction design and terminology are informed by Morph's Context Compaction work: [Morph's Context Compaction](https://www.morphllm.com/context-compaction). Atomic follows the same core idea that coding agents often benefit more from deleting low-signal context than from rewriting high-signal details like file paths, line numbers, commands, and error strings into a lossy summary.
6
-
7
- **Source files** ([atomic](https://github.com/bastani-inc/atomic)):
8
-
9
- - [`packages/coding-agent/src/core/compaction/context-compaction.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/compaction/context-compaction.ts) - Public barrel for Verbatim Compaction types, helpers, tools, and runner exports
10
- - [`packages/coding-agent/src/core/compaction/context-compaction-runner.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/compaction/context-compaction-runner.ts) - Planner loop, strict target gate, auto-compaction fallback ladder, and planner nudge cap
11
- - [`packages/coding-agent/src/core/compaction/context-compaction-critical.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/compaction/context-compaction-critical.ts) - Internal overflow-only critical-pass protected-entry eligibility and prompt guidance
12
- - [`packages/coding-agent/src/core/compaction/context-compaction-eviction.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/compaction/context-compaction-eviction.ts) - Internal overflow-only deterministic LRU eviction runner
13
- - [`packages/coding-agent/src/core/compaction/context-compaction-eviction-alternates.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/compaction/context-compaction-eviction-alternates.ts) - Bounded alternate-boundary planning and shared eviction-plan validation
14
- - [`packages/coding-agent/src/core/compaction/branch-summarization.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) - Branch summarization
15
- - [`packages/coding-agent/src/core/compaction/utils.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/compaction/utils.ts) - Shared utilities (file tracking, serialization)
16
- - [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/session-manager.ts) - Entry types (`ContextCompactionEntry`, `BranchSummaryEntry`) and active-context rebuild logic
17
- - [`packages/coding-agent/src/core/provider-context-usage.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/provider-context-usage.ts) - Provider-bound usage scrub that keeps post-compaction token budgeting based on the compacted prompt
18
- - [`packages/coding-agent/src/core/extensions/session-events.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/extensions/session-events.ts) - Compaction extension event payloads
19
-
20
- For TypeScript definitions in your project, inspect `node_modules/@bastani/atomic/dist/`.
5
+ Compaction runs entirely locally with the active session model; no external compaction service is involved. The model only selects which lines to delete Atomic reconstructs the retained text mechanically, so surviving lines are never rewritten.
21
6
 
22
7
  ## Overview
23
8
 
24
- Atomic has one context compaction behavior and one separate branch-summarization mechanism:
25
-
26
- | Mechanism | Trigger | Purpose |
27
- |-----------|---------|---------|
28
- | Verbatim Compaction (context compaction) | Context exceeds threshold, context overflow, or `/compact` | Delete safe old transcript entries/content blocks while retaining surviving content verbatim |
29
- | Branch summarization | `/tree` navigation | Preserve useful context when switching branches |
9
+ | Mechanism | Trigger | Model output | Durable result |
10
+ |---|---|---|---|
11
+ | Verbatim compaction | `/compact`, RPC `compact`, or automatic threshold/overflow recovery | Compact JSON `{"d":[[start,end],...]}` only | A `CompactionEntry` whose `summary` is mechanically reconstructed transcript text |
12
+ | Branch summarization | Optional `/tree` navigation | Generated summary prose | A `BranchSummaryEntry` |
30
13
 
31
- Summary compaction the earlier behavior that generated replacement prose — has been removed as an active runtime path. Historical JSONL lines with `type:"compaction"` remain readable on disk but are not injected into active LLM context. See [Legacy Summary Compaction (Retired)](#legacy-summary-compaction-retired) for a comparison and historical reference.
14
+ There is one context-compaction door: `compact`.
32
15
 
33
- `/compact` has no user-facing arguments. It uses the effective `compaction` settings (`compression_ratio`, `preserve_recent`, and optional `query`), a fixed internal prompt, transcript-bound inspection/deletion tools, local validation, and a `context_compaction` session entry. Manual compaction (`/compact` and the `contextCompact` RPC path) still uses the strict planner target only. Auto-compaction uses the same deletion-only commit path, but threshold and overflow triggers can accept validated below-target reductions or, on overflow only, escalate through internal recovery tiers when the strict target is not achievable.
16
+ ## Verbatim Line Compaction
34
17
 
35
- ## Verbatim vs. Summary Compaction
18
+ ### What "verbatim" means
36
19
 
37
- Atomic uses Verbatim Compaction as its sole compaction strategy. The following comparison explains why, and documents what legacy summary compaction used to do.
20
+ Atomic serializes the compactable part of the conversation into role-tagged lines:
38
21
 
39
- | Property | Verbatim Compaction | Summary Compaction (retired) |
40
- |----------|---------------------|------------------------------|
41
- | Mechanism | Deletes entries/content blocks | Rewrites earlier context into new prose |
42
- | Surviving content | Exact original transcript content | Generated summary text |
43
- | File paths / commands / errors | Kept exact or deleted | Can be paraphrased or omitted |
44
- | Line numbers and stack traces | Kept exact or deleted | Can be distorted in summary |
45
- | Auditability | Deleted targets are listed and inspectable | Omission/paraphrase is hard to audit |
46
- | Recoverability | Pre-compaction backup snapshot; deleted targets listed in entry | Generated summary cannot be losslessly reversed |
47
- | Failure mode | Needed context may be deleted (mitigated by validation and backups) | Needed context may be silently distorted |
48
- | Atomic end state | **Canonical behavior** | **Removed runtime behavior** |
22
+ ```text
23
+ [User]: Fix the failing parser test
24
+ [Assistant thinking]: I will inspect the parser.
25
+ [Assistant tool calls]: read(path="src/parser.ts")
26
+ [Tool result]: export function parse(...) {
27
+ ...
28
+ [Assistant]: The off-by-one error is fixed.
29
+ ```
49
30
 
50
- Coding agents depend on exact file paths (`src/foo.ts:42`), exact commands (`npm run build`), exact error strings, and exact line numbers. A generated summary that says "an error occurred in the auth module" instead of recording the actual stack trace loses irreplaceable information. Deletion is honest: what remains is unchanged, and what was deleted is listed in an inspectable `context_compaction` entry.
31
+ The planner sees the same text numbered as `N→content` and may return only one-based, inclusive line ranges:
51
32
 
52
- Deletion can still lose needed context. Atomic mitigates this with:
53
- - **Local validation**: Disallowed deletion targets return explicit non-terminating tool errors; grep/regex deletion ignores rejected matches and continues with accepted matches.
54
- - **Pre-compaction backups**: A `.compact.bak` snapshot is written before each compaction for persisted sessions.
55
- - **Auditable targets**: The `context_compaction` entry records every deleted entry/content-block ID.
33
+ ```json
34
+ {"d":[[2,5]]}
35
+ ```
56
36
 
57
- ## Default Context Compaction (Verbatim Compaction)
37
+ Prompt version 3 accepts only this compact grammar. Atomic safety-normalizes finite integer endpoints by truncating, swapping reversed pairs, clamping to the transcript, sorting, merging overlap/adjacency, and splitting around explicit protected spans. It then reconstructs from the original input lines. The model never writes, summarizes, reorders, or normalizes retained text. Every retained non-marker line is byte-identical to an input line and remains in input order.
58
38
 
59
- ### What "Verbatim" Means
39
+ ### Markers and repeated compaction
60
40
 
61
- Verbatim Compaction never asks a model to rewrite the conversation for the main active context. Instead, the model may only choose deletion targets by stable transcript ID:
41
+ Each deleted span is replaced on its own line with exactly:
62
42
 
63
- - **Whole entries** such as an old assistant message or obsolete tool result.
64
- - **Individual content blocks** inside a multi-block message, such as one stale tool call block while keeping other blocks.
43
+ ```text
44
+ (filtered N lines)
45
+ ```
65
46
 
66
- Replay-sensitive assistant messages are protected as logical tool-use turns. Each provider-visible user-like input starts a turn: user/custom content with non-whitespace text or an image, context-eligible bash executions, and non-empty branch summaries. Empty or whitespace-only user/custom content and empty branch summaries are omitted from provider replay and therefore do not split turns; a whitespace-only branch summary remains visible because Atomic wraps it in explanatory text. Unknown blocks with a non-empty string `type` fail visible for forward compatibility, while malformed or untyped blocks remain invisible. Assistant messages and intervening tool results remain in that turn until the next visible user-like input. The current final logical turn is active (including a turn whose final assistant message is tool-call-only), so none of its `thinking` or `redacted_thinking`-bearing assistant entries may be deleted. A trailing visible input with no assistant response makes the preceding assistant turn historical. In a completed historical turn, Atomic may retain every signed-thinking-bearing assistant entry or omit all of them, but never retain a proper subset. Every retained thinking-bearing message also remains byte-for-byte intact: individual sibling blocks cannot be deleted. This preserves the signed Anthropic/GitHub Copilot replay sequence rather than merely preserving each remaining message in isolation.
47
+ The spelling is always plural, including `(filtered 1 lines)`. When a later compaction swallows an earlier marker, Atomic adds the earlier marker's count to the new marker. Adjacent old markers are folded too, so counts remain cumulative across repeated compactions.
67
48
 
68
- Tool-call/tool-result pairs are also treated as replay dependencies. Fresh plans are reconciled before the turn invariant is checked, so paired deletions cannot indirectly create a partial signed sequence. During active-context reconstruction, unsafe persisted plans are repaired in memory by restoring the affected signed entries and re-running tool reconciliation, which also restores their paired results. The append-only JSONL is not rewritten, while safe complete historical signed-sequence omissions remain effective. As a final provider-safety guard, orphaned `toolResult` messages are dropped before LLM serialization if their matching assistant `toolCall` is no longer the immediately preceding tool-use group. Raw `redacted_thinking` blocks are normalized in the transient, non-mutating LLM-compatible messages returned by `convertToLlm`; durable session messages remain byte-exact.
49
+ ### Protected structure
69
50
 
70
- Atomic records those targets in an append-only `context_compaction` entry. When the active branch is rebuilt, Atomic filters the targeted objects out and reuses every retained entry/content block unchanged. There is no generated summary, no paraphrasing, and no replacement message inserted.
51
+ Role-header lines such as `[User]:` and `[Assistant]:` are ordinary ranked lines and may be deleted. Explicit protected spans, including blank lines, are never deleted. The recent logical-turn tail is protected client-side by remaining outside the classifier request entirely.
71
52
 
72
- The raw session JSONL remains append-only. Deleted objects stay available in the stored session file and backup snapshot; they are only omitted from future active LLM context on that branch.
53
+ Images in the compactable region become the literal line `[image]`; images in the protected recent tail remain normal image content. Tool-result text remains capped at 16,000 characters before becoming durable compaction text, with an explicit truncation marker for the remainder.
73
54
 
74
- Provider-bound context is cloned one more time before each LLM request. Retained assistant messages from before the latest `context_compaction` keep their historical usage in the durable session JSONL, but Atomic zeroes that usage in the request-only clone so provider token-budget estimators do not treat the compacted context as if it still contained the old, larger prompt. The first assistant response after compaction then supplies fresh usage for subsequent turns.
55
+ ## Parameters
75
56
 
76
- ### Compaction Parameters
57
+ The effective parameters appear in extension events and successful results:
77
58
 
78
- Atomic uses three effective parameters for each context-compaction run. They are available to extension hooks as `event.parameters`, copied into `event.preparation.parameters`, and returned on `event.result.parameters` after a successful compaction.
59
+ | Parameter | Default | Meaning |
60
+ |---|---:|---|
61
+ | `compression_ratio` | `0.5` | Fraction of compactable **lines to keep**, not a token ratio |
62
+ | `preserve_recent` | `2` | Number of recent context-visible messages protected client-side; the cut widens backward to a user-turn start |
63
+ | `query` | Last visible user message | Relevance focus for deciding which older lines to retain |
79
64
 
80
- | Parameter | Type | Default | Meaning |
81
- |-----------|------|---------|---------|
82
- | `compression_ratio` | `float` | `0.5` | Fraction of compactable context to keep. `0.3` is aggressive (keep 30%, delete 70%); `0.7` is light (keep 70%, delete 30%). |
83
- | `preserve_recent` | `int` | `2` | Number of most recent context-eligible messages kept uncompressed / undeletable. |
84
- | `query` | `string` | auto-detected | Focus query for relevance-based pruning. If provided in settings or `ctx.compact()`, Atomic uses that value; otherwise it derives the query from the latest context-eligible user message. |
65
+ `preserve_recent` never leaves an assistant message or tool result at the start of the kept tail. Even when it is `0`, Atomic keeps the final logical turn. If `query` is absent, Atomic derives it from the last visible user message.
85
66
 
86
- Settings use the same snake_case names under `compaction`, for example:
67
+ Configure defaults in `~/.atomic/agent/settings.json` or `.atomic/settings.json`:
87
68
 
88
69
  ```json
89
70
  {
90
71
  "compaction": {
72
+ "enabled": true,
73
+ "reserveTokens": 16384,
91
74
  "compression_ratio": 0.5,
92
75
  "preserve_recent": 2,
93
- "query": "preserve details relevant to the current refactor"
76
+ "query": "optional focus"
94
77
  }
95
78
  }
96
79
  ```
97
80
 
98
- ### When It Triggers
99
-
100
- Auto-compaction threshold checks trigger when:
101
-
102
- ```text
103
- contextTokens > effectiveInputBudget - reserveTokens
104
- ```
105
-
106
- By default, `reserveTokens` is 16384 tokens. Configure it in `~/.atomic/agent/settings.json` or `<project-dir>/.atomic/settings.json`; legacy `.pi` paths are also supported. This leaves room for the LLM's response. Providers that advertise a larger total context window than their hard prompt cap use the model's effective input budget for threshold and overflow recovery decisions.
107
-
108
- You can also trigger compaction manually with `/compact`. Custom summary instructions are not accepted because Verbatim Compaction is deletion-only and retained transcript content stays verbatim. Manual compaction keeps the strict `compression_ratio` completion requirement and does not run the auto-compaction overflow ladder.
109
-
110
- If auto-compaction runs while a turn still has queued work (for example a failed tool-call result or a follow-up queued during compaction), Atomic resumes through the same continuation lifecycle as a normal queued turn: provider retry handling runs, additional queued messages drain, and any post-compaction resume failure is surfaced instead of being swallowed silently.
111
-
112
- For any compaction event that succeeds with `willRetry: true`, the public `AgentSession.prompt()` promise remains pending until the post-compaction retry continuation has run through the normal continuation lifecycle. This includes overflow recovery, threshold recovery after output-token length stops, and threshold recovery after retry-worthy OpenAI Responses output-budget errors. If overflow continuation exhausts the one compact-and-retry attempt and emits `compaction_end` with `unresolvedOverflow: true`, workflow callers can observe the signal before deciding whether the prompt succeeded or should advance model fallback.
113
-
114
- When an assistant response is truncated at the provider's per-turn output-token cap (`stopReason: "length"`) with real output produced, Atomic treats it as work cut off mid-flight and continues it automatically instead of leaving the turn dead-ended on the "maximum output token limit" error. If the context is at or above the compaction threshold, the truncation is recovered through the normal compact-and-continue path (the incomplete assistant is dropped from retry context, then generation resumes, and `AgentSession.prompt()` waits for that continuation). If the context is still below the threshold — genuine long output with input room to spare — compaction would free no room, so Atomic continues the generation directly without compacting. Consecutive direct continuations are bounded by a small cap, so a turn that keeps exceeding the per-turn output cap still terminates rather than looping. This resume applies only to the live turn-completion path; a fresh user prompt never resumes a previously truncated turn.
115
-
116
- OpenAI Responses providers can also report context pressure as a request-budget underflow instead of a normal context-overflow stop, for example `Invalid 'max_output_tokens': integer below minimum value. Expected a value >= 16, but got 1 instead.` When that exact output-budget family of errors arrives on a live, threshold-sized context, Atomic treats it as retry-worthy interrupted work: auto-compaction records the `context_compaction` entry, removes the empty error assistant from retry context, and automatically continues from the preceding user/tool-result anchor. Other `invalid_request_body` errors, such as malformed tool schemas, remain visible and are not auto-retried through compaction. Output-budget underflow uses a separate one-attempt guard and intentionally does not set `unresolvedOverflow`; if the compact-and-continue attempt still cannot produce a non-error assistant turn, the session leaves the visible terminal provider error in place instead of looping or advancing overflow-specific fallback.
117
-
118
- ### Image Context and Compaction
119
-
120
- Image content blocks (screenshots, pasted images, image-bearing tool results) are expensive: providers fold image tokens into their reported prompt/input usage, so image-heavy conversations reach the compaction threshold sooner. Atomic accounts for this in two complementary ways:
121
-
122
- - **Token accounting includes images.** When provider usage is available (after a normal assistant response), the actual image token cost is already captured in the reported input/prompt tokens. For heuristic estimates of trailing messages without usage (for example, on an error fallback), each image content block contributes a single shared conservative estimate of `1200` tokens. This same estimate is used by the transcript planner, so the threshold check and the planner agree on how costly images are.
123
- - **Irrelevant images can be deleted.** The deletion planner can remove stale, superseded, or unrelated image content blocks from older entries using `context_delete` with `kind: "content_block"` or `context_grep_delete` matching the `[image]` placeholder. This includes old user-pasted image attachments when provider-visible non-image content remains in the same entry, plus old image-only user entries when another provider-visible task-bearing entry remains. `context_grep_delete` canonicalizes multi-image-only user matches into one safe entry deletion so a batch of `[image]` matches does not fail because every individual block would be removed. When images dominate the context, the `context_compaction_budget` tool reports the remaining image token share (`imageTokenPercent`) and the planner is instructed to prefer deleting stale image blocks before removing useful recent text. The budget tool recomputes image statistics from the current deletion-target set on every call, so after deleting image blocks the reported `remainingImageTokens`/`imageBlockCount`/`imageTokenPercent` immediately reflect the reduced live working set rather than the original pre-deletion totals. `imageTokenPercent` is computed against the **remaining** (post-deletion) context total, not the original pre-deletion total, so deleting non-image text correctly raises the reported image share while deleting image blocks correctly lowers it.
124
-
125
- Task-relevant images are preserved automatically:
126
-
127
- - **User text and task context remain protected.** Stale, non-recent user `image` content blocks may be deleted only when provider-visible non-image user content remains in the same entry. Old image-only user entries may be deleted only when another provider-visible task-bearing entry remains, so compaction can remove irrelevant pasted screenshots without erasing the last statement of the task.
128
- - **Recent entries** (the last `preserve_recent` provider-visible transcript entries, default `2`) are protected, keeping current user-pasted images and the most recent image-bearing results the agent is still acting on.
129
- - **Provider-visible custom/branch-summary messages** are protected as task-bearing context.
130
-
131
- Because Verbatim Compaction is deletion-only, compaction never generates summaries, paraphrases, or replacement content. Deleted image blocks are simply omitted from the rebuilt active context; surviving content stays byte-for-byte identical. No image payload data is ever reintroduced, and image payloads never appear in the compaction prompt (images are surfaced as the `[image]` placeholder with their token estimate).
132
-
133
- ### How It Works
134
-
135
- The diagram below is intentionally a block diagram, not a flowchart DSL. Read it left to right first, then use the lower diagrams to inspect the tool loop, validation airlock, dependency repair, and persistence path.
136
-
137
- #### Context compaction at a glance
138
-
139
- ```text
140
- ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
141
- │ GOAL │
142
- │ Delete low-signal transcript objects while leaving every surviving object byte-for-byte │
143
- │ equivalent in active model context. No summaries. No paraphrases. No replacement messages. │
144
- └──────────────────────────────────────────────────────────────────────────────────────────────┘
145
-
146
- ┌──────────────┐ ┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────┐
147
- │ 1 Trigger │───▶│ 2 Prepare transcript │───▶│ 3 Planner workspace │───▶│ 4 Tool loop │
148
- └──────────────┘ └──────────────────────┘ └──────────────────────┘ └──────────────────┘
149
- │ │ │ │
150
- │ │ │ ▼
151
- │ │ │ ┌──────────────────────────┐
152
- │ │ │ │ 5 Validation airlock │
153
- │ │ │ └──────────────────────────┘
154
- │ │ │ │
155
- │ │ │ ┌─────────────┴─────────────┐
156
- │ │ │ ▼ ▼
157
- │ │ │ ┌──────────────────┐ ┌─────────────────────┐
158
- │ │ │ │ ✗ Correction │ │ ✓ Validated state │
159
- │ │ │ │ tool result │ │ replaces tool store │
160
- │ │ │ └──────────────────┘ └─────────────────────┘
161
- │ │ │ │ │
162
- │ │ │ └──────────────┬────────────┘
163
- │ │ │ ▼
164
- │ │ │ ┌──────────────────────────┐
165
- │ │ └─────────────▶│ 6 Planner stops or adds │
166
- │ │ │ more deletion targets │
167
- │ │ └──────────────────────────┘
168
- │ │ │
169
- │ │ ▼
170
- │ │ ┌──────────────────────────┐
171
- └───────────────────────┴─────────────────────────────────────────▶│ 7 Persist compaction │
172
- └──────────────────────────┘
173
-
174
-
175
- ┌──────────────────────────┐
176
- │ 8 Rebuild active context │
177
- └──────────────────────────┘
178
- ```
179
-
180
- | Block | Main code path | Input | Output |
181
- |-------|----------------|-------|--------|
182
- | 1 Trigger | `/compact`, threshold check, overflow retry, `ctx.compact()` | Current session branch | Compaction request with reason and parameters |
183
- | 2 Prepare transcript | `prepareContextCompaction` | Branch `SessionEntry[]` plus prior `context_compaction` filters | `ContextCompactionPreparation` |
184
- | 3 Planner workspace | `runContextDeletionAssistant` | `CompactableTranscript` | Temp JSONL transcript file plus bounded manifest prompt, inheriting the session's current model thinking level |
185
- | 4 Tool loop | `createContextDeletionTool` tools | Planner tool calls | In-run deletion store updates or correction errors |
186
- | 5 Validation airlock | `validateContextDeletionRequest` | Candidate cumulative deletion request | Reconciled `deletedTargets` or thrown error |
187
- | 6 Target/fallback decision | `contextCompact` runner ladder | Final or salvaged validated deletion state | Strict-target success, feasible auto-compaction acceptance, overflow-only critical pass, deterministic eviction, or terminal error |
188
- | 7 Persist compaction | session manager append path | `ContextCompactionResult` | New append-only `context_compaction` entry |
189
- | 8 Rebuild active context | `buildSessionContext` | Branch plus all logical deletion filters | Model messages with deleted objects omitted verbatim |
190
-
191
- #### Block 1: trigger sources
192
-
193
- ```text
194
- ┌───────────────────────────────────────────────┐
195
- │ Trigger source │
196
- ├───────────────────────────────────────────────┤
197
- │ /compact │
198
- │ fixed deletion-only prompt │
199
- │ │
200
- │ Auto threshold / provider overflow │
201
- │ if contextTokens > contextWindow - reserve │
202
- │ │
203
- │ Extension ctx.compact() │
204
- │ optional compression parameters │
205
- └───────────────────────────────────────────────┘
206
- ```
207
-
208
- All triggers produce the same `ContextDeletionTarget[]` shape and append the same `context_compaction` entry type.
209
-
210
- #### Block 2: transcript preparation
211
-
212
- ```text
213
- append-only SessionEntry branch
214
-
215
- │ Example branch path:
216
-
217
- │ entry-0 system/header context
218
- │ entry-1 user task
219
- │ entry-2 assistant with toolCall(call-a)
220
- │ entry-3 toolResult(call-a)
221
- │ entry-4 assistant note
222
- │ entry-5 context_compaction ← old logical deletion filters
223
- │ entry-6 user clarification
224
- │ entry-7 recent assistant
225
-
226
-
227
- ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
228
- │ A. Accumulate prior deletion filters │
229
- │ │
230
- │ Prior context_compaction entries are interpreted as filters: │
231
- │ deletedEntries = Set<entryId> │
232
- │ deletedContentBlocks = Map<entryId, Set<blockIndex>> │
233
- │ │
234
- │ Disk is append-only. Old entries remain in JSONL. They are only hidden from active context. │
235
- └──────────────────────────────────────────────────────────────────────────────────────────────┘
236
-
237
-
238
- ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
239
- │ B. Build filtered path │
240
- │ │
241
- │ entry deletion → remove that SessionEntry from the compactable path │
242
- │ content_block → keep the SessionEntry, but omit selected content blocks │
243
- │ context_compaction → do not include as a model message │
244
- │ excludeFromContext → omit from compactable transcript │
245
- └──────────────────────────────────────────────────────────────────────────────────────────────┘
246
-
247
-
248
- ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
249
- │ C. Mark entries that validation will not delete │
250
- │ │
251
- │ protected = true when any of these are true: │
252
- │ • entry is inside the configured preserve_recent context window │
253
- │ • role is user │
254
- │ • role is custom │
255
- │ • role is branchSummary, or entryType is branch_summary │
256
- │ • assistant stopReason is error │
257
- │ • toolResult isError is true │
258
- │ • bashExecution has non-zero exitCode │
259
- └──────────────────────────────────────────────────────────────────────────────────────────────┘
260
-
261
-
262
- ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
263
- │ D. Emit CompactableTranscript │
264
- │ │
265
- │ transcript.entries[] contains one CompactableTranscriptEntry per compactable message: │
266
- │ │
267
- │ entryId stable id used in deletion targets │
268
- │ entryType message | custom_message | branch_summary | ... │
269
- │ role user | assistant | toolResult | bashExecution | custom | branchSummary │
270
- │ text searchable/readable text │
271
- │ tokenEstimate stats and manifest prioritization │
272
- │ protected validation guard bit │
273
- │ contentBlocks per-block delete targets with original blockIndex │
274
- │ message original AgentMessage for invariant checks │
275
- │ toolCallIds ids from assistant toolCall content blocks │
276
- │ toolResultFor call id answered by a toolResult entry │
277
- │ │
278
- │ transcript.protectedEntryIds records the ids protected by the active validation pass. │
279
- └──────────────────────────────────────────────────────────────────────────────────────────────┘
280
- ```
281
-
282
- #### Block 3: planner workspace
283
-
284
- ```text
285
- CompactableTranscript
286
-
287
- ├─ writeContextCompactionTranscriptFile(transcript)
288
-
289
- │ Temporary file layout:
290
-
291
- │ /tmp/atomic-context-transcript-*/transcript.jsonl
292
-
293
- │ line 1: { entryId, role, protected, tokenEstimate, text, contentBlocks, ... }
294
- │ line 2: { entryId, role, protected, tokenEstimate, text, contentBlocks, ... }
295
- │ ...
296
-
297
- │ The full transcript text lives here, not in the prompt.
298
-
299
- └─ buildContextCompactionPrompt(transcript, transcriptFilePath)
300
-
301
- Prompt body
302
- ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
303
- │ Planner guardrails │
304
- │ • context_delete is id-only: kind, entryId, and optional blockIndex. │
305
- │ • context_grep_delete may use a concise content pattern, never full block bodies. │
306
- │ • No-summary/no-paraphrase wording prevents legacy replacement-context behavior. │
307
- │ • Atomic ignores final prose as a deletion plan; validated tool state is the result. │
308
- ├──────────────────────────────────────────────────────────────────────────────────────────────┤
309
- │ Strategy │
310
- │ • Aggressively compact/remove blocks. │
311
- │ • Start with context_compaction_budget to inspect window fullness and reduction target. │
312
- │ • Spend a few turns exploring with search/read tools to gain high confidence of candidate │
313
- │ blocks to remove. │
314
- │ • Prefer high-confidence exploit actions after that: delete obvious low-value entries via │
315
- │ context_grep_delete or context_delete. │
316
- │ • Check context_compaction_budget after deletion batches. │
317
- │ • Treat compression_ratio as strict for the standard planner pass: default 0.5 means keep │
318
- │ 50% / delete 50%. │
319
- │ • If the strict target is not met, continue deleting low-value entries/content blocks until │
320
- │ the planner reaches the target, reaches the auto-compaction budget fallback, or stops. │
321
- │ • Converge quickly; do not keep reading once safe deletion targets are clear. │
322
- ├──────────────────────────────────────────────────────────────────────────────────────────────┤
323
- │ Transcript file path │
324
- │ The planner can search/read slices through tools instead of loading the whole JSONL file. │
325
- ├──────────────────────────────────────────────────────────────────────────────────────────────┤
326
- │ Manifest │
327
- │ • max 80 entries │
328
- │ • entries selected by largest tokenEstimate │
329
- │ • sorted back into transcript order │
330
- │ • previews truncated to 240 chars │
331
- └──────────────────────────────────────────────────────────────────────────────────────────────┘
332
- ```
333
-
334
- #### Block 4: transcript-bound tool loop
335
-
336
- ```text
337
- ┌────────────────────────────────────┐
338
- │ ContextDeletionMemoryStore │
339
- ├────────────────────────────────────┤
340
- │ deletionTargets: [] │
341
- │ callCount: 0 │
342
- │ lastError: undefined │
343
- │ immutable entry rows │
344
- │ immutable content-block rows │
345
- └────────────────────────────────────┘
346
-
347
- │ serialized transaction
348
-
349
- ┌──────────────────────────────┐ ┌──────────────┴──────────────┐ ┌──────────────────────────────┐
350
- │ Inspection tools │ │ Mutation tools │ │ Planner continuation │
351
- ├──────────────────────────────┤ ├─────────────────────────────┤ ├──────────────────────────────┤
352
- │ context_search_transcript │ │ context_delete │ │ Every tool result has │
353
- │ search entry/block text │ │ exact targets │ │ terminate: false. │
354
- │ no mutation │ │ │ │ │
355
- │ context_read_entry │ │ context_grep_delete │ │ The planner can respond with │
356
- │ read bounded text slice │ │ guarded bulk targets │ │ more tool calls, or stop. │
357
- │ no mutation │ │ │ │ │
358
- │ context_compaction_budget │ │ Both route through │ │ Final assistant prose is │
359
- │ window fullness + target │ │ validateContextDeletionRequest│ │ ignored for deletion targets. │
360
- └──────────────────────────────┘ └─────────────────────────────┘ └──────────────────────────────┘
361
- ```
362
-
363
- Mutation tool transaction shape:
364
-
365
- ```text
366
- ┌─────────────────────────────────────────────────────────────────────┐
367
- │ context_delete / context_grep_delete │
368
- └─────────────────────────────────────────────────────────────────────┘
369
-
370
- ├─ snapshot current store
371
- ├─ increment callCount
372
- ├─ build candidate ContextDeletionTarget[]
373
- │ context_delete payload is id-only: { kind, entryId, blockIndex? }
374
- │ context_grep_delete payload uses a concise pattern selector
375
- ├─ validate incoming targets
376
- ├─ merge with existing store.deletionTargets
377
- ├─ validate merged cumulative plan
378
-
379
- ├─ ✓ success
380
- │ ├─ replace store.deletionTargets with reconciled targets
381
- │ ├─ clear lastError
382
- │ └─ return { content: success text, details: stats, terminate: false }
383
-
384
- └─ ✗ failure
385
- ├─ restore snapshot
386
- ├─ set lastError to exact validation message
387
- └─ return { content: correction text, details.error, terminate: false }
388
- ```
389
-
390
- #### Block 5: validation airlock
391
-
392
- ```text
393
- Candidate cumulative deletion request
394
-
395
-
396
- ┌─────────────────────────────────────────────────────────────────────┐
397
- │ Gate 0: request and target shape │
398
- │ request object with deletions[]; each target is an id-only object │
399
- │ with a valid kind and known, non-empty entryId │
400
- └─────────────────────────────────────────────────────────────────────┘
401
-
402
-
403
- ┌─────────────────────────────────────────────────────────────────────┐
404
- │ Gate 1: recent-context guard │
405
- │ requested targets in the effective recent window are rejected │
406
- │ (critical/deterministic overflow uses max(preserve_recent, 5)) │
407
- └─────────────────────────────────────────────────────────────────────┘
408
-
409
-
410
- ┌─────────────────────────────────────────────────────────────────────┐
411
- │ Gate 2: protected target guard │
412
- │ requested disallowed entries/blocks are rejected │
413
- └─────────────────────────────────────────────────────────────────────┘
414
-
415
-
416
- ┌─────────────────────────────────────────────────────────────────────┐
417
- │ Gate 3: content-block details │
418
- │ valid integer blockIndex, block exists, not the only block │
419
- └─────────────────────────────────────────────────────────────────────┘
420
-
421
-
422
- ┌─────────────────────────────────────────────────────────────────────┐
423
- │ Gate 4: duplicate targets │
424
- │ duplicate entry/block targets are rejected │
425
- └─────────────────────────────────────────────────────────────────────┘
426
-
427
-
428
- ┌─────────────────────────────────────────────────────────────────────┐
429
- │ Gate 5: tool-call/tool-result reconciliation │
430
- │ repair paired call/result deletion dependencies when safe │
431
- │ and reject repair across protected or effective recent boundaries │
432
- └─────────────────────────────────────────────────────────────────────┘
433
-
434
-
435
- ┌─────────────────────────────────────────────────────────────────────┐
436
- │ Gate 6: post-reconciliation recent-context guard │
437
- │ reject any recent target introduced by dependency reconciliation │
438
- └─────────────────────────────────────────────────────────────────────┘
439
-
440
-
441
- ┌─────────────────────────────────────────────────────────────────────┐
442
- │ Gate 7: post-reconciliation thinking-bearing assistant block guard │
443
- │ a retained assistant containing thinking/redacted_thinking cannot │
444
- │ have any individual content block deleted │
445
- └─────────────────────────────────────────────────────────────────────┘
446
-
447
-
448
- ┌─────────────────────────────────────────────────────────────────────┐
449
- │ Gate 8: post-reconciliation signed-turn integrity guard │
450
- │ retain every signed-thinking assistant in the active turn; in a │
451
- │ historical turn retain all signed assistants or omit all of them │
452
- └─────────────────────────────────────────────────────────────────────┘
453
-
454
-
455
- ┌─────────────────────────────────────────────────────────────────────┐
456
- │ Gate 9: structural integrity │
457
- │ no entry/block overlap, all-block deletion by blocks, or orphaned │
458
- │ tool result/dangling tool call │
459
- └─────────────────────────────────────────────────────────────────────┘
460
-
461
-
462
- ┌─────────────────────────────────────────────────────────────────────┐
463
- │ Gate 10: context survival │
464
- │ at least one entry and one provider-visible task entry remain │
465
- │ (user, custom, branchSummary, or branch_summary) │
466
- └─────────────────────────────────────────────────────────────────────┘
467
-
468
-
469
- ┌─────────────────────────────────────────────────────────────────────┐
470
- │ Gate 11: stats │
471
- │ compute objectsBefore, objectsDeleted, tokensBefore, tokensAfter, │
472
- │ and percentReduction │
473
- └─────────────────────────────────────────────────────────────────────┘
474
-
475
-
476
- ValidatedContextDeletionResult
477
- ```
478
-
479
- #### Block 6: dependency repair as a block diagram
81
+ `reserveTokens` controls the automatic threshold that decides when compaction runs; it is not converted into a classifier line ratio. Manual calls can pass parameter overrides through the SDK.
480
82
 
481
- ```text
482
- Normal model-visible pairing
483
-
484
- ┌─────────────────────────────────────────┐ toolCallId ┌────────────────────────────┐
485
- │ assistant entry │────────────────────────▶│ toolResult entry │
486
- │ content block: { type: toolCall, id } │ │ toolResultFor = id │
487
- └─────────────────────────────────────────┘ └────────────────────────────┘
488
-
489
- If the assistant tool-call block is deleted:
490
-
491
- ┌─────────────────────────────────────────┐ ┌────────────────────────────┐
492
- │ assistant tool-call block deleted │──────── requires ──────▶│ paired result deleted │
493
- └─────────────────────────────────────────┘ └────────────────────────────┘
494
- │ │
495
- └─ if paired result is not deletable │
496
- validation removes/rejects the unsafe call deletion │
497
-
498
- If the tool result is deleted:
499
-
500
- ┌─────────────────────────────────────────┐ ┌────────────────────────────┐
501
- │ paired call deleted │◀────── requires ───────│ toolResult entry deleted │
502
- └─────────────────────────────────────────┘ └────────────────────────────┘
503
- │ │
504
- └─ if paired call is not deletable │
505
- validation removes/rejects the unsafe result deletion │
506
-
507
- Standard recent boundary case:
508
-
509
- ┌──────────────────────────────┐ repair would delete ┌──────────────────────────────┐
510
- │ old side of pair requested │────────────────────────────────▶│ preserve_recent side of pair │
511
- └──────────────────────────────┘ └──────────────────────────────┘
512
-
513
-
514
- explicit correction error
515
- "Cannot delete recent context entry ..."
516
- ```
517
-
518
- #### Block 7: persistence and rebuild
519
-
520
- ```text
521
- ValidatedContextDeletionResult
522
-
523
- ├─ deletedTargets
524
- │ [{ kind: "entry", entryId }, { kind: "content_block", entryId, blockIndex }]
525
-
526
- ├─ protectedEntryIds
527
- │ snapshot of ids protected by the validation pass that produced the result
528
- │ (critical overflow excludes entries deliberately relaxed for eviction)
529
- └─ stats
530
- object and token reduction estimate
531
-
532
-
533
- ┌─────────────────────────────────────────────────────────────────────┐
534
- │ Persist │
535
- │ 1. write .compact.bak for persisted sessions when available │
536
- │ 2. append one context_compaction SessionEntry │
537
- │ 3. emit session_compact event │
538
- └─────────────────────────────────────────────────────────────────────┘
539
-
540
-
541
- ┌─────────────────────────────────────────────────────────────────────┐
542
- │ Future buildSessionContext │
543
- │ 1. walk branch path │
544
- │ 2. accumulate all context_compaction filters │
545
- │ 3. omit deleted entries │
546
- │ 4. clone messages with deleted content blocks removed │
547
- │ 5. preserve surviving message objects and content blocks verbatim │
548
- │ 6. repair unsafe signed-turn and retained-message block filters │
549
- │ 7. retain paired tool results for restored tool-call blocks │
550
- └─────────────────────────────────────────────────────────────────────┘
551
- ```
552
-
553
- #### Failure paths
554
-
555
- | Failure path | State mutation | What the planner or caller sees |
556
- |--------------|----------------|----------------------------------|
557
- | `context_delete` validation error | Store rolls back to previous deletion targets | Non-terminating correction tool result with exact error |
558
- | `context_grep_delete` regex/pattern error | Store rolls back to previous deletion targets | Non-terminating correction tool result with exact error |
559
- | `context_grep_delete` protected/recent match | Matching protected target is ignored and not counted as a deletion | Non-protected matches still apply when validation succeeds |
560
- | Manual planner stops below the strict `compression_ratio` target | Nothing persisted | Manual compaction fails with achieved reduction, deletion count, and tokens-after details |
561
- | Threshold auto-compaction stops below the strict target but deletes at least one target and projected `tokensAfter` is at or below `effectiveInputBudget - reserveTokens` | Validated deletion targets are persisted | Tier 2 accepts the feasible result so threshold compaction does not immediately re-trigger |
562
- | Threshold auto-compaction stops below the strict target and still exceeds the trigger boundary | Nothing persisted | Auto-compaction fails; threshold compaction never escalates to protected-entry eviction |
563
- | Threshold auto-compaction finds no preparable compactable transcript | Nothing persisted | Silent no-op is preserved because threshold compaction is only opportunistic |
564
- | Overflow auto-compaction finds no preparable compactable transcript | Nothing persisted | Terminal overflow-recovery error states that nothing more was safely deletable instead of silently no-oping |
565
- | Overflow auto-compaction has validated deletions whose projected `tokensAfter` is at or below the model's effective input budget | Validated deletion targets are persisted | Tier 1 target-met results, Tier 2 feasible results, and provider-overflow salvage are committed only when they fit the effective input budget; target-met-but-over-budget results escalate instead of being persisted |
566
- | Overflow planner misses the strict target or meets the strict target while still exceeding the effective input budget | No persistence until a later tier succeeds | Tier 3 reruns the planner with internal `<critical-overflow-mode>` guidance, overflow-only protected-entry eligibility, and an effective recent guard of `max(preserve_recent, 5)` across provider-visible transcript entries |
567
- | Critical overflow pass cannot produce a fitting validated result, or planner auth is unavailable during overflow | No model-generated plan is persisted | Tier 4 runs deterministic code-level LRU eviction with no model call or auth requirement while enforcing the same `max(preserve_recent, 5)` recent floor across provider-visible transcript entries |
568
- | Deterministic overflow eviction exhausts its finite candidate phases without fitting the effective input budget | Nothing persisted from the failed attempt | Terminal overflow-recovery error includes achieved stats (`tokensAfter`, percent reduction, deletion-target count), the budget, and that nothing more was safely deletable |
569
- | Planner run reaches its 50 real provider-turn cap | No additional provider calls are made for that planner run | The runner evaluates the validated deletions recorded so far against the current tier's acceptance rule, then either escalates or fails terminally with achieved stats |
570
- | Planner nudge loop reaches its 50 follow-up cap | No extra follow-ups are queued for that planner run | The runner evaluates the best validated state against the current tier's acceptance rule, then either escalates or fails terminally with achieved stats |
571
- | Provider non-overflow error | Nothing persisted unless an overflow-only later tier succeeds | Error propagates for manual/threshold; overflow recovery can continue to lower tiers unless the request was aborted |
572
- | Overflow planner request itself exceeds the provider context window before producing a usable plan | No model-generated plan is persisted | Overflow auto-compaction marks both assistant state-message overflow and thrown planner/provider overflow explicitly; when no validated deletion fits the budget, it skips the critical overflow planner model call and goes straight to deterministic eviction instead of throwing or looping on planner calls |
573
- | Overflow recovery exhausts the compact-and-retry attempt without a fitting result | Nothing more is retried on the same model | The session emits `compaction_end` with `unresolvedOverflow: true`; workflow-owned `fallbackModels` can advance to the next configured model tier, and non-workflow callers see the terminal overflow-recovery error |
574
- | Extension-provided deletion request invalid | Nothing persisted | Extension/caller sees validation failure; extension-provided requests bypass the internal fallback ladder |
83
+ ## When compaction runs
575
84
 
85
+ - **Manual:** `/compact`, `ctx.compact()`, `session.compact()`, or RPC `{ "type": "compact" }`.
86
+ - **Threshold:** automatic compaction starts when estimated context usage reaches the effective input budget minus `reserveTokens`.
87
+ - **Overflow:** an actual provider context overflow compacts and then retries the interrupted turn.
576
88
 
89
+ The in-flight/final logical turn is outside the compactable region. Cancellation and abort behavior remains consistent with normal session operations. Atomic writes a backup snapshot immediately before appending a compaction boundary.
577
90
 
578
- 1. **Collect active branch context.** Atomic walks the current session branch and applies any earlier `context_compaction` logical deletions.
579
- 2. **Build a compactable transcript.** Each provider-visible compactable entry includes a stable `entryId`, role, token estimate, full text, content-block indexes, tool-call IDs, and tool-result links; omitted user/custom inputs and empty branch summaries contribute no transcript tokens or recent-window slots.
580
- 3. **Mark validation guards.** Atomic marks provider-visible user instructions, custom messages, branch/summary messages, the configured `preserve_recent` context-eligible entries, unresolved assistant/tool errors, and failed bash executions as protected in the standard transcript. If a standard planner targets one, the deletion tool returns an explicit correction error.
581
- 4. **Write a temporary transcript file.** The compaction assistant receives a compact manifest plus the path to a JSONL transcript file. It should inspect with tools instead of loading the whole transcript into prompt context.
582
- 5. **Run the standard deletion planner.** The user's currently selected model runs Atomic's fixed Verbatim Compaction prompt using the session's current model thinking level. It can search/read transcript slices and then call deletion tools. The prompt substitutes the effective compaction parameters: `compression_ratio` (fraction to keep, default `0.5`), `preserve_recent` (default `2`), and `query` (explicit or auto-detected). The target reduction is `1 - compression_ratio` and is treated as a strict completion requirement for the standard planner pass.
583
- 6. **Validate fail-closed.** Atomic validates every cumulative deletion plan locally. Unknown IDs, protected targets, duplicate/overlapping targets, empty-context plans, missing provider-visible task-bearing context, and tool-call/tool-result orphaning are rejected.
584
- 7. **Apply the auto-compaction fallback ladder when needed.** Manual compaction stops at the strict standard planner result. Threshold auto-compaction can accept a below-target result only when it has at least one validated deletion and projected `tokensAfter` is at or below `effectiveInputBudget - reserveTokens`; it never escalates to protected-entry eviction. Overflow auto-compaction commits any planner result (strict-target or below-target feasible) only when projected `tokensAfter` fits the effective input budget, then can rerun the planner in an internal critical overflow pass, and finally can use deterministic code-level LRU eviction until the effective input budget fits or no safe deletion remains. The overflow-only critical planner and deterministic eviction tiers enforce an effective recent guard of `max(preserve_recent, 5)` over provider-visible transcript entries.
585
- 8. **Save and rebuild.** Atomic writes a backup snapshot for persisted sessions, appends a `context_compaction` entry with validated targets and stats, then rebuilds the active LLM context from the filtered branch.
91
+ ## One-pass planning and failure behavior
586
92
 
587
- Deterministic eviction is finite by construction rather than by an arbitrary pass counter. It (1) batches or sweeps non-boundary groups, (2) tries repaired boundary prefixes and individual boundaries, (3) sweeps newly historical signed groups, (4) retries skipped boundaries by shared restoration component and then individually, and (5) explores alternate boundary plans. Each loop traverses a finite candidate array; the alternate phase deduplicates plans and retains at most 16 states per boundary before either finding a fitting validated plan or reporting terminal exhaustion.
93
+ Atomic asks the active session model, at the active reasoning level and through the normal session stream/provider wrapper, to rank every eligible line in one global pass and apply one threshold. The entire compactable region is sent in exactly one classifier request; it is never split into chunks. Manual, threshold, and overflow compaction all calculate the line target directly from the prepared `compression_ratio`. Explicit protected lines form a hard keep floor.
588
94
 
589
- ### Transcript-Bound Tools
95
+ The request uses the same provider path and failure handling as pi's summary compaction. Provider/API errors, overflow, abort, malformed JSON, or empty/unusable safe ranges fail after that one request. These failures write no compaction entry and schedule no continuation. There is no semantic retry, critical rung, deterministic fallback, or deterministic target correction.
590
96
 
591
- The compaction assistant can only compact by using these internal tools. Exact deletion is intentionally id-only: the planner identifies entries or content blocks, then calls `context_delete` with `kind`, `entryId`, and optional `blockIndex`. Content-based deletion goes through `context_grep_delete`, where the planner sends a concise literal or regex pattern and Atomic resolves the matching ids locally. Neither mutation path accepts full block text, replacement bodies, summaries, or rationale fields as deletion payload content.
97
+ A syntactically valid usable result is accepted once after safety-only normalization, even when it deletes fewer lines or tokens than requested. Atomic never adds or restores model-selected deletions to force a target. During overflow recovery, the existing one-shot compact-and-retry continuation may therefore surface unresolved overflow naturally.
592
98
 
593
- | Tool | Purpose |
594
- |------|---------|
595
- | `context_search_transcript` | Search entry or content-block text and return small snippets. |
596
- | `context_read_entry` | Read a bounded slice of one entry or content block. |
597
- | `context_compaction_budget` | Report context-window fullness, selected-deletion progress, `compression_ratio`, and remaining work to reach the strict reduction target. |
598
- | `context_delete` | Record exact entry/content-block deletion targets. |
599
- | `context_grep_delete` | Bulk-delete matching entries or content blocks with guardrails. |
99
+ ## Persistence and resume
600
100
 
601
- The planner is prompted to call `context_compaction_budget` before deleting and after deletion batches. The tool reports the current transcript token estimate as a percentage of the selected model's context window, the configured `compression_ratio`, the projected percentage after selected deletions, current reduction percentage, how many more estimated tokens must be removed to reach the strict target, and the image token share (`remainingImageTokens`, `imageBlockCount`, `imageTokenPercent`) so the planner can prioritize deleting stale image context when images dominate. With the default `compression_ratio: 0.5`, the strict standard planner target is a 50% token reduction. Auto-compaction can still commit a validated below-target result when the projected `tokensAfter` clears the relevant budget: threshold compaction uses the trigger boundary (`effectiveInputBudget - reserveTokens`), while overflow recovery uses the model's effective input budget. On the overflow path, strict-target results are also gated by that effective input budget before they can be committed.
602
-
603
- `context_grep_delete` supports literal or regex matching, skips already-deleted or disallowed context, enforces a per-call `maxMatches` safety cap, can require `expectedMatchCount` when the planner wants an exact-match safety check, and routes every accepted match through the same validation pipeline as exact deletions. Disallowed matches are ignored before `matches`, `expectedMatchCount`, deletion stats, and selected targets are calculated, so a broad regex can still remove safe blocks without counting rejected candidates as removed. This includes both signed-thinking guards: no content block may be removed from any retained thinking-bearing assistant message, and entry deletion must preserve the complete active/historical turn invariant described above. `maxMatches` limits only one tool call; there is no cumulative deletion cap across repeated `context_delete` or `context_grep_delete` calls. Exact deletion attempts that target disallowed entries/blocks return an explicit non-terminating tool error with correction guidance. Exact deletion payloads that include unsupported fields such as transcript `text`, block `content`, summaries, or replacement data are rejected as non-id-only requests.
604
-
605
- Tool calls are cumulative during one planner run. The assistant can apply several small deletion batches, inspect the updated state, and stop only after the validated stats meet the strict reduction target or an auto-compaction budget fallback can safely accept the current result. Atomic uses the validated tool state as the compaction result; ordinary assistant text is ignored for deletion targets. Each planner run is bounded to 50 real provider turns (including tool-call turns), and the planner nudge loop is additionally bounded to 50 follow-up nudges per planner run, so a planner that keeps making tiny changes or repeated tool calls cannot spin indefinitely.
606
-
607
- ### Validation Rules
608
-
609
- Validation preserves tool-call/tool-result consistency. If deleting a tool call would leave a tool result behind, Atomic either deletes the paired result too or rejects the plan when that would violate a validation guard. If deleting a tool result would leave a visible dangling tool call, Atomic either deletes the paired call too or rejects the plan.
610
-
611
- Atomic also refuses plans that would delete all context or leave no provider-visible task-bearing context. These checks are local; the model cannot bypass them. Provider context-overflow recovery uses the same validation rules as manual and threshold compaction. During the overflow-only critical planner pass and deterministic eviction fallback, Atomic internally enforces an effective recent guard of `max(preserve_recent, 5)` across provider-visible transcript entries, restoring the pre-#1399 last-5 floor even for otherwise-unprotected assistant/tool entries. Within that floor, deletion is rejected through the same recent-target validation used elsewhere. Outside that floor, Atomic relaxes deletion eligibility only for stale protected provider-visible task-bearing entries (`user`, `custom`, branch summary) that are not carrying assistant/tool/bash errors; deterministic eviction proposes signed-thinking entries as complete historical turn groups and excludes signed entries in the active turn. Every resulting plan still passes fail-closed validation, including the turn-level signed sequence invariant, task-bearing floor, and tool-call/result pairing.
612
-
613
- ### ContextCompactionEntry Structure
614
-
615
- Defined in [`session-manager.ts`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/session-manager.ts):
101
+ A successful run appends the existing pi-style `type:"compaction"` entry shape:
616
102
 
617
- ```typescript
618
- type ContextDeletionTarget =
619
- | { kind: "entry"; entryId: string }
620
- | { kind: "content_block"; entryId: string; blockIndex: number };
621
-
622
- interface ContextCompactionStats {
623
- objectsBefore: number;
624
- objectsAfter: number;
625
- objectsDeleted: number;
626
- tokensBefore: number;
627
- tokensAfter: number;
628
- percentReduction: number;
629
- }
630
-
631
- interface ContextCompactionEntry {
632
- type: "context_compaction";
633
- id: string;
634
- parentId: string | null;
635
- timestamp: string;
636
- promptVersion: 1;
637
- deletedTargets: ContextDeletionTarget[];
638
- protectedEntryIds: string[];
639
- stats: ContextCompactionStats;
640
- backupPath?: string;
103
+ ```json
104
+ {
105
+ "type": "compaction",
106
+ "id": "c1",
107
+ "parentId": "m9",
108
+ "timestamp": "2026-07-13T10:00:00.000Z",
109
+ "summary": "[User]: fix the failing test\n(filtered 42 lines)\n[Assistant]: Fixed.",
110
+ "firstKeptEntryId": "m7",
111
+ "tokensBefore": 51234,
112
+ "details": {
113
+ "strategy": "verbatim-lines",
114
+ "promptVersion": 3,
115
+ "rung": "planned",
116
+ "parameters": {"compression_ratio": 0.5, "preserve_recent": 2, "query": "fix the failing test"},
117
+ "stats": {"linesBefore": 812, "linesDeleted": 417, "linesKept": 395, "rangeCount": 63, "tokensBefore": 51234, "tokensAfter": 24980, "percentReduction": 51.2}
118
+ }
641
119
  }
642
120
  ```
643
121
 
644
- `deletedTargets` is the only active-context mutation. The entry records what to omit; it does not contain replacement prose.
645
-
646
- ### Verbatim Compaction Diagram
647
-
648
- Unlike legacy summary compaction, Verbatim Compaction does not add a generated summary or rewrite retained messages. It appends a `context_compaction` entry that records exactly which older transcript objects should be hidden from future active context rebuilds.
649
-
650
- ```text
651
- Before verbatim compaction:
652
-
653
- entry: 0 1 2 3 4 5 6 7
654
- ┌─────┬─────┬─────┬──────┬─────┬──────┬──────┬─────┐
655
- │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ ass │
656
- └─────┴─────┴─────┴──────┴─────┴──────┴──────┴─────┘
657
- │ │ │ │
658
- └──────┴────────────┴──────┘
659
- planner may mark low-signal old objects
660
-
661
- Validated deletion plan:
662
-
663
- delete entry 2 (older assistant text)
664
- delete entry 3 (superseded tool output)
665
- keep entries 0,1,4,5,6,7 unchanged
122
+ A `compaction` entry is active only when `details.strategy === "verbatim-lines"`. On rebuild, Atomic emits a visible custom-role boundary message containing the durable `summary`, followed by the original messages beginning at `firstKeptEntryId`. The boundary is converted to a user-role provider message and shown in the TUI as a collapsible compaction card.
666
123
 
667
- After compaction (new entry appended; JSONL remains append-only):
124
+ Resume does not rerun planning or re-derive deletions: the exact compacted string is already in JSONL. Legacy `context_compaction` logical-deletion records and old `compaction` summary records without the discriminator are inert archival data. Their historical omissions are not reapplied when an old session resumes.
668
125
 
669
- entry: 0 1 2 3 4 5 6 7 8
670
- ┌─────┬─────┬─────┬──────┬─────┬──────┬──────┬─────┬─────┐
671
- │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ ass │ ctx │
672
- └─────┴─────┴─────┴──────┴─────┴──────┴──────┴─────┴─────┘
673
- ╳ ╳ ↑
674
- logical deletions context_compaction entry
126
+ ## Extension hooks
675
127
 
676
- What the LLM sees after rebuild:
128
+ ### `session_before_compact`
677
129
 
678
- ┌────────┬─────┬─────┬──────┬──────┬─────┐
679
- │ system │ usr │ usr │ ass │ tool │ ass │
680
- └────────┴─────┴─────┴──────┴──────┴─────┘
681
- entry 1 entry 4 entry 5 entry 6 entry 7
682
-
683
- No generated summary is inserted. Every surviving entry/content block is reused
684
- verbatim; deleted objects are simply omitted from the active LLM context.
685
- ```
686
-
687
- ## Extension Hooks for Compaction
688
-
689
- Extensions can observe, cancel, or contribute exact deletion targets to the compaction pipeline. They cannot provide generated summaries.
690
-
691
- ### session_before_compact
692
-
693
- Fired before the internal deletion planner runs. Extensions can cancel compaction or provide their own validated deletion request.
130
+ Extensions may cancel or provide a complete replacement for the prepared region:
694
131
 
695
132
  ```typescript
696
- pi.on("session_before_compact", async (event, ctx) => {
697
- const { preparation, parameters, branchEntries, reason, signal } = event;
698
-
699
- // parameters.compression_ratio - fraction of compactable context to keep
700
- // parameters.preserve_recent - recent context-eligible messages kept uncompressed
701
- // parameters.query - focus query used by the planner
702
- // preparation.parameters - same effective parameters on the frozen preparation snapshot
703
- // preparation.transcript.entries - entries eligible for deletion
704
- // preparation.transcript.protectedEntryIds - entry ids validation will reject if directly deleted
705
- // preparation.transcript.tokensBefore - context token estimate before compaction
706
- // branchEntries - all entries on current branch
707
- // reason - "manual" | "threshold" | "overflow"
708
-
709
- // Cancel compaction:
710
- return { cancel: true };
133
+ pi.on("session_before_compact", async (event) => {
134
+ const { reason, parameters, preparation, branchEntries, signal } = event;
135
+ if (signal.aborted) return { cancel: true };
711
136
 
712
- // Or provide a deletion request (Atomic validates it locally before persisting):
713
- return {
714
- deletionRequest: {
715
- deletions: [
716
- { kind: "entry", entryId: "abc123" },
717
- { kind: "content_block", entryId: "def456", blockIndex: 2 },
718
- ],
719
- },
720
- };
137
+ // Optional offline override. It must contain non-whitespace text.
138
+ if (reason === "manual" && branchEntries.length > 100) {
139
+ return { compactedText: preparation.region.lines.slice(0, 40).join("\n") };
140
+ }
721
141
  });
722
142
  ```
723
143
 
724
- If `{ cancel: true }` is returned, compaction aborts with a cancellation error. If `{ deletionRequest }` is returned, Atomic validates it through the same local airlock as model-proposed deletions unknown IDs, protected targets, orphaning, and empty-context plans are rejected — and skips the internal planner. If nothing is returned, the internal planner runs normally.
144
+ `preparation` is a deep-frozen clone. An override changes only the compacted region text; Atomic retains the prepared boundary and persists the supplied text verbatim. Empty/whitespace text is rejected. The override path does not require provider credentials.
725
145
 
726
- Extension-provided deletion requests validate against the original standard transcript and bypass the internal fallback ladder, including its overflow budget-fit gate. The overflow guarantee that committed results fit the effective input budget applies to Atomic's internal ladder results; extension-supplied deletion requests remain a public hook escape hatch that commits after local fail-closed validation. Atomic does not expose a public compaction mode API; protected-entry relaxation is reserved for Atomic's own overflow recovery tiers.
146
+ ### `session_compact`
727
147
 
728
- ### session_compact
729
-
730
- Fired after compaction succeeds and the `context_compaction` entry is persisted.
731
-
732
- ```typescript
733
- pi.on("session_compact", async (event, ctx) => {
734
- // event.parameters - effective compression_ratio, preserve_recent, and query
735
- // event.result - ContextCompactionResult, including result.parameters
736
- // event.contextCompactionEntry - the saved ContextCompactionEntry
737
- // event.reason - "manual" | "threshold" | "overflow"
738
- // event.fromExtension - true if extension provided the deletionRequest
739
-
740
- const { result } = event;
741
- ctx.ui.notify(
742
- `Compaction: deleted ${result.stats.objectsDeleted} objects, ` +
743
- `${result.stats.percentReduction}% token reduction`,
744
- "info",
745
- );
746
- });
747
- ```
748
-
749
- ### ctx.compact()
750
-
751
- Trigger Verbatim Compaction without awaiting completion. See [Extensions](/extensions) for full `ctx.compact()` documentation.
148
+ After persistence, Atomic emits an observe-only event:
752
149
 
753
150
  ```typescript
754
- ctx.compact({
755
- compression_ratio: 0.3,
756
- preserve_recent: 2,
757
- query: "keep context relevant to the active bug fix",
758
- onComplete: (result) => {
759
- ctx.ui.notify(`Compacted: deleted ${result.stats.objectsDeleted} objects`, "info");
760
- },
761
- onError: (error) => {
762
- ctx.ui.notify(`Compaction failed: ${error.message}`, "error");
763
- },
151
+ pi.on("session_compact", async (event) => {
152
+ console.log(event.result.rung, event.result.stats);
153
+ console.log(event.compactionEntry.details.strategy); // "verbatim-lines"
154
+ console.log(event.fromExtension);
764
155
  });
765
156
  ```
766
157
 
767
- `ctx.compact()` accepts the same compaction parameters as hooks/settings (`compression_ratio`, `preserve_recent`, and `query`) but does not accept arbitrary custom summary instructions. Verbatim Compaction uses a fixed internal prompt; no custom summary text can be injected.
768
-
769
- See [examples/extensions/trigger-compact.ts](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/examples/extensions/trigger-compact.ts) for a full example.
158
+ Observer errors are isolated and cannot roll back the already-persisted boundary.
770
159
 
771
160
  ## Branch Summarization
772
161
 
@@ -960,75 +349,11 @@ Configure compaction in `~/.atomic/agent/settings.json` or `<project-dir>/.atomi
960
349
 
961
350
  Disable auto-compaction with `"enabled": false`. You can still compact manually with `/compact`.
962
351
 
963
- ## Legacy Summary Compaction (Retired)
352
+ ## Historical formats
964
353
 
965
- Summary compaction an earlier behavior that generated replacement prose for older context — has been removed as an active runtime path in Atomic. This section documents it for historical reference only.
354
+ Two old formats remain parseable but inactive:
966
355
 
967
- ### What it did
968
-
969
- The summary compaction pipeline:
970
- 1. Selected a cut point (user message boundary) called `firstKeptEntryId`.
971
- 2. Passed all messages before that cut point to an LLM to generate a replacement summary.
972
- 3. Appended a `CompactionEntry` with `type:"compaction"` to the session JSONL.
973
- 4. When rebuilding active context, injected a `compactionSummary` message at the boundary.
974
-
975
- ```text
976
- (Historical — no longer the active behavior)
977
-
978
- Before summary compaction:
979
-
980
- entry: 0 1 2 3 4 5 6 7 8 9
981
- ┌─────┬─────┬─────┬─────┬──────┬─────┬─────┬──────┬──────┬─────┐
982
- │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ tool │ ass │ tool│
983
- └─────┴─────┴─────┴──────┴─────┴─────┴──────┴──────┴─────┴─────┘
984
- └────────┬───────┘ └──────────────┬──────────────┘
985
- messagesToSummarize kept messages
986
-
987
- firstKeptEntryId (entry 4)
988
-
989
- After compaction (new entry appended):
990
-
991
- entry: 0 1 2 3 4 5 6 7 8 9 10
992
- ┌─────┬─────┬─────┬─────┬──────┬─────┬─────┬──────┬──────┬─────┬─────┐
993
- │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ tool │ ass │ tool│ cmp │
994
- └─────┴─────┴─────┴──────┴─────┴─────┴──────┴──────┴─────┴─────┴─────┘
995
- └──────────┬──────┘ └──────────────────────┬───────────────────┘
996
- not sent to LLM sent to LLM
997
-
998
- starts from firstKeptEntryId
999
-
1000
- What the LLM saw:
1001
-
1002
- ┌────────┬─────────┬─────┬─────┬──────┬──────┬─────┬──────┐
1003
- │ system │ summary │ usr │ ass │ tool │ tool │ ass │ tool │
1004
- └────────┴─────────┴─────┴─────┴──────┴──────┴─────┴──────┘
1005
- ↑ ↑ └─────────────────┬────────────────┘
1006
- prompt from cmp messages from firstKeptEntryId
1007
- ```
1008
-
1009
- ### Why it was removed
1010
-
1011
- The core problem: a generated summary can paraphrase or omit exact file paths (`src/auth/middleware.ts:87`), commands (`npm run build -- --watch`), error strings, and line numbers. For coding agents, this loss of precision frequently causes confusion and regressions. Verbatim Compaction is honest: what remains is unchanged, and what was deleted is recorded.
1012
-
1013
- See [Verbatim vs. Summary Compaction](#verbatim-vs-summary-compaction) for the full comparison.
1014
-
1015
- ### Historical entry types
1016
-
1017
- `type:"compaction"` JSONL lines may exist in sessions created before the removal. They remain readable on disk and visible in session exports, but Atomic does not inject them as active LLM context. If you encounter sessions with these entries, they are safe to leave in place.
1018
-
1019
- `type:"compaction"` entry structure (historical):
1020
- ```typescript
1021
- interface CompactionEntry {
1022
- type: "compaction";
1023
- id: string;
1024
- parentId: string | null;
1025
- timestamp: string;
1026
- summary: string; // generated replacement prose
1027
- firstKeptEntryId: string; // cut point boundary
1028
- tokensBefore: number;
1029
- fromHook?: boolean;
1030
- details?: unknown;
1031
- }
1032
- ```
356
+ - `type:"context_compaction"` records store logical entry/content-block deletion targets from older versions. Those records are inert, so content they once hid can re-enter context when an old session resumes.
357
+ - `type:"compaction"` without `details.strategy: "verbatim-lines"` stored generated summary prose. Those records also remain inert.
1033
358
 
1034
- This entry type is no longer produced by Atomic. Extension hooks that returned `{ compaction: { summary, firstKeptEntryId, tokensBefore } }` no longer have effect; update extensions to use the new `{ cancel: true }` or `{ deletionRequest }` hook returns instead.
359
+ Both are distinguished from active boundaries by the discriminated `details` on the shared `CompactionEntry` shape; the session format version is the same for all of them.