Extract sollinhaChatStreamBody + mockSollinhaChat into campaignE2EFixtures.ts
(canonical v7 wire format), reuse across all 6 chat e2e specs and migrate the
two legacy specs (transcribe, openingChips) from the format that fails the v7
client schema. Closes#556
- P1: B167 settle forçava open=true no load desktop mesmo com sessão restaurada
open:false (storage auto-curava para true); restore agora vence quando existe
- prune: cabeça assistant quebra convertToModelMessages; drop até ancorar em user
- MarkdownLink: node do react-markdown não vaza para <Link>/<a>
- isUIMessage: parts com shape inválido falham-closed no restore
- B167 mock: chunk legado {"type":"text"} falha schema v7 (status preso em erro);
agora usa start/text-start/text-delta/text-end/finish
- sessionStorage por aba: mensagens + estado aberto, restaurados no reload;
escrita só em estado settle (nunca mid-stream); guardrail 50 msgs / 256 KB
- links internos (/campanha…) do markdown navegam via next/link (sem reload)
- e2e novo + ajuste do B167 (visita mobile nova agora loga em viewport mobile)
- Converse (useChat) lifts to the provider: survives desktop panel <-> mobile
drawer swaps, internal /campanha navigation and resize (new tab still resets).
- Chat Panel/Separator always mounted (RRP panel-count change forces a full
navigation); footprint hidden via elementRef + .b167-ai-chat-hidden
(display:none !important), avoiding RRP's imperative collapse/expand races.
- Single 'open' flag drives both surfaces (open && viewport); reconciled with
the panel at desktop settle and on user drag-collapse (gated by isUserInteraction).
- Mobile Drawer extracted to CampaignAIDrawer; FAB/setOpen unified; focus moves
into the chat on the mobile->desktop swap.
- e2e campaignAiChatResize: desktop->mobile, mobile->desktop, closed stays
closed, fresh mobile visit closed, navigation survival, new tab resets.
- Impl plan: docs/plans/migrar-chat-painel-drawer-resize-impl.md
Closes#416