You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(compressor): redesign compressor with depth-aware ratios and grace period
The old compressor selected candidates greedily and merged them at a fixed 2:1
ratio until the history block fit the budget. On large sessions this could
swallow 80%+ of all compartments in one pass (selecting ~292 out of 352
compartments into one LLM call), causing ordinal drift in the output and
pathological over-compression of recent work that did not need it yet.
Selection rewrite:
- Bound each pass to at most `max_compartments_per_pass` (default 15) so the
LLM never handles more context than it can track reliably.
- Always exclude the newest `grace_compartments` compartments (default 10) so
freshly published historian output has time to be used before compression
touches it. Count-based instead of time-based so long autonomous runs that
publish dozens of compartments overnight stay protected.
- Pick the oldest contiguous band of same-rounded-depth compartments,
respecting the count floor and merge-depth cap. Mixed-depth bands are
skipped so compression progresses from depth 0 upward uniformly.
- Replace the fixed 2:1 ratio with per-depth ratios: 4:3 at depth 1, 3:2 at
depth 2, 2:1 at depths 3 and 4, title-only collapse at depth 5. Depth 1
keeps ~75% of tokens instead of halving them, protecting narrative content.
Ordinal-snap fix:
- `compartment-runner-compressor.ts` previously required exact messageId
matches when mapping LLM output back to DB rows. Any off-by-one drift
failed the whole pass. Now off-by-one LLM output snaps to the enclosing
input compartment's canonical boundary. The snap count is logged for
observability.
New config surfaces under top-level `compressor`: `enabled`,
`min_compartment_ratio`, `max_merge_depth`, `cooldown_ms`,
`max_compartments_per_pass`, `grace_compartments`. Schema regenerated,
documented in CONFIGURATION.md, and threaded through hook, transform, and
runner dependencies.
Copy file name to clipboardExpand all lines: CONFIGURATION.md
+57Lines changed: 57 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -74,6 +74,7 @@ Higher-tier models with longer cache windows benefit from a longer TTL. Setting
74
74
|`history_budget_percentage`|`number` (0.05–0.5) |`0.15`| Fraction of usable context (`context_limit × execute_threshold`) reserved for the history block. Triggers compression when exceeded. |
75
75
|`compaction_markers`|`boolean`|`true`| Inject compaction boundaries into OpenCode's DB after historian publishes. Reduces transform input size for long sessions. |
76
76
|`commit_cluster_trigger`|`object`| See below | Controls the commit-cluster historian trigger. |
77
+
|`compressor`|`object`| See below | Controls the background compressor that merges older compartments when the history block exceeds its budget. |
77
78
78
79
### `commit_cluster_trigger`
79
80
@@ -88,6 +89,56 @@ A **commit cluster** is a distinct work phase where the agent made one or more g
88
89
}
89
90
```
90
91
92
+
### `compressor`
93
+
94
+
Compressor is a background pass that runs when the rendered `<session-history>` block exceeds its budget. It merges older compartments using progressively aggressive **caveman-style** compression at each depth level, enforcing style consistency via a deterministic post-process after the historian LLM call. Each compartment range can be compressed at most `max_merge_depth` times.
95
+
96
+
**Depth tiers** (applied progressively as compartments are re-compressed):
97
+
98
+
| Depth | Style | What happens |
99
+
|---|---|---|
100
+
| 1 |**Merge only**| Preserve narrative and all U: lines. Drop only duplicates spanning compartments. |
101
+
| 2 |**Lite caveman**| Drop filler words (just, really, basically) and hedging. Keep grammar. |
102
+
| 3 |**Full caveman**| Drop articles (the, a, an), weak auxiliaries. Fragments OK. Single paragraph per compartment. |
| 5 |**Title-only collapse**| Content cleared (no LLM call). Raw messages recoverable via `ctx_expand`. |
105
+
106
+
Inspired by the [caveman Claude Code skill](https://github.com/JuliusBrussee/caveman) which validated telegraph-style compression as LLM-friendly (and saves tokens without tokenizer fallback issues that character-dropping causes).
| 4 → 5 | — | Title-only collapse (no LLM, recoverable via `ctx_expand`) |
130
+
131
+
**Selection strategy:** The compressor picks the oldest contiguous run of compartments that share the SAME rounded compression depth (up to `max_compartments_per_pass`). This progresses naturally: depth-0 bands get compressed first → depth-1 bands compressed next → and so on. Each run goes through one LLM call.
132
+
133
+
**Floor protection:** The compressor never reduces your session's compartment count below `ceil(total_raw_messages / min_compartment_ratio)`. For a 20K-message session with the default ratio, that's a floor of 20 compartments.
134
+
135
+
**Grace period:** The newest `grace_compartments` compartments are always excluded from compression. This protects freshly-published historian output from being re-compressed before it has been used. Default is 10, which works well even for long autonomous runs that publish many compartments per hour.
136
+
137
+
**Ordinal snap:** When the LLM drifts by ±1-2 ordinals on merged boundaries (e.g. outputs `start=8161` when the actual input boundary is `8160`), the runtime snaps those values to the enclosing input compartment's canonical boundary rather than rejecting the whole pass. Snaps are logged for observability.
138
+
139
+
**Disable entirely:** Set `compressor.enabled: false` to skip all background compression. Older sessions will simply carry a larger history footprint.
140
+
141
+
91
142
| Field | Type | Default | Description |
92
143
|-------|------|---------|-------------|
93
144
|`enabled`|`boolean`|`true`| Enable commit-cluster based historian triggering. |
@@ -401,6 +452,12 @@ When enabled, dreamer analyzes which files each session's agent reads most frequ
Copy file name to clipboardExpand all lines: assets/magic-context.schema.json
+54Lines changed: 54 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -166,6 +166,60 @@
166
166
"default": true,
167
167
"description": "Inject compaction boundaries into OpenCode's DB after historian publishes. Reduces transform input size for long sessions by letting OpenCode's filterCompacted skip older messages."
168
168
},
169
+
"compressor": {
170
+
"type": "object",
171
+
"properties": {
172
+
"enabled": {
173
+
"type": "boolean",
174
+
"default": true,
175
+
"description": "Enable background compressor. When false, history block compression never runs and older sessions may carry a larger history footprint."
176
+
},
177
+
"min_compartment_ratio": {
178
+
"type": "number",
179
+
"minimum": 100,
180
+
"maximum": 10000,
181
+
"default": 1000,
182
+
"description": "Floor = ceil(total_raw_messages / min_compartment_ratio). Compressor never reduces compartment count below this floor."
183
+
},
184
+
"max_merge_depth": {
185
+
"type": "number",
186
+
"minimum": 1,
187
+
"maximum": 5,
188
+
"default": 5,
189
+
"description": "Maximum compression depth a compartment range can reach. Depth 5 collapses to title-only (recoverable via ctx_expand). Depths 1-4 apply caveman lite/full/ultra compression."
190
+
},
191
+
"cooldown_ms": {
192
+
"type": "number",
193
+
"minimum": 60000,
194
+
"default": 600000,
195
+
"description": "Minimum milliseconds between background compressor runs for a session."
196
+
},
197
+
"max_compartments_per_pass": {
198
+
"type": "number",
199
+
"minimum": 3,
200
+
"maximum": 50,
201
+
"default": 15,
202
+
"description": "Cap on compartments sent to the LLM in one pass. Smaller batches avoid ordinal drift and dedup mistakes on large inputs."
203
+
},
204
+
"grace_compartments": {
205
+
"type": "number",
206
+
"minimum": 0,
207
+
"maximum": 100,
208
+
"default": 10,
209
+
"description": "Number of newest compartments always excluded from compression. Protects freshly published historian output from being re-compressed before it has been used."
210
+
}
211
+
},
212
+
"additionalProperties": false,
213
+
"default": {
214
+
"enabled": true,
215
+
"min_compartment_ratio": 1000,
216
+
"max_merge_depth": 5,
217
+
"cooldown_ms": 600000,
218
+
"max_compartments_per_pass": 15,
219
+
"grace_compartments": 10
220
+
},
221
+
"description": "Background compressor configuration — merges older compartments with caveman-style compression when the history block exceeds its budget."
Copy file name to clipboardExpand all lines: packages/plugin/scripts/build-schema.ts
+62Lines changed: 62 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -221,6 +221,68 @@ function buildSchema(): Record<string, unknown> {
221
221
"Inject compaction boundaries into OpenCode's DB after historian publishes. Reduces transform input size for long sessions by letting OpenCode's filterCompacted skip older messages.",
222
222
},
223
223
224
+
compressor: {
225
+
type: "object",
226
+
properties: {
227
+
enabled: {
228
+
type: "boolean",
229
+
default: true,
230
+
description:
231
+
"Enable background compressor. When false, history block compression never runs and older sessions may carry a larger history footprint.",
232
+
},
233
+
min_compartment_ratio: {
234
+
type: "number",
235
+
minimum: 100,
236
+
maximum: 10000,
237
+
default: 1000,
238
+
description:
239
+
"Floor = ceil(total_raw_messages / min_compartment_ratio). Compressor never reduces compartment count below this floor.",
240
+
},
241
+
max_merge_depth: {
242
+
type: "number",
243
+
minimum: 1,
244
+
maximum: 5,
245
+
default: 5,
246
+
description:
247
+
"Maximum compression depth a compartment range can reach. Depth 5 collapses to title-only (recoverable via ctx_expand). Depths 1-4 apply caveman lite/full/ultra compression.",
248
+
},
249
+
cooldown_ms: {
250
+
type: "number",
251
+
minimum: 60000,
252
+
default: 600000,
253
+
description:
254
+
"Minimum milliseconds between background compressor runs for a session.",
255
+
},
256
+
max_compartments_per_pass: {
257
+
type: "number",
258
+
minimum: 3,
259
+
maximum: 50,
260
+
default: 15,
261
+
description:
262
+
"Cap on compartments sent to the LLM in one pass. Smaller batches avoid ordinal drift and dedup mistakes on large inputs.",
263
+
},
264
+
grace_compartments: {
265
+
type: "number",
266
+
minimum: 0,
267
+
maximum: 100,
268
+
default: 10,
269
+
description:
270
+
"Number of newest compartments always excluded from compression. Protects freshly published historian output from being re-compressed before it has been used.",
271
+
},
272
+
},
273
+
additionalProperties: false,
274
+
default: {
275
+
enabled: true,
276
+
min_compartment_ratio: 1000,
277
+
max_merge_depth: 5,
278
+
cooldown_ms: 600000,
279
+
max_compartments_per_pass: 15,
280
+
grace_compartments: 10,
281
+
},
282
+
description:
283
+
"Background compressor configuration — merges older compartments with caveman-style compression when the history block exceeds its budget.",
0 commit comments