You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#122718 fixes spool replay/drop ordering. This draft addresses the separate lossy message representation used by shutdown-history and cap-drop recovery; the two changes may need conflict resolution if both land.
Risk
The codec is versioned and legacy-compatible, but recovery is a data-integrity path. This remains a draft for broader CI and maintainer review.
AI code review — automated review for reference; please use your judgment.
Batching the spool files per session is the right idea, and the UIDs make the idempotency
work. One precondition of the batch writer isn't met by the merge, though, and it turns a
recoverable situation into a total loss.
append_recovered_messages_batch documents itself as replaying one versioned envelope
(hermes_state_messages.py:485) and rejects a repeated message_uid outright
(:500-503). shutdown_flush.py:218-220 concatenates every spool file for the session into
a single call, so the input is no longer one envelope.
A cap-dropped file and an agent-history snapshot can hold the same live message: the
cap-dropped dict came out of _dirty_transcripts (session_transcript.py:139) and the
shutdown snapshot is _session_messages (run_shutdown.py:1172), and a message that was
enqueued and later persisted can sit in both. message_uid is deliberately not derived
from content, timestamp or tool-call ids (message_metadata.py:77-78) — it is minted once
and copied, which is exactly what makes it stable across those two snapshots. Same uid,
twice, in one batch.
Measured on the same two files, base vs head:
recovered
files left
base
1 (already in db)
pending-hist.json
head
0
both preserved
The batch that arrived was [UID-SHARED, UID-LOST, UID-SHARED, UID-LOST], where UID-LOST
is a message that exists only on disk — the exact data this recovery path exists to
save. Because the write is all-or-nothing, one duplicate costs the whole session, and every
subsequent boot repeats the failure on the same files.
So base recovered the messages it could; head recovers nothing. Worth noting the guard is
right to exist — it is the caller that must not hand it two envelopes at once. Deduping
merged messages by message_uid before the call keeps the crash-after-commit idempotency
the batching was for, and is a couple of lines at the merge point; alternatively the writer
could tolerate a repeated uid by keeping the first occurrence rather than raising, since
the later existing_uids filter already collapses anything genuinely in the DB.
Not asking to drop the batching — the atomic assistant/tool adjacency it buys is real, and
the (ts, seq, filename) ordering is a genuine improvement over sorting on a uuid4 name.
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
area/sessionsSession lifecycle, resume, persistence, historycomp/gatewayGateway runner, session dispatch, deliveryP2Medium — degraded but workaround existssweeper:risk-session-stateSweeper risk: may lose/corrupt/mis-associate session or context statetype/bugSomething isn't working
3 participants
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.
Summary
Preserve full transcript message semantics when shutdown recovery spools are the only durable copy.
Verification
tests/gateway/test_session_messages_shutdown_preserve.pytests/gateway/test_shutdown_flush.pytests/gateway/test_pending_queue_spool.pyResult: 21 passed, 0 failed.
git diff --checkpassed.Related work
#122718 fixes spool replay/drop ordering. This draft addresses the separate lossy message representation used by shutdown-history and cap-drop recovery; the two changes may need conflict resolution if both land.
Risk
The codec is versioned and legacy-compatible, but recovery is a data-integrity path. This remains a draft for broader CI and maintainer review.
Base:
663362680b6ffa4fbffeb58f6682564239a1953bCo-authored-by: FroRaut 79215537+Froraut@users.noreply.github.com