7.4 KiB
Falas longas entram no acervo sem estourar o limite do texto normalizado
Status: rascunho Atualizado em: 2026-09-25 Issue: #1337 Priority: P1 Impeccable: A — N/A Design UI: N/A Appetite: ~0,5 dia; um outcome verificável (fala longa entra e continua pesquisável) Responsável: —
Intenção
Na última rodada de ingestão web (pnpm falas-web:import, C215/C218), as quatro falas mais longas do lote — justamente podcasts, programas de rádio e plenárias — não entraram no acervo: o import falhou no estágio media porque o texto normalizado de busca estourou o limite de 40 000 caracteres do Payload. A transcrição (ASR) já tinha sido paga e o operador só descobre o problema no relatório, depois do custo. O dono quer que uma fala de qualquer duração entre no catálogo e continue pesquisável do começo ao fim — perder acervo por tamanho de transcrição não é aceitável.
Persona e fluxo
- Persona / contexto: operador do acervo (comunicação/gabinete) rodando a rodada web na mesa; dispara o lote e confere o relatório no fim, sem acompanhar item a item.
- Job principal: garantir que toda fala transcrita entre no acervo e siga encontrável por qualquer termo dito.
- Fluxo desejado: dispara o lote → o import cria a fala e seus segmentos → a fala longa aparece no acervo → busca por um termo do fim da transcrição devolve a fala → relatório do lote não lista falha de validação.
- Anti-goals de produto: não virar pipeline de truncamento silencioso; não redesenhar busca/facetas (C192/C153/C154); não criar segundo lugar de transcrição nem tela nova. Correção de ingestão, não feature.
Objetivo e aceite
- Importar uma fala de ~3h entra no acervo e aparece na busca por termos do fim da transcrição.
- O relatório do import não reporta falha de validação para falas longas.
- As 4 falas que ficaram pendentes podem ser reingeridas com o mesmo lote e entram (retry idempotente).
- Guardrail: nenhuma fala pode ser rejeitada por tamanho de transcrição; a busca textual funciona para o texto inteiro.
- Guardrail: sem perda silenciosa — qualquer limite remanescente aparece de forma honesta no relatório; nunca truncar sem registro.
- Guardrail: não mudar o comportamento de busca/facetas já entregue (C192/C153/C154) nem o contrato público.
Dados (intenção)
- Vou apresentar dados? Não — é correção de ingestão; o relatório do lote (C215/C218) já existe e continua sendo a superfície de verificação.
- Decisões desbloqueadas: operador do acervo — confiar que o lote web entrou completo, sem caçar falha de validação em fala longa.
- Forma: adiada ao plano de implementação — aqui só a restrição de produto: a busca precisa cobrir o texto inteiro, sem corte silencioso.
Dados da decisão (literais)
- Limite que causa a falha:
defaultMaxTextLength = 40000do Payload, aplicado atext/textareasemmaxLengthpróprio (node_modules/payload/dist/config/defaults.js:48;node_modules/payload/dist/fields/validations.js:24).src/payload.config.tsnão sobrescreve esse default. - Campos irmãos sob o mesmo teto, todos com label
Texto normalizado (busca):Speech.searchText,SpeechSegment.searchText,Recording.searchText,RecordingSegment.searchText,ContentPiece.searchText. - Mensagem literal da falha:
O campo a seguir está inválido: Texto normalizado (busca). - Lote da evidência: 4 itens falharam no estágio
media— 6394s, 10187s, 3528s e 4052s de duração; relatóriodata/falas-web/reports/falas-web-2026-09-25T02-18-30-484Z.json(gitignored; registro da sessão). - A coluna no Postgres é
character varyingsem limite (information_schema.columns) — é validação de aplicação, sem migration envolvida. - Caminho de escrita compartilhado Câmara/web:
upsertSpeechBundleemsrc/utilities/speech/speechImport.ts.
Direção no codebase (hipótese)
- Áreas prováveis:
src/collections/Speech.ts(camposearchText, ~233–248) e irmãosSpeechSegment.ts,Recording.ts,RecordingSegment.ts,ContentPiece.ts;src/payload.config.ts;src/utilities/speech/speechImport.ts. - Precedente a olhar: C154 (searchText denormalizado por fala), C215/C218 (ingestão web e relatório), índice GIN trigram hand-written.
- Risco de acoplamento: a busca lê
searchTextcom LIKE/contains e o índice GIN é escrito à mão — a correção não pode degradar C192/C153/C154 nem o contrato de URL pública.
Dependências
- Nenhuma.
Fora de escopo
- Reindexação/limpeza de dados históricos: a falha impedia a criação, então não há fala parcial no acervo — só o retry do lote pendente.
- Trocar a estratégia de
searchText(ex.: buscar direto nos segmentos) — fica para item próprio, se algum dia for desejado. - Mudanças em busca, facetas ou listagem (C192/C153/C154).
- Limite de exibição da transcrição na página da fala (não é o campo de busca).
- Custo de ASR e re-transcrição: nada a fazer; a transcrição já existe.
Rabbit holes de produto
- “Só subir o default global e pronto”. Se alguém “só completar”: o teto vira decisão única para todo o admin e mascara limites de outros domínios. Corte neste item: a escolha do mecanismo é do plano de implementação (ver Questões em aberto), com a restrição de não truncar o texto de busca.
- “Truncar em 40 000 com registro no relatório”. Se alguém “só completar”: atende o relatório, mas quebra o aceite de achar termos do fim da transcrição e perde acervo pesquisável. Corte neste item: busca no texto inteiro é obrigatória; registro honesto é piso, não solução.
- “Redesenhar a busca para varrer segmentos”. Se alguém “só completar”: explode para redesign de C153/C154 e do índice. Corte neste item: manter o contrato entregue.
Questões em aberto (produto)
- Qual mecanismo garante o texto inteiro? Opções: A) elevar o teto global (
defaultMaxTextLength); B)maxLengthexplícito nos campos de texto normalizado; C) truncar com registro no relatório. Recomendação: A ou B — qualquer uma que preserve o texto inteiro e a busca ponta a ponta; C não atende o aceite. A escolha fina é do plano de implementação, com a evidência de que a coluna não tem limite. (assumido — validar com produto) - Se algum limite remanescente existir, como o relatório o mostra? Opções: A) manter a falha de validação visível; B) registrar contagem de caracteres e motivo do corte. Recomendação: A como estado atual seguro; B só se houver limite inevitável — nunca truncar sem linha no relatório. (assumido — validar com produto)
Referências
- GitHub Issue #1337 (C223)
- Design UI (gate): N/A
docs/plans/acervo-falas-web-ingestao.mdeacervo-falas-web-ingestao-impl.md(C215/C218);docs/plans/catalogo-falas-solla.md- Abrir primeiro:
src/collections/Speech.ts(~233–248),src/utilities/speech/speechImport.ts,src/collections/SpeechSegment.ts,src/collections/Recording.ts,src/collections/RecordingSegment.ts,src/collections/ContentPiece.ts,src/payload.config.ts - Para confirmar o teto:
node_modules/payload/dist/config/defaults.js:48enode_modules/payload/dist/fields/validations.js:24 AGENTS.md— ingestão de falas e convenção de migrations (push: false; esta correção, pela evidência da coluna, não deve precisar de migration)