Mantendo Especificações, Testes e Código Sincronizados no Desenvolvimento de IA
Evite que agentes de IA se desviem das especificações, testes e código.
Agentes de codificação com IA entregam funcionalidades rapidamente, mas especificações, testes e código se afastam silenciosamente uns dos outros. Este guia aborda um modelo de rastreabilidade, mapeamento de especificação para teste e de especificação para código, e as verificações de CI que detectam esse desvio antes de um merge.
Uma especificação que ninguém revalida contra o sistema em execução é pior do que não ter especificação alguma, porque cria uma falsa confiança. Os revisores confiam no documento em vez do diff, e um agente de IA instruído a “seguir o padrão existente” seguirá alegremente o que o código realmente faz, mesmo quando isso contradiz o requisito que deveria satisfazer.
A solução não é mais documentação. É um pequeno vínculo executável entre quatro coisas que já existem na maioria dos repositórios: o requisito, a decisão de design por trás dele, os testes que o provam e os commits ou pull requests que o alteraram.

Uma vez que esse vínculo existe como dados e não como um entendimento compartilhado, você pode consultá-lo. Você pode perguntar quais requisitos não têm cobertura de teste, quais testes não mapeiam mais para nenhum requisito e quais arquivos foram alterados em um pull request sem um ID de requisito correspondente. Essa consulta é o entregável real deste artigo, e o restante do post explica como construí-lo com ferramentas que você provavelmente já usa.
O Problema do Desvio: Por que Especificações, Testes e Código Saem de Sincronia
O desvio aparece em quatro formas reconhecíveis, e equipes assistidas por IA tendem a encontrar as quatro mais rapidamente do que equipes que escrevem cada linha manualmente.
- A especificação muda, o código não. Um requisito é esclarecido em uma conversa de acompanhamento ou em um thread de comentários, mas ninguém regenera ou edita a implementação para corresponder.
- O código muda, a especificação não. Um agente ou um desenvolvedor corrige um bug ou refatora um módulo, e a especificação continua descrevendo o comportamento antigo como se ainda fosse atual.
- Testes cobrem a implementação, não a intenção. Testes unitários afirmam o que o código currently faz, o que é circular: eles passam por construção mesmo quando o código satisfaz o requisito errado.
- Pull requests não referenciam requisitos. Revisores aprovam um diff baseado na força de “parece razoável” porque não há uma reivindicação explícita para verificar contra.
Pesquisas recentes de processos em frameworks de desenvolvimento com IA identificam o desvio de especificação como um risco recorrente precisamente porque os agentes regeneram código rapidamente e repetidamente, e cada regeneração é uma nova oportunidade para que a especificação e a implementação diverjam um pouco mais. O debate sobre Desenvolvimento Dirigido por Especificação vs Vibe Coding é realmente um argumento sobre esse mesmo modo de falha: uma especificação que ninguém aplica degenera no mesmo desvio que você teria sem uma, apenas com cerimônia extra.
Workflows modernos no estilo spec-kit cada vez mais enquadram isso como degradação de especificação: a especificação continua parecendo autoritativa enquanto perde silenciosamente sua conexão com o que o sistema realmente faz. A definição central do desenvolvimento dirigido por especificação trata a especificação como a fonte da verdade, mas uma fonte de verdade só permanece verdadeira se algo continuar verificando-a contra a realidade.
Um Modelo de Rastreabilidade para Desenvolvimento Assistido por IA
Um modelo de rastreabilidade funcional precisa de seis identificadores que conectem um requisito de negócio até as linhas de código e o pull request que o implementou. A maioria das equipes já tem três ou quatro desses; os faltantes geralmente são o ID da decisão de design e o vínculo explícito de volta dos testes e commits.
| Identificador | Localizado em | Exemplo |
|---|---|---|
| ID de Requisito | requirements.md ou ferramenta de especificação |
REQ-014 |
| ID de Decisão de Design | ADR / registro de decisão | ADR-0032 |
| ID de Tarefa | divisão de tarefas ou rastreador de issues | TASK-014-3 |
| ID de Teste | arquivo de teste ou nome do teste | test_req_014_password_reset |
| Link de Commit / PR | histórico do Git | PR #482 |
| Arquivos alterados | diff do Git | auth/reset.go, auth/reset_test.go |
Os relacionamentos entre esses identificadores formam um gráfico em vez de uma linha reta, porque um requisito pode gerar várias tarefas, e um pull request pode tocar em vários requisitos de uma vez.
REQ-014"] --> ADR["Decisão de Design
ADR-0032"] ADR --> TASK["Tarefa
TASK-014-3"] TASK --> CODE["Alteração de Código
auth/reset.go"] TASK --> TEST["Teste
test_req_014_password_reset"] CODE --> PR["Pull Request
#482"] TEST --> PR PR --> COMMIT["Histórico de Commits"]
Armazenar esse gráfico como dados estruturados, e não como prosa, é o que permite consultá-lo posteriormente. O ecossistema Spec Kit do GitHub moveu-se exatamente nessa direção: extensões como spec-kit-trace escaneiam tokens REQ-XXX embutidos em arquivos de especificação e arquivos de teste e geram uma matriz determinística a partir dessa correspondência literal de texto, evitando deliberadamente adivinhações baseadas em nomes fuzzy que produzem falsos positivos silenciosos.
Mapeamento de Especificação para Teste: Transformando Critérios de Aceitação em Casos de Teste
Cada critério de aceitação em uma especificação é, por construção, uma afirmação comportamental: dado este estado, quando o ator faz isto, então o sistema deve responder daquela maneira. Essa já é a forma de um caso de teste, é por isso que os fluxos de trabalho SDD mais fortes geram testes a partir dos mesmos critérios de aceitação que geram o código, em vez de pedir ao agente de geração de código que também invente seus próprios testes depois do fato.
Um formato amplamente utilizado para escrever esses critérios é o EARS (Easy Approach to Requirements Syntax), que força cada requisito em um padrão inequívoco e testável como “Quando <gatilho>, o sistema deve <resposta>.” Essa estrutura mapeia limpa em quatro categorias de teste que cada requisito deve carregar:
- Testes positivos — o caminho feliz que o requisito descreve explicitamente.
- Testes negativos — entradas ou estados que o requisito diz que devem ser rejeitados.
- Testes de limite — as bordas de faixas, limites e limiares mencionados nos critérios de aceitação.
- Testes de migração — comportamento para dados ou estados que antecedem o requisito, para que um registro antigo não contorne silenciosamente uma nova regra.
| Tipo de requisito | Categoria de teste a adicionar | Erro comum |
|---|---|---|
| “O sistema deve rejeitar X” | Negativo | Apenas o caminho de aceitação é testado |
| “O limite é N itens” | Limite | N-1, N e N+1 não estão todos cobertos |
| “Novo campo substitui campo antigo” | Migração | Registros antigos sem o novo campo causam falhas silenciosas |
| “Dentro de 60 segundos” | Limite + tempo | O teste afirma a lógica, não o orçamento de tempo real |
Testes unitários escritos dessa forma ainda importam como a camada rápida e barata da pirâmide; os padrões práticos para estruturá-los são cobertos no guia de testes unitários em Go e no guia de testes unitários em Python. O que a rastreabilidade adiciona por cima é um token de requisito literal e estável embutido no nome do teste ou em um comentário de teste, para que uma consulta posterior possa provar — não assumir — que REQ-014 tem cobertura.
Mapeamento de Especificação para Código: De Planos de Design a uma Tabela de Rastreabilidade
O mapeamento de especificação para teste prova comportamento; o mapeamento de especificação para código prova escopo. Ele responde a uma pergunta diferente: quais arquivos realmente deveriam mudar para este requisito, e o diff permaneceu dentro desse limite ou transbordou para módulos não relacionados?
Um plano de design que lista os arquivos afetados antecipadamente — mesmo uma lista rascunhada — dá algo para comparar com o pull request real posteriormente. Comentários no código devem referenciar um ID de requisito apenas quando fazê-lo adiciona informações que um revisor não pode obter da própria especificação; um comentário repetindo o texto do requisito verbatim é ruído, mas // impõe limite REQ-014: máx 5 tentativas de reset por hora ganha seu lugar porque o número é, caso contrário, invisível no diff.
Uma tabela de rastreabilidade gerada transforma isso em algo revisável em segundos em vez de algo que um revisor tem que reconstruir lendo ambos os documentos lado a lado:
| Requisito | Decisão de design | Arquivos alterados | Testes | Status |
|---|---|---|---|---|
| REQ-014 | ADR-0032 | auth/reset.go, auth/reset_test.go |
test_req_014_* (4) |
Coberto |
| REQ-015 | ADR-0032 | auth/reset.go |
nenhum | Lacuna |
| REQ-016 | — | auth/notify.go |
test_notify_basic |
Link de especificação órfã |
Essa única tabela revela dois dos padrões de falha mais comuns de relance: REQ-015 alterou código com zero testes correspondentes, e o teste anexado a REQ-016 não referencia realmente um ID de requisito, o que significa que ou a especificação está faltando ou o teste foi classificado incorretamente.
O Fluxo de Trabalho do Pull Request: Revisando Diffs de Especificação, Código e Teste Juntos
Um pull request construído em torno de rastreabilidade revisa três diffs lado a lado em vez de um: o que mudou na especificação, o que mudou no código e o que mudou nos testes. A pergunta de revisão deixa de ser “isso parece certo?” e torna-se muito mais específica: “qual requisito essa alteração satisfaz e as provas demonstram isso?”
Uma checklist de revisor curta e concreta funciona melhor aqui do que uma longa, porque os revisores pulam checklists longas sob pressão de prazo:
- A descrição do PR nomeia o(s) ID(s) de requisito que satisfaz?
- Todo arquivo alterado aparece na lista de arquivos afetados do plano de design, ou o escopo extra é explicado?
- Pelo menos um teste novo ou existente referencia cada ID de requisito tocado por este PR?
- Se a especificação mudou, o código e os testes mudaram no mesmo PR, ou há um acompanhamento rastreado?
Automatizando a Rastreabilidade no CI
A revisão manual detecta desvios apenas com a frequência com que os revisores lembram de procurá-los, é por isso que as verificações acima pertencem ao CI e não em uma página de wiki que ninguém relê. Os mesmos padrões do [cheat sheet de GitHub Actions](https://www.glukhov.org/pt/developer-tools/ci-cd/github-actions-cheatsheet/ “GitHub Actions Cheatsheet - Standard structure and a List of most useful actions”}) que você já usa para trabalhos de build e teste aplicam-se diretamente aqui — as verificações de rastreabilidade são apenas outro trabalho no mesmo pipeline.
Ideias práticas de automação, aproximadamente em ordem de esforço:
- Verificações de CI para arquivos de especificação — falhar o build se um arquivo de especificação foi editado sem uma alteração correspondente de código ou teste no mesmo PR, ou vice-versa.
- Exigir IDs de requisito nos títulos ou descrições dos PRs — uma verificação regex leve (
REQ-\d+) bloqueia merges que não nomeiam o que implementam. - Resumos de rastreabilidade gerados por agente — ter um agente produzindo um resumo curto de quais requisitos um PR toca, para um humano confirmar em vez de escrever do zero.
- Cobertura de teste por critério de aceitação, não apenas por linha — a cobertura de linha diz que o código foi executado; a cobertura de requisito diz que uma reivindicação foi verificada.
- Avisos de especificação obsoleta — sinalizar especificações que não foram tocadas em N commits tocando seus arquivos vinculados, já que especificações silenciosas por longo tempo são as mais propensas a ter se deteriorado silenciosamente.
Extensões construídas sobre o Spec Kit do GitHub já implementam mecanicamente várias dessas: uma escaneia tokens literais REQ-XXX através de arquivos de especificação e teste para construir uma matriz e sinalizar testes órfãos, e um pacote mais rigoroso orientado ao V-Model vai além, gerando uma especificação de teste pareada para cada especificação de desenvolvimento e produzindo múltiplas matrizes de rastreabilidade para equipes trabalhando sob frameworks regulatórios como IEC 62304 ou ISO 26262. Você não precisa desse nível de cerimônia para a maioria dos projetos, mas a ideia subjacente — uma matriz determinística gerada por script em vez de uma planilha mantida manualmente — escala para baixo tão bem quanto escala para cima.
Usando Agentes de IA para Rastreabilidade, Não Como Oráculo
Agentes de IA são bem adequados às partes mecânicas da rastreabilidade e mal adequados a serem o juiz final de se um requisito foi realmente satisfeito. Três tarefas se encaixam diretamente nas forças de um agente:
- Comparar especificação e diff — pedir ao agente para listar cada requisito mencionado nos arquivos de especificação tocados por um PR, e cada um para o qual não encontrou código correspondente.
- Encontrar requisitos não cobertos — pedir ao agente para escanear a suíte de teste em busca de tokens de requisito e relatar quais requisitos na especificação não têm nenhum.
- Detectar código não descrito pela especificação — pedir ao agente para sinalizar arquivos ou funções alteradas que tocam módulos portadores de requisitos, mas não correspondem a nenhum ID de requisito no diff.
O modo de falha a ser protegido é confiar no resumo do agente como verdade nua e crua em vez de como ponto de partida para um revisor. Um agente pode mal interpretar um comentário, perder um token de requisito dividido em dois arquivos ou declarar com confiança cobertura para um teste que apenas exerce o caminho do código superficialmente. Trate cada relatório de rastreabilidade gerado por agente como você trataria uma passagem de um revisor júnior: útil, rápido e ainda sujeito a um segundo olhar antes de bloquear um merge. Esta é a mesma cautela que se aplica a registros de decisão para desenvolvimento impulsionado por IA — o registro só permanece confiável se algo além do agente que o escreveu eventualmente verificá-lo.
Um Modelo de Rastreabilidade Mínimo que Você Pode Copiar
Você não precisa de um framework pesado para começar. Um modelo de cinco arquivos, commitado no repositório junto ao código que descreve, cobre o essencial:
docs/
requirements.md # IDs de REQ com critérios de aceitação estilo EARS
design.md # IDs de ADR, arquivos afetados, decisões de arquitetura
tasks.md # IDs de TAREFA mapeados para um ou mais IDs de REQ
tests.md # quais arquivos/funções de teste referenciam quais IDs de REQ
traceability.md # tabela gerada: REQ -> ADR -> TAREFA -> arquivos -> testes -> PR
requirements.md, design.md e tasks.md são escritos ou editados por humanos e agentes juntos, da mesma forma que o fluxo de trabalho de desenvolvimento dirigido por especificação já descreve. tests.md e traceability.md devem ser gerados, não mantidos manualmente, mesmo que o gerador seja um script curto que apenas faz grep por REQ-\d+ através do diretório de teste e dos arquivos de especificação — tabelas de rastreabilidade mantidas manualmente são, em si, uma forma de risco de desvio, porque ninguém atualiza uma planilha sob pressão de prazo.
Conclusão
O desenvolvimento dirigido por especificação não está concluído no momento em que o código sai de um agente; é apenas útil uma vez que código, testes e especificações se mantenham honestos ao longo do tempo, através de PRs, refatorações e alterações de requisitos que chegam meses separados. Um modelo de rastreabilidade construído a partir de seis identificadores simples, imposto por algumas verificações de CI e revisado com uma checklist de PR curta, dá a você a maior parte do benefício sem o sobrecarga de um framework de conformidade completo. Comece com o modelo mínimo, conecte a verificação de CI mais barata primeiro — IDs de requisito nas descrições dos PRs — e adicione a tabela de rastreabilidade e os avisos de especificação obsoleta assim que esse hábito se firmar.
A rastreabilidade é uma peça de uma disciplina maior de teste e documentação coberta no cluster Arquitetura de Aplicação em Produção, e ela está lado a lado com as questões de ferramental exploradas no cluster Ferramentas de Desenvolvimento com IA para equipes escolhendo quais fluxos de trabalho de agente padronizar.