← Todos los artículos EN

Spec-Driven Development: escribe el plano antes de construir

La calidad del código generado por IA está acotada por la calidad de tu especificación. Esta es la práctica que cambió cómo uso las herramientas de IA en ingeniería de producción.

Hay un patrón que he observado en equipos de ingeniería que adoptan herramientas de IA para código: ganancias iniciales de productividad, seguidas de una meseta, seguidas de una vaga frustración de que las herramientas “no entienden realmente” el codebase.

El diagnóstico suele estar equivocado. Las herramientas no están fallando en entender el codebase. Están fallando en entender las restricciones que no están en el codebase — las reglas de negocio, las decisiones arquitectónicas, las cosas que se decidieron antes de que se escribiera una línea de código y que nunca se codificaron en ningún lugar que una máquina pueda leer.

El Spec-Driven Development es la práctica de codificar esas restricciones antes de pedirle a las herramientas de IA — o a otros ingenieros — que las implementen.

Qué es y qué no es una spec

Una spec no es un documento de requisitos. Los requisitos describen qué debe hacer un sistema desde la perspectiva del usuario. Una spec describe cómo debe verse una implementación desde la perspectiva de la ingeniería.

Una spec incluye:

  • Modelos de datos con tipos y restricciones
  • Contratos de API (entradas, salidas, casos de error)
  • Invariantes de comportamiento — cosas que siempre deben ser verdad
  • Qué está explícitamente fuera de alcance
  • La decisión tomada cuando había múltiples opciones válidas

Una spec se escribe antes de la implementación. No como parte de ella — antes. Esta es la disciplina que la mayoría de los equipos omite, y es la que hace las herramientas de IA significativamente más útiles.

Un ejemplo real

Aquí hay una spec que escribí antes de implementar un servicio de envío de solicitudes de préstamo:

# LoanApplicationSubmissionService

## Responsabilidad
Valida una solicitud de préstamo completada y la envía a la API de core bancario.
NO maneja solicitudes parciales o en estado borrador — eso es ApplicationDraftService.

## Input
SolicitudPrestamo: {
  solicitanteId: string (UUID)
  codigoProducto: string (del enum PRODUCTO_PRESTAMO)
  montoSolicitado: number (positivo, máx 50_000_000 CLP)
  plazoMeses: number (12 | 24 | 36 | 48 | 60)
  perfilSolicitante: PerfilSolicitante (ver schemas/solicitante.ts)
}

## Orden de validación
1. Validación de schema con SolicitudPrestamoSchema (Zod)
2. Validación de reglas de negocio:
   - Solicitante debe tener 18+ y < 75 años
   - montoSolicitado no debe superar 5x el ingreso mensual
   - Sin solicitudes activas en los últimos 90 días
3. Verificación de elegibilidad del producto vía ProductEligibilityService

## Output
Éxito: { submissionId: string, fechaDecisionEstimada: string (ISO 8601) }
Error: { code: ApplicationErrorCode, message: string, field?: string }

## Códigos de error
VALIDATION_FAILED — error de validación de schema (incluir nombre del campo)
BUSINESS_RULE_VIOLATION — regla de negocio fallida (incluir id de regla)
PRODUCT_INELIGIBLE — el solicitante no califica para este producto
CORE_API_UNAVAILABLE — error del servicio upstream (no reintentar en esta capa)

## Invariantes
- Nunca confirmar en la base de datos antes de que responda la API de core
- Registrar cada intento de envío con input completo (sanitizado) y resultado
- No exponer detalles de errores de la API de core al caller

## Fuera de alcance
- Guardado de borradores
- Recolección de documentos
- Notificación de decisión

Cuando le entregué esta spec a Claude Code con “implementa este servicio en TypeScript, siguiendo la arquitectura en src/application/”, el output fue inmediatamente usable. No perfecto — el manejo de errores necesitó ajustes y una invariante se implementó incorrectamente — pero la estructura era correcta, los tipos eran correctos, y la revisión fue rápida porque tenía una especificación clara contra la cual revisar.

Sin la spec, el mismo prompt produce código que funciona en el happy path y no tiene una estrategia coherente de manejo de errores, porque el manejo de errores requiere saber qué errores importan y por qué.

Escribir specs para consumo de IA

Las specs escritas para ingenieros humanos pueden ser imprecisas porque los humanos llenan los vacíos con contexto compartido. Las specs para herramientas de IA necesitan ser explícitas sobre cosas que parecen obvias.

Enumera los casos de error. Los humanos infieren “y maneja los errores apropiadamente.” Las herramientas de IA implementan el primer patrón de manejo de errores en sus datos de entrenamiento que parece relevante. Si quieres códigos de error específicos con semántica específica, escríbelos.

Especifica el orden de las operaciones. “Valida, luego verifica la elegibilidad, luego llama a la API” parece obvio en la spec anterior. Sin el orden, la implementación podría verificar la elegibilidad antes de validar el input — mensajes de error diferentes, comportamiento diferente bajo input inválido.

Declara explícitamente qué está fuera de alcance. Si el servicio no debe manejar el estado borrador, dilo. De lo contrario la implementación podría agregar un parámetro esBorrador porque parece una extensión natural.

Incluye invariantes. Las invariantes son las cosas que deben permanecer verdaderas independientemente del input. Raramente se codifican en los requisitos, frecuentemente se omiten en la implementación, y son costosas de descubrir en producción.

La capa del CLAUDE.md

Las specs cubren implementaciones individuales. CLAUDE.md cubre el contexto a nivel de proyecto que aplica en todas las implementaciones: patrones de arquitectura, convenciones, qué evitar.

Los dos trabajan juntos. CLAUDE.md provee contexto ambiental (“usamos Zod para validación, no usamos any”); la spec provee contexto específico de la implementación (“valida en este orden, devuelve estos códigos de error”).

Un flujo de trabajo que he encontrado efectivo:

  1. Escribir la spec en un directorio specs/ antes de tocar el código
  2. Referenciarla en el prompt: “implementa el servicio descrito en specs/loan-submission.md
  3. Revisar el output contra la spec, no contra tu modelo mental de lo que querías
  4. Si el output se desvía, actualiza la spec para ser más precisa, luego regenera

El paso 3 es la parte crucial. Revisar contra una spec escrita es más rápido y confiable que revisar contra tu memoria de la intención. La spec externaliza la intención — que es donde debería estar.

El efecto compuesto

Las specs no solo hacen la primera implementación más rápida. Hacen cada cambio posterior más rápido.

Cuando los requisitos cambian seis meses después, lees la spec primero. Entiendes contra qué estaba protegiendo la implementación. Actualizas la spec para reflejar las nuevas restricciones. Luego implementas el cambio — o le pides a Claude Code que lo implemente — contra una especificación actualizada y precisa.

Sin spec, cada cambio requiere reverse-engineering de la intención desde el código. Lees la implementación, intentas inferir por qué está estructurada como lo está, haces suposiciones, y a veces te equivocas.

Lo que esto cuesta

Escribir una spec toma tiempo. Para un servicio de complejidad moderada, quizás dos horas. Esas son dos horas no escritas en código.

El retorno: una implementación revisable en treinta minutos en vez de dos horas, con un documento que sirve como el ADR de por qué la implementación se ve como se ve.

Para sistemas donde la corrección importa — servicios financieros, cualquier cosa con requisitos de compliance, cualquier cosa que sea difícil de testear exhaustivamente — la spec se paga sola en la primera sesión de debugging significativa que previene.

El cambio más amplio

El Spec-Driven Development no es principalmente una práctica de IA. Es una práctica de ingeniería que se vuelve significativamente más valiosa en un flujo de trabajo asistido por IA.

Antes de las herramientas de IA, las especificaciones ayudaban a los ingenieros humanos a alinearse antes de construir. Ese valor era real pero el overhead era suficientemente alto como para que muchos equipos lo omitieran.

Con herramientas de IA, la spec se convierte en la interfaz principal entre la intención de ingeniería y la implementación generada. La calidad de la spec determina directamente la calidad del output. El overhead de escribir una spec está compensado por la velocidad de implementación — y la alternativa (generar sin spec y revisar cuidadosamente) suele ser más lenta.

Los ingenieros con quienes trabajo que más aprovechan las herramientas de IA son los que escriben las mejores specs. Eso no me ha sorprendido. La buena especificación es la habilidad central de la ingeniería senior. Solo tiene un consumidor más rápido ahora.