Padrões de Design
Fluxo de TrabalhoAvançado

Engenharia de Specs

Como escrever Live Specs eficazes que produzam altas Spec-to-Code Ratios e minimizem a intervenção do agente.

Visão Geral

Engenharia de Specs é a disciplina de escrever documentos Live Spec que agentes podem executar com intervenção mínima. Uma spec bem projetada produz uma alta Spec To Code Ratio — a saída do agente segue fielmente a especificação em vez de improvisar. Uma spec mal projetada produz alucinações, casos de borda ignorados e loops, independentemente de quão capaz o modelo seja.

Este padrão fornece uma metodologia estruturada para a criação de specs. Ele move as equipes de "escrever alguns requisitos e esperar que o agente entenda" para um processo repetível: começar por critérios de aceitação executáveis, decompor em comportamentos testáveis, anexar Golden Samples e restrições arquiteturais, e iterar com base em resultados mensurados. O Context Architect é o responsável por este processo, mas cada engenheiro que escreve specs se beneficia da metodologia.

A engenharia de specs é a atividade de maior alavancagem em um fluxo de trabalho de desenvolvimento agentic. Um investimento de 30 minutos em uma spec precisa economiza horas de tentativas do agente, escalonamentos de Rescue Mission e correção humana. Equipes que medem a Spec To Code Ratio descobrem consistentemente que a qualidade da spec — não a seleção do modelo, nem truques de engenharia de prompt — é o fator dominante na qualidade da saída do agente.

Problema

A maioria das equipes escreve specs que são legíveis por humanos, mas ambíguas para agentes:

  • Requisitos densos em texto. As specs descrevem o que a funcionalidade deve fazer em forma de narrativa. Um leitor humano infere os detalhes não declarados a partir da experiência. Um agente não possui essa inferência — ou ele inventa os detalhes (alucinação) ou faz perguntas esclarecedoras (atrasos).

  • Critérios de aceitação não testáveis. Critérios como "o componente deve lidar com erros de forma graciosa" ou "a API deve ser performática" não podem ser validados por um Eval Harness. O agente não tem como verificar sua própria saída em relação a esses critérios, e o portão automatizado também não.

  • Condições de contorno ausentes. As specs descrevem o caminho feliz, mas omitem o tratamento de erros, estados vazios, acesso concorrente, casos de borda com caracteres especiais e valores de limite. Os agentes ignoram esses casos ou inventam um tratamento que não corresponde às expectativas da equipe.

  • Conhecimento arquitetural implícito. A spec diz "criar um novo serviço", mas não especifica qual padrão de camada de serviço seguir, em qual diretório colocar os arquivos, quais convenções de nomenclatura usar ou quais dependências são permitidas. O agente faz escolhas que podem violar regras arquiteturais não capturadas na spec.

  • Sem loop de feedback. As equipes não medem a qualidade das specs de forma sistemática. Uma spec que causou três rescue missions parece idêntica no backlog a uma spec que o agente acertou na primeira tentativa. Sem os dados de Spec To Code Ratio e Correction Ratio vinculados a specs individuais, não há sinal para melhoria.

Solução

Aplique uma metodologia de engenharia de specs de seis etapas que produz especificações legíveis por máquina, testáveis e independentes.

As Seis Etapas

  1. Comece com os critérios de aceitação — Escreva condições executáveis e testáveis antes de qualquer outra coisa.
  2. Escreva o contrato comportamental — Defina entradas, saídas, casos de borda e tratamento de erros.
  3. Defina a referência da constituição do sistema — Crie links para padrões de codificação, restrições arquiteturais e regras de segurança.
  4. Decomponha em um mapa de tarefas acionáveis — Divida a spec em subtarefas ordenadas que o agente possa executar sequencialmente.
  5. Anexe Golden Samples e referências de contexto — Forneça exemplos concretos da qualidade de saída esperada.
  6. Revise e valide antes da execução do agente — Trate as specs como código: revise-as, versione-as e teste-as.

Implementação

1

Exemplos de Código

Spec Quality Scoring
// scripts/score-spec.ts
interface SpecQualityScore {
  acceptanceCriteriaScore: number;   // 0-25
  behavioralContractScore: number;   // 0-25
  contextCompletenessScore: number;  // 0-25
  taskDecompositionScore: number;    // 0-25
  total: number;                     // 0-100
  grade: "A" | "B" | "C" | "D" | "F";
  suggestions: string[];
}

function scoreSpec(specContent: string): SpecQualityScore {
  const suggestions: string[] = [];

  // Score acceptance criteria
  let acScore = 0;
  const acTable = specContent.match(
    /\| AC-\d+.*\|/g
  );
  if (acTable && acTable.length > 0) {
    acScore += 10; // Has structured ACs
    if (acTable.every((row) => row.includes("-test") || row.includes("-check"))) {
      acScore += 10; // All ACs have validation methods
    } else {
      suggestions.push(
        "Some acceptance criteria lack validation methods"
      );
    }
    if (acTable.length >= 5) {
      acScore += 5; // Sufficient coverage
    } else {
      suggestions.push(
        "Consider adding more acceptance criteria for edge cases"
      );
    }
  } else {
    suggestions.push(
      "Add structured acceptance criteria with IDs and validation methods"
    );
  }

  // Score behavioral contract
  let bcScore = 0;
  if (specContent.includes("**Inputs:**")) bcScore += 5;
  else suggestions.push("Add an Inputs table to the behavioral contract");
  if (specContent.includes("**Outputs (success):**")) bcScore += 5;
  else suggestions.push("Add a success Outputs table");
  if (specContent.includes("**Outputs (error):**")) bcScore += 5;
  else suggestions.push("Add an error Outputs table");
  if (specContent.includes("**Behavior — Normal Flow:**")) bcScore += 5;
  else suggestions.push("Add normal flow behavior description");
  if (specContent.includes("**Behavior — Error Flow:**")) bcScore += 5;
  else suggestions.push("Add error flow behavior description");

  // Score context completeness
  let ctxScore = 0;
  if (specContent.includes("## System Constitution")) ctxScore += 5;
  else suggestions.push("Add System Constitution reference");
  if (specContent.includes("Golden Sample")) ctxScore += 10;
  else suggestions.push("Add golden sample references");
  if (specContent.includes("Context Packet")) ctxScore += 5;
  else suggestions.push("Add context packet file listing");
  if (specContent.includes("token") || specContent.includes("budget"))
    ctxScore += 5;
  else suggestions.push("Add token budget estimate");

  // Score task decomposition
  let tdScore = 0;
  const taskMatches = specContent.match(/### Task \d+/g);
  if (taskMatches && taskMatches.length > 0) {
    tdScore += 10;
    if (specContent.includes("**Dependencies:**")) tdScore += 5;
    if (specContent.includes("**Validates:**")) tdScore += 5;
    if (specContent.includes("**Golden Sample:**")) tdScore += 5;
  } else {
    suggestions.push("Decompose spec into ordered subtasks with dependencies");
  }

  const total = acScore + bcScore + ctxScore + tdScore;
  const grade =
    total >= 85
      ? "A"
      : total >= 70
        ? "B"
        : total >= 55
          ? "C"
          : total >= 40
            ? "D"
            : "F";

  return {
    acceptanceCriteriaScore: acScore,
    behavioralContractScore: bcScore,
    contextCompletenessScore: ctxScore,
    taskDecompositionScore: tdScore,
    total,
    grade,
    suggestions,
  };
}
Before and After Spec Comparison
# BEFORE: Vague spec that causes agent failures
# ------------------------------------------------
feature: User Authentication
description: Add login functionality
requirements:
  - Users can log in with email and password
  - Show error on invalid credentials
  - Use JWT for sessions
notes: Follow existing patterns

# AFTER: Engineered spec that agents execute reliably
# ------------------------------------------------
feature: User Authentication — Login Endpoint
spec_version: 1
status: ready
author: "@context-architect"

behavioral_contract:
  purpose: "Authenticate user by email/password, return signed JWT"
  inputs:
    - name: email
      type: string
      constraints: "RFC 5322 email format"
      required: true
    - name: password
      type: string
      constraints: "8-128 characters"
      required: true
  outputs_success:
    - name: token
      type: string
      description: "RS256-signed JWT, 24h expiry, contains userId/email/role"
    - name: user
      type: object
      description: "{ id: string, email: string, role: string }"
  outputs_error:
    - status: 401
      code: AUTH_INVALID_CREDENTIALS
      when: "Email exists but password does not match"
    - status: 401
      code: AUTH_USER_NOT_FOUND
      when: "No user with provided email"
    - status: 429
      code: AUTH_RATE_LIMITED
      when: "5+ failures from same IP in 15 minutes"
    - status: 400
      code: AUTH_INVALID_INPUT
      when: "Email or password fails format validation"

acceptance_criteria:
  - id: AC-1
    criterion: "Returns 200 with JWT on valid credentials"
    validation: integration-test
    priority: must-have
  - id: AC-2
    criterion: "Returns 401 AUTH_INVALID_CREDENTIALS on wrong password"
    validation: integration-test
    priority: must-have
  - id: AC-3
    criterion: "Returns 429 after 5 failed attempts from same IP in 15min"
    validation: integration-test
    priority: must-have
  - id: AC-4
    criterion: "JWT uses RS256, contains userId/email/role, 24h expiry"
    validation: unit-test
    priority: must-have
  - id: AC-5
    criterion: "bcrypt timing-safe comparison for passwords"
    validation: unit-test
    priority: must-have

system_constitution_ref: "context/constitution/coding-standards.md"
golden_samples:
  - path: "src/users/services/user-service.ts"
    demonstrates: "Service pattern, error handling"
  - path: "src/users/__tests__/user-service.test.ts"
    demonstrates: "Test structure, mocking"

context_packet:
  - "prisma/schema.prisma"
  - "src/shared/errors/app-error.ts"
  - "docs/api/auth-spec.yaml"

task_map:
  - id: 1
    name: "Input validation schema"
    deliverable: "src/auth/schemas/login-schema.ts"
    validates: [AC-4]
    dependencies: []
  - id: 2
    name: "Auth service login method"
    deliverable: "src/auth/services/auth-service.ts"
    validates: [AC-1, AC-2, AC-3, AC-4, AC-5]
    dependencies: [1]
  - id: 3
    name: "Auth controller login endpoint"
    deliverable: "src/auth/controllers/auth-controller.ts"
    validates: [AC-1, AC-2, AC-3]
    dependencies: [2]
  - id: 4
    name: "Rate limiting middleware"
    deliverable: "src/auth/middleware/rate-limiter.ts"
    validates: [AC-3]
    dependencies: []
  - id: 5
    name: "Tests for all acceptance criteria"
    deliverable: "src/auth/__tests__/"
    validates: [AC-1, AC-2, AC-3, AC-4, AC-5]
    dependencies: [1, 2, 3, 4]

token_budget: 12000

Considerações

Benefícios
  • **Higher Spec-to-Code Ratio.** Engineered specs leave less room for agent improvisation. When the spec defines inputs, outputs, error cases, and task decomposition, the agent follows the specification rather than guessing. Teams that adopt this methodology typically see [[spec-to-code-ratio]] increase from 50-60% to 80-90%.
  • **Fewer rescue missions.** The most common [[rescue-mission]] root cause is "ambiguous spec" (~40% of rescues). Engineered specs with testable acceptance criteria and explicit boundary conditions eliminate most of these. The [[correction-ratio]] drops because the agent gets it right on the first attempt.
  • **Specs become institutional knowledge.** A well-engineered spec is not a throwaway document — it is a reusable reference. When a similar feature needs to be built in the future, the team can adapt an existing spec rather than starting from scratch. The spec library grows into a valuable asset.
  • **Measurable quality improvement.** By tying [[spec-to-code-ratio]] and [[correction-ratio]] back to individual specs, teams can identify which spec patterns work and which do not. This creates a data-driven feedback loop for continuous improvement.
  • **Reduced onboarding time for new engineers.** A library of well-engineered specs teaches new team members how the codebase works, what patterns to follow, and what quality looks like. The specs are living documentation of the team's engineering standards.
Desafios
  • **Initial slowdown perception.** Engineers accustomed to jumping straight into code perceive spec writing as overhead. The response is data: show that a 30-minute spec investment saves 2-3 hours of agent retries and human correction. Track the numbers to make the case.
  • **Spec maintenance as code evolves.** Specs that reference specific file paths, database schemas, or API contracts become stale as the codebase changes. Include spec staleness checks in the monthly Context Hygiene ceremony. Flag specs where referenced files have changed since the spec was last updated.
  • **Translation gap between business and technical language.** Product managers write requirements in business language. [[context-architect]] roles translate these into technical specs. The translation step introduces potential information loss. Pair the [[context-architect]] with the product manager during spec authoring to minimize gaps.
  • **Over-engineering specs for simple tasks.** Not every task needs a full six-step spec. A simple CRUD endpoint following an existing pattern may need only acceptance criteria and a golden sample reference. Scale the spec effort to the task complexity — use the routing matrix from [[agent-task-routing]] to determine how thorough the spec needs to be.
  • **Resistance to peer review of specs.** Engineers may view spec review as bureaucratic overhead. Frame it as the highest-leverage review activity: 15 minutes of spec review prevents hours of wasted agent execution. Start with lightweight reviews (a quick read-through) and formalize only for high-complexity tasks.