En el artículo anterior vimos cómo las Skills nos permiten que un agente revise el trabajo de otro, reduciendo el cuello de botella del ingeniero. Pero el análisis acabó con una conclusión incómoda: la skill detectó 9 issues, dos de ellos críticos — datos de dominio perdidos en runtime — y no fueron errores del agente. El agente implementó exactamente lo que se le pidió. El problema estaba en los requisitos: se describió el qué y el cómo, pero nadie pensó en el impacto sobre el resto del sistema.
El problema de los requisitos ambiguos no es nuevo — lleva con nosotros desde que existe el software. Lo que cambia con la IA es la velocidad a la que se acumula el daño: si un agente puede generar cientos de líneas de código por minuto partiendo de una instrucción incompleta, el error escala al mismo ritmo. Eso nos lleva al Spec Driven Development, la metodología que exploraremos en este artículo.
El problema real con los requisitos#
En el mundo pre-IA y en el actual siempre hay un factor común y es que los requisitos no estan claro en el inicio del proyecto, pero las prisas de empezarlo, de avanzar, de tenerlo en la fecha acordada pues hace vamos tirando con como creemos que es lo más probable que quiera y si luego no es así ya hacemos los “ajustes” cuando este claro. Igual esos ajustes impactan en un cambio total de la aplicación y estamos en el mismo punto de partida del inicio. Pero era algo cultural que se aceptaba.
Repasemos el ejemplo anterior cuando le pedimos a un agente “crea el endpoint POST /characters para añadir un personaje”, le estamos dando una instrucción incompleta. Igual que ocurriría con un ingeniero nuevo: implementa lo que entiende, y lo que entiende es solo lo que le has dicho y no lo que tu piensas que el va a entender.
El problema con ImageUrl del artículo anterior es un ejemplo perfecto. El modelo Character tenía ese campo porque queríamos mostrar la imagen en el frontend. Pero en el requisito de “crear personaje” nadie lo mencionó. El agente no tenía forma de saber que ese campo era obligatorio en el dominio — no estaba en los requisitos, no estaba en las reglas del CLAUDE.md ni debia de estar, y tampoco saltaba ningún constraint de base de datos que pudiera detectar. Simplemente lo ignoró.
Este tipo de error no se resuelve con más contexto en el CLAUDE.md ni con una skill de revisión más exhaustiva. Se resuelve antes: en el momento de definir el requisito.
Qué es el Spec Driven Development#
El Spec Driven Development (SDD) no es un concepto nuevo. La idea de escribir las especificaciones antes que el código existe desde hace tiempo: es la filosofía detrás de cosas como API-first design u OpenAPI. Lo que cambia con la IA es la importancia que cobra.
Cuando programas tú mismo, puedes compensar un requisito mal definido con tu conocimiento del sistema. Sabes que ImageUrl es obligatorio porque llevas meses en el proyecto. El agente no tiene ese conocimiento implícito. Si no está escrito, no existe.
El SDD en este contexto significa: antes de pedirle al agente que implemente nada, escribir una especificación que sea completa, sin ambigüedades y verificable. Una especificación que responda no solo al qué, sino también al impacto en el dominio, a las reglas de negocio y a los criterios de aceptación.
La diferencia entre un requisito y una spec:
| Requisito | Spec | Consecuencia de no tenerla |
|---|---|---|
| “Crea el endpoint POST /characters” | Define el contrato completo: campos obligatorios, validaciones, respuesta esperada, impacto en el dominio | El agente genera el endpoint sin ImageUrl porque nadie dijo que era obligatorio en el dominio. Compila, los tests básicos pasan, llega a producción con datos corruptos. |
| “Añade paginación a la lista” | Define el comportamiento exacto: parámetros, valores por defecto, límites, formato de respuesta, qué ocurre en página fuera de rango | El agente inventa los nombres de los parámetros (page/limit, offset/size, pageIndex/pageSize…) y el frontend que ya consumía el endpoint se rompe silenciosamente. |
| “Muestra el detalle del personaje” | Define qué datos se exponen, qué pasa si el ID no existe, qué relaciones se cargan | El agente devuelve 200 con body vacío o null en lugar de 404. El frontend no sabe distinguir “personaje sin datos” de “personaje inexistente” y muestra una pantalla en blanco. |
| “El usuario puede editar el personaje” | Define qué campos son editables, si es PUT completo o PATCH parcial, qué pasa si se envían campos de solo lectura, quién puede editar | El agente implementa PUT que sobreescribe todos los campos. El primer usuario que edita el nombre borra la imagen porque no la incluyó en el payload. |
Cómo escribir una spec que funcione con agentes#
Una spec útil para un agente tiene que cubrir cuatro cosas:
1. El contrato de la API
Qué endpoint, qué método HTTP, qué body recibe, qué responde en cada caso. Cuanto más cerca del formato OpenAPI, mejor — los agentes lo entienden bien y puedes usarlo también para generar documentación.
2. Las reglas del dominio
Qué invariantes tiene que respetar la operación. Qué campos son obligatorios en el modelo de dominio (no solo en el request). Qué restricciones de negocio aplican.
3. Los criterios de aceptación
Qué tests tienen que pasar para considerar la feature completa. Escritos en lenguaje de comportamiento: dado X, cuando Y, entonces Z. Esto es lo que la skill de revisión puede verificar.
4. El impacto en el sistema
Qué otras partes del código se ven afectadas. Si añadir un personaje requiere que el frontend lo pueda mostrar con imagen, eso tiene que estar en la spec — no es responsabilidad del agente inferirlo.
La spec del endpoint CreateCharacter#
Volvamos al ejemplo de la API de DragonBall. Este es el requisito original que causó los 9 issues:
“Añade el endpoint POST /characters para crear un personaje”
Y esta es la spec equivalente:
## Feature: Crear personaje
### Contrato de API
POST /characters
Request body:
- name (string, obligatorio, max 100 chars)
- race (string, obligatorio, max 50 chars)
- powerLevel (int, obligatorio, > 0, usar long para evitar overflow con valores altos)
- affiliation (string, obligatorio, max 100 chars)
- imageUrl (string, obligatorio, URL válida — requerido por el dominio para mostrar imagen en el frontend)
Respuestas:
- 201 Created: devuelve el Character creado con id generado
- 422 Unprocessable Entity: si algún campo no cumple la validación (usar FluentValidation + WithValidation())
### Reglas de dominio
- Character es una entidad con los campos: Id, Name, Race, PowerLevel, Affiliation, ImageUrl
- ImageUrl es obligatorio en el modelo de dominio — un personaje sin imagen no es válido
- PowerLevel debe ser long, no int — valores como 1.400.000.000 rozan el límite de int
### Impacto en el sistema
- El frontend (CharacterPage.tsx) muestra la imagen del personaje usando ImageUrl
- El repositorio InMemoryCharacterRepository.Add debe copiar todos los campos del Command, incluido ImageUrl
- Añadir el campo ImageUrl al CreateCharacterCommand, CreateCharacterRequest y CreateCharacterValidator
### Criterios de aceptación
- [ ] POST /characters con body válido devuelve 201 y el personaje creado con id
- [ ] POST /characters con name vacío devuelve 422
- [ ] POST /characters con powerLevel = 0 devuelve 422
- [ ] POST /characters sin imageUrl devuelve 422
- [ ] POST /characters con imageUrl inválida devuelve 422
- [ ] El personaje creado es visible en GET /characters con su imagen
- [ ] Los tests pasan CancellationToken en todas las llamadas asíncronasEsta spec tiene treinta líneas. Con ella, ninguno de los 9 issues del artículo anterior habría llegado a la skill de revisión.
El agente con la spec: resultado#
Le pasamos esta spec a Claude con el mismo prompt de antes, pero ahora con la especificación completa como contexto:
“Implementa esta feature siguiendo la spec y las guidelines del proyecto”
El resultado es radicalmente diferente. El agente genera CreateCharacterCommand incluyendo ImageUrl:
public sealed record CreateCharacterCommand(
string Name,
string Race,
long PowerLevel,
string Affiliation,
string ImageUrl);El validador cubre todos los campos obligatorios, incluyendo la URL:
public sealed class CreateCharacterValidator : AbstractValidator<CreateCharacterCommand>
{
public CreateCharacterValidator()
{
RuleFor(x => x.Name)
.NotEmpty().WithMessage("El nombre es obligatorio.")
.MaximumLength(100);
RuleFor(x => x.Race)
.NotEmpty().WithMessage("La raza es obligatoria.")
.MaximumLength(50);
RuleFor(x => x.PowerLevel)
.GreaterThan(0L).WithMessage("El nivel de poder debe ser mayor que 0.");
RuleFor(x => x.Affiliation)
.NotEmpty().WithMessage("La afiliación es obligatoria.")
.MaximumLength(100);
RuleFor(x => x.ImageUrl)
.NotEmpty().WithMessage("La URL de imagen es obligatoria.")
.Must(url => Uri.TryCreate(url, UriKind.Absolute, out _))
.WithMessage("La URL de imagen no es válida.");
}
}El repositorio copia todos los campos correctamente:
public Character Add(CreateCharacterCommand command)
{
var character = new Character
{
Id = _characters.Max(c => c.Id) + 1,
Name = command.Name,
Race = command.Race,
PowerLevel = command.PowerLevel,
Affiliation = command.Affiliation,
ImageUrl = command.ImageUrl
};
_characters.Add(character);
return character;
}Y los tests cubren los criterios de aceptación de la spec, incluyendo el nuevo campo:
[Fact]
public async Task POST_characters_without_image_url_returns_422()
{
var body = new
{
Name = "Bardock",
Race = "Saiyan",
PowerLevel = 10000L,
Affiliation = "None",
ImageUrl = ""
};
var response = await _client.PostAsJsonAsync("/characters", body,
TestContext.Current.CancellationToken);
response.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
}La skill de revisión pasa sin issues críticos. El mismo agente, el mismo prompt base, pero con una spec que elimina la ambigüedad.
Dónde vive la spec#
Una spec que no está versionada junto al código no sirve de nada. Si vive en una wiki, en un Notion o en un email, ya está desincronizada en cuanto el código cambia.
La forma de hacerlo es sencilla: la spec vive en el repositorio, en una carpeta docs/specs/ o directamente junto a la feature si es específica:
docs/
└── specs/
├── create-character.md
├── get-character-by-id.md
└── update-character.mdDe esta forma:
- La spec pasa por revisión en la PR igual que el código
- El agente puede leerla directamente cuando le pides que implemente
- La skill de revisión puede validar el código contra ella
- Si la spec cambia, el diff de git lo muestra junto al cambio de código
Esta es la parte que más cuesta adoptar en equipos que llevan tiempo sin hacerlo, porque requiere escribir antes de implementar. Pero es también la que más valor aporta: si no defines el comportamiento esperado, no puedes verificar que lo que el agente genera es correcto.
Dicho esto, hay una fricción real que sería deshonesto ignorar: cuando los requisitos cambian a mitad del desarrollo — y cambian, siempre — actualizar la spec es un paso extra que bajo presión se suele saltar. Una spec desactualizada es casi peor que no tenerla, porque el agente genera código confiando en información incorrecta y los tests validan un comportamiento que ya no es el acordado. La única forma de evitarlo es tratar la spec con la misma disciplina que el código: si un requisito cambia, la PR que introduce ese cambio también actualiza la spec. Si eso no ocurre, el equipo está acumulando deuda de contexto igual que acumula deuda técnica.
De la spec monolítica a la entrega iterativa: spec-kit#
Todo lo anterior — qué es el SDD, cómo estructurar una spec, dónde versionarla — describe la filosofía: el qué y el por qué. Lo que viene ahora es el cómo llevarlo a escala cuando tienes múltiples features, múltiples agentes y necesitas que el progreso sea visible sin que alguien lo persiga a mano.
La respuesta a ese problema no es abandonar la spec — es hacer que se ejecute.
Aquí está el salto conceptual que diferencia este enfoque de cualquier otro artículo sobre SDD: no hablamos de una spec como documento que alguien escribe y los demás leen. Hablamos de una spec que es el programa de trabajo del equipo. spec-kit materializa exactamente eso: en lugar de que la spec guíe la implementación, la genera directamente a través de un agente. El flujo no es “escribe la spec, luego codifica” — es “escribe la spec, el agente la convierte en tareas ordenadas, las ejecuta respetando dependencias y marca el progreso en tiempo real”.
La consecuencia práctica es que la entrega incremental deja de ser algo que el equipo tiene que planificar a mano. spec-kit genera el desglose de tareas con dependencias explícitas, marcadores de paralelismo y checkpoints verificables por historia de usuario, de forma que el agente sabe exactamente qué puede hacer ahora, qué tiene que esperar y cuándo una historia está lista para entregar. La spec deja de ser un artefacto de análisis y pasa a ser el único punto de verdad que conecta el requisito de negocio con la tarea que ejecuta el agente.
Funciona con Claude Code, GitHub Copilot, Gemini CLI y más de 30 agentes.
Instalación#
Un detalle de nomenclatura antes de continuar: el proyecto se llama spec-kit en GitHub, el paquete que se instala es specify-cli y el comando que usarás en el terminal es specify. Es la misma herramienta, con tres nombres según el contexto.
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@v0.10.2
specify init my-project --integration claude-code
cd my-projectEsto crea la estructura .specify/ con plantillas, scripts y la configuración de integración con tu agente.
El flujo de trabajo#
spec-kit propone un pipeline de comandos que se ejecutan dentro del agente. Cada uno genera un artefacto que sirve de entrada al siguiente. Lo hemos aplicado directamente en el repositorio de DragonBall — todos los ejemplos que siguen son reales.
1. Constitución del proyecto
/speckit.constitutionGenera .specify/memory/constitution.md — las reglas que el agente respetará en todos los pasos. En el proyecto de DragonBall la constitución define, entre otras cosas:
### III. Validaciones de Dominio
- FluentValidation es el único mecanismo para validar comandos y queries.
- Los errores de validación retornan HTTP 422 usando Results.ValidationProblem(...)
- Las entidades de dominio en src/Domain DEBEN proteger sus invariantes en el constructor
### V. Testing Disciplinado
- Una prueba unitaria por cada regla de negocio crítica. No más, no menos.
- PROHIBIDO usar mocks complejos (> 2 niveles de setup). Preferir stubs simples.
- Todo método async DEBE aceptar CancellationToken. Usar TestContext.Current.CancellationToken en tests.
## Definition of Done
1. dotnet build y npm run build sin errores ni warnings
2. dotnet test y npm test pasan al 100%
3. Sin código muerto: no hay variables, imports ni métodos sin uso
4. Los errores de dominio retornan 422 con descripción clara
5. Los nuevos endpoints aparecen en /scalar/v1 con tipos correctosEsto es lo que el agente lee antes de generar cualquier línea de código. En el artículo anterior, la constitución habría sido la pieza que documenta que ImageUrl es obligatorio en el dominio.
2. Escribir la spec (el qué y el por qué, sin entrar en el cómo)
/speckit.specify Necesitamos un CRUD completo de personajes de DragonBall.
El usuario puede ver la lista, consultar el detalle, crear nuevos personajes,
actualizar los existentes de forma parcial y eliminarlos. Los personajes tienen
nombre, apellido (obligatorio), raza (opcional), nivel de poder (>= 0), descripción
(opcional) e imagen.El artefacto que genera spec-kit en specs/001-characters-crud/spec.md tiene este aspecto:
# Feature Specification: Dragon Ball Characters — CRUD API
## User Stories & Acceptance Criteria
### User Story 1: Consultar el catálogo (P1)
- GET /characters devuelve HTTP 200 con array JSON de al menos 5 personajes
- GET /characters/{id} con ID válido devuelve HTTP 200 con el personaje
- GET /characters/{id} con ID inexistente devuelve HTTP 404 con mensaje descriptivo
### User Story 2: Añadir nuevo personaje (P2)
- Payload válido con name, lastName y powerLevel (>= 0) devuelve HTTP 201 con ID generado
- name vacío o ausente → HTTP 422
- lastName vacío o ausente → HTTP 422
- powerLevel negativo → HTTP 422
- powerLevel = 0 está permitido → HTTP 201
### User Story 3: Modificar personaje existente (P2)
- PUT /characters/{id} con payload parcial → HTTP 200, solo se actualizan los campos enviados
- ID inexistente → HTTP 404
- Payload vacío {} → HTTP 200 sin cambios (no-op válido)
### User Story 4: Eliminar personaje (P3)
- DELETE válido → HTTP 204
- ID inexistente → HTTP 404
- GET posterior al DELETE → HTTP 404
## Reglas de validación
- Name: obligatorio, no vacío, no solo espacios, máx 100 caracteres
- LastName: obligatorio, no vacío, no solo espacios, máx 100 caracteres
- Race: opcional, máx 100 caracteres
- PowerLevel: obligatorio, entero no negativo
- Description: opcional, máx 500 caracteres
## Restricciones técnicas
- Sin base de datos — almacenamiento en memoria como Singleton
- Sin autenticación ni autorización
- CORS configurado para http://localhost:5173
- Scalar en /scalar/v1Fíjate en dos cosas. Primera: el agente documenta explícitamente que powerLevel = 0 es válido — exactamente la ambigüedad que habría quedado sin resolver en el flujo anterior. Segunda: lastName aparece como campo obligatorio en el contrato desde el primer artefacto, no como corrección posterior. Este fichero es el que alimenta /speckit.clarify y /speckit.plan en los pasos siguientes.
3. Clarificación (antes de planificar)
/speckit.clarifyEl agente formula preguntas estructuradas sobre lo que está ambiguo antes de crear el plan técnico. En el proyecto de DragonBall habría preguntado, por ejemplo: ¿powerLevel: 0 es un valor de negocio válido o debe ser mayor que cero? La respuesta — que sí es válido — quedó recogida en la spec y se reflejó después en el validator (GreaterThanOrEqualTo(0) en lugar del GreaterThan(0) que el agente habría asumido por defecto).
4. Plan técnico
/speckit.plan La API usa .NET 10 con Minimal APIs y MinApiLib. El frontend es React 19
con Vite y TypeScript estricto. Base de datos en memoria para el ejemplo.Genera specs/001-characters-crud/plan.md, data-model.md y api-spec.json. El plan descompone el trabajo en bloques: Domain Foundation → Application → API Endpoints → Frontend → Tests. Cada bloque declara sus dependencias explícitamente.
5. Desglose en tareas
/speckit.tasksGenera specs/001-characters-crud/tasks.md — el artefacto más valioso para la entrega iterativa. Las tareas se organizan en fases, con marcadores [P] para las que pueden ejecutarse en paralelo y checkpoints explícitos entre fases.
Este es el desglose real del proyecto:
## Phase 1: Setup — Verificación del estado inicial
- [ ] T001 Ejecutar dotnet build y confirmar cero errores
- [ ] T002 Ejecutar dotnet test (línea base: 31 tests en verde)
- [ ] T003 Ejecutar npm test en src/frontend/ (línea base: 24 tests)
- [ ] T004 Verificar que GET /characters devuelve 200
---
## Phase 2: Foundational — Capa de Dominio (bloqueante)
⚠️ CRÍTICO: Completar T005–T008 antes de avanzar al Phase 3.
- [ ] T005 Modificar Character.cs: añadir LastName (obligatorio), Description (opcional);
hacer Race, Affiliation, ImageUrl nullable
- [ ] T006 Modificar ICharacterRepository.cs: añadir Update() y Delete()
- [ ] T007 Implementar Update() con merge parcial y Delete() en InMemoryCharacterRepository
- [ ] T008 Añadir LastName al dataset inicial de 40 personajes
Checkpoint: dotnet build DEBE compilar sin errores antes de continuar.
---
## Phase 3: User Story 1 — Consultar el catálogo (MVP) 🎯
- [ ] T009 [US1] Mover MapOpenApi() y MapScalarApiReference() fuera del bloque IsDevelopment
- [ ] T010 [US1] [P] Añadir WithName, WithTags, Produces a GetCharactersEndpoint
- [ ] T011 [US1] [P] Añadir WithName, WithTags, Produces a GetCharacterByIdEndpoint
- [ ] T014 [US1] Tests de integración: respuesta incluye lastName
Checkpoint: GET /characters funciona + /scalar/v1 muestra los endpoints.
---
## Phase 4: User Story 2 — Crear personaje
- [ ] T016 [US2] Añadir LastName y Description a CreateCharacterCommand
- [ ] T018 [US2] Actualizar validator: LastName obligatorio, PowerLevel >= 0, Race opcional
- [ ] T019 [US2] Actualizar CreateCharacterEndpoint con los nuevos campos y metadata OpenAPI
- [ ] T020 [US2] Tests: LastName vacío → 422; PowerLevel = 0 → 201
Checkpoint: POST con PowerLevel: 0 → 201. Con lastName: "" → 422.
---
## Phase 5–6: User Stories 3 y 4 — Actualizar y eliminar
- [ ] T023–T029 [US3] Slice completo UpdateCharacter: command, validator, handler, endpoint, tests
- [ ] T030–T036 [US4] Slice completo DeleteCharacter: command, handler, endpoint, tests
---
## Phase 7: Frontend — Sincronización de tipos y componentes
- [ ] T037 [P] Actualizar character.ts: añadir lastName y description?
- [ ] T039 [P] CharacterCard.tsx: mostrar nombre + apellido
- [ ] T042 CharacterPage.tsx: mostrar lastName y description usando useCharacter(id)
- [ ] T043 npm test en verde (sin errores TypeScript por campos faltantes)
---
## Phase 8: Polish — Verificación final
- [ ] T044 dotnet build sin errores ni warnings
- [ ] T045 dotnet test — todos los tests en verde (≥ 57 esperado)
- [ ] T048 Verificación manual en Scalar de los 5 endpoints
- [ ] T050 Marcar spec.md como ImplementedLos [P] le indican al agente qué tareas puede ejecutar en paralelo porque tocan ficheros distintos. Las dependencias entre fases son explícitas: la Phase 2 bloquea todo lo demás, y la Phase 7 (frontend) puede ejecutarse en paralelo con las fases 3–6 una vez que el dominio está listo.
6. Implementación
/speckit.implementEl agente ejecuta las tareas en orden, respetando dependencias y paralelismo. Cada checkpoint actúa como una mini-entrega: cuando termina la Phase 3 tienes el listado y el detalle funcionando en Scalar y desplegable, aunque el CRUD completo todavía no exista.
La estrategia MVP que genera el propio agente#
Una de las partes más útiles del tasks.md real es la sección de estrategia al final, que el propio agente genera a partir de la spec:
## MVP (solo US1 — lectura del catálogo)
1. Completar Phase 1 (Setup)
2. Completar Phase 2 (Domain)
3. Completar Phase 3 (US1 — T009 a T015)
4. STOP y VALIDAR: GET /characters con lastName + Scalar funcionando
5. Si MVP aprobado → continuar con Phase 4
## Entrega incremental
Phase 1 + 2 → Base lista
Phase 3 → Lectura funcional (demo posible)
Phase 4 → Creación funcional (CRUD parcial)
Phase 5 → Actualización funcional
Phase 6 → Eliminación funcional (CRUD completo)
Phase 7 → Frontend actualizado
Phase 8 → Verificación y cierreEl agente infiere esta estrategia de las historias de usuario y sus prioridades. No es algo que tengas que escribir tú — sale del pipeline.
Por qué esto cambia el flujo#
Entrega incremental real. Cada fase es una unidad de valor que puede llegar a producción de forma independiente. No hay que esperar a tener el DELETE para desplegar el GET.
El agente trabaja con scope acotado. Sin este desglose, un agente con mucho contexto puede anticiparse e intentar implementar la actualización mientras trabaja en el listado. Con las fases y sus checkpoints, el scope está claro en cada momento.
La ambigüedad se resuelve antes de planificar. El paso /speckit.clarify obliga a responder las preguntas que de otra forma el agente adivinaría. En el proyecto de DragonBall, la regla de PowerLevel >= 0 quedó recogida en la spec y el agente la aplicó correctamente en el validator — sin que nadie tuviera que corregirlo después.
Trazabilidad por fase. El historial de git refleja las fases: cada commit corresponde a un checkpoint verificable, no a una masa de cambios que nadie puede revisar de un vistazo.
Integrando SDD en el flujo completo#
Con las tres piezas en su sitio — contexto, skills y specs — el flujo de desarrollo con IA queda así:
1. Se define la spec de la feature (docs/specs/)
2. El agente lee el CLAUDE.md + la spec y genera la implementación
3. La skill /reviewpr valida el código contra la spec y los estándares del equipo
4. Si hay issues, otro agente los corrige leyendo la misma spec
5. Solo cuando todo pasa, la PR llega al revisor humanoEl ingeniero interviene en dos momentos: al escribir la spec (donde está el criterio de negocio) y en la revisión final (donde está el criterio de calidad). El resto del ciclo lo gestiona el flujo automático.
La spec no solo mejora lo que genera el agente — también hace más fácil la revisión humana. Un revisor que tiene la spec delante puede comprobar en dos minutos si la implementación la cumple. Sin la spec, tiene que inferir la intención a partir del código.
Conclusión#
La IA en el ciclo de desarrollo no falla por falta de capacidad técnica. Falla cuando no tiene suficiente información para tomar las decisiones correctas. El contexto del CLAUDE.md le dice cómo trabaja el equipo. Las skills le dicen cómo verificar que lo ha hecho bien. Pero la spec es lo que le dice qué tiene que hacer exactamente.
Sin una spec clara, el agente adivina. Y cuando adivina, genera código que compila, pasa los tests básicos, funciona visualmente… y aun así tiene inconsistencias en el dominio que solo aparecen en producción.
El SDD no es un proceso burocrático: es la forma de que el agente y el equipo hablen el mismo idioma desde el principio. Una spec de treinta líneas puede ahorrar una hora de revisión y evitar un bug en producción. Y con spec-kit, esa spec deja de ser un documento estático: se convierte en el pipeline que lleva del requisito de negocio a las tareas ejecutables por el agente, historia de usuario a historia de usuario, entregando valor en cada paso en lugar de acumular trabajo hasta que todo esté listo.
Con esto tenemos el ciclo completo: contexto para que el agente entienda el proyecto, specs en fases para que sepa exactamente qué implementar y en qué orden, y skills para que verifique que lo ha hecho bien.
