Event
Origin
When it fires
Carries
UI reacts
◎
chat.message.user_appended
New user message ingested (per message inside a turn)
user_id, content, turn_id, source_channel_id
append user bubble to timeline
◎
chat.message.token
LLM emits one streaming token
delta, turn_id, source_channel_id
concatenate into persona bubble
◎
chat.message.done
Channel.send() succeeds, turn complete
content, delivery, source_channel_id
finalise bubble · render channel pill
◎
chat.message.voice_ready
TTS finishes, voice artifact cached
audio_url, duration
show ▶ voice play button
◎
chat.mood.update
L6 episodic_state refreshed (post session-close, via extraction's session_mood_signal)
persona_id, user_id, mood_summary
re-render chat header mood · prepend mood-shift row into Memory Timeline panel
◎
chat.session.boundary
Session transitions open → closed · or a new session starts
closed_session_id, new_session_id, events_count, thoughts_count (close edge)
timeline session-close summary row + timestamped horizontal rule in bubble column
◎
memory.event.created
Consolidate or import commits a new L3 event (RuntimeMemoryObserver → on_event_created)
event_id, description, emotional_impact, session_id
prepend event row into Memory Timeline panel
◎
memory.thought.created
Fast-loop reflection, slow_tick G phase, or import commits a new L4 thought / intention / expectation
thought_id, type, subject, description, source ∈ {reflection, slow_tick, import}, filling_event_ids
prepend thought / intention / expectation row into Memory Timeline panel (subject='persona' feeds # How you see yourself lately on next turn)
◎
memory.entity.confirmed
L5 entity resolves to confirmed (new row, alias-matched, or operator-merged · uncertain entities are filtered at source)
entity_id, canonical_name, kind, merge_status
prepend entity row into Memory Timeline panel
◎
memory.entity.description_updated
slow_tick synthesizes a description over threshold, or owner PATCHes via admin API
entity_id, canonical_name, description, source ∈ {slow_tick, owner}
prepend entity-description row into Memory Timeline panel
◎
chat.settings.updated
voice_enabled / provider / etc flipped (e.g. SIGHUP)
changed_fields
cross-tab config sync
◎
chat.connection.ready
SSE handshake complete
—
green dot in status pill
◎
chat.connection.heartbeat
Every 30s · NAT keepalive
—
no visual