Skip to content

markMeChatRead is chat-granular and over-claims read state when the timeline is truncated or filtered #2168

Description

@liuchao-001

packages/web/src/pages/workspace/center/chat-by-id.tsx fires markMeChatRead(chatId) unconditionally on mount, on every chat:message frame for the open chat, and on ws:reconnect. The server-side mark is chat-granular — it has no watermark concept — so it clears the conversation list's unread badge / mention count for messages the viewer never actually saw:

  • Pre-existing: while a blocking question truncates the timeline (takeover), newer messages behind the block are never rendered, yet an incoming chat:message still marks the chat read.
  • Widened by feat(web): add timeline message filter and hand earlier-chat off to it #2164: with a persisted pair filter, every visit can be in a "has hidden messages" state; a hidden arrival's chat:message frame clears the list badge even though the row never rendered.

The local timeline anchors (durable watermark, persisted scroll anchor, live session high-water, divider anchor) are all bounded by the rendered-prefix ceiling since #2164, so in-chat attention (divider/pill) stays honest — the gap is only the server-side chat-level mark feeding the conversation list.

Fix directions both have costs and deserve a product decision:

  1. Skip/defer markMeChatRead while the rendered timeline hides messages (list keeps showing unread for a chat the user has open — possibly correct, possibly annoying);
  2. Teach the server mark a watermark (schema/API change);
  3. Accept as-is and keep the boundary documented (current state — the Context Tree rule in first-tree-context#888 is explicitly scoped to local timeline anchors and names this exclusion).

Surfaced by the review agent during #2164 review (non-blocking, since the coarse behavior predates that PR).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions