5.3 KiB
Created
Created by tickets.sh create.
Plan
Investigation summary
Read-only investigation found that the most likely cause is live-event ordering between Event::UserMessage and the first Event::SegmentRotated in a fresh session.
Observed flow:
- TUI submit path calls
App::submit_input()/method_for_run()and sendsMethod::Run { input }. crates/pod/src/controller.rshandlesMethod::Runand currently broadcastsEvent::UserMessage { segments }before callingpod.run(input).- TUI receives
Event::UserMessageand appends aTurnHeader/UserMessageblock. Pod::run()callsprepare_for_run()/ensure_segment_head().- In a fresh session,
entries_written == 0, soLogEntry::SegmentStartis committed only at this point. crates/pod/src/segment_log_sink.rsconvertsSegmentStartintoEvent::SegmentRotated.- TUI handles
SegmentRotatedby clearing blocks throughreset_for_rotation()and replayingSegmentStart.history. - The current
UserInputhas not been committed yet, soSegmentStart.historydoes not contain the first user message. - Later
LogEntry::UserInputis committed, but the live path does not emitEvent::UserMessagefrom that commit, so the cleared user block is not restored in the live TUI view.
Likely affected files / functions:
crates/tui/src/app.rsApp::submit_input()method_for_run()App::handle_pod_event(Event::UserMessage)App::handle_pod_event(Event::SegmentRotated)reset_for_rotation()
crates/pod/src/controller.rsMethod::Runbranch
crates/pod/src/pod.rsPod::run()prepare_for_run()ensure_segment_head()
crates/pod/src/segment_log_sink.rs- session-log-derived live event conversion
Implementation intent
Move the live Event::UserMessage authority away from the controller's pre-pod.run() optimistic broadcast and toward the persisted LogEntry::UserInput commit path.
Preferred shape:
- Remove the controller-side
Event::UserMessagebroadcast that happens beforepod.run(input). - Emit
Event::UserMessagewhenLogEntry::UserInputis committed. - Prefer doing this in the session-log-derived event lane, such as
SegmentLogSink, soSegmentStart,UserInput, and other replayable entries share a single ordering source.
This should make a fresh session produce SegmentRotated first and then UserMessage for the committed input, preserving the first user message in the TUI after rotation.
Requirements / invariants for implementation
- Do not fix this by adding a TUI-only fake/pending user block after rotation.
- Do not reintroduce local optimistic user blocks in
App::method_for_run(). - The displayed message should correspond to
LogEntry::UserInput/ persisted history. - Existing session attach/restore must continue to replay
UserInputfromSnapshot.entries. - 2nd and later sends must continue to display normally.
- Running-state queued input should display when the queued run is actually accepted/committed, not merely when typed.
- Composer input history should remain TUI-local and unaffected.
Suggested validation
- Add or update a Pod/session-log event ordering test for a fresh session's first
Method::Run, asserting the live event stream makes the committed user message visible after the initial segment rotation. - Add or update TUI app/view-model tests if available:
- Current problematic ordering
UserMessagethenSegmentRotatedclears the block. - Corrected ordering
SegmentRotatedthenUserMessageleaves the block visible.
- Current problematic ordering
- Confirm snapshot restore still creates user blocks from
LogEntry::UserInput. - Run focused tests for
pod/tuicrates as appropriate, plus formatting/checks that are reasonably scoped to the touched code.
Review: approve
External review summary
Status: approved
Reviewer inspected the ticket, investigation artifact, and implementation commit 501dcc9 fix: show initial TUI user message in branch tui-new-session-first-message-missing.
Findings:
- The implementation matches the ticket intent and investigation result.
- The controller-side pre-run optimistic
Event::UserMessagebroadcast is removed from the authoritative path. - Live
Event::UserMessageemission is tied to persistedLogEntry::UserInput/ session-log-derived ordering. - Fresh sessions should now see initial
SegmentRotatedbefore the committed user message event, preserving the first message in the TUI view. - The fix does not use a TUI-only fake/pending message.
- No unnecessary protocol/schema expansion was found.
- Existing snapshot restore, later sends, queued input, and composer input history did not show obvious regressions from the diff.
Validation reviewed:
cargo fmtcargo test -p podcargo test -p tui
Parent decision needed: none.
Closed
Merged branch tui-new-session-first-message-missing via merge commit ff27917 after external review approval. Validation on develop passed: cargo fmt --check, cargo test -p pod, cargo test -p tui, cargo check -p insomnia, ./tickets.sh doctor.