---
name: ejecutar-fase
description: Ejecuta el PLAN.md de una fase con commits atómicos por tarea. Aplica reglas de desviación, maneja checkpoints HITL, ejecuta TDD por default con evidencia RED en telemetría (opt-out declarado), y mantiene ESTADO.md y HOJA-RUTA.md actualizados tras cada tarea completada.
version: "1.2.1"
herramientasPermitidas: [Read, Write, Edit, Bash, Glob, Grep]
exclusiones:
  - "No cargar si no existe PLAN.md con `estado: aprobado` — ejecutar `planear-fase` primero."
  - "No cargar para ejecutar tareas ad-hoc sin plan formal; si no hay oleadas ni criterios de verificación, no hay fase que ejecutar."
  - "No cargar para retomar una sesión pausada en checkpoint `decision` o `human-action` sin resolverlo primero — el agente no debe avanzar pasando por alto una decisión pendiente del usuario."
  - "No cargar solo para verificar el trabajo ya hecho; en ese caso usar `verificar-trabajo`."
# Nota: este skill supera el límite estándar de 380 líneas (406 líneas en v1.1.0).
# Excepción aprobada: las secciones Phase Gates y Dev↔QA Loop formal aportan
# protocolos de calidad de alto valor que no pueden condensarse sin perder
# precisión operativa. No eliminar contenido para ajustar al límite.
evolvable: true  # default para skill estandar
---
# Habilidad: Ejecutar Fase de Desarrollo

## Propósito

La ejecución es donde el plan se convierte en código. Esta habilidad convierte
el PLAN.md en cambios reales, verificables y atómicamente comprometidos, con
trazabilidad completa entre cada tarea y su commit correspondiente. Evita el
antipatrón de acumular cambios sin verificar y commitear "todo de golpe".

## Cuándo activar

- Existe un PLAN.md válido en `.planning/`
- El usuario dice "ejecuta la fase" o "ejecuta el plan"
- Se retoma una fase interrumpida (ESTADO.md indica progreso parcial)

## Cuándo NO cargar

- No hay PLAN.md o el plan no tiene `estado: aprobado` — ejecutar `planear-fase` y aprobar con `/swl:aprobar-plan N` (firma el lock G1) antes de ejecutar.
- El objetivo es solo verificar calidad del trabajo ya implementado; usar `verificar-trabajo`.
- Hay un checkpoint `decision` o `human-action` sin resolver en ESTADO.md — resolver el checkpoint antes de continuar la ejecución.
- Se quiere ejecutar solo una sub-tarea fuera de la secuencia de oleadas del plan; hacerlo rompe el grafo de dependencias y el estado en ESTADO.md.

## Prerrequisito obligatorio

Leer `.planning/fases/0N-PLAN.md` y `.planning/ESTADO.md` (si existe) antes de
ejecutar la primera tarea.

### Gate G1 — integridad del plan firmado

Antes de la primera tarea Y al inicio de cada slice, verificar que el PLAN no
fue mutado tras su aprobación:

```bash
node -e "const {verificarPlan}=require('./scripts/lib/plan-lock'); console.log(JSON.stringify(verificarPlan('.planning/fases/0N-PLAN.md')))"
```

- `modo: "firmado"` → continuar.
- `modo: "legacy"` (plan aprobado sin lock, cláusula de gracia D-05 para planes
  pre-Fase09) → advertencia visible al usuario y continuar sin verificación de
  integridad. Para activar el gate: `/swl:aprobar-plan N`.
- `modo: "mutado"` → DETENER. El plan cambió tras la firma; reportar
  `hashEsperado`/`hashActual` y remitir a `/swl:aprobar-plan N`.
- cualquier otro `ok: false` → DETENER y reportar el `motivo`.

La firma se escribe en `.planning/locks/0N-PLAN.md.lock` (versionado en git).
La única vía válida de aprobar+firmar es `/swl:aprobar-plan`.

---

## Protocolo de ejecución por tarea

### Para cada tarea del plan, en orden de oleadas:

```
1. Leer la descripción completa de la tarea
2. Verificar que las dependencias estén marcadas como COMPLETADA en ESTADO.md
3. Ejecutar la implementación
4. Ejecutar el criterio de verificación de la tarea
5. Si pasa: hacer commit atómico + actualizar ESTADO.md
6. Si falla: aplicar retry con backoff exponencial (ver abajo)
7. Si agota reintentos: marcar como BLOQUEADA y reportar al usuario
8. Al cerrar la tarea: ejecutar el propose-step sobre su diff (ver abajo)
```

### Propose-step al cerrar tarea/fase (Fase 13, ADR-0037)

Tras commitear una tarea (y al cerrar la fase), evaluar las adyacencias de riesgo
del diff y anexar propuestas SOLO si hay señal. Propone, nunca bloquea ni ejecuta:

```bash
node hooks/lib/propose-step.js --rango=HEAD~1..HEAD
```

Si imprime un anexo, agregarlo al reporte de la tarea (y al RESUMEN.md al cerrar
la fase). Si no imprime nada, silencio — no agregar sección vacía. Opt-out con
`SWL_PROPOSE=0`. Antes de una acción autónoma de clase `cambio_reversible`,
registrar el auto-checkpoint: `node hooks/lib/autonomia.js --accion "<acción>"`.
Detalle en el fragmento `agentes/_propose-step.md`.

### Protocolo de retry con backoff exponencial

Cuando una tarea falla verificacion:

| Intento | Delay | Accion |
|---------|-------|--------|
| 1 (original) | — | Ejecutar normalmente |
| 2 | 0s | Leer error, diagnosticar, corregir UNA cosa, re-verificar |
| 3 | 5s | Repensar enfoque, corregir, re-verificar |
| 4 (final) | 15s | Ultimo intento con enfoque diferente |

Reglas:
- `maxRetries`: 3 (configurable por tarea en el plan)
- Si el error es identico en 2 intentos: abortar (loop detectado)
- Si el error es tipo STOP (Regla 4): no reintentar, reportar
- Registrar en ESTADO.md: `intentos: N, ultimo_error: "desc"`

## Dev↔QA Loop formal

Cuando el plan incluye tareas de implementación seguidas de tareas de verificación
(patrón `T-NN impl → T-NN+1 verify`), aplicar el loop formal de calidad:

```
implementador → tdd-qa-swl → [PASS] → siguiente tarea
                           ↘ [FAIL] → implementador (intento 2)
                                    → tdd-qa-swl → [PASS]
                                               ↘ [FAIL] → implementador (intento 3)
                                                        → tdd-qa-swl → [PASS]
                                                                   ↘ [FAIL] → ESCALAR
```

### Reglas del loop

- **Máximo 3 ciclos** Dev→QA por tarea. En el ciclo 3, el agente implementador
  DEBE cambiar de enfoque completamente, no hacer el mismo fix.
- **Loop detectado** (mismo error dos veces seguidas): abortar y escalar a
  `arquitecto-swl` con el diagnóstico completo.
- **Criterio de PASS**: todos los niveles de validación (1–4) deben pasar,
  no solo los tests.
- **Criterio de FAIL**: cualquier nivel de validación falla o el criterio de
  aceptación de la tarea no se cumple.

### Cómo registrar en ESTADO.md

```markdown
| T-05 | Crear endpoint /pagos | EN_PROGRESO | — | Ciclo QA: 2/3 |
```

### Cuándo escalar (Regla 4 del loop)

Si después de 3 ciclos la tarea sigue fallando:

```
ALERTA: Loop Dev↔QA agotado — T-[NN]: [nombre de la tarea]

Ciclos intentados: 3
Último error: [descripción exacta]
Archivos involucrados: [lista]

Escalando a arquitecto-swl para revisión de enfoque.
NO hacer más intentos de implementación hasta recibir dirección.
```

### Niveles de validación estructurada (después de cada tarea)

Ejecutar validaciones en orden ascendente. Si un nivel falla, NO avanzar al siguiente:

| Nivel | Qué valida | Ejemplo de comandos |
|-------|-----------|-------------------|
| 1. Sintaxis y estilo | Código compila, linter pasa | `ruff check .`, `npx tsc --noEmit`, `cargo clippy`, `go vet ./...` |
| 2. Tests unitarios | Lógica de negocio correcta | `pytest -x`, `npm test`, `cargo test`, `go test ./...` |
| 3. Tests de integración | Componentes conectados | `pytest tests/integration/`, `playwright test`, curl a endpoints |
| 4. Validación de aceptación | Criterio del plan satisfecho | Criterio de verificación específico de la tarea en PLAN.md |

Reglas:
- Nivel 1 se ejecuta SIEMPRE, incluso en tareas triviales
- Nivel 2 se ejecuta si existen tests en el proyecto
- Nivel 3 se ejecuta si la tarea toca integración entre componentes
- Nivel 4 se ejecuta siempre (es el criterio de verificación de la tarea)
- Si la validación falla: corregir inmediatamente. NUNCA acumular estado roto

### Formato de commit atómico

```
[F<fase>·T-NN] tipo(scope): descripción en imperativo

- Detalle adicional si es necesario
- Referencia a la tarea del plan

Refs: REQ-<fase>-NN[, REQ-<fase>-MM]
```

Desde la Fase 12 los IDs se namespacean por fase (DT-IDS-NAMESPACE): prefijo
`[F12·T-03]` y footer `Refs: REQ-12-03`. Las fases 01-11 usan el formato plano
`[T-NN]` / `Refs: REQ-NN` (gracia legacy). `verificar-trazabilidad.js` y el
parser del changelog aceptan ambos.

Tipos de commit válidos: `feat`, `fix`, `test`, `refactor`, `docs`, `chore`, `migration`

El footer `Refs: REQ-<fase>-NN` cierra la cadena de trazabilidad REQ→T→commit (G4):
lleva los REQ que la tarea declara en su campo `**Verifica REQ**` del PLAN.
Omitirlo solo en fases legacy sin REQ-IDs. SIN co-autores ni atribuciones a IA
(regla global `git-coauthor.md` — el único autor es el usuario).

---

## Modo Pipeline: acumulación de resultados entre tareas

Cuando el PLAN.md tiene **7 o más tareas con dependencias encadenadas**, activar
el modo pipeline para pasar contexto filtrado entre tareas en lugar del contexto
completo de la conversación.

### Cómo funciona

Al completar cada tarea, generar un `stepResult` compacto:

```json
{
  "step": 3,
  "agentName": "backend-python-swl",
  "output": {
    "filesCreated": ["src/models/user.py", "db/migrations/001_users.sql"],
    "endpointsAdded": ["POST /users", "GET /users/{id}"],
    "keyDecisions": ["usé async SQLAlchemy con session factory"]
  },
  "status": "completed"
}
```

Al delegar la siguiente tarea a un agente, construir el `TaskDelegationContext`
(schema en `manifiestos/handoff-context.json`) incluyendo **solo los stepResults
que la tarea siguiente necesita** — no el array completo:

```
TaskDelegationContext:
  reason: "task_delegation"
  parentAgent: "orquestador-swl"
  transferCount: [incrementar desde handoff previo]
  taskId: "T-04"
  taskDescription: "[descripción exacta del PLAN.md — self-contained]"
  verificationCriteria: "[criterio de verificación del plan]"
  relevantFiles: ["src/models/user.py:1", "db/migrations/001_users.sql"]
  previousTaskOutputs:
    - { taskId: "T-03", output: { endpointsAdded: [...] } }
```

### Beneficio

Un pipeline de 7 tareas pasa ~60% menos contexto a cada agente especializado
versus pasar el historial completo de la conversación.

### Límite de transferCount

Si `transferCount >= 10`, reportar al usuario:
```
ALERTA: Cadena de delegaciones muy larga (transferCount = N).
Posible loop de agentes. Revisar el PLAN.md y continuar manualmente.
```

---

## Reglas de desviación

Una desviación ocurre cuando la implementación difiere del plan. Hay tres tipos:

### Desviación Menor (continuar y registrar)
- Un nombre de función o archivo difiere del plan
- Se añade un helper que no estaba planificado pero no cambia el alcance
- El tiempo real es diferente al estimado

**Acción**: Continuar. Registrar en ESTADO.md bajo `## Desviaciones`.

### Desviación Moderada (notificar y continuar)
- Se descubre que una tarea requiere subdivisión en el momento de ejecutar
- Se encuentra código existente que cubre parcialmente la tarea
- Una dependencia no funciona como se esperaba

**Acción**: Notificar al usuario en el mismo mensaje donde reportas avance.
Registrar decisión tomada en ESTADO.md.

### Desviación Mayor (STOP — requiere replanificación)
- La tarea no puede completarse sin cambiar el diseño de otra tarea ya completada
- Se descubre un requerimiento que invalida 2+ tareas del plan
- La implementación requeriría romper la compatibilidad con código existente

**Acción**: PARAR. No hacer commit. Reportar al usuario con:
1. Qué se encontró
2. Qué tareas están afectadas
3. Opciones de resolución propuestas

---

## Manejo de tareas HITL

Cuando el plan llega a una tarea marcada `HITL`:

1. Presentar al usuario el resultado del trabajo previo
2. Describir exactamente qué decisión o revisión se necesita
3. Esperar confirmación explícita antes de continuar
4. Registrar la respuesta del usuario en ESTADO.md

Formato de presentación de checkpoint:

```
CHECKPOINT HITL — T-[NN]: [Nombre]

Estado actual: [descripción de lo implementado hasta aquí]

Se necesita tu revisión/decisión:
[descripción precisa de qué revisar o decidir]

Opciones (si aplica):
A) [opción A]
B) [opción B]

¿Cómo procedo?
```

---

## TDD por default con evidencia RED (gate G2 — opt-out declarado)

TDD es **default ON** desde la Fase 10 (vNext H2). Solo se omite cuando el
CONTEXTO.md declara `**TDD**: off — razón: [...]` (excepción registrada en
AUDITORIA.md por `discutir-fase`). Sin esa declaración, toda tarea de código
sigue el ciclo con evidencia.

### Ciclo RED → GREEN → REFACTOR por tarea (con telemetría)

Al iniciar la primera tarea de código de la fase, abrir la corrida de evidencia:

```bash
node -e "const lt=require('./hooks/lib/loop-telemetry');const r=lt.iniciarCorrida({tipo:'tdd',direccion:'lower_is_better',config:{fase:'0N',tarea:'T-NN'}});console.log(r.dir)"
```

**RED**: Escribir el test que describe el comportamiento esperado.
El test DEBE fallar. Verificar que falla por la razón correcta, no por error
de sintaxis o configuración. **Registrar la evidencia** (métrica = tests fallando,
descripción = fallo exacto):

```bash
node -e "const lt=require('./hooks/lib/loop-telemetry');lt.registrarIteracion('<dir>',{iteracion:0,metrica:<N_fallan>,delta:0,estado:'baseline',descripcion:'RED T-NN: <fallo exacto del runner>'})"
```

**GREEN**: Escribir la implementación mínima que hace pasar el test.
"Mínima" significa: no implementar más de lo que el test exige. Registrar:

```bash
node -e "const lt=require('./hooks/lib/loop-telemetry');lt.registrarIteracion('<dir>',{iteracion:1,metrica:0,delta:-<N>,estado:'keep',descripcion:'GREEN T-NN: suite verde'})"
```

**REFACTOR**: Limpiar el código sin cambiar el comportamiento.
El test DEBE seguir pasando después del refactor. Hacer commit solo en este paso.

La fila RED en `.planning/loops/tdd-*/iteraciones.tsv` es la evidencia que
`hooks/tdd-gate.js` busca al commitear (warn-only, ADR-0035) — cierra F-TDD-6
("el RED no deja evidencia"). Sin registro, el gate emite nudge `tdd-red-evidence`.

### Cobertura mínima en modo TDD

- Toda función pública tiene al menos 1 test de camino feliz
- Toda función con branches tiene tests de cada rama relevante
- Toda función que puede lanzar excepción tiene test del caso de error

---

## Estado de ejecución serializable con execution-state.js

Para planes multi-agente complejos, usar `hooks/lib/execution-state.js` para
mantener el estado de ejecución serializable y recuperable entre sesiones:

### API disponible

- `nuevo(dir, { planId, tareas })` → inicializa estado de ejecución
- `leer(dir)` → lee el estado actual (devuelve `null` si no existe)
- `iniciarAgente(dir, { agente, tareaId })` → marca agente como activo
- `completarAgente(dir, { agente, tareaId, resultado })` → registra completación
- `establecerProximo(dir, { agente, tareaId })` → define el siguiente paso
- `actualizarContexto(dir, datos)` → actualiza contexto compartido entre agentes
- `formatearResumen(dir)` → resumen legible del estado actual
- `limpiar(dir)` → elimina el archivo de estado

### Integración con el protocolo de ejecución

Antes de cada tarea:
```
estado = leer(dir)
iniciarAgente(dir, { agente: "backend-python-swl", tareaId: "T-03" })
```

Después de cada tarea completada:
```
completarAgente(dir, { agente: "backend-python-swl", tareaId: "T-03", resultado: { ... } })
establecerProximo(dir, { agente: "tdd-qa-swl", tareaId: "T-04" })
```

### Persistencia

El estado se persiste en `.planning/execution-state.json`. Al retomar una sesión
interrumpida, `leer()` recupera el estado exacto donde se detuvo.

---

## Actualización de ESTADO.md

Actualizar ESTADO.md después de cada tarea (no al final de la oleada):

```markdown
# ESTADO.md — Fase [N]: [Nombre]
**Última actualización**: [fecha y hora]

## Progreso
- Tareas totales: N
- Completadas: M
- Bloqueadas: K
- Pendientes: N-M-K

## Estado por tarea
| ID   | Nombre | Estado | Commit | REQ | Notas |
|------|--------|--------|--------|-----|-------|
| T-01 | [nombre] | COMPLETADA | abc1234 | REQ-01 | |
| T-02 | [nombre] | COMPLETADA | def5678 | REQ-01, REQ-02 | |
| T-03 | [nombre] | EN_PROGRESO | — | |
| T-04 | [nombre] | PENDIENTE | — | depende T-03 |
| T-05 | [nombre] | BLOQUEADA | — | [descripción del bloqueo] |

## Desviaciones registradas
| Tarea | Tipo | Descripción | Resolución |
|-------|------|-------------|-----------|
|       |      |             |           |

## Decisiones HITL tomadas
| Tarea | Pregunta | Respuesta del usuario | Fecha |
|-------|---------|----------------------|-------|
|       |         |                      |       |

## Próxima acción
[Qué se ejecuta a continuación y por qué]
```

---

## Actualización de HOJA-RUTA.md al completar la fase

Al completar todas las tareas del plan:

1. Marcar la fase como completada en HOJA-RUTA.md
2. Actualizar la fecha real de completación
3. Añadir nota de desviaciones si las hubo
4. Marcar la siguiente fase como "lista para discutir"

---

## Modo Ralph: ejecución autónoma hasta completar

Cuando el usuario dice "ejecuta hasta terminar", "modo autónomo" o "modo Ralph":

1. Ejecutar TODAS las tareas del plan en secuencia de oleadas
2. Después de cada tarea: ejecutar los 4 niveles de validación
3. Si una validación falla: corregir y re-validar inmediatamente
4. Si después de 3 intentos no se resuelve: marcar como BLOQUEADA y continuar con la siguiente tarea que no dependa de ella
5. Al terminar todas las tareas: ejecutar validación completa del proyecto
6. Si todo pasa: reportar éxito con resumen de lo completado
7. Si hay tareas bloqueadas: reportar cuáles y por qué

Reglas del modo Ralph:
- NUNCA preguntar al usuario durante la ejecución (excepto tareas HITL)
- Registrar CADA decisión tomada en ESTADO.md bajo `## Decisiones autónomas`
- Si se detecta loop (mismo error 2 veces): abortar esa tarea, NO el modo
- Al finalizar, producir resumen: tareas completadas, bloqueadas, decisiones tomadas
- El modo Ralph NO salta el protocolo de retry ni los niveles de validación

---

## Phase Gates — criterios para cambiar de fase

Un Phase Gate es una verificación formal antes de declarar una fase completa
y comenzar la siguiente. NO avanzar si algún criterio falla.

### Gate de Implementación → Calidad

Antes de invocar al equipo de calidad (tdd-qa-swl, revisor-codigo-swl):

- [ ] Todas las tareas del plan en estado COMPLETADA o BLOQUEADA documentada
- [ ] Nivel 1 (linter/tipado) pasa en todo el código nuevo: `ruff`, `tsc --noEmit`, `clippy`
- [ ] Tests existentes siguen pasando (no hay regresiones)
- [ ] No hay secrets ni hardcodeos detectados por el hook escaneo-secretos

### Gate de Calidad → Deploy

Antes de invocar deploy o release:

- [ ] Score de revisión de código ≥ 9.0/10 (revisor-codigo-swl)
- [ ] 0 findings críticos de seguridad (revisor-seguridad-swl)
- [ ] Cobertura de tests ≥ 80% en código nuevo (tdd-qa-swl)
- [ ] Validación de accesibilidad si hay cambios de UI (accesibilidad-wcag-swl)
- [ ] Performance sin regresión: p95 ≤ baseline + 20% (si aplica rendimiento-swl)

### Gate de Deploy → Producción

Antes de declarar la fase completa en producción:

- [ ] Runbook de rollback documentado
- [ ] Alertas de monitoreo configuradas para la nueva funcionalidad
- [ ] Feature flag listo si el cambio es de alto riesgo
- [ ] Release notes actualizadas

### Cómo reportar un Gate fallido

```
PHASE GATE FALLIDO — Gate: [Calidad → Deploy]

Criterio no cumplido: Score de revisión 7.8/10 (mínimo 9.0)
Findings pendientes:
  - [CRITICO] Validación de input en endpoint /usuarios/perfil
  - [ALTO] N+1 query en listado de facturas

Acción requerida: corregir findings antes de continuar.
NO proceder con el deploy hasta aprobar este gate.
```

---

## Gotchas / Errores comunes no obvios

- **Dos agentes escriben al mismo archivo en paralelo**: en modo pipeline con oleadas paralelas, dos agentes distintos reciben tareas que tocan el mismo archivo (ej: `ESTADO.md` o un service compartido). Causa: las tareas no tenían dependencia explícita entre sí pero sí tenían acoplamiento de escritura. Solución: en el plan, si dos tareas modifican el mismo archivo, deben estar en oleadas distintas (secuencial), no paralelas.
- **Commit acumulado al final de la oleada, no por tarea**: el agente ejecuta 3 tareas y hace un solo commit grande al terminar la oleada. Causa: interpretación laxa del protocolo. Solución: el commit se hace inmediatamente después de pasar la verificación de cada tarea individual — si la sesión se interrumpe, el trabajo de las tareas completadas está protegido.
- **Loop Dev↔QA silencioso**: el mismo error aparece en el ciclo 2 y el ciclo 3 y el agente sigue intentando el mismo fix. Causa: no se detectó que el error era idéntico. Solución: comparar el mensaje de error exacto entre ciclos — si coincide en 2 intentos consecutivos, declarar loop y escalar a `arquitecto-swl`.
- **ESTADO.md no actualizado tras una tarea completada**: el agente completa T-03 pero no actualiza ESTADO.md antes de iniciar T-04. Causa: se omitió el paso 5 del protocolo. Solución: la actualización de ESTADO.md es parte del protocolo de cada tarea, no opcional — sin ella el estado de ejecución es inconsistente y la reanudación falla.
- **`transferCount` no incrementado en delegaciones encadenadas**: el orquestador delega 10 tareas sin incrementar el contador, superando el umbral sin alerta. Causa: se olvida actualizar el campo en el `TaskDelegationContext`. Solución: verificar y actualizar `transferCount` antes de cada delegación de tarea; si supera 10, reportar al usuario antes de continuar.

## Checklist de cierre de fase

- [ ] Todas las tareas en ESTADO.md con estado COMPLETADA o documentadas como BLOQUEADA
- [ ] Todos los commits hechos y referenciados en ESTADO.md
- [ ] HOJA-RUTA.md actualizado con la fase completada
- [ ] Desviaciones documentadas
- [ ] Decisiones HITL registradas con respuesta del usuario
- [ ] Tests pasan en el estado final del código
- [ ] No hay `console.log`, `print()` de debug ni pendientes sin ticket en el código nuevo
- [ ] `.planning/locks/fase-activa.json` eliminado (libera el gate G0 — el `.lock`
      del plan NO se toca: es evidencia versionada)
- [ ] `/swl:verificar --until-converge` invocado automáticamente (gate G4) — o
      desviación `--sin-verify` registrada en RESUMEN.md con razón
- [ ] Propose-step ejecutado sobre el diff de la fase; anexo propositivo agregado
      al RESUMEN.md si hubo ≥1 señal, o silencio si no (Fase 13, ADR-0037)
