Claude Code para falhas de CI: peça que cite a saída com falha, sugira a menor correção e adicione um teste de regressão para evitar repetições.

Uma falha de CI geralmente não é misteriosa. O log diz onde parou, qual comando falhou e a mensagem de erro. Uma execução boa inclui um stack trace, um erro de compilador com arquivo e número de linha, ou um relatório de teste mostrando qual asserção falhou. Às vezes você ainda tem uma pista em estilo diff como "expected X, got Y" ou um passo claramente falho como "lint", "build" ou "migrate database".
O problema real é que pessoas (e IAs) muitas vezes tratam o log como ruído de fundo. Se você colar um log longo e pedir "uma correção", muitos modelos pulam para uma explicação familiar em vez de ler as últimas linhas significativas. O chute piora quando o erro parece comum ("module not found", "timeout", "permission denied"). Você acaba com uma grande reescrita, uma nova dependência ou um conselho do tipo "tente atualizar tudo" que não corresponde à falha real.
O objetivo não é "fazer passar de qualquer jeito". É mais simples:
Na prática, a "menor correção" costuma ser uma destas: uma alteração de algumas linhas em um só lugar, um import faltando ou caminho errado, um valor de configuração claramente errado para o ambiente de CI, ou reverter uma mudança acidentalmente quebrada em vez de redesenhar o código.
Um teste de acompanhamento importa também. Passar no CI uma vez não é o mesmo que prevenir repetições. Se a falha veio de um caso de borda (input nulo, timezone, arredondamento, permissões), adicione um teste de regressão que falha antes da correção e passa depois. Isso transforma um resgate pontual em uma guarda.
A maioria das más correções começa com contexto faltando. Se você só colar a última linha vermelha, o modelo tem que adivinhar o que aconteceu antes, e essas suposições frequentemente viram reescritas.
Tente fornecer detalhe suficiente para que alguém consiga seguir a falha desde o primeiro erro real até o fim, e então mudar o mínimo possível.
Copie isto na sua mensagem (verbatim quando puder):
go test ./..., npm test, flutter test, golangci-lint run).Adicione restrições em palavras simples. Se você quer uma correção mínima, diga isso: sem refatores, sem mudanças de comportamento a menos que necessário, mantenha o patch limitado à área com falha.
Um exemplo simples: CI falha na etapa de lint após um bump de dependência. Cole a saída do linter começando pelo primeiro aviso, inclua o comando que o CI usou e mencione a única alteração de versão do pacote. Isso é suficiente para sugerir um ajuste de config de uma linha ou uma pequena mudança no código, em vez de reformatar metade do repositório.
Se quiser algo copiable, esta estrutura costuma ser suficiente:
CI command:
Failing output (full):
Recent changes:
Constraints (smallest fix, no refactor):
Flaky? (runs attached):
Quando um modelo erra numa quebra de CI, geralmente é porque seu prompt permite que ele chute. Seu trabalho é fazê-lo mostrar o raciocínio usando a saída com falha exata, e então se comprometer com a menor mudança que pode fazer a tarefa passar.
Exija evidência e um plano mínimo. Um bom prompt força cinco coisas:
Incerteza é OK. Incerteza escondida é o que faz perder tempo.
Cole isto no topo da sua pergunta sobre CI:
Use ONLY the evidence in the CI output below.
1) Quote the exact failing lines you are using.
2) Give ONE sentence: the most likely cause.
3) Propose the smallest fix: 1-3 edits, with file paths.
4) Do NOT do formatting/renames/refactors or "cleanup".
5) List uncertainties + the one extra detail that would confirm the diagnosis.
Se o log diz "expected 200, got 500" mais um stack trace em user_service.go:142, essa estrutura empurra a resposta para aquela função e uma pequena cláusula de proteção ou tratamento de erro, não um redesenho do endpoint.
As vitórias mais rápidas vêm de um prompt que força a citação dos logs, permanece dentro das restrições e para quando falta algo.
You are helping me fix a CI failure.
Repo context (short):
- Language/framework:
- Test/build command that failed: <PASTE THE EXACT COMMAND>
- CI environment (OS, Node/Go/Python versions, etc.):
Failing output (verbatim, include the first error and 20 lines above it):
<PASTE LOG>
Constraints:
- Propose the smallest possible code change that makes CI pass.
- Do NOT rewrite/refactor unrelated code.
- Do NOT touch files you do not need for the fix.
- If behavior changes, make it explicit and justify why it is correct.
Stop rule (no guessing):
- If the log is incomplete or you need more info (missing stack trace, config, versions, failing test name), STOP and ask only the minimum questions needed.
Your response format (follow exactly):
1) Evidence: Quote the exact log lines that matter.
2) Hypothesis: Explain the most likely cause in 2-4 sentences.
3) Smallest fix: Describe the minimal change and why it addresses the evidence.
4) Patch: Provide a unified diff.
5) Follow-up: Tell me the exact command(s) to rerun locally to confirm.
Then, write ONE regression test (or tweak an existing one) that would fail before this fix and pass after it, to prevent the same failure class.
- Keep the test focused. No broad test suites.
- If a test is not feasible, explain why and propose the next-best guardrail (lint rule, type check, assertion).
Duas informações que reduzem idas e vindas:
A forma mais rápida de perder tempo é aceitar um conjunto de mudanças de “limpeza” que modifica cinco coisas de uma vez. Defina "mínimo" desde o início: o menor diff que faz a tarefa com falha passar, com menor risco e verificação mais rápida.
Uma regra simples funciona bem: corrija o sintoma primeiro, depois decida se um refactor maior vale a pena. Se o log aponta para um arquivo, uma função, um import faltando ou um caso de borda, foque ali. Evite edições do tipo "já que estamos aqui".
Se realmente precisar de alternativas, peça duas e só duas: "correção mínima mais segura" vs "correção mínima mais rápida." Você quer trade-offs, não um menu.
Também exija verificação local que combine com o CI. Peça o mesmo comando que o pipeline roda (ou o equivalente mais próximo), para confirmar em minutos:
# run the same unit test target CI runs
make test
# or the exact script used in CI
npm test
Se a resposta sugerir uma grande mudança, rebata com: "Mostre o menor patch que corrige a asserção com falha, sem formatação ou renomes não relacionados."
Uma correção sem teste é uma aposta de que o problema não vai voltar. Peça sempre um teste de regressão que falha antes do patch e passa depois.
Seja específico sobre o que é um "bom" teste:
Um padrão útil é exigir quatro coisas: onde colocar o teste, como nomeá-lo, qual comportamento cobre e uma nota curta explicando por que impede regressões.
Trecho pronto para colar:
Exemplo: CI mostra um panic quando um handler de API recebe uma ID vazia. Não peça "um teste para esta linha". Peça um teste que cubra IDs inválidos (vazio, espaços, formato errado). A menor correção pode ser uma cláusula de guarda que retorna 400. O teste de acompanhamento deve afirmar comportamento para múltiplos inputs inválidos, então se alguém refatorar o parsing, o CI falha rápido.
Se seu projeto já tem convenções de teste, explique-as. Se não, peça que o novo teste espelhe testes próximos no mesmo pacote/pasta e mantenha-o minimal e legível.
Cole a seção do log de CI com o erro e 20–40 linhas acima. Também cole o comando exato que falhou e detalhes de ambiente importantes (SO, versões do runtime, flags relevantes).
Depois peça para ele reformular o que falhou em linguagem simples e apontar as linhas do output que provam isso. Se não conseguir citar o log, não leu de fato.
Peça a menor mudança de código possível que faça o comando falho passar. Repele refatores. Antes de aplicar, peça que liste:
Aplique o patch e rode o comando falho localmente (ou no mesmo job de CI se for sua única opção). Se ainda falhar, cole só a nova saída e repita. Manter contexto pequeno mantém a resposta focada.
Quando estiver verde, adicione um teste de acompanhamento que falharia antes do patch e agora passa. Mantenha-o direcionado: um teste, um motivo.
Rode o comando novamente com o novo teste incluído para confirmar que você não só silenciou o erro.
Peça uma mensagem de commit curta e uma descrição de PR que inclua o que falhou, o que mudou, como você verificou e qual teste previne a repetição. Revisores andam mais rápido quando a justificativa está explícita.
Uma falha comum: tudo funcionava localmente, então uma pequena mudança faz os testes quebrarem no runner de CI. Aqui vai um simples exemplo em Go onde um handler começou a aceitar um valor só com data (2026-01-09) mas o código ainda tentava parsear apenas timestamps RFC3339.
Este é o tipo de trecho para colar (mantenha curto, mas inclua a linha de erro):
--- FAIL: TestCreateInvoice_DueDate (0.01s)
invoice_test.go:48: expected 201, got 400
invoice_test.go:49: response: {"error":"invalid due_date: parsing time \"2026-01-09\" as \"2006-01-02T15:04:05Z07:00\": cannot parse \"\" as \"T\""}
FAIL
exit status 1
FAIL app/api 0.243s
Agora use um prompt que force evidências, correção mínima e um teste:
You are fixing a CI failure. You MUST use the log to justify every claim.
Context:
- Language: Go
- Failing test: TestCreateInvoice_DueDate
- Log snippet:
<PASTE LOG>
Task:
1) Quote the exact failing line(s) from the log and explain the root cause in 1-2 sentences.
2) Propose the smallest possible code change (one function, one file) to accept both RFC3339 and YYYY-MM-DD.
3) Show the exact patch.
4) Add one regression test that fails before the fix and passes after.
Return your answer with headings: Evidence, Minimal Fix, Patch, Regression Test.
Uma boa resposta apontará para o desencontro de formatos de parsing, então fará uma pequena alteração em uma função (por exemplo, parseDueDate em invoice.go) para tentar RFC3339 primeiro e cair para 2006-01-02. Sem refactor, sem novos pacotes.
O teste de regressão é a guarda: envie due_date: "2026-01-09" e espere 201. Se alguém depois "limpar" o parser e remover o fallback, o CI falhará imediatamente com a mesma classe de erro.
A forma mais rápida de perder uma hora é dar uma visão cortada do problema. Logs de CI são barulhentos, mas a parte útil costuma estar ~20 linhas acima do erro final.
Uma armadilha é colar só a última linha vermelha (por exemplo, "exit 1") escondendo a causa real anterior (uma variável de ambiente faltando, um snapshot quebrado, ou o primeiro teste que crashou). Solução: inclua o comando de falha e a janela do log onde o primeiro erro real aparece.
Outro desperdício é deixar o modelo "arrumar" no meio do caminho. Formatação extra, bumps de dependência ou refactors tornam a revisão mais difícil e aumentam o risco de quebrar algo. Solução: trave o escopo para a menor mudança possível e rejeite tudo que seja não relacionado.
Padrões a observar:
Se suspeitar de flakiness, não oculte com retries. Remova a aleatoriedade (tempo fixo, RNG sementeado, diretórios temporários isolados) para deixar o sinal claro.
Antes de enviar, faça uma checagem curta. O objetivo é garantir que a mudança é real, mínima e repetível, não um passe de sorte.
Por fim, rode um conjunto um pouco maior que o job que falhou (por exemplo, lint + unit tests). Um erro comum é uma correção que passa no job original, mas quebra outro target.
Se quiser que isso economize tempo semana após semana, trate seu prompt e o formato de resposta como processo de time. O objetivo é entradas repetíveis, saídas repetíveis e menos "correções misteriosas" que quebram outra coisa.
Transforme seu melhor prompt em um snippet compartilhado e fixe no chat da equipe. Quando todos usam o mesmo formato, as revisões ficam mais rápidas porque os revisores sabem onde olhar.
Um ciclo leve que funciona na maioria dos times:
Se preferir um fluxo centrado em chat para construir e iterar, você pode rodar o mesmo loop de conserto e teste dentro do Koder.ai, usar instantâneos enquanto experimenta e exportar o código quando estiver pronto para dar merge de volta ao repo.
Comece pelo primeiro erro real, não pelo exit 1 final.
Peça que prove ter lido o log.
Use uma restrição como:
Padronize para o menor patch que faz a etapa com falha passar.
Normalmente isso significa:
Evite “limpeza” até o CI estar verde novamente.
Cole contexto suficiente para recriar a falha, não apenas a última linha vermelha.
Inclua:
Sim — deixe isso explícito em palavras simples e repita as restrições.
Exemplo de restrições:
Isso mantém a resposta focada e revisável.
Conserte primeiro a primeira falha real.
Em dúvida, peça ao modelo para identificar o primeiro passo que falhou no log e foque nele.
Trate flakiness como um sinal para remover aleatoriedade, não para adicionar retries.
Estabilizadores comuns:
Quando ficar determinístico, a “correção mínima” fica óbvia.
Peça o comando exato que o CI rodou e execute localmente.
Se a reprodução local for difícil, peça um repro mínimo dentro do repositório (um único teste/target) que dispare o mesmo erro.
Escreva um teste de regressão focado que falha antes da correção e passa depois.
Bons alvos incluem:
Se for falha de lint/build, o “teste” equivalente pode ser apertar uma regra de lint ou adicionar uma checagem que evita o mesmo erro.
Use snapshots/rollback para manter experimentos reversíveis.
Um loop prático:
Se usar Koder.ai, instantâneos ajudam a iterar sem misturar experimentos no patch final que será exportado.
go test ./...npm testflutter test