Persona: send chat_read for the newest placed event per room at the echo #28
Loading…
Reference in a new issue
No description provided.
Delete branch "eureka/chat-read-receipt"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Heimdall's Bifrost #35 (mouth read-through) waits on this: Huginn sends her read receipt when the model's input holds the event.
What it does
gamecult.persona.chat_read.v1, positional[persona, room, event_id, at_unix_ms],ChatReadbesideChatAckincrates/mind-body/src/chat_client.rs,Chat::read, sent byRudpChat::readover the same loopback RUDP endpoint aschat_ack(no answer awaited).PersonaInbox::echoed(the seam: ata60e83fpersona.rsechoed()1593,held[room]insert 1596-1600, the one ack at 1661), i.e. when the CLI has taken the line. One report per room per echoed batch. Not sent at write, not from the ack path.report_readkeeps a per-room "reported through seq" so a retold or revised batch never repeats an event or moves a receipt back. It advances only on a report the mouth took.Decision: newest placed event per room, no ids on earlier lines
Only the newest event id per room is reported. Every delivery of the echoed batch is a
messageline of the input and theearlierlines come before it, so the newest message is the newest event the model saw; queued-unread deliveries are not in the batch and are never reported. Event ids are NOT added to earlier prompt lines: a receipt needs only the latest event the model saw, and per-line ids grow the prompt for no receipt benefit. (Same text is in the code comment onreport_read.)Room identifier: the delivered room id, not the alias
echoed()holdsheld[room_alias] = (seq, event_id), keyed by alias, becausesendaddresses by alias.chat_ackcarries no room at all (persona and seq only). The delivery also carriesroom_id, and the report sends that (second tuple slot; the field is namedroom, the wire is positional). Reason: the mouth must postm.readto the delivered room, and a room id names exactly one room with no lookup; a direct room has no alias (its alias is its id). Bifrost'sread()at heimdall/mouth-read-through 0a44bf8 accepts eitherknown.roomAliasorknown.roomIdfor the event and posts toknown.roomId, so the id is accepted there. The mouth and Bifrost are untouched.Tests (
cargo test -p mind-body, run underunshare -rbecause the control-store tests need root-owned temp dirs)a_read_is_sent_only_at_the_echo_one_per_room_for_the_newest_event_that_went_into_her_input: fails if a report names an event whose text is not in the prompt (including a queued-unread one), sends before the echo, sends more than one per room, names the alias, or puts event ids on earlier lines.a_line_told_and_not_echoed_reports_nothing_and_a_report_is_never_repeated_or_moved_backa_read_the_mouth_does_not_take_is_dropped_without_ending_the_session_and_is_tried_again_with_the_next_batcha_read_reaches_the_mouth_as_the_positional_tuple_persona_room_event_instant(RUDP,tests/chat_rudp.rs)tests/public_surface.txtupdated for the new trait method, struct and const.Hand mutants (cargo-mutants not installed; run once, not committed), each caught: newest->oldest per room, forward guard off, advance on failed report, alias instead of room id, no report at all at the echo, report at write instead of echo, failed report ends the session.
Deviations / open
room_alias(wire position unchanged).earlier-only events cannot be reported (ContextLinehas no event id); out of scope by design.unsafe_installsintegration test fails underunshare -r(uid 0 artefact of the namespace; it does not touch this change).🤖 Generated with Claude Code