What Compaction Actually Destroys
A long agent session crossed a compaction boundary at 652,664 tokens and came out the other side at 20,421, as a summary in the tool's stock nine-section format. It had lost 96 of its 101 file paths, 43 of its 44 URLs, and all 31 of the record ids its work cited. Five of those ids came back cut to eight or nine characters and an ellipsis, which is worse than gone: they look like provenance and resolve to nothing.
Thesis: At a compaction boundary, prose mostly survives and identifiers do not. On the same fixture rolls, about three decisions in four came through unaided and not one planted citation did. The summary keeps what the session decided and drops the pointers the next step needs to act on it, so anything that must cross the boundary has to be written down before it, not recovered from the summary after.
This is the first post of "The Amnesia Tax", a series on what long-running agents lose, why the obvious fixes have not worked, and what does.
What Was Measured
Compaction is the step a coding agent takes when its context fills up: a model summarizes the conversation so far, the summary replaces the transcript, and the session carries on. Nothing in that loop checks what the summary dropped.
So I built an observer. It is a private instrument, and its question is mechanical: take the identifiers present before the boundary, take those present in the summary, intersect them. No judge model is needed. A file path either survived verbatim or it did not.
It produced three kinds of evidence, of unequal weight:
- A live session, re-derivable in one command inside that instrument; the instrument is not public. The 652,664-token event above was an ordinary working session compacted by hand on
claude-opus-5. Its figures are the output of the instrument's own recount, which reads the session transcript, finds the boundary by parsing the record (not by searching for the word, which once matched a user message about compaction 1,395 records early) and counts each identifier class before and after. - Paired forks on a fixture. A loader session plants labelled items, grows its context, then forks into arms that compact byte-identical content, so each arm varies one lever. The grader is kept and the loader is not, so these are reported measurements, not a reproducible battery.
- A production event nobody planned. A session compacted automatically at 998,437 tokens on 2026-07-11 (07-12 in UTC), and the instrument's ledger records it. What it lost has been counted three ways, and that matters below.
What Survives and What Dies
The live event, from the reproducer's output:
| Identifier class | Before | After | Lost |
|---|---|---|---|
| Distinct file paths | 101 | 5 | 95.0% |
| Distinct URLs | 44 | 1 | 97.7% |
| Resolvable record ids | 31 | 0 | 100% |
| PR references | 9 | 2 | 77.8% |
Two details make the table worse than it looks. The five surviving paths were not the important ones; all five came from the session's last two units of work. The summarizer kept what was recent, not what the work depended on. And the record ids that "appeared" in the summary were truncated (four cut at eight hex characters, one at nine) so a reader, human or agent, sees a citation where there is none. A missing id prompts a lookup. A truncated one fails silently.
The cleanest contrast is on the fixture, where both kinds of item sat in the same rolls. On claude-haiku-4-5, with 105 competing identifiers, decisions stated in ordinary sentences survived at 73.3% unaided and planted citations at 0.0%. A short block of prose in the project instructions asking for decisions lifted them to 100% and took the run-to-run spread from four decisions to zero. It moved citations not at all: 0 of 15, in every roll. Decisions are not safe either; one in four was lost without the prose.
The table sets that fixture beside the live event. Models and conditions differ, so read it as two kinds of failure, not one experiment.
| Mostly survives the boundary | Dies at the boundary | |
|---|---|---|
| What it is | Decisions, stated in sentences | File paths, URLs, record ids, PR numbers |
| Measured | 73.3% unaided; 100% when prose asks (fixture, claude-haiku-4-5, n=3) |
0.0% of citations on those same rolls; live on claude-opus-5, 95.0% of paths, 97.7% of URLs and 31 of 31 ids lost |
| Responds to instructions | Yes | No: 0 of 15 citations with the instruction present |
| Which items survive | What was decided | Whatever was most recent |
| How it fails | The decision is absent | Absent, or truncated so it reads as a source (5 of 31 ids) |
Density matters too. With no competing identifiers in a 46,246-token context, every planted citation survived; at 180,675 tokens with 105 competitors (and 15 plants, not 8), none did. That round changed three things at once, so it does not isolate density, but a compaction figure quoted without its competitor density cannot be compared with another. In a live session the before-count is the density: 101 paths, 44 URLs and 31 ids in the first table.
The Number That Does Not Add Up
The 998,437-token event is the largest in the record, and it is written down two ways. The counts: 42 of 42 URLs and 111 of 129 file paths lost, which leaves 18 paths, about 14%. A results table written under an hour later, the same day, says 17.8% of paths survived. Both cannot be true. A later write-up flagged the conflict rather than averaging it, and this post uses the counts. A recount from the recovered transcript, made for this post, gives a third reading: 7 of 66 paths and none of 44 URLs kept. Its extractor differs from the original count, so it settles nothing between the first two. Under all three readings the event lost every URL and more than four in five paths. Three counts of one event still disagree on how many paths it held; only the losses agree.
What This Means for an Enterprise Agent
An illustration: picture an agent six hours into a migration across a large monorepo: renaming a configuration key across services, with a ticket per service and an audit trail your change board will read. It compacts. The summary says, accurately, that the loader is done and three call sites remain. It no longer says which three, which tickets it closed, or which commit fixed the test it broke an hour ago. The agent will search for them again if it notices, or act on paths it half-remembers if it does not.
The governance angle is the truncated id. An audit trail that cites atom:f6b7c841… looks like evidence. It is not. Any process that reads an agent's summary as a record of what was done inherits identifiers that point nowhere.
Capturing the summary afterwards does not help. An arm that stored it durably the moment compaction finished never recalled more than the summary held, in any roll. Capture after the boundary stores an artifact that is already lossy.
When the Opposite Wins
"Million-token windows make this obsolete." They do not. The 998,437-token event is the million-token window, by inference: the instrument cannot recover the window in effect, but no smaller window holds 998,437 tokens. A larger window moves the boundary later; it does not change what happens at it.
"Use a stronger model." The 998k event was summarized by claude-opus-4-8, the model that kept 15 of 15 marked citations on a fixture, and it still lost every URL; unmarked, the same model kept 6.7% (n=2, indicative). The instrument's own conclusion is that a stronger model is not the fix. Models differed in one place: on the marked fixture, the stronger one used the marker and a smaller one ignored it.
Short sessions win. A session that never reaches the boundary loses nothing to it, and in a small context with no competing identifiers every planted citation survived (decisions in that round came through at 66.7%). If your agents work in short, bounded units, compaction may never be your problem.
Decision-shaped work. If the session's value is a judgement (which approach, what tradeoff) and the next step does not need to open a specific file, the summary carries most of it: about three decisions in four survived unaided, and all of them when prose asked. The fourth decision is the one to write down.
Marking the identifiers as important. It is the one lever that ever moved the number, on a planted fixture. At real-session scale, paired against an unmarked arm, it did not hold. That result, and the decision rule written before it, is the next post.
What to Do Next
- Write identifiers to disk before the boundary. Keep paths, ids, URLs and ticket numbers in a progress file, verbatim, as the work happens. The summary is for intent; the file is for pointers. The Critic Said No shows an agent doing this: it wrote four open review findings, by number, into its compaction handoff before the boundary.
- After a compaction, re-read the file, not the summary. Treat any path or id in the summary as a hint to verify, never as a reference.
- Reject ids that do not resolve. A truncated identifier should fail a check, not pass as a citation. This is a string comparison, not a model call.
- Measure your own boundaries. Identifier survival is a set intersection of before and after; run it on your own transcripts, and report it with the before-count.
- Know when yours fires. Without a configured threshold, the automatic events in this record fired anywhere from 209,404 to 1,000,494 tokens. Set one, so you can prepare for it.
- Budget the tax. Count boundaries per task, and at each one log how many paths, ids and URLs were live before it. That count, not the token count, is what the next step will have to find again.
Next in The Amnesia Tax: the salience marker, and the decision rule its authors wrote before the test that went against it. Related reading: The Files Are the Memory, which this post corrects: it called compaction a way to distill a context "down to the disk-worthy essence", true for decisions and not for identifiers, because a summary is not a write to disk; Chosen, Not Assigned, whose loss chart drew this post's two events as one survey, where they are kept apart here; The Three-Tier Context System; and Your Tool Schemas Are the Bloat, which corrects The alwaysApply Tax's cost lane.