Revisão de Regra de Lint (ESLint, typescript-eslint, Flint)

Revise uma regra de lint customizada da mesma forma que um mantenedor experiente de ESLint, typescript-eslint e Flint faria, encontrando bugs através de mutações na regra e executando casos de teste adversários. Use esta habilidade sempre que o usuário pedir para revisar, auditar, criticar ou verificar a sanidade de uma regra de lint, seu fixador, seus testes ou sua documentação, ou um PR ou branch que a adicione ou altere, mesmo que eles digam apenas "dê uma olhada nesta regra" ou forneçam um número de PR em um repositório de linter ou plugin. Não use-a para configurar regras de lint em um projeto ou corrigir erros de lint em código de aplicação.

O que é Revisão de Regra de Lint (ESLint, typescript-eslint, Flint)?

Esta habilidade permite revisar regras de lint (como as do ESLint, typescript-eslint e Flint) com o rigor e a profundidade de um mantenedor experiente. O revisor não apenas lê o código, mas tenta ativamente quebrá-lo: ele muta condições, executa testes adversários e compara versões antigas e novas para garantir que não haja regressões. A abordagem é empírica: descobertas apoiadas por um teste com falha ou um mutante sobrevivente têm muito mais valor do que observações superficiais. A habilidade é útil para qualquer pessoa que precise auditar a qualidade de uma regra de lint, seja ela nova ou modificada em um Pull Request (PR). A habilidade é compatível com ESLint, typescript-eslint e Flint, e pode ser usada em qualquer repositório que utilize esses linters. Ela automatiza etapas manuais críticas, como ler o diff linha por linha, verificar nomes, condições, reutilização de código e comprimento do código. Além disso, ela usa um script de mutação para alterar condições da regra e verificar se os testes existentes conseguem detectar a falha, identificando assim lacunas na cobertura de testes ou código morto. O resultado final é uma revisão completa, com comentários inline, um veredito claro (aprovação, solicitação de alterações ou revisão de alto nível) e evidências das descobertas, tudo salvo em um arquivo local.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/JoshuaKGoldberg/lint-rule-review-skill/tree/HEAD/skills/lint-rule-review-skill

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

Habilidade de Revisão de Regra de Lint (ESLint)

Revise uma regra de lint da forma que um mantenedor com milhares de comentários de revisão anteriores faria. O hábito definidor desse mantenedor é empírico: ele não apenas lê uma regra, ele tenta quebrá-la. Ele deleta uma condição e vê se um teste falha, e inventa a sintaxe em que ninguém pensou. Siga esse hábito aqui. Uma descoberta apoiada por um teste com falha ou um mutante sobrevivente vale muito mais do que uma que parece plausível, e o ruído que parece plausível é o que faz as revisões automatizadas serem ignoradas.

As descobertas vão para o usuário, que decide o que fazer com elas. Escrever a revisão em um arquivo local é todo o trabalho: publicar no GitHub, ou enviar qualquer coisa, acontece apenas se o usuário pedir separadamente.

1. Entender a mudança

Descubra o que está sendo revisado: um PR, uma branch ou um arquivo de regra. Para um PR, faça checkout do commit principal, se possível, porque as etapas posteriores executam o código.

Leia isto antes de formar opiniões:

  • A regra, seus testes e sua página de documentação
  • A descrição do PR e a issue vinculada, porque uma regra é julgada contra seu propósito, não contra seu próprio algoritmo
  • Duas ou três regras irmãs no mesmo repositório, mais a documentação CONTRIBUTING

Anote qualquer pergunta que o autor faça na descrição. A revisão deve respondê-la.

As convenções do repositório prevalecem sobre as referências desta habilidade. As referências vêm de vários projetos, portanto, se um padrão contradizer o que o repositório claramente faz, siga o repositório.

As referências são grandes, então não as leia de ponta a ponta. Comece em references/index.md, que lista todos os padrões, e extraia apenas as seções que se encaixam nesta mudança. Leia também references/extra-checks.md, que é curto e cobre armadilhas de ferramentas, além de verificações para fixadores, regras de importação e Flint.

2. Verificar o design da regra

Escolha da lista design.md no índice pelo tipo de mudança:

  • Nova regra: se ela pertence, seu escopo, sobreposição com outras regras, informações de tipo, opções e posicionamento no preset.
  • Mudança em uma regra estabelecida: impacto semântico (semver), regras irmãs que precisam da mesma mudança e se a mudança atende à issue. Pule o resto.

Se o PR for bruto, como ainda não ter testes ou um design que precise ser repensado, pare em uma revisão de alto nível e diga isso, e pule a mutação, que não pode lhe dizer nada sem testes. Ainda assim, tente a regra em alguns casos, já que um bug real vale a pena ser relatado em qualquer estágio. Comentários detalhados sobre código que está prestes a mudar perdem o tempo de todos.

3. Ler cada linha adicionada

Use o índice para extrair as seções que correspondem ao que mudou:

MudouOlhe em
Lógica da regrabugs.md, simplification.md, performance.md
Fixadores ou sugestõesfixes.md
Mensagensmessages.md
Testestest-method.md
Páginas de documentaçãodocs.md
Novos nomes, opções ou regrasnaming.md

Faça isso antes de tentar quebrar qualquer coisa, porque a caça a bugs toma conta uma vez que começa. Faça anotações enquanto avança e classifique-as na etapa 5.

Percorra o diff uma linha adicionada de cada vez e pergunte-se sobre cada uma:

  • Nomes: você saberia dizer o que este identificador contém ou faz sem ler mais? Cuidado com nomes que descrevem um tipo em vez de um propósito, e nomes que alegam a ação errada. Se foi preciso ler duas vezes para entender, diga isso e sugira um nome melhor.
  • Variáveis locais: esta variável é usada uma vez, logo após ser definida? Sugira inline.
  • Condições: ela colapsa? !x || x.kind !== y se torna x?.kind !== y. ifs aninhados ou adjacentes geralmente se fundem, e um if booleano geralmente retorna diretamente.
  • Guardas: este estado realmente pode acontecer, dado o AST e o código acima dele?
  • Reutilização: um utilitário compartilhado já faz isso? Verifique antes de aceitar qualquer auxiliar. Um auxiliar precisaria de menos parâmetros se vivesse dentro de create?
  • Comprimento: existe menos código que faça a mesma coisa? Simplificação é a maior categoria em revisões passadas.
  • Vale a pena fazer: este código ou TODO planeja algo que ninguém precisa? Diga que pode ir.

Se o código parecer assistido por IA, leia-o com um olhar mais crítico, porque é aí que o excesso tende a se acumular.

Varra cada comentário e frase da documentação. A caça a bugs ofusca isso, mas é uma fonte regular de comentários de revisão reais, então faça isso como uma passagem separada sobre cada comentário adicionado e cada linha de documentação adicionada. Não pergunte se está correto, pergunte se deveria estar lá como escrito:

  • Este comentário ficará desatualizado? Anotações sobre cobertura de teste, histórico ou o que um teste cobre ficam desatualizadas, então sugira deletá-las.
  • Ele repete o código? Sugira deletá-lo.
  • É um atalho significativo e conhecido, como um fork de código upstream? Peça um TODO, com um link para a issue se existir, e sugira o comentário exato.
  • Um usuário final se importaria com esta frase da documentação? Detalhes de implementação não pertencem à página.
  • Este exemplo de documentação carrega código que não precisa? Sugira cortar qualquer coisa além do que mostra o comportamento.
  • A frase é precisa? Cuidado com redações que soam universais ou sempre verdadeiras quando não são, e sugira uma reescrita.

Dê estes como blocos `sugestão'. Eles são rápidos para o autor aceitar.

Observe o que é bom. Anote qualquer coisa que o ajudou a revisar ou que lida com algo complicado, e mencione-o especificamente, no corpo da revisão ou como um comentário [Elogio].

4. Tentar quebrar

Esta etapa produz as descobertas de maior valor, então não a pule. Comece fazendo os testes existentes da regra passarem, para que você tenha um comando funcional que execute apenas os testes desta regra.

Mutar as condições. Execute o script incluído a partir da raiz do repositório. Ele precisa do Node 22.18 ou mais novo, que pode diferir da versão que o repositório fixa. Cada mutante é uma execução de teste, então execute-o em segundo plano. Ele edita a regra no lugar, portanto, qualquer outra coisa que você executar nesse meio tempo precisa usar uma cópia da regra salva com um nome temporário:

node <diretório-da-habilidade>/scripts/mutate-conditions.ts --file <regra> --test "<comando de teste>" --base <ref base>

--base limita os mutantes às linhas que o PR mudou, e --diff <arquivo> faz o mesmo a partir de um diff. Omita ambos para mutar uma regra nova inteira. Os mutantes são executados na ordem de origem até --max, 60 por padrão, então aumente se o resumo mostrar algum não testado. Se os testes forem executados de uma pasta de pacote, execute o script a partir dela. --out <arquivo> salva os resultados completos, e uma lista curta de sobreviventes é sempre impressa por último. Ele primeiro verifica se os testes falham quando a regra lança uma exceção, e para se não falharem, porque então eles não estão exercitando a regra. O script restaura o arquivo quando termina ou é interrompido. Se for morto abruptamente, a próxima execução se recusa a iniciar e imprime onde o original está salvo, então compare os dois antes de alterar a regra, porque você pode tê-la editado desde então. Se o comando de teste construir a regra, reconstrua depois, porque a saída da construção ainda contém o último mutante. Ele faz o parsing com o typescript do repositório, e no TypeScript 7 ou posterior, ele imprime como passar uma cópia mais antiga com --typescript.

Os mutantes que os testes não percebem são sobreviventes: cada um significa que um teste está faltando ou o código está morto, e você deve descobrir qual. Delete a condição e pense em qual entrada precisaria dela. Se você não conseguir construir uma, recomende deletar o código. Se conseguir, adicione-a à próxima etapa. Sobreviventes marcados como likelyTypeOnly são saídas de verificação nula nuas que geralmente existem apenas para o compilador, então olhe para eles por último, mas verifique se o branch não está simplesmente não testado. Se o executor de teste fizer verificação de tipo, um mutante também pode "falhar" apenas porque não compila, então use um comando de apenas transpilação quando puder.

O script cobre apenas mutações comuns. Tente também manualmente qualquer coisa que ele não possa alcançar e da qual o PR dependa, como trocar um argumento por uma variável similar já no escopo.

Comparar cabeça e base. Para uma mudança em uma regra existente, esta é a verificação mais importante. Uma regressão em código que costumava funcionar importa muito mais do que uma lacuna que já estava lá, e você não pode diferenciá-las sem executar ambas as versões. Salve a versão base ao lado da regra, por exemplo com git show <base>:./<regra> > <diretório-da-regra>/<nome>.base-tmp.ts, ou aplicando o diff de forma reversa. Em seguida, copie assets/compare-rule.test.ts ao lado dos testes da regra e ajuste suas linhas marcadas. Ele ordena cada caso comparando contagens de relatórios, e também registra mensagens, intervalos, saída de correção, sugestões, travamentos e erros de compilação em cada fixture. Leia os resultados SAÍDA ALTERADA (CHANGED OUTPUT) você mesmo, porque uma mensagem ou correção alterada pode ser o bug, e ignore qualquer caso com fixtureErrors até que sua fixture compile. Para um PR que adiciona um fixador, a saída de correção e sugestão é a principal coisa a ser lida, então defina expectedOutput nesses casos. Se o PR adicionar uma opção, defina baseOptions para que o esquema da versão base aceite o caso. Sem isso, o caso é julgado apenas na cabeça.

Para uma nova regra, importe-a como head e base, para que o harness relate ok ou ERRADO (WRONG) em vez de comparar versões. Se o harness não se encaixar no plugin, use um arquivo de teste temporário no harness de teste do próprio repositório.

Escrever casos adversários. Escolha as categorias de references/test-cases.md que se encaixam na sintaxe e nos tipos que esta regra toca, e escreva casos literais. Decida o comportamento correto antes de executar cada caso, porque isso impede você de racionalizar o que quer que retorne. Imprima também os dados da mensagem, bem como as contagens de relatórios, já que um nome de tipo errado em uma mensagem também é um bug. Emparelhe um caso em sintaxe nova com um controle em sintaxe antiga, como uma chave de símbolo com o mesmo caso usando uma chave de string. Procure por:

  • Travamentos
  • Falsos positivos, onde código válido é reportado
  • Falsos negativos, onde código inválido não é reportado
  • Correções que produzem código inválido, mudam comportamento ou removem comentários
  • Intervalos de relatório que são mais largos do que o código ofensor

Mantenha os casos que expuseram algo para que possam ir na revisão como casos de teste literais. Literal é importante: este mantenedor pede casos escritos à mão e rejeita .map, fábricas e testes gerados.

Provar grandes sugestões. Se você acha que um redesign removeria vários bugs, faça um protótipo e execute os testes existentes. "267 de 268 testes passam, e aqui está o porquê do outro falhar" é muito mais útil do que uma suposição.

Limpar. Execute git status e remova cada arquivo temporário antes de prosseguir, para que o repositório volte ao estado em que você o encontrou.

5. Filtrar as descobertas

Antes de escrever qualquer coisa, passe por cada descoberta:

  • Bugs: inclua o caso e o que realmente aconteceu. Se você não conseguiu reproduzi-lo, corte-o, ou rebaixe-o para uma [Pergunta] se você ainda tiver um motivo específico para suspeitar dele.
  • Ordem: regressões vêm primeiro, depois bugs em código novo, depois bugs existentes que o PR toca.
  • Uma causa raiz: se um redesign consertaria vários bugs, faça um comentário e liste os casos nele. Mantenha um comentário separado apenas onde um bug precisa de sua própria correção de qualquer maneira, como uma regressão.
  • Posições contestadas: trate-as como perguntas não bloqueantes: verificações in em nós, uso de esquery, forma do esquema de opções e estilo import ts. Outros mantenedores discordaram razoavelmente sobre eles.
  • Ampliar ou adiar: se uma lacuna é o mesmo conceito que a regra e usuários reais a encontrariam, peça-a neste PR. Caso contrário, sugira uma issue de acompanhamento.
  • Adicionar ou remover uma opção: peça uma opção apenas onde a regra de outra forma baniria código válido, ou onde um usuário real pediu uma.
  • Código existente: deixe de fora problemas que o PR não tocou, a menos que sejam sérios, e marque-os como [Não Acionável].
  • Duplicatas: mescle repetições em um comentário que diga "aqui e em outros lugares".

Ruído custa mais do que uma omissão: um autor que passa por cima de três comentários fracos também passará por cima do real. Comentários bloqueantes devem ser apenas o que deve mudar antes do merge. Mantenha no máximo cerca de oito comentários não bloqueantes, escolhendo aqueles que mais melhoram o código, com uma sugestão pronta para aplicar sempre que o comentário solicitar uma mudança. Corte estes primeiro:

  • Questões de gosto sem ganho real em clareza, como reformular uma mensagem ou colapsar um condicional que está bom
  • Qualquer coisa que a descrição diga ser deliberada, como scaffolding para trabalho planejado
  • Bugs que você tentou e não conseguiu encontrar um caso real para eles, sem nenhuma razão específica restante para suspeitar
  • Espaços em branco e estilo de aspas
  • Solicitações de processo que não acrescentam nada, como uma issue de rastreamento para cada pequeno TODO

Nada a relatar é um resultado perfeitamente aceitável, então não invente descobertas para parecer minucioso.

Combine o veredito com os comentários bloqueantes. Se nada bloquear, aprove e deixe o resto como sugestões. Muitas revisões deste mantenedor em PRs sólidos são uma aprovação calorosa com uma ou duas pequenas solicitações.

6. Escrever a revisão

Leia references/review-voice.md, então escreva lint-rule-review-skill-<pr-ou-regra>.md no diretório atual, sem fazer commit. Mantenha o corpo da revisão em algumas frases, indo mais longe apenas para responder às perguntas do autor ou explicar uma decisão de design. Use esta estrutura:

# Revisão de <PR ou regra>

**Veredito:** aprovar | solicitar alterações | apenas alto nível

<Corpo da revisão, seguindo a ordem em review-voice.md>

## Comentários inline

### `path/to/file.ts:42` · bloqueante

[Bug] <Comentário como seria postado>

```ts
<Caso literal de falha ou sugestão>

Evidência: <O que você executou e o que aconteceu, ou "não reproduzido">

Não verificado

<Qualquer coisa que você não conseguiu executar ou verificar, e por que>


Marque cada comentário como `bloqueante` ou `não bloqueante`, ordenados bloqueantes primeiro. "Evidência" é para o usuário e não seria postada no GitHub; é a base para sua confiança na descoberta.
Se o bug for reproduzível, escreva o caso exato que falha.

## 7. Auto-verificação

Depois de escrever, verifique:

- **Nada enviado:** você verificou que nenhum arquivo foi adicionado ou alterado além do arquivo de revisão e dos arquivos temporários limpos na etapa 4?
  `git status` mostrará aqueles.
- **Nenhum trabalho residual:** o repositório está de volta ao estado do commit head do PR, sem patches aplicados, mutantes ou versões base?
- **Arquivo de revisão no diretório de trabalho:** a revisão foi salva no diretório de trabalho atual, não em algum lugar de difícil acesso?
- **Referências não deixadas para trás:** você removeu todas as referências a caminhos do sistema que não seriam válidos para o autor?

Habilidades Relacionadas