Repository navigation
Read receipts #62
Description
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_seqon the participant record, inside the writetouchParticipantalready 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_seqwhen the roster is built.afteris 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=1addsread_seqto 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.
Activity