Repository navigation
fix(chat): session-loss ordinal mismatch + long-session render OOM + version restore - #11
Merged
Merged
Conversation
added 4 commits
October 14, 2026 02:24
…load; add version restore Session loss (2026-10-14 incident, 1386 rows lost from one retry tap): deleteFromMessage / retryFromMessage / truncateBeforeEdit resolved their deleteMessagesAfter cutoff via visible-user ordinal, but the two counters disagreed: the UI side counted every user-role ChatMessage while the DB walk (visibleUserCutoff + anchorHeadHasVisibleUserText) skipped toolResult-only user rows. On any session with tool traffic the ordinal resolved to a row dozens of turns early, and deleteMessagesAfter archived + deleted the entire session tail. Fix: anchor by the tapped message's DB row id (ChatMessage.id is the MessageEntity.id; sourceDbIds covers merged assistant bubbles) via new ChatDao.sortOrderForMessageId. visibleUserCutoff / anchorHeadHasVisibleUserText removed. DeleteAnchorByIdTest pins the anchor-selection logic. Crash (tombstone_09/12, RenderThread/SKIA 4.68GB native in 11s): MAX_TAIL_MESSAGES 4000 -> 500. The UI tail is the initial render window; at 4000 a 1441-message session loaded every row into the UI on open and SKIA exhausted Scudo mappings. 500 bounds the worst case; older history stays one tap away via loadOlderMessages turn paging; the DB remains the full transcript. Recovery: ChatRepository.restoreArchivedVersions re-inserts rows lost to the ordinal-mismatch truncation from message_versions (latest version per message, above the current tail, idempotent).
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.
Root causes
1. Session loss (2026-10-14 incident — 1386 rows lost from one retry tap)
deleteFromMessage / retryFromMessage / truncateBeforeEdit resolved their deleteMessagesAfter cutoff via visible-user ordinal. The two counters disagreed:/n/n- UI side: counts EVERY user-role ChatMessage, including toolResult-only carrier rows that render as nothing
On any session with tool traffic (agent loop persists a synthetic user row per tool_result), ordinal N on the UI side resolved to a DB row dozens of turns early → deleteMessagesAfter archived + deleted the entire session tail.
2. Crash (tombstone_09/12 — RenderThread/SKIA 4.68 GB native in 11 s)
MAX_TAIL_MESSAGES = 4000: the UI tail IS the initial render window. A 1441-message session loaded every row into the UI on open → SKIA exhausted Scudo mappings → abort.
Fixes
Tests