Files
DeskcommCRM/evidence/wave6-d20-editar-sem-fechar.png
Rafael MelgaçoandClaude Opus 5 e340882587 fix(crm-vivo): lead_edited nomeia o que MUDOU, não o que foi enviado [wave 6]
Achado provando o D20 na tela: mudei APENAS a descrição pelo dossiê e a timeline
registrou "Alterou o título, a descrição, o valor, a data prevista de fechamento
e as tags". Cinco campos, um mexido.

A causa é a família de defeito desta entrega inteira — um lado do contrato mudou
e o outro não acompanhou. O formulário do dossiê usa react-hook-form e envia o
form INTEIRO a cada salvamento; o handler lia `Object.keys(input)` e tratava
ENVIO como ALTERAÇÃO. Ninguém reclamava porque os dois lados estavam "certos".

E o dano não é cosmético: um registro que afirma o que não aconteceu é pior que
registro nenhum. Ele é lido como verdade, entra na auditoria, e quem investigar
"quem mexeu no título deste negócio?" acusa a pessoa errada — na única
superfície do produto que promete contar a vida do lead.

`camposAlterados(patch, anterior)` compara valor a valor (lib/leads/), com as
armadilhas que a comparação ingênua erraria: tag reordenada não é alteração,
`null`/`""`/`undefined` são o mesmo estado "não preenchido", e campo derivado
(updated_at, assigned_at, owner_kind) nunca é "o que a pessoa alterou" — nomeá-lo
seria mentir na direção oposta.

Duas decisões que valem registro:

 - o SELECT do estado anterior virou `*`, não lista de colunas. Com lista fixa,
   um campo NOVO no patch cairia contra `undefined` e seria marcado como
   alterado em toda edição: o mesmo defeito voltando por outra porta em seis
   meses. Nenhuma query a mais — o select já existia;
 - salvar sem mexer em nada deixou de emitir atividade. Não é acontecimento.

NÃO mexi no `emit_event lead.updated`: ele passa a carregar o payload correto de
graça, mas suprimi-lo quando nada muda alteraria o gatilho de automações
existentes. Isso é decisão de contrato, não minha — fica para o Arquiteto.

PROVA na tela (sonda tests/sonda-dossie-d20-d21.ts):
  D20.3 "Alterou a descrição" — e só ela
  D20.5 o texto digitado NÃO vazou para a linha (o reason nomeia campo, §9)
  D20.7 salvar sem mexer: 1 PATCH SAIU, updated_at mudou no banco, e nenhuma
        linha entrou. Os dois primeiros existem porque "não registrou" passaria
        igualzinho se o clique não tivesse feito nada — acertando pelo motivo
        errado e provando o oposto do que afirma.
  D20.1 o Sheet continua aberto · D20.4 a linha entra marcada "agora"
  D21   PATCH de outra aba entra ao vivo sem recarregar (canal subscribed)
  evidence/wave6-d20-editar-sem-fechar.png · wave6-d21-outra-aba-ao-vivo.png

A sonda repara o lead na saída (restaura a descrição), mas NÃO apaga as
atividades geradas: elas são registro real de que a edição aconteceu.

typecheck limpo · lint 0 erros · 29 testes (5 arquivos)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013dxBNZMjUzBx8xWs8DvGvP
2026-07-25 11:34:19 -03:00

128 KiB
1400x950px