It publishes the number where it loses

lossless-context-mcp

A content-addressed archive of every file version an agent was shown, hook-fed so a compaction cannot destroy the working set — and a benchmark whose headline result is that its own compression saves nothing on real sessions.

Carries 2 of 7 rubric mechanisms. Most systems here carry none or one (41%), and a dash means the mechanism was not found at this commit — not that the system needed it. Each mark is one LLM reviewer's reading of the code at this commit rather than a run of it — known limits.

  • Tombstone
  • Trust state
  • Bi-temporal
  • Scope enforced
  • Mutation audit
  • Human review
  • Negative evals

1. Executive Summary

lossless-context-mcp is a flight recorder for a coding agent's context — MIT, TypeScript, roughly 4,800 lines across seventeen modules, 20 commits and 4 contributors since 31 May 2026. It archives every file version the agent was shown, content-addressed, with an append-only event log of when and how, and stands four products on that substrate: restore (put the working set back after a compaction), packs (one cache-friendly prefix for a fan-out fleet), receipts (git-bound attestation of exactly what the model saw), and metering (where the read tokens went).

The engineering is careful and well argued throughout, but the reason this report exists is BENCHMARK.md, which is the most honest benchmark document in this corpus.

It defines two mandatory metrics. Savings is 1 − (sent / baseline) with a real tokenizer. Losslessness is a byte-for-byte reconstruction of the view the model would hold, after every single operation, where "one divergence = fail" — and the document states the reason a savings number alone is not a result: "A savings number without a reconstruction proof is a marketing number."

Then it publishes three workloads, and the headline is the one that does not flatter the project. The synthetic ceiling saves 72.1%. The synthetic floor saves 0.0% — correct, since first-contact reads must never be reduced. And the real-session replay, over 1,839 transcripts and 16,823 reads, measures −1.4%: the tool costs tokens. A re-measurement on a grown corpus of 3,363 transcripts and 26,041 reads puts it at −2.6%.

The explanation is given rather than hedged around: only 7–8% of reads are re-reads, the median session re-reads nothing, most re-reads arrive changed, and a unified diff regularly exceeds the content it patches — because "the harness's native file-state cache already eliminated redundant re-reads." The document even grades a competing approach through the same harness on the same corpus, at −0.2%. And it draws the general rule: "Any context tool that quotes only its ceiling is quoting the wrong number."

A project publishing, as a headline table row, that its compression feature has negative value on the workload people actually run is rare enough to be the finding. It also reframes the system: what remains valuable is everything the benchmark does not score — surviving compaction, blocking a blind edit, and proving after the fact what the model saw.

2. Mental Model

Two ideas do the work.

A file version is a memory with an identity, and the identity is its content. Blobs are stored under the SHA-256 of what they contain, with a git blob sha1 recorded beside it so a version can be tied to a commit. Writes are idempotent by construction — temp file then rename — and the design note draws the conclusion that matters operationally: "two writers racing on the same hash produce the same bytes."

Concurrency is designed away rather than locked away. Each writing process appends only to its own events/<writer>.jsonl. There is no lock anywhere in the archive, and multi-process safety is a property of the file layout instead of a protocol anyone has to honour. Readers merge the logs.

The third idea is the one worth stealing, and it is about what not to store. Paths matching a secret deny list are never written to blobs — but the event is still appended, carrying excluded: true. The record that the agent read something survives; the content does not. Most systems facing this choice drop both, and lose the ability to say afterwards what was touched.

Diagram — Reads arrive from MCP tools and from transcript sweeps at PreCompact; content-addressed blobs are written once and never updated, while deny-listed paths get an event with excluded:true and no blob — so the record of the access survives without the secret. Restore, packs and receipts all read from that one substrate.
Diagram source
%% caption: Reads arrive from MCP tools and from transcript sweeps at PreCompact; content-addressed blobs are written once and never updated, while deny-listed paths get an event with excluded:true and no blob — so the record of the access survives without the secret. Restore, packs and receipts all read from that one substrate.
flowchart TD
    M["MCP read_file"] --> A
    S["PreCompact sweep<br/>parses transcript — native Read/Edit/Write too"] --> A
    A{"isExcluded(path)?<br/>deny list + LOSSLESS_ARCHIVE_EXCLUDE<br/>+ symlink target resolved"}
    A -->|"denied"| E1["event appended, excluded: true<br/><i>no blob written</i>"]
    A -->|"allowed"| B["blob written under SHA-256<br/>temp file + rename, idempotent"]
    B --> E2["event appended to events/&lt;writer&gt;.jsonl<br/>ts, session, path, repo, hash,<br/>gitBlobSha1, bytes, tokens, op, sidechain"]
    E1 --> L["append-only log, one file per writer<br/><i>no locking anywhere</i>"]
    E2 --> L
    L --> R["restore_context<br/>ranked working set, budget-capped,<br/>changed files annotated"]
    L --> P["packs — stable hot files<br/>across sessions"]
    L --> C["receipts — git-bound<br/>what did it see"]
    G["PreToolUse guard"] -->|"model has not seen<br/>current version"| X["edit BLOCKED"]

3. Architecture

Seventeen modules. archive.ts is the substrate. sweep.ts parses transcripts. guard.ts and session-guard.ts decide whether an edit may proceed. restore.ts writes and reads working-set manifests. pack.ts, slice.ts and outline.ts shape what gets emitted. receipt.ts and gitid.ts do attestation. meter.ts does the token accounting. presence.ts and blame.ts handle multi-agent coordination.

Five hooks in hooks/ are the integration surface, and the screen flags the directory as auto-running for exactly that reason: these are scripts a harness executes on its own schedule.

4. Essential Implementation Paths

The guard's self-vouch rule is the sharpest piece of reasoning in the repository, and it is a general lesson about any system that decides whether a caller has earned a permission by reading a log the caller is already in:

SELF-VOUCH RULE (the guard's load-bearing invariant): for guarded tools (Edit/Write/MultiEdit), only tool RESULTS may mark a file as seen — never the tool_use intent block. The current call's own tool_use is already in the transcript when PreToolUse fires, so intent-based marking would let every edit approve itself … Results only exist after successful execution, so a pending call can never vouch for itself, regardless of hook/transcript write ordering.

The exception is stated with its failure direction named rather than buried: intent-based marks are allowed for the server's own read tools, where "worst case here is a false ALLOW when a read later errors, which is the fail-open direction." Knowing which way your exception fails, and writing it down beside the exception, is the practice this atlas keeps asking for.

The sweep runs on the compaction path, which means its cost is a correctness constraint rather than a nice-to-have. The README publishes the measurement — one real 14 MB transcript swept in 361 ms — and ships the command to reproduce it on your own transcript.

5. Memory Data Model

ArchiveEvent carries ts, session, path, repo, hash (SHA-256 of the content version), optional gitBlobSha1, bytes, approxTokens, source (mcp or sweep), op (read, edit or write), view, and two booleans worth naming: sidechain, true when the event came from a subagent transcript line, and excluded, true when the path matched the deny list.

sidechain is a small field with a large implication. Subagent transcripts are a known contamination source for systems that mine transcripts for durable content — this atlas found exactly that failure in another system read the same day. Here the provenance is recorded on the row rather than the subagent runs being silently folded in or silently dropped, which leaves the decision to the consumer.

6. Retrieval Mechanics

There is no search index and no ranking model. Retrieval is re-emission from a ranked working set: restore_context replays the manifest from current disk state, capped by a token budget, "annotating any file that changed since the model last saw it."

That annotation is the part that matters. Re-emitting a stale copy would be worse than not restoring at all, because the model would proceed confidently on a file that has since moved. Marking drift at the moment of restore keeps the mechanism honest about the one thing it cannot control — the disk.

7. Write Mechanics

Hook-fed and append-only. The PreCompact sweep parses the session transcript and archives everything the session touched, explicitly including native Read, Edit and Write results rather than only this server's own MCP reads — which is what makes it a recorder of the agent's context rather than of its own usage.

Nothing is ever updated. A changed file is a new blob under a new hash, and the old version remains addressable.

8. Agent Integration

An MCP server plus five hooks: sweep-transcript at PreCompact, inject-manifest at SessionStart(compact), guard-edit at PreToolUse, publish-edit, and reset-epoch. The demo recordings in the README are generated by a script that "drives the real hooks and server and renders what they actually said", and the README tells the reader to re-run it — a recording generated from the shipped code is a materially different claim from a recording made by hand, and the distinction is stated rather than assumed.

9. Reliability, Safety, and Trust

Secret hygiene is the strongest part, and it is tested where it should be. The deny list covers .env, .env.production, a Windows-shaped .env.local and secrets.json; a near-miss (environment.ts) is asserted not to be denied, which is the half of a deny-list test that usually goes missing; a user-supplied LOSSLESS_ARCHIVE_EXCLUDE glob is honoured; and there is a case for "an innocuously named symlink pointing at a secret", so the check resolves the target rather than trusting the name.

There is no epistemic state on content — nothing stored is a claim, and a blob is a byte sequence the model was shown. What the system does track is whether the model has seen the current version of a file, and it refuses an edit when it has not. That is authorization derived from history rather than a trust ladder, and the trust mark is withheld for that reason.

Scope is recorded but not enforced on a read path: session and repo sit on every event and manifests are per-session files, while the boundary that is genuinely enforced — the deny list — is applied at write time. A reader wanting tenant-style isolation should not read the recorded keys as one.

10. Tests, Evals, and Benchmarks

Twelve test files covering the archive, engine, guard, session guard, receipts (two generations), restore and packs, slice, sweep, meter, presence and blame.

The benchmark is covered in section 1 and is the reason to read this repository even if you never install it. Three properties are worth restating as transferable practice:

  • Losslessness is a gate, not a metric. Reconstruct the model's view after every operation and compare byte-for-byte; one divergence fails the run.
  • Publish the floor and the ceiling and the realistic case, and let the realistic case be the headline when it is the unflattering one.
  • Grade the competitor through your own harness on your own corpus, and publish that number too — here, −0.2% for a marker-only dedup approach, which makes the −2.6% legible as a property of the workload rather than of the tool.

What is not committed is the raw per-transcript output. The corpus is the author's own ~/.claude/projects history and cannot be published, which is stated; the harness and the commands to re-run it on your own history are shipped, which is the reproducible half of the claim and is the right trade for a corpus made of private transcripts.

11. Patterns Worth Stealing

Record the access, withhold the content. excluded: true keeps the audit trail complete while the secret never lands on disk. Dropping the event too would make the archive quietly incomplete in exactly the cases someone will later ask about.

Design concurrency out of the format. One append-only file per writer plus content-addressed idempotent blobs removes the need for a lock, and therefore the need for every future writer to remember one.

A pending call must never vouch for itself. Any check that reads a log the subject is already in has this bug available to it; the fix is to accept only evidence that could not exist before the fact.

Name the direction your exception fails in. "The fail-open direction", written beside the exception, tells the next reader what they are trading.

Annotate drift at re-emission. Restoring from current disk is right; saying which files moved since the model last saw them is what keeps it safe.

Publish the number where you lose. The credibility the −2.6% row buys is worth more than the 72.1% row it sits beside, and the document says why.

12. Open Questions

  • What is the system worth when the compression is worth nothing? Restore, coordination and receipts are the surviving value and none of them is scored by the benchmark; the project has built the harness culture to measure them and has not pointed it at them.
  • Does the archive have a retention policy? Every version of every file the agent ever read is kept, content-addressed, and no eviction, TTL or size cap appears in the archive module.
  • What does a consumer do with sidechain? The provenance is recorded on every event, and whether ranking, packs or receipts treat a subagent read differently from a main-thread read is not something the field's presence answers.
  • Is excluded: true reachable in a receipt? An attestation of what the model saw is most interesting precisely where content was withheld, and how a receipt renders an excluded event decides whether the audit trail survives into the artifact people would actually show someone.

Appendix: File Index

Path What it carries
src/archive.ts The content-addressed store, the event schema, the deny list, and the no-locking argument
src/guard.ts The self-vouch rule and the edit decision
src/session-guard.ts Single-claim coordination between concurrent agents
src/sweep.ts Transcript parsing at PreCompact, including native Read/Edit/Write
src/restore.ts Working-set manifests, per-session, and budget-capped re-emission
src/receipt.ts, src/gitid.ts Git-bound attestation of exact versions
hooks/ The five Claude Code hooks — the auto-running surface the screen flags
test/archive.test.ts Deny-list cases, the near-miss, the glob, and the symlink
BENCHMARK.md Two mandatory metrics, three workloads, and the negative headline

Appendix: Recorded Searches

Run from the root of the checkout at the pinned commit.

Claim Command Result at this pin
A subagent gets its own seen-state read guardStateKey at src/guard.ts:226-232 agentId ? \sessionId.agent{agentId}` : sessionId`
Cursors are per transcript path read the offsets doc comment in src/guard.ts Keyed by normalized path; the legacy scalar is retained for old state files and never consulted
Only a tool result marks a file seen grep -n "Intent-based marks" src/guard.ts "ONLY for this server's read tools (never guarded tools)", and "only tool RESULTS may mark a file as seen"
Suite size grep -c "it(|test(" test/*.test.ts summed 156 cases across ten files

History

2026-09-111ef5bf9e… — re-read, 7 files and 323 insertions past the previous pin in a single commit, almost all of it the guard and its tests. Both marks re-verified and unchanged. The commit fixes a failure mode worth recording, because the guard's whole value is that it denies an edit the model should not make, and this made it deny edits it should have allowed. A single scalar byte cursor was applied across every transcript in a session — and a session has more than one, because "Claude Code gives every subagent its own file while keeping the parent's session_id". When the parent's cursor exceeded a subagent transcript's size, the reader took its truncated-or-rotated branch, returned nothing, and "the agent's own Read calls were never recorded — the guard then denied edits to files that agent had just read." The fix is a cursor per normalized path, with the old scalar retained so existing state files still load and explicitly never consulted for reads, plus guardStateKey giving a subagent its own state file under the parent session, on the reasoning that "a subagent has its own context window: the parent's Reads are not in it, and its Reads are not in the parent's." Two committed test files cover the multi-transcript and per-agent cases. One further distinction in the same change deserves naming: only a tool result may mark a file as seen, never an intent, and intent-based marks are accepted only for this server's own read tools — so an agent announcing it read something does not earn the right to edit it. Screened before reading: seven findings; nothing was installed or run.

2026-08-1947440a01… — first reading. Screened before reading: two auto-run surfaces — the hooks/ directory, which is the product, and server.json, an MCP manifest — one build-time package.json lifecycle script, one unpinned range with a package-lock.json beside it. Nothing was installed and nothing was executed; the benchmark numbers were read rather than reproduced, and the corpus they were measured on is the author's own transcript history and is not published.