fix(inbox): a sugestão de resposta diz por que falhou, e a rejeitada sai da tela - #740
Conversation
…sai da tela
Dois defeitos medidos numa instalacao real em 2026-09-12.
1) A REJEITADA NAO SAIA DA TELA
O painel pedia as cinco ultimas sugestoes (`order by created_at desc limit 5`)
e mostrava a primeira SEM olhar o estado dela. Rejeitar nao fecha nada: a
rejeitada continua sendo a mais recente, entao o texto morto ficava na tela,
com a caixa desabilitada e sem botao de fechar — nao existe nenhum no
componente.
O caso que travou de vez: quem rejeita costuma pedir outra em seguida. Se essa
geracao falha, nada substitui a rejeitada e a tela fica presa. Foi exatamente o
que aconteceu.
Escolha deliberada: olhar SO a mais recente. Procurar na lista a primeira que
ainda sirva ressuscitaria uma sugestao antiga logo depois de a atual ser
rejeitada — um texto que o atendente acabou de recusar voltando sozinho.
`failed` continua aparecendo: a frase dela e a unica pista que sobra.
E a confirmacao da rejeicao estava amarrada a `draft` existir. Sem ajustar
isso, o conserto faria o aviso sumir junto com a sugestao, e o clique em
Rejeitar apenas esvaziaria a tela em silencio.
2) O ERRO NAO DIZIA NADA, E O IDENTIFICADOR NAO LEVAVA A NADA
A rota fazia `} catch {` — SEM NOME. A causa morria ali. Tres situacoes sem
nada em comum viravam a mesma frase, que mandava conferir a publicacao do
agente mesmo quando o problema era o provedor de IA fora do ar.
E nada era registrado — nem logger, nem Sentry — enquanto a tela exibia o
requestId, o que faz a mensagem PARECER rastreavel. Um numero que promete e nao
entrega manda a pessoa procurar onde nao ha o que achar.
Agora `motivoDaFalha` nomeia as duas causas que `generateReplyDraft` lanca de
proposito, o resto admite que e outra coisa, e o motivo vai para o
`logger.error` com org, conversa e requestId.
MEDIDO E DESCARTADO: a hipotese de que a falha vinha de enviar conteudo vazio
nao se sustenta. Os tres caminhos ja validavam — o composer barra em
`Composer.tsx:111` e `:344`, o "Aprovar e enviar" em `!body.trim()`, e o
"Sugerir resposta" nao tem campo nenhum. Nao ha validacao faltando; ha causa
escondida, que e o defeito 2.
Regras puras em `lib/agent-engine/agent/sugestao-de-resposta.ts` para poderem
ser medidas fora da tela, com cerca de forma contra o `catch` sem nome voltar.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
@paulolimajr77 is attempting to deploy a commit to the rafael-maudibrasil's projects Team on Vercel. A member of the Team first needs to authorize it. |
ECC Tools / Security EvidenceCommit: Security scanner evidence required (action_required) Detected 1 security-sensitive predictive risk signal(s) without scanner evidence. Mode: enforce Findings:
Touched security-sensitive paths:
Expected evidence:
Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
ECC Tools / PR Risk TaxonomyCommit: PR taxonomy review recommended (neutral) Detected 2 PR taxonomy bucket(s): Security Evidence, CI/CD Recommendation. Scanned 6 changed file(s). Roadmap taxonomy buckets: Security EvidenceSecurity-sensitive changes should carry explicit scanner, code-scanning, or focused regression evidence. Signals:
Paths:
CI/CD RecommendationCI, dependency, coverage, and contract signals should be routed into follow-up checks or verification work. Signals:
Paths:
Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
ECC Tools / Reference Set ReadinessCommit: Reference set readiness gaps detected (neutral) Reference evidence present for 0/7 areas (0%) across 6 changed file(s). This check is based on files changed in this PR. Repository-level readiness is still reported by
Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
ECC Tools / Hosted Promotion ReadinessCommit: Hosted promotion readiness passed (success) No hosted promotion evidence gaps detected across 6 changed file(s); 0 corpus scenarios had matching evidence. This check compares PR file changes against the evaluator/RAG promotion corpus in No evaluator corpus scenarios matched this PR. Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
|
Recebido, @paulolimajr77 — obrigado por isto. Duas coisas que vão parecer erro seu e não são:
Um mantenedor vai revisar de verdade — rodando os gates e reproduzindo o comportamento, não só Esta mensagem é automática e não diz nada sobre o seu PR: ela é sobre o processo. O que vem |
Dois defeitos da tela de atendimento, medidos numa instalação real em 2026-09-12.
O que muda para quem atende
1. A sugestão rejeitada não saía da tela
ReplyReviewPanelpedia as cinco últimas sugestões da conversa e mostrava aprimeira sem olhar o estado dela:
Rejeitar não fecha nada: a rejeitada continua sendo a mais recente. E não há
botão de fechar no componente — procurei, não existe.
O caso que trava de vez, e foi o que aconteceu: quem rejeita costuma pedir
outra em seguida. Se essa geração falha, nada substitui a rejeitada e a tela
fica presa naquele texto, indefinidamente.
Agora
dismissed,staleesentsoltam o painel.failednão — a frasedela é a única pista que sobra para quem não sabe por que a sugestão não veio.
Duas decisões que valem explicar:
primeira que ainda sirva — ressuscitaria uma sugestão anterior logo depois de
a atual ser rejeitada: um texto que o atendente acabou de recusar voltando
sozinho para a tela. Há um caso cobrindo exatamente isso.
draftexistir. Sem ajustarjunto, o conserto faria o aviso "o feedback será usado na próxima sugestão"
sumir com a sugestão, e o clique em Rejeitar apenas esvaziaria a tela em
silêncio.
2. O erro descartava a causa — e o identificador não levava a nada
A rota fazia
} catch {— sem nome. A causa morria ali, e três situaçõessem nada em comum viravam a mesma frase, que manda conferir a publicação do
agente mesmo quando o problema é o provedor de IA fora do ar:
reply_no_agentreply_context_unavailableE nada era registrado — nem
logger, nem Sentry — enquanto a tela exibia orequestIdao lado da mensagem, o que a faz parecer rastreável. Não era:não havia nada gravado para procurar com aquele identificador. Um número que
promete e não entrega manda a pessoa procurar onde não há o que achar. Foi
assim que este defeito chegou até aqui: com o identificador em mãos e sem
caminho nenhum para a causa.
Agora
motivoDaFalhanomeia as duas causas quegenerateReplyDraftlança depropósito, o resto admite que é outra coisa, e a causa vai para
logger.errorcom organização, conversa e
requestId.O que eu medi e DESCARTEI
A primeira hipótese era que a falha vinha de enviar conteúdo vazio. Não se
sustenta — os três caminhos já validavam, e está medido:
Composer.tsx:111(if (!body || …) return) e:344(botão desabilitado)disabled={… || !body.trim()}{}Não falta validação. Falta a causa aparecer — que é o defeito 2. Registro aqui
para ninguém refazer esse caminho.
O que eu medi
typechecklint(arquivos tocados)mainsem este PRSabotagem, previsto × medido — cada conserto desfeito sozinho, um por vez,
com restauração conferida em passo separado:
sugestaoParaMostrarvolta a devolver a mais recente} catch {sem nome voltaOs cinco vermelhos são de ambiente desta máquina (resolução do
pdfjs-distnoWindows) e estão medidos nos dois lados. Uma primeira rodada trouxe três
arquivos a mais; rodados sozinhos, os três passam, e a segunda rodada da suíte
inteira voltou aos mesmos cinco — instabilidade da máquina, registrada aqui em
vez de omitida.
Os controles positivos ficaram verdes nas duas: a sugestão que espera revisão
continua aparecendo, e as três frases de erro continuam distintas. Sem eles,
uma implementação que escondesse tudo — ou que devolvesse sempre o genérico —
passaria por metade dos casos sem conservar nada.
O que eu NÃO medi
visíveis, e merecem ser conferidos por quem revisar.
justamente o que o defeito 2 impedia de saber. O que este PR garante é que a
próxima ocorrência diga qual foi.
generateReplyDraft. As duas exceções que ela lança jáexistiam; só pararam de ser descartadas.
Checklist (Definition of Done)
pnpm typecheckzeradopnpm lintzeradopnpm test:unit)console.logesquecidoreply_no_agent,reply_context_unavailable) e o antigoreply_unavailablecontinua sendo o genéricoFragmento em
.changes/incluído.🤖 Generated with Claude Code