Compaction Forgets What You Knew
· 10 min read
The moment I dread in a long agent session is the one where the context meter runs out, auto-compaction kicks in, and the agent comes back from its little nap sounding exactly as confident as before while knowing noticeably less. It still remembers the task. What it’s lost is the reason we ruled out the obvious fix two hours ago, so it goes and tries the obvious fix again.
I’d assumed this was a me problem, probably caused by letting sessions run too long, until I read Stencil’s write-up on Snapcompact.1 Most of the post is about their answer to it: rendering the context as images and feeding the model pictures of its own transcript, which I’ll come back to. The part that stuck with me is a short section near the top called “The Case Against Compaction”, where Can Bölük says that in every harness they’ve used, compaction “cripples” the model “to the point where you would have been better off with a completely new session.”
That matches my experience closely enough that I went looking for evidence, and there’s more of it than I expected. My own coping strategy, for the record, was cruder: I made habitual use of /new and /clear, because long sessions got compacted and things went to shit, and killing the session preemptively felt safer than letting it survive compaction.
tl;dr: Compaction preserves what the agent was doing and discards what it knew: which approaches were rejected, which files changed, and the rules. That claim now has evidence behind it, from benchmarks and from studies of real coding sessions, and the countermeasures are boring rather than clever: constraints in files the harness re-reads, summaries you steer yourself, handoffs where a human writes down what done means, and no second compaction.
What the summary keeps #
Stencil benchmarked the compaction strategies that agents actually ship by having models answer SQuAD questions, a standard reading-comprehension test, over a document, once with the original text and once with what each strategy left behind. With the original text, Opus 4.8 scored 0.911 F1; from its own compacted context, 0.000. Gemini 3.5 Flash also zeroed, answering “UNREADABLE” to every question. Handoff documents did a bit better but not by much: 0.248. Their summary of the result is the line I keep repeating to people: “the summaries preserve what you were doing, not what you knew.”
SQuAD is trivia retrieval, which is a harsher test than most coding sessions, so I wouldn’t read those zeros as the score your agent gets after /compact, though the direction lines up with research that uses real coding work. Factory’s study of compaction2 graded agents on whether they could keep working after a compression point, across 36,611 messages from real engineering sessions. The weakest dimension for every method, theirs included, was artifact tracking, meaning knowledge of which files had already been changed. Factory sells an agent and ranked its own compaction first, so take the leaderboard with some salt, but the shared weakness is the useful finding.
The constraint results are worse. A write-up on governance decay3 reports rule violations going from 0% with full context to 30% after compaction, and as high as 59% for some models, because a rule like “never write to the production database” reads to a summariser like boilerplate it can safely drop.
Put those together and you get a fairly specific list of what a summary loses: exact facts, which files were touched, which approaches were rejected and why, and the rules. In other words, everything that stops an agent from making a mistake it has already made once.
Stencil also points out a quieter version of the same failure. Eliding is the cheaper alternative to summarising: instead of compressing old turns, the harness deletes old tool outputs (file contents, test logs, command output) and leaves literal [elided] placeholders in the transcript. As they put it, “LLMs complete stories; if half of your story is [elided…], how confident do you think it will be about using them?” I’d never thought of it that way, but it explains the slightly hesitant tool use I see after a long session has been trimmed.
Nothing about the models changed #
Stencil’s own answer to all this is Snapcompact: render the context as dense pixel-font images and pass those back to the model, because a 1568×1568 PNG holds about 40,000 characters, which is roughly 10,000 tokens of text billed as 3,279 image tokens. Their white-box work on Qwen2.5-VL suggests the model’s internal state ends up nearly the same whether it reads the text or the picture of the text, and on their best-tuned model they report carrying the same information for about a third of the input price.
There’s a catch, which they’re upfront about: models spend a lot of reasoning tokens decoding the images, and at Anthropic’s output prices that can eat the input savings. I’m not going to start screenshotting my sessions next week (my own harness ships it, which takes some of the virtue out of the position), but I liked the experiment a lot, and the reasoning behind it is the part that stuck: if the summary is the problem, stop summarising.
I used to blame the plan #
For a long time my rule was the one Stencil says they held too: if you need compaction often, the plan is wrong. Either the scope crept, or the work should have been split across subagents so the main agent could hold the whole picture without holding every file read and test log.
I still think that rule is mostly right, and it’s still the first thing I check; what’s changed is the size of the window. With million-token contexts, sessions past 500k tokens stopped being a sign that something had gone wrong and became the normal length for a large refactor. Stencil’s argument for why is one I agree with: “long-horizon tasks simply do better when one coherent agent drives the plan uninterrupted,” and you hit those sizes even with aggressive delegation.
There’s a real counterweight here. Chroma’s context rot research4 found that all 18 models they tested got worse as input length grew, even on simple tasks, so a huge context isn’t free either: you’re choosing between attention spread thin over a long transcript and a summary that has thrown the details away. Neither is great, but you can make either one less bad by deciding what survives the cut yourself.
The handoff that ships an MVP #
Stencil considers a handoff, where the agent writes a document for a fresh session to pick up, the best option available. I agree with them, with the same caveat they give: nobody steers it. Left alone, the agent writes “an unnecessarily detailed diary, followed by a TODO list that practically begs the next agent to declare the goal impossible and ship an ‘MVP’ instead.”
I laughed at that because I’ve read that exact TODO list. It has eleven items, four of them marked “stretch”, and the new session reads it as permission to quietly redefine done.
This is the same problem I wrote about in Stop Reviewing Code. Start Reviewing Intent. In that post, my argument was that human attention belongs on the spec, the tests, and the constraints, because those are where intent lives, while the code is just one implementation of them. A handoff document is a spec. It tells the next agent what the goal is, what done means, and what it isn’t allowed to do. The difference is that this spec is written by the agent, for the agent, at the moment it’s lowest on context, and nobody reviews it before it becomes the only record of what the task was. If I wouldn’t let an agent rewrite the acceptance criteria halfway through a feature, I shouldn’t let it do that by summarising them.
So handoffs need the treatment I’d give any other piece of intent: a human writes the parts that define success, and the agent fills in the rest.
What I do now #
None of this needs new tooling: it’s mostly a set of habits that move the important information out of the transcript, where compaction can reach it, and into places it can’t.
Keep constraints in files the harness re-reads. Anything that must survive goes in CLAUDE.md (or AGENTS.md for Codex), not in a message I typed three hours ago. Project instructions get loaded again after compaction; a rule I mentioned in passing does not. The mechanical part is the habit: when I catch myself correcting the agent, I say “add that to CLAUDE.md” right there, so the correction becomes a file edit instead of a chat message. None of the file-based advice is new, and I’d be pretending otherwise if I dressed it up as a discovery. The addition is doing the edit in the moment and having the agent do it, so the file grows as a byproduct of corrections rather than as a chore I keep meaning to get to.
Steer the summary. /compact takes instructions, and I’ve started using them every time instead of letting auto-compact choose what to keep. Something like /compact keep the list of rejected approaches and why, the files changed so far, and the failing test names costs a few seconds and saves an argument later.
Write the handoff template, and let the agent fill it. When I’d rather start fresh than compact, I ask for a handoff in a fixed shape, saved to a file, and I edit the top two sections myself before the new session reads it:
## Goal
<one or two sentences, written by me>
## Done means
<acceptance criteria or test names, written by me; the agent may not edit this>
## Constraints
<or "see CLAUDE.md" if they're already there>
## Decisions and rejected approaches
- Tried X, failed because Y. Do not retry.
## Files changed
<from git, not from memory>
## Next action
<one concrete step>
The “Done means” section is what stops the MVP drift: the agent can propose changes to it, but the change happens in the conversation with me rather than by omission in a summary. A fixed template like this is also a natural fit for a skill or slash command: the shape lives somewhere reusable instead of being retyped or reconstructed each time, and the agent just fills it.
Check the summary against the repo. The Factory study’s recommendation, which I’ve adopted, is to reconcile with the working tree before resuming any serious edits. In practice that’s asking the agent to run git status, git diff --stat, and the test suite as its first step after compaction, and to trust those over its own recollection of what it changed.
Push the noisy work into subagents. This is 2025-vintage advice, table stakes by now. I’m keeping it because it directly reduces compaction pressure: test runs, log spelunking, and broad searches belong in a subagent that reports a conclusion, so the main context fills up with decisions instead of output.
Don’t compact a compacted session. Each round summarises a summary, and the losses add up. After one compaction I’ll keep going, but after a second I write a handoff and start clean.
Stencil’s closing line is the bit I’d keep: “nothing about the models changed; we changed the context around them.” That’s true of the boring habits above as well. Compaction will keep getting better, but how well a long session survives it depends mostly on what I’ve put somewhere it can’t be summarised away, and on whether a person, rather than a tired agent, has written down what done means.