10 KiB
Biblioteca de cortes: apagar um corte e não acumular cortes falhados
Status: rascunho Atualizado em: 2026-09-16 Issue: #1105 Priority: P2 Impeccable: B — encaixe na biblioteca de cortes (lista + detalhe): ação de apagar e tratamento de corte falhado Design UI: docs/plans/biblioteca-cortes-apagar-e-falhas-ui-design.html Appetite: ~1 dia eng; um outcome verificável: a assessoria consegue apagar um corte que não serve, e a lista não acumula itens "Falhou" sem ação. Responsável: —
Intenção
A biblioteca de cortes (C168) resolveu o reencontro, mas deixou dois becos. Primeiro: um corte errado, duplicado ou que ninguém vai usar fica lá para sempre — só um admin do Payload consegue apagar. A assessoria, que é quem sabe que o item não presta, não tem como limpar a própria biblioteca. Segundo: um corte que falhou continua listado como um item "Falhou" morto, sem nenhuma ação; o único "Tentar novamente" que existe mora no diálogo da fala de origem, não onde a pessoa vê a falha. O pedido é direto: poder apagar um corte, e não acumular cortes falhados — ou eles somem sozinhos, ou aparecem com um "Tentar novamente" acionável.
Persona e fluxo
- Persona / contexto: assessoria de comunicação (
communicator) e coordenação/candidatura, em/campanha/comunicacao/acervo/cortes, na mesa ou no celular, sob prazo — quem não é da vertical (advisor,leader) segue negado. - Job principal: "manter a biblioteca limpa e recuperar um corte que falhou sem ter de voltar à fala de origem".
- Fluxo desejado: abre a biblioteca → vê um corte que não serve (ou um "Falhou") → no item ou no detalhe decide apagar (com confirmação) ou tentar de novo → a lista reflete: o corte sumiu, ou o corte falhado voltou a processar.
- Anti-goals de produto: não virar lixeira/desfazer (soft delete), restauração de apagado, ações em lote, editor de vídeo, métricas ou segundo fluxo de corte.
- Reabertura de anti-goal (produto): o C168 (#1015,
docs/plans/c168-biblioteca-cortes.md) declarou "deletar corte não existe na UI (admin pode)" como guardrail aceito. O pedido humano reabre esse anti-goal de propósito. Ao apagar, respeitar o contrato da página pública: um cortepublishedtem link público/corte/<id>, então apagá-lo é ação explícita e avisada — nunca em silêncio.
Esboço de fluxo (B)
[biblioteca de cortes: lista] → abre item/corte
→ corte que não serve: [Apagar] → confirmação (avisa o link público se published) → some da lista
→ corte "Falhou": [Tentar novamente] (ou já não aparece como item morto)
→ [outcome: biblioteca limpa e corte falhado recuperável de onde se vê a falha]
Design UI (B)
- Design UI (gate):
docs/plans/biblioteca-cortes-apagar-e-falhas-ui-design.html
Objetivo e aceite
- A biblioteca (lista e/ou detalhe) permite apagar um corte, com confirmação explícita do efeito no link público quando o corte está publicado.
- Corte falhado não fica como item morto: ou é descartado automaticamente, ou aparece com "Tentar novamente" acionável — nunca as duas coisas ausentes.
- Nenhuma leitura nova de métricas, comentários ou coleções.
- Quem pode apagar: a mesma audiência da vertical que hoje lê/edita o acervo (
communicator,coordinator,candidate), alinhada ao kill-switch de publicar/despublicar; o admin do Payload segue podendo.advisoreleadernegados (fail-closed). - Guardrail de produto preservado: apagar um
failednão quebra nada público (nunca houve página); apagar umpublishedquebra o/corte/<id>já distribuído — por isso o aviso.
Dados (intenção)
- Vou apresentar dados? Não — é uma decisão de estado do item (apagar/recuperar), não um painel.
- Decisões desbloqueadas: a assessoria decide o que sai da biblioteca e o que vale tentar de novo; nenhuma leitura agregada nova.
- Forma: adiada ao plano de implementação — restrição de produto: sem contadores de biblioteca nem métricas de falha.
Dados da decisão (literais)
- Vocabulário de status:
processing|published|unpublished|failed; o rótulo visível defailedé "Falhou". - Contrato público:
failednunca tem página pública (nada foi publicado);publishedtem link público/corte/<id>— apagar quebra esse link para quem já recebeu. - Rotas internas:
/campanha/comunicacao/acervo/cortes(lista) e/campanha/comunicacao/acervo/cortes/[id](detalhe). - Retry existente: é por request (
retryOf) e só aceitastatus === 'failed'— reusa a row, não duplica. - Copy de confirmação (apagar publicado): título "Apagar este corte?" · corpo "O link público /corte/ deixa de funcionar para quem já recebeu. Esta ação não pode ser desfeita." · botões "Cancelar" / "Apagar".
- Copy de confirmação (apagar não publicado/falho): mesma pergunta sem a linha do link público; botões "Cancelar" / "Apagar".
- Acesso:
communicator,coordinator,candidateapagam e reprocessam;advisoreleadernegados (fail-closed); admin mantém o delete do Payload.
Direção no codebase (hipótese)
- Áreas prováveis:
src/collections/SpeechCut.ts(access de delete hoje é só-admin),src/utilities/speech/speechCutListUrl.ts+speechCutPageData.ts(owheresemqvolta{}e a lista incluifailed),src/components/campaign/speech/SpeechCutLibraryCard.tsxe o detalhe.../cortes/[id]/page.tsx,SpeechCutDialog.tsx+actions/speech.ts(retry reusável), e as rotascortes/[id]/.... - Precedente a olhar: o kill-switch de publicar/despublicar e a confirmação de "Despublicar este corte?" do C168; o retry por
retryOfdo C167. - Risco de acoplamento: não criar fluxo paralelo ao retry do C167 (editar o dono); não misturar com o
where/ordenação das falas; gatespeechCataloge leader lockdown intocados;/corte/<id>é do C167 (aqui só se decide o efeito de apagar).
Dependências
- C168 (#1015, entregue) — a biblioteca é a superfície; seu anti-goal de "não deletar pela UI" é reaberto aqui.
- C169 (#1045, entregue) — falha honesta e retry por row; é o material do tratamento de corte falhado.
- Suave: C167 (#1014) — o retry por request que se reusa.
Fora de escopo
- Editor de vídeo (trocar início/fim, re-render) — destino: nenhum, não é pedido.
- Lixeira/desfazer e restauração de apagado (soft delete) — reversibilidade fica fora desta fatia.
- Ações em lote (apagar/tentar vários).
- Métricas, comentários, coleções/kits.
- Mudar a página pública além de a ação de apagar refletir nela.
Rabbit holes de produto
- "Já que apaga, deixa uma lixeira pra desfazer." Se alguém "só completar": soft delete, retenção e restauração. Corte neste item: apagar é definitivo, com confirmação; sem lixeira.
- "Corte falhado vira fila de reprocessamento automático." Se alguém "só completar": worker/cron e retry em lote. Corte neste item: resolver no ponto da falha (diálogo de origem) com o retry que já existe; na biblioteca, no máximo um "Tentar novamente" manual.
- "Aproveita e mostra estatística de falhas." Se alguém "só completar": dashboard de vaidade. Corte neste item: sem métrica.
Questões em aberto (produto)
- Descartar corte falhado automaticamente ou manter com "Tentar novamente"? Opções: A) a falha deixa de virar item de biblioteca e é resolvida onde nasceu (diálogo da fala, retry existente) | B) o falhado aparece na biblioteca com "Tentar novamente" acionável. Recomendação: A, com B como piso — falha não é acervo; se por algum motivo ela aparecer na biblioteca, aparece com retry, nunca como item morto. (assumido — validar no gate)
- Apagar só o falhado/não publicado ou qualquer corte com aviso? Opções: A) só falhado/não publicado | B) qualquer corte, com aviso explícito pelo link público. Recomendação: B — a assessoria precisa poder remover um corte errado/duplicado mesmo publicado; o aviso cobre o contrato do link. (assumido)
- Onde fica a ação? Opções: A) no detalhe | B) no item da lista e no detalhe. Recomendação: B — a lista é onde a limpeza acontece; a confirmação evita o clique errado. (assumido)
- Publicado, apagar é definitivo ou só despublica? Opções: A) apaga de vez com aviso | B) redireciona para "Despublicar". Recomendação: A — despublicar é reversível e já existe; quem quer apagar quer remover. (assumido)
Referências
- GitHub Issue: — (após
pnpm agent:register) - Design UI (gate):
docs/plans/biblioteca-cortes-apagar-e-falhas-ui-design.html docs/plans/c168-biblioteca-cortes.md(anti-goal reaberto) ·docs/plans/c169-corte-vod-confiabilidade.md·docs/plans/c167-cortar-trecho-publicar.md- Arquivos-chave (pista, não contrato):
src/collections/SpeechCut.ts,src/lib/speechCut.ts,src/utilities/speech/speechCutListUrl.ts,src/utilities/speech/speechCutPageData.ts,src/components/campaign/speech/SpeechCutLibraryCard.tsx,src/components/campaign/speech/SpeechCutDialog.tsx,src/app/(campaign)/campanha/(app)/comunicacao/acervo/cortes/[id]/page.tsx,src/app/(campaign)/campanha/actions/speech.ts - Testes a tocar:
tests/unit/speechCutDialog.unit.spec.tsx,tests/unit/speechCutListUrl.unit.spec.ts,tests/int/speechCut.int.spec.ts,tests/e2e/campaignSpeechCut.e2e.spec.ts AGENTS.md/AGENTS-campaign.md— vertical Comunicação, gate do acervo, naming/i18n
Self-score (shaping)
5/5 — (1) fatia = um outcome verificável (apagar um corte e não acumular falhados); (2) appetite ~1 dia declarado e o escopo cabe (encaixe na biblioteca, sem lixeira/fila/editor); (3) persona, job e aceite em linguagem de usuário, com a reabertura de anti-goal e o contrato do link público explicitados; (4) direção no codebase é hipótese com precedente nomeado, sem contrato; (5) zero decisão dura de engenharia (rota exata da ação e access ficam para o plano de implementação — aqui só se declara quem pode apagar, como decisão de produto).