Skill: /story-implement
Objetivo
Orquesta el ciclo TDD (RED → GREEN → REFACTOR) para una historia SDDF delegando la generación de pruebas y código a skills especializados declarados en sddf.config.yaml. El skill es agnóstico al stack: solo lee configuración y delega; los skills de generación son subagentes independientes.
Posición en el pipeline:
story-plan → story-testcases → story-implement (ciclo TDD completo) → story-code-review
Qué hace este skill:
- Invoca
skill-preflightcomo Paso 0 - Fase RED: Lee
implement.test_generatorsdesddf.config.yaml; valida skills (fail-fast); resuelve artefactos (testcases.mdo fallbackstory.md+design.md); invoca cada skill de pruebas en orden; confirma estado rojo; escribered-phase-status.json - Fase GREEN: Lee
red-phase-status.jsoncomo precondición; lee y validaimplement.code_generatorscomo lista; itera sobre cada capa activa invocando su skill conphase:"GREEN"ylayer:"{layer}"; consolida resultados; confirma que los tests pasan - Fase REFACTOR: Itera sobre cada capa activa invocando su skill con
phase:"REFACTOR"ylayer:"{layer}"; verifica no-regresión ejecutando comandos de test - Al completar el ciclo exitosamente: evalúa DoD IMPLEMENT, genera
implement-report.md, actualizastory.mdaIMPLEMENT/DONE(oIMPLEMENT/IN-PROGRESSsi hay DoD-ERRORs), actualiza checklist deepic.mdy escribecycle-status.json
Qué NO hace este skill:
- Crear skills de generación específicos (ej.
story-test-unit-jest,story-code-nodejs) — son skills separados - Gestionar modos interactivo/automático (
--auto) — cubiertos en STORY-082 - Ejecutar el suite completo de CI — solo ejecuta comandos de test configurados por tipo
Posicionamiento
[story.md: READY-FOR-IMPLEMENT/DONE] ← precondición inicial (viene de story-plan/story-analyze)
[story.md: IMPLEMENT/IN-PROGRESS] ← precondición reanudación (viene de story-code-review needs-changes)
↓
story-implement → Entry point de la implementación: ejecuta TDD tarea por tarea ← aquí
│ Al iniciar: story.md → IMPLEMENT/IN-PROGRESS
│ Al finalizar: story.md → IMPLEMENT/DONE + epic.md checklist actualizado
↓
[story.md: IMPLEMENT/DONE]
──────────────────────────────────────────────────────────────────────────────────────
story.md → What: requisitos, criterios de aceptación, comportamiento esperado
design.md → How: arquitectura, componentes, interfaces, decisiones técnicas
testcases.md → test plan detallado, casos de prueba explícitos
tasks.md → (optativo) When: tareas de implementación, orden, seguimiento
implement-report.md → Done: código generado, estado por tarea, bloqueos documentados ← aquí
story-plan → Entry point del planning: orquesta design → tasking → analyze
story-implement → Entry point de la implementación: ejecuta TDD tarea por tarea ← aquí
Parámetros
| Parámetro | Tipo | Descripción |
|---|---|---|
{story_id} |
posicional | ID de la historia (ej. STORY-059) |
Si no se proporciona argumento, solicitar interactivamente.
Filosofía, Restricciones y Reglas
Filosofía
Write Tests First, Code Later
Reglas
- Primero escribe las pruebas, luego el código: cada punto funcional debe tener sus casos de prueba correspondientes
- Las pruebas son documentación: los casos de prueba describen el comportamiento esperado del sistema
- Rojo-Verde-Refactorizar: primero haz fallar la prueba, luego hazla pasar
- Utiliza los fallos en las pruebas como retroalimentación: una prueba fallida debe guiar su desarrollo y resaltar las mejoras necesarias.
- Historias de nueva funcionalidad → Los tests preexistentes no deben romperse.
- Historias de refactorización → Los tests pueden modificarse, siempre que el comportamiento funcional (criterios de aceptación) no cambie y que los tests sigan pasando después de la refactorización.
- Transición de estado bloqueada por DoD-ERRORs: si hay criterios DoD con
❌, el frontmatter permanece enIMPLEMENT/IN-PROGRESS. Solo al resolver todos los bloqueos, cumplir el DoD y pruebas pasan, se actualiza aIMPLEMENT/DONE.
Flujo de ejecución
Concepto fundamental — test_generators vs. ejecución de tests:
Los
test_generators(Paso 4) generan archivos estáticos de especificación de pruebas: feature files Gherkin, archivos.test.tsx, step definitions TypeScript, etc. Estos archivos son la Fase RED del ciclo TDD — deben existir (y fallar) antes de la implementación.
- Paso 4 = GENERAR archivos de prueba → no necesita servidor, base de datos, ni servicios externos corriendo
- Paso 5 = EJECUTAR comandos para confirmar estado rojo → puede fallar por infraestructura
tasks.mdes un artefacto del desarrollador y no guía el pipeline destory-implement. El pipeline está guiado exclusivamente porsddf.config.yaml(qué skills invocar) ytestcases.md(qué casos generar).
Paso 0 — Verificar entorno (skill-preflight)
Invocar skill-preflight. Si retorna ✗ Entorno inválido, detener la ejecución. skill-preflight resuelve y expone $SPECS_BASE y $CLI_ROOT — usar $SPECS_BASE en todas las rutas a artefactos de specs y $CLI_ROOT en todas las rutas a skills ($CLI_ROOT/skills/{skill}/SKILL.md) en los pasos siguientes.
Paso 0b — Parsear flags de invocación e inicializar $EXEC_MODE
Inspeccionar los argumentos de invocación buscando el flag --auto:
- Si
--autoestá presente →$EXEC_MODE = auto - Si
--autoestá ausente →$EXEC_MODE = interactive(predeterminado)
Emitir: [INFO] Modo de ejecución: {$EXEC_MODE}
$EXEC_MODE es una variable en memoria para esta ejecución. No se persiste en ningún archivo ni se pasa a los subagentes.
Paso 1 — Leer configuración de test_generators
Leer sddf.config.yaml.
Si sddf.config.yaml no existe:
❌ sddf.config.yaml no encontrado
Verifica que el archivo existe o ejecuta /sddf-init para inicializar el entorno.
Detener la ejecución.
Extraer la sección implement.test_generators.
Extraer también la sección implement.e2e_context (opcional). Si no existe, registrar $E2E_CONTEXT = null.
Si la sección implement no existe o test_generators está vacío:
[WARN] No hay test_generators configurados en sddf.config.yaml — Fase RED sin generación de pruebas
Continuar con Paso 4 (confirmación RED) sin invocar subagentes.
Si un tipo activo no tiene campo skill declarado:
[WARN] Sin skill declarado para tipo '<tipo>' — omitiendo ese tipo
Paso 2 — Validar existencia de skills declarados (fail-fast)
Validar todos los skills declarados en test_generators antes de invocar ninguno:
Para cada entry en test_generators:
- Construir ruta:
$CLI_ROOT/skills/{entry.skill}/SKILL.md - Verificar existencia con Glob
- Si no existe y
required: true:
Detener la ejecución sin generar ningún archivo de prueba.❌ Skill '<nombre>' declarado en sddf.config.yaml no encontrado en $CLI_ROOT/skills/ Verifica el nombre del skill en sddf.config.yaml o instálalo antes de continuar. - Si no existe y
required: false:
Marcar entry como omitida y continuar con la siguiente.[WARN] Skill '<nombre>' no encontrado — omitiendo tipo '<tipo>'
Paso 3 — Resolver artefactos de especificación
Resolver los artefactos de la historia en $SPECS_BASE/specs/03-stories/<story_id>*/:
| Prioridad | Artefacto | Acción |
|---|---|---|
| 1 | testcases.md existe |
Usarlo como fuente primaria |
| 2 | testcases.md ausente |
⚠️ testcases.md no encontrado — generando pruebas desde story.md y design.md |
| 3 | story.md o design.md ausentes (fallback) |
❌ Artefactos de especificación insuficientes (falta story.md y/o design.md) + detener |
Construir bundle base de inputs (común a todos los test_generators):
{
"story_id": "<STORY-NNN>",
"testcases_path": "<ruta o null>",
"story_path": "<ruta>",
"design_path": "<ruta>"
}
Nota sobre testcases.md: Si existe, es la fuente canónica y excluyente de casos de prueba. Contiene todos los tipos (UT, CT, IT, E2E, etc.) ya derivados y tipificados por
story-testcases. El skill NO necesita releerstory.mdnidesign.mdpara derivar casos adicionales cuandotestcases.mdestá presente. El subagente generador debe leertestcases.mdy filtrar los casos del tipo que le corresponde.Nota sobre tasks.md: El skill NO lee ni considera
tasks.mden ningún paso del ciclo TDD. La presencia de una tarea "T-NNN — ejecutar E2E" entasks.mdno reemplaza ni posterga la generación del spec E2E en Paso 4.tasks.mdes un artefacto del desarrollador, no del pipeline.
Paso 4 — Invocar skills de generación en orden
⚠️ RESTRICCIÓN CRÍTICA — Omisiones válidas e inválidas:
Las únicas condiciones que justifican no invocar un test_generator en este paso son:
skill: "none"en el YAML → omisión declarada explícitamente por el proyectorequired: false+ el skill no existe en$CLI_ROOT/skills/→ skill opcional ausente- El skill retorna
status: errordurante la invocación → error real del subagenteLos siguientes razonamientos NO son válidos para omitir un test_generator:
Razonamiento incorrecto Por qué es incorrecto "El tipo e2e requiere servidor corriendo" Paso 4 genera archivos estáticos; el servidor no es relevante "El test E2E se genera/verifica en task T-NNN" tasks.mdno guía el pipeline; esta fase no lo lee"Hay un bloqueador de infraestructura para otro tipo" Cada tipo es independiente; un error en unitno afecta ae2e"El servidor de la demo no está disponible" Paso 4 genera archivos; Paso 5 ejecuta comandos — son pasos distintos Si un generator con
required: trueyskill != "none"no es invocado sin una condición válida, es un error del orquestador, no una situación prevista. Ver Paso 6 — validación post-escritura.
Para cada entry de test_generators no omitida (en el orden del YAML):
- Mostrar:
[{tipo}] → invocando {skill}... - Construir el bundle de inputs según el tipo:
- Tipos que no sean
e2e: usar el bundle base del Paso 3 - Tipo
e2e: usar el bundle base del Paso 3 más el campoe2e_context:
Si{ "story_id": "<STORY-NNN>", "testcases_path": "<ruta o null>", "story_path": "<ruta>", "design_path": "<ruta>", "e2e_context": { "framework": "<valor de sddf.config.yaml implement.e2e_context o null>", "base_path": "<valor de sddf.config.yaml o null>", "features_path": "<valor de sddf.config.yaml o null>", "steps_path": "<valor de sddf.config.yaml o null>", "pages_path": "<valor de sddf.config.yaml o null>", "support_path": "<valor de sddf.config.yaml o null>" } }$E2E_CONTEXT = null(sección ausente en el YAML), pasar"e2e_context": null. En ese caso el subagente es responsable de explorar el proyecto para detectar el framework E2E (buscar scripts E2E enpackage.json, archivos de configuración comunes comocucumber.js,playwright.config.ts,cypress.config.ts) y respetar la estructura de directorios existente.
- Tipos que no sean
- Invocar el skill siguiendo el contrato ADR-0002:
a. Leer
$CLI_ROOT/skills/{skill}/SKILL.mdconReadb. Lanzar subagente víaAgenttool consubagent_type: general-purpose, cuyo prompt es:- Contenido íntegro del SKILL.md leído
- Bloque de contexto con las variables resueltas:
Contexto de invocación: - story_id: {$RED_STORY_ID} - testcases_path: {$TESTCASES_PATH} - story_path: {$STORY_PATH} - design_path: {$DESIGN_PATH} - e2e_context: {$E2E_CONTEXT} ← solo para tipo e2e; null si la sección está ausente en el YAML
- El subagente escribe sus resultados en
.tmp/story-implement/{story_id}/{tipo}/results.json - Si el subagente retorna
status: error:
Detener sin invocar skills siguientes.❌ El skill '{skill}' retornó error durante la Fase RED — deteniendo ejecución Error: {message} - Si retorna
status: ok:- Registrar
files_generateddel subagente - Mostrar:
[{tipo}] ✓ {N} archivo(s) generado(s) - Añadir el tipo a
$RED_GENERATORS_INVOKED
- Registrar
Paso 5 — Confirmar estado RED
Para cada tipo generado exitosamente:
- Leer
defaults.{type}.commanddesddf.config.yaml - Si el comando existe:
- Ejecutarlo en el directorio raíz del proyecto
- Exit code ≠ 0:
✅ Tests en estado rojo (fallan correctamente) — tipo: {tipo} - Exit code = 0:
⚠️ Los tests PASAN sin implementación — verificar que los tests sean correctos
- Si no hay comando declarado:
[INFO] Sin comando configurado para tipo '{tipo}' — confirmación de RED omitida
Paso 6 — Escribir output intermedio
Escribir .tmp/story-implement/{story_id}/red-phase-status.json:
{
"story_id": "{story_id}",
"generators_invoked": ["unit", "e2e"],
"generators_skipped": ["eval"],
"files_generated": ["ruta/al/test.spec.js"],
"red_confirmed": true,
"timestamp": "{ISO timestamp}"
}
Este archivo es la precondición que leerá la Fase GREEN antes de invocar el code-generator.
Validación post-escritura — Omisiones inválidas
Después de escribir el archivo, verificar que ningún generator con required: true y skill != "none" aparece en generators_skipped:
Para cada entry en generators_skipped:
- Buscar esa entry en
sddf.config.yaml → implement.test_generators - Si tiene
required: trueyskill != "none"→ detener la ejecución:❌ ERROR: El test_generator de tipo '{tipo}' (skill: '{skill}') está declarado como required:true en sddf.config.yaml pero fue omitido sin una condición válida. Condiciones válidas de omisión: · skill: "none" en el YAML · required: false + skill no existe en $CLI_ROOT/skills/ Acción requerida: a) Volver al Paso 4 e invocar el skill '{skill}' para el tipo '{tipo}' b) O cambiar required: false en sddf.config.yaml si la omisión es intencional permanente - No continuar con Pause-1 ni Paso 7 hasta resolver.
Pause-1 — Confirmación interactiva antes de Fase GREEN
Si $EXEC_MODE = auto: saltar este bloque completamente sin mostrar nada.
Si $EXEC_MODE = interactive:
Mostrar resumen de la Fase RED completada:
📋 Fase RED completada
· Tipos generados: {$RED_GENERATORS_INVOKED}
· Tests en rojo: ✅ (confirmado) / ⚠️ (sin confirmar)
¿Continuar con la Fase GREEN? (s/n)
Leer respuesta del usuario:
s(o Enter vacío) → continuar con Paso 7n→ emitir🛑 Ciclo TDD pausado por el usuario tras Fase REDy terminar sin error (exit limpio)- Cualquier otra entrada → repetir la pregunta una sola vez más
- Si vuelve a ser inválida → asumir
n(emitir🛑 Ciclo TDD pausado por el usuario tras Fase REDy terminar)
- Si vuelve a ser inválida → asumir
Paso 7 — Verificar precondición RED (Fase GREEN)
Leer .tmp/story-implement/{story_id}/red-phase-status.json.
Si el archivo no existe:
❌ Precondición RED no cumplida: .tmp/story-implement/{story_id}/red-phase-status.json no encontrado
Ejecuta story-implement primero para completar la Fase RED antes de continuar con GREEN.
Detener la ejecución.
Si el archivo existe pero red_confirmed: false:
❌ Precondición RED no cumplida: red_confirmed es false en red-phase-status.json
La Fase RED no fue confirmada correctamente. Revisa los archivos de prueba generados.
Detener la ejecución.
Si el archivo existe y red_confirmed: true:
Extraer y registrar internamente:
$RED_STORY_ID=story_id$RED_FILES_GENERATED=files_generated$RED_GENERATORS_INVOKED=generators_invoked
Mostrar: [INFO] Precondición RED verificada — story_id: {$RED_STORY_ID}, {N} archivo(s) de prueba
Paso 8 — Leer y validar code_generators
Leer sddf.config.yaml (ya cargado en Paso 1).
Extraer implement.code_generators como lista.
Si implement.code_generators no existe en el YAML o está vacío:
❌ implement.code_generators no declarado o vacío en sddf.config.yaml
Añade la sección code_generators bajo implement en sddf.config.yaml.
Detener la ejecución.
Inicializar $CODE_GENERATORS_VALID = [] y $CODE_GENERATORS_SKIPPED = [].
Para cada entry {layer, skill, required} en la lista (en orden del YAML):
Si
skill == "none":[INFO] Capa '{layer}': skill none — omitiendoAñadir
{layer}a$CODE_GENERATORS_SKIPPED. Continuar con la siguiente entry.Verificar existencia:
$CLI_ROOT/skills/{skill}/SKILL.md(Glob).Si el skill no existe y
required: true:❌ Skill '{skill}' (capa '{layer}') declarado como code_generator no encontrado en $CLI_ROOT/skills/ Verifica el nombre del skill en sddf.config.yaml o instálalo antes de continuar.Detener la ejecución.
Si el skill no existe y
required: false:[WARN] Skill '{skill}' (capa '{layer}') no encontrado — omitiendo capaAñadir
{layer}a$CODE_GENERATORS_SKIPPED. Continuar con la siguiente entry.Si el skill existe: añadir la entry completa
{layer, skill, required}a$CODE_GENERATORS_VALID.
Si $CODE_GENERATORS_VALID está vacío (ningún error bloqueante, pero ningún skill activo):
[WARN] Ningún code_generator activo — Fases GREEN y REFACTOR sin invocación de skills
Continuar (no es error).
Mostrar: [INFO] code_generators resueltos: {N} activo(s), {M} omitido(s)
Paso 9 — Fase GREEN: invocar code_generators
Inicializar $GREEN_FILES_GENERATED = [] y $GREEN_LAYERS_OK = [].
Para cada entry {layer, skill, required} en $CODE_GENERATORS_VALID (en orden del YAML):
Construir bundle de inputs:
{
"story_id": "{$RED_STORY_ID}",
"phase": "GREEN",
"layer": "{layer}",
"test_files": "{$RED_FILES_GENERATED}",
"story_path": "{$SPECS_BASE}/specs/03-stories/{story_id}*/story.md",
"design_path": "{$SPECS_BASE}/specs/03-stories/{story_id}*/design.md"
}
Mostrar: [GREEN/{layer}] → invocando {skill}...
Invocar el skill siguiendo el contrato ADR-0002:
- Leer
$CLI_ROOT/skills/{skill}/SKILL.mdconRead - Lanzar subagente vía
Agenttool consubagent_type: general-purpose, cuyo prompt es:- Contenido íntegro del SKILL.md leído
- Bloque de contexto con las variables resueltas:
Contexto de invocación: - story_id: {$RED_STORY_ID} - phase: GREEN - layer: {layer} - test_files: {$RED_FILES_GENERATED} - story_path: {$SPECS_BASE}/specs/03-stories/{story_id}*/story.md - design_path: {$SPECS_BASE}/specs/03-stories/{story_id}*/design.md
- El subagente escribe sus resultados en
.tmp/story-implement/{story_id}/green/{layer}/results.json
Si el subagente retorna status: error:
Si
required: true:❌ Fase GREEN fallida: skill '{skill}' (capa '{layer}') retornó error Error: {message} Sugerencia: revisa el código generado manualmente o ajusta la configuración del skill.Detener la ejecución sin procesar capas restantes, sin ejecutar la Fase REFACTOR ni modificar story.md.
Si
required: false:[WARN] Capa '{layer}' falló en GREEN — continuando con capas restantes Error: {message}Continuar con la siguiente entry.
Si retorna status: ok:
- Agregar
files_generateddel subagente a$GREEN_FILES_GENERATED. - Agregar
{layer}a$GREEN_LAYERS_OK. - Mostrar:
[GREEN/{layer}] ✓ {N} archivo(s) de producción generado(s)
Al finalizar todas las capas:
Mostrar: [GREEN] ✓ {N} archivo(s) de producción generado(s) en {M} capa(s) ({$GREEN_LAYERS_OK})
Paso 9b — Confirmar estado GREEN (tests en verde)
Para cada tipo en $RED_GENERATORS_INVOKED:
- Leer
defaults.{type}.commanddesddf.config.yaml - Si el comando existe:
- Ejecutarlo en el directorio raíz del proyecto
- Exit code = 0:
- Emitir:
✅ Fase GREEN exitosa — tipo: {tipo} (tests pasan) - Actualizar checkboxes en testcases.md (si existe la sección
## Test Cases Progress for):- Determinar el prefijo de ID según el tipo del generador:
unit → UT|component → CT|integration → IT|api → API|e2e → E2E|eval → EV|store → ST - En la sección de progreso, reemplazar
- [ ] {PREFIX}-→- [x] {PREFIX}-para todas las líneas del prefijo - Emitir:
✅ testcases.md — {count} caso(s) de tipo {PREFIX} marcados como [x] - Si testcases.md no existe o no tiene la sección: omitir silenciosamente
- Determinar el prefijo de ID según el tipo del generador:
- Emitir:
- Exit code ≠ 0:
- Actualizar checkboxes en testcases.md (si existe la sección
## Test Cases Progress for):- Reemplazar
- [ ] {PREFIX}-→- [!] {PREFIX}-para todas las líneas del prefijo - Emitir:
⚠️ testcases.md — {count} caso(s) de tipo {PREFIX} marcados como [!]
- Reemplazar
❌ Fase GREEN fallida: el skill '{skill}' retornó error — los tests de tipo '{tipo}' no pasan Sugerencia: revisa el código generado en {archivos} y asegúrate de que satisface los tests.Detener sin ejecutar Fase REFACTOR ni modificar story.md.
- Actualizar checkboxes en testcases.md (si existe la sección
- Si no hay comando declarado:
[INFO] confirmación GREEN omitida para tipo '{tipo}' — sin comando configurado
Pause-2 — Confirmación interactiva antes de Fase REFACTOR
Si $EXEC_MODE = auto: saltar este bloque completamente sin mostrar nada.
Si $EXEC_MODE = interactive:
Mostrar resumen de la Fase GREEN completada:
📋 Fase GREEN completada
· Archivos de producción generados: {N} ({$GREEN_FILES_GENERATED})
· Tests: todos pasan ✅
¿Continuar con la Fase REFACTOR? (s/n)
Leer respuesta del usuario:
s(o Enter vacío) → continuar con Paso 10n→ emitir🛑 Ciclo TDD pausado por el usuario tras Fase GREENy terminar sin error (exit limpio)- Cualquier otra entrada → repetir la pregunta una sola vez más
- Si vuelve a ser inválida → asumir
n(emitir🛑 Ciclo TDD pausado por el usuario tras Fase GREENy terminar)
- Si vuelve a ser inválida → asumir
Paso 10 — Fase REFACTOR: invocar code_generators y verificar no-regresión
Para cada entry {layer, skill, required} en $CODE_GENERATORS_VALID (en orden del YAML):
Construir bundle de inputs:
{
"story_id": "{$RED_STORY_ID}",
"phase": "REFACTOR",
"layer": "{layer}",
"test_files": "{$RED_FILES_GENERATED}",
"story_path": "{$SPECS_BASE}/specs/03-stories/{story_id}*/story.md",
"design_path": "{$SPECS_BASE}/specs/03-stories/{story_id}*/design.md"
}
Mostrar: [REFACTOR/{layer}] → invocando {skill}...
Invocar el skill siguiendo el contrato ADR-0002:
- Leer
$CLI_ROOT/skills/{skill}/SKILL.mdconRead - Lanzar subagente vía
Agenttool consubagent_type: general-purpose, cuyo prompt es:- Contenido íntegro del SKILL.md leído
- Bloque de contexto con las variables resueltas:
Contexto de invocación: - story_id: {$RED_STORY_ID} - phase: REFACTOR - layer: {layer} - test_files: {$RED_FILES_GENERATED} - story_path: {$SPECS_BASE}/specs/03-stories/{story_id}*/story.md - design_path: {$SPECS_BASE}/specs/03-stories/{story_id}*/design.md
- El subagente escribe sus resultados en
.tmp/story-implement/{story_id}/refactor/{layer}/results.json
Si el subagente retorna status: error:
Si
required: true:❌ Fase REFACTOR fallida: skill '{skill}' (capa '{layer}') retornó error Nota: los tests siguen en verde (Fase GREEN fue exitosa). El refactor no se aplicó.Detener sin modificar story.md.
Si
required: false:[WARN] Capa '{layer}' falló en REFACTOR — continuando con capas restantesContinuar con la siguiente entry.
Si retorna status: ok: continuar con la siguiente capa.
Al finalizar todas las capas, verificar no-regresión ejecutando comandos de test por tipo:
Para cada tipo en $RED_GENERATORS_INVOKED:
- Leer
defaults.{type}.commanddesddf.config.yaml - Si existe, ejecutar:
- Exit code = 0:
✅ Fase REFACTOR sin regresiones — tipo: {tipo} - Exit code ≠ 0: recopilar tests fallidos y emitir:
Registrar⚠️ Fase REFACTOR introdujo regresiones: {N} tests que pasaban ahora fallan Tests regresados: · {test_1} · {test_2}$REFACTOR_REGRESIONES = true. No modificar story.md. Continuar para reportar todos los tipos.
- Exit code = 0:
Si todos los tipos sin regresiones: registrar $REFACTOR_REGRESIONES = false.
Paso 11 — Transición de estado y output final
Si GREEN y REFACTOR completaron sin errores ni regresiones ($REFACTOR_REGRESIONES = false):
11a — Evaluar criterios DoD IMPLEMENT
Cargar los criterios de la sección IMPLEMENT de docs/policies/definition-of-done-story.md.
Para cada criterio evaluar:
✓si hay evidencia positiva en los artefactos generados por el ciclo (archivos de test, código, sin errores reportados)❌si hay evidencia explícita de incumplimiento⚠️cuando no se puede determinar con certeza (caso por defecto para ejecución manual de tests)
Registrar $DOD_BLOQUEADO:
truesi algún criterio resultó❌falsesi ningún criterio resultó❌
11b — Generar implement-report.md
Escribir $SPECS_BASE/specs/03-stories/<STORY-NNN>/implement-report.md:
---
type: implement-report
id: <story_id>
story: <STORY-NNN>
created: <YYYY-MM-DD>
updated: <YYYY-MM-DD>
---
## Resumen
| Métrica | Valor |
|---|---|
| Fase RED confirmada | sí / no |
| Fase GREEN confirmada | sí / no |
| Fase REFACTOR confirmada | sí / no |
| Archivos de prueba generados | N |
| Archivos de producción generados | N |
## Ciclo TDD
| Fase | Estado | Detalle |
|---|---|---|
| RED | ✅/❌ | {tipos generados, rojo confirmado} |
| GREEN | ✅/❌ | {capas, archivos generados} |
| REFACTOR | ✅/❌ | {sin regresiones / regresiones detectadas} |
## DoD IMPLEMENT
| Criterio | Estado | Observación |
|---|---|---|
| {criterio 1} | ✓/❌/⚠️ | {observación} |
| {criterio N} | ✓/❌/⚠️ | {observación} |
> Los tests deben ejecutarse manualmente para confirmar el resultado final.
11c — Actualizar story.md (condicional)
Si $DOD_BLOQUEADO = false:
status: IMPLEMENTsubstatus: DONEupdated: {YYYY-MM-DD}
Si $DOD_BLOQUEADO = true:
status: IMPLEMENTsubstatus: IN-PROGRESSupdated: {YYYY-MM-DD}- Emitir:
⚠️ story.md permanece en IMPLEMENT/IN-PROGRESS por criterios DoD con ❌ — resolver antes de continuar
11d — Actualizar epic.md (si existe épica padre)
- Leer campo
parentdel frontmatter destory.md - Si
parentexiste, resolver ruta:$SPECS_BASE/specs/02-epics/<parent>/epic.md - Si el archivo existe:
- Buscar la línea del checklist que contenga el id o slug de la historia (ej.
STORY-NNN) - Cambiar
- [ ]→- [x]en esa línea - Emitir:
[INFO] epic.md actualizado: [{story_id}] marcado como completado
- Buscar la línea del checklist que contenga el id o slug de la historia (ej.
- Si no existe o
parentestá vacío:- Emitir:
[INFO] epic.md no encontrado o sin parent declarado — omitiendo actualización - No es condición de error.
- Emitir:
11e — Escribir cycle-status.json y mostrar resumen final
Escribir .tmp/story-implement/{story_id}/cycle-status.json:
{
"story_id": "{$RED_STORY_ID}",
"red_confirmed": true,
"green_confirmed": true,
"refactor_confirmed": true,
"files_generated": "{$GREEN_FILES_GENERATED}",
"files_modified": "{archivos modificados en REFACTOR}",
"dod_bloqueado": false,
"final_status": "IMPLEMENT/DONE",
"timestamp": "{ISO timestamp}"
}
Mostrar resumen según $EXEC_MODE:
Si $EXEC_MODE = auto:
── Ciclo TDD completado automáticamente (--auto) ──────────
✅ Fase RED: {N} tipo(s) generado(s) | rojo confirmado: {✅ / ⚠️}
✅ Fase GREEN: {N} archivo(s) de producción generados
✅ Fase REFACTOR: sin regresiones
──────────────────────────────────────────────────────────
📄 implement-report.md → {$SPECS_BASE}/specs/03-stories/{story_id}/implement-report.md
📄 cycle-status.json → .tmp/story-implement/{story_id}/cycle-status.json
📋 story.md: {IMPLEMENT/DONE o IMPLEMENT/IN-PROGRESS} ✓
📋 epic.md: {actualizado / no encontrado}
DoD IMPLEMENT:
{tabla criterios ✓/❌/⚠️}
Si $EXEC_MODE = interactive:
✅ Ciclo TDD completado
Fase RED: tests en rojo confirmados
Fase GREEN: {N} archivo(s) de producción generados
Fase REFACTOR: sin regresiones
implement-report.md → {$SPECS_BASE}/specs/03-stories/{story_id}/implement-report.md
cycle-status.json → .tmp/story-implement/{story_id}/cycle-status.json
story.md → {IMPLEMENT/DONE o IMPLEMENT/IN-PROGRESS}
epic.md → {actualizado / no encontrado}
DoD IMPLEMENT:
{tabla criterios ✓/❌/⚠️}
Si hubo errores en GREEN o REFACTOR: no ejecutar este paso (la detención ya ocurrió en el paso correspondiente).
Manejo de errores
| Condición | Mensaje | Acción |
|---|---|---|
sddf.config.yaml no encontrado |
❌ sddf.config.yaml no encontrado |
Detener ejecución |
implement.test_generators vacío o ausente |
[WARN] No hay test_generators configurados — Fase RED sin generación de pruebas |
Continuar sin subagentes |
Tipo activo sin campo skill |
[WARN] Sin skill declarado para tipo '<tipo>' — omitiendo ese tipo |
Omitir tipo |
Skill required:true no existe (test_generator) |
❌ Skill '<nombre>' declarado en sddf.config.yaml no encontrado en $CLI_ROOT/skills/ |
Detener sin generar archivos |
Skill required:false no existe (test_generator) |
[WARN] Skill '<nombre>' no encontrado — omitiendo tipo '<tipo>' |
Omitir tipo y continuar |
testcases.md ausente |
⚠️ testcases.md no encontrado — generando pruebas desde story.md y design.md |
Continuar con fallback |
Generator required:true con skill!=none en generators_skipped |
❌ ERROR: test_generator '{tipo}' es required:true pero fue omitido sin condición válida |
Detener antes de GREEN; exigir corrección o cambiar a required:false |
story.md o design.md ausentes |
❌ Artefactos de especificación insuficientes (falta story.md y/o design.md) |
Detener ejecución |
Subagente retorna status: error (Fase RED) |
❌ El skill '{skill}' retornó error durante la Fase RED |
Detener sin invocar siguientes |
| Tests pasan sin implementación (Fase RED) | ⚠️ Los tests PASAN sin implementación — verificar que los tests sean correctos |
Advertir, continuar |
red-phase-status.json no existe |
❌ Precondición RED no cumplida: .tmp/story-implement/{story_id}/red-phase-status.json no encontrado |
Detener Fase GREEN |
red_confirmed: false en red-phase-status.json |
❌ Precondición RED no cumplida: red_confirmed es false |
Detener Fase GREEN |
implement.code_generators no declarado o vacío |
❌ implement.code_generators no declarado o vacío en sddf.config.yaml |
Detener Fase GREEN |
Entry con skill: none |
[INFO] Capa '{layer}': skill none — omitiendo |
Omitir capa |
code_generator required:true no existe |
❌ Skill '{skill}' (capa '{layer}') declarado como code_generator no encontrado en $CLI_ROOT/skills/ |
Detener Fase GREEN |
code_generator required:false no existe |
[WARN] Skill '{skill}' (capa '{layer}') no encontrado — omitiendo capa |
Omitir capa, continuar |
| Ningún code_generator activo | [WARN] Ningún code_generator activo — Fases GREEN y REFACTOR sin invocación de skills |
Continuar (no es error) |
Subagente required:true retorna error (Fase GREEN) |
❌ Fase GREEN fallida: skill '{skill}' (capa '{layer}') retornó error |
Detener sin REFACTOR, story.md sin cambio |
Subagente required:false retorna error (Fase GREEN) |
[WARN] Capa '{layer}' falló en GREEN — continuando con capas restantes |
Continuar con siguiente capa |
| Tests no pasan tras GREEN | ❌ Fase GREEN fallida: el skill '{skill}' retornó error — los tests de tipo '{tipo}' no pasan |
Detener sin REFACTOR, story.md sin cambio |
Subagente required:true retorna error (Fase REFACTOR) |
❌ Fase REFACTOR fallida: skill '{skill}' (capa '{layer}') retornó error |
Detener, story.md sin cambio |
Subagente required:false retorna error (Fase REFACTOR) |
[WARN] Capa '{layer}' falló en REFACTOR — continuando con capas restantes |
Continuar |
| REFACTOR introduce regresiones | ⚠️ Fase REFACTOR introdujo regresiones: {N} tests que pasaban ahora fallan |
Listar tests, story.md sin cambio |
| Usuario responde 'n' en Pause-1 | 🛑 Ciclo TDD pausado por el usuario tras Fase RED |
Terminar sin error (exit limpio), sin invocar GREEN ni REFACTOR |
| Usuario responde 'n' en Pause-2 | 🛑 Ciclo TDD pausado por el usuario tras Fase GREEN |
Terminar sin error (exit limpio), sin invocar REFACTOR |
| Entrada inválida repetida en pausa | Repetir pregunta una vez; si vuelve a ser inválida → asumir 'n' | Terminar como si usuario respondiera 'n' |
Error en cualquier fase en modo --auto |
Mismo ❌ {mensaje_error_fase} que en modo interactivo |
Detener sin prompt de confirmación al usuario |
Arquitectura de delegación
story-implement (orquestador — Fase RED)
└── {skill de tipo unit} ← subagente, ej. story-test-unit-jest
└── {skill de tipo e2e} ← subagente, ej. story-test-e2e-playwright
└── {skill de tipo eval} ← subagente, ej. story-test-eval
story-implement (orquestador — Fases GREEN y REFACTOR)
└── {skill capa frontend} ← subagente, ej. code-frontend-library-react
└── {skill capa backend} ← subagente, ej. code-backend-nodejs (si existe)
└── {skill capa database} ← subagente, ej. code-database-prisma (si existe)
Los subagentes de Fase RED reciben el bundle {story_id, testcases_path, story_path, design_path} (más e2e_context para el tipo e2e) y escriben en .tmp/story-implement/{story_id}/{tipo}/results.json.
Los subagentes de Fases GREEN/REFACTOR reciben el bundle {story_id, phase, layer, test_files, story_path, design_path} y escriben en .tmp/story-implement/{story_id}/{phase}/{layer}/results.json.
El orquestador nunca pasa su contexto completo heredado a los subagentes.
La invocación sigue el contrato de 4 pasos del ADR-0002: Read del SKILL.md → Agent tool (subagent_type: general-purpose) → output en .tmp/ → Read de resultados. Los skills de generación permanecen en $CLI_ROOT/skills/ (no en $CLI_ROOT/agents/) para preservar su invocabilidad directa y la configurabilidad vía sddf.config.yaml.
Salida
| Artefacto | Ruta | Descripción |
|---|---|---|
| Archivos de prueba | según skill de generación | Tests generados en código productivo |
| Archivos de producción | según skill de generación | Código generado en Fases GREEN/REFACTOR |
implement-report.md |
$SPECS_BASE/specs/03-stories/<STORY-NNN>/implement-report.md |
Reporte final: ciclo TDD, DoD compliance, estado por fase |
story.md (actualizado) |
mismo directorio | Frontmatter → IMPLEMENT/DONE (o IMPLEMENT/IN-PROGRESS si DoD-ERRORs) |
epic.md (actualizado) |
$SPECS_BASE/specs/02-epics/<parent>/epic.md |
Checklist con [x] para la historia completada (si existe) |
red-phase-status.json |
.tmp/story-implement/{story_id}/red-phase-status.json |
Estado de la Fase RED — precondición para GREEN |
cycle-status.json |
.tmp/story-implement/{story_id}/cycle-status.json |
Estado final del ciclo TDD completo |
results.json por tipo/capa |
.tmp/story-implement/{story_id}/{tipo o fase/capa}/results.json |
Output de cada subagente |