diff --git a/docs/plans/acervo-gravacoes-enviadas-ui-design.html b/docs/plans/acervo-gravacoes-enviadas-ui-design.html new file mode 100644 index 00000000..1ed71e17 --- /dev/null +++ b/docs/plans/acervo-gravacoes-enviadas-ui-design.html @@ -0,0 +1,820 @@ + + + + + + + Design — Gravações enviadas no acervo + + + + + +
+
+

Teqo · acervo de comunicação

+

Gravações enviadas no acervo

+

+ Referência hi-fi para enviar, acompanhar, buscar e consultar gravações próprias. A + transcrição é somente leitura. +

+
+ + +
+

Cena 1 · Desktop — acervo com alternador de fonte

+
+ +
+
+ ☰ +
+

Acervo

+

Comunicação

+
+
+
+
+
+

Acervo de falas

+

+ Busque nas falas da Câmara ou nas gravações da equipe. +

+
+ +
+
+ + +
+ +
+ +
+
+
+
+ +
+
+
+

Título da gravação

+ Pronto +
+

dd/mm/aaaa · —:—:—

+

+ Texto transcrito da gravação aparece aqui quando corresponde à busca. +

+
+ +
+
+
+ +
+
+
+

Outra gravação enviada

+ Processando +
+

dd/mm/aaaa · —:—:—

+

+ Transcrevendo a gravação. Ela ainda não aparece na busca. +

+
+ +
+
+
+ +
+
+
+

+ Gravação com falha na transcrição +

+ Falhou +
+

dd/mm/aaaa · —:—:—

+

+ O arquivo foi preservado. Reprocesse a transcrição no detalhe. +

+
+ +
+
+
+
+
+
+ + +
+

+ Cena 2 · Desktop — estados de processamento na lista e no detalhe +

+
+
+
+
+

Estados da gravação

+

+ O arquivo permanece visível desde o envio. +

+
+ Gravações enviadas +
+
+
+
+
+ Enviando +

Título da gravação

+

+ Arquivo sendo enviado · ainda não pesquisável +

+
+ +
+
+
+
+

Enviando arquivo…

+
+
+
+
+ Processando +

Título da gravação

+

+ Transcrevendo · ainda não pesquisável +

+
+ +
+
+ A transcrição ficará disponível neste detalhe quando o processamento terminar. +
+
+
+
+
+ Falhou +

Título da gravação

+

+ A transcrição não foi concluída. O arquivo foi preservado. +

+
+ +
+ +
+
+
+
+ Pronto +

Título da gravação

+

+ Transcrição disponível e pesquisável +

+
+ ✓ +
+ +
+
+
+
+
+ + +
+

Cena 3 · Desktop — detalhe da gravação

+
+
+ ☰ +
+

Gravação enviada

+

Acervo

+
+
+
+ +
+
+

Título da gravação

+

dd/mm/aaaa · —:—:—

+
+ Pronto +
+
+
+
+ +
+ 00:00 +
+
+
+ —:—:— +
+
+
+ +
+
+
+
+

TRANSCRIÇÃO

+ Clique para posicionar +
+
    +
  1. + +
  2. +
  3. + +
  4. +
  5. + +
  6. +
  7. + +
  8. +
+
+
+
+
+
+ + +
+

Cena 4 · Desktop — envio de gravação

+
+
+ +
+
+ + +
+

Cena 5 · Desktop — vazio

+
+
+
+ Falas da CâmaraGravações enviadas +
+
+ +

Nenhuma gravação enviada ainda

+

+ Envie um arquivo de vídeo para acompanhar a transcrição e pesquisar o conteúdo no + acervo. +

+ +
+
+
+
+ + +
+

+ Cena 6 · Mobile (390 px) — lista e detalhe com transcrição +

+
+
+

Lista de gravações

+
+
+

Acervo

+ +
+
+
+ +
+
+ Buscar nas gravações… +
+
+
+
+
+
+
+

Título da gravação

+

dd/mm/aaaa · —:—:—

+
+ Pronto +
+

+ Texto transcrito correspondente à busca aparece aqui. +

+ +
+
+
+
+

Outra gravação

+

dd/mm/aaaa · —:—:—

+
+ Processando +
+

+ Transcrevendo. Ainda não pesquisável. +

+
+
+ +
+
+
+

Detalhe

+
+
+ +
+

Gravação enviada

+

Acervo

+
+
+
+
+
+

Título da gravação

+

dd/mm/aaaa · —:—:—

+
+ Pronto +
+
+ +
+ +
+
+
TRANSCRIÇÃO
+ Toque para posicionar +
+
    +
  1. + +
  2. +
  3. + +
  4. +
  5. + +
  6. +
+
+
+ +
+
+
+
+
+ + + + diff --git a/docs/plans/acervo-gravacoes-enviadas.md b/docs/plans/acervo-gravacoes-enviadas.md new file mode 100644 index 00000000..5d499d1b --- /dev/null +++ b/docs/plans/acervo-gravacoes-enviadas.md @@ -0,0 +1,116 @@ +# Gravações enviadas no acervo de comunicação + +Status: rascunho +Atualizado em: 2026-09-18 +Issue: #1166 +Priority: P2 +Impeccable: C — fluxo novo na vertical `/campanha/comunicacao/acervo` (upload + nova fonte + detalhe) +Design UI: docs/plans/acervo-gravacoes-enviadas-ui-design.html +Appetite: ~3–4 dias eng; um outcome verificável — a assessoria sobe uma plenária/debate e a gravação fica pesquisável no acervo, com player e transcrição +Responsável: — + +## Intenção + +O acervo de falas só tem o que a Câmara publica. Mas a comunicação do mandato também grava plenárias, debates e material próprio que hoje fica em pastas e celulares — sem transcrição, sem busca e sem lugar comum. Quem precisa de um trecho continua garimpando vídeo no olho. + +Este item permite que a assessoria envie um arquivo de gravação e o transforme numa fonte pesquisável dentro do acervo: transcrição com timestamps ao longo de toda a gravação, busca textual que alcança a fala de qualquer pessoa presente (não só o Solla — requisito, não efeito colateral), player que abre no trecho e download do arquivo. É o primeiro passo da linha; separar/rotular quem falou é o C200. + +## Persona e fluxo + +- **Persona / contexto:** assessoria de comunicação (`communicator`), na mesa, lidando com arquivos longos (horas) de plenárias e debates; `coordinator`/`candidate` usam o mesmo acervo. Busca e leitura também acontecem em campo. +- **Job principal:** guardar uma gravação própria no acervo e, depois, achar nela a fala/trecho que embasa a peça — de qualquer pessoa que falou. +- **Fluxo desejado:** abre o acervo → alterna para "Gravações enviadas" → "Enviar gravação" (arquivo local, título e data) → acompanha o estado → com "Pronto", busca por assunto e lê o trecho com timestamps → abre o detalhe: player, transcrição clicável, "Baixar" → se falhou, "Reprocessar transcrição". +- **Anti-goals de produto:** não é editor de vídeo/transcrição; não expõe o acervo; não publica nada; não cria cadastro de pessoa; não é CMS de vídeo genérico. + +### Esboço de fluxo (C) + +```text +[acervo /campanha/comunicacao/acervo] + → alternador de fonte: "Falas da Câmara" | "Gravações enviadas" + → "Enviar gravação" → arquivo local + título/data → estado visível na lista + → (Enviando → Processando → Pronto | Falhou) + → Pronto: busca textual alcança a fala de qualquer pessoa → abre o detalhe + → player + transcrição clicável (clique posiciona o player) + "Baixar" + → Falhou: "Reprocessar transcrição" +[outcome: gravação própria pesquisável no acervo, sem depender de fora] +``` + +### Design UI (C) + +- Design UI (gate): `docs/plans/acervo-gravacoes-enviadas-ui-design.html` — alternador de fonte, envio com estados, lista e detalhe (player + transcrição + download), na linguagem visual do `/campanha`. Por que C: fluxo novo (upload + nova fonte + detalhe), mesmo sem rota de topo nova. + +## Objetivo e aceite + +- `communicator` — e `coordinator`/`candidate` — envia um arquivo de vídeo local e acompanha o processamento até "Pronto"; `advisor`/`leader` não têm acesso (fail-closed). +- A gravação vira uma fonte do acervo em `/campanha/comunicacao/acervo`, com alternador visível "Falas da Câmara" × "Gravações enviadas"; a fonte nova tem busca própria, sem as facetas da Câmara. +- A busca textual encontra a fala de qualquer pessoa da gravação, com trecho e timestamps; a unidade do resultado é a gravação. +- Detalhe da gravação: player, transcrição clicável por segmento (clique posiciona o player, como no acervo atual), "Baixar" e "Reprocessar transcrição" no estado "Falhou". +- Estados de processamento visíveis e honestos; a falha preserva o arquivo e permite reprocessar. +- Gravação só é servida para quem tem acesso ao acervo — nunca URL pública — reusando o dono do mecanismo de mídia privada definido no C193. +- **Guardrails:** sem diarização/rotulagem de pessoa (C200), sem corte/clipe, sem publicação externa, sem segundo cadastro de pessoa, sem score/vaidade; transcrição somente leitura em v1. + +## Dados (intenção) + +- **Vou apresentar dados?** N/A — resultados de busca não são métrica nem agregado; não desbloqueiam decisão numérica. +- **Decisões desbloqueadas:** N/A — a escolha da persona ("qual fala/trecho usar") é qualitativa. +- **Forma:** N/A — restrição de produto: nenhum score de relevância/similaridade exposto como número. + +## Dados da decisão (literais) + +- **Papel:** `communicator` = "Assessor de Comunicação"; `coordinator`/`candidate` também. Mesmo gate de leitura do acervo (`speechCatalog`); `advisor`/`leader` fora. +- **Fontes (rótulos):** "Falas da Câmara" (acervo atual) e "Gravações enviadas" (novo), no mesmo `/campanha/comunicacao/acervo` via alternador; detalhe da gravação em rota própria sob o acervo, `/campanha/comunicacao/acervo/gravacoes/[id]`. +- **Gestos:** "Enviar gravação" (upload) · "Reprocessar transcrição" · "Baixar" (arquivo) · player no detalhe. +- **Estados de processamento:** "Enviando" (arquivo subindo; ainda não pesquisável) · "Processando" (transcrevendo; ainda não pesquisável) · "Pronto" (pesquisável: player, transcrição e download) · "Falhou" (transcrição não saiu; arquivo preservado e "Reprocessar transcrição" disponível). A gravação aparece na lista com o estado desde o envio. +- **Transcrição:** timestamps por segmento; clique no segmento posiciona o player — mesmo comportamento do acervo atual. +- **Entrada:** arquivo de vídeo local (mp4/mov/mkv e afins); erro claro acima do limite; gravações de horas são o caso real — o valor do limite é decisão da implementação. +- **Apagar:** com confirmação; remove a gravação (e sua transcrição/mídia) sem tocar nas falas da Câmara. +- **Dependência dura:** C193 (mídia privada/servir autenticado); C200 (separação por pessoa) depende deste. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `src/app/(campaign)/campanha/(app)/comunicacao/acervo/` (página atual + sub-rota nova), `src/components/campaign/speech/` (alternador, lista, filtros, player, detalhe), `src/utilities/speech/` (`speechPageData.ts`, `speechListFilters.ts`, `speechListUrl.ts`, `speechViewModels.ts`), `src/utilities/access/speeches.ts` (leitura), `src/utilities/campaignPageActor.ts` (gate `speechCatalog`), esteira de mídia (`Media`/`mediaStorage.ts` como referência, respeitando o dono do C193). +- **Precedente a olhar:** C174 (segunda fonte já entra na mesma busca via OR de ids), `speechCutJob.ts` (status + step + disparo pós-resposta + reaper preguiçoso), `speechPosterJob.ts` (single-flight), import CSV de apoiadores (enviar → processar → confirmar), route handler multipart `src/app/(campaign)/campanha/api/ai-transcribe/route.ts`, CLI da Câmara (`scripts/import-camara-speeches.mjs` + `scripts/lib/camaraFetch.mjs`) para o padrão de ASR com timestamps. +- **Risco de acoplamento:** (1) mídia privada é do C193 — não criar mecanismo gêmeo; `Media` continua leitura pública (contrato pinado em teste); (2) upload de vídeo de horas não cabe no default de server action (1 MB) — decisão do plano de implementação; (3) regra de chrome/regex do acervo pode capturar `gravacoes` como id (mesma armadilha anotada no C194); (4) nav pinada `[Acervo, Cortes]` e C184/#1106 mexem nos mesmos arquivos — nada de item de nav novo; (5) contrato de URL da lista atual (`q|year|topic|scope|phase|municipality|duration|page`) não pode quebrar deep-links. + +## Dependências + +- **C193 (dura):** mecanismo de mídia privada e servir autenticado. O C199 pode possuir o upload de arquivo grande; o _servir privado_ é do C193 — sem ele fechado, a fatia privada não entra. +- **C153/C154 (entregues):** base do acervo (dados, busca, rota, gate). +- **C184/#1106 (soft):** conflito de nav/sub-itens — serializar. +- **C200 (futuro):** depende deste; não bloqueia a fatia. + +## Fora de escopo + +- Diarização/rotulagem por pessoa (C200). +- Link/YouTube/download automático por URL. +- Cortes/clipes (C167/C174 são da Câmara). +- Busca semântica (C192). +- Edição de transcrição. +- Publicação externa/espelhamento em rede social. +- Dossiês/Sollinha. +- Comissões/outras fontes e classificação por tema/alcance. + +## Rabbit holes de produto + +- **Virar editor.** Se alguém "só completar": cortar, corrigir, legendar, remixar. **Corte neste item:** transcrição somente leitura; a única "edição" é reprocessar a transcrição inteira. +- **Diarização no v1.** Se alguém "só completar": rotular quem falou em horas de áudio. **Corte neste item:** C200; a busca textual geral já resolve o job. +- **Espelhar/publicar.** Se alguém "só completar": derivar para redes ou galeria. **Corte neste item:** arquivo interno; nada sai do acervo. +- **Segundo cadastro de pessoa.** Se alguém "só completar": transformar falante em `Contact`. **Corte neste item:** sem rótulo de pessoa em v1. +- **Merge unificado das fontes.** Se alguém "só completar": lista única Câmara+gravações e entrada no `home-search`. **Corte neste item:** alternador dentro do acervo; a busca global não entra. +- **Fila/infra de processamento.** Se alguém "só completar": pipeline genérico, tempo real, chunking. **Corte neste item:** processamento inteiro com estado visível. + +## Questões em aberto (produto) + +- **Forma da segunda fonte?** **Opções:** A) duas fontes no mesmo acervo, com alternador e busca própria | B) merge das duas numa lista única | C) rota separada fora do acervo. **Recomendação:** A — as facetas da Câmara não se aplicam à gravação e o merge multi-coleção é caro; o alternador mantém "acervo pesquisável" sem fingir homogeneidade. _(assumido — validar no gate)_ +- **Transcrição editável em v1?** **Opções:** A) somente leitura | B) correção manual inline. **Recomendação:** A — correção vira curadoria; se doer, item próprio. _(assumido — validar no gate)_ +- **Quem apaga uma gravação?** **Opções:** A) qualquer um dos três papéis com acesso, com confirmação | B) só `coordinator`/`candidate`. **Recomendação:** A — a assessoria é dona do acervo no dia a dia; apagar não toca nas falas da Câmara e é confirmado. _(assumido — validar no gate)_ +- **Gravação que falhou fica visível?** **Opções:** A) sim, com "Falhou" e "Reprocessar transcrição" | B) só aparece quando "Pronto". **Recomendação:** A — falha silenciosa faz o arquivo sumir sem explicação. _(assumido — validar no gate)_ +- **O que a assessoria preenche ao enviar?** **Opções:** A) título obrigatório + data da gravação | B) só o arquivo. **Recomendação:** A — sem isso a lista vira pilha de `IMG_…`; uploader e duração são automáticos. _(assumido — validar no gate)_ + +## Referências + +- GitHub Issue #1166 +- Design UI (gate): `docs/plans/acervo-gravacoes-enviadas-ui-design.html` (+ assets em `docs/plans/acervo-gravacoes-enviadas-ui-design-assets/`) +- Planos irmãos: `docs/plans/catalogo-falas-solla.md` (C153) · `docs/plans/acervo-videos-comunicacao.md` (C154) · `docs/plans/acervo-busca-semantica.md` (C192) · `docs/plans/reels-reel-privado.md` (C193) · `docs/plans/reels-biblioteca.md` (C194) +- Arquivos-pista: `src/app/(campaign)/campanha/(app)/comunicacao/acervo/page.tsx` · `src/components/campaign/speech/` · `src/utilities/speech/speechPageData.ts` · `src/utilities/speech/speechListFilters.ts` · `src/utilities/speech/speechListUrl.ts` · `src/lib/speechSearch.ts` · `src/collections/SpeechSegment.ts` · `src/utilities/speech/speechCutJob.ts` · `scripts/import-camara-speeches.mjs` +- `AGENTS.md` — RBAC de `/campanha`, acervo interno e leader lockdown diff --git a/docs/plans/acervo-separacao-por-pessoa-ui-design.html b/docs/plans/acervo-separacao-por-pessoa-ui-design.html new file mode 100644 index 00000000..8ca679c7 --- /dev/null +++ b/docs/plans/acervo-separacao-por-pessoa-ui-design.html @@ -0,0 +1,701 @@ + + + + + + + Design — Separar falas por pessoa + + + + + +
+
+

Teqo · acervo de comunicação

+

Separar falas por pessoa

+

+ Referência hi-fi para agrupamentos acústicos e identificação humana. O produto nunca + sugere nem infere quem falou. +

+
+ + +
+

+ Cena 1 · Desktop — detalhe com transcrição separada por falante +

+
+
+ ☰ +
+

Gravação enviada

+

Acervo

+
+
+
+ +
+
+

Título da gravação

+

dd/mm/aaaa · —:—:—

+
+ Pronto +
+
+
+
+ +
+ 00:00 +
+
+
+ —:—:— +
+
+ +
+ + + +

+ Os falantes são agrupados automaticamente pelo áudio. A identificação de cada + pessoa é feita pela equipe. +

+
+
+
+
+

TRANSCRIÇÃO POR FALANTE

+ Clique para posicionar +
+
+
+
+
+ +
+
Falante 1
+

+ Agrupamento sem identificação +

+
+
+ +
+ +
+
+
+
+ +
+
Nome do falante
+

+ Identificação feita pela equipe +

+
+
+ +
+ +
+
+
+
+ +
+
Falante 3
+

+ Agrupamento sem identificação +

+
+
+ +
+ +
+
+
+
+
+
+
+ + +
+

Cena 2 · Desktop — diálogo para rotular o falante

+
+
+ +
+
+ + +
+

+ Cena 3 · Desktop — lista com faceta “Pessoa” aplicada +

+
+ +
+
+ ☰ +
+

Acervo

+

Comunicação

+
+
+
+
+

Acervo de falas

+

Gravações enviadas

+
+
+ Falas da CâmaraGravações enviadas +
+ +
+ Busque por palavra ou trecho da transcrição… +
+
+ +
+
+
+
+
+
+
+

Título da gravação

+ Pronto +
+

dd/mm/aaaa · —:—:—

+

+ Trecho da transcrição encontrado pela busca geral. +

+
+ Nome do falanteaparece nesta gravação +
+
+ +
+
+
+
+
+
+

Outra gravação enviada

+

dd/mm/aaaa · —:—:—

+

+ Outro trecho continua alcançável pela busca de texto. +

+
+ Nome do falanteaparece nesta gravação +
+
+ +
+
+
+
+
+
+
+ + +
+

+ Cena 4 · Desktop — agrupamento aproximado / qualidade ruim +

+
+
+
+

Título da gravação

+

Transcrição por falante

+
+
+ +
+

+ A separação por falante pode estar imprecisa +

+

+ O agrupamento é automático e aproximado. Ruído e falas sobrepostas podem colocar + trechos no agrupamento errado. A equipe continua responsável por identificar cada + falante. +

+
+
+
+
+
+
+
Falante 1
+

Agrupamento sem identificação

+
+ +
+ +
+
+
+
+
Falante 2
+

Agrupamento sem identificação

+
+ +
+ +
+
+
+
+
+ + +
+

+ Cena 5 · Mobile (390 px) — detalhe com agrupamentos e identificação +

+
+
+ +
+

Gravação enviada

+

Acervo

+
+
+
+
+

Título da gravação

+

dd/mm/aaaa · —:—:—

+
+
+ +
+
+ +

+ Agrupamento automático e aproximado. A identificação é feita pela equipe. +

+
+
+
+
TRANSCRIÇÃO POR FALANTE
+ Toque para posicionar +
+
+
+
+
+
+ +
Falante 1
+
+ +
+
+ +
+
+
+
+
+ +
+
Nome do falante
+

Identificado pela equipe

+
+
+ +
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/docs/plans/acervo-separacao-por-pessoa.md b/docs/plans/acervo-separacao-por-pessoa.md new file mode 100644 index 00000000..b77ec472 --- /dev/null +++ b/docs/plans/acervo-separacao-por-pessoa.md @@ -0,0 +1,115 @@ +# C200 — Separar falas por pessoa nas gravações enviadas + +Status: rascunho +Atualizado em: 2026-09-18 +Issue: #1167 +Priority: P3 +Impeccable: C — fluxo novo no acervo (rotulagem de falantes no detalhe + faceta "Pessoa" na fonte de gravações enviadas) +Design UI: docs/plans/acervo-separacao-por-pessoa-ui-design.html +Appetite: ~2–3 dias eng; um outcome verificável — a assessoria identifica quem fala numa gravação enviada e filtra o acervo pelas falas de uma pessoa +Responsável: — + +## Intenção + +As gravações enviadas ao acervo (C199) não têm só fala do Solla: plenárias e debates têm várias vozes, e a transcrição sai como um bloco único. A busca geral já cobre esse texto inteiro, mas não responde à pergunta que a assessoria faz o tempo todo: "o que **fulano** disse nesta gravação?". Este item é a camada de quem-falou-o-quê: a transcrição passa a vir dividida por agrupamento de falante, a assessoria identifica quem é cada voz e o acervo ganha um recorte por pessoa. + +O guardrail é duro e vem do próprio pedido: separar por áudio é **agrupamento acústico** ("Falante 1", "Falante 2", …), e a identificação é **humana** — a assessoria ouve e rotula. Nada de voiceprint, nada de casar voz com pessoa conhecida, nada de identificar terceiros por biometria. Rótulo não preenchido continua "Falante N"; nunca se inventa identidade. + +P3: melhora real o garimpo, mas depende do C199 e não bloqueia operação — o acervo segue útil com a busca geral enquanto isso. + +## Persona e fluxo + +- **Persona / contexto:** assessoria de comunicação (`communicator`) — e também `coordinator`/`candidate` — na mesa, montando peça com prazo curto, garimpando em plenárias/debates enviados pela equipe; não é editor de transcrição nem curador de cadastro. +- **Job principal:** achar as falas de uma pessoa específica dentro de uma gravação e conseguir recortar as gravações em que ela fala. +- **Fluxo desejado:** + 1. Abre o acervo na fonte "Gravações enviadas" e abre uma gravação. + 2. A transcrição aparece dividida em "Falante 1", "Falante 2", … — sem nome inventado, sem sugestão automática de identidade. + 3. Ouve o trecho e usa "Identificar falante" para rotular o agrupamento (ex.: "Falante 2" → "Dep. Jorge Solla"); o rótulo vale para todas as falas daquele agrupamento naquela gravação. + 4. Volta à lista e usa a faceta "Pessoa" para ver só as gravações com falas daquela pessoa; a busca geral continua cobrindo a transcrição inteira. + 5. Abre o trecho e assiste/baixa como já faz hoje. +- **Anti-goals de produto:** não vira biometria/identificação automática de voz; não cria cadastro de pessoas paralelo ao `Contact`; não troca nem esvazia a busca geral; não edita transcrição; não reprocessa o acervo antigo sozinho. + +### Esboço de fluxo (C) + +```text +[acervo: fonte "Gravações enviadas"] → abre a gravação + → transcrição dividida em "Falante 1", "Falante 2", … (sem nome inventado) + → ouve + "Identificar falante" → rótulo vale para todas as falas daquele agrupamento + → volta à lista → faceta "Pessoa" recorta as gravações com falas daquela pessoa + → abre o trecho, assiste/baixa → [outcome: a fala da pessoa certa na mão] +``` + +### Design UI (C) + +- Design UI (gate): `docs/plans/acervo-separacao-por-pessoa-ui-design.html` (+ assets em `docs/plans/acervo-separacao-por-pessoa-ui-design-assets/`) — a produzir pelo designer. +- Por que C: há affordance nova no detalhe (rotular agrupamento) e estado novo na lista (faceta "Pessoa" só na fonte de gravações enviadas, com rótulos por gravação), dentro da tela existente. Design hi-fi obrigatório no gate e fonte de verdade do port. + +## Objetivo e aceite + +- Gravações enviadas (C199) têm a transcrição dividida por agrupamento de falante; o rótulo default é "Falante 1", "Falante 2", … (sempre com número). +- A assessoria rotula um agrupamento com "Identificar falante" no detalhe da gravação; o rótulo passa a valer para todas as falas daquele agrupamento naquela gravação. +- A faceta "Pessoa" existe na fonte "Gravações enviadas" e recorta as gravações em que aquele rótulo aparece; a busca geral continua alcançando a transcrição inteira, como hoje. +- Rótulo não preenchido permanece "Falante N"; o produto nunca sugere, infere ou completa identidade. +- Reprocessar a transcrição de uma gravação não perde os rótulos já feitos (ou exige re-vinculação clara e avisada) — requisito de produto, não detalhe técnico. +- Escopo de aplicação: gravações novas a partir deste item; reprocessar/diarizar as antigas é ação explícita, nunca automática. +- **Guardrails:** sem biometria de voz; identificação é humana; sem segundo cadastro de pessoa (rótulo é texto, não `Contact`); gate fail-closed do acervo (`communicator` + `coordinator`/`candidate`; demais negados); acervo segue interno; sem score de confiança de "quem falou" na UI. + +## Dados (intenção) + +- **Vou apresentar dados?** N/A — o filtro por pessoa é recorte de conteúdo/conteúdo editorial, não métrica nem agregado. +- **Decisões desbloqueadas:** N/A — a escolha da persona ("qual fala usar") é qualitativa. +- **Forma:** N/A — sem superfície de dados; restrição de produto: agrupamento é acústico e aproximado, então nada de confiança numérica por falante (número cru engana e sugere precisão que não existe). + +## Dados da decisão (literais) + +- **Rótulo default dos agrupamentos:** "Falante 1", "Falante 2", … (sempre com número; nunca nome inventado). +- **Ação de curadoria:** "Identificar falante" (rotular), no detalhe da gravação. +- **Faceta:** "Pessoa", na fonte "Gravações enviadas" do acervo. +- **Fonte:** "Gravações enviadas" (a fonte que o C199 popula). +- **Papéis:** `communicator` ("Assessor de Comunicação") + `coordinator`/`candidate`; demais negados (fail-closed) — mesmo gate do acervo. +- **Guardrail literal:** sem biometria de voz; identificação humana; sem segundo cadastro de pessoa. +- **Dependência dura:** C199. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `src/app/(campaign)/campanha/(app)/comunicacao/acervo/…` (lista + detalhe); `src/components/campaign/speech/SpeechAcervoFilters.tsx` e `src/components/campaign/shared/CampaignHeaderFilterPopover.tsx` (faceta multi-seleção reutilizável); `src/utilities/speech/speechListUrl.ts` (`SpeechFilterOptions` e params/URLs da lista), `speechListFilters.ts`, `speechOmnibox.ts`, `speechPageData.ts`; `src/utilities/ai/deepInfraTranscribe.ts` e o import (`src/utilities/speech/speechImport.ts`); `src/utilities/access/speeches.ts` (gate). +- **Precedente a olhar:** C154 (filtros/facetas do acervo), C153 (menções como texto; anti-goal de normalizar pessoa), C192 (recorte adicional na mesma tela), `src/collections/SpeechSegment.ts` (segmento hoje sem locutor, admin-hidden, substituído em bloco no import). +- **Risco de acoplamento:** o reprocessamento do import substitui os segmentos em bloco — um rótulo por trecho só sobrevive se o reprocessamento carregar/re-aplicar; o contrato de URL da lista sustenta deep-links e a faceta nova não pode quebrar as existentes; busca geral, cortes e gate de leitura intocados. + +## Dependências + +- **C199** (dura, bloqueante) — sem as gravações transcritas não há o que separar. +- Soft: C192 (busca semântica) compartilha a tela e a organização de filtros; não bloqueia nem é pré-requisito. + +## Fora de escopo + +- Biometria/voiceprint e qualquer identificação automática de pessoa. +- `Contact`/segundo cadastro de pessoa. +- Edição/correção de transcrição e correção de erros de ASR. +- Cortes/clipes e biblioteca de cortes. +- Busca semântica (C192) — recorte ortogonal sobre a mesma tela. +- Publicação externa, compartilhamento e Sollinha/dossiês. +- Backfill automático de diarização nas gravações antigas. + +## Rabbit holes de produto + +- **Virar reconhecimento biométrico.** Se alguém "só completar": voiceprint, match automático voz↔pessoa, identificação de terceiros. **Corte neste item:** agrupamento acústico + rótulo humano; nada automático. +- **Cadastro de pessoas/vozes.** Se alguém "só completar": diretório de falantes, entidade nova, merge entre gravações. **Corte:** rótulo é texto por gravação; sem unificação automática. +- **Transcrição perfeita por falante.** Se alguém "só completar": correção de sobreposição, refino de palavras, edição de texto. **Corte:** agrupamento é aproximado; fala sobreposta pode cair no agrupamento errado e a assessoria re-rotula. +- **Identificar automaticamente autoridades.** Se alguém "só completar": inferir "quem presidia" ou "o deputado" por heurística. **Corte:** se quiserem marcar presidência, é rótulo humano como qualquer outro. + +## Questões em aberto (produto) + +- **Qual provedor/etapa faz a diarização?** **Opções:** A) provedor com diarização nativa no pipeline de transcrição | B) etapa de diarização sobre o áudio já transcrito | C) diarização local no homeserver. **Recomendação:** decisão do plano de implementação, com custo por minuto medido e fallback honesto — o ASR atual (Whisper large-v3) **não** entrega diarização; sem a etapa, a transcrição volta a bloco único (nunca fingir separação). _(assumido — validar no gate)_ +- **Reprocessar as gravações antigas?** **Opções:** A) backfill automático de todo o acervo | B) ação explícita por gravação | C) não oferecer. **Recomendação:** B — o custo por minuto não justifica varrer tudo agora, e reprocessar pode mexer em rótulos já feitos; quando rodar, é avisado e não perde rótulo. _(assumido — validar no gate)_ +- **Mesma pessoa em gravações diferentes?** **Opções:** A) unificação automática por voz (biometria — proibida) | B) texto livre por gravação, sem unificação; o filtro casa pelo texto do rótulo | C) diretório sugerido + merge manual (item futuro). **Recomendação:** B — sem segunda fonte de identidade nem matching biométrico; se as variações de nome ("Solla" vs "Dep. Jorge Solla") fragmentarem o filtro, é curadoria, outro item se doer. _(assumido — validar no gate)_ +- **O que mostrar quando o agrupamento é ruim (sobreposição/ruído)?** **Opções:** A) esconder a separação quando a qualidade for baixa | B) mostrar mesmo aproximada, com aviso discreto de que o agrupamento é automático | C) permitir marcar "não sei quem falou". **Recomendação:** B (+ C se couber no design) — transparência sobre o limite; esconder quebra a confiança no que apareceu. _(assumido — validar no gate)_ + +## Referências + +- GitHub Issue #1167 +- Design UI (gate): `docs/plans/acervo-separacao-por-pessoa-ui-design.html` (+ assets em `docs/plans/acervo-separacao-por-pessoa-ui-design-assets/`) +- Dependência: C199 (upload de gravações no acervo — a definir planos irmãos) +- Planos irmãos: `docs/plans/acervo-videos-comunicacao.md` (C154), `docs/plans/catalogo-falas-solla.md` (C153), `docs/plans/acervo-busca-semantica.md` (C192) +- Arquivos-pista: `src/components/campaign/speech/SpeechAcervoFilters.tsx`, `src/components/campaign/shared/CampaignHeaderFilterPopover.tsx`, `src/utilities/speech/speechListUrl.ts`, `src/utilities/speech/speechImport.ts`, `src/collections/SpeechSegment.ts`, `src/utilities/ai/deepInfraTranscribe.ts` +- `AGENTS.md` — RBAC de `/campanha`, acervo interno, LGPD/consentimento fail-closed