Skip to content

chatd ask: wire-level correlation between a queue entry and its materialized message #119

Description

@ThomasK33

Context

#114 shipped a client-side attribution gate for queued submissions: when POST /chats/{id}/messages returns queued: true, the SDK withholds attribution until the queue entry materializes as the turn's own user message. Because nothing on the wire links queued_message.id (queue-entry id space) to the chat_messages id it eventually becomes, the gate correlates by:

  1. structural content equality — the queue entry's content and the materialized message's content are produced by the same server-side parse/strip (db2sdk.chatMessageParts), so a canonicalized comparison is exact today;
  2. FIFO confirmation — a matching user message snapshot becomes the anchor candidate, confirmed when the next queue_update (which carries the full queue) no longer lists our entry; a candidate observed while our entry is still listed is discarded as an earlier identical-content entry's materialization.

Residual ambiguity (why a wire correlation is still wanted)

Two entries with byte-identical content from concurrent clients can still be mis-anchored in one window: a reconnect that spans both promotions replays both user-message snapshots but only the connect-time queue state — the per-promotion queue_updates that would have disambiguated them are collapsed into one. The gate then anchors on the newest matching snapshot, which may be the other client's twin. Content matching is also inherently coupled to the server's content encoding staying replay-stable.

Ask

Expose the correlation chatd already has in hand at promotion time (FinishTurn/FinishInterruption/PromoteQueuedMessage insert the message and delete the queue entry in one transaction):

  • Preferred: stamp the materialized user message (or its message stream event) with the queue-entry id it came from — e.g. queued_message_id on codersdk.ChatMessage or on the stream envelope; or
  • allocate and return the future message id in CreateChatMessageResponse.queued_message; or
  • extend queue_update with the promotion pairing (queued_message_idmessage_id).

Any of these lets the SDK anchor exactly, delete the content-matching heuristic, and close the identical-twin window.

Downstream context

coder/tss runs many turns against long-lived chats where corrective follow-up turns are submitted precisely while the previous run is dying — the population where queued submissions and identical retried prompts are common.


Generated with mux • Model: anthropic:claude-fable-5 • Thinking: xhigh

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedTriaged and accepted by a maintainerenhancementNew feature or improvement

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions