O que Caçador de Bugs faz?
Uma afirmação sem um teste que falhe é um palpite. Tudo que esta skill relata é provado por um teste observado como vermelho antes da correção e verde depois; tudo o que não consegue provar é descartado. Essa é a ideia central, e a razão pela qual sua saída vale a pena ser lida.
Ela edita a árvore de trabalho, adiciona arquivos de teste e, por padrão, faz commit.
- Como realizar cada passo — reference.md. Leia antes dos Passos 4–7, antes de escrever um relatório e antes de fazer commit.
- Teste de mutação, Passo 3 ao Passo 9 — mutation.md. Leia antes de começar qualquer mutante.
O contrato
- Todo bug corrigido tem um teste de regressão que foi observado vermelho no código não corrigido e verde após a correção.
- Todo candidato que não pode ser levado ao vermelho, ou que uma segunda opinião refuta, é descartado — e seu teste é excluído, nunca deixado falhando.
- Qualquer coisa real, mas fora do escopo ou não testável, é relatada, não corrigida.
- A suíte de testes completa termina não pior do que começou.
Lista de verificação do fluxo de trabalho
- [ ] Passo 0: Delimitar a mudança — apenas o diff staged
- [ ] Passo 1: Triagem — este commit vale a pena ser revisado?
- [ ] Passo 2: Linha de base — executar a suíte antes de tocar em qualquer coisa
- [ ] Passo 3: Encontrar candidatos (modelo forte, alcançabilidade obrigatória); subagentes de mutação ao lado onde as funções alteradas têm testes
- [ ] Passo 4: Provar — escrever o teste, executá-lo, exigir um vermelho correspondente
- [ ] Passo 5: Refutar — uma segunda opinião tenta matar cada bug provado, e verifica cada teste sobrevivente e alegação de código morto
- [ ] Passo 6: Corrigir (pergunta de prevenção, confinado ao escopo)
- [ ] Passo 7: Verificar — novos testes verdes; a suíte completa uma vez, antes do Passo 9
- [ ] Passo 8: Iterar — repetir, até 3 vezes, sem perguntar; nunca uma 4ª
- [ ] Passo 9: Relatar uma vez no final; perguntar ao usuário cada decisão em aberto (seletor — escrito não é perguntado); então fazer commit (com o trailer da prosa quando a prosa estiver instalada) ou deixar para revisão — ou, sob "o chamador faz commit", terminar com o bloco de `scripts/caller-result.sh`
Nunca execute isso de dentro de um hook pre-commit do git. Ele escreve arquivos, adiciona
testes e faz commit — tudo isso conflita com o bloqueio do índice do git. Ele é executado antes
do commit ser criado, e o commit acontece no Passo 9.
Um hook complementar observa commits que nunca passaram por aqui: após cada
comando, ele pergunta ao git se HEAD se moveu e se o novo commit carrega um
trailer Bug-hunter:. Portanto, o trailer é o único marcador que importa — nenhuma
variável de ambiente, nada para lembrar, e o registro permanece no próprio commit
onde git log pode auditá-lo.
O hook também faz uma segunda pergunta sobre qualquer trailer que não seja uma nota de
pulo — 0 bugs encontrados e abortado ... incluídos, não apenas os que relatam uma
correção: um trailer Bug-hunter-Tree corresponde à árvore que realmente foi enviada? Esse
vínculo é o que scripts/mint-trailer.sh produz
quando executado contra a árvore staged real, imediatamente antes do commit — veja
Passo 9 para como. Um trailer Bug-hunter: pode ser um trailer git real com exatamente a
redação correta e ainda ser uma frase lembrada de ter lido este arquivo,
em vez de uma produzida por executar qualquer parte dele — essa é a forma
que a verificação de presença de string não consegue capturar, e para a qual esse vínculo serve.
Um commit que chega sem um trailer Bug-hunter:, ou com um cujo
vínculo Bug-hunter-Tree não corresponde, é nomeado em um relatório, com o
repositório em que está. O relatório o envia para a seção abaixo e não dá
comando para corrigir o commit: o hook não pode ver onde você está, e o
commit que ele nomeia geralmente não é seu HEAD.
Se você é um agente prestes a fazer commit
Se outra skill faz seus commits e executa esta skill antes de cada um deles, deixe essa skill começar com "fazer commit disso"; ainda execute para "verificar bugs disso". Se esta rodada já declarou um assunto de commit, use esse assunto inalterado. Apenas adicione trailers.
Cada commit que você cria passa por esta skill e carrega um trailer Bug-hunter:. Não quando solicitado pelo nome — toda vez. Um commit com código recebe a caçada. Um commit com apenas docs, especificações, testes ou formatação pula a caçada, não a skill. "Fazer commit disso", "fazer commit das minhas alterações", "finalizar e fazer commit", ou sua própria decisão de fazer commit após terminar uma tarefa, todos significam: staged a mudança, execute esta skill, então faça o commit. A triagem (Passo 1) é o que decide se um dado commit vale a pena ser revisado, então executá-lo sempre é barato quando não se aplica.
Execute você mesmo, em sua própria sessão. O agente que escreveu a mudança executa esta skill. Não entregue a execução completa a um subagente que então inicia localizadores, refutadores e agentes de mutação por conta própria: a execução precisa de um orquestrador que permaneça vivo para coletar sobreviventes e retomar agentes, e um delegado aninhado continua terminando sua vez enquanto seus filhos são executados. Delegar as passagens individuais, como os passos dizem, é como deve ser executado.
Não evite esta skill
Um cabeçalho, não cinco regras, porque um agente procurando uma saída para uma verificação encontra de forma confiável a costura entre regras declaradas separadamente. Cada linha aqui foi adicionada depois que um agente contornou a regra que ela fecha.
1. Diga qual você está fazendo, em voz alta, toda vez. Uma linha na resposta
que o usuário pode ver: "executando bug-hunter em N arquivos", ou "pulando bug-hunter
— ". Não em seu raciocínio — na resposta. Pular sem dizer nada
parece exatamente como executá-lo e não encontrar nada. Um pulo declarado pode
ser anulado em quatro palavras; um não declarado é uma decisão que você tomou por eles. Se
você pular, o commit também carrega o trailer — commit-with-trailer.sh -F msg.txt "pulado — <motivo>", como no Passo 9. Ambos, não um ou outro.
Sob o chamador faz commit, o pulo vai para o script de resultado
em vez disso (Quando o chamador faz commit).
2. Nunca peça permissão para executá-lo. O gatilho é uma propriedade do código, não um momento: se código foi escrito desde a última passagem que voltou limpa, uma passagem é devida. Antes de um commit, entre iterações, após uma correção que o usuário pediu, após um refatoramento, após um commit que já foi enviado — não são casos separados, todos são "código foi escrito". Uma lista de momentos convida a procurar o momento que não está na lista.
3. Anunciar só conta se você já começou. "Isso será executado a seguir, a menos que você queira parar por aqui" · "Vou iniciar isso se você estiver satisfeito" · "as correções precisam de sua própria passagem — quer que eu execute?" Cada um termina a vez com a verificação não sendo executada, o que devolve a decisão tão claramente quanto perguntar faria. Se você está descrevendo uma execução no tempo futuro, você não a iniciou, e esse é o bug.
4. As iterações são executadas consecutivamente, e o relatório é devido. Até três, sem check-in entre elas, e sem relatório intermediário — um relatório entre iterações convida a parar cedo e faz uma execução inacabada parecer concluída. Veja os Passos 8 e 9.
Três é o orçamento, não uma oferta inicial. Não há quarta iteração. "quer que eu execute mais uma passagem?" · "as correções da iteração 3 nunca foram revisadas — devo fazer uma 4ª?" Ambas devolvem uma decisão que o orçamento já havia tomado, no momento em que o usuário tem mais probabilidade de dizer não. Uma execução que atinge o limite termina no relatório de causas raiz (Passo 9) e uma escolha por causa, onde a primeira escolha é uma nova execução na iteração 1 focada nessa causa. Isso não é a regra 2 suspensa: uma passagem sobre as correções da iteração 3 é realmente devida, e ainda é devida — o que acabou foi o orçamento para incluí-la dentro desta execução, e é por isso que ela se torna uma nova execução e por que qual causa a recebe é a decisão do usuário. Nem é a regra 3 invertida: dentro do orçamento, uma passagem é devida e você a inicia sem perguntar; no limite, a execução terminou, e o que resta é uma decisão, oferecida como opções em vez de como uma pergunta em aberto.
5. Estes não são motivos. Cada um já foi usado, por um modelo capaz, para pular esta skill em um commit que então enviou um bug:
- a mudança é pequena — alterações de uma linha estão erradas o tempo todo
- estou confiante neste código — assim estava todo autor de todo bug que isso já encontrou
- o usuário está esperando / estamos nos movendo rápido — esse é o momento em que a qualidade é trocada, que é o momento para o qual isso existe
- a sessão é longa e isso é caro — uma execução que não encontra nada é barata, a triagem para a maioria dos commits antes da parte cara, e as passagens longas são executadas em segundo plano de qualquer maneira (Passo 3)
- eu já executei em código relacionado antes — você não executou nisso
- isso é a própria mecânica da skill, não código real — é código real, e os piores bugs na própria história desta skill estavam exatamente nessa mecânica
- o usuário está claramente observando e objetaria se se importasse — eles estão observando a saída, não a ausência dela
Criar bugs e seguir em frente porque verificar era inconveniente é o comportamento específico que esta skill existe para parar. Fazer isso com esta skill não é ironia, é apenas o bug.
De quem é a decisão sobre o custo. Uma execução completa leva minutos; uma ruim leva meia hora. Quem instalou isso já pesou um commit mais lento contra um bug atingindo o main. Um agente que silenciosamente decide que a verificação é muito lenta hoje não fez um julgamento de engenharia — ele substituiu essa decisão em nome de alguém que não está na sala, na direção que acaba sendo menos trabalho. Se o custo realmente importa agora, diga em uma frase e deixe que eles escolham.
De quem é a decisão
Duas listas curtas, porque ambas as falhas vivem no limite entre elas: perguntar sobre a primeira treina o usuário a passar os olhos, e decidir a segunda por eles é a escolha 3 feita silenciosamente.
Sua, nunca perguntada. Se executar e quando; se um candidato é provado, refutado ou descartado; como corrigir um bug provado dentro da mudança; se iterar, até o limite; executar a suíte; fazer commit de uma execução que terminou limpa com nada em aberto — exceto sob o chamador faz commit, onde o commit é do chamador.
Do usuário, sempre perguntada. Sobre o que agir: cada causa raiz e cada recomendação (corrigir agora / anotar / pular), cada entrada não resolvida de um aborto, se um commit prossegue quando algo relatado-não-corrigido muda o que ele significa (modo apenas relatório), e a parada do Passo 0 — qual das edições divergentes staged e não staged de um arquivo manter.
Quando você perguntar, use o seletor interativo do host (no Claude Code, a
ferramenta AskUserQuestion): qualquer pergunta com
opções discretas passa por ele, uma pergunta por decisão, em ordem de gravidade,
nunca enterrada em prosa no final de um relatório longo. Texto simples é o fallback
para hosts sem um seletor, não o padrão. O seletor também é a única coisa aqui
que é estrutural em vez de consultiva — uma rodada com um seletor aberto não pode
terminar até que o usuário responda — e é por isso que a próxima regra importa.
Perguntado significa que o usuário viu. Uma pergunta é feita quando está em uma resposta que o usuário lê ou um seletor ao qual ele responde — não quando um agente a anotou. Se esta skill é executada em um agente que relata para outro agente, seu relatório do Passo 9 e suas perguntas alcançam aquele agente, e nada foi perguntado ainda: o salto move o seletor, não descarrega a pergunta. Então:
- Se um agente que você gerou executou isso em sua própria mudança, seu relatório é sua entrada do Passo 9, não sua saída do Passo 9. Cada decisão em aberto nesse relatório vai para o usuário em sua próxima resposta, antes de qualquer outra coisa — através do seu seletor, uma pergunta por decisão, ou o bloco numerado do relatório literal onde não há nenhum. "A execução abortou" ou "encontrou três causas raiz" sem opções abaixo é relatar sobre o relatório em vez de entregá-lo; se você está escrevendo essa frase, esse é o bug. Reter a decisão durante uma rodada enquanto outro trabalho termina é a escolha 3, feita por eles — o outro trabalho espera, ou a resposta carrega ambos.
- Se você está executando isso em um agente que relata para outro agente, você não tem seletor que alcance o usuário. Imprima o relatório inteiro em seu formato — não um resumo dele — com o rodapé de passagem (reference.md) que diz a quem o recebe o que ainda é deles para perguntar. Diga claramente quais decisões estão em aberto e que você não pôde perguntá-las. Sob o chamador faz commit, o bloco de resultado substitui a lista de decisões do rodapé (Quando o chamador faz commit).
Uma execução não terminou até que suas perguntas estejam na frente do usuário, não importa qual agente as leva até lá.
Passo 0 — Delimitação
A mudança sob revisão é o diff staged:
git diff --cached --stat
git diff --cached
Leia o arquivo inteiro para cada arquivo alterado, não apenas os hunks — um bug está geralmente na interação entre o novo código e o código ao redor.
Se algum arquivo aparecer tanto no diff staged quanto no unstaged, pare. Você
estaria raciocinando sobre o índice enquanto testa a árvore de trabalho, e eles
discordam. Diga ao usuário quais arquivos divergem e peça a eles para fazer staged ou reverter
essas edições. Nunca git stash para contornar isso — o usuário tem
trabalho não commitado e esta skill está prestes a escrever arquivos por cima dele.
Alterações não staged em outros arquivos são normais. Anote-as no relatório.
Não caçe bugs em especificações, documentação ou testes existentes. As alterações nesses arquivos ainda são contexto que vale a pena ler.
Passo 1 — Triagem
A triagem decide pelo diff, não pela mensagem de commit. Para um diff de
até cerca de 300 linhas alteradas, faça a triagem você mesmo, no loop em que
você já está: um subagente custa mais para iniciar do que ler um diff desse tamanho.
Delegue um diff maior para uma única passagem rápida em um modelo pequeno e barato. De
qualquer forma, a passagem recebe a lista de arquivos, o diff e se o usuário pediu por um
ponto de verificação (abaixo). Peça por um de REVIEW ou
SKIP mais um motivo de uma linha. Não peça por uma mensagem de commit primeiro, e não
leia um prefixo de assunto como um sinal — esta skill não impõe convenção de
commit (reference.md).
SKIP quando o diff mostra:
- Nada fora de docs, especificações, testes, lockfiles, gerados...