Níveis de rigor — spec-first, spec-anchored, spec-as-source

TL;DR

SDD não é binário. Há um espectro de rigor entre vibe coding (zero spec) e spec-as-source (spec gera código). A escolha depende do contexto: protótipo pode viver sem; produto crítico precisa de spec viva. Quatro níveis nomeáveis: Vibe (sem spec), Spec-first/static (escreveu uma vez, não mantém), Spec-anchored/living (mantida em sincronia com código), Spec-as-source (spec é fonte autoritativa, código é derivado). Escolher o nível errado é tão custoso quanto não ter spec.

Por que o espectro importa

Quando alguém diz “adotar SDD”, a pergunta natural é: quanto? Não existe uma resposta universal. Um protótipo com vida útil de duas semanas não precisa do mesmo rigor de um sistema de pagamentos com 5 anos de operação e auditoria regulatória.

A analogia é o mercado de seguros. Você não contrata o mesmo seguro para uma bicicleta e para um avião. A cobertura deve ser proporcional ao risco. Spec é o mesmo: o rigor deve ser proporcional ao custo de falhar.

O erro mais comum é aplicar nível zero (vibe) onde deveria ser pelo menos nível 1, ou aplicar nível máximo (spec-as-source) onde spec-anchored seria suficiente e mais barato. Ambos os erros geram dor — de formas diferentes.

graph LR
    A["⚪ Vibe<br/>(sem spec)"] --> B["📄 Spec-first<br/>static"]
    B --> C["📐 Spec-anchored<br/>living"]
    C --> D["🏛️ Spec-as-source<br/>código derivado"]

    style A fill:#ff6b6b,color:#fff
    style B fill:#ffd93d,color:#333
    style C fill:#6bcb77,color:#fff
    style D fill:#4d96ff,color:#fff
NívelSpec mantida?ValidaçãoCusto inicialCusto de falha
0 — VibeNão existeOlhômetroZeroAlto em prod
1 — Spec-first / staticUma vezManual eventualBaixoMédio (drift previsível)
2 — Spec-anchored / livingContínuaAutomatizada parcialMédioBaixo
3 — Spec-as-sourceAutoritativaAutomatizada totalAltoMínimo

Nível 0 — Vibe coding (referência)

Como é: “Faça um sistema de login.” → modelo gera → você olha → merge.

Não existe documento de requisitos, critério de aceitação explícito, ou registro de decisão. Code review é intuitivo. Cada sessão começa do zero. O agente não sabe o que foi decidido na semana passada.

Ciclo de trabalho:

prompt → código → "parece bem?" → merge → próxima sessão começa do zero

Quando ainda faz sentido:

  • Protótipos descartáveis (vai ser jogado fora)
  • Hackathons e POCs de validação rápida
  • Scripts pessoais de uso único
  • Exploração técnica sem intenção de produção

Onde dói inevitavelmente:

  • Qualquer sistema com usuários reais
  • Qualquer sistema com dados sensíveis
  • Qualquer sistema com SLA
  • Qualquer sistema que vai crescer além de uma feature

Ver 01 - O problema do vibe coding em produção para os dados quantitativos da dor.

Nível 1 — Spec-first / Static-spec

Como é: você escreve a spec antes de pedir código ao agente, mas depois que o código está escrito, a spec vira documentação estática — não é atualizada automaticamente com mudanças futuras.

docs/features/auth/login.md   ← escrito uma vez, antes
src/auth/login/               ← código vive depois; evolui independentemente

A spec da primeira implementação está correta. As specs das implementações 2, 3, 4 não existem — estão implícitas no código. Em 3-6 meses, spec e código divergem. Quem chega novo no projeto lê a spec e encontra um sistema diferente.

Ciclo de trabalho:

spec → agente implementa → testes manuais → merge
(mudança de requisito) → código muda → spec fica stale

Armadilha — mudança frequente escolhendo spec-first

Spec-first funciona bem para escopo fixo e curta duração. Mas se o projeto tem mudança frequente de requisito — típico de produto em fase de descoberta, com pivôs constantes — spec-first garante que a spec fica obsoleta em semanas, não meses. Nesse cenário, ou o time aceita que a spec é só um artefato de kickoff (e trata como tal, sem fingir que é fonte de verdade), ou sobe direto para spec-anchored. Manter spec-first como documentação viva em contexto de mudança rápida é o pior dos dois mundos: dá trabalho de escrever e mente sobre o estado real do sistema.

Onde spec-first brilha:

  • Projetos com escopo fixo e curta duração (< 1 sprint)
  • Features isoladas sem revisão futura planejada
  • Primeiro uso de SDD num time (custo de entrada baixo)
  • Documentação de sistemas legados existentes

Limitações inevitáveis:

  • Drift entre spec e código cresce com o tempo
  • Time esquece de atualizar (é humano, não falha moral)
  • LLM em sessões posteriores usa spec desatualizada como contexto — pior que sem spec
  • Spec vira “documentação de comissão”: útil só no onboarding inicial

Ferramentas típicas: Notion + revisão pré-PR, GitHub Issues estruturadas com acceptance criteria, ADRs em /docs/decisions/.

Sinal de que está no limite: alguém pergunta “isso ainda funciona assim?” e ninguém sabe. Hora de subir para spec-anchored.

Nível 2 — Spec-anchored / Living-spec

Como é: spec está versionada no repositório e é mantida em sincronia com o código a cada PR. Mudança de comportamento → mudança na spec → mudança no código. Os três andam juntos no mesmo commit ou PR.

specs/auth/login.md     ← source of truth, sempre atualizada
src/auth/login/         ← implementação (validada contra spec)
tests/auth/login/       ← assertions derivadas dos acceptance criteria da spec

A diferença crítica em relação ao nível 1: há automação que detecta drift. Se a spec menciona um endpoint que não existe no código, o CI falha. Se o código implementa comportamento que não está na spec, o reviewer percebe na revisão (PR template inclui “spec atualizada”).

Ciclo de trabalho:

spec nova ou atualizada → PR review da spec → agente implementa
→ testes automáticos validam contra spec → merge (spec + código juntos)

Estrutura típica de um repositório spec-anchored:

projeto/
├── specs/
│   ├── auth/
│   │   ├── login.md          ← spec da feature
│   │   └── permissions.md
│   ├── payments/
│   │   └── checkout.md
│   └── _conventions.md       ← como escrever specs aqui
├── src/
│   └── ...                   ← implementação
└── .github/
    └── pull_request_template.md  ← inclui checklist de spec

Benefícios concretos:

  • Spec sempre fresca → agente em sessões futuras tem contexto correto
  • Onboarding de novo dev: lê specs/ e entende o sistema sem arqueologia de código
  • Code review tem critério mecânico (spec atendida ou não, não só “parece certo”)
  • Mudanças de requisito têm rastreabilidade: diff de spec + diff de código no mesmo PR
  • Compliance: auditor lê spec, não código

Custo real de adoção:

  • PR template com checklist (1 hora para configurar)
  • CI job básico de validação de drift (1-2 dias para implementar)
  • Reunião de alinhamento de processo (1-2 horas)
  • Curva de adaptação do time: 2-4 semanas para virar hábito

Ferramentas que suportam nativamente: GitHub Spec Kit, OpenSpec, Kiro (steering docs), Augment Code workspace context.

O sinal de que spec-anchored é o nível certo: você tem um produto crescendo, com features se sobrepondo, e precisa que o conhecimento do sistema sobreviva à rotatividade do time.

Nível 3 — Spec-as-source

Como é: spec é autoritativa. Código é regenerado/derivado a partir dela. Quando spec e código conflitam, spec ganha — código é refeito, não o contrário.

specs/auth.spec.yml      ← AUTORITATIVO (machine-readable)
src/auth/                ← gerado/derivado (regenerável)
contracts/auth.test.yml  ← gerado da spec, executável

Mudança de comportamento entra na spec. A pipeline regenera stubs, contracts, testes, e às vezes código completo. O código não é editado diretamente para mudanças de comportamento — é um artefato derivado, como bytecode.

Ciclo de trabalho:

spec atualizada → pipeline CI → gera stubs/contracts → agente implementa dentro dos stubs
→ validação formal (spec vs implementação) → merge

Onde spec-as-source é o nível correto:

  1. Compliance regulatório com rastreabilidade total — LGPD, PCI DSS, SOC 2, HIPAA. Auditores exigem prova de que o sistema implementa o que diz implementar. Com spec-as-source, a prova é matemática.

  2. Múltiplas implementações da mesma spec — API, SDK mobile, Web app, CLI. Mesma spec, três implementações. Sem spec autoritativa, drift entre implementações é inevitável.

  3. Sistemas de alta frequência de mudança com zero tolerância a drift — fintech, infraestrutura crítica.

  4. Multi-agent SDD — quando múltiplos agentes trabalham em paralelo, cada um precisa de spec autoritativa clara. Spec-as-source é o contrato entre agentes. Ver 09 - SDD com agentes — coordinator, implementor, validator.

Benefícios:

  • Drift é impossível por construção (não por disciplina)
  • Auditoria trivial (spec é o registro completo)
  • Multiagent coordenado sem conflito
  • Regeneração após upgrade de framework (reaplica spec na nova base)

Custo e requisitos:

  • Stack precisa suportar geração: OpenAPI Generator, Protobuf, Tessl, Kiro com spec formal
  • Spec precisa de linguagem formal ou estrutura machine-readable (YAML/JSON schema > markdown)
  • Não funciona para domínios que não se modelam formalmente (ex: UX, criatividade)
  • Time precisa desenvolver habilidade de pensar em especificação formal
  • Investimento inicial: semanas a meses dependendo do tamanho do sistema

Ferramentas que suportam: Tessl, Kiro com steering + hook files estruturados, OpenAPI Generator, Protobuf + gRPC, sistemas de codegen tradicionais acoplados a SDD.

Armadilha — spec-as-source sem cultura de spec-anchored

Pular direto de spec-first (ou de vibe) para spec-as-source, sem o time ter passado por spec-anchored, tende a falhar. A razão não é técnica — é humana: a disciplina de manter spec e código sincronizados, de tratar drift como bug, de revisar spec como parte do PR, é um hábito que se constrói em spec-anchored. Sem esse hábito, a automação de spec-as-source fica órfã: ninguém sabe editar a spec corretamente, ninguém audita se o gerador está coerente com a intenção, e o time acaba editando o código gerado diretamente (quebrando a garantia central do nível 3). Ver a seção “O espectro como jornada, não como destino” abaixo.

Quando subir um nível

A regra de ouro é reagir a sinais do sistema, não antecipar por precaução excessiva:

Gatilhos para subir de nível

Vibe → Spec-first: quando a feature vai durar mais de um sprint, ou quando você precisar explicar o que construiu para alguém.

Spec-first → Spec-anchored: quando alguém perguntou “isso ainda funciona assim?” e ninguém sabia; quando spec divergiu do código pela primeira vez; quando novo membro chegou e spec não ajudou.

Spec-anchored → Spec-as-source: quando compliance exige rastreabilidade total; quando você tem ≥3 implementações da mesma spec; quando agentes múltiplos trabalham em paralelo na mesma base.

Subir de nível desnecessariamente tem custo. Implementar spec-as-source num projeto de 3 meses é matar mosquito com canhão.

Mistura de níveis dentro do mesmo projeto

Projetos maduros frequentemente têm níveis diferentes por área — e isso é correto, não inconsistência:

projeto/
├── core/            ← Spec-as-source (compliance crítico, zero tolerância a drift)
├── public-api/      ← Spec-anchored (estabilidade, clientes externos dependem)
├── admin-ui/        ← Spec-first (mudança rápida, usuário interno)
└── experiments/     ← Vibe (descartável, duração < 2 semanas)

A lógica: o nível certo é proporcional ao custo de erro naquela área. core/ que falha pode derrubar a empresa; experiments/ que falha é deletado.

A decisão de qual nível aplica a qual área é uma decisão arquitetural — deve ser explícita, registrada, e revisada periodicamente.

Armadilha — mistura de níveis sem registro arquitetural

Ter níveis diferentes por área é saudável. O que não é saudável é a mistura acontecer por acidente — cada equipe escolhendo seu próprio nível sem ninguém decidir isso conscientemente, e sem nenhum documento dizendo por quê. Sem esse registro, dois problemas aparecem: (1) alguém aplica spec-as-source num módulo que não precisava (custo desperdiçado) ou vibe coding num módulo crítico (risco não percebido); (2) quando o sistema cresce e as fronteiras entre core/, public-api/ e admin-ui/ mudam, ninguém sabe se o nível de rigor deveria mudar junto — porque a decisão nunca foi um ADR, foi um hábito tácito de cada squad.

Sinais de que escolheu o nível errado

Sintoma observadoDiagnósticoAjuste
”Spec atrapalha mais que ajuda — burocracia”Nível alto demais para o escopoReduzir para spec-first ou vibe
”Não sei o que era pra fazer”Nível baixo demaisSubir para spec-first mínimo
”Spec stale, ninguém usa”Spec-first onde precisava ser anchoredImplementar sincronia automática
”Geração quebra tudo na primeira mudança”Spec-as-source prematuroVoltar para anchored
”Agente segue spec mas drift acontece mesmo”Falta automação de validaçãoAdicionar CI check de drift
”Compliance quer mais rastreabilidade”Anchored insuficiente para o reguladorSubir para spec-as-source

A escolha é organizacional, não só técnica

O nível certo não depende só da tecnologia — depende do contexto humano:

FatorNível recomendado
Time de 1-2 devsSpec-first como piso mínimo
Time de 5+ devsSpec-anchored como base
Time distribuído/remotoSpec-anchored obrigatório (sem alinhamento verbal)
Alta rotatividadeSpec-anchored (documentação viva substitui conhecimento tácito)
Sistema < 6 meses de vidaSpec-first
Sistema > 2 anos de vidaSpec-anchored mínimo
Compliance regulatórioSpec-as-source obrigatório
Produto crítico sem compliance formalSpec-anchored como teto prático
Múltiplos agentes autônomosSpec-as-source (agentes precisam de contrato autoritativo)

Exemplo concreto: a mesma feature nos três níveis

Para tornar a diferença tangível, aqui está a implementação de “autenticação com OAuth” em cada nível:

Nível 1 — Spec-first

# Auth: OAuth Login
Usuário pode fazer login com Google OAuth.
Deve redirecionar para callback, criar session, redirecionar para dashboard.

O agente implementa. Em 3 meses, adicionamos “login com GitHub”. Spec diz só “Google OAuth”. Código suporta os dois. Spec fica stale. Quando o time crescer, novo dev vai ler a spec e implementar uma terceira OAuth com pattern diferente.

Nível 2 — Spec-anchored

# Auth: OAuth Login — spec v2.1
Atualizado: 2026-03-15 (adicionado GitHub provider)
 
## Providers suportados
- Google OAuth 2.0 (PKCE flow)
- GitHub OAuth App
 
## Acceptance criteria
- [ ] Redirect para provider com state anti-CSRF
- [ ] Callback válida state + troca code por token
- [ ] Session criada com user_id, email, provider, expires_at (24h)
- [ ] Redirect para dashboard após login bem-sucedido
- [ ] Login com provider não suportado → HTTP 400
 
## Não inclui
- Login com senha (ver spec auth-password.md)
- Login com Facebook (fora do roadmap)

A spec está no repositório. O PR do GitHub OAuth incluiu a atualização da spec. CI verifica que os endpoints da spec existem no código. Qualquer adição futura segue o mesmo padrão.

Nível 3 — Spec-as-source

# specs/auth/oauth.spec.yml
version: "2.1"
feature: oauth-login
providers:
  - id: google
    flow: pkce
    scopes: [openid, email, profile]
  - id: github
    flow: authorization_code
    scopes: [read:user, user:email]
endpoints:
  - path: /auth/{provider}/login
    method: GET
    response: redirect_to_provider
  - path: /auth/{provider}/callback
    method: GET
    params: [code, state]
    response: session_created
acceptance_criteria:
  - anti_csrf_state: required
  - session_expires: 86400  # 24h
  - invalid_provider: http_400

O CI gera stubs, OpenAPI contracts, e teste de integração a partir desse YAML. O agente implementa dentro dos stubs. Mudança de provider é mudança no YAML, não no código — o gerador recria os stubs.

A spec garante que o código web, o SDK mobile e a API pública implementam exatamente o mesmo comportamento de OAuth.

Custo-benefício ao longo do tempo

Uma análise simplificada de custo relativo nos primeiros 12 meses:

xychart-beta
    title "Custo acumulado de manutenção por nível (relativo)"
    x-axis ["Mês 1", "Mês 3", "Mês 6", "Mês 9", "Mês 12"]
    y-axis "Custo acumulado (relativo)" 0 --> 200
    line [10, 30, 80, 140, 200]
    line [20, 40, 65, 90, 110]
    line [40, 55, 70, 82, 95]
    line [80, 90, 100, 105, 108]

Da mais alta à mais baixa ao fim: Vibe (vermelha), Spec-first (amarela), Spec-anchored (verde), Spec-as-source (azul). Vibe tem menor custo inicial mas crescimento exponencial; spec-as-source tem maior custo inicial mas trajetória quase plana.

A divergência começa por volta do mês 3-4 — quando o primeiro retrabalho causado por drift chega. Times de vibe coding frequentemente não percebem o custo porque ele é distribuído em forma de bugs, revisões lentas e onboarding ruim. Só comparando com o alternativo é que o delta fica claro.

O espectro como jornada, não como destino

Times não começam em spec-as-source. Evoluem:

Mês 1-2:  Vibe → Spec-first (uma feature piloto)
Mês 3-4:  Spec-first para todas as features novas
Mês 5-6:  Spec-anchored com CI check de drift
Mês 7+:   Spec-as-source para áreas críticas específicas

Essa progressão permite que o time construa o hábito antes de aumentar a automação. Pular direto para spec-as-source sem a cultura de spec-anchored tende a falhar porque a automação sem disciplina humana fica órfã.

Há um padrão recorrente nos times que falham na adoção de SDD: tentam fazer muito de uma vez. Querem ir de vibe para spec-as-source num sprint de duas semanas. A transição bem-sucedida é incremental e oportunista — começa na próxima feature nova, não num big bang de migração.

Regra prática

Se você está escolhendo o nível certo agora: comece um nível abaixo do que você acha que precisa. Você pode sempre subir quando sentir a necessidade. Descer de nível depois de implementar automação é mais custoso.

Como explicar em inglês

Em entrevista ou em contexto internacional, os quatro níveis e seus conceitos-satélite têm nomes específicos em inglês — nem sempre a tradução literal do português é a que aparece na literatura.

PT-BREN
Spec estáticaStatic spec
Spec vivaLiving spec
Spec como fonteSpec-as-source
Fonte autoritativaSource of truth / authoritative source
Critério de aceitaçãoAcceptance criteria
Drift de specSpec drift
RastreabilidadeTraceability
Código derivadoDerived code / generated code
Checklist de aceitaçãoDefinition of Done (DoD)
VersionamentoVersioning

Frase de referência

“We run spec-anchored for the public API — the spec lives in the repo and CI fails on drift. For the admin UI we’re still spec-first; it just doesn’t have the traffic to justify the overhead yet.” — frase que comunica em uma sentença que o nível de rigor é uma escolha deliberada, não um acidente.

O que vem a seguir

Depois de escolher o nível de rigor certo para o contexto, o próximo passo prático é começar a primeira fase do ciclo SDD: escrever a spec em si. Isso significa decidir o que entra nela — outcomes desejados, constraints técnicas e de negócio, o que fica de fora explicitamente — antes de qualquer linha de código. Ver 04 - Fase Specify — definindo outcomes e constraints para como estruturar essa primeira fase na prática.

Veja também

Referências