@bastani/atomic 0.9.19-alpha.5 → 0.9.19-alpha.7

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 (209) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +2 -2
  3. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  4. package/dist/builtin/intercom/broker/client.ts +19 -1
  5. package/dist/builtin/intercom/index.bundle.mjs +8 -1
  6. package/dist/builtin/intercom/package.json +1 -1
  7. package/dist/builtin/mcp/package.json +1 -1
  8. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  9. package/dist/builtin/subagents/README.md +3 -1
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +7 -7
  11. package/dist/builtin/subagents/package.json +1 -1
  12. package/dist/builtin/subagents/skills/subagent/SKILL.md +3 -1
  13. package/dist/builtin/subagents/src/extension/index.bundle.mjs +2 -1
  14. package/dist/builtin/web-access/CHANGELOG.md +13 -0
  15. package/dist/builtin/web-access/README.md +31 -24
  16. package/dist/builtin/web-access/index.bundle.mjs +16121 -80
  17. package/dist/builtin/web-access/package.json +2 -1
  18. package/dist/builtin/workflows/CHANGELOG.md +15 -0
  19. package/dist/builtin/workflows/README.md +1 -1
  20. package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
  21. package/dist/builtin/workflows/builtin/{chunk-vhmnzdj9.js → chunk-1jth021m.js} +1 -1
  22. package/dist/builtin/workflows/builtin/{chunk-p8jjwfg6.js → chunk-2377r57g.js} +4 -2
  23. package/dist/builtin/workflows/builtin/{chunk-hbnwv56f.js → chunk-31j2gs7h.js} +2 -2
  24. package/dist/builtin/workflows/builtin/{chunk-n8zysf1t.js → chunk-ngkqkzej.js} +1 -1
  25. package/dist/builtin/workflows/builtin/{chunk-1nbq96fh.js → chunk-nkrafh9s.js} +1 -1
  26. package/dist/builtin/workflows/builtin/{chunk-1kx4aggw.js → chunk-wf741bv3.js} +2 -2
  27. package/dist/builtin/workflows/builtin/{chunk-t6x2d78s.js → chunk-z29qbehr.js} +1 -1
  28. package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
  29. package/dist/builtin/workflows/builtin/goal.js +3 -3
  30. package/dist/builtin/workflows/builtin/index.js +7 -7
  31. package/dist/builtin/workflows/builtin/ralph.js +3 -3
  32. package/dist/builtin/workflows/builtin/tournament.js +2 -2
  33. package/dist/builtin/workflows/package.json +1 -1
  34. package/dist/builtin/workflows/src/extension/index.bundle.mjs +339 -31
  35. package/dist/builtin/workflows/src/index.js +67 -19
  36. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -0
  37. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  38. package/dist/core/agent-session-tool-registry.js +10 -0
  39. package/dist/core/agent-session-tool-registry.js.map +1 -1
  40. package/dist/core/bash-executor.js.map +1 -1
  41. package/dist/core/tools/bash.d.ts +1 -1
  42. package/dist/core/tools/bash.d.ts.map +1 -1
  43. package/dist/core/tools/bash.js +3 -2
  44. package/dist/core/tools/bash.js.map +1 -1
  45. package/dist/core/tools/edit.d.ts +3 -0
  46. package/dist/core/tools/edit.d.ts.map +1 -1
  47. package/dist/core/tools/edit.js +91 -12
  48. package/dist/core/tools/edit.js.map +1 -1
  49. package/dist/core/tools/file-mutation-coordinator.d.ts +255 -0
  50. package/dist/core/tools/file-mutation-coordinator.d.ts.map +1 -0
  51. package/dist/core/tools/file-mutation-coordinator.js +300 -0
  52. package/dist/core/tools/file-mutation-coordinator.js.map +1 -0
  53. package/dist/core/tools/file-mutation-queue.d.ts +14 -1
  54. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  55. package/dist/core/tools/file-mutation-queue.js +15 -3
  56. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  57. package/dist/core/tools/hashline.d.ts +9 -0
  58. package/dist/core/tools/hashline.d.ts.map +1 -1
  59. package/dist/core/tools/hashline.js +12 -1
  60. package/dist/core/tools/hashline.js.map +1 -1
  61. package/dist/core/tools/index.d.ts +9 -1
  62. package/dist/core/tools/index.d.ts.map +1 -1
  63. package/dist/core/tools/index.js +67 -12
  64. package/dist/core/tools/index.js.map +1 -1
  65. package/dist/core/tools/non-minting-snapshot-store.d.ts +49 -0
  66. package/dist/core/tools/non-minting-snapshot-store.d.ts.map +1 -0
  67. package/dist/core/tools/non-minting-snapshot-store.js +64 -0
  68. package/dist/core/tools/non-minting-snapshot-store.js.map +1 -0
  69. package/dist/core/tools/powershell.d.ts +2 -2
  70. package/dist/core/tools/powershell.d.ts.map +1 -1
  71. package/dist/core/tools/powershell.js +2 -5
  72. package/dist/core/tools/powershell.js.map +1 -1
  73. package/dist/core/tools/read-document-extract.js.map +1 -1
  74. package/dist/core/tools/render-utils.js.map +1 -1
  75. package/dist/core/tools/write.d.ts +30 -1
  76. package/dist/core/tools/write.d.ts.map +1 -1
  77. package/dist/core/tools/write.js +97 -8
  78. package/dist/core/tools/write.js.map +1 -1
  79. package/dist/index.d.ts +1 -1
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js.map +1 -1
  82. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  83. package/dist/modes/interactive/components/task-live-transcript.d.ts +1 -1
  84. package/dist/modes/interactive/components/task-live-transcript.d.ts.map +1 -1
  85. package/dist/modes/interactive/components/task-live-transcript.js +19 -11
  86. package/dist/modes/interactive/components/task-live-transcript.js.map +1 -1
  87. package/dist/modes/interactive/interactive-mode-base.d.ts +1 -0
  88. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  89. package/dist/modes/interactive/interactive-mode-base.js +3 -1
  90. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  91. package/dist/modes/interactive/interactive-mode-surface.d.ts +1 -1
  92. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  93. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  94. package/dist/modes/interactive/interactive-render-chat.js +28 -4
  95. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  96. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  97. package/dist/modes/interactive/interactive-startup.js +3 -0
  98. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  99. package/dist/modes/interactive-engine/activity-watchdog.d.ts +2 -2
  100. package/dist/modes/interactive-engine/activity-watchdog.d.ts.map +1 -1
  101. package/dist/modes/interactive-engine/activity-watchdog.js.map +1 -1
  102. package/dist/modes/interactive-engine/engine-diagnostic-view.d.ts +3 -1
  103. package/dist/modes/interactive-engine/engine-diagnostic-view.d.ts.map +1 -1
  104. package/dist/modes/interactive-engine/engine-diagnostic-view.js +11 -0
  105. package/dist/modes/interactive-engine/engine-diagnostic-view.js.map +1 -1
  106. package/dist/modes/interactive-engine/isolated-runtime.js +2 -1
  107. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  108. package/dist/modes/rpc/rpc-client-process.d.ts +2 -0
  109. package/dist/modes/rpc/rpc-client-process.d.ts.map +1 -1
  110. package/dist/modes/rpc/rpc-client-process.js +23 -1
  111. package/dist/modes/rpc/rpc-client-process.js.map +1 -1
  112. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  113. package/dist/modes/rpc/rpc-client.js +20 -3
  114. package/dist/modes/rpc/rpc-client.js.map +1 -1
  115. package/dist/utils/markit.d.ts +2 -0
  116. package/dist/utils/markit.d.ts.map +1 -1
  117. package/dist/utils/markit.js +65 -5
  118. package/dist/utils/markit.js.map +1 -1
  119. package/docs/background-tasks.md +15 -11
  120. package/docs/build.md +51 -0
  121. package/docs/changelog.mdx +8 -8
  122. package/docs/compaction/reference.md +267 -0
  123. package/docs/compaction.md +36 -219
  124. package/docs/computer-use.md +35 -0
  125. package/docs/containerization.md +9 -5
  126. package/docs/custom-provider/api-reference.md +145 -0
  127. package/docs/custom-provider/oauth.md +131 -0
  128. package/docs/custom-provider/override.md +34 -0
  129. package/docs/custom-provider/registration.md +163 -0
  130. package/docs/custom-provider/streaming.md +214 -0
  131. package/docs/custom-provider.md +43 -607
  132. package/docs/development.md +87 -0
  133. package/docs/docs.json +199 -76
  134. package/docs/environment-variables.md +1 -1
  135. package/docs/extensions/api-reference.md +1001 -0
  136. package/docs/extensions/authoring.md +676 -0
  137. package/docs/extensions/events.md +793 -0
  138. package/docs/extensions/examples.md +94 -0
  139. package/docs/extensions/ui.md +470 -0
  140. package/docs/extensions.md +270 -2768
  141. package/docs/getting-started/authentication.md +55 -0
  142. package/docs/getting-started/first-session.md +172 -0
  143. package/docs/getting-started/installation.md +154 -0
  144. package/docs/getting-started/project-instructions.md +43 -0
  145. package/docs/guides/configuration.md +65 -0
  146. package/docs/guides/intercom.md +24 -0
  147. package/docs/guides/non-interactive.md +33 -0
  148. package/docs/guides/subagents.md +24 -0
  149. package/docs/guides/workflows.md +27 -0
  150. package/docs/guides.md +41 -0
  151. package/docs/index.md +13 -45
  152. package/docs/intercom/operations.md +178 -0
  153. package/docs/intercom/reference.md +146 -0
  154. package/docs/intercom.md +54 -259
  155. package/docs/json.md +17 -0
  156. package/docs/llama-cpp.md +5 -0
  157. package/docs/models/artificial-analysis-index.md +89 -0
  158. package/docs/models/evals.md +2 -2
  159. package/docs/models/model-selection.md +3 -3
  160. package/docs/models/pareto-efficiency.md +2 -2
  161. package/docs/models/reference.md +601 -0
  162. package/docs/models.md +45 -550
  163. package/docs/packages/authoring.md +88 -0
  164. package/docs/packages/reference.md +43 -0
  165. package/docs/packages.md +28 -107
  166. package/docs/programmatic.md +29 -0
  167. package/docs/prompt-templates.md +11 -0
  168. package/docs/providers/reference.md +23 -0
  169. package/docs/providers.md +10 -15
  170. package/docs/quickstart.md +44 -238
  171. package/docs/reference/cli.md +252 -0
  172. package/docs/reference.md +52 -0
  173. package/docs/rpc/examples.md +64 -0
  174. package/docs/rpc/extension-ui.md +198 -0
  175. package/docs/rpc/protocol.md +1341 -0
  176. package/docs/rpc.md +109 -1346
  177. package/docs/sdk/reference.md +1090 -0
  178. package/docs/sdk.md +56 -1002
  179. package/docs/session-format.md +2 -0
  180. package/docs/sessions.md +6 -10
  181. package/docs/settings.md +6 -45
  182. package/docs/skills/authoring.md +95 -0
  183. package/docs/skills/reference.md +60 -0
  184. package/docs/skills.md +20 -122
  185. package/docs/subagents/authoring.md +37 -0
  186. package/docs/subagents/reference.md +60 -0
  187. package/docs/subagents.md +42 -96
  188. package/docs/terminal-setup.md +1 -1
  189. package/docs/themes/reference.md +176 -0
  190. package/docs/themes.md +21 -135
  191. package/docs/tmux.md +5 -0
  192. package/docs/tools/edit.md +5 -0
  193. package/docs/tools.md +31 -0
  194. package/docs/tui/reference.md +343 -0
  195. package/docs/tui.md +23 -286
  196. package/docs/usage.md +26 -209
  197. package/docs/web-access.md +40 -0
  198. package/docs/windows.md +2 -1
  199. package/docs/workflows/api-reference.md +11 -4
  200. package/docs/workflows/authoring.md +4 -2
  201. package/docs/workflows/builtins.md +2 -2
  202. package/docs/workflows/operations.md +11 -7
  203. package/docs/workflows/reliable-design.md +21 -3
  204. package/docs/workflows/verification.md +8 -0
  205. package/examples/extensions/gondolin/index.ts +116 -148
  206. package/examples/extensions/gondolin/package.json +1 -1
  207. package/examples/extensions/ssh.ts +56 -34
  208. package/npm-shrinkwrap.json +33 -33
  209. package/package.json +4 -4
@@ -0,0 +1,267 @@
1
+ ---
2
+ title: Compaction reference
3
+ sidebarTitle: "Compaction internals"
4
+ description: Compaction parameters, persistence, extension hooks, formats, settings, and historical formats.
5
+ ---
6
+
7
+ # Compaction reference
8
+
9
+ ## Parameters
10
+
11
+ The effective parameters appear in extension events and successful results:
12
+
13
+ | Parameter | Default | Meaning |
14
+ |---|---:|---|
15
+ | `compression_ratio` | `0.5` | Fraction of compactable **lines to keep**, not a token ratio |
16
+ | `preserve_recent` | `2` | Exact number of newest context-visible messages protected client-side |
17
+ | `query` | Last visible user message | Relevance focus for deciding which older lines to retain |
18
+
19
+ `preserve_recent` counts context-visible messages without aligning the boundary to a user turn. An assistant message or tool result may therefore begin the kept tail. Because such a tail can start or end mid-turn, the kept messages are not replayed as structured message blocks: they are serialized with the same transcript grammar as the compacted region and appended to the end of the boundary string, so the whole boundary reaches the provider as one message. Serialization of the kept tail is lossless — tool results keep their full text instead of being truncated at 16k characters, and images stay attached as image blocks rather than becoming `[image]` markers — so protected content is preserved, not merely summarized. A value of `0` protects no messages and makes the entire active transcript compactable. If `query` is absent, Atomic derives it from the last visible user message.
20
+
21
+ One consequence is worth stating for Claude models that sign their reasoning. Because the kept tail is serialized into the boundary string rather than replayed as structured assistant messages, no `thinking` or `redacted_thinking` block survives a compaction boundary. Compaction therefore **intentionally resets the signed reasoning chain**: reasoning produced before a boundary is not carried across it. This is deliberate, and it is the first of the two remedies Anthropic documents for keep-tail compaction — carry the text and tool calls across, leave the thinking blocks behind — reached structurally rather than by a stripping pass. The tail's own content is unaffected: text, tool calls, and tool results cross the boundary losslessly. See [Preserved thinking and model switches](/models/reference#preserved-thinking-and-model-switches) for how Atomic handles prefix changes *between* boundaries, which is a separate mechanism.
22
+
23
+ The query is used whole and is never truncated. This matters for structured prompts: a truncated query would make section order the retention policy, because only the leading section could influence what the planner kept, and a constraint stated later in the prompt could not. Long queries are safe — an oversized planner request surfaces as an explicit provider-overflow failure rather than silent truncation — but `keepContext` tags, not query length, are the way to guarantee a span survives.
24
+
25
+ Configure defaults in `~/.atomic/agent/settings.json` or `.atomic/settings.json`:
26
+
27
+ ```json
28
+ {
29
+ "compaction": {
30
+ "enabled": true,
31
+ "reserveTokens": 16384,
32
+ "compression_ratio": 0.5,
33
+ "preserve_recent": 2,
34
+ "query": "optional focus"
35
+ }
36
+ }
37
+ ```
38
+
39
+ `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.
40
+
41
+ ### Per-model budgets
42
+
43
+ Use `compaction.modelOverrides` to set `reserveTokens` and/or `preserve_recent` for an exact `"provider/modelId"` key. For example:
44
+
45
+ ```json
46
+ {
47
+ "compaction": {
48
+ "reserveTokens": 16384,
49
+ "preserve_recent": 2,
50
+ "modelOverrides": {
51
+ "anthropic/claude-sonnet-4-5": { "reserveTokens": 32768, "preserve_recent": 4 }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ Each field falls back independently to the ordinary setting, then its built-in default. Keys are case-sensitive and do not support wildcards or reasoning suffixes. Both fields require non-negative safe integers. The active session model selects the budgets for manual, automatic, overflow, and post-tool compaction; switching models changes the next resolution, while borrowing a fallback planner does not. Explicit manual parameters take precedence over resolved defaults.
58
+
59
+ Atomic intentionally differs from upstream pi: the recent-history override is an exact message count (`preserve_recent`), not a token budget (`keepRecentTokens`). Verbatim line reconstruction, `compression_ratio`, and `query` are unchanged; the latter two and `enabled` remain ordinary settings. See [Settings](/settings#compaction) for merge and validation details.
60
+
61
+ ## Persistence and resume
62
+
63
+ A successful run appends the existing pi-style `type:"compaction"` entry shape:
64
+
65
+ ```json
66
+ {
67
+ "type": "compaction",
68
+ "id": "c1",
69
+ "parentId": "m9",
70
+ "timestamp": "2026-07-13T10:00:00.000Z",
71
+ "summary": "[User]: fix the failing test\n(filtered 42 lines)\n[Assistant]: Fixed.",
72
+ "firstKeptEntryId": "m7",
73
+ "tokensBefore": 51234,
74
+ "details": {
75
+ "strategy": "verbatim-lines",
76
+ "promptVersion": 3,
77
+ "rung": "planned",
78
+ "parameters": {"compression_ratio": 0.5, "preserve_recent": 2, "query": "fix the failing test"},
79
+ "stats": {"linesBefore": 812, "linesDeleted": 417, "linesKept": 395, "rangeCount": 63, "tokensBefore": 51234, "tokensAfter": 24980, "percentReduction": 51.2}
80
+ }
81
+ }
82
+ ```
83
+
84
+ `details.rung` is one of `"planned"` (a model ranked the lines — the session model **or** a borrowed fallback, including silent partial recovery), `"extension"` (a `session_before_compact` override), or `"fresh"` (the compactable conversation was discarded and a new context window started). `details.plannerModel` is present **only** when a borrowed fallback model ranked the lines:
85
+
86
+ ```json
87
+ "details": {
88
+ "strategy": "verbatim-lines",
89
+ "promptVersion": 3,
90
+ "rung": "planned",
91
+ "plannerModel": {"provider": "openai", "id": "gpt-5.1", "thinkingLevel": "high"}
92
+ }
93
+ ```
94
+
95
+ There is no format-version bump and no new entry type. Both `"fresh"` and `plannerModel` are additive: they are absent on every existing entry and on any compaction that used the session model, so old readers are unaffected. A `"fresh"` boundary that had to drop the `preserve_recent` tail persists `firstKeptEntryId: null`.
96
+
97
+ A `compaction` entry is active only when `details.strategy === "verbatim-lines"`. On rebuild, Atomic emits one visible custom-role boundary message: the durable `summary` with the kept tail—the entries from `firstKeptEntryId` up to the boundary—serialized and concatenated onto its end. The tail is never restored as separate assistant/tool-result blocks, so a tail that starts or ends mid-turn cannot produce out-of-order provider blocks; images inside the tail ride along as image blocks on that same boundary message. When no pre-boundary context-visible message is retained—such as with `preserve_recent: 0`—`firstKeptEntryId` is `null` and the boundary carries the `summary` alone. Messages appended after the boundary are always replayed as real messages. The boundary is converted to a user-role provider message and shown in the TUI as a collapsible compaction card.
98
+
99
+ Resume does not rerun planning or re-derive deletions: the exact compacted string and nullable tail boundary are already in JSONL. Existing records with a string `firstKeptEntryId` keep their original resume behavior. 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.
100
+
101
+ ## Extension hooks
102
+
103
+ ### `session_before_compact`
104
+
105
+ Extensions may cancel or provide a complete replacement for the prepared region:
106
+
107
+ ```typescript
108
+ pi.on("session_before_compact", async (event) => {
109
+ const { reason, parameters, preparation, branchEntries, signal } = event;
110
+ if (signal.aborted) return { cancel: true };
111
+
112
+ // Optional offline override. It must contain non-whitespace text.
113
+ if (reason === "manual" && branchEntries.length > 100) {
114
+ return { compactedText: preparation.region.lines.slice(0, 40).join("\n") };
115
+ }
116
+ });
117
+ ```
118
+
119
+ `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.
120
+
121
+ ### `session_compact`
122
+
123
+ After persistence, Atomic emits an observe-only event:
124
+
125
+ ```typescript
126
+ pi.on("session_compact", async (event) => {
127
+ console.log(event.result.rung, event.result.stats); // rung: "planned" | "extension" | "fresh"
128
+ console.log(event.result.plannerModel); // set only when a fallback model was borrowed
129
+ console.log(event.compactionEntry.details.strategy); // "verbatim-lines"
130
+ console.log(event.fromExtension);
131
+ });
132
+ ```
133
+
134
+ Observer errors are isolated and cannot roll back the already-persisted boundary.
135
+
136
+ ### `session_compact_failed`
137
+
138
+ A failed or cancelled manual, threshold, or overflow compaction emits an observe-only failure event:
139
+
140
+ ```typescript
141
+ pi.on("session_compact_failed", async (event) => {
142
+ console.log(event.reason, event.errorMessage);
143
+ console.log(event.aborted, event.willRetry, event.fromExtension);
144
+ });
145
+ ```
146
+
147
+ `errorMessage` is absent for cancellation. `fromExtension` identifies failures after a `session_before_compact` handler supplied replacement text; no compaction boundary is persisted.
148
+
149
+ ## Branch Summary Format
150
+
151
+ Branch summarization uses a structured format:
152
+
153
+ ```markdown
154
+ ## Goal
155
+ [What the user is trying to accomplish]
156
+
157
+ ## Constraints & Preferences
158
+ - [Requirements mentioned by user]
159
+
160
+ ## Progress
161
+ ### Done
162
+ - [x] [Completed tasks]
163
+
164
+ ### In Progress
165
+ - [ ] [Current work]
166
+
167
+ ### Blocked
168
+ - [Issues, if any]
169
+
170
+ ## Key Decisions
171
+ - **[Decision]**: [Rationale]
172
+
173
+ ## Next Steps
174
+ 1. [What should happen next]
175
+
176
+ ## Critical Context
177
+ - [Data needed to continue]
178
+
179
+ <read-files>
180
+ path/to/file1.ts
181
+ path/to/file2.ts
182
+ </read-files>
183
+
184
+ <modified-files>
185
+ path/to/changed.ts
186
+ </modified-files>
187
+ ```
188
+
189
+ ### Message Serialization for Branch Summaries
190
+
191
+ Before branch summarization, messages are serialized to text via [`serializeConversation()`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/compaction/utils.ts):
192
+
193
+ ```text
194
+ [User]: What they said
195
+ [Assistant thinking]: Internal reasoning
196
+ [Assistant]: Response text
197
+ [Assistant tool calls]: read(path="foo.ts"); edit(path="bar.ts", ...)
198
+ [Tool result]: Output from tool
199
+ ```
200
+
201
+ This prevents the model from treating it as a conversation to continue.
202
+
203
+ Tool results are truncated to 2000 characters during serialization. Content beyond that limit is replaced with a marker indicating how many characters were truncated.
204
+
205
+ ## Extension Hooks for Branch Summarization
206
+
207
+ ### session_before_tree
208
+
209
+ Fired before `/tree` navigation. Always fires regardless of whether user chose to summarize. Can cancel navigation or provide custom summary.
210
+
211
+ ```typescript
212
+ pi.on("session_before_tree", async (event, ctx) => {
213
+ const { preparation, signal } = event;
214
+
215
+ // preparation.targetId - where we're navigating to
216
+ // preparation.oldLeafId - current position (being abandoned)
217
+ // preparation.commonAncestorId - shared ancestor
218
+ // preparation.entriesToSummarize - entries that would be summarized
219
+ // preparation.userWantsSummary - whether user chose to summarize
220
+
221
+ // Cancel navigation entirely:
222
+ return { cancel: true };
223
+
224
+ // Provide custom summary (only used if userWantsSummary is true):
225
+ if (preparation.userWantsSummary) {
226
+ return {
227
+ summary: {
228
+ summary: "Your summary...",
229
+ details: { /* custom data */ },
230
+ }
231
+ };
232
+ }
233
+ });
234
+ ```
235
+
236
+ See `SessionBeforeTreeEvent` and `TreePreparation` in the types file.
237
+
238
+ ## Settings
239
+
240
+ Configure compaction in `~/.atomic/agent/settings.json` or `<project-dir>/.atomic/settings.json` (legacy `.pi` paths are also supported):
241
+
242
+ ```json
243
+ {
244
+ "compaction": {
245
+ "enabled": true,
246
+ "reserveTokens": 16384
247
+ }
248
+ }
249
+ ```
250
+
251
+ | Setting | Default | Description |
252
+ |---------|---------|-------------|
253
+ | `enabled` | `true` | Enable automatic Verbatim Compaction. |
254
+ | `reserveTokens` | `16384` | Tokens to reserve for the next LLM response; threshold auto-compaction starts when completed-response usage or a prospective post-tool context exceeds the model's effective input budget minus this reserve. It is an **input-side** reserve only and never caps planner output. |
255
+
256
+ Compaction has no configuration key of its own for fallback borrowing: it reuses `settings.fallbackModels`, the same ordered `provider/model[:thinkingLevel]` list that main-chat model fallback walks. With no `fallbackModels` configured, compaction behaves as before: one planner model, then either an honest failure (recoverable) or a fresh context window (load-bearing).
257
+
258
+ Disable auto-compaction with `"enabled": false`. You can still compact manually with `/compact`.
259
+
260
+ ## Historical formats
261
+
262
+ Two old formats remain parseable but inactive:
263
+
264
+ - `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.
265
+ - `type:"compaction"` without `details.strategy: "verbatim-lines"` stored generated summary prose. Those records also remain inert.
266
+
267
+ 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.
@@ -1,9 +1,18 @@
1
+ ---
2
+ title: "Context and compaction"
3
+ description: "Verbatim line compaction, when it runs, planning rungs, and branch summarization."
4
+ ---
5
+
1
6
  # Compaction & Branch Summarization
2
7
 
3
8
  LLMs have finite context windows. Atomic reduces transcript context with **verbatim line compaction** while preserving an exact count of recent context-visible messages as ordinary messages. Branch summarization is a separate, intentionally lossy feature used only when navigating away from a branch.
4
9
 
5
10
  Compaction runs entirely locally; no external compaction service is involved. It normally uses the active session model. If that model cannot rank the lines — a rate limit, a quota exhaustion, a provider error, a context overflow, or an empty plan — Atomic *borrows* the next model from your configured `fallbackModels` for that one planner request. **A configured fallback model may therefore receive the compaction transcript**, and it is sent with that provider's own credentials. Borrowing never changes the session's model or thinking level. The model only selects which lines to delete — Atomic reconstructs the retained text mechanically, so surviving lines are never rewritten.
6
11
 
12
+ ## On this page and its reference
13
+
14
+ This page covers the concepts and normal use of compaction and branch summarization. Parameters, persistence, extension hooks, formats, settings, and historical formats live in the [Compaction reference](/compaction/reference).
15
+
7
16
  ## Overview
8
17
 
9
18
  | Mechanism | Trigger | Model output | Durable result |
@@ -17,6 +26,8 @@ There is one context-compaction door: `compact`.
17
26
 
18
27
  ## Verbatim Line Compaction
19
28
 
29
+ <a id="what-verbatim-means"></a>
30
+
20
31
  ### What "verbatim" means
21
32
 
22
33
  Atomic serializes the compactable part of the conversation into role-tagged lines:
@@ -78,55 +89,11 @@ Use it for role constraints, invariants, and anything whose loss would silently
78
89
 
79
90
  ## Parameters
80
91
 
81
- The effective parameters appear in extension events and successful results:
82
-
83
- | Parameter | Default | Meaning |
84
- |---|---:|---|
85
- | `compression_ratio` | `0.5` | Fraction of compactable **lines to keep**, not a token ratio |
86
- | `preserve_recent` | `2` | Exact number of newest context-visible messages protected client-side |
87
- | `query` | Last visible user message | Relevance focus for deciding which older lines to retain |
88
-
89
- `preserve_recent` counts context-visible messages without aligning the boundary to a user turn. An assistant message or tool result may therefore begin the kept tail. Because such a tail can start or end mid-turn, the kept messages are not replayed as structured message blocks: they are serialized with the same transcript grammar as the compacted region and appended to the end of the boundary string, so the whole boundary reaches the provider as one message. Serialization of the kept tail is lossless — tool results keep their full text instead of being truncated at 16k characters, and images stay attached as image blocks rather than becoming `[image]` markers — so protected content is preserved, not merely summarized. A value of `0` protects no messages and makes the entire active transcript compactable. If `query` is absent, Atomic derives it from the last visible user message.
90
-
91
- One consequence is worth stating for Claude models that sign their reasoning. Because the kept tail is serialized into the boundary string rather than replayed as structured assistant messages, no `thinking` or `redacted_thinking` block survives a compaction boundary. Compaction therefore **intentionally resets the signed reasoning chain**: reasoning produced before a boundary is not carried across it. This is deliberate, and it is the first of the two remedies Anthropic documents for keep-tail compaction — carry the text and tool calls across, leave the thinking blocks behind — reached structurally rather than by a stripping pass. The tail's own content is unaffected: text, tool calls, and tool results cross the boundary losslessly. See [Preserved thinking and model switches](/models#preserved-thinking-and-model-switches) for how Atomic handles prefix changes *between* boundaries, which is a separate mechanism.
92
-
93
- The query is used whole and is never truncated. This matters for structured prompts: a truncated query would make section order the retention policy, because only the leading section could influence what the planner kept, and a constraint stated later in the prompt could not. Long queries are safe — an oversized planner request surfaces as an explicit provider-overflow failure rather than silent truncation — but `keepContext` tags, not query length, are the way to guarantee a span survives.
94
-
95
- Configure defaults in `~/.atomic/agent/settings.json` or `.atomic/settings.json`:
96
-
97
- ```json
98
- {
99
- "compaction": {
100
- "enabled": true,
101
- "reserveTokens": 16384,
102
- "compression_ratio": 0.5,
103
- "preserve_recent": 2,
104
- "query": "optional focus"
105
- }
106
- }
107
- ```
108
-
109
- `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.
92
+ Moved to [Compaction reference](/compaction/reference#parameters).
110
93
 
111
94
  ### Per-model budgets
112
95
 
113
- Use `compaction.modelOverrides` to set `reserveTokens` and/or `preserve_recent` for an exact `"provider/modelId"` key. For example:
114
-
115
- ```json
116
- {
117
- "compaction": {
118
- "reserveTokens": 16384,
119
- "preserve_recent": 2,
120
- "modelOverrides": {
121
- "anthropic/claude-sonnet-4-5": { "reserveTokens": 32768, "preserve_recent": 4 }
122
- }
123
- }
124
- }
125
- ```
126
-
127
- Each field falls back independently to the ordinary setting, then its built-in default. Keys are case-sensitive and do not support wildcards or reasoning suffixes. Both fields require non-negative safe integers. The active session model selects the budgets for manual, automatic, overflow, and post-tool compaction; switching models changes the next resolution, while borrowing a fallback planner does not. Explicit manual parameters take precedence over resolved defaults.
128
-
129
- Atomic intentionally differs from upstream pi: the recent-history override is an exact message count (`preserve_recent`), not a token budget (`keepRecentTokens`). Verbatim line reconstruction, `compression_ratio`, and `query` are unchanged; the latter two and `enabled` remain ordinary settings. See [Settings](/settings#compaction) for merge and validation details.
96
+ Moved to [Compaction reference](/compaction/reference#per-model-budgets).
130
97
 
131
98
  ## When compaction runs
132
99
 
@@ -244,91 +211,23 @@ Context thresholds and persisted token-reduction statistics use API-aware normal
244
211
 
245
212
  ## Persistence and resume
246
213
 
247
- A successful run appends the existing pi-style `type:"compaction"` entry shape:
248
-
249
- ```json
250
- {
251
- "type": "compaction",
252
- "id": "c1",
253
- "parentId": "m9",
254
- "timestamp": "2026-07-13T10:00:00.000Z",
255
- "summary": "[User]: fix the failing test\n(filtered 42 lines)\n[Assistant]: Fixed.",
256
- "firstKeptEntryId": "m7",
257
- "tokensBefore": 51234,
258
- "details": {
259
- "strategy": "verbatim-lines",
260
- "promptVersion": 3,
261
- "rung": "planned",
262
- "parameters": {"compression_ratio": 0.5, "preserve_recent": 2, "query": "fix the failing test"},
263
- "stats": {"linesBefore": 812, "linesDeleted": 417, "linesKept": 395, "rangeCount": 63, "tokensBefore": 51234, "tokensAfter": 24980, "percentReduction": 51.2}
264
- }
265
- }
266
- ```
267
-
268
- `details.rung` is one of `"planned"` (a model ranked the lines — the session model **or** a borrowed fallback, including silent partial recovery), `"extension"` (a `session_before_compact` override), or `"fresh"` (the compactable conversation was discarded and a new context window started). `details.plannerModel` is present **only** when a borrowed fallback model ranked the lines:
269
-
270
- ```json
271
- "details": {
272
- "strategy": "verbatim-lines",
273
- "promptVersion": 3,
274
- "rung": "planned",
275
- "plannerModel": {"provider": "openai", "id": "gpt-5.1", "thinkingLevel": "high"}
276
- }
277
- ```
278
-
279
- There is no format-version bump and no new entry type. Both `"fresh"` and `plannerModel` are additive: they are absent on every existing entry and on any compaction that used the session model, so old readers are unaffected. A `"fresh"` boundary that had to drop the `preserve_recent` tail persists `firstKeptEntryId: null`.
280
-
281
- A `compaction` entry is active only when `details.strategy === "verbatim-lines"`. On rebuild, Atomic emits one visible custom-role boundary message: the durable `summary` with the kept tail—the entries from `firstKeptEntryId` up to the boundary—serialized and concatenated onto its end. The tail is never restored as separate assistant/tool-result blocks, so a tail that starts or ends mid-turn cannot produce out-of-order provider blocks; images inside the tail ride along as image blocks on that same boundary message. When no pre-boundary context-visible message is retained—such as with `preserve_recent: 0`—`firstKeptEntryId` is `null` and the boundary carries the `summary` alone. Messages appended after the boundary are always replayed as real messages. The boundary is converted to a user-role provider message and shown in the TUI as a collapsible compaction card.
282
-
283
- Resume does not rerun planning or re-derive deletions: the exact compacted string and nullable tail boundary are already in JSONL. Existing records with a string `firstKeptEntryId` keep their original resume behavior. 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.
214
+ Moved to [Compaction reference](/compaction/reference#persistence-and-resume).
284
215
 
285
216
  ## Extension hooks
286
217
 
287
- ### `session_before_compact`
288
-
289
- Extensions may cancel or provide a complete replacement for the prepared region:
218
+ Moved to [Compaction reference](/compaction/reference#extension-hooks).
290
219
 
291
- ```typescript
292
- pi.on("session_before_compact", async (event) => {
293
- const { reason, parameters, preparation, branchEntries, signal } = event;
294
- if (signal.aborted) return { cancel: true };
295
-
296
- // Optional offline override. It must contain non-whitespace text.
297
- if (reason === "manual" && branchEntries.length > 100) {
298
- return { compactedText: preparation.region.lines.slice(0, 40).join("\n") };
299
- }
300
- });
301
- ```
220
+ ### `session_before_compact`
302
221
 
303
- `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.
222
+ Moved to [Compaction reference](/compaction/reference#session_before_compact).
304
223
 
305
224
  ### `session_compact`
306
225
 
307
- After persistence, Atomic emits an observe-only event:
308
-
309
- ```typescript
310
- pi.on("session_compact", async (event) => {
311
- console.log(event.result.rung, event.result.stats); // rung: "planned" | "extension" | "fresh"
312
- console.log(event.result.plannerModel); // set only when a fallback model was borrowed
313
- console.log(event.compactionEntry.details.strategy); // "verbatim-lines"
314
- console.log(event.fromExtension);
315
- });
316
- ```
317
-
318
- Observer errors are isolated and cannot roll back the already-persisted boundary.
226
+ Moved to [Compaction reference](/compaction/reference#session_compact).
319
227
 
320
228
  ### `session_compact_failed`
321
229
 
322
- A failed or cancelled manual, threshold, or overflow compaction emits an observe-only failure event:
323
-
324
- ```typescript
325
- pi.on("session_compact_failed", async (event) => {
326
- console.log(event.reason, event.errorMessage);
327
- console.log(event.aborted, event.willRetry, event.fromExtension);
328
- });
329
- ```
330
-
331
- `errorMessage` is absent for cancellation. `fromExtension` identifies failures after a `session_before_compact` handler supplied replacement text; no compaction boundary is persisted.
230
+ Moved to [Compaction reference](/compaction/reference#session_compact_failed).
332
231
 
333
232
  ## Branch Summarization
334
233
 
@@ -415,92 +314,33 @@ See [`collectEntriesForBranchSummary()`](https://github.com/bastani-inc/atomic/b
415
314
 
416
315
  ## Branch Summary Format
417
316
 
418
- Branch summarization uses a structured format:
419
-
420
- ```markdown
421
- ## Goal
422
- [What the user is trying to accomplish]
423
-
424
- ## Constraints & Preferences
425
- - [Requirements mentioned by user]
426
-
427
- ## Progress
428
- ### Done
429
- - [x] [Completed tasks]
317
+ Moved to [Compaction reference](/compaction/reference#branch-summary-format).
430
318
 
431
- ### In Progress
432
- - [ ] [Current work]
433
-
434
- ### Blocked
435
- - [Issues, if any]
436
-
437
- ## Key Decisions
438
- - **[Decision]**: [Rationale]
439
-
440
- ## Next Steps
441
- 1. [What should happen next]
442
-
443
- ## Critical Context
444
- - [Data needed to continue]
445
-
446
- <read-files>
447
- path/to/file1.ts
448
- path/to/file2.ts
449
- </read-files>
319
+ ### Message Serialization for Branch Summaries
450
320
 
451
- <modified-files>
452
- path/to/changed.ts
453
- </modified-files>
454
- ```
321
+ Moved to [Compaction reference](/compaction/reference#message-serialization-for-branch-summaries).
455
322
 
456
- ### Message Serialization for Branch Summaries
323
+ ## Extension Hooks for Branch Summarization
457
324
 
458
- Before branch summarization, messages are serialized to text via [`serializeConversation()`](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/src/core/compaction/utils.ts):
325
+ Moved to [Compaction reference](/compaction/reference#extension-hooks-for-branch-summarization).
459
326
 
460
- ```text
461
- [User]: What they said
462
- [Assistant thinking]: Internal reasoning
463
- [Assistant]: Response text
464
- [Assistant tool calls]: read(path="foo.ts"); edit(path="bar.ts", ...)
465
- [Tool result]: Output from tool
466
- ```
327
+ ### session_before_tree
467
328
 
468
- This prevents the model from treating it as a conversation to continue.
329
+ Moved to [Compaction reference](/compaction/reference#session_before_tree).
469
330
 
470
- Tool results are truncated to 2000 characters during serialization. Content beyond that limit is replaced with a marker indicating how many characters were truncated.
331
+ ## Branch Summaries
471
332
 
472
- ## Extension Hooks for Branch Summarization
333
+ When `/tree` switches away from one branch to another, Atomic can summarize the abandoned branch and attach that summary at the new position. This preserves important context from the path you left without replaying the whole branch.
473
334
 
474
- ### session_before_tree
335
+ When prompted, choose one of:
475
336
 
476
- Fired before `/tree` navigation. Always fires regardless of whether user chose to summarize. Can cancel navigation or provide custom summary.
337
+ 1. no summary
338
+ 2. summarize with the default prompt
339
+ 3. summarize with custom focus instructions
477
340
 
478
- ```typescript
479
- pi.on("session_before_tree", async (event, ctx) => {
480
- const { preparation, signal } = event;
481
-
482
- // preparation.targetId - where we're navigating to
483
- // preparation.oldLeafId - current position (being abandoned)
484
- // preparation.commonAncestorId - shared ancestor
485
- // preparation.entriesToSummarize - entries that would be summarized
486
- // preparation.userWantsSummary - whether user chose to summarize
487
-
488
- // Cancel navigation entirely:
489
- return { cancel: true };
490
-
491
- // Provide custom summary (only used if userWantsSummary is true):
492
- if (preparation.userWantsSummary) {
493
- return {
494
- summary: {
495
- summary: "Your summary...",
496
- details: { /* custom data */ },
497
- }
498
- };
499
- }
500
- });
501
- ```
341
+ Branch summaries are separate from `/compact`: branch navigation can generate summary prose (optionally with focus instructions), while Verbatim Compaction lets a model select numbered line ranges and reconstructs retained text mechanically.
502
342
 
503
- See `SessionBeforeTreeEvent` and `TreePreparation` in the types file.
343
+ See [Compaction](/compaction) for Verbatim Compaction, branch summarization internals, and extension hooks.
504
344
 
505
345
  ## Summary request isolation
506
346
 
@@ -510,31 +350,8 @@ Verbatim planning and branch summarization are standalone provider requests. Eac
510
350
 
511
351
  ## Settings
512
352
 
513
- Configure compaction in `~/.atomic/agent/settings.json` or `<project-dir>/.atomic/settings.json` (legacy `.pi` paths are also supported):
514
-
515
- ```json
516
- {
517
- "compaction": {
518
- "enabled": true,
519
- "reserveTokens": 16384
520
- }
521
- }
522
- ```
523
-
524
- | Setting | Default | Description |
525
- |---------|---------|-------------|
526
- | `enabled` | `true` | Enable automatic Verbatim Compaction. |
527
- | `reserveTokens` | `16384` | Tokens to reserve for the next LLM response; threshold auto-compaction starts when completed-response usage or a prospective post-tool context exceeds the model's effective input budget minus this reserve. It is an **input-side** reserve only and never caps planner output. |
528
-
529
- Compaction has no configuration key of its own for fallback borrowing: it reuses `settings.fallbackModels`, the same ordered `provider/model[:thinkingLevel]` list that main-chat model fallback walks. With no `fallbackModels` configured, compaction behaves as before: one planner model, then either an honest failure (recoverable) or a fresh context window (load-bearing).
530
-
531
- Disable auto-compaction with `"enabled": false`. You can still compact manually with `/compact`.
353
+ Moved to [Compaction reference](/compaction/reference#settings).
532
354
 
533
355
  ## Historical formats
534
356
 
535
- Two old formats remain parseable but inactive:
536
-
537
- - `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.
538
- - `type:"compaction"` without `details.strategy: "verbatim-lines"` stored generated summary prose. Those records also remain inert.
539
-
540
- 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.
357
+ Moved to [Compaction reference](/compaction/reference#historical-formats).
@@ -54,10 +54,15 @@ Prefer direct file automation for structured tasks such as assembling slides, fi
54
54
  | AppleScript or JavaScript for Automation through `osascript` | Create documents, address named app objects, export files, coordinate scriptable macOS apps. | macOS only. Each app defines its own scripting dictionary; some apps expose little or no scripting support. |
55
55
  | Office Scripts | Repeatable Excel workbook operations through the Automate tab, including supported Power Automate flows. | Excel only. Availability depends on the account, app version, and organization policy; it is not a general desktop-control API. |
56
56
  | PowerShell with COM automation | Drive installed Windows applications that expose COM, including desktop Office. | Windows-specific. Do not assume unattended service execution is supported or reuse the user's active app instance without permission. |
57
+ | VBA in desktop Excel, Word, or PowerPoint | Format ranges, update charts, assemble slides, or automate document operations through Office's object models. | Requires a supporting desktop Office app and permitted macros. Windows and Mac APIs differ; VBA does not run in Office on the web. |
57
58
  | Application APIs, such as Blender's Python API | Generate geometry, set scene properties, apply repeated edits, and render or export. | Use the API and runtime for the installed app version. Some operations depend on an active document, selection, or editor context. |
58
59
 
59
60
  Before writing a script, identify the input format, required features, output path, and library or app version. Read the relevant API reference rather than guessing methods. Start with a read-only query or a disposable copy. Save to a new path and reopen the result to check its contents; use a compatible viewer or renderer when appearance matters. Scripts still need the same authorization as UI actions to overwrite, upload, or publish files.
60
61
 
62
+ For scripts that operate an application, also keep these application-specific checks:
63
+
64
+ Before writing a script, identify the target app/version, input document, object names, and output path. Read the application's API reference or scripting dictionary rather than guessing methods. Start with a read-only query or a disposable copy, and keep a record of which operations changed the document.
65
+
61
66
  ### macOS recipe: create a draft with osascript
62
67
 
63
68
  Open Script Editor and choose File > Open Dictionary to inspect an application's supported commands, objects, and properties. Apple's [scripting terminology guide](https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/AboutScriptingTerminology.html) explains how to read the dictionary. App scripting addresses document objects directly; `System Events` UI scripting instead drives accessible interface controls and needs Accessibility permission.
@@ -128,6 +133,36 @@ Reopen the saved deck to check slide count and text. Then view it in PowerPoint,
128
133
 
129
134
  For similar file-based tasks, use [python-docx](https://python-docx.readthedocs.io/en/latest/) for Word documents or [openpyxl](https://openpyxl.readthedocs.io/en/stable/) for Excel workbooks. Check feature support before editing a complex existing file. Use an app's own API when a library cannot make the required change, rather than forcing a lossy conversion. If an approved task requires macros, inspect the code and follow the organization's macro policy; never weaken security settings to run it.
130
135
 
136
+ ### Office recipe: format an Excel report with VBA
137
+
138
+ For a desktop workbook, use [VBA](https://learn.microsoft.com/en-us/office/vba/library-reference/concepts/getting-started-with-vba-in-office) to change specific ranges instead of sending a long sequence of clicks. Try this on a trusted copy of a workbook with a worksheet named `Summary` and a report in `A1:D20`:
139
+
140
+ 1. Save the copy as an Excel Macro-Enabled Workbook, `.xlsm`, if you want to retain the macro.
141
+ 2. Open Developer > Visual Basic. In the copied workbook's project, choose Insert > Module and paste the macro below. If Developer is hidden, enable that tab through Excel's ribbon settings.
142
+ 3. Review the code and run `FormatSummary` through Developer > Macros, subject to your organization's macro policy.
143
+ 4. Inspect the header, number formatting, and column widths. Save only the reviewed copy.
144
+
145
+ ```vb
146
+ Option Explicit
147
+
148
+ Sub FormatSummary()
149
+ Dim report As Worksheet
150
+ Set report = ThisWorkbook.Worksheets("Summary")
151
+
152
+ report.Range("A1:D1").Font.Bold = True
153
+ report.Range("B2:D20").NumberFormat = "#,##0.00"
154
+ report.Range("A1:D20").Columns.AutoFit
155
+ End Sub
156
+ ```
157
+
158
+ `ThisWorkbook` is the workbook containing the macro, not whichever workbook happens to be active. Put the macro in the copied report's project, not a personal macro workbook. The example changes formatting only and does not save automatically. Its operations are documented in the [Excel VBA reference](https://learn.microsoft.com/en-us/office/vba/api/overview/excel).
159
+
160
+ For other jobs, address workbook, worksheet, slide, shape, or document objects explicitly. A recorded macro can help discover operations, but replace dependence on `Selection`, `ActiveSheet`, or `ActivePresentation` with references to the intended objects before reusing it. For presentations, use PowerPoint's object model rather than treating Excel VBA as a universal Office API.
161
+
162
+ Never enable all macros, weaken Trust Center settings, or enable programmatic access to the VBA project just to inject code. If policy blocks the macro, use an approved mechanism or report the restriction. VBA in a document can access more than that document, so inspect unfamiliar macros before opening or running them. If a script changes application-wide settings such as events or alerts, restore their previous values on success and error; do not suppress prompts to force a save.
163
+
164
+ VBA support in desktop Excel, Word, and PowerPoint includes macOS, but Windows COM, ActiveX, and Win32-dependent code is not portable. Consult Microsoft's [Office for Mac guidance](https://learn.microsoft.com/en-us/office/vba/api/overview/office-mac) for sandbox and file-access differences. Saving as `.xlsx` cannot retain VBA; choose the output format deliberately.
165
+
131
166
  ### Office Scripts, app runtimes, and file tools
132
167
 
133
168
  For Excel on the web or a supported desktop installation with the Automate tab, consider Office Scripts. Record a small action or create a script there, then use the `ExcelScript` workbook API for repeatable edits. These TypeScript scripts are not VBA and do not run as ordinary Node.js scripts. Check [Office Scripts versus VBA](https://learn.microsoft.com/en-us/office/dev/scripts/resources/vba-differences) for platform, licensing, and API differences. Creating a Power Automate flow can introduce scheduled runs and cloud access; do so only when that automation is part of the request.