Context
The web/mobile timeline cache (shared/src/cache.ts, web/src/cacheIdb.ts) persists a raw event log per channel (CachedTimeline = { events: WireEvent[], hasMore }, max 300/channel): message.posted rows with their original text plus separate modifier events accumulated from the ack/WS path. On warm reload, mergeHistory (shared/src/timeline.ts) must re-apply those modifiers or acked edits/reactions silently vanish — this replay is the last structurally load-bearing copy of the client fold and has been the root of the warm-reload staleness family (#454, #460, #467).
Unlocked by the folded catch-up wire
Once reconnect/catch-up ships watermarked folded rows (lastModifierId on wire rows, server change-feed keyed by message_state.last_modifier_id), the cache can stop being an event log:
- Persist folded rows only (the wire shape already IS the folded shape; cached rows carry
lastModifierId).
- Live WS modifiers update the cached row in place (or are dropped — the next delta heals) instead of appending to a replay log.
mergeHistory's modifier-replay path and cachedTimelineNeedsStructuralRepair retire entirely; warm reload becomes hydrate + watermark-gated delta.
Notes
- Needs cache schema versioning (existing IndexedDB data is a raw log; simplest migration: drop and refetch on version bump).
- Effect schemas ignore excess keys, so cached folded rows are forward/backward tolerant.
- Deliberately split out of the folded-wire PR to keep that train reviewable.
Context
The web/mobile timeline cache (
shared/src/cache.ts,web/src/cacheIdb.ts) persists a raw event log per channel (CachedTimeline = { events: WireEvent[], hasMore }, max 300/channel):message.postedrows with their original text plus separate modifier events accumulated from the ack/WS path. On warm reload,mergeHistory(shared/src/timeline.ts) must re-apply those modifiers or acked edits/reactions silently vanish — this replay is the last structurally load-bearing copy of the client fold and has been the root of the warm-reload staleness family (#454, #460, #467).Unlocked by the folded catch-up wire
Once reconnect/catch-up ships watermarked folded rows (
lastModifierIdon wire rows, server change-feed keyed bymessage_state.last_modifier_id), the cache can stop being an event log:lastModifierId).mergeHistory's modifier-replay path andcachedTimelineNeedsStructuralRepairretire entirely; warm reload becomes hydrate + watermark-gated delta.Notes