@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.
- package/CHANGELOG.md +28 -0
- package/dist/builtin/cursor/CHANGELOG.md +6 -0
- package/dist/builtin/cursor/package.json +2 -2
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +6 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +2 -0
- package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +7 -1
- package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +2 -0
- package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +8 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +2 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +2 -0
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +6 -0
- package/dist/builtin/subagents/src/shared/types-config.ts +4 -0
- package/dist/builtin/subagents/src/shared/types-depth.ts +29 -2
- package/dist/builtin/web-access/CHANGELOG.md +6 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +22 -0
- package/dist/builtin/workflows/README.md +17 -8
- package/dist/builtin/workflows/builtin/goal-prompts.ts +8 -2
- package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +26 -9
- package/dist/builtin/workflows/builtin/ralph-forked-prompts.ts +1 -1
- package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +8 -3
- package/dist/builtin/workflows/builtin/ralph-runner.ts +2 -0
- package/dist/builtin/workflows/builtin/shared-prompts.ts +24 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/durable/backend.ts +53 -15
- package/dist/builtin/workflows/src/durable/completed-catalog.ts +245 -0
- package/dist/builtin/workflows/src/durable/completed-inspection.ts +213 -0
- package/dist/builtin/workflows/src/durable/dbos-backend.ts +120 -170
- package/dist/builtin/workflows/src/durable/dbos-envelope.ts +84 -8
- package/dist/builtin/workflows/src/durable/dbos-metadata.ts +98 -0
- package/dist/builtin/workflows/src/durable/dbos-tombstone.ts +27 -0
- package/dist/builtin/workflows/src/durable/factory.ts +1 -1
- package/dist/builtin/workflows/src/durable/file-backend.ts +247 -241
- package/dist/builtin/workflows/src/durable/file-lock.ts +153 -0
- package/dist/builtin/workflows/src/durable/file-state.ts +104 -0
- package/dist/builtin/workflows/src/durable/format-version.ts +12 -0
- package/dist/builtin/workflows/src/durable/index.ts +12 -0
- package/dist/builtin/workflows/src/durable/resume-catalog.ts +16 -27
- package/dist/builtin/workflows/src/durable/resume-eligibility.ts +20 -0
- package/dist/builtin/workflows/src/durable/resume-runtime.ts +29 -29
- package/dist/builtin/workflows/src/durable/scoped-backend.ts +20 -3
- package/dist/builtin/workflows/src/durable/stage-primitive.ts +29 -8
- package/dist/builtin/workflows/src/durable/types.ts +3 -0
- package/dist/builtin/workflows/src/engine/primitives/task.ts +1 -0
- package/dist/builtin/workflows/src/engine/run.ts +14 -14
- package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +39 -9
- package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +10 -0
- package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +133 -0
- package/dist/builtin/workflows/src/extension/runtime.ts +15 -40
- package/dist/builtin/workflows/src/extension/wiring.ts +9 -6
- package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +226 -0
- package/dist/builtin/workflows/src/extension/workflow-prompts.ts +1 -0
- package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +66 -112
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +5 -5
- package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +16 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +50 -43
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-output.ts +91 -0
- package/dist/builtin/workflows/src/runs/foreground/executor-direct.ts +95 -46
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +3 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-task-prompts.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +3 -0
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-options.ts +36 -7
- package/dist/builtin/workflows/src/runs/shared/worktree-cache-lifecycle.ts +25 -0
- package/dist/builtin/workflows/src/runs/shared/worktree-cwd.ts +103 -0
- package/dist/builtin/workflows/src/runs/shared/worktree-generation.ts +57 -0
- package/dist/builtin/workflows/src/runs/shared/worktree-git.ts +134 -8
- package/dist/builtin/workflows/src/runs/shared/worktree.ts +2 -0
- package/dist/builtin/workflows/src/shared/resumable-workflow-notices.ts +43 -0
- package/dist/builtin/workflows/src/shared/timing.ts +4 -0
- package/dist/builtin/workflows/src/shared/types.ts +5 -3
- package/dist/builtin/workflows/src/tui/graph-view-constants.ts +1 -0
- package/dist/builtin/workflows/src/tui/graph-view-input.ts +24 -14
- package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +43 -13
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +5 -7
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-compaction.d.ts +6 -34
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +95 -233
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-message-queue.d.ts +0 -4
- package/dist/core/agent-session-message-queue.d.ts.map +1 -1
- package/dist/core/agent-session-message-queue.js +1 -5
- package/dist/core/agent-session-message-queue.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +5 -6
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +2 -12
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +1 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction-boundary.d.ts +9 -0
- package/dist/core/compaction/compaction-boundary.d.ts.map +1 -0
- package/dist/core/compaction/compaction-boundary.js +115 -0
- package/dist/core/compaction/compaction-boundary.js.map +1 -0
- package/dist/core/compaction/compaction-parameters.d.ts +5 -0
- package/dist/core/compaction/compaction-parameters.d.ts.map +1 -0
- package/dist/core/compaction/compaction-parameters.js +27 -0
- package/dist/core/compaction/compaction-parameters.js.map +1 -0
- package/dist/core/compaction/compaction-runner.d.ts +14 -0
- package/dist/core/compaction/compaction-runner.d.ts.map +1 -0
- package/dist/core/compaction/compaction-runner.js +29 -0
- package/dist/core/compaction/compaction-runner.js.map +1 -0
- package/dist/core/compaction/compaction-types.d.ts +79 -0
- package/dist/core/compaction/compaction-types.d.ts.map +1 -0
- package/dist/core/compaction/compaction-types.js +6 -0
- package/dist/core/compaction/compaction-types.js.map +1 -0
- package/dist/core/compaction/deleted-ranges.d.ts +6 -0
- package/dist/core/compaction/deleted-ranges.d.ts.map +1 -0
- package/dist/core/compaction/deleted-ranges.js +134 -0
- package/dist/core/compaction/deleted-ranges.js.map +1 -0
- package/dist/core/compaction/index.d.ts +7 -1
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +7 -1
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/range-planner.d.ts +21 -0
- package/dist/core/compaction/range-planner.d.ts.map +1 -0
- package/dist/core/compaction/range-planner.js +145 -0
- package/dist/core/compaction/range-planner.js.map +1 -0
- package/dist/core/compaction/transcript-serialization.d.ts +11 -0
- package/dist/core/compaction/transcript-serialization.d.ts.map +1 -0
- package/dist/core/compaction/transcript-serialization.js +104 -0
- package/dist/core/compaction/transcript-serialization.js.map +1 -0
- package/dist/core/extensions/context-types.d.ts +2 -2
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/event-results.d.ts +2 -2
- package/dist/core/extensions/event-results.d.ts.map +1 -1
- package/dist/core/extensions/event-results.js.map +1 -1
- package/dist/core/extensions/session-events.d.ts +7 -7
- package/dist/core/extensions/session-events.d.ts.map +1 -1
- package/dist/core/extensions/session-events.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/messages.d.ts +4 -0
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +11 -0
- package/dist/core/messages.js.map +1 -1
- package/dist/core/provider-context-usage.d.ts.map +1 -1
- package/dist/core/provider-context-usage.js +1 -2
- package/dist/core/provider-context-usage.js.map +1 -1
- package/dist/core/session-manager-archive.d.ts +2 -1
- package/dist/core/session-manager-archive.d.ts.map +1 -1
- package/dist/core/session-manager-archive.js +2 -2
- package/dist/core/session-manager-archive.js.map +1 -1
- package/dist/core/session-manager-classification.d.ts +9 -0
- package/dist/core/session-manager-classification.d.ts.map +1 -0
- package/dist/core/session-manager-classification.js +37 -0
- package/dist/core/session-manager-classification.js.map +1 -0
- package/dist/core/session-manager-core.d.ts +4 -4
- package/dist/core/session-manager-core.d.ts.map +1 -1
- package/dist/core/session-manager-core.js +13 -8
- package/dist/core/session-manager-core.js.map +1 -1
- package/dist/core/session-manager-entries.d.ts +4 -3
- package/dist/core/session-manager-entries.d.ts.map +1 -1
- package/dist/core/session-manager-entries.js +12 -10
- package/dist/core/session-manager-entries.js.map +1 -1
- package/dist/core/session-manager-history.d.ts +6 -23
- package/dist/core/session-manager-history.d.ts.map +1 -1
- package/dist/core/session-manager-history.js +23 -256
- package/dist/core/session-manager-history.js.map +1 -1
- package/dist/core/session-manager-list.d.ts.map +1 -1
- package/dist/core/session-manager-list.js +3 -3
- package/dist/core/session-manager-list.js.map +1 -1
- package/dist/core/session-manager-storage.d.ts +1 -1
- package/dist/core/session-manager-storage.d.ts.map +1 -1
- package/dist/core/session-manager-storage.js +3 -2
- package/dist/core/session-manager-storage.js.map +1 -1
- package/dist/core/session-manager-types.d.ts +14 -15
- package/dist/core/session-manager-types.d.ts.map +1 -1
- package/dist/core/session-manager-types.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +1 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/main-session.d.ts +1 -0
- package/dist/main-session.d.ts.map +1 -1
- package/dist/main-session.js +7 -0
- package/dist/main-session.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -2
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +4 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +12 -22
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.js +5 -11
- package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.js +3 -0
- package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.d.ts +1 -0
- package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.js +1 -0
- package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-utils.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-utils.js +1 -1
- package/dist/modes/interactive/components/chat-session-host-utils.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.js +1 -0
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/components/compaction-boundary-message.d.ts +20 -0
- package/dist/modes/interactive/components/compaction-boundary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/compaction-boundary-message.js +48 -0
- package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -0
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-list.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-list.js +3 -0
- package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +3 -47
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +2 -2
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +5 -3
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.js +21 -12
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +3 -5
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +1 -6
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.js +0 -4
- package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +2 -11
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/compaction.md +97 -772
- package/docs/extensions.md +25 -29
- package/docs/json.md +2 -2
- package/docs/rpc.md +32 -24
- package/docs/sdk.md +3 -3
- package/docs/session-format.md +49 -30
- package/docs/sessions.md +5 -3
- package/docs/settings.md +14 -4
- package/docs/usage.md +1 -1
- package/docs/workflows.md +30 -15
- package/examples/extensions/custom-compaction.ts +14 -58
- package/examples/extensions/handoff.ts +2 -3
- package/npm-shrinkwrap.json +23 -23
- package/package.json +2 -2
- package/dist/core/compaction/context-assistant-turns.d.ts +0 -42
- package/dist/core/compaction/context-assistant-turns.d.ts.map +0 -1
- package/dist/core/compaction/context-assistant-turns.js +0 -87
- package/dist/core/compaction/context-assistant-turns.js.map +0 -1
- package/dist/core/compaction/context-compaction-critical.d.ts +0 -15
- package/dist/core/compaction/context-compaction-critical.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-critical.js +0 -57
- package/dist/core/compaction/context-compaction-critical.js.map +0 -1
- package/dist/core/compaction/context-compaction-eviction-alternates.d.ts +0 -18
- package/dist/core/compaction/context-compaction-eviction-alternates.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-eviction-alternates.js +0 -186
- package/dist/core/compaction/context-compaction-eviction-alternates.js.map +0 -1
- package/dist/core/compaction/context-compaction-eviction.d.ts +0 -12
- package/dist/core/compaction/context-compaction-eviction.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-eviction.js +0 -222
- package/dist/core/compaction/context-compaction-eviction.js.map +0 -1
- package/dist/core/compaction/context-compaction-metrics.d.ts +0 -28
- package/dist/core/compaction/context-compaction-metrics.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-metrics.js +0 -107
- package/dist/core/compaction/context-compaction-metrics.js.map +0 -1
- package/dist/core/compaction/context-compaction-prompt.d.ts +0 -9
- package/dist/core/compaction/context-compaction-prompt.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-prompt.js +0 -163
- package/dist/core/compaction/context-compaction-prompt.js.map +0 -1
- package/dist/core/compaction/context-compaction-runner.d.ts +0 -11
- package/dist/core/compaction/context-compaction-runner.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-runner.js +0 -273
- package/dist/core/compaction/context-compaction-runner.js.map +0 -1
- package/dist/core/compaction/context-compaction-strategy.d.ts +0 -5
- package/dist/core/compaction/context-compaction-strategy.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-strategy.js +0 -27
- package/dist/core/compaction/context-compaction-strategy.js.map +0 -1
- package/dist/core/compaction/context-compaction-types.d.ts +0 -75
- package/dist/core/compaction/context-compaction-types.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-types.js +0 -6
- package/dist/core/compaction/context-compaction-types.js.map +0 -1
- package/dist/core/compaction/context-compaction.d.ts +0 -10
- package/dist/core/compaction/context-compaction.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction.js +0 -8
- package/dist/core/compaction/context-compaction.js.map +0 -1
- package/dist/core/compaction/context-deletion-application.d.ts +0 -14
- package/dist/core/compaction/context-deletion-application.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-application.js +0 -261
- package/dist/core/compaction/context-deletion-application.js.map +0 -1
- package/dist/core/compaction/context-deletion-store.d.ts +0 -78
- package/dist/core/compaction/context-deletion-store.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-store.js +0 -162
- package/dist/core/compaction/context-deletion-store.js.map +0 -1
- package/dist/core/compaction/context-deletion-targets.d.ts +0 -43
- package/dist/core/compaction/context-deletion-targets.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-targets.js +0 -292
- package/dist/core/compaction/context-deletion-targets.js.map +0 -1
- package/dist/core/compaction/context-deletion-tool-definitions.d.ts +0 -193
- package/dist/core/compaction/context-deletion-tool-definitions.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-tool-definitions.js +0 -98
- package/dist/core/compaction/context-deletion-tool-definitions.js.map +0 -1
- package/dist/core/compaction/context-deletion-tool-helpers.d.ts +0 -19
- package/dist/core/compaction/context-deletion-tool-helpers.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-tool-helpers.js +0 -210
- package/dist/core/compaction/context-deletion-tool-helpers.js.map +0 -1
- package/dist/core/compaction/context-deletion-tools.d.ts +0 -4
- package/dist/core/compaction/context-deletion-tools.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-tools.js +0 -403
- package/dist/core/compaction/context-deletion-tools.js.map +0 -1
- package/dist/core/compaction/context-transcript-analysis.d.ts +0 -11
- package/dist/core/compaction/context-transcript-analysis.d.ts.map +0 -1
- package/dist/core/compaction/context-transcript-analysis.js +0 -228
- package/dist/core/compaction/context-transcript-analysis.js.map +0 -1
- package/dist/core/session-manager-tool-dependencies.d.ts +0 -10
- package/dist/core/session-manager-tool-dependencies.d.ts.map +0 -1
- package/dist/core/session-manager-tool-dependencies.js +0 -133
- package/dist/core/session-manager-tool-dependencies.js.map +0 -1
- package/dist/modes/interactive/components/context-compaction-summary-message.d.ts +0 -17
- package/dist/modes/interactive/components/context-compaction-summary-message.d.ts.map +0 -1
- package/dist/modes/interactive/components/context-compaction-summary-message.js +0 -83
- package/dist/modes/interactive/components/context-compaction-summary-message.js.map +0 -1
package/docs/compaction.md
CHANGED
|
@@ -1,772 +1,161 @@
|
|
|
1
1
|
# Compaction & Branch Summarization
|
|
2
2
|
|
|
3
|
-
LLMs have
|
|
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
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
|
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
|
-
|
|
14
|
+
There is one context-compaction door: `compact`.
|
|
32
15
|
|
|
33
|
-
|
|
16
|
+
## Verbatim Line Compaction
|
|
34
17
|
|
|
35
|
-
|
|
18
|
+
### What "verbatim" means
|
|
36
19
|
|
|
37
|
-
Atomic
|
|
20
|
+
Atomic serializes the compactable part of the conversation into role-tagged lines:
|
|
38
21
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
31
|
+
The planner sees the same text numbered as `N→content` and may return only one-based, inclusive line ranges:
|
|
51
32
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- **Auditable targets**: The `context_compaction` entry records every deleted entry/content-block ID.
|
|
33
|
+
```json
|
|
34
|
+
{"d":[[2,5]]}
|
|
35
|
+
```
|
|
56
36
|
|
|
57
|
-
|
|
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
|
-
###
|
|
39
|
+
### Markers and repeated compaction
|
|
60
40
|
|
|
61
|
-
|
|
41
|
+
Each deleted span is replaced on its own line with exactly:
|
|
62
42
|
|
|
63
|
-
|
|
64
|
-
|
|
43
|
+
```text
|
|
44
|
+
(filtered N lines)
|
|
45
|
+
```
|
|
65
46
|
|
|
66
|
-
|
|
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
|
-
|
|
49
|
+
### Protected structure
|
|
69
50
|
|
|
70
|
-
|
|
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
|
-
|
|
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
|
-
|
|
55
|
+
## Parameters
|
|
75
56
|
|
|
76
|
-
|
|
57
|
+
The effective parameters appear in extension events and successful results:
|
|
77
58
|
|
|
78
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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": "
|
|
76
|
+
"query": "optional focus"
|
|
94
77
|
}
|
|
95
78
|
}
|
|
96
79
|
```
|
|
97
80
|
|
|
98
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
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
|
-
`
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
697
|
-
const {
|
|
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
|
-
//
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
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
|
-
|
|
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
|
-
|
|
146
|
+
### `session_compact`
|
|
727
147
|
|
|
728
|
-
|
|
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
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
352
|
+
## Historical formats
|
|
964
353
|
|
|
965
|
-
|
|
354
|
+
Two old formats remain parseable but inactive:
|
|
966
355
|
|
|
967
|
-
|
|
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
|
-
|
|
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.
|