Bug
Used to work: scroll the chat-widget up → loads more historical messages from the room. As of PR #950 baseline, scroll-to-top no longer pages older messages in. The widget renders a fixed initial slice and stops.
Joel called the fix shape directly: cursor-based paging via the ORM + an IntersectionObserver on a sentinel element at the top of the message list. When the sentinel becomes visible (user has scrolled to top), kick off the next-page fetch with before=<oldest visible message id>.
Why it matters
- Joel can't review prior conversation arcs from the UI.
- Personas already have full history via RAG, but Joel can't see what they're seeing.
- "It worked before" — regression, not a missing feature.
Fix shape
- ORM side:
data/list for chat_messages with { filter: { roomId, timestamp: { $lt: cursor } }, orderBy: [{ field: 'timestamp', direction: 'desc' }], limit: 50 }. Confirm cursor pagination is implemented in DataList/ORM; if not, add it (no fallback to offset — cursor is correct for messages).
- Widget side:
IntersectionObserver on a sentinel <div> at the top of the message list. On intersection, dispatch a "load older" action that fetches the next 50 with the cursor = oldest currently-rendered timestamp. Prepend results, preserve scroll position.
- Edge cases: dedup against in-memory cache, stop fetching when result < limit, debounce so rapid scroll doesn't fire 10 fetches.
Out of scope for this issue
- Search-jump-to-message (separate issue)
- Date-divider grouping in the rendered list
Linked
PR #950 follow-up — UX-class regression Joel called out during paired QA 2026-04-23.
Bug
Used to work: scroll the chat-widget up → loads more historical messages from the room. As of PR #950 baseline, scroll-to-top no longer pages older messages in. The widget renders a fixed initial slice and stops.
Joel called the fix shape directly: cursor-based paging via the ORM + an IntersectionObserver on a sentinel element at the top of the message list. When the sentinel becomes visible (user has scrolled to top), kick off the next-page fetch with
before=<oldest visible message id>.Why it matters
Fix shape
data/listforchat_messageswith{ filter: { roomId, timestamp: { $lt: cursor } }, orderBy: [{ field: 'timestamp', direction: 'desc' }], limit: 50 }. Confirm cursor pagination is implemented inDataList/ORM; if not, add it (no fallback to offset — cursor is correct for messages).IntersectionObserveron a sentinel<div>at the top of the message list. On intersection, dispatch a "load older" action that fetches the next 50 with the cursor = oldest currently-rendered timestamp. Prepend results, preserve scroll position.Out of scope for this issue
Linked
PR #950 follow-up — UX-class regression Joel called out during paired QA 2026-04-23.