-- 0011_session_persona: per-session role binding + per-message authoring role -- (DevDocs/design/22 多角色并存 + 按会话选角 §4.1 / §7-5, 批次 1). -- -- chat_sessions.persona_id: which role a conversation belongs to. It is the -- single source of truth for "this session is Cyrene / this session is Y" -- (design/22 §2: session-level wins, channel-level only seeds a new session, -- request-level is a temporary override that is never persisted). -- -- chat_messages.persona_id: the role that SPOKE a message, so the context and -- the UI can tell "who said the Nth turn" after a session switched roles -- (design/22 §7-5: switching keeps the context, so each message must carry its -- authoring role). -- -- '' means "inherit the current global default role" (owner.yaml:defaultPersona). -- That is why NO backfill is needed: every pre-existing session and message keeps -- persona_id = '' and therefore keeps resolving to the default role, i.e. the -- pre-multi-character behavior is byte-for-byte unchanged (design/22 §4.7), and -- changing owner.yaml:defaultPersona still moves those rows (design/22 §7-6). -- -- The 0003 chat_sessions / chat_messages tables already exist at this point, so -- ALTER ADD COLUMN is the correct, non-destructive step. The canonical schema -- (including these columns) is also re-issued idempotently by -- internal/runtime/history.NewStore so a fresh in-memory store used by tests stays -- self-contained; the migration is the authoritative path for an existing -- database. -- -- No index is added: persona_id is never a query predicate on the hot paths -- (sessions are read by primary key, messages by session_id + created_at, which -- idx_chat_msgs_session_created already covers). It is read as a column only. ALTER TABLE chat_sessions ADD COLUMN persona_id TEXT NOT NULL DEFAULT ''; ALTER TABLE chat_messages ADD COLUMN persona_id TEXT NOT NULL DEFAULT '';