diff --git a/docs/changelog/2026-09-12-b201.md b/docs/changelog/2026-09-12-b201.md
new file mode 100644
index 00000000..e93db320
--- /dev/null
+++ b/docs/changelog/2026-09-12-b201.md
@@ -0,0 +1 @@
+**B201 — Sollinha e título de demanda no nome canônico `deepseek-flash` (DeepSeek V4.1 Flash) (2026-09-12):** o DeepSeek lançou o V4.1 Flash em 2026-09-10 e o nome canônico passou a ser `deepseek-flash`; o legado `deepseek-v4-flash` continua aceito como alias servido pelo próprio V4.1-Flash ao preço Flash, mas o modelo foi aposentado. Os 2 call sites do app passaram ao nome canônico — o chat do Sollinha (`src/app/(campaign)/campanha/api/ai-chat/route.ts:62`) e o gerador automático de título de demanda (`src/utilities/ai/campaignDemandTitle.ts:31`) — com o literal trocado no call site (2 linhas, sem constante compartilhada: DRY < 3 e os módulos são independentes). Comportamento visível idêntico: gate de papel (leader lockdown), tools, prompt, rate limit e sessão do chat intocados; visão do V4.1 continua desligada e o provider segue `api.deepseek.com` (`@ai-sdk/deepseek` 3.0.19, sem bump). Sem migration, sem UI, sem teste novo — nenhuma camada pina o literal (e2e mockam a rota HTTP; unit cobre só o fallback sem `DEEPSEEK_API_KEY`). Verificação: `pnpm gate:fast` verde (lint/format/typecheck/knip/cycles + 284 arquivos/2687 testes unit); CI do PR a preencher; deploy manual pendente.
diff --git a/docs/plans/sollinha-modelo-canonico-deepseek-flash-impl.md b/docs/plans/sollinha-modelo-canonico-deepseek-flash-impl.md
new file mode 100644
index 00000000..e3a5d463
--- /dev/null
+++ b/docs/plans/sollinha-modelo-canonico-deepseek-flash-impl.md
@@ -0,0 +1,68 @@
+# Impl: Sollinha no nome canônico `deepseek-flash` (DeepSeek V4.1 Flash)
+
+Status: aprovado (gate humano 2026-09-12)
+Atualizado em: 2026-09-12
+Issue: #945
+Intenção: docs/plans/sollinha-modelo-canonico-deepseek-flash.md
+Appetite restante: herdado — ~0,5 dia eng (troca de literal + verificação)
+
+## Leitura da intenção
+
+- **Outcome:** o chat do Sollinha e o gerador automático de título de demanda passam a chamar o nome canônico `deepSeek('deepseek-flash')`; comportamento visível idêntico e nenhuma capacidade nova exposta.
+- **O que NÃO negociar:** gate de papel (leader lockdown), tools, prompt, rate limit e sessão do chat intocados; visão do V4.1 continua desligada; provider segue `api.deepseek.com`; SDK fica em `@ai-sdk/deepseek` 3.0.19; docs históricos congelados (`docs/plans/*`, `docs/changelog/*`, `docs/CHANGELOG-AGENTS-HISTORY.md`) não são editados; default de modelo do worktree (OPS101/#944) fora de escopo.
+- **O que reavaliar:** a hipótese "nenhum teste pina o literal" foi verificada (só pins de worktree/opencode em `tests/`; e2e mockam a rota) — se algum teste quebrar por pin da string, é achado novo, não ajuste do plano. "Sem migration" confirmado: nenhum schema Payload tocado.
+
+## Abordagem recomendada
+
+```mermaid
+flowchart LR
+ A["ai-chat/route.ts:62
deepSeek('deepseek-v4-flash')"] -->|"troca do literal"| B["deepSeek('deepseek-flash')"]
+ C["campaignDemandTitle.ts:31
deepSeek('deepseek-v4-flash')"] -->|"troca do literal"| D["deepSeek('deepseek-flash')"]
+ B --> E["gates: lint + typecheck + unit
(+ e2e curado no CI)"]
+ D --> E
+```
+
+**Opções consideradas:** A) trocar o literal direto nos 2 call sites | B) centralizar constante de modelo compartilhada | C) ler o modelo de env.
+**Recomendação:** A — porque são 2 call sites de módulos independentes, o literal vive no call site por convenção do repo, o SDK recebe a string direto e a troca é reversível numa linha por arquivo.
+**Rejeitadas:** B (abstração para 2 call sites de módulos independentes — DRY < 3; criaria acoplamento artificial entre chat e título, e o repo historicamente mantém o literal no call site; dono é o call site + SDK); C (capacidade nova não pedida — mudaria deploy/env sem ganho algum).
+
+**Decisões acessórias (baratas — registradas, não deliberadas):** não criar teste novo pinando a string (teste de implementação sem comportamento; gatilho de revisitação: se o modelo virar configurável); não tocar worktree default nem docs históricos.
+
+### Componentes / mudanças
+
+- **`src/app/(campaign)/campanha/api/ai-chat/route.ts:62`** — única ocorrência no arquivo: `model: deepSeek('deepseek-v4-flash')` → `deepSeek('deepseek-flash')`. Nada mais no arquivo muda; import `deepSeek` de `@ai-sdk/deepseek` já existe.
+- **`src/utilities/ai/campaignDemandTitle.ts:31`** — mesma troca; `deriveDemandTitle` com fallback `null` sem `DEEPSEEK_API_KEY` e timeout de 4s intocados.
+- **Migration:** sem migration (nenhum schema Payload tocado).
+- **Access / Consent:** nenhum helper novo; gate de papel do chat e Consent intocados — sem fail-closed novo porque não há write path novo.
+- **UI:** Impeccable A — N/A sem UI.
+
+## Fases verificáveis
+
+1. **Tracer / server** — trocar os 2 literais (único entregável de código). Verificação: `grep -rn "deepSeek('deepseek" src/` retorna exatamente 2 matches, ambos `deepseek-flash`. Quota: ~15 min.
+2. **UI** — N/A (Impeccable A).
+3. **Gates** — `pnpm gate:fast` (lint + typecheck + unit); push via `pnpm push`. No CI, o e2e curado roda conforme `ci-scope.mjs`; a rota é mockada e não há mudança de contrato — se o diff cair em área de risco sem mapping, o gate falha fechado (`unmapped-risk`) e o curado roda mesmo assim.
+
+## Rabbit holes / Não escopo (engenharia)
+
+- Habilitar imagem/visão do V4.1 no chat — feature nova, outro item.
+- Mexer em prompt, tools, rate limit ou sessão do Sollinha.
+- Bump da SDK `@ai-sdk/deepseek` (fica 3.0.19) ou troca de provider.
+- Default de modelo do worktree (OPS101/#944).
+- Centralizar constante de modelo ou ler de env — sem terceiro call site, sem necessidade.
+- Editar planos/changelogs históricos que citam o literal legado.
+- Criar teste de string do modelo — não há comportamento a proteger.
+
+## Riscos e mitigação
+
+- **Nome canônico rejeitado pela API/SDK:** a SDK repassa a string direto; mitigação é smoke manual do chat e do título no dev (`pnpm dev`); rollback é reverter o literal (1 linha por arquivo).
+- **Comportamento diferente entre V4.1 e o alias legado:** a intenção registra que o legado já é servido pelo V4.1-Flash ao preço Flash — a troca não muda comportamento; preço inalterado.
+- **Algum consumidor/teste pina o literal:** verificado — nenhum em `src/` além dos 2 call sites; `tests/` só tem pins de worktree/opencode; e2e mockam a rota.
+- **Falso ganho de escopo (visão/prompt/tools):** cortado explicitamente nos rabbit holes e no "Fora de escopo".
+
+## Aceite de engenharia
+
+- [ ] Aceite de produto da intenção ainda coberto (2 call sites no nome canônico; comportamento visível idêntico; nenhuma capacidade nova)
+- [ ] Invariantes AGENTS/engineering-standards (sem migration, sem access/Consent, sem twinning, literais PT/URLs intocados)
+- [ ] Testes de domínio previstos (unit/int) onde access/write paths mudam — N/A: sem access/write path; a suíte existente roda em `pnpm gate:fast` e no e2e curado do CI
+
+Self-score decision-quality: 5/5 — decisão cara (A vs B vs C) com rejeitadas explícitas; cabe no appetite de ~0,5 dia; rabbit holes nomeados; depth check feito (não criar abstração/constante para 2 call sites); outcome da intenção satisfeito sem tocar lockdowns nem docs históricos.
diff --git a/src/app/(campaign)/campanha/api/ai-chat/route.ts b/src/app/(campaign)/campanha/api/ai-chat/route.ts
index 9f83e4bf..65e14007 100644
--- a/src/app/(campaign)/campanha/api/ai-chat/route.ts
+++ b/src/app/(campaign)/campanha/api/ai-chat/route.ts
@@ -59,7 +59,7 @@ export async function POST(req: Request) {
})
const result = streamText({
- model: deepSeek('deepseek-v4-flash'),
+ model: deepSeek('deepseek-flash'),
system: AI_SYSTEM_PROMPT,
messages: strippedMessages,
tools: buildAITools({ user, payload }),
diff --git a/src/utilities/ai/campaignDemandTitle.ts b/src/utilities/ai/campaignDemandTitle.ts
index fe68eedf..27b19971 100644
--- a/src/utilities/ai/campaignDemandTitle.ts
+++ b/src/utilities/ai/campaignDemandTitle.ts
@@ -28,7 +28,7 @@ export const deriveDemandTitle = async (
try {
const { text } = await generateText({
- model: deepSeek('deepseek-v4-flash'),
+ model: deepSeek('deepseek-flash'),
system: DEMAND_TITLE_SYSTEM_PROMPT,
prompt: kind
? `Tipo: ${campaignDemandKindLabels[kind]}\nPedido: ${description}`