Maturidade do SDD: os 3 níveis do código guiado por IA

Maturidade do SDD: os 3 níveis do código guiado por IA

A maturidade do SDD define o quanto a especificação realmente governa o código que sua equipe entrega com apoio de agentes de IA. Em outras palavras, não basta escrever uma spec antes de abrir o editor, porque o que importa é o papel que esse documento assume depois do primeiro commit.

Neste artigo, você vai conhecer os três níveis descritos pela comunidade: spec-first, spec-anchored e spec-as-source. Além disso, vai aprender a identificar em qual deles sua equipe está e quais práticas ajudam a avançar sem transformar a spec em burocracia.

O que significa maturidade do SDD

Spec Driven Development, ou SDD, é uma abordagem em que uma especificação estruturada e versionada ocupa o centro do desenvolvimento. Assim, o código passa a ser a implementação dessa intenção, e não a única fonte da verdade sobre o sistema.

A ideia ganhou força em 2025, quando agentes de código tornaram viável transformar uma descrição em linguagem natural em software funcionando. Nesse cenário, a GitHub lançou o Spec Kit, um toolkit open source que organiza o trabalho em etapas como constitution, specify, plan, tasks e implement.

Contudo, a definição de SDD ainda está em movimento. Por isso, Birgitta Böckeler, Distinguished Engineer da Thoughtworks, propôs em outubro de 2025 uma leitura em camadas no artigo Understanding Spec-Driven-Development.

Segundo ela, todas as abordagens de SDD são spec-first, mas nem todas buscam ser spec-anchored ou spec-as-source. Ou seja, os níveis se acumulam: cada um herda as práticas do anterior e acrescenta uma nova exigência.

Essa progressão é o que chamamos aqui de maturidade do SDD. Portanto, a pergunta central não é se a equipe escreve specs, mas por quanto tempo e com qual autoridade essas specs continuam valendo.

Um artigo acadêmico publicado no arXiv em janeiro de 2026 reforça essa visão ao descrever um espectro de rigor. Nele, quanto mais a autoridade da spec cresce, maior também é a disciplina necessária para manter spec e código alinhados.

Por que a maturidade do SDD importa no código guiado por IA

Modelos de linguagem são excelentes em completar padrões, mas não leem mentes. Quando o prompt é vago, o agente preenche as lacunas com suposições plausíveis, e muitas delas estão erradas.

Esse comportamento ficou conhecido como vibe coding. Na prática, ele funciona bem para protótipos, porém cobra um preço alto quando o sistema precisa sobreviver a meses de manutenção.

A spec resolve o primeiro problema, porque entrega ao agente um contrato claro sobre o que construir. Já a maturidade do SDD resolve o segundo, pois determina se esse contrato continua útil quando o produto muda.

Além disso, a velocidade dos agentes amplia o risco de divergência. Afinal, um agente gera código muito mais rápido do que uma pessoa consegue atualizar documentos, então a spec envelhece em dias, e não em meses.

Por esse motivo, entender os níveis de maturidade do SDD ajuda a escolher o investimento certo para cada contexto. Uma ferramenta interna descartável não precisa do mesmo rigor de um serviço financeiro com dezenas de consumidores.

Nível 1: spec-first

No spec-first, a equipe escreve uma especificação bem pensada antes do código e a usa para orientar o agente na tarefa em questão. Depois que a implementação fica pronta e os testes passam, porém, o documento perde importância.

Esse é o ponto de entrada natural da maturidade do SDD. De fato, a maioria das equipes começa aqui, muitas vezes sem sequer usar o nome Spec Driven Development.

Como o spec-first funciona na prática

Primeiro, alguém descreve a funcionalidade em termos de comportamento, com histórias de usuário e critérios de aceitação. Em seguida, o agente recebe esse material como contexto e produz um plano, uma lista de tarefas e o código.

Um trecho típico de spec nesse nível se parece com o exemplo abaixo, escrito em markdown.

# Feature: Short link creation

## User story
As a registered user, I want to shorten a long URL so that I can share it easily.

## Acceptance criteria
- AC-01: Given a valid URL, when the user submits it, then the system returns a 7-character code.
- AC-02: Given an invalid URL, when the user submits it, then the system returns a 400 error.
- AC-03: Given an expired link, when someone opens it, then the system returns a 410 error.

Repare que a spec descreve o que o sistema faz, sem prescrever como. Com isso, o agente tem um alvo claro e deixa de adivinhar formatos, limites e respostas de erro.

No Spec Kit, esse fluxo aparece nos comandos /speckit.specify, /speckit.plan, /speckit.tasks e /speckit.implement. Inclusive, Böckeler observa que a ferramenta cria uma branch para cada spec.

Na leitura dela, isso indica uma spec viva durante a mudança, mas não durante toda a vida da funcionalidade.

O problema da spec que envelhece

O ganho do spec-first é real, porque a clareza inicial melhora muito a qualidade do código gerado. Além disso, o custo de manutenção é baixo, já que ninguém precisa sincronizar documentos depois da entrega.

Contudo, esse modelo não protege contra o drift. Na segunda sprint, alguém altera uma regra direto no código; na terceira, o agente corrige um bug sem consultar a spec.

Logo depois, o documento passa a descrever um sistema que não existe mais. Nesse momento, o código volta a ser a única fonte confiável da verdade.

Em resumo, o spec-first funciona muito bem como kickoff, mas representa apenas o primeiro degrau da maturidade do SDD. Para protótipos, provas de conceito e funcionalidades isoladas, ele costuma ser o nível adequado de maturidade do SDD.

Nível 2: spec-anchored

No spec-anchored, a especificação permanece no repositório depois da entrega e evolui junto com o código durante todo o ciclo de vida do sistema. Toda mudança de comportamento exige atualizar a spec e o código, de preferência no mesmo pull request.

A grande diferença em relação ao nível anterior é a validação contínua. Em vez de confiar apenas na disciplina das pessoas, a equipe cria mecanismos automáticos que falham quando spec e implementação divergem.

Por isso, muitos autores consideram o spec-anchored o ponto de equilíbrio da maturidade do SDD para sistemas em produção. Ele entrega documentação confiável sem exigir que todo o código saia de um gerador.

Sincronização e validação contínua

Na prática, a sincronização depende de três peças. Primeiro, a spec vive no mesmo repositório do código e passa pelo mesmo processo de revisão.

Segundo, cada critério de aceitação vira um teste executável, seja um cenário BDD, um teste de contrato ou um teste de integração. Terceiro, o pipeline de CI executa esses testes a cada commit e bloqueia o merge quando algo diverge.

Ferramentas como Cucumber e Reqnroll seguem esse modelo há anos com cenários em Gherkin. Da mesma forma, contratos OpenAPI combinados com testes de contrato garantem que uma API continue respeitando o acordo publicado.

Exemplo de spec-anchored com testes em .NET

Considere o critério AC-03, do link expirado. Em um projeto .NET 10 com Minimal APIs, ele pode virar um teste de integração com xUnit e WebApplicationFactory, apontando para o identificador da spec.

// Critério AC-03 da spec specs/short-links/spec.md
public class ExpiredLinkTests(WebApplicationFactory<Program> factory)
    : IClassFixture<WebApplicationFactory<Program>>
{
    [Fact]
    [Trait("Spec", "AC-03")]
    public async Task Should_return_410_when_link_is_expired()
    {
        var client = factory.CreateClient(new() { AllowAutoRedirect = false });

        // O código "exp0001" está cadastrado como expirado nos dados de teste
        var response = await client.GetAsync("/exp0001");

        Assert.Equal(HttpStatusCode.Gone, response.StatusCode);
    }
}

O atributo Trait liga o teste ao critério AC-03. Dessa forma, a equipe consegue rastrear qual requisito cada teste protege e descobrir rapidamente quais critérios ainda não têm cobertura.

Em seguida, o pipeline executa esses testes e verifica se toda spec alterada veio acompanhada de mudanças nos testes.

name: spec-anchored-check
on: [pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '10.0.x'
      # Executa os testes ligados aos critérios da spec
      - run: dotnet test --filter "Spec~AC"
      # Falha se a spec mudou sem alteração nos testes
      - name: Check spec and tests changed together
        run: |
          CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
          if echo "$CHANGED" | grep -q '^specs/' && ! echo "$CHANGED" | grep -q '^tests/'; then
            echo "Spec changed without matching tests"
            exit 1
          fi

Os agentes de IA também se beneficiam desse degrau da maturidade do SDD. Afinal, quando a spec está sempre atualizada, cada nova sessão do agente parte de um contexto confiável, em vez de inferir regras a partir de código antigo.

Se você usa o Claude Code, por exemplo, o artigo Claude Code na prática mostra como estruturar um spec.md que serve de base para esse contexto.

Nível 3: spec-as-source

No spec-as-source, a spec se torna o artefato soberano do sistema. Somente ela recebe edições humanas, enquanto o código surge sob demanda como um produto de build que ninguém altera manualmente.

Esse é o topo da maturidade do SDD e também o nível mais radical. Na prática, a especificação passa a funcionar como código-fonte escrito em um nível de abstração mais alto.

Código como artefato derivado

O Tessl Framework é o exemplo mais citado dessa abordagem com IA. Nele, cada spec gera um arquivo de código que traz no topo um comentário avisando que o arquivo veio da spec e não deve sofrer edições.

Quem quer mudar o comportamento altera a spec e executa a geração novamente. Assim, o drift desaparece por construção, porque o código nunca evolui de forma independente.

Uma spec nesse nível tende a ser mais próxima do componente, como no exemplo a seguir.

# ShortCodeGenerator

Generates unique short codes for links.

## Capabilities
- Returns a 7-character alphanumeric string. @test
- Never returns a code that already exists in storage. @test

## API
- interface IShortCodeGenerator
- method GenerateAsync(CancellationToken cancellationToken): Task<string>
// GENERATED FROM SPEC - DO NOT EDIT
// Fonte: specs/short-code-generator.spec.md
public sealed class ShortCodeGenerator(ILinkStore store) : IShortCodeGenerator
{
    private const string Alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";

    public async Task<string> GenerateAsync(CancellationToken cancellationToken)
    {
        string code;

        do
        {
            code = new string(Random.Shared.GetItems(Alphabet.AsSpan(), 7));
        }
        while (await store.ExistsAsync(code, cancellationToken));

        return code;
    }
}

Repare que a spec define a interface pública e os testes esperados. Com isso, a parte mais sensível do componente, o contrato com o restante do sistema, continua sob controle humano.

Esse modelo não é novo fora do mundo da IA. Na indústria automotiva, por exemplo, engenheiros modelam algoritmos no Simulink e geram código C certificado que ninguém edita à mão.

Os riscos do não determinismo

A diferença é que geradores tradicionais são determinísticos, enquanto modelos de linguagem não são. Böckeler relata que, ao gerar código várias vezes a partir da mesma spec, obteve resultados diferentes.

Para aumentar a repetibilidade, ela precisou refinar o texto até deixá-lo cada vez mais específico, o que mostra o custo real desse degrau da maturidade do SDD.

Ela também traça um paralelo com o Model Driven Development, que nunca decolou em aplicações de negócio por gerar overhead e rigidez. Nesse sentido, o risco do spec-as-source é herdar a inflexibilidade do MDD e, ao mesmo tempo, o não determinismo dos LLMs.

Por isso, esse nível de maturidade do SDD exige confiança alta na ferramenta de geração. Hoje, ele faz sentido principalmente em módulos estáveis, com contratos claros e uma bateria robusta de testes derivados da própria spec.

Comparação entre os níveis de maturidade do SDD

A tabela abaixo resume as diferenças práticas entre os três níveis.

Critério Spec-first Spec-anchored Spec-as-source
Papel da spec Kickoff da tarefa Documentação viva Código-fonte real
Quem edita o código Pessoas e agentes Pessoas e agentes Apenas o gerador
Vida útil da spec Até a entrega Toda a vida da funcionalidade Toda a vida do sistema
Proteção contra drift Nenhuma Testes e CI Por construção
Custo de manutenção Baixo Médio Alto no início
Ferramentas típicas Kiro, Spec Kit Spec Kit, Reqnroll, OpenAPI com testes de contrato Tessl, geradores OpenAPI, Simulink
Uso indicado Protótipos e funcionalidades isoladas Sistemas em produção Módulos estáveis e domínios regulados

Perceba que a autoridade da spec cresce da esquerda para a direita. Em contrapartida, a disciplina necessária para manter tudo alinhado cresce na mesma proporção.

Além disso, os níveis não são excludentes dentro do mesmo produto. Muitas equipes combinam spec-as-source em um núcleo estável, spec-anchored nos serviços principais e spec-first em experimentos de curto prazo.

Essa combinação mostra que a maturidade do SDD não é um selo da empresa inteira. Na verdade, ela se aplica módulo a módulo, conforme o risco e a expectativa de vida de cada parte do sistema.

Como diagnosticar a maturidade do SDD da sua equipe

Um diagnóstico honesto começa por perguntas sobre o dia a dia, e não pelas ferramentas instaladas. Afinal, ter o Spec Kit configurado não significa estar no nível spec-anchored.

  • Depois do merge, alguém abre a spec de novo? Se a resposta for não, a equipe está no spec-first.
  • Existe algum teste que falha quando spec e código divergem? Se não existe, a equipe ainda não chegou ao spec-anchored.
  • O pull request de uma mudança de comportamento traz alteração na spec? Quando isso acontece de forma consistente, a equipe já opera em spec-anchored.
  • Alguém edita código gerado à mão? Se a resposta for nunca, e a geração é confiável, a equipe está no spec-as-source.

Também vale observar o comportamento dos agentes. Quando o agente precisa ler o código para descobrir uma regra de negócio, a spec deixou de ser a fonte da verdade.

Nesse caso, a maturidade do SDD real está abaixo da declarada. Ou seja, o processo existe no papel, mas não orienta o trabalho de fato.

Como evoluir na maturidade do SDD

Subir de nível não exige trocar de ferramenta, mas sim mudar hábitos. A recomendação do artigo do arXiv é usar o menor nível de rigor que elimina a ambiguidade no seu contexto.

Do spec-first para o spec-anchored

Comece pelas funcionalidades mais críticas, não pelo sistema inteiro. Mova as specs para uma pasta versionada, como specs/, e dê um identificador a cada critério de aceitação.

Em seguida, transforme os critérios em testes rastreáveis. Depois, inclua no template de pull request uma pergunta direta: esta mudança altera algum comportamento descrito na spec?

Por fim, ajuste as instruções do agente para que ele leia e atualize a spec antes de alterar o código. No Spec Kit, a constitution é o lugar ideal para registrar essa regra, já que ela vale para todas as interações.

Para padronizar esse contexto entre projetos, o artigo sobre como estender seu coding agent com .NET Skills mostra uma forma prática de empacotar instruções reutilizáveis.

Do spec-anchored para o spec-as-source

Esse passo deve acontecer de forma localizada e gradual. Escolha um módulo estável, com interface pública clara e poucas mudanças de regra, e teste a geração repetidas vezes antes de confiar nela.

Depois, marque os arquivos gerados com um cabeçalho explícito e bloqueie edições manuais no CI, como faz qualquer equipe madura nesse nível. Assim, qualquer alteração direta no código gerado aparece como violação, e não como atalho.

Ainda assim, mantenha os testes derivados da spec como rede de segurança. Como o modelo pode produzir resultados diferentes a cada geração, os testes garantem que o comportamento continua o mesmo.

Erros comuns ao avançar na maturidade do SDD

O primeiro erro é a superespecificação. Quando a spec começa a parecer pseudocódigo, ela perde a separação entre o que e o como, e o agente fica preso a decisões que deveriam ser técnicas.

O segundo é tratar a spec como burocracia. Se o processo vira um formulário a preencher, as pessoas contornam o fluxo e o documento volta a envelhecer em silêncio.

Outro erro frequente é usar o mesmo fluxo para tudo. Böckeler conta que, ao pedir a correção de um bug pequeno, o Kiro gerou quatro histórias de usuário com dezesseis critérios de aceitação.

Por fim, existe a falsa sensação de controle. Mesmo com templates, checklists e constitution, o agente às vezes ignora instruções ou segue uma regra com zelo excessivo.

Além disso, um teste que passa garante apenas que o código segue a spec, e não que a spec está correta. Em outras palavras, a especificação exige a mesma revisão cuidadosa que o código.

A maturidade do SDD aumenta a autoridade da especificação, mas não substitui o julgamento humano sobre os requisitos. Nesse sentido, o papel do desenvolvedor muda de escrever cada linha para orquestrar specs, revisar saídas e decidir o que de fato importa.

Conclusão sobre a maturidade do SDD

Os três níveis respondem a uma pergunta simples: depois do primeiro commit, quem manda no sistema, a spec ou o código? No spec-first, o código assume logo; no spec-anchored, os dois andam juntos; no spec-as-source, a spec governa sozinha.

Para a maioria das equipes, o objetivo realista é o spec-anchored. Ele mantém a documentação confiável, melhora o contexto dos agentes de IA e não depende de geradores que ainda estão amadurecendo.

Portanto, avalie com honestidade em que ponto da maturidade do SDD sua equipe está hoje. Em seguida, escolha uma funcionalidade crítica, ligue seus critérios a testes e coloque essa verificação no pipeline.

Esse pequeno passo já muda a forma como pessoas e agentes trabalham juntos. Com o tempo, a spec deixa de ser um documento de kickoff e se torna o contrato que todo o time respeita.

FAQ

O que é SDD?

Spec Driven Development é uma abordagem em que uma especificação versionada orienta o desenvolvimento. O código implementa essa especificação, que passa a ser a referência principal sobre o comportamento do sistema.

Qual é a diferença entre spec-first e spec-anchored?

No spec-first, a spec orienta apenas a implementação inicial e depois fica desatualizada. No spec-anchored, ela evolui junto com o código, e testes automáticos garantem o alinhamento.

O Spec Kit é spec-anchored?

O Spec Kit aspira a specs vivas, mas o fluxo padrão cria uma spec por mudança. Para chegar ao spec-anchored, a equipe precisa manter as specs e ligá-las a testes no CI.

Spec-as-source substitui o programador?

Não. O trabalho muda para escrever specs precisas, revisar o código gerado e garantir que os testes protejam o comportamento esperado.

Qual nível de maturidade do SDD devo adotar?

Use o menor nível que elimina a ambiguidade no seu contexto. Spec-first atende protótipos, spec-anchored atende sistemas em produção e spec-as-source atende módulos estáveis com geração confiável.