Session slimming: measured waste per source, and a proposed S4 bench gate #54
Replies: 1 comment
|
Thanks — this is the most careful measurement anyone has brought here. I checked every claim that touches this repo before answering, so this is long; the short version is at the bottom. Your measurements
Your reading of the benchCorrect. S2 counts anything under a content key, S3 caps the individual record at 25 KB, and superseded snapshots are small and content-keyed. OpenCode and Hermes pass both honestly by the rubric and still fill disks. That is a rubric gap, not a scoring error, so it goes through a version bump and the corrections log rather than a quiet re-score. Your two archive-path findingsBoth verified: One correction
Your risks, one by one
What I'd take, in order
Not taking: steps 3→4 as reclamation, the hash-cap lift (only needed for reclamation), and any format-internal rewrite. If that sequencing works for you, open the S4 PR against |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
I spent a couple of days measuring where the ~15 GB of agent session data on my Mac actually goes, across the sources this app already reads plus a couple it doesn't. Most of it turns out to be losslessly removable. This is a proposal to surface that — and eventually act on it — with the measurements behind it.
What the waste looks like
All measured on one machine, all reproducible:
eventtable stores a full message snapshot per streaming updatemessage.updated.1rows for 4,639 distinct messages; 378 MB where keeping the newest per message is 16 MBlogs_2.sqlitefreelist never reclaimedlogstable only 43 MBPRAGMA incremental_vacuum—auto_vacuumis already INCREMENTAL but never run (openai/codex#35823)~/.codex/sqlite/logs_2.sqlite, 167 MB, last written 2026-06-15state-snapshots/20260717-…-pre-update, 1,008 MB.envandauth.json, so it can't be silently removedtool_call_updatecarries the whole accumulated output instead of a delta, stored twice per recordtoolCallIdto its final eventOn the Grok one: a blanket "keep the last event per tool call" is not safe. I checked, and the prefix property only holds for 66% of tool-call groups. One group with 8,359 events and 256 MB looked identical to the pathological ones but was carrying genuine deltas from a render log. Any collapse that ships has to prove the property per group and default to dry-run.
A blind spot in Session Bench
S1/S2/S3 measure format leanness on a controlled probe and on corpus composition. OpenCode passes both gates it was scored on — yet 96% of its event table is superseded snapshots and people are hitting 50 GB stores.
Neither gate can see it. The redundant snapshots live under content keys, so S2 counts them as real work product; each individual record is under 25 KB, so S3 passes. What actually fills disks is how many times the same bytes get re-stored across a session's lifetime, which is orthogonal to both. Hermes passes S2 for the same reason.
Hence a possible fourth Signal gate — S4 · Superseded share: the fraction of stored bytes a lossless collapse would remove, measured on real corpus, with something like a ≤ 20% floor.
scripts/session_bench/measure.pyandevaluate.pyalready provide the harness, and the numbers above could seed the first pass. It measures what users feel rather than format elegance, which feels in keeping with the rest of the bench.Two things in the archive path that would block reclamation
If reclamation ever reuses
SessionArchiveManager— copy out, verify, then remove upstream — two current behaviours are in the way. Both are correct for what the archive does today:hashIfSmall()caps integrity hashing at 128 KB (sizeBytes <= 128 * 1024, "Hash only small files to keep sync lightweight"). Fine for sync, but it leaves large archives unverified — and large sessions are the only ones worth reclaiming. The cap would need lifting for sessions explicitly marked for reclamation.trashItemis wired to the archive, not upstream. It sits indeleteArchive()and removessessionRootunder Application Support. The reversible-delete pattern is established; it just points the other way.Risks
VACUUM INTOa temp file, parity-check row counts acrossmessage/part/session/event/todo, then swap.Suggested sequencing
Session.fileSizeBytesis already a first-class field with a sort column — though the Codex and Claude paths don't appear among the indexers that populate it, so coverage may need a look first.Happy to contribute measurements, fixtures, or a PR for whichever slice is actually wanted, and equally happy to be told parts of this are out of scope. If a more useful starting point is adding Grok as a source instead — it's absent today and it's the worst offender I measured — I'd be glad to start there.
All reactions