1. O momento: quando o app funciona por fora mas range por dentro
No começo tudo é mágica. Você diz à IA "adicione uma tela de perfil" e ela aparece. "Agora um botão para exportar", e aparece. Você vai rápido, muito rápido. Mas tem um momento — quase sempre entre a terceira e a décima semana — em que algo muda. Pedir uma função pequena já não é instantâneo. A IA demora mais, se confunde, mexe em coisas que não devia. Aparecem bugs em lugares que você nem tocou. O app funciona, mas mexer nele ficou pesado, como andar com barro nos sapatos.
Esse é O momento. Não aconteceu nada dramático: não quebrou nada visível. O que aconteceu é invisível e se chama dívida técnica. A IA construiu rápido e, como todo mundo que constrói rápido, deixou entulho: código que ninguém mais usa mas continua ali, a mesma lógica copiada em cinco arquivos, tipos any que desligam todos os alarmes, animações montadas de qualquer jeito. Nada disso aparece na tela. Tudo isso faz cada mudança futura ser mais difícil.
2. A dor: de onde vem e por que a IA suja (mesmo escrevendo "bem")
Aqui o importante e honesto: a IA não escreve código ruim. Ela escreve código que funciona. O problema é que otimiza para "funcionar agora", não para "ser fácil de manter daqui a três meses". E essas duas coisas puxam em direções diferentes. Por isso, mesmo cada pedaço estando bom, a soma fica suja. Estes são os quatro tipos de entulho que ela deixa, e por que deixa:
- Código morto. Você pede uma mudança, a IA reescreve uma função nova… mas esquece de apagar a antiga. Ela fica ali, órfã, sem ninguém chamar. Multiplique isso por centenas de mudanças e você tem arquivos inteiros que não servem mais para nada.
- Duplicação. A IA nem sempre lembra que já escreveu essa mesma lógica antes, então escreve de novo. Agora a mesma regra vive em cinco lugares. No dia em que a regra mudar, tem que corrigir cinco vezes — e sempre esquece uma.
- `any` e tipos frouxos. Quando a IA não tem certeza do tipo de um dado, ela pega o atalho: marca como
any. Com isso desliga todos os alarmes que o TypeScript tem para te avisar de erros. O código compila… e explode em produção. - Animações e efeitos montados na força bruta. A IA coloca gradientes animados, desfoques, sombras — parecem bonitos, mas mal montados fazem a GPU suar e o app fica lento em celulares e notebooks modestos.
3. As 7 fases da cirurgia (o coração de tudo)
Um cirurgião não abre e fuça a esmo: segue um protocolo, em ordem, passo a passo. A cirurgia de código é igual. São sete fases, e a ordem importa: primeiro você tira o que está morto (para não limpar código que ia apagar), depois funde duplicados, depois endurece animações, depois o desempenho do React, depois os tipos, depois acalma a GPU, e no fim emite um relatório de saúde. Aqui vai cada uma.
Fase 1 · Eliminar código morto
A primeira coisa é tirar da mesa tudo que já não respira. É a fase mais rentável porque limpa o terreno para todas as outras: não faz sentido otimizar uma função que você vai apagar.
- Arquivos órfãos — arquivos que ninguém importa de lugar nenhum. Estão ali de uma versão antiga que nunca foi apagada.
- Exports sem consumidores — funções ou componentes exportados que ninguém usa. Foram exportados "por via das dúvidas" e as dúvidas nunca chegaram.
- Variáveis, funções e imports sem uso — declarados e esquecidos. O linter costuma marcá-los, mas a IA os deixa porque "não incomodam". Incomodam sim: são ruído.
- Ramos de código inalcançáveis — condições que nunca podem ser verdadeiras, código depois de um
return,ifque ninguém dispara mais.
Fase 2 · Auditar duplicados
Com o terreno limpo, agora você busca o que está repetido. A regra do ofício é simples: se algo aparece três vezes ou mais, deixa de ser coincidência e passa a ser um padrão que merece um único lugar onde viver.
- Lógica repetida → extraia para uma função auxiliar (
helper) que os dois lugares chamam. Uma regra, um único lugar. - Números e textos mágicos repetidos (o mesmo
48, a mesma URL, a mesma cor) → centralize em constantes com nome. Muda uma vez, muda em todos os lugares. - JSX repetido três ou mais vezes (o mesmo card, o mesmo botão com leves variações) → transforme num subcomponente que recebe suas diferenças por props.
- O padrão `useState` + seu handler repetido (o mesmo estado com sua função de atualização copiado em vários componentes) → extraia para um hook próprio (um
custom hook) que encapsula a lógica uma única vez.
Fase 3 · Cumprir as regras de animação
As animações são onde a IA mais improvisa e onde mais deixa falhas sutis — coisas que não quebram mas fazem o app parecer "barato": piscadas, saltos, transições que não engatam. Estas são as regras concretas que a cirurgia verifica (valem para bibliotecas de animação do React como Motion / Framer Motion, o padrão do ecossistema):
- Animar para/de `transparent` pode piscar → use
rgba(0,0,0,0)no lugar. Quando você interpola a palavratransparentcom uma cor, a transição pode dar uma piscada feia no meio do caminho;rgba(0,0,0,0)interpola limpo. - Sem `transition` duplicado — uma animação com duas definições de transição brigando entre si dá um resultado imprevisível. Uma única fonte de verdade para o timing.
- Não animar o atalho `border` (o shorthand que junta espessura, estilo e cor) → anime propriedades separadas como
borderColor. O shorthand não interpola limpo. - `background` → `backgroundColor` em animações — animar o atalho completo
backgroundé problemático; anime só a propriedade específica que muda. - Keys estáveis em listas que entram e saem (
AnimatePresence) — se os elementos de uma lista animada não têm umakeyestável e única, as animações de saída quebram e os elementos saltam. A key deve ser um id real, nunca o índice do array.
Fase 4 · Desempenho do React
Aqui a cirurgia busca o trabalho que o React repete sem necessidade. Cada re-render desnecessário é um pouquinho de lentidão; somados, fazem o app parecer pesado. Quatro coisas concretas são revisadas:
- Handlers passados como props sem `useCallback` → envolva-os. Se não, cada render cria uma função nova e obriga os componentes filhos a re-renderizar mesmo sem nada ter mudado.
- Cálculos caros sem `useMemo` (filtrar/ordenar uma lista grande, cálculos pesados) → memoize-os. Se não, são recalculados a cada render mesmo com os dados idênticos.
- `useEffect` com dependências mal declaradas — dependências a mais disparam o efeito sem razão; dependências a menos fazem ele usar dados velhos. Ambas são bugs. O array de dependências deve listar exatamente o que o efeito usa.
- `.map` sem `key` estável — renderizar listas sem uma key única (ou usando o índice) faz o React se confundir ao reordenar e perder estado. Cada elemento precisa do seu id próprio.
useCallback e useMemo "por via das dúvidas". Não: memoizar também custa (memória, complexidade). A cirurgia só memoiza onde há benefício real e mensurável — um handler que desce para muitos filhos, um cálculo de verdade caro. Otimizar demais é a sua própria forma de sujeira.Fase 5 · Higiene do TypeScript
O TypeScript é o sistema de alarmes do seu código: te avisa antes de um erro chegar ao usuário. Mas só funciona se você deixar ele enxergar os tipos. Cada any é um alarme que alguém desligou. Esta fase os liga de novo.
- `any` → um tipo real, ou `unknown` — o
anydesativa todas as verificações. Se você de verdade não sabe o tipo, useunknown, que te obriga a verificá-lo antes de usar (seguro), em vez deany, que não obriga a nada (perigoso). - Revisar os casts `as Tipo` — dizer ao TypeScript "confie em mim, isto é deste tipo" é uma promessa que pode ser mentira. Cada
asé um ponto onde o compilador parou de verificar. São revisados um por um: é verdade, ou é um remendo? - Internalizar exports de uso único — se um tipo ou função é exportado mas só é usado no próprio arquivo, não deveria ser público. Torne-o privado: menos superfície, menos ruído.
- Tipar as props dos componentes — cada componente deve declarar quais props recebe e de que tipo. Props sem tipo são
anydisfarçados.
Fase 6 · Auditar o colapso da GPU
Esta é a fase que quase ninguém conhece e a que mais se nota em dispositivos modestos. Certos efeitos visuais são lindíssimos mas brutalmente caros de desenhar: se você abusa deles, a placa gráfica satura e o app trava. A cirurgia busca os três culpados clássicos:
- Gradiente cônico (`conic-gradient`) animado → mova-o para uma animação CSS com
@keyframes. Animar um gradiente cônico por JavaScript a cada frame é caríssimo; com keyframes o navegador otimiza. - Muitos `repeat: Infinity` (várias animações em loop infinito ao mesmo tempo) → consolide-as. Dez animações eternas rodando em paralelo mantêm a GPU acordada e queimando bateria sem parar. Junte-as ou reduza as que de fato são necessárias.
- `backdrop-blur` em muitos elementos pequenos repetidos → se o mesmo desfoque de fundo se repete em vinte cardzinhos, a GPU o recalcula vinte vezes. Para elementos pequenos e repetidos, um fundo sólido (ou semitransparente) parece quase igual e custa uma fração.
backdrop-blur, aquele efeito de vidro fosco tão da moda) obriga a GPU a olhar TUDO que está atrás do elemento e borrar em tempo real. Um só, grande, tudo bem. Vinte pequenos se repetindo é como pedir para a placa borrar a tela vinte vezes por frame. É aí que o notebook do seu usuário começa a soprar a ventoinha.Fase 7 · O relatório de saúde
Toda cirurgia termina com um laudo. Sem relatório você não sabe o que foi tocado nem pode confiar que não houve danos colaterais. A última fase é o agente te entregar um resumo claro, no seu idioma, de tudo que fez:
- Contagem por fase — quantos arquivos órfãos, quantos duplicados fundidos, quantos
anyeliminados, quantas animações corrigidas, etc. - Linhas expurgadas — o total de linhas de código morto que saíram. É o número mais satisfatório: código que você não precisa mais manter.
- Veredito de "pronto para produção" — a confirmação explícita de que nada visual nem de comportamento foi mudado, só a estrutura interna.
- O que NÃO foi tocado e por quê — as coisas que pareciam candidatas mas foram deixadas de propósito (duplicados que mudam por razões diferentes, memoize que não valia a pena). A honestidade do que se decidiu não fazer.
4. O hábito: a cirurgia é manutenção, não uma operação única
O erro mais comum é pensar a cirurgia como algo que você faz uma vez, quando já está tudo uma bagunça. Não. O código de IA suja CONTINUAMENTE, porque cada sessão de construção deixa entulho novo. A cirurgia não é uma operação de emergência: é a limpeza de dentes que você faz a cada seis meses para nunca chegar ao canal.
- Depois de um sprint grande de construção — quando a IA acabou de gerar muito código de uma vez, esse é o entulho fresco. Limpe antes que se acumule por cima.
- Antes de começar uma função importante — dê à IA uma tela limpa para construir. Sobre código sujo, ela constrói sujo.
- Quando você percebe que a IA começa a se confundir — se a ferramenta mexe em coisas que não devia ou se perde, é sinal de que há ruído demais. A cirurgia devolve clareza a ela.
- Um arquivo ou módulo por vez, não o projeto todo de uma vez — operar um único módulo é seguro e revisável. Operar tudo de uma vez é uma cirurgia de coração aberto sem anestesia. Vá por partes.
5. O prompt mestre · passe para o seu agente e opere fase por fase
Aqui está a peça-chave: UM único prompt que transforma seu agente de código num cirurgião que aplica as 7 fases, em ordem, a um arquivo ou módulo — sem tocar em nada visual. Preencha os [colchetes], cole, e deixe operar. Um conselho antes: faça um commit no GitHub primeiro (sua rede de segurança) e mire em UM módulo, não no projeto todo.
Aja como um cirurgião de código especialista em debug. Você vai operar este arquivo/módulo: [CAMINHO DO ARQUIVO OU PASTA, ex: src/components/Dashboard/]. A stack é: [ex: React + TypeScript + Motion/Framer Motion + Tailwind]. REGRA SAGRADA E INVIOLÁVEL: ZERO mudanças visuais e ZERO mudanças de comportamento. O app deve parecer e se comportar EXATAMENTE igual antes e depois. Você só limpa e endurece por dentro. Diante de qualquer dúvida entre limpar mais ou preservar o comportamento, SEMPRE ganha preservar o comportamento. Não apague nada se você não tiver certeza de que não é usado; marque e me pergunte. Aplique estas 7 fases EM ORDEM. Não passe para a próxima sem terminar a anterior. Ao fim de cada fase, me diga em uma linha o que encontrou e o que mudou. FASE 1 — CÓDIGO MORTO: elimine arquivos órfãos (que ninguém importa), exports sem consumidores, variáveis/funções/imports sem uso, e ramos de código inalcançáveis. Antes de apagar algo duvidoso, liste para mim e espere minha confirmação. FASE 2 — DUPLICADOS: busque lógica repetida (→ extraia para um helper), números/textos mágicos repetidos (→ constantes com nome), JSX repetido 3+ vezes (→ subcomponente com props), e o padrão useState+handler repetido (→ custom hook). NÃO funda coisas que só se parecem mas mudam por razões diferentes. FASE 3 — REGRAS DE ANIMAÇÃO: corrija transparent→rgba(0,0,0,0), elimine transition duplicado, não anime o shorthand border (use borderColor), troque background→backgroundColor em animações, e garanta keys estáveis e únicas (nunca o índice) em listas com AnimatePresence. FASE 4 — DESEMPENHO REACT: envolva em useCallback os handlers passados como props, memoize com useMemo os cálculos caros, corrija os arrays de dependências do useEffect (nem a mais nem a menos), e adicione key estável a cada .map. NÃO memoize por via das dúvidas: só onde houver benefício real. FASE 5 — TYPESCRIPT: substitua cada any por um tipo real ou por unknown; revise cada cast 'as Tipo' (é verdade ou é remendo?); internalize os exports que só são usados no próprio arquivo; e tipe as props de todos os componentes. FASE 6 — COLAPSO DE GPU: mova gradientes cônicos animados para CSS @keyframes; consolide os repeat:Infinity se houver muitos ao mesmo tempo; e substitua backdrop-blur por um fundo sólido/semitransparente em elementos pequenos que se repetem muitas vezes. FASE 7 — RELATÓRIO DE SAÚDE: ao terminar, me entregue um relatório com: contagem por fase, total de linhas expurgadas, a confirmação explícita de que você não mudou nada visual nem de comportamento, e uma lista do que você decidiu NÃO tocar e por quê. Trabalhe fase por fase, me mostre o diff de cada uma, e se algo colocar em risco a regra sagrada, PARE e me pergunte antes de seguir.
6. Verifique que a cirurgia não deixou feridas
Uma cirurgia não termina quando você fecha: termina quando você confirma que o paciente está bem. A regra sagrada (zero mudanças de comportamento) precisa ser comprovada, não só confiada. Há duas redes de segurança automáticas que confirmam isso em segundos, e que seu agente pode rodar sem você programar nada.
# 1) A checagem de tipos: zero erros = a cirurgia não quebrou os contratos npx tsc --noEmit # 2) Os testes: se passavam antes e passam igual depois, # o comportamento foi preservado npm test
git diff. Regra de leitura: quase tudo que você ver deve ser linhas VERMELHAS (apagadas) ou movimentos de lugar, não lógica nova. Se aparecerem cadeias de texto que o usuário vê mudadas, valores padrão diferentes, ou condições novas, aí há uma possível ferida — pergunte à IA por quê antes de aceitar.7. Os caminhos mais fáceis · o que a IA faz por chat e o que você decide
Para não complicar: a maior parte da cirurgia o seu agente de código faz sozinho, pelo chat. O seu papel é dirigir e aprovar. Esta é a divisão.
- Percorrer o módulo e detectar o código morto, os duplicados, os
anye as animações mal montadas — você só dá o prompt mestre. - Aplicar as correções fase por fase, mostrando o diff de cada uma.
- Rodar
tsce os testes para confirmar que não quebrou nada. - Escrever o relatório de saúde final com as contagens e o que decidiu não tocar.
- Fazer o commit de segurança ANTES — seu botão de desfazer. Isso você faz pelo GitHub Desktop ou pelo chat, antes de operar.
- Aprovar os apagamentos duvidosos — quando a IA não tem certeza se algo é usado, ela te pergunta; a decisão final é sua.
- Revisar o diff — ler as mudanças e confirmar que não há feridas de comportamento antes de aceitar.
- Decidir o escopo — qual módulo se opera e em que ordem. Não delegue "opere tudo": vá por partes.