M2Anatomía de una spec

Semana 1 de 4 Carga 2-3 horas Entregable Spec completa de una feature real

2.1 De la plantilla mínima a la spec completa

En el M1 usaste una plantilla mínima de 4 bloques. Funciona para empezar. Pero una spec profesional tiene más capas — no porque sea burocracia, sino porque cada capa elimina una categoría de ambigüedad.

La estructura completa de una spec SDD es:

1. TÍTULO
2. CONTEXTO
3. OBJETIVO
4. COMPORTAMIENTO ESPERADO
5. RESTRICCIONES
6. CASOS LÍMITE (edge cases)
7. CRITERIOS DE VALIDACIÓN
8. NOTAS TÉCNICAS (opcional)
9. FUERA DE ALCANCE
1 · TÍTULOacción + resultado 2 · CONTEXTOstack · archivos · estado 3 · OBJETIVOpor qué 4 · COMPORTAMIENTO ESPERADOnúcleo · todos los estados 5 · RESTRICCIONESqué no puede hacer 6 · CASOS LÍMITEedge cases 7 · VALIDACIÓNcriterios verificables 8 · NOTAS TÉCNICASopcional 9 · FUERA DE ALCANCEdefine el límite del trabajo · tan importante como el resto

Cada bloque elimina una categoría de ambigüedad. El 9, sin el cual la IA expande el alcance.

Vamos bloque a bloque.

2.2 Bloque por bloque

1. TÍTULO

Una línea. Describe la acción, no el resultado.

❌ Mal: "Autenticación"
✅ Bien: "Implementar login con email/password y redirección post-auth"

El título debe poder leerse en 5 segundos y saber exactamente qué se va a construir.

2. CONTEXTO

Qué existe ahora mismo. El estado del sistema antes de que empieces.

Incluye:

El contexto es lo que evita que la IA asuma cosas que no son ciertas. Si no le dices que usas Next.js 14 con App Router, puede generarte código de Pages Router.

3. OBJETIVO

Por qué se hace esto. Una o dos frases.

No es lo mismo que el comportamiento esperado. El objetivo es la razón de negocio o técnica.

Ejemplo:

El objetivo ayuda a la IA a tomar decisiones cuando hay ambigüedad. Si sabe por qué existe algo, puede elegir mejor entre dos implementaciones posibles.

4. COMPORTAMIENTO ESPERADO

El núcleo de la spec. Qué tiene que hacer exactamente.

Reglas para escribirlo bien:

Ejemplo:

- El usuario introduce email y password en el formulario
- Al hacer submit, el sistema valida formato de email (regex estándar)
- Si el formato es inválido, muestra error inline bajo el campo sin submit al servidor
- Si el formato es válido, hace POST a /api/auth/login
- Si la respuesta es 200, redirige a /dashboard
- Si la respuesta es 401, muestra mensaje "Credenciales incorrectas" sin limpiar el email
- Si la respuesta es 500, muestra mensaje genérico "Error del servidor. Inténtalo de nuevo."

Fíjate: cada estado tiene una respuesta definida. No hay "ya veremos qué pasa".

5. RESTRICCIONES

Qué no puede hacer. Qué debe respetar.

Tipos de restricciones:

Sin restricciones, la IA hace lo que le parece más cómodo. A veces bien. A veces no.

6. CASOS LÍMITE (edge cases)

Las situaciones no obvias que hay que manejar. Son los que más fallan en vibe coding porque nadie los piensa de antemano.

Ejemplos para un formulario de login:

Listar edge cases antes de implementar es uno de los gestos más valiosos de SDD. Obliga a pensar en el sistema como un todo, no solo en el happy path.

7. CRITERIOS DE VALIDACIÓN

Cómo se verifica que la implementación es correcta.

Pueden ser:

La regla de oro: si un criterio no es verificable, no es un criterio. "Que funcione bien" no es un criterio. "Que retorne 401 con credenciales incorrectas" sí lo es.

8. NOTAS TÉCNICAS (opcional)

Información técnica adicional que ayuda a la implementación pero no define el comportamiento.

Ejemplos:

Este bloque ahorra tiempo. Evita que la IA reinvente lo que ya existe.

9. FUERA DE ALCANCE

Qué no entra en esta spec explícitamente. Es tan importante como el comportamiento esperado. Define el límite del trabajo.

Ejemplos:

Sin este bloque, la IA puede intentar hacer más de lo que necesitas, o tú puedes acabar expandiendo el alcance sin darte cuenta (scope creep).

2.3 Ejemplo completo de spec

TÍTULO: Implementar filtro por estado en el listado de subastas (gowy.es)

CONTEXTO:
- Stack: Next.js 14, App Router, Supabase (tabla: subastas), TypeScript
- El listado de subastas existe en /app/subastas/page.tsx
- Actualmente muestra todas las subastas sin filtro
- La tabla subastas tiene columna "estado" con valores: activa | finalizada | cancelada

OBJETIVO:
Permitir al usuario filtrar subastas por estado para reducir el ruido visual
y encontrar más rápido lo que le interesa.

COMPORTAMIENTO ESPERADO:
- Encima del listado aparecen 4 botones: Todas | Activas | Finalizadas | Canceladas
- Por defecto está seleccionado "Todas"
- Al hacer click en un filtro, el listado se actualiza sin recargar la página
- El botón activo tiene estilo visual diferenciado (usar clase CSS existente .active)
- Si no hay subastas para el filtro seleccionado, muestra texto "No hay subastas en este estado"
- El filtro seleccionado se mantiene si el usuario navega dentro de la página

RESTRICCIONES:
- El filtrado se hace en cliente, no con nueva query a Supabase
- No añadir nuevas dependencias
- Usar el componente Button existente en /components/ui/Button.tsx
- No modificar la query inicial de carga de datos

CASOS LÍMITE:
- Si subastas es null o undefined, no romper (mostrar estado vacío genérico)
- Si el usuario llega con ?estado=activa en la URL, aplicar ese filtro por defecto
- Si el valor del estado en DB no coincide con ninguno de los 4 valores conocidos, mostrarlo en "Todas"

CRITERIOS DE VALIDACIÓN:
- Click en "Activas" → solo se muestran subastas con estado=activa
- Click en "Todas" → se muestran todas las subastas
- Con 0 subastas activas → muestra "No hay subastas en este estado"
- Con ?estado=finalizada en URL → filtro "Finalizadas" activo al cargar
- Test unitario: filterSubastas(subastas, 'activa') retorna solo las de estado activa

NOTAS TÉCNICAS:
- El tipo Subasta está definido en /types/subastas.ts
- Para el estado visual del botón activo, ver cómo lo hace el componente NavBar

FUERA DE ALCANCE:
- Filtro por categoría (pendiente)
- Filtro por rango de precio (pendiente)
- Persistencia del filtro en localStorage

2.4 Cuánto detalle es suficiente

La regla práctica: una spec está completa cuando puedes dársela a alguien que no sabe nada del proyecto y construiría exactamente lo que tú tienes en la cabeza.

Si hay cosas que "se sobreentienden", escríbelas. La IA no sobreentiende igual que tú.

Dicho esto: no es una novela. Si el comportamiento es simple, la spec es corta. El detalle se proporcional a la complejidad, no al perfeccionismo.

2.5 Spec vs. ticket vs. historia de usuario

ArtefactoPara qué sirveNivel de detalle
Historia de usuarioComunicar valor al negocioBajo
Ticket de Jira/RallyGestionar trabajo en equipoMedio
Spec SDDInstruir a la IA con precisiónAlto

Una spec SDD puede nacer de una historia de usuario o un ticket. No los reemplaza. Los complementa con la precisión que la IA necesita.

Ejercicio M2

Coge el entregable del M1 (tu primera spec en formato mínimo) y expándela usando la estructura completa de 9 bloques.

Si algún bloque no aplica a tu caso, escribe explícitamente "N/A — [razón breve]". No lo dejes en blanco: el blanco da lugar a dudas.

Cuando termines, compártela en el chat para revisión. El feedback que recibas sobre tu spec es la mejor preparación para el M3.

Entregable M2

Spec completa (9 bloques) de una feature real. Guárdala como: M2-Entregable-SpecCompleta.md

Resumen del Módulo 2