diff --git a/docs/postmortems/2026-09-24-busca-por-tema-indisponivel.md b/docs/postmortems/2026-09-24-busca-por-tema-indisponivel.md index ca969db0..8e494c47 100644 --- a/docs/postmortems/2026-09-24-busca-por-tema-indisponivel.md +++ b/docs/postmortems/2026-09-24-busca-por-tema-indisponivel.md @@ -10,7 +10,7 @@ | Severidade | alta (cinco capacidades de IA degradadas em silêncio em prod; nenhum dado perdido) | | Ambiente | prod (e staging — mesma config) | | Issue(s) | sem Issue — relato do humano na sessão do worktree `fix/11` (o bug-fix não exige Issue; o post-mortem é o registro) | -| PR do fix | este PR | +| PR do fix | [#1333](https://github.com/fsolla/teqo/pull/1333) | | Detectado por | humano | ## Timeline @@ -21,7 +21,7 @@ | Início provável (código) | 2026-09-18 (`45eef25b`, C192) | A busca por tema nasce chamando `generateObject` do `deepseek-flash` com `maxOutputTokens: 200` e thinking default; S28 (2026-09-23) reusa o mecanismo e C219 (2026-09-24, `38e67426`) adiciona o 3º corpus — mesma config. Os tetos irmãos (120/400/500) nasceram junto dos seus donos. | | Detecção | 2026-09-24 (sessão `fix/11`) | Humano relata "A busca por tema esta indisponivel." — o aviso do modo `tema` no acervo interno (`/campanha/comunicacao/acervo`). | | Diagnóstico | 2026-09-24 | Read-only em prod: containers `teqo-1313`/`teqo-staging` **sem** `DEEPSEEK_API_KEY`/`DEEPINFRA_API_KEY`/`RESEND_API_KEY`/`VAPID_*` no env (nomes via `docker inspect`); `~/stack/.env` **tem** `DEEPSEEK_API_KEY` + `DEEPINFRA_API_KEY`; os env files do app não. Smoke real do módulo com a chave da estação: 5/10 falhas com `AI_NoObjectGeneratedError` (JSON truncado / resposta vazia) no teto 200; `usage` medido: 93–354 tokens de raciocínio contra 28–34 de texto. Com `thinking: disabled`: 6/6. | -| Correção mergeada | a definir (este PR) | — | +| Correção mergeada | a definir (PR #1333) | — | | Deploy | a definir | deploy começa no merge; produção só após approve humano no environment `production` | | Verificado em prod | pendente (aguarda o humano) | pendente — e só vale depois de a chave entrar no `~/stack/teqo-1313.env` e o container ser recriado | @@ -53,15 +53,15 @@ Nenhuma migration, nenhum Consent/access, nenhum contrato de URL/shape público. - Provedor real (chave da estação, nunca impressa): tema 10/10, rerank 4/4 (antes 0/4), corte 4/4 `source: 'ai'` (antes 2/4), título 4/4 (antes 1/4), catalogação 2/2 `source: 'ai'` — 0 falhas. - Suíte: `pnpm gate:fast` verde (lint, `tsc --noEmit`, 422 arquivos/4677 unit, +9); `pnpm format:check` verde; int da superfície (7 arquivos: `contentPiece`, `speechAcervo`, `recording`, `webSpeechAcervo`, `speechCut`, `speechExcerpts`, `campaignDemandWorkflow`) 136 passed/1 skipped; e2e curados (`campaignAiTranscribe`, `campaignSpeechAcervo`) verdes no relevante (2 flakes de fixture rerodados isolados verdes — pré-existentes de ordem). - Guard de ops: `bash -n` verde; `deployScript.unit.spec.ts` verde (22) pinando o audit e a ordem (healthcheck → audit → smoke); audit exercitado com `docker` stubado (env com buraco → `::warning::` com a lista exata; tudo presente → silêncio). -- CI: verde no PR (a preencher) +- CI: o required check `CI (PR) / checks` do PR #1333 (o auto-merge nativo só mergeia com ele verde). - Prod: pendente — deploy começa no merge; produção só após approve humano; a validação do humano depende de a chave entrar no `~/stack/teqo-1313.env` (copia-e-cola do runbook) e o container ser recriado. ## Prevenção | Estratégia | Custo | Estado | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------- | -| Pin de regressão por dono (thinking off + teto ≥1000) e dono único das defaults (`deepseekFlashDefaults.ts`) | barata | implementada agora (este PR) | -| Audit não-fatal de feature envs no deploy (lê o env do container pós-healthcheck, emite `say` + `::warning::`) + pin em `deployScript.unit.spec.ts` + seção no runbook | barata | implementada agora (este PR) | +| Pin de regressão por dono (thinking off + teto ≥1000) e dono único das defaults (`deepseekFlashDefaults.ts`) | barata | implementada agora (PR #1333) | +| Audit não-fatal de feature envs no deploy (lê o env do container pós-healthcheck, emite `say` + `::warning::`) + pin em `deployScript.unit.spec.ts` + seção no runbook | barata | implementada agora (PR #1333) | | Helper único do boilerplate DeepSeek (`generateObject`/`generateText` + guard de chave + timeout + `catch`→`null`), débito já registrado em `docs/plans/acervo-busca-semantica-impl.md:153` | cara | documentada — não implementada neste fluxo | | Falhar o deploy quando uma feature env esperada está ausente | cara | documentada — muda contrato de ops (pode travar hotfix/rollback) e é decisão humana | | Observabilidade de degradação (contador/alerta por `catch`→`null` de cada feature, em vez de só o aviso na UI) | cara | documentada — instrumentação nova |