fix(session): stop leaving an empty messages.jsonl in every session - #4585
Draft
ZaynJarvis wants to merge 1 commit into
Draft
fix(session): stop leaving an empty messages.jsonl in every session#4585ZaynJarvis wants to merge 1 commit into
ZaynJarvis wants to merge 1 commit into
Conversation
Committing with keep_recent_count=0 moves every message into history/archive_NNN and then rewrote the live file as an empty string, so each session directory kept a 0-byte messages.jsonl forever. Users see a tree full of files that contain nothing. Remove the file instead. "No live messages" and "an empty list of live messages" are the same state, and VikingFS.rm is documented idempotent. The catch is #3820, which made messages.jsonl the materialization boundary so a half-created session root is not used for session-aware recall (retrieve/context_assembler/pipeline.py:44). Deleting the file naively would make every committed session look half-created and drop it out of context assembly. So is_materialized() now also accepts history/: a committed session has archives, a half-created root has neither. The boundary #3820 drew is preserved, it just has two halves now. Also guard the commit path's strict live read: once the file can be absent, a second commit with nothing new must read as empty rather than raising. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft — the
is_materialized()change touches the boundary #3820 deliberately drew, so I want that looked at before this merges.Problem
Committing with
keep_recent_count=0moves every message intohistory/archive_NNNand then rewrites the live file as an empty string (session.py,_write_to_agfs_async). Every session directory therefore keeps a 0-bytemessages.jsonlforever.This is the single most complained-about piece of session-directory clutter — it has come up from more than one person internally and in the user group. A directory listing full of files containing nothing is hard to read and hard to explain.
Change
Remove the file rather than writing zero bytes. "No live messages" and "an empty list of live messages" are the same state, and
VikingFS.rmis documented idempotent, so a session that never wrote a live file needs no separate guard.The part that needs review
#3820 made
messages.jsonlthe materialization boundary:is_materialized()exists so a half-created session root is not used for session-aware recall (retrieve/context_assembler/pipeline.py:44returnsNonewhen it is false).Deleting the file naively would make every committed session look half-created and silently drop it out of context assembly. That would be a real regression, and it is the reason this is not a one-line change.
So
is_materialized()now accepts eithermessages.jsonlorhistory/:messages.jsonl→ materializedhistory/→ materializedThe boundary #3820 drew is preserved; it just has two halves now that the live file is no longer permanent.
Also guarded the commit path's strict live read: once the file can be absent, a second commit with nothing new must read as empty rather than raising.
Scope
This fixes it for all sessions, not only MCP ones. An earlier attempt (#4582, closed) went at the
remembertool instead; that was the wrong layer — the empty file is written by the generic commit path, so every session had it.Tests
tests/session/test_no_empty_live_messages.py, 5 cases: the empty write becomes a removal; a committed session (history only) is still materialized; a live session still is; a half-created root still is not — the #3820 regression case; and a storage failure is not swallowed as "not materialized".tests/session,tests/service,tests/server,tests/retrieveshow an identical failure set with and without the change — 177 failed / 790 errors before and after, 1182 → 1187 passed. Those pre-existing failures are this machine lacking a compiledovbinary and a server config, so I could not exercise a real commit end to end; the new tests use a fake filesystem. Worth a reviewer with a working environment confirming the archive path.