A revisited session stores one contiguous newest message interval, uses its
true oldest cursor, and can paginate to an attributed peer prompt that was
persisted while the session was inactive.
In scope
Add a pure latest-window reconciliation helper for session messages.
Track which cached IDs existed when a latest fetch began.
Join overlapping cached and fetched windows without duplicates.
Replace a disjoint cached prefix while retaining live rows received during
the fetch.
Apply the helper and its cursor to fetchAndStoreMessages.
Add focused unit tests before the implementation.
Add a deterministic desktop Playwright regression for same-task sibling
session history.
Exclusions
Backend, database, MCP, and WebSocket routing changes.
New API fields, pagination modes, or eager gap filling.
Responsive layout or interaction changes.
New user-facing text or localization keys.
Implementation acceptance conditions
A disjoint stale cache and newest response produce only the contiguous
fetched suffix plus rows proven to have arrived during the request, with
oldestCursor equal to the fetched suffix boundary.
An overlapping response preserves cached older pages, deduplicates shared
rows, retains live additions, and keeps one chronological interval.
In a browser flow with two sessions on one task, a receiver cached before it
becomes inactive can later paginate to exactly one attributed sibling prompt
after more than 100 newer rows have been persisted.
TDD sequence
Add helper tests for an overlapping window, a disjoint stale window, and a
live row that appears after the fetch begins. Run them and record the RED
failure.
Add the same-task sibling Playwright scenario and record that the prompt is
unreachable with the stale cursor.
Implement the smallest pure reconciliation helper and wire it into the
latest-fetch path.
Run the focused unit and browser tests to GREEN, then refactor without
widening the store or backend contracts.
apps/web/e2e/helpers/api-client.ts only if the existing message seed helpers
cannot express the deterministic same-task scenario.
Exact verification commands
(cd apps && pnpm --filter @kandev/web exec vitest run hooks/domains/session/message-window-reconciliation.test.ts)(cd apps/web && pnpm e2e:run --project chromium tests/chat/inactive-session-transcript-reconciliation.spec.ts)(cd apps/web && pnpm run typecheck)(cd apps/web && pnpm run lint)(cd apps/web && pnpm run i18n:ratchet)
Results
RED unit evidence: the pre-fix hook retained stale-1 and stale-2 around a
disjoint newest response and derived oldestCursor from stale-1.
RED browser evidence: the newest receiver message loaded, but upward
pagination could not reach the persisted attributed peer prompt.
GREEN implementation: reconcileLatestMessageWindow joins overlapping
windows, replaces disjoint prefixes, preserves in-flight live additions, and
returns the cursor for the actual contiguous boundary.
PR fixup: the deduplicated request owns the first cache baseline, timestamp
ordering preserves the backend's normalized-microsecond precision, and older
out-of-order live rows remain for the next page instead of preceding the
cursor boundary.
GREEN verification:
pnpm --filter @kandev/web exec vitest run hooks/domains/session/message-window-reconciliation.test.ts hooks/domains/session/use-session-messages.test.ts (27 passed)