The Three Ways in the AI Era -- Parte 2

Specs antes que código: por qué la IA necesita SDD para mantener los lotes pequeños

#devops #ai #sdd #spec-kit #atlas #three-ways

En el artículo anterior vimos a un equipo producir una pull request de 47 archivos en 45 minutos. El reviewer cerró la pestaña. La PR se quedó aparcada 6 días. El Primer Principio — Flujo, lotes pequeños — estaba roto.

Este artículo va de arreglarlo. Mismo equipo, misma tarea, un cambio grande: escriben una spec antes de escribir un prompt. El lote baja de 47 archivos a 5. El lead time de 6 días a 1. Y los humanos siguen al mando.

El Problema

Un developer sosteniendo una pequeña nota adhesiva que pone "integrar QuantumAPI" junto a un robot de IA generando una montaña de archivos de código detrás

El problema no es la IA. El problema es lo que le damos.

En el artículo anterior, el dev senior escribió una frase en Copilot Chat:

“Integra QuantumAPI en nuestra API y frontend. Necesitamos encriptación en reposo y respuestas firmadas.”

Eso es un prompt. No es una spec. No tiene límites, no tiene criterios de aceptación, no tiene lista de cosas que la IA no debe tocar. Así que la IA llenó cada hueco vacío con código. Middleware de auth. Políticas de retry. Imágenes base de Docker. Componentes React. 47 archivos de sugerencias “útiles”.

Gene Kim escribió en 2016 que el tamaño de lote es el predictor más fuerte del lead time. Lotes pequeños = flujo rápido. Lotes grandes = caos. Diez años después, el State of DevOps Report de DORA lo confirma cada año. Las matemáticas no han cambiado. Solo las herramientas.

Las herramientas de IA tiran por defecto a lotes grandes. Quieren ser útiles. Les pides un vaso de agua, te dan una bañera. Si no les pones límites, llenan cada hueco libre con más código.

Eso es lo que arregla SDD.

La Solución

Dos paneles lado a lado — izquierda: un bocadillo desordenado con un prompt vago; derecha: una pila ordenada de planos etiquetados "spec" — ilustración editorial plana

SDD — Spec-Driven Development — es la idea de que la spec es la fuente de verdad, no el código. Escribes qué debe hacer el sistema, qué no debe hacer y cómo vas a saber que está terminado. Luego le das la spec a la IA. El código pasa a ser el output, no el input.

No es una idea nueva. Dan North escribía specs BDD en 2006. La era del waterfall tenía specs funcionales. Lo que cambió es que los LLMs hacen que las specs sean por fin útiles — porque ahora la spec es el input para generar código, no un documento que acumula polvo en Confluence.

Dos herramientas están empujando SDD con fuerza ahora mismo:

  • GitHub Spec Kit — open source, basado en CLI, funciona con Copilot, Claude y Gemini
  • AWS Kiro — un IDE completo construido alrededor de specs

Ambas comparten la misma estructura. Una buena spec tiene 5 partes:

ParteQué responde
Goal¿Por qué existe esto? ¿Qué problema resuelve?
Scope¿Qué entra? Una feature, superficie pequeña.
Non-goals¿Qué queda explícitamente fuera? Esta es la parte crítica.
Criterios de aceptación¿Cómo sabemos que está terminado? Checklist verificable.
RestriccionesStack, deadlines, dependencias, guardarraíles.

Una comparación rápida con lo que hicimos en el Artículo 1:

Prompt (Artículo 1)Spec (este artículo)
“Integra QuantumAPI en nuestra API y frontend”Encriptar 3 campos PII de UserProfile en reposo. Scope: entidad UserProfile solo. Non-goals: auth, UI, retry. Aceptación: test de round-trip pasa, no cambian los shapes de los endpoints. Restricciones: .NET 10, EF Core 10, SDK QuantumAPI v2.3. PR ≤ 8 archivos.

¿Dónde encaja ATLAS? SDD te dice qué va dentro de la spec. ATLAS — en especial los pasos Architect y Trace — te dice cómo validar que la spec es buena de verdad antes de pasársela a la IA. Sin supuestos ocultos, sin scope creep, sin dependencias no trazadas. El humano es dueño de la spec. La IA es dueña del código.

Ejecutar

Nuestro equipo de QuantumAPI vuelve. Misma misión: encriptar campos sensibles, firmar respuestas de la API, rotar claves cada 90 días. Mismo deadline de 8 semanas. Esta vez con SDD.

Paso 1 — Descomponer la petición grande

Una petición gigante etiquetada "integrar QuantumAPI" siendo partida por una línea de puntos en tres cajas más pequeñas etiquetadas Spec A, Spec B, Spec C — ilustración plana

El equipo aplica el paso Architect de ATLAS a la petición: “¿Se puede hacer esto en una sola PR?” Respuesta: no. Tres responsabilidades distintas. Así que lo parten:

  • Spec A: encriptar campos sensibles en reposo
  • Spec B: firmar respuestas de la API con ML-DSA
  • Spec C: rotación automática de claves

Tres specs. Tres PRs. Revisables por separado. Mergeables de forma independiente. El monstruo de 47 archivos ya está muerto sobre el papel.

Paso 2 — Escribir la Spec A

Inicializan Spec Kit en el repo. Fija una versión con el tag (consulta las releases de Spec Kit para la última):

uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init <proyecto>

Esto crea una carpeta .specify/ con plantillas. Escriben la Spec A en specs/001-encrypt-pii/spec.md:

# Spec 001: Encriptar campos sensibles en reposo

## Goal
Encriptar 3 campos (email, phone, nationalId) de UserProfile y 2 campos
(iban, accountHolder) de Transaction antes de escribir en PostgreSQL.
La desencriptación ocurre de forma transparente al leer. La auditoría
de compliance en 8 semanas exige encriptación a nivel de campo para PII.

## Scope
- Nueva clase de servicio `IFieldEncryptor` + implementación `QuantumApiFieldEncryptor`
- Value converters de EF Core cableados solo en los 5 campos indicados
- Binding de configuración para el endpoint de QuantumAPI y vault ID
- Tests unitarios del encryptor
- Un test de integración: escribir un UserProfile, releerlo, verificar
  que devuelve los valores originales

## Non-goals
- NO se tocan autenticación ni autorización
- NO se tocan UI ni componentes React
- NO se añaden políticas de retry (puede venir en una spec futura si hace falta)
- NO rotación de claves (es la Spec C)
- NO firmado de respuestas (es la Spec B)
- NO se tocan otras entidades (Portfolio, Position, Order, etc.)
- NO hay endpoints nuevos; los existentes deben comportarse igual

## Criterios de aceptación
- [ ] Interfaz `IFieldEncryptor` con métodos `EncryptAsync` y `DecryptAsync`
- [ ] `QuantumApiFieldEncryptor` usa el SDK oficial de QuantumAPI .NET v2.3
- [ ] Value converters de EF Core aplicados solo en los 5 campos listados
- [ ] Test de round-trip: escribir/leer devuelve el plaintext original
- [ ] El `GET /users/{id}` existente devuelve la misma forma JSON que antes
- [ ] Sin secretos en appsettings.json; vault ID vía variable de entorno
- [ ] `dotnet build` y `dotnet test` pasan
- [ ] La PR toca ≤ 8 archivos

## Restricciones
- .NET 10, EF Core 10
- SDK QuantumAPI .NET v2.3 (ya está en Directory.Packages.props)
- PostgreSQL 16 (sin cambios de esquema; los campos se quedan como `text`)
- El CI de Azure DevOps debe seguir en verde
- Deadline: mergear antes del viernes

## Preguntas abiertas
- Ninguna. Todas las decisiones de arriba están cerradas.

40 líneas. Se escribe en 20 minutos. Ahorra días de rework.

Paso 3 — Pasarle la spec a la IA

Con los slash commands de Spec Kit dentro del asistente de IA:

/specify @specs/001-encrypt-pii/spec.md
/plan
/tasks
/implement

O, sin Spec Kit, la misma idea como prompt plano:

“Implementa la spec en specs/001-encrypt-pii/spec.md. No añadas nada fuera del scope. No toques archivos que no estén en los criterios de aceptación. Si una decisión no está en la spec, para y pregunta.”

La IA produce una PR con 5 archivos:

  • src/Domain/IFieldEncryptor.cs
  • src/Infrastructure/QuantumApiFieldEncryptor.cs
  • src/Infrastructure/Data/QuantumEncryptedConverter.cs
  • src/Infrastructure/Data/ApplicationDbContext.cs (solo cambios de configuración de la entidad)
  • tests/Infrastructure.Tests/QuantumApiFieldEncryptorTests.cs

Un fragmento del QuantumApiFieldEncryptor generado:

public class QuantumApiFieldEncryptor(
    IQuantumApiClient client,
    IOptions<QuantumApiOptions> options) : IFieldEncryptor
{
    public async Task<string> EncryptAsync(string plaintext, CancellationToken ct)
    {
        var result = await client.Vault
            .EncryptAsync(options.Value.VaultId, plaintext, ct);

        return result.Ciphertext;
    }

    public async Task<string> DecryptAsync(string ciphertext, CancellationToken ct)
    {
        var result = await client.Vault
            .DecryptAsync(options.Value.VaultId, ciphertext, ct);

        return result.Plaintext;
    }
}

Limpio. Responsabilidad única. Hace exactamente lo que dice la spec. Nada más.

Paso 4 — Resultado

Una pequeña y ordenada PR de 5 archivos brillando en verde junto a una enorme PR gris de 47 archivos al fondo — comparación visual, ilustración plana

MétricaArtículo 1 (sin spec)Artículo 2 (con SDD)
Archivos modificados475
Tiempo de reviewel reviewer se rindió8 minutos
Lead time6 días1 día
Scope creepauth, retry, Docker, UIninguno
Bus factor03 (todos pueden leer la spec)

El equipo repite el proceso con la Spec B (firmado) y la Spec C (rotación). Tres PRs pequeñas en dos semanas. Todas mergeables. Todas revisables. Todas trazables hasta una spec que un humano escribió y firmó.

Primer Principio restaurado. Lotes pequeños. Trabajo visible. Sin grandes handoffs.

Plantilla

Aquí tienes la plantilla mínima de spec. Copia, pega, rellena. Guárdala en specs/XXX-nombre-feature/spec.md.

# Spec XXX: <nombre corto de la feature>

## Goal
<1-3 frases. El porqué. Enlaza con la razón de negocio.>

## Scope
- <qué entra — pequeño>

## Non-goals
- <qué NO entra — aquí es donde ganan las specs>

## Criterios de aceptación
- [ ] <resultado verificable 1>
- [ ] <resultado verificable 2>

## Restricciones
- <stack, deadlines, dependencias>

## Preguntas abiertas
- <si hay alguna — si no, escribe "Ninguna">

Regla del pulgar: si tu spec tiene menos de 15 líneas, probablemente está demasiado vaga. Si tiene más de 100 líneas, has metido demasiado scope — pártela en dos specs.

El Reto

Esta semana, coge la próxima tarea asistida por IA de tu backlog. Antes de abrir Copilot o Claude, escribe la spec. Límite: una página de markdown. Luego pásale la spec a la IA y mide el tamaño de la PR. Compáralo con tus PRs generadas por IA habituales.

En el próximo artículo atacamos el Segundo Principio — Feedback. Nuestro equipo acertó con el tamaño del lote usando SDD. Pero entonces el reviewer de IA dejó 22 comentarios sobre la PR limpia de 5 archivos. 19 eran ruido. Lo vamos a arreglar con GOTCHA.

→ Artículo 3: AI Code Review que no grita ‘¡que viene el lobo!’ (próximamente)


Si esta serie te ayuda, considera patrocinarme en GitHub o invitarme a un café.

Esta es la parte 2 de 6 de la serie “Los Tres Principios en la Era de la IA”. Anterior: El DevOps Handbook cumple 10 años.

Comments

Loading comments...