Spec-driven development: por que a IA gera o código errado mesmo com a spec pronta?

erros de especificação no spec-driven development que confundem a IA
Resposta rápida

Spec pronta e código errado é o cenário mais frustrante do spec-driven development, e quase nunca a culpa é do modelo: o agente só preencheu sozinho o que a frase deixou em aberto. Este post cataloga os 4 defeitos que mais causam isso (ambiguidade, escopo implícito, restrição técnica ausente e decisão em aberto), mostra o trecho reescrito de cada um e fecha com a rotina de validação: marcar as lacunas com [NEEDS CLARIFICATION], reescrever em padrão EARS, guardar as regras inegociáveis na constituição e rodar clarify e analyze antes de mandar implementar 🙂

Tu escreveu a spec, o agente seguiu o que estava lá, e mesmo assim o código saiu diferente do que tinha na tua cabeça

Fala aí, beleza? Essa cena é bem mais comum do que parece, e na maioria das vezes o problema não é o modelo

O agente não desobedeceu: ele preencheu sozinho o buraco que a spec deixou

E ele vai preencher SEMPRE, porque é isso que um LLM faz quando falta informação: escolhe a opção mais plausível e segue em frente, sem avisar

Aqui o post é um diagnóstico dos defeitos de escrita que transformam spec-driven development em retrabalho: quatro padrões de frase que sabotam a implementação, o trecho reescrito de cada um e a rotina de validação antes de pedir o código

Se tu ainda tá se situando no conceito, vale ler antes o que é spec-driven development e voltar pra cá com a tua spec na mão

O que você precisa antes de diagnosticar sua spec

São três coisas, e a terceira é opcional:

  • Uma spec já escrita, mesmo torta, mesmo pela metade (o diagnóstico é sobre o texto que existe, não sobre um template em branco)
  • Um agente de código integrado ao teu ambiente, seja CLI ou IDE
  • Opcionalmente, o Spec Kit, o toolkit open source publicado pelo GitHub pra guiar agentes por um processo estruturado

O Spec Kit vive no repositório github/spec-kit, mantido pelo GitHub, com documentação em github.github.com/spec-kit

Se tu só quer experimentar sem instalar nada, dá pra rodar avulso via uvx apontando pro repositório:

uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME>

Pra usar o diretório atual em vez de criar pasta nova, troca o nome do projeto por um ponto, mantendo o mesmo uvx na frente:

uvx --from git+https://github.com/github/spec-kit.git specify init .

Já se tu quer o CLI sempre à mão, a instalação persistente é essa:

Formação Claude Code
Formação Recomendada

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 120 aulas
  • 4 projetos
  • 9h 45min
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git

Roda com o teu agente? Provavelmente sim: o Claude Code está entre as integrações oficialmente suportadas (chave claude), junto de copilot, gemini, cursor-agent, codex, windsurf, qwen, opencode, kilocode, auggie, codebuddy e q

Tome cuidado com um detalhe: as integrações de CLI exigem a ferramenta já instalada na máquina, senão o init não tem com quem conversar

Os 4 defeitos de spec que fazem a IA gerar o código errado

Cada bloco aqui segue o mesmo formato: o sintoma que tu vê no código, a frase da spec que causou aquilo, o trecho reescrito e como prevenir

Bora ver na prática?

Defeito 1: ambiguidade (o adjetivo sem critério)

Sintoma no código gerado: o agente entrega algo que tecnicamente funciona, mas tu olha e pensa "não é isso que eu queria", sem conseguir apontar a linha errada

Causa na spec: adjetivo solto, sem número e sem condição. Palavras tipo rápido, amigável, seguro, intuitivo, performático

# frase ambígua
A busca de produtos precisa ser rápida e ter uma interface amigável

"Rápida" pra ti pode ser resposta instantânea, pro modelo pode ser "não travar o navegador"

Reescrita com condição verificável:

# frase com critério
Quando o usuário enviar o termo de busca, o sistema deve exibir a
primeira página de resultados em até X segundos (X é o limite que
tu define pro teu projeto)
A lista deve mostrar nome, preço e imagem de cada produto,
ordenados por relevância

O número ali é teu, não meu: o ponto é que ele EXISTA e possa ser conferido depois

Como prevenir: régua simples, se tu não consegue imaginar um teste que prova a frase, ela ainda tá ambígua

Defeito 2: escopo implícito (o óbvio que tu não escreveu)

Sintoma no código gerado: o agente inventa telas, campos e fluxos que ninguém pediu, ou ignora um pedaço que pra ti era parte do combo

Causa na spec: tu descreveu o que quer e presumiu que o resto vinha junto

# escopo implícito
O usuário deve poder salvar seus itens favoritos

Salvar onde? Precisa de login? Edita? Exclui? Tem limite de quantos? Aparece em alguma listagem?

O agente vai responder tudo isso sozinho, e cada resposta é uma decisão de produto que ele tomou no teu lugar

Reescrita explicitando dentro e fora:

# escopo fechado
Dentro do escopo:
- usuário autenticado salva e remove um item da lista de favoritos
- a lista de favoritos aparece em uma página própria

Fora do escopo desta tarefa:
- compartilhar a lista com outros usuários
- ordenar ou filtrar os favoritos
- notificação de mudança de preço

Como prevenir: toda spec ganha uma seção "fora do escopo". Parece burocracia, mas é a parte que mais economiza token e retrabalho

Defeito 3: restrição técnica ausente

Sintoma no código gerado: aparece uma biblioteca que tu não usa, um formato de data diferente do resto do projeto, um padrão de pasta que não é o teu

Causa na spec: nenhuma menção a stack, formato de dado ou limite, então o modelo escolhe pelo que é mais comum no treino dele

# sem restrição
Criar o endpoint que retorna o histórico de pedidos do usuário

Reescrita fixando a restrição como regra:

# com restrição
Criar o endpoint de histórico de pedidos seguindo as regras do projeto:
- acesso ao banco somente pela camada de repositório já existente
- datas sempre em ISO 8601, em UTC
- resposta paginada, nunca a lista completa
- nenhuma dependência nova sem aprovação

Como prevenir: restrição que vale pro projeto inteiro não deve ficar repetida em cada spec, e sim num lugar só. É exatamente pra isso que existe o arquivo de constituição, que a gente vê no próximo bloco

Defeito 4: decisão deixada em aberto

Esse é o mais traiçoeiro, porque a frase parece completa

Sintoma no código gerado: duas partes do sistema tratam a mesma regra de jeitos diferentes, e tu só descobre quando algo quebra na integração

Causa na spec: duas interpretações razoáveis convivendo no mesmo parágrafo

# decisão em aberto
O carrinho expira depois de um período de inatividade

Expira apagando os itens ou só liberando o estoque reservado? Conta inatividade da aba ou da conta?

Tem dois caminhos aqui: ou tu fecha a decisão na hora, ou tu marca ela de forma explícita

Os templates do Spec Kit obrigam a marcar toda ambiguidade com um marcador NEEDS CLARIFICATION (escrito entre colchetes no template), sempre no formato de pergunta específica, justamente pra impedir o comportamento típico do LLM de assumir algo plausível porém errado:

NEEDS CLARIFICATION: o carrinho expirado apaga os itens ou
apenas libera o estoque reservado?

E tem um limite que vale ouro: no máximo 3 marcadores por spec, reservados pra decisões críticas, aquelas que mudam escopo ou experiência e têm mais de uma leitura razoável

Se tu tá com onze marcadores, o problema não é ambiguidade pontual, é que a spec inteira ainda não foi pensada 😅

O checklist de completude do template ainda exige que NENHUM marcador desses continue na spec na hora de implementar

A prevenção que corta os quatro de uma vez: EARS

A notação EARS ataca a raiz dos três primeiros defeitos restringindo a própria frase a um conjunto pequeno de padrões com palavra-chave fixa

Ela foi criada por Alistair Mavin e colegas na Rolls-Royce, durante a análise de regulamentação de aeronavegabilidade pra um sistema de controle de motor a jato, e publicada na IEEE International Requirements Engineering Conference (RE’09), em 2009

Ou seja: nasceu num contexto onde requisito ambíguo custa muito caro 😀

São 5 padrões, mais um complexo que combina estado e gatilho:

Padrão Palavra-chave Pra que serve
Ubíquo sem gatilho regra que vale sempre, o tempo todo
Dirigido a estado While comportamento enquanto o sistema está em certo estado
Dirigido a evento When comportamento disparado por um gatilho
Comportamento indesejado If / Then erro, exceção, entrada inválida
Feature opcional Where comportamento que só existe se a feature estiver presente
Complexo combinação estado e gatilho juntos na mesma frase

Se tu conhece a ideia de escrever critério de aceite antes do código, EARS é a versão disciplinada disso: a palavra-chave te obriga a dizer QUANDO a regra vale

O Kiro, a IDE agêntica da AWS construída em torno de spec-driven development, usa justamente EARS pra converter o teu prompt em um documento formal de requisitos na etapa de requirements

Documentação oficial da notação pra quem quiser se aprofundar nos padrões

Como reescrever a spec e validar antes de mandar implementar

Agora a rotina, aplicando o catálogo em ordem

  1. Releia a spec caçando os 4 defeitos e marque cada lacuna crítica com o marcador NEEDS CLARIFICATION seguido da pergunta específica, respeitando o teto de 3

O erro comum deste passo: marcar tudo que gera dúvida. O marcador é pra decisão que muda escopo ou experiência, não pra detalhe de implementação que tu resolve numa linha

  1. Reescreva as frases vagas em padrão EARS, uma por uma, começando pelas que descrevem comportamento do usuário

O erro comum deste passo: trocar o adjetivo por outro adjetivo ("rápida" virando "eficiente") em vez de colocar gatilho e critério

  1. Mova as regras inegociáveis do projeto pra constituição, no caminho padrão .specify/memory/constitution.md

A estrutura .specify/ criada pelo init traz ainda scripts/, specs/ e a pasta templates/ com spec-template.md, plan-template.md e tasks-template.md

O erro comum deste passo: repetir a mesma restrição de stack em toda spec nova, e aí um dia tu esquece de repetir e o agente escolhe sozinho

  1. Rode o comando de clarificação, que é a etapa opcional entre specify e plan:
/speckit.clarify

Ele existe exatamente pra atacar áreas subespecificadas: o agente lê a spec, faz perguntas dirigidas sobre as ambiguidades e grava as respostas de volta na própria spec

O erro comum deste passo: responder as perguntas no chat e achar que acabou. O valor tá na resposta ficar gravada no documento, não na conversa

  1. Rode a análise dos artefatos, que é somente leitura e não altera arquivo nenhum:
/speckit.analyze

Ela revisa em busca de inconsistências, ambiguidades e lacunas de cobertura

O erro comum deste passo: pular ela por pressa, justo quando ela é a etapa mais barata do fluxo inteiro (read-only, zero risco)

  1. Só então siga pro resto do fluxo, que é todo dirigido por comandos de barra no formato /speckit.<comando>: constitution, specify, clarify, plan, checklist, tasks, analyze, implement e converge

O erro comum deste passo: mandar implementar com marcador de clarificação ainda vivo no texto. Faz a checagem final: se sobrou um NEEDS CLARIFICATION na spec, o agente vai decidir por ti

  1. Não usa Spec Kit? Dá pra fazer o mesmo diagnóstico com o modo de planejamento somente leitura do Claude Code, em que ele lê arquivos e responde perguntas sem alterar nada até tu aprovar

Tu entra apertando Shift+Tab até a barra de status mostrar o modo plano, ou já começa a sessão assim:

claude --permission-mode plan

Nesse modo o Claude pode usar o AskUserQuestion pra esclarecer requisitos antes de fechar o plano, que é a mesma função do clarify: te obrigar a decidir antes de virar código

O erro comum deste passo: aprovar o plano no automático, sem ler. O plano é a última tela onde o erro ainda é barato

E se o teu ambiente é outro, o raciocínio não muda: a ideia de escrever a spec antes do código vale igual no Cursor

O que muda na prática quando a spec fecha as lacunas

No vídeo do canal eu montei o SDD na mão, com três documentos, em vez de usar framework pronto

O terceiro documento é o de tarefas: a ordem de execução que faz sentido pela perspectiva de uso, não uma lista solta

Eu ordenei começando pelo setup inicial (criar pastas, instalar bibliotecas), depois autenticação por ser complexa e vital, depois a função central do produto, e só então as partes que dependem de login. No fim eu costumo reservar uma tarefa de polimento pra aparar as arestas

O projeto foi um gerador de QR Code: sem login gera e baixa o QR Code (texto, wi-fi, contato), com login salva, gerencia e vê os anteriores numa dashboard

Escolhi de propósito uma stack que as IAs dominam: Next, TypeScript, Prisma e SQLite pra não precisar de setup de banco, mais a camada de estilização (e sim, num cenário real aquele SQLite teria que virar Postgres)

E aqui vem a parte que interessa pro assunto deste post

Com a decisão já fechada no documento, a tarefa de autenticação levou cerca de 2 minutos pra IA implementar

Depois foi só subir o servidor local, que abriu na porta 3002, e testar na mão: gerei o QR Code, baixei o PNG, escaneei e caiu no site certo. Testei o login e confirmei que estava autenticado

Os prompts de execução viraram uma coisa curta e repetitiva: executa a tarefa X, segue o documento de design, me avisa quando terminar

Percebe o deslocamento? O tempo saiu da execução e foi pro planejamento

Tu gasta mais na escrita do requisito, e em troca as etapas seguintes ficam previsíveis e sequenciais, sem precisar caprichar no prompt a cada rodada. Eu até agrupei tarefas relacionadas na execução (o CRUD de salvar QR Codes junto da dashboard) em vez de rodar uma a uma, e o ritmo foi acelerando conforme avançava

Pra ver o método rodando do zero antes de aplicar o diagnóstico na tua spec, o vídeo mostra o fluxo completo:

Quanto rigor a sua spec precisa ter?

Nem toda tarefa merece o mesmo nível de spec, e essa é a pergunta que quase ninguém faz

Birgitta Böckeler, da Thoughtworks, analisou Kiro, Spec Kit e Tessl no site do Martin Fowler e chegou numa leitura que ajuda demais aqui: spec-driven development não é uma prática única, é uma escada de ambição em três níveis

Nível O que a spec é Onde o defeito dói mais
Spec-first a spec dirige a tarefa atual ambiguidade e escopo implícito, porque o estrago aparece já na primeira entrega
Spec-anchored a spec é mantida e a feature evolui por ela restrição técnica ausente, porque cada rodada nova reintroduz decisão que já tinha sido tomada
Spec-as-source a spec é o arquivo-fonte e o código é a saída decisão em aberto, já que a lacuna não é um bug pontual e sim um buraco no próprio fonte

Se tu tá no primeiro degrau, resolver ambiguidade e fechar escopo já resolve a maior parte da dor

Agora, quanto mais tu sobe na escada, mais a spec precisa ser um documento vivo e versionado, e menos ela aguenta frase solta

O Kiro leva isso ao pé da letra materializando a spec em três documentos versionados: requirements.md, design.md e tasks.md

Repara que é a mesma lógica dos três documentos que eu montei na mão, só que com a ferramenta cuidando da estrutura pra ti

Conclusão

A spec errada sai mais cara que a spec ausente, e o motivo é psicológico: ela PARECE pronta

Sem spec tu desconfia de tudo que a IA entrega

Com uma spec ambígua tu confia, aprova, e só descobre o buraco três features depois

Recapitulando os quatro defeitos: adjetivo sem critério, escopo que tu achou óbvio e não escreveu, restrição técnica que ficou na tua cabeça e decisão com duas leituras razoáveis no mesmo parágrafo

Próximo passo prático, e é rapidinho: pega a spec da tua próxima tarefa, passa os 4 defeitos nela, marca com o marcador NEEDS CLARIFICATION mais a pergunta específica o que continuar em aberto (no máximo 3, lembra) e roda a validação antes de pedir implementação

Faça o teste e compara com a última vez que tu mandou direto 😀

até o próximo post!

Perguntas frequentes

Dá pra fazer spec-driven development sem instalar nenhum toolkit?

Dá sim, o conceito é sobre a disciplina de escrever a spec antes do código, não sobre uma ferramenta específica. O Spec Kit só dá estrutura e comandos pra esse processo, mas os quatro defeitos de escrita (ambiguidade, escopo implícito, restrição ausente e decisão em aberto) valem pra qualquer spec, com ou sem toolkit.

Qual a diferença entre spec-first, spec-anchored e spec-as-source?

São os três níveis da escada de ambição descrita por Birgitta Böckeler, da Thoughtworks, em análise publicada no site do Martin Fowler. No spec-first a spec só dirige a tarefa atual, no spec-anchored ela é mantida e a feature evolui a partir dela, e no spec-as-source a spec vira o arquivo-fonte e o código passa a ser apenas a saída gerada.

O que é a notação EARS e por que ela reduz ambiguidade?

EARS (Easy Approach to Requirements Syntax) restringe cada frase de requisito a um conjunto pequeno de padrões com palavras-chave fixas, o que reduz ambiguidade. São 5 padrões: ubíquo (sem gatilho), dirigido a estado (While), dirigido a evento (When), comportamento indesejado (If/Then) e feature opcional (Where), mais um padrão complexo que combina estado e gatilho. A notação foi criada por Alistair Mavin e colegas na Rolls-Royce, durante análise de regulamentação de aeronavegabilidade, e publicada na IEEE RE’09 em 2009.

Para que serve o comando /speckit.clarify antes de rodar o /speckit.plan?

O /speckit.clarify é uma etapa opcional entre o specify e o plan feita justamente pra atacar área subespecificada: o agente lê a spec, faz perguntas dirigidas sobre os pontos ambíguos e grava as respostas de volta na própria spec. Os templates marcam cada ambiguidade com um marcador NEEDS CLARIFICATION no formato de pergunta específica, no máximo 3 por spec, e o checklist de completude exige que nenhum sobre antes de seguir pro plano.

O que fica guardado no arquivo constitution.md do Spec Kit?

É onde ficam as regras inegociáveis do projeto, tipo padrão de acesso a banco, formato de data ou proibição de dependência nova sem aprovação. O caminho é .specify/memory/constitution.md, dentro da estrutura que o init cria (junto com scripts/, specs/ e templates/), então restrição que vale pro projeto inteiro não precisa ser repetida em cada spec individual.

Dá pra usar o modo de planejamento do Claude Code pra revisar a spec antes de gerar o código?

Dá sim, e ajuda bastante nesse diagnóstico. Basta entrar com Shift+Tab até a barra de status mostrar o modo plano, ou iniciar a sessão com claude –permission-mode plan: nesse modo o Claude só lê arquivos e responde perguntas, sem alterar nada, e pode usar o AskUserQuestion pra esclarecer requisitos antes de fechar o plano.




Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares