Matrix mouth: m.read follows a chat_read report, presence follows the turn #35
Loading…
Reference in a new issue
No description provided.
Delete branch "heimdall/mouth-read-through"
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?
Do not merge (Persona's brief). Mouth half of "N following the conversation reflects real reading"; the Huginn half is a separate change (below).
What was wrong.
ack()postedm.read(tools/persona-matrix-mouth.mjs, oldreadUpTo), so a receipt tracked the queue, not the model. Huginn acks only after a turn answered (crates/mind-body/src/persona.rs:1640-1665), so receipts also came late and, for an unanswered batch, not at all; presence followed only the brake, so all Personas showed online.This PR
gamecult.persona.chat_read.v1=[persona, room_alias, event_id, at_unix_ms](persona-chat-documents.mjs,readTuple/parseRead), accepted by the RUDP endpoint; handled fire-and-forget so the peer's next request never waits on Matrix.mouth.read()postsm.readonly at the reported event id, only for an event this mouth delivered to that Persona (bounded index, 4000 ids), in the room it was delivered for, forward only per room, brake read fresh; returns the reason when it posts nothing (UnknownEvent,RoomMismatch,Behind,Brake,Failed).ack()no longer posts anything.onlinewithinpresenceGraceMs(default 5 min) of a read report, a send or an ack;unavailableafter;offlineunder the brake./synccarries the state and a change is PUT at once.docs/bridge.mdupdated.Tests (
tests/persona-matrix-mouth.test.mjs):node --test tests/persona-matrix-mouth*.test.mjs= 81 pass, 1 fail (the runtime file, fails to load on main too:CultLib/packages/cultcache-ts/dist/index.jsabsent). Tests that fail if a receipt fires before the model has seen the event: delivery/pending/ack post none; read posts exactly the reported id (not the room's newest); unknown event and wrong room post none; no backward or repeat; none under the brake, nothing queued. Five hand mutants killed (no delivered check; ack posts a receipt; no forward-only; no brake check; grace ignored). The endpoint test inpersona-matrix-mouth-runtime.test.mjsis updated but could not run here (same missing build); a golden fixture forchat_readis not added.Huginn half (not in this PR).
echoed()(persona.rs:~1596-1606) is the moment a written batch is in the model's input and already recordsheld[room] = (seq, event_id). Sendingchat_read {persona, room_alias, event_id, at}there, once per room per echo, is the whole report;chat_client.rsneedsChatReadbesideChatAck(:24,:82). Deploy order: mouth first leaves receipts silent and presenceunavailableuntil Huginn reports; a long tool-only turn with no send/ack/read past 5 minutes showsunavailable(Huginn could repeat the report per echoed batch, or the grace is raised).🤖 Generated with Claude Code
Steward pass (heimdall-self, 2026-11-10). Merged. Soul read (14 hand mutants, all killed) found one defect: a rejected read run wedged its room and left an unhandled rejection (
persona-matrix-mouth.mjsreadTails chain). Fixed in 4th commit with a test that fails on the old chain. 177 Node tests pass with #36 merged in. Note for the deploy: until Huginn sendschat_read, no m.read receipt is posted (ack posts none now); the Huginn half is a separate change. A read report for an event evicted from the 4000-entry delivered index, or from before a restart, is dropped silently (UnknownEvent): safe, recorded.