---
name: swl:aprobar-plan
description: Aprueba el PLAN.md de una fase y lo firma con un lock SHA256 (gate G1 de SDD). Transiciona el frontmatter de estado borrador a aprobado y escribe .planning/locks/<plan>.lock. Es la única vía válida de aprobación — ejecutar-fase verifica este lock antes de implementar y detiene la ejecución si el plan fue mutado tras la firma.
allowed_tools: ["Read", "Write", "Edit", "Bash", "Glob"]
---

# /swl:aprobar-plan <n> — Aprobar y firmar el plan de una fase (Gate G1)

Eres el guardián del gate G1 del enforcement SDD. Tu trabajo es transicionar un
PLAN de `borrador` a `aprobado` Y firmarlo con un lock SHA256, de modo que
cualquier mutación posterior del plan sea detectable por `/swl:ejecutar-fase`.

Este comando es la **única vía documentada de aprobación**. Editar el frontmatter
a mano (`estado: aprobado`) deja el plan en modo legacy (cláusula de gracia D-05):
se ejecuta con advertencia pero sin protección de integridad. Usar este comando
es lo que activa el gate real.

## Uso

```
/swl:aprobar-plan 9
```

El argumento `<n>` es el número de la fase cuyo PLAN se aprueba.

## Paso 1 — Localizar el PLAN

Resuelve la ruta `.planning/fases/0N-PLAN.md` (N con cero a la izquierda si N < 10).

- Si no existe: detente con "No existe el PLAN de la fase N. Ejecuta `/swl:planear-fase N` primero."
- Lee el archivo completo.

## Paso 2 — Validar el estado actual del frontmatter

Lee el campo `estado:` del frontmatter:

- Si `estado: borrador` → continúa al Paso 3 (caso normal).
- Si `estado: aprobado` → ya está aprobado. Verifica si existe el lock:
  ```bash
  node -e "const {verificarPlan}=require('./scripts/lib/plan-lock'); console.log(JSON.stringify(verificarPlan('.planning/fases/0N-PLAN.md')))"
  ```
  - Si `modo: "firmado"` → informa "El plan ya está aprobado y firmado." y termina.
  - Si `modo: "legacy"` (aprobado sin lock) → pregunta al usuario: "El plan está
    aprobado pero sin firmar (modo legacy). ¿Lo firmo ahora para activar el gate
    G1?" Si confirma, salta al Paso 4 (firmar sin re-transicionar).
  - Si `modo: "mutado"` → el plan cambió tras una firma previa. Informa el
    `hashEsperado` vs `hashActual` y pregunta si re-aprobar (re-firmar el estado
    actual). Procede solo con confirmación explícita.
- Si no hay campo `estado` → detente: "El PLAN no tiene campo `estado` en el
  frontmatter. Revisa que sea un plan válido generado por `/swl:planear-fase`."

## Paso 2.5 — Validar la matriz REQ×T (trazabilidad G4)

Lee `.planning/fases/0N-CONTEXTO.md` y extrae los IDs `REQ-NN:` (fases 01-11) o
`REQ-<fase>-NN:` (namespaceados, fases ≥12) de la sección de criterios de
aceptación. `verificar-trazabilidad.js` reconoce ambos formatos.

- **CONTEXTO sin REQ-IDs** (fases legacy 01-09): advertencia informativa
  ("CONTEXTO sin REQ-IDs — trazabilidad no exigible, gracia legacy") y continúa.
- **CONTEXTO con REQ-IDs**: verifica que el PLAN cubra TODOS:
  ```bash
  node scripts/verificar-trazabilidad.js --fase=N --solo-plan
  ```
  - Exit 0 → continúa al Paso 3.
  - Exit 1 (REQ huérfanos) → **RECHAZA la aprobación**. Lista los REQ sin tarea y
    remite a `/swl:planear-fase N` para cubrirlos (o a retirar el REQ del CONTEXTO
    con marca "RETIRADO — razón"). NO firmes un plan con REQ huérfanos.

## Paso 3 — Confirmar con el usuario antes de aprobar

NUNCA apruebes sin confirmación explícita. Presenta un resumen breve del plan
(número de slices, tareas, slices HITL) y pregunta:

```
El plan de la fase N tiene [X] slices y [Y] tareas ([Z] HITL).
¿Confirmas la aprobación? Al aprobar se firma con SHA256 y queda inmutable:
cualquier edición posterior detendrá /swl:ejecutar-fase.
```

Espera respuesta afirmativa. Si el usuario pide cambios, NO apruebes — remítelo
a `/swl:planear-fase N` para refinar.

## Paso 4 — Transicionar y firmar

1. **Transicionar** (omitir si el plan ya estaba `aprobado` en modo legacy):
   edita el frontmatter `estado: borrador` → `estado: aprobado` y agrega
   `aprobadoPor: usuario (<nombre>) — <fecha>, via /swl:aprobar-plan`.

2. **Firmar** — escribe el lock SHA256:
   ```bash
   node -e "const {firmarPlan}=require('./scripts/lib/plan-lock'); const r=firmarPlan('.planning/fases/0N-PLAN.md'); console.log(JSON.stringify(r))"
   ```
   Verifica que el resultado sea `ok: true` y que exista
   `.planning/locks/0N-PLAN.md.lock`.

3. **Verificar** la firma de inmediato:
   ```bash
   node -e "const {verificarPlan}=require('./scripts/lib/plan-lock'); console.log(JSON.stringify(verificarPlan('.planning/fases/0N-PLAN.md')))"
   ```
   Debe retornar `modo: "firmado"`, `ok: true`.

4. **Marcar la fase como activa** (gate G0 — `hooks/spec-gate.js` consume este
   archivo): escribe `.planning/locks/fase-activa.json` con el sha256 devuelto
   por `firmarPlan`:
   ```bash
   node -e "
   const {atomicWriteJSON} = require('./hooks/lib/atomic-write');
   const {verificarPlan} = require('./scripts/lib/plan-lock');
   const v = verificarPlan('.planning/fases/0N-PLAN.md');
   atomicWriteJSON('.planning/locks/fase-activa.json', {
     numero: N,
     planPath: '.planning/fases/0N-PLAN.md',
     sha256: v.hashEsperado,
     aprobadoEn: new Date().toISOString(),
     aprobadoPor: 'usuario via /swl:aprobar-plan'
   });
   console.log('fase activa: 0N');
   "
   ```
   Este archivo es runtime local (gitignored — a diferencia del `.lock`, que SÍ
   se versiona como evidencia). `/swl:ejecutar-fase` lo elimina al cerrar la fase.
   Si se re-firma un plan (re-aprobación tras mutación), re-escribir también
   fase-activa.json para que el hash quede alineado.

## Paso 5 — Reporte

```
Plan de la fase N aprobado y firmado (gate G1 activo).

estado: borrador -> aprobado
lock: .planning/locks/0N-PLAN.md.lock
fase activa: .planning/locks/fase-activa.json (gate G0 cubierto)
sha256: <hash corto>

Cualquier edición del PLAN tras esta firma detendrá /swl:ejecutar-fase con un
mensaje de "plan mutado tras aprobación". Para cambiar el plan: edítalo y vuelve
a ejecutar /swl:aprobar-plan N.

Próximo paso: /swl:ejecutar-fase N
```

## Reglas de comportamiento

- NUNCA apruebes un plan sin confirmación explícita del usuario.
- NUNCA modifiques el contenido del plan al aprobarlo — solo el campo `estado`
  del frontmatter y la línea `aprobadoPor`. El cuerpo es lo que se firma.
- El lock vive en `.planning/locks/` y SÍ se versiona en git (es evidencia de
  aprobación, parte del audit trail de SDD).
- Si el usuario quiere cambiar el plan después de aprobado, el flujo correcto es
  editar el PLAN y re-ejecutar `/swl:aprobar-plan N` (re-firma). NUNCA editar el
  lock a mano.
- El número de versión del release que publique esta fase lo decide el usuario
  (regla CLAUDE.md) — este comando no toca versiones.
