armandkaufmann/refactor-pass

Encontre o que precisa ser refatorado em um repositório Git e o que não precisa, da maneira que os desenvolvedores costumavam sentir enquanto codificavam manualmente.

O que é refactor-pass?

Esta skill oferece uma abordagem sistemática para identificar prioridades de refatoração em repositórios Git, substituindo a intuição perdida por métricas objetivas. Ela mede três aspectos fundamentais: o mapa de calor do histórico de Git, que mostra onde as mudanças realmente acontecem; um catálogo de code smells, cada um com seu playbook de refatorações nomeadas; e o custo da próxima mudança, através de um passo a passo detalhado. A skill é compatível com agentes como Claude Code, Cursor e Codex, e seu valor central está em combinar o 'onde' (arquivos quentes) com o 'que' (cheiros) para produzir um veredito claro: refatore o que muda frequentemente e tem cheiro, mas deixe em paz o que raramente é tocado. O resultado é um checklist ranqueado e um relatório que inclui tanto as refatorações recomendadas quanto os itens conscientemente deixados de lado, restaurando o equilíbrio entre ação e contenção.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/armandkaufmann/refactor-pass/tree/HEAD

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Passada de refatoração

Antigamente, refatorar começava com um pressentimento. O código era difícil de trabalhar: uma classe que você percorria para encontrar onde colocar a novidade, uma função que você mantinha na cabeça para alterar um branch, uma funcionalidade que exigia visitar oito arquivos. O mesmo pressentimento dizia o que deixar em paz. Código feio que você nunca tocava nunca doía, então você o deixava quieto.

Um agente escrevendo código não sente nada disso, e um desenvolvedor que lê principalmente o que o agente escreveu também não. Então os cheiros se acumulam sem serem notados. Um agente adicionará um trigésimo branch a uma função sem reclamar. E quando é solicitado a refatorar, ele arruma o que parece desarrumado, incluindo código que ninguém toca. Esta skill devolve ambas as metades do pressentimento, como três coisas que você pode medir:

  1. Onde você sentiria: o mapa de calor. O atrito só importa onde as mudanças continuam pousando. Em diversos estudos, o tamanho do arquivo e a frequência com que ele muda preveem problemas de manutenção melhor do que qualquer cheiro isolado.
  2. O que você sentiria: os cheiros. O catálogo estabelecido de cheiros, cada um traduzido no que contar, quando não é um cheiro, e o playbook de refatorações nomeadas que décadas de prática construíram para ele: referências/cheiros.md.
  3. O quanto você sentiria: o passo a passo. Pegue a próxima mudança que está por vir, planejada ou provável, e liste tudo o que ela tocaria.

Então o veredito combina onde e o quê:

Tem cheiroNão tem cheiro
Muda com frequênciaRefatoreDiga que está bem
Raramente mudaDeixe quieto; no máximo uma nota "Depois"Nada

A caixa "Diga que está bem" é tão importante quanto a "Refatore". É a metade da contenção da intuição, e o relatório a mostra.

Dois tamanhos de pergunta. Uma passada cobre o repositório inteiro: etapas 1 a 7. Uma pergunta sobre uma área ("devemos refatorar X?") executa as mesmas etapas apenas nessa área. Ela pula a lista de verificação a menos que haja vários itens, e sua resposta pode ser "não". De qualquer forma, primeiro execute o script da etapa 1 com --checklists sozinho: se ele listar uma lista de verificação de uma passada anterior, leia Após uma passada anterior primeiro.

1. Onde: o mapa de calor

python3 <diretório desta skill>/scripts/heatmap.py -C <repo> <escopo ...>

<diretório desta skill> é a pasta que contém este SKILL.md. Onde python3 não for o comando, como frequentemente no Windows, use python ou py.

  • Escopo: as pastas de código-fonte e as pastas de testes, como src tests ou app, não docs ou assets. Leia o README do projeto, uma listagem de diretórios e quaisquer instruções do agente (AGENTS.md, CLAUDE.md) para decidir. Arquivos de teste, conhecidos pelo nome (Board.spec.ts, test_x.py, XTest.php...) ou pasta, ficam fora da tabela e pares, e são listados separadamente quando mudam com vários arquivos. Adicione --test GLOB para outros nomes de teste, --not-test GLOB para um arquivo que só parece ser um teste (o mapa de calor nomeia qualquer um que duvidar), e --ignore GLOB para arquivos gerados.
  • Janela: por padrão, os últimos 200 commits. --since define em vez disso quando o usuário nomeia um ponto de partida ("desde v2.0", "desde que adicionamos cobrança", "os últimos três meses"): uma tag, branch ou commit, ou uma data. Commits de bots, as reformatações em massa que um repositório lista em .git-blame-ignore-revs e os commits registrados em listas de verificação anteriores são deixados de fora automaticamente. --exclude-commits exclui outros que fariam tudo o que tocaram parecer quente, como uma importação de fornecedor.
  • Muito fino? Com menos de cerca de 30 commits na janela, as contagens não podem distinguir arquivos quentes de frios. Alargue a janela, ou diga que o histórico é muito curto para apontar qualquer lugar e julgue apenas pelos cheiros. Um clone raso (o mapa de calor informa) precisa de git fetch --unshallow; pergunte ao usuário.

--help explica cada coluna e opção.

Lendo

  • Um ponto quente tem muitos commits e também é grande, então a lista os coloca primeiro: é ordenada por commits vezes tamanho. Muitos commits em um arquivo pequeno geralmente é normal, como um config editado para cada funcionalidade. Um arquivo grande que ninguém toca é barato de deixar quieto.
  • Ainda quente? recent conta seus commits na metade mais nova da janela (metade dos commits, não metade do tempo), e last é a data do mais recente. Leia ambos contra as datas da janela: oito commits recent, todos no dia em que a metade mais nova começa, são uma explosão que esfriou. Um arquivo que encolheu pode já ter sido tratado.
  • rel são linhas alteradas sobre o tamanho do arquivo. A rotatividade relativa prevê defeitos muito melhor do que a rotatividade absoluta. Muito acima de 1 significa que o arquivo foi reescrito ou cresceu na janela. Leia com crescimento: um arquivo que só cresce, commit após commit, é Crescimento Aditivo-Apenas. Um arquivo nascido na janela tem crescimento igual ao seu tamanho.
  • Pares são arquivos que mudam juntos nos mesmos commits. Um grupo são três ou mais que todos se emparelham entre si, contados pelos commits que os alteraram a todos; grupos que se sobrepõem são listados juntos como uma área.
    • Arquivos de camadas diferentes que se emparelham fortemente, ou um grupo entre camadas, geralmente significam uma funcionalidade espalhada por eles (Cirurgia com Dispersão).
    • Verifique o que liga cada par. Uma importação, uma chamada ou um contrato que algo nomeia (uma rota, um esquema, o arquivo de tipo entre um controlador e sua página) é uma dependência visível: uma funcionalidade através de um limite. Arquivos que mudam juntos sem tal ligação, como duas cópias de uma regra ou duas listas mantidas em sincronia manualmente, têm uma dependência oculta, o tipo mais forte de acoplamento.
    • Um arquivo que se emparelha com muitos outros é um hub por onde toda mudança passa.
    • Um teste listado como mudando com vários arquivos além do seu próprio está vinculado aos seus internos e bloqueará a refatoração, a menos que esses arquivos sejam um grupo que o teste apenas segue.
    • Se muitos commits eram grandes demais para emparelhar (--max-files), como em um repositório que faz squash-merge, aumente-o ou leia os pares como parciais.
  • Por que muda. Leia as mensagens de commit dos principais arquivos (--show) e agrupe-as por funcionalidade. Muitas razões não relacionadas para alterar um arquivo é Mudança Divergente, e isso aparece aqui mais diretamente do que em qualquer contagem.

2. O que: os cheiros

  • Meça os arquivos quentes contra o próprio código-fonte, dentro de um idioma. python3 <diretório desta skill>/scripts/measure.py -C <repo> <escopo ...> coloca cada arquivo em uma faixa pelos percentis 70, 80 e 90 do seu idioma, e --show <arquivo> cada uma de suas funções. Grande é a faixa do 80º ou 90º percentil (as faixas também aplicam o piso do catálogo); o 70º merece uma olhada mais de perto. Onde ele disser que os percentis se apoiam em um arquivo, julgue também pelos pontos de referência em Medindo, que também diz como contar o resto (ramos, parâmetros, coesão), ou usar o linter do projeto.
  • Leia os dois ou três principais arquivos centrais você mesmo. Números apontam; a leitura decide.
  • Revise as outras áreas quentes. Se você pode executar subagentes, dê a dois ou três deles uma área cada (uma camada ou um diretório, para que cada um leia uma área inteira uma vez) e execute-os em paralelo. Instrua cada um a partir de referencias/resumo-revisao.md. Sem subagentes, revise as áreas você mesmo, uma de cada vez, contra o mesmo resumo.
  • Nomeie cada cheiro com seu nome estabelecido (Função Longa, Cirurgia com Dispersão, Switches Repetidos...), e verifique-o contra a entrada "Não é um cheiro quando" antes de contá-lo. O nome é o índice para seu playbook.
  • Procure a ideia faltante. Cheiros viajam em clusters, e um cluster geralmente aponta para uma coisa que o código usa o tempo todo, mas nunca nomeou: um estado, a definição de um tipo, uma fonte única para uma configuração. Veja Cheiros viajam juntos.
  • Verifique quais testes alcançam o código quente: veja Código Não Testado.
  • Bugs que você notar vão para a lista como itens F, não corrigidos agora. Um bug ainda não reproduzido é uma suspeita: intitule-o como tal ("Verificar: edições pulam a regra de fim de semana"), com a evidência em sua nota. Seu primeiro passo é um teste com falha; se nenhum falhar, é pulado, com o que você encontrou.

3. Quanto: o passo a passo

Isso é o mais próximo do velho pressentimento. Também é o que torna um item convincente.

  1. Encontre as próximas mudanças. Uma mudança planejada é melhor que uma inferida, então pegue-as primeiro do que o usuário disse que está por vir ("antes de começarmos no bloco 7"), depois do plano ou roteiro do projeto, se tiver um, depois das mensagens de commit: os tipos de mudança que aparecem com mais frequência ("adicionar um novo tipo de relatório", "adicionar uma configuração", "adicionar uma tela"). Pegue os dois ou três tipos mais comuns, não apenas um.
  2. Para cada tipo, pegue o commit real mais recente dele e liste o que ele tocou (git show --stat). Se for mais antigo que a janela, use-o mesmo assim e forneça sua data; o passo a passo, no código de hoje, mostra o que mudou desde então. Se a documentação do projeto ou instruções do agente tiverem uma receita para essa mudança, conte seus passos. Uma receita de cinco passos para adicionar uma coisa é uma admissão.
  3. Percorra a próxima, sem escrevê-la. Liste cada arquivo que você precisaria ler, cada lugar que você editaria e cada cópia que você manteria em sincronia.
  4. Anote a contagem de hoje e a contagem após a refatoração que você proporia: "um novo tipo de relatório toca 7 arquivos e 3 switches hoje, e tocaria 1 arquivo depois".

Um arquivo frio onde o trabalho planejado vai pousar não é mais frio: coloque-o na linha superior da tabela, já que a próxima mudança paga o que custar. Se a próxima mudança for barata hoje, o cheiro está custando pouco, seja lá como for.

4. Verifique cada descoberta

A descoberta de um revisor é uma pista, não um fato, e o mesmo vale para suas próprias primeiras impressões. Antes de qualquer coisa ir para a lista, abra as linhas citadas, reexecute as contagens e descarte ou corrija o que não se sustentar. Diga no relatório o que você verificou. Um item errado que envia o usuário para uma refatoração custa muito mais do que o minuto que leva para verificá-lo.

Em seguida, aplique a contenção. Um revisor solicitado a encontrar problemas sempre encontrará algo, e corrigir cada descoberta deixa camadas extras e testes para casos que não podem acontecer. Deixe de fora o que é frio, o que as linhas "Não é um cheiro quando" desculpam, e o que o passo a passo diz que é barato.

5. Classifique

Dê a cada item um ID estável, porque o usuário nomeará itens por ele ("começar R4"), possivelmente em uma sessão posterior. Os nomes entre colchetes são os campos do item na lista de verificação (etapa 6); itens F, L e D dizem os seus em uma note.

  • R1, R2… Refatorações, na ordem sugerida. Para cada:
    • um título nomeando a ideia faltante, como um resultado ("Nomear os estados de um checkout", não "Refatorar CheckoutController") (title);
    • os cheiros por nome, com números e file:line (smells);
    • o tipo de mudança que facilita, da etapa 3 (eases), e o custo dessa mudança (cost: today e after);
    • o plano, como os passos do playbook (plan);
    • os arquivos, tamanho (P, M ou G) e risco (Baixo, Médio ou Alto) (files, size, risk);
    • como verificar que o comportamento não mudou (verify).
  • F1… Pequenas correções encontradas pelo caminho, cada uma seu próprio commit.
  • L1… Depois: fedorento, mas frio, ou que vale a pena fazer quando o código próximo for tocado em seguida.
  • D1… Decisão do usuário: mudanças em como eles trabalham, como uma convenção de docs que torna toda mudança cara. Apresente a troca, não uma decisão.

Classifique pelo retorno contra o risco. Retorno é o quanto a mudança facilita o trabalho futuro: o mapa de calor e o passo a passo são as evidências. As prioridades dos cheiros dizem quais tipos tendem a importar. Código longo e complexo, e mudança espalhada por arquivos, importam mais. Cheiros de acoplamento como Inveja de Funcionalidade e Homem do Meio importam menos, e são corrigidos de passagem.

Ordene a lista de modo que:

  • os bloqueadores venham primeiro: testes vinculados a internos que fariam cada passo posterior parecer que quebrou algo, e código sem cobertura de teste, cujo item começa com fixação de testes ou diz claramente que não pode ser verificado (etapa 7);
  • os itens pequenos que removem um caminho de copiar-colar venham em seguida;
  • grandes movimentos venham depois, já que frequentemente precisam de uma costura primeiro;
  • qualquer coisa que você não possa verificar por si mesmo (como soa, parece ou se sente) venha por último, porque o usuário precisa verificar.

6. Escreva a lista de verificação e o relatório

Execute o comando da etapa 1 novamente com --page .refactor-pass/<AAAA-MM-DD>.html, pela data de hoje. Ele faz a lista de verificação a partir de assets/page.html e escreve o mapa de calor em seu bloco heatmap; execute novamente, ele atualiza o mapa de calor e nada mais. Você escreve o bloco pass abaixo dele, cujo project, started, base e updated já estão preenchidos:

  • summary: o estado geral em duas ou três frases;
  • items: cada item, com os campos da etapa 5, um status (todo, doing, waiting no usuário, done, ou skipped com o motivo em seu outcome), e commits e outcome, vazios para um item novo; um item transferido mantém seu from. Cada item começa com seu ID e status em uma linha, {"id": "R1", "status": "todo",, com seus outros campos depois, como o comentário acima dos blocos mostra por completo; não como um formatador JSON bonito o dispõe, já que as atualizações de status da etapa 7 editam essa linha única;
  • left_alone: cada um com what e why;
  • checks: as verificações do projeto, de suas instruções, ou o que você verificará manualmente se não tiver nenhuma;
  • earlier: após uma passada anterior, seu checklist e results, um por refatoração concluída nele: seu id, title, eases e cost, a change real que veio em seguida e o que ela actualmente tocou (ambos vazios se nenhum veio ainda), e uma note. Caso contrário, null;
  • log: cada um com uma date e text, mais recente primeiro.

Após cada edição, execute python3 <diretório desta skill>/scripts/check_page.py <página>, que captura um colchete quebrado, um campo com erro de ortografia, um ID duplicado ou um item que não começa em uma linha. Se seu ambiente puder publicar ou pré-visualizar páginas HTML, p

[...]

Habilidades Relacionadas