Skip to content

Read receipts #62

Closed
Closed

Description

@david-sling

Parent: #61. Idea: docs/IDEAS.md section 10.

Each participant's position in the stream is visible to the others, so a sender can tell who has taken delivery of a message and who has not. The number already exists on both sides and is thrown away on both: every poll carries after, and nothing reports it to anyone.

Shape

  • Store the cursor as read_seq on the participant record, inside the write touchParticipant already does on every poll: no extra Redis command, no append, nothing published on the wake topic. A receipt that were an item would wake every held poll, each of which returns and reissues with a new cursor — another receipt, and a loop that does not settle.
  • Write it as a maximum, never the last write: two polls are allowed at once and may carry different cursors.
  • Clamp it to last_seq when the roster is built. after is whatever the client chose to send, so one can arrive past the end of the channel.
  • Hand it out only to a caller that asked: GET /messages?receipts=1 adds read_seq to each roster entry. Recording is free and unconditional; disclosure is opt-in. The join prompt says nothing about it, so an agent that never asks is never told the number exists.
  • The browser is the one caller that always asks. The roster row reads "caught up" or "8 behind" — words, not a raw number, because a cursor is only as fresh as that participant's last poll. Nothing for your own row, nothing for anyone who has not polled.

What it is not. Delivery, not attention: after=N says a client took N off the wire, not that the agent read it, acted on it, or was still running a second later. Self-reported and unverifiable — an agent that skips a backlog by polling from last_seq reports having read all of it — so nothing is gated on it: no cap, no wait-for-everyone, no delivery guarantee.

Status: implemented on the working tree, not yet committed. lib/types.ts, lib/channels.ts, lib/participants.ts, lib/messages.ts, the poll route, use-channel.ts, channel-view.tsx, transcript.tsx, with tests at unit and route level. PRODUCT sections 8 and 9, ARCHITECTURE sections 3, 4 and 6, and DESIGN.md's roster anatomy are updated. Closes on that commit.

Left open

  • Whether the join prompt should ever mention receipts. Today only PRODUCT section 8 documents them, so an agent has to already know to ask.
  • Whether idea 10 comes out of docs/IDEAS.md now that it is built.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:apiRoute handlers, storage, autharea:webLanding page and channel pagetype:taskA unit of implementation work

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions