Fase Specify — definindo outcomes e constraints

TL;DR

Specify é a primeira fase do pipeline SDD: descrever o que vai ser construído e por quê, sem tocar em como. Foco em outcomes (o resultado que valida sucesso) e constraints (o que não pode ser violado). Em 2026, o padrão de facto é markdown estruturado, legível por humano e por LLM, versionado no repositório. GitHub Spec Kit, Kiro e OpenSpec convergiram em um formato semelhante: user journeys + acceptance criteria + non-functional requirements. Uma spec boa elimina a ambiguidade antes de gastar tokens gerando código.

A regra fundamental

Specify responde “o quê” e “por quê”. Nunca “como”.

Essa regra parece simples e é violada constantemente. O “como” é mais confortável para engenheiros — é o que sabemos fazer. Especificar o “quê” de forma precisa sem cair no “como” é a habilidade central que Specify exige.

NívelPergunta centralOnde mora
SpecifyO quê? Por quê? Para quem?specs/
PlanComo (arquitetura)? Com quê (stack)?plan/
TasksEm que ordem? Que unidades atômicas?tasks/
ImplementEm código concreto?src/

Misturar “como” em Specify é o erro mais comum. Quando aparece “vamos usar Postgres com índice em user_id” ou “implementar com padrão Repository”, isso é Plan, não Specify. Remova e coloque no lugar certo.

Por que a separação importa

Se você misturar “o quê” com “como” na spec, o agente vai tratar a decisão de implementação como requisito. Quando você quiser mudar de Postgres para DynamoDB, vai parecer que está violando a spec — quando, na verdade, está exercendo uma decisão de implementação legítima.

Por que Specify é a fase mais crítica

Uma spec ruim não é um problema que você resolve na implementação. É um multiplicador de erro: código errado gerado em alta velocidade, testes validando o comportamento errado, débito que escala antes de ser detectado.

A analogia mais precisa: spec é o plano de navegação. Se você partir com o destino errado, velocidade maior te leva mais rápido ao lugar errado. O “destino” no SDD é o outcome — e ele deve estar explícito e correto antes da primeira linha de código.

Em termos concretos: um bug na spec descoberto na fase Specify custa minutos para corrigir (editar um markdown). O mesmo bug descoberto na fase Implement custa horas (reescrever código). Descoberto em produção, custa incidentes, reputação e dados de usuários.

xychart-beta
    title "Custo de corrigir um erro por fase (relativo)"
    x-axis ["Specify", "Plan", "Tasks", "Implement", "Produção"]
    y-axis "Custo relativo" 0 --> 100
    bar [1, 5, 10, 25, 100]

Invest na spec é o melhor ROI do processo.

Anatomia de uma spec completa

O template canônico convergiu em 2025-2026 entre as principais ferramentas:

# Feature: [Nome da feature]
 
## Contexto e objetivo
[Por que estamos construindo isso? Qual o problema de negócio que resolve?]
 
## Outcome
[Definição de sucesso em 1-3 frases. O que deve ser verdadeiro quando isso estiver pronto?]
 
## Usuários e personas
[Quem usa essa feature? Qual o contexto deles?]
 
## User journeys
 
### J1 — [Nome do journey principal]
1. [Passo 1 da perspectiva do usuário]
2. [Passo 2]
...
 
### J2 — [Nome do journey alternativo ou edge case]
...
 
## Acceptance criteria
 
- [ ] [Critério verificável 1]
- [ ] [Critério verificável 2]
...
 
## Non-functional requirements
 
- Latência: [número concreto, não "rápido"]
- Disponibilidade: [SLA]
- Segurança: [constraint explícita]
- Compliance: [regulação aplicável]
 
## Out of scope (explícito)
 
- [O que NÃO será feito nesta feature]
- [Features relacionadas que ficam para depois]
 
## Open questions
 
- [Dúvida que precisa de resposta antes de implementar]
- [Decisão de negócio pendente]
 
## Dependências
 
- [Outras features ou sistemas dos quais isso depende]

Exemplo completo: Refund de pagamentos

Um exemplo concreto aplica o template e mostra as decisões em cada seção:

# Feature: Refund de pagamentos
 
## Contexto e objetivo
Clientes que solicitam cancelamento de pedido precisam de um processo claro
para reembolso. Atualmente, o suporte recebe os pedidos por email e o processo
é manual, causando SLA inconsistente e insatisfação.
 
## Outcome
Cliente que solicita refund deve receber confirmação em até 24h
e crédito processado em até 5 dias úteis, com visibilidade do status
em tempo real no app.
 
## Usuários e personas
- **Cliente final** — fez uma compra, quer reembolso por produto não entregue
  ou arrependimento em até 7 dias.
- **Analista de suporte** — aprova refunds parciais ou casos fora do prazo.
 
## User journeys
 
### J1 — Refund total dentro de 7 dias (automático)
1. Cliente abre app → Histórico de pagamentos
2. Seleciona pagamento dos últimos 7 dias
3. Clica em "Solicitar reembolso" → escolhe tipo: total
4. Confirma motivo (dropdown: arrependimento / produto com defeito / etc.)
5. Sistema cria refund automaticamente + envia email com ID e prazo
6. Em até 5 dias úteis: crédito no método original
7. App mostra status em tempo real: pendente → processando → concluído
 
### J2 — Refund parcial após 7 dias (requer aprovação)
1. Cliente solicita refund após 7 dias
2. Sistema cria solicitação com status "aguardando aprovação"
3. Analista recebe notificação e avalia
4. Aprovação → mesmo fluxo de J1; recusa → notificação ao cliente com motivo
 
## Acceptance criteria
 
- [ ] Cliente vê apenas pagamentos elegíveis (últimos 30 dias, não cancelados)
- [ ] Refund total possível para pagamentos ≤ 7 dias sem aprovação
- [ ] Refund parcial OU pagamentos > 7 dias exigem aprovação do analista
- [ ] Email de confirmação: enviado em < 5 minutos com ID de transação e prazo
- [ ] Estado do refund visível no histórico com atualização em tempo real
- [ ] Notificação push quando status muda (push + email)
- [ ] Refund duplicado bloqueado (idempotência por order_id + type)
- [ ] Log de auditoria imutável para cada evento de refund
 
## Non-functional requirements
 
- Latência p95 da requisição de criação: < 500ms
- Idempotência: operação repetida com mesmo order_id deve retornar o mesmo resultado
- Auditabilidade: todo evento de refund registrado por 7 anos (compliance PCI DSS)
- Disponibilidade: 99.9% (refund é crítico para satisfação do cliente)
 
## Out of scope
 
- Refund em método diferente do original (ex: cashback quando pagou cartão)
  → será spec separada se necessário
- Refund de pedidos com mais de 90 dias → não suportado, retornar erro claro
- Interface administrativa completa → analista usa endpoint de API nesta iteração
 
## Open questions
 
- Como tratar refund quando o cartão original foi cancelado?
  → Aguardando resposta do time financeiro antes de implementar
- O prazo de 5 dias úteis é o mesmo para crédito e débito?
  → Confirmar com compliance antes da Fase Plan
 
## Dependências
 
- Sistema de pagamentos (Stripe) — API de refunds
- Sistema de notificações — email + push
- Feature "Histórico de pagamentos" (já existe — verificar contratos)

Os 6 elementos canônicos

ElementoFunçãoErro mais comum
OutcomeDefinir sucesso em 1-3 frasesConfundir outcome com lista de features
User journeysComo o usuário interage do início ao fimPular para componentes técnicos
Acceptance criteriaLista binária, verificável, exaustivaCritério vago (“deve ser rápido”)
Non-functional requirementsPerformance, segurança, complianceEsquecer — vira surpresa em prod
Out of scopeLimites explícitos do que não vai ser feitoNão declarar — agente decide sozinho
Open questionsO que ainda não foi decididoFingir certeza onde não há

O out-of-scope merece atenção especial: quando um agente recebe uma spec sem limites explícitos, ele preenche o que falta com inferências plausíveis. Às vezes certo; frequentemente além do escopo. “Out of scope” é o fence que impede expansão não-planejada.

Spec sem "out of scope" declarado é convite ao scope creep silencioso

Se a seção “Out of scope” está vazia ou ausente, o agente não tem sinal de onde parar. Ele não pergunta “isso está dentro do escopo?” — ele infere, e a inferência tende a ser generosa demais. O sintoma aparece só depois: a feature “cresceu” para incluir coisas que ninguém pediu, e ninguém consegue apontar onde a decisão foi tomada. Declarar explicitamente o que fica de fora é tão importante quanto declarar o que entra.

Open question sem resposta vira decisão tomada por default

Uma pergunta listada em “Open questions” mas nunca respondida não trava a implementação — ela apenas desaparece. O agente (ou o engenheiro apressado) escolhe a interpretação mais conveniente e segue. Se a pergunta era sobre um caso de borda regulatório ou financeiro, essa “decisão por omissão” pode ser exatamente o tipo de erro que a Métrica de qualidade acima (open questions sem resposta ao entrar em Plan) existe para capturar. Zero open questions pendentes é o alvo — não “resolvemos a maioria”.

O que “outcome” realmente significa

“Outcome” não é sinônimo de “feature” ou “funcionalidade”. A distinção:

  • Feature (output): “Sistema de refund com aprovação manual”
  • Outcome (resultado): “Cliente que solicita refund recebe crédito em 5 dias úteis com visibilidade em tempo real”

A feature é o que você constrói. O outcome é o que muda para o usuário. Features podem ser entregues sem o outcome ser atingido (sistema existe mas é inutilizável). Outcomes são o critério real de sucesso.

Algumas features têm outcomes óbvios; outras precisam de investigação para descobrir o outcome real. A pergunta certa é: “Se eu entregar isso e o usuário não conseguir fazer X, foi um sucesso?” O que completa X é o outcome.

Acceptance criteria: a arte de ser verificável

O critério mais importante para um acceptance criteria (AC) é verificabilidade: você consegue escrever um teste automático para isso? Se não, provavelmente está vago.

AC vagoAC verificável
”Sistema deve ser rápido""p95 de latência < 200ms em carga normal"
"Interface amigável""Usuário conclui checkout em ≤ 5 cliques"
"Email de confirmação enviado""Email chega em < 5 minutos após confirmação"
"Dados seguros""PII criptografado em repouso com AES-256"
"Erro tratado corretamente""Pagamento duplicado retorna HTTP 409 com mensagem X”

ACs vagos parecem inofensivos mas criam interpretação aberta. Dois engenheiros podem ler “rápido” e implementar soluções radicalmente diferentes. A spec que não resolve a ambiguidade não está fazendo seu trabalho.

A regra de ouro: cada AC deve ter uma resposta binária (atende / não atende), não uma escala subjetiva.

Non-functional requirements: o que matou o sistema em prod

NFRs são os requisitos que “ninguém pediu explicitamente” mas que todo mundo esperava. Não documentá-los é uma das fontes mais comuns de incidente em produção.

As categorias que nunca devem faltar:

mindmap
  root((NFRs))
    Performance
      Latência p95/p99
      Throughput máximo
      Tempo de resposta em carga
    Confiabilidade
      SLA de disponibilidade
      Tolerância a falha
      Recovery time objetivo
    Segurança
      Autenticação/autorização
      Criptografia em repouso/trânsito
      Sanitização de inputs
    Compliance
      Retenção de dados
      Auditabilidade
      Regulações aplicáveis
    Escalabilidade
      Volume esperado de usuários
      Crescimento projetado

A pergunta que revela NFRs ausentes: “Se isso fosse para produção amanhã com 10x o volume esperado, o que quebraria?” As respostas são NFRs que você esqueceu de escrever.

Linguagem natural estruturada

A spec deve ser simultaneamente legível por humanos e consumível por LLMs como contexto. Isso define algumas características de estilo:

Faça:

  • Frases declarativas curtas: “Sistema faz X dado Y”
  • Números concretos: ”< 500ms”, “em 24 horas”, “máximo 3 tentativas”
  • Listas e checklists (LLMs processam bem)
  • Estrutura consistente (headers, seções, templates)

Evite:

  • Prosa livre e longa (difícil de parsear para AC específico)
  • Jargão de implementação (mistura com Plan)
  • Subjetivos sem medida: “boa performance”, “interface intuitiva”
  • Tempo futuro ambíguo: “vai precisar”, “eventualmente suportar”

Teste do "explica para outro engenheiro"

Se você lesse essa spec sem ter participado da discussão, conseguiria implementar uma versão do que se espera? Se houvesse ≥ 2 implementações plausíveis e contraditórias, a spec ainda está vaga.

Como LLMs ajudam e atrapalham na fase Specify

Onde LLMs ajudam genuinamente:

  • Transformar bullet points soltos em spec estruturada
  • Detectar ambiguidade (“isso tem duas interpretações possíveis”)
  • Sugerir edge cases que passariam despercebidos
  • Converter linguagem de negócio em ACs verificáveis
  • Revisar completude (identificar seções ausentes)

Onde LLMs introduzem problemas:

  • Inventam ACs razoáveis que não foram validados pelo PM ou stakeholder
  • Saltam para decisões de Plan (adicionam stack, libs, padrões)
  • Adicionam funcionalidades não pedidas (scope creep silencioso)
  • Usam templates verbosos que aumentam tokens sem aumentar clareza
  • Confundem “plausível” com “correto para este domínio”

Spec gerada por IA precisa de revisão humana mais cuidadosa do que código

Se a spec está errada, todo o resto cai em cascata. Tempo investido em revisar a spec é o melhor ROI do projeto. Um PM que lê a spec em 20 minutos pode poupar 3 sprints de retrabalho.

Anti-patterns frequentes

Anti-patternO que aconteceCorreção
Spec verbosa (10+ páginas)Ninguém lê; agente perde contextoMáximo 2-3 páginas; use links para contexto extra
Sem acceptance criteriaAgente decide o que “funcionar” significaAC binário para cada outcome
Sem out-of-scopeAgente expande feature além do planejadoDeclarar explicitamente o que NÃO entra
Open questions não documentadasDecisão tomada pelo agente silenciosamenteListar e resolver antes de implementar
Spec stale após 1 sprintContexto do agente desatualizadoAtualizar spec no mesmo PR do código
Spec em Confluence/NotionNão é versionada com o códigoMover para /specs/ no repositório
AC subjetivoInterpretações divergentes entre dev e PMReescrever com números, prazos, comportamentos observáveis
”Como” misturado com “o quê”Decisões de implementação viram requisitoMover tudo que é “como” para Plan

Spec como comunicação: o problema do PM-Engenheiro-Agente

Spec resolve um problema de comunicação de três vias: PM sabe o que o negócio precisa, engenheiro sabe como construir, agente executa. Sem um artefato compartilhado e formal, a mensagem muda em cada handoff.

graph LR
    PM["🧑‍💼 PM<br/>'Preciso de refund'"] -->|"sem spec"| Eng
    Eng["👩‍💻 Engenheiro<br/>'Entendi, farei um sistema'"] -->|"sem spec"| Agente
    Agente["🤖 Agente<br/>'Implementei conforme entendi'"] -->|"resultado"| PM2
    PM2["🧑‍💼 PM<br/>'Isso não é o que pedi'"]
graph LR
    PM["🧑‍💼 PM"] -->|"escreve spec"| Spec
    Spec["📐 Spec"] -->|"alinhamento"| Eng
    Eng["👩‍💻 Engenheiro"] -->|"revisa spec"| Spec
    Spec -->|"contexto"| Agente
    Agente["🤖 Agente"] -->|"valida contra spec"| Done
    Done["✅ Done<br/>(alinhado com PM)"]

A spec é o canal de comunicação sem distorção. PM lê spec e confirma: “é isso”. Agente lê spec e sabe: “é isso que devo produzir”. Engenheiro revisa spec e verifica: “isso é implementável e seguro”.

Machine-readable specs: o próximo nível

Em spec-as-source, a spec é parcialmente estruturada para máquina:

# specs/payments/refund.spec.yml
version: "1.0"
feature: refund_payment
outcome: |
  Cliente que solicita refund recebe confirmação em <24h
  e crédito processado em <5 dias úteis.
 
acceptance_criteria:
  - id: AC1
    description: Refund total dentro de 7 dias
    given: "payment_age <= 7d AND payment.status == completed"
    when: "customer.requests_refund(type=full)"
    then: "refund.created AND email.sent(< 5min) AND status=pending"
 
  - id: AC2
    description: Refund parcial requer aprovação
    given: "payment_age > 7d OR refund_type == partial"
    when: "customer.requests_refund"
    then: "approval_request.created AND status=awaiting_approval"
 
nfr:
  latency:
    p95_ms: 500
  idempotency: required
  audit_retention_years: 7
  availability_sla: "99.9%"

Vantagem: AC pode ser input direto para gerador de testes. Custo: requer linguagem formal, learning curve, e disciplina de manutenção mais rigorosa. Adequado para nível spec-as-source.

Métricas de qualidade para Specify

MétricaAlvoSinal de problema
% de PRs que aderem a 100% dos ACs> 85%Spec vaga ou ACs mal definidos
Tamanho médio da spec1-3 páginas (≤ 2K tokens)Spec verbosa = ninguém lê
Tempo entre spec e aprovação< 2 diasSpec incompleta → ciclos de revisão
Frequência de “volta para Specify” durante ImplementBaixaAlta = spec incompleta saiu sem revisão
Open questions sem resposta ao entrar em PlanZeroBloqueio durante implementação

O que vem a seguir

Uma spec completa — com outcome, journeys, ACs verificáveis, NFRs e out-of-scope declarado — é o insumo da próxima fase. Mas Specify só responde “o quê” e “por quê”; é hora de decidir “como”. Isso é o assunto de 05 - Fase Design e Plan — arquitetura e decomposição: como a spec vira arquitetura, decisões de stack e decomposição em unidades implementáveis, sem violar os limites que acabamos de declarar aqui.

Veja também

Referências

  • GitHub Spec Kitspec-driven.md (2026). Template canônico de spec para AI coding.
  • Augment CodeWhat Is Spec-Driven Development? (2026). Definição da fase Specify.
  • Microsoft for DevelopersDiving Into Spec-Driven Development With GitHub Spec Kit (2026).
  • Zencoder DocsA Practical Guide to Spec-Driven Development (2026). Exemplos práticos de specs.
  • DeepLearning.AISpec-Driven Development with Coding Agents (abr 2026). Curso com exemplos de spec por fase.
  • Cohn, M.User Stories Applied (2004). Fundamentos de user stories como precursor do formato de journeys.
  • North, D.Introducing Behaviour-Driven Development (2006). Given/When/Then como padrão de AC verificável.
  • Robertson, S.; Robertson, J.Mastering the Requirements Process (2012). Framework de requisitos que influencia o formato de spec SDD.
  • Adzic, G.Specification by Example (2011). Especificação com exemplos executáveis como precursor direto de SDD.
  • Humble, J.; Farley, D.Continuous Delivery (2010). NFRs como critérios de deployment — influência no formato de non-functional requirements.