Mouth: fetch one named event's image for its Persona, store it, post an inert receipt (CHAT_FETCH, off by default) #73

Merged
heimdall merged 4 commits from eureka/mouth-fetch-attachment into main 2026-11-12 00:59:28 +00:00

2026-11-12

docs: the fetch line carries room and event ids; no error-derived text
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-12 00:57:32 +00:00
Mouth: fetch failures log fixed words only; pin deadline signal, redacted clause, pre-PUT abort; receipt names the resolved event
The fetch-error and file-receipt-not-proven lines are gone: a failure folds into the one fetch line as cause=Class/status, never a message.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-12 00:44:08 +00:00
Mouth: fetch one named event's image for its Persona, verify, store, post an inert receipt (CHAT_FETCH, off by default)
chat_fetch_request.v1 [request_id, persona, room, event_id] and chat_fetch_receipt.v1
[request_id, outcome, room_id, image, receipt] with a closed 14-word outcome enum. The mouth
reads live membership, the full room state, and the event itself; takes content.url from the
event; fetches through fetchImage (one optional deadline signal added); decides info.sha256
against the computed hash before images.put; posts the contract's org.gamecult.file_received
as her own user (thread reply, else plain m.reference), idempotence read from Matrix.
One 15 s deadline owns the fetch; throwIfAborted and released() are the first step inside the
gate, as send does. Event id, room, and the sender-controlled album root must be path-safe
Matrix ids or nothing is built from them. Golden fixtures persona-chat-v7.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-12 00:34:10 +00:00