Host-composed command replies, runtime and admission diagnostics, and
lifecycle notices now carry role="system" plus a descriptive system_type at
their producer. send_with_budget persists both fields on progress records as
well as ordinary chat rows, and gateway/history.py replays the recorded voice,
so a reload no longer re-narrates host text in Ouroboros's own voice. Rows
written before these fields existed keep the assistant default.
Model speech stays model-authored: round narration, proactive replies, final
answers and question pointers are selected by the existing narration fact
rather than by reading message text.
The Host Service named-operation view accepted only direction="out" terminal
rows, so a typed command reply would have stayed pending forever; it now
recognizes either output voice while keeping the exact-origin ownership check.
tests/test_host_message_voice.py scans runtime send calls and literal chat
envelopes with counted, reasoned model/transport exceptions, so a new
unstamped producer or a stale exception fails the suite; computed aliases stay
a documented review duty. web/tests/host_message_voice.test.js pins the real
Chat consumer: System versus assistant voice, escaped System text, a typed
nonterminal notice that must not finish a working card, and an explicit
terminal fact that still does.
DESIGN defines chat authorship, the System row and the markdown asymmetry;
CHECKLISTS item 30 now covers backend UI-message producers, which closes the
stale pointer in the design-system chapter. The architecture chapter's byte
budget is raised because the previous raise consumed its own headroom and this
description replaces nothing.
Out of scope and unchanged: the message-bus role default, the history replay
gate, PROJECT_ROW_TYPES, question cards, the untyped terminal-host-notice
contract (#1010), the palette-token contradictions (#1125), and the
pre-existing clearing of live-header state by unkeyed notices.
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>