fix(rooms): carry cross-segment turn bookends in historyPolicy: full#59
Merged
Conversation
If a turn straddles a segment boundary (hermes compaction mid-turn, or session/load with an in-flight turn that completes after the load response), historyPolicy: full would surface `amux/turn_complete` without a matching `amux/turn_started` to a late joiner — coterie- style correlators drop the orphan or render the turn as still typing. Both `history_full` and `replay_entries_for_policy` now compute a `cross_segment_turn_carry` set: turn ids whose lifecycle frames touch the active segment OR match the currently active turn. Frames in the log that are turn-lifecycle frames (`amux/turn_started`, `amux/turn_complete`, `amux/turn_cancelled`) with a turn id in the carry set are included in the `full` view even when they live in a prior segment. Behavior: - pre-segment bootstrap and active-segment frames still appear, - turn-lifecycle bookends from prior segments are carried iff their turn touches the active segment, - non-bookend frames from prior segments are still excluded (chunks before rotation stay out of `full`; they're available via `full_lineage`), - frames remain in original `replaySeq` order — carried bookends appear temporally before active-segment frames, so the bracket reads naturally on the client. No wire-shape changes. Today's clients just stop seeing the orphan they couldn't render. Scoped subset of #57 (the broader "orphan chunks outside any turn" case remains open).
…ends The implementation in 7306469 now carries amux/turn_started, amux/turn_complete, and amux/turn_cancelled from prior segments into the `full` view when their amuxTurnId brackets the active segment, but the docs still described `full` as strictly current segment only. Three touch points updated: - docs/design/rooms.md `## historyPolicy` — spell out the lifecycle-frame carve-out and the reason (mid-rotation turn staying bracketed), plus the non-lifecycle-frames-still-excluded guarantee. - src/protocol/attach.rs `HistoryPolicy::Full` doc — same in shorter form for the rustdoc surface. - README.md replay-log bullet and session/attach coverage row — short carve-out mention so the README isn't ahead/behind of rooms.md. CHANGELOG: new Fixed entry under Unreleased calling out the cross-segment turn bookend fix as a scoped subset of #57.
Owner
Author
|
Pushed Docs
CHANGELOG
Marking the PR ready for review. |
This was referenced May 27, 2026
Merged
lsaether
added a commit
that referenced
this pull request
May 27, 2026
Cuts v0.1.3 — rooms + RFD #533 attach polish. Highlights since v0.1.2: - Rooms abstraction with compaction-aware transcripts (#58) and cross-segment turn-bookend carry in historyPolicy: full (#59). Closes #56. - RFD #533-inspired session/attach + session/detach foundation (#46) with replay ordering (#47), streamed history delivery (#53), and ?replay=skip opt-out for attach-aware clients (#50). - amux/* active-turn controls (steer #41, queue #41, cancel #30) plus replay-safe agent request lifecycle openings (#33). - Safe-by-default client-tool blocking (fs/* + terminal/*) with --unsafe-debug-client-tool-broadcast escape hatch (#36). - amux/session_context surfaces the mux/agent cwd to subscribers (#35). Validation: - cargo fmt --check - cargo clippy --all-targets -- -D warnings - cargo test (63 unit + 78 integration = 141 tests) Co-authored-by: lsaether <25539605+lsaether@users.noreply.github.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.
Context
After #58 shipped rooms with mid-turn rotation deliberately preserved (an active turn is not torn down across segment boundaries),
historyPolicy: fullcould leave a late joiner with an orphan:amux/turn_completelands in the active segment, butamux/turn_startedfor the same turn lives in the closed prior segment and was filtered out by the current-segment-only rule. Coterie- and vibe-style correlators either drop the orphan or render the finished turn as if the agent were still typing.Scoped subset of #57 (the broader "orphan chunks outside any turn" case remains open).
Fix
history_fullandreplay_entries_for_policynow compute across_segment_turn_carryset:amux/turn_started/amux/turn_complete/amux/turn_cancelledframe found in the active segment contributes itsamuxTurnId.amuxTurnId(fromactive_amux_turn_id) is also added so an in-flight cross-segment turn'sturn_startedgets carried even before it completes.Frames that are turn-lifecycle frames with an
amuxTurnIdin the carry set are then included in thefullview even when they sit in a prior segment. Non-lifecycle frames (chunks) from prior segments are still excluded — those belong tofull_lineage.Frames stay in original
replaySeqorder, so the carriedturn_startedappears temporally before the active-segment frames and the bracket reads naturally on the client.Wire impact
None — strictly additive. The
fullview returns more frames it should have been returning all along. No new fields, no new methods, no enum variants. Today's clients just stop seeing the orphan they couldn't handle.Tests
Four new unit tests in
src/room/state.rs::tests:history_full_carries_turn_started_when_turn_completed_across_segments— turn_started in seg-1, hermes compaction mid-turn, turn_complete in seg-2; full view contains both bookends in order.history_full_carries_turn_started_when_turn_is_still_active_across_segments— turn_started in seg-1, rotation, turn still in flight; carry pulls turn_started forward viaactive_amux_turn_id.history_full_does_not_carry_turn_that_completed_before_active_segment— a fully prior-segment turn must NOT appear in full view.history_full_lineage_returns_every_segment_unchanged— regression guard that lineage view is unaffected.cargo fmt --check,cargo clippy --all-targets -- -D warnings, 63 lib + 78 integration tests all pass.Test plan
_meta.hermesyet anyway.